profile_tokens.go raw

   1  package linodego
   2  
   3  import (
   4  	"context"
   5  	"encoding/json"
   6  	"time"
   7  
   8  	"github.com/linode/linodego/internal/parseabletime"
   9  )
  10  
  11  // Token represents a Token object
  12  type Token struct {
  13  	// This token's unique ID, which can be used to revoke it.
  14  	ID int `json:"id"`
  15  
  16  	// The scopes this token was created with. These define what parts of the Account the token can be used to access. Many command-line tools, such as the Linode CLI, require tokens with access to *. Tokens with more restrictive scopes are generally more secure.
  17  	// Valid values are "*" or a comma separated list of scopes https://techdocs.akamai.com/linode-api/reference/get-started#oauth-reference
  18  	Scopes string `json:"scopes"`
  19  
  20  	// This token's label. This is for display purposes only, but can be used to more easily track what you're using each token for. (1-100 Characters)
  21  	Label string `json:"label"`
  22  
  23  	// The token used to access the API. When the token is created, the full token is returned here. Otherwise, only the first 16 characters are returned.
  24  	Token string `json:"token"`
  25  
  26  	// The date and time this token was created.
  27  	Created *time.Time `json:"-"`
  28  
  29  	// When this token will expire. Personal Access Tokens cannot be renewed, so after this time the token will be completely unusable and a new token will need to be generated. Tokens may be created with "null" as their expiry and will never expire unless revoked.
  30  	Expiry *time.Time `json:"-"`
  31  }
  32  
  33  // TokenCreateOptions fields are those accepted by CreateToken
  34  type TokenCreateOptions struct {
  35  	// The scopes this token was created with. These define what parts of the Account the token can be used to access. Many command-line tools, such as the Linode CLI, require tokens with access to *. Tokens with more restrictive scopes are generally more secure.
  36  	Scopes string `json:"scopes"`
  37  
  38  	// This token's label. This is for display purposes only, but can be used to more easily track what you're using each token for. (1-100 Characters)
  39  	Label string `json:"label"`
  40  
  41  	// When this token will expire. Personal Access Tokens cannot be renewed, so after this time the token will be completely unusable and a new token will need to be generated. Tokens may be created with "null" as their expiry and will never expire unless revoked.
  42  	Expiry *time.Time `json:"expiry"`
  43  }
  44  
  45  // TokenUpdateOptions fields are those accepted by UpdateToken
  46  type TokenUpdateOptions struct {
  47  	// This token's label. This is for display purposes only, but can be used to more easily track what you're using each token for. (1-100 Characters)
  48  	Label string `json:"label"`
  49  }
  50  
  51  // UnmarshalJSON implements the json.Unmarshaler interface
  52  func (i *Token) UnmarshalJSON(b []byte) error {
  53  	type Mask Token
  54  
  55  	p := struct {
  56  		*Mask
  57  
  58  		Created *parseabletime.ParseableTime `json:"created"`
  59  		Expiry  *parseabletime.ParseableTime `json:"expiry"`
  60  	}{
  61  		Mask: (*Mask)(i),
  62  	}
  63  
  64  	if err := json.Unmarshal(b, &p); err != nil {
  65  		return err
  66  	}
  67  
  68  	i.Created = (*time.Time)(p.Created)
  69  	i.Expiry = (*time.Time)(p.Expiry)
  70  
  71  	return nil
  72  }
  73  
  74  // GetCreateOptions converts a Token to TokenCreateOptions for use in CreateToken
  75  func (i Token) GetCreateOptions() (o TokenCreateOptions) {
  76  	o.Label = i.Label
  77  	o.Expiry = copyTime(i.Expiry)
  78  	o.Scopes = i.Scopes
  79  
  80  	return o
  81  }
  82  
  83  // GetUpdateOptions converts a Token to TokenUpdateOptions for use in UpdateToken
  84  func (i Token) GetUpdateOptions() (o TokenUpdateOptions) {
  85  	o.Label = i.Label
  86  	return o
  87  }
  88  
  89  // ListTokens lists Tokens
  90  func (c *Client) ListTokens(ctx context.Context, opts *ListOptions) ([]Token, error) {
  91  	return getPaginatedResults[Token](ctx, c, "profile/tokens", opts)
  92  }
  93  
  94  // GetToken gets the token with the provided ID
  95  func (c *Client) GetToken(ctx context.Context, tokenID int) (*Token, error) {
  96  	e := formatAPIPath("profile/tokens/%d", tokenID)
  97  	return doGETRequest[Token](ctx, c, e)
  98  }
  99  
 100  // CreateToken creates a Token
 101  func (c *Client) CreateToken(ctx context.Context, opts TokenCreateOptions) (*Token, error) {
 102  	// Format the Time as a string to meet the ISO8601 requirement
 103  	createOptsFixed := struct {
 104  		Label  string  `json:"label"`
 105  		Scopes string  `json:"scopes"`
 106  		Expiry *string `json:"expiry"`
 107  	}{}
 108  	createOptsFixed.Label = opts.Label
 109  
 110  	createOptsFixed.Scopes = opts.Scopes
 111  	if opts.Expiry != nil {
 112  		iso8601Expiry := opts.Expiry.UTC().Format("2006-01-02T15:04:05")
 113  		createOptsFixed.Expiry = &iso8601Expiry
 114  	}
 115  
 116  	return doPOSTRequest[Token](ctx, c, "profile/tokens", createOptsFixed)
 117  }
 118  
 119  // UpdateToken updates the Token with the specified id
 120  func (c *Client) UpdateToken(ctx context.Context, tokenID int, opts TokenUpdateOptions) (*Token, error) {
 121  	e := formatAPIPath("profile/tokens/%d", tokenID)
 122  	return doPUTRequest[Token](ctx, c, e, opts)
 123  }
 124  
 125  // DeleteToken deletes the Token with the specified id
 126  func (c *Client) DeleteToken(ctx context.Context, tokenID int) error {
 127  	e := formatAPIPath("profile/tokens/%d", tokenID)
 128  	return doDELETERequest(ctx, c, e)
 129  }
 130