Skip to content

Commit

Permalink
Migrated profile_phone_number to regions from resty to request helpers (
Browse files Browse the repository at this point in the history
#547)

* Migrated profile_phone_number to regions and reran fixtures

* Reran more fixtures and fixed caching issues

* Reran new fixtures

* Removed listHelper
  • Loading branch information
ezilber-akamai authored Jul 19, 2024
1 parent a2241c8 commit 7a5aaec
Show file tree
Hide file tree
Showing 132 changed files with 2,425 additions and 1,061 deletions.
8 changes: 8 additions & 0 deletions kernels.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,18 @@ func (c *Client) ListKernels(ctx context.Context, opts *ListOptions) ([]LinodeKe
// GetKernel gets the kernel with the provided ID. This endpoint is cached by default.
func (c *Client) GetKernel(ctx context.Context, kernelID string) (*LinodeKernel, error) {
e := formatAPIPath("linode/kernels/%s", kernelID)

if result := c.getCachedResponse(e); result != nil {
result := result.(LinodeKernel)
return &result, nil
}

response, err := doGETRequest[LinodeKernel](ctx, c, e)
if err != nil {
return nil, err
}

c.addCachedResponse(e, response, nil)

return response, nil
}
14 changes: 12 additions & 2 deletions paged_response_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,18 @@ type ObjectStorageClustersPagedResponse legacyPagedResponse[ObjectStorageCluster
// Deprecated: PaymentsPagedResponse exists for historical compatibility and should not be used.
type PaymentsPagedResponse legacyPagedResponse[Payment]

// Deprecated: RegionsAvailabilityPagedResponse exists for historical compatibility and should not be used.
type RegionsAvailabilityPagedResponse legacyPagedResponse[RegionAvailability]
// Deprecated: RegionsPagedResponse exists for historical compatibility and should not be used.
type RegionsPagedResponse legacyPagedResponse[Region]

// Deprecated: SSHKeysPagedResponse exists for historical compatibility and should not be used.
type SSHKeysPagedResponse legacyPagedResponse[SSHKey]

// Deprecated: TokensPagedResponse exists for historical compatibility and should not be used.
type (
TokensPagedResponse legacyPagedResponse[Token]
// Deprecated: RegionsAvailabilityPagedResponse exists for historical compatibility and should not be used.
RegionsAvailabilityPagedResponse legacyPagedResponse[RegionAvailability]
)

// Deprecated: StackscriptsPagedResponse exists for historical compatibility and should not be used.
type StackscriptsPagedResponse legacyPagedResponse[Stackscript]
Expand Down
36 changes: 0 additions & 36 deletions pagination.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package linodego
*/

import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
Expand Down Expand Up @@ -91,41 +90,6 @@ type PagedResponse interface {
castResult(*resty.Request, string) (int, int, error)
}

// listHelper abstracts fetching and pagination for GET endpoints that
// do not require any Ids (top level endpoints).
// When opts (or opts.Page) is nil, all pages will be fetched and
// returned in a single (endpoint-specific)PagedResponse
// opts.results and opts.pages will be updated from the API response
func (c *Client) listHelper(ctx context.Context, pager PagedResponse, opts *ListOptions, ids ...any) error {
req := c.R(ctx)
if err := applyListOptionsToRequest(opts, req); err != nil {
return err
}

pages, results, err := pager.castResult(req, pager.endpoint(ids...))
if err != nil {
return err
}
if opts == nil {
opts = &ListOptions{PageOptions: &PageOptions{Page: 0}}
}
if opts.PageOptions == nil {
opts.PageOptions = &PageOptions{Page: 0}
}
if opts.Page == 0 {
for page := 2; page <= pages; page++ {
opts.Page = page
if err := c.listHelper(ctx, pager, opts, ids...); err != nil {
return err
}
}
}

opts.Results = results
opts.Pages = pages
return nil
}

// flattenQueryStruct flattens a structure into a Resty-compatible query param map.
// Fields are mapped using the `query` struct tag.
func flattenQueryStruct(val any) (map[string]string, error) {
Expand Down
19 changes: 5 additions & 14 deletions profile_phone_number.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package linodego

import (
"context"
"encoding/json"
)

// SendPhoneNumberVerificationCodeOptions fields are those accepted by SendPhoneNumberVerificationCode
Expand All @@ -18,31 +17,23 @@ type VerifyPhoneNumberOptions struct {

// SendPhoneNumberVerificationCode sends a one-time verification code via SMS message to the submitted phone number.
func (c *Client) SendPhoneNumberVerificationCode(ctx context.Context, opts SendPhoneNumberVerificationCodeOptions) error {
body, err := json.Marshal(opts)
if err != nil {
return err
}

e := "profile/phone-number"
_, err = coupleAPIErrors(c.R(ctx).SetBody(string(body)).Post(e))
_, err := doPOSTRequest[any](ctx, c, e, opts)

return err
}

// DeletePhoneNumber deletes the verified phone number for the User making this request.
func (c *Client) DeletePhoneNumber(ctx context.Context) error {
e := "profile/phone-number"
_, err := coupleAPIErrors(c.R(ctx).Delete(e))
err := doDELETERequest(ctx, c, e)
return err
}

// VerifyPhoneNumber verifies a phone number by confirming the one-time code received via SMS message after accessing the Phone Verification Code Send command.
func (c *Client) VerifyPhoneNumber(ctx context.Context, opts VerifyPhoneNumberOptions) error {
body, err := json.Marshal(opts)
if err != nil {
return err
}

e := "profile/phone-number/verify"
_, err = coupleAPIErrors(c.R(ctx).SetBody(string(body)).Post(e))
_, err := doPOSTRequest[any](ctx, c, e, opts)

return err
}
16 changes: 5 additions & 11 deletions profile_security_questions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package linodego

import (
"context"
"encoding/json"
)

type SecurityQuestion struct {
Expand All @@ -27,23 +26,18 @@ type SecurityQuestionsAnswerOptions struct {
// SecurityQuestionsList returns a collection of security questions and their responses, if any, for your User Profile.
func (c *Client) SecurityQuestionsList(ctx context.Context) (*SecurityQuestionsListResponse, error) {
e := "profile/security-questions"
req := c.R(ctx).SetResult(&SecurityQuestionsListResponse{})
r, err := coupleAPIErrors(req.Get(e))
response, err := doGETRequest[SecurityQuestionsListResponse](ctx, c, e)
if err != nil {
return nil, err
}
return r.Result().(*SecurityQuestionsListResponse), nil

return response, nil
}

// SecurityQuestionsAnswer adds security question responses for your User.
func (c *Client) SecurityQuestionsAnswer(ctx context.Context, opts SecurityQuestionsAnswerOptions) error {
body, err := json.Marshal(opts)
if err != nil {
return err
}

e := "profile/security-questions"
req := c.R(ctx).SetBody(string(body))
_, err = coupleAPIErrors(req.Post(e))

_, err := doPOSTRequest[any](ctx, c, e, opts)
return err
}
63 changes: 15 additions & 48 deletions profile_sshkeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package linodego
import (
"context"
"encoding/json"
"fmt"
"time"

"github.com/go-resty/resty/v2"
"github.com/linode/linodego/internal/parseabletime"
)

Expand Down Expand Up @@ -62,83 +60,52 @@ func (i SSHKey) GetUpdateOptions() (o SSHKeyUpdateOptions) {
return
}

// SSHKeysPagedResponse represents a paginated SSHKey API response
type SSHKeysPagedResponse struct {
*PageOptions
Data []SSHKey `json:"data"`
}

// endpoint gets the endpoint URL for SSHKey
func (SSHKeysPagedResponse) endpoint(_ ...any) string {
return "profile/sshkeys"
}

func (resp *SSHKeysPagedResponse) castResult(r *resty.Request, e string) (int, int, error) {
res, err := coupleAPIErrors(r.SetResult(SSHKeysPagedResponse{}).Get(e))
if err != nil {
return 0, 0, err
}
castedRes := res.Result().(*SSHKeysPagedResponse)
resp.Data = append(resp.Data, castedRes.Data...)
return castedRes.Pages, castedRes.Results, nil
}

// ListSSHKeys lists SSHKeys
func (c *Client) ListSSHKeys(ctx context.Context, opts *ListOptions) ([]SSHKey, error) {
response := SSHKeysPagedResponse{}
err := c.listHelper(ctx, &response, opts)
response, err := getPaginatedResults[SSHKey](ctx, c, "profile/sshkeys", opts)
if err != nil {
return nil, err
}
return response.Data, nil

return response, nil
}

// GetSSHKey gets the sshkey with the provided ID
func (c *Client) GetSSHKey(ctx context.Context, keyID int) (*SSHKey, error) {
e := fmt.Sprintf("profile/sshkeys/%d", keyID)
req := c.R(ctx).SetResult(&SSHKey{})
r, err := coupleAPIErrors(req.Get(e))
e := formatAPIPath("profile/sshkeys/%d", keyID)
response, err := doGETRequest[SSHKey](ctx, c, e)
if err != nil {
return nil, err
}
return r.Result().(*SSHKey), nil

return response, nil
}

// CreateSSHKey creates a SSHKey
func (c *Client) CreateSSHKey(ctx context.Context, opts SSHKeyCreateOptions) (*SSHKey, error) {
body, err := json.Marshal(opts)
if err != nil {
return nil, err
}

e := "profile/sshkeys"
req := c.R(ctx).SetResult(&SSHKey{}).SetBody(string(body))
r, err := coupleAPIErrors(req.Post(e))
response, err := doPOSTRequest[SSHKey](ctx, c, e, opts)
if err != nil {
return nil, err
}
return r.Result().(*SSHKey), nil

return response, nil
}

// UpdateSSHKey updates the SSHKey with the specified id
func (c *Client) UpdateSSHKey(ctx context.Context, keyID int, opts SSHKeyUpdateOptions) (*SSHKey, error) {
body, err := json.Marshal(opts)
e := formatAPIPath("profile/sshkeys/%d", keyID)
response, err := doPUTRequest[SSHKey](ctx, c, e, opts)
if err != nil {
return nil, err
}

e := fmt.Sprintf("profile/sshkeys/%d", keyID)
req := c.R(ctx).SetResult(&SSHKey{}).SetBody(string(body))
r, err := coupleAPIErrors(req.Put(e))
if err != nil {
return nil, err
}
return r.Result().(*SSHKey), nil
return response, nil
}

// DeleteSSHKey deletes the SSHKey with the specified id
func (c *Client) DeleteSSHKey(ctx context.Context, keyID int) error {
e := fmt.Sprintf("profile/sshkeys/%d", keyID)
_, err := coupleAPIErrors(c.R(ctx).Delete(e))
e := formatAPIPath("profile/sshkeys/%d", keyID)
err := doDELETERequest(ctx, c, e)
return err
}
17 changes: 5 additions & 12 deletions profile_tfa.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,35 +46,28 @@ func (s *TwoFactorSecret) UnmarshalJSON(b []byte) error {
// CreateTwoFactorSecret generates a Two Factor secret for your User.
func (c *Client) CreateTwoFactorSecret(ctx context.Context) (*TwoFactorSecret, error) {
e := "profile/tfa-enable"
req := c.R(ctx).SetResult(&TwoFactorSecret{})
r, err := coupleAPIErrors(req.Post(e))
response, err := doPOSTRequest[TwoFactorSecret, any](ctx, c, e)
if err != nil {
return nil, err
}

return r.Result().(*TwoFactorSecret), nil
return response, nil
}

// DisableTwoFactor disables Two Factor Authentication for your User.
func (c *Client) DisableTwoFactor(ctx context.Context) error {
e := "profile/tfa-disable"
_, err := coupleAPIErrors(c.R(ctx).Post(e))
_, err := doPOSTRequest[TwoFactorSecret, any](ctx, c, e)
return err
}

// ConfirmTwoFactor confirms that you can successfully generate Two Factor codes and enables TFA on your Account.
func (c *Client) ConfirmTwoFactor(ctx context.Context, opts ConfirmTwoFactorOptions) (*ConfirmTwoFactorResponse, error) {
body, err := json.Marshal(opts)
if err != nil {
return nil, err
}

e := "profile/tfa-enable-confirm"
req := c.R(ctx).SetResult(&ConfirmTwoFactorResponse{}).SetBody(string(body))
r, err := coupleAPIErrors(req.Post(e))
response, err := doPOSTRequest[ConfirmTwoFactorResponse](ctx, c, e, opts)
if err != nil {
return nil, err
}

return r.Result().(*ConfirmTwoFactorResponse), nil
return response, nil
}
Loading

0 comments on commit 7a5aaec

Please sign in to comment.