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