Skip to content

Commit b7bf9b6

Browse files
author
williamd5
authored
Merge pull request #16 from cloudnode-pro/next
Implement token operations
2 parents ab784d1 + a33c85b commit b7bf9b6

File tree

11 files changed

+827
-12
lines changed

11 files changed

+827
-12
lines changed

README.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,21 @@ const newsletter: Cloudnode.Newsletter = await cloudnode.newsletter.get("newslet
6767
- [`cloudnode.newsletter.subscribe(id, email, [data])`](#cloudnodenewslettersubscribeid-email-data)
6868
- [`cloudnode.newsletters.listSubscriptions([limit], [page])`](#cloudnodenewsletterslistsubscriptionslimit-page)
6969
- [`cloudnode.newsletters.unsubscribe(subscription)`](#cloudnodenewslettersunsubscribesubscription)
70+
- [`cloudnode.token.create(permissions, lifetime, [note])`](#cloudnodetokencreatepermissions-lifetime-note)
71+
- [`cloudnode.token.get(id)`](#cloudnodetokengetid)
72+
- [`cloudnode.token.list([limit], [page], [internal])`](#cloudnodetokenlistlimit-page-internal)
73+
- [`cloudnode.token.revoke(id)`](#cloudnodetokenrevokeid)
74+
- [`cloudnode.tokens.refresh()`](#cloudnodetokensrefresh)
7075

7176
- [Namespace: `Cloudnode`](#namespace-cloudnode)
7277
- [Interface: `Cloudnode.DatedNewsletterSubscription`](#interface-cloudnodedatednewslettersubscription)
7378
- [Interface: `Cloudnode.Error`](#interface-cloudnodeerror)
7479
- [Interface: `Cloudnode.Newsletter`](#interface-cloudnodenewsletter)
7580
- [Interface: `Cloudnode.NewsletterData`](#interface-cloudnodenewsletterdata)
7681
- [Interface: `Cloudnode.NewsletterSubscription`](#interface-cloudnodenewslettersubscription)
82+
- [Interface: `Cloudnode.PartialToken`](#interface-cloudnodepartialtoken)
83+
- [Interface: `Cloudnode.Token`](#interface-cloudnodetoken)
84+
- [Interface: `Cloudnode.TokenMetadata`](#interface-cloudnodetokenmetadata)
7785

7886
</details>
7987

@@ -166,6 +174,87 @@ Revoke a subscription (unsubscribe)
166174
- Throws: `Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}`
167175
- Throws: `Cloudnode.Error & {code: "MAINTENANCE"}`
168176

177+
<a name="cloudnodetokencreatepermissions-lifetime-note"></a>
178+
179+
### `cloudnode.token.create(permissions, lifetime, [note])`
180+
181+
Create token
182+
183+
- `permissions` `string[]` List of permissions to grant to the token. You must already have each of these permissions with your current token.
184+
- `lifetime` `number` Lifetime of the token in seconds. If null, the token will never expire (not recommended). Max: 31560000 (1 year). Min: 60 (1 minute).
185+
- `note` `string` A user-specified note to label the token. Max length: 2⁸ (256) characters.
186+
- Returns: `Cloudnode.Token`
187+
- Throws: `Cloudnode.Error & {code: "INVALID_DATA"}`
188+
- Throws: `Cloudnode.Error & {code: "UNAUTHORIZED"}`
189+
- Throws: `Cloudnode.Error & {code: "NO_PERMISSION"}`
190+
- Throws: `Cloudnode.Error & {code: "RATE_LIMITED"}`
191+
- Throws: `Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}`
192+
- Throws: `Cloudnode.Error & {code: "MAINTENANCE"}`
193+
194+
<a name="cloudnodetokengetid"></a>
195+
196+
### `cloudnode.token.get(id)`
197+
198+
Get token details
199+
200+
- `id` `string` The ID of the token to get. Specify `current` to get information about the token that was used to authenticate the request.
201+
- Returns: `Cloudnode.Token`
202+
- Throws: `Cloudnode.Error & {code: "RESOURCE_NOT_FOUND"}`
203+
- Throws: `Cloudnode.Error & {code: "INVALID_DATA"}`
204+
- Throws: `Cloudnode.Error & {code: "UNAUTHORIZED"}`
205+
- Throws: `Cloudnode.Error & {code: "NO_PERMISSION"}`
206+
- Throws: `Cloudnode.Error & {code: "RATE_LIMITED"}`
207+
- Throws: `Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}`
208+
- Throws: `Cloudnode.Error & {code: "MAINTENANCE"}`
209+
210+
<a name="cloudnodetokenlistlimit-page-internal"></a>
211+
212+
### `cloudnode.token.list([limit], [page], [internal])`
213+
214+
List tokens of user
215+
216+
- `limit` `number` The number of tokens to return per page. No more than 50. Default: `10`
217+
- `page` `number` The page number. No more than 2³² (4294967296). Default: `1`
218+
- `internal` `any` Internal tokens are returned as well if this parameter is present.
219+
- Returns: `Cloudnode.PaginatedData<Cloudnode.PartialToken[]>`
220+
- Throws: `Cloudnode.Error & {code: "UNAUTHORIZED"}`
221+
- Throws: `Cloudnode.Error & {code: "NO_PERMISSION"}`
222+
- Throws: `Cloudnode.Error & {code: "RATE_LIMITED"}`
223+
- Throws: `Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}`
224+
- Throws: `Cloudnode.Error & {code: "MAINTENANCE"}`
225+
226+
<a name="cloudnodetokenrevokeid"></a>
227+
228+
### `cloudnode.token.revoke(id)`
229+
230+
Revoke token
231+
232+
- `id` `string` The ID of the token to revoke. Specify `current` to revoke the token that was used to authenticate the request.
233+
- Returns: `void`
234+
- Throws: `Cloudnode.Error & {code: "RESOURCE_NOT_FOUND"}`
235+
- Throws: `Cloudnode.Error & {code: "INVALID_DATA"}`
236+
- Throws: `Cloudnode.Error & {code: "MODIFICATION_NOT_ALLOWED"}`
237+
- Throws: `Cloudnode.Error & {code: "UNAUTHORIZED"}`
238+
- Throws: `Cloudnode.Error & {code: "NO_PERMISSION"}`
239+
- Throws: `Cloudnode.Error & {code: "RATE_LIMITED"}`
240+
- Throws: `Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}`
241+
- Throws: `Cloudnode.Error & {code: "MAINTENANCE"}`
242+
243+
<a name="cloudnodetokensrefresh"></a>
244+
245+
### `cloudnode.tokens.refresh()`
246+
247+
Refresh current token. The token that was used to authenticate the request will be deleted. A new token with a new ID but the same permissions will be created and returned. The lifespan of the new token will be the same as the old one, starting from the time of the request. This operation effectively allows a token to be used indefinitely.
248+
249+
250+
- Returns: `Cloudnode.Token`
251+
- Throws: `Cloudnode.Error & {code: "INVALID_DATA"}`
252+
- Throws: `Cloudnode.Error & {code: "UNAUTHORIZED"}`
253+
- Throws: `Cloudnode.Error & {code: "NO_PERMISSION"}`
254+
- Throws: `Cloudnode.Error & {code: "RATE_LIMITED"}`
255+
- Throws: `Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}`
256+
- Throws: `Cloudnode.Error & {code: "MAINTENANCE"}`
257+
169258

170259

171260
<a name="namespace-cloudnode"></a>
@@ -226,6 +315,39 @@ Your subscription to a newsletter
226315
- `email` `string` The email address of the subscriber
227316
- `newsletter` `string` The ID of the newsletter that was subscribed to
228317

318+
<a name="interface-cloudnodepartialtoken"></a>
319+
320+
### Interface: `Cloudnode.PartialToken`
321+
322+
A token, however, the `permissions` field is not included
323+
324+
- `id` `string` The ID or key of the token
325+
- `created` `Date` Date and time when this token was created
326+
- `expires` `Date | null` Date and time when this token expires. Null if it never expires.
327+
- `internal` `string | undefined` Whether this token is for internal use only, e.g. to power a session. In other words, an internal token is one that was **not** created by the client.
328+
- `metadata` `Cloudnode.TokenMetadata` Additional metadata about this token
329+
330+
<a name="interface-cloudnodetoken"></a>
331+
332+
### Interface: `Cloudnode.Token`
333+
334+
An authentication token
335+
336+
- `id` `string` The ID or key of the token
337+
- `created` `Date` Date and time when this token was created
338+
- `expires` `Date | null` Date and time when this token expires. Null if it never expires.
339+
- `permissions` `string[]` Permission scopes that this token holds
340+
- `internal` `string | undefined` Whether this token is for internal use only, e.g. to power a session. In other words, an internal token is one that was **not** created by the client.
341+
- `metadata` `Cloudnode.TokenMetadata` Additional metadata about this token
342+
343+
<a name="interface-cloudnodetokenmetadata"></a>
344+
345+
### Interface: `Cloudnode.TokenMetadata`
346+
347+
Token metadata
348+
349+
- `note` `string | undefined` A user-supplied note for this token
350+
229351

230352

231353

browser/Cloudnode.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,5 +148,84 @@ class Cloudnode {
148148
return await this.#sendRequest({ "type": "operation", "description": "List subscriptions of the authenticated user", "token": "newsletter.subscriptions.list.own", "method": "GET", "path": "/newsletters/subscriptions", "parameters": { "query": { "limit": { "description": "The number of subscriptions to return per page. No more than 50.", "default": "10", "type": "number", "required": false }, "page": { "description": "The page number. No more than 2³² (4294967296).", "default": "1", "type": "number", "required": false } } }, "returns": [{ "status": 200, "type": "DatedNewsletterSubscription[]" }, { "status": 401, "type": "Error & {code: \"UNAUTHORIZED\"}" }, { "status": 403, "type": "Error & {code: \"NO_PERMISSION\"}" }, { "status": 429, "type": "Error & {code: \"RATE_LIMITED\"}" }, { "status": 500, "type": "Error & {code: \"INTERNAL_SERVER_ERROR\"}" }, { "status": 503, "type": "Error & {code: \"MAINTENANCE\"}" }] }, {}, { limit: `${limit}`, page: `${page}` }, {});
149149
},
150150
};
151+
token = {
152+
/**
153+
* List tokens of user
154+
* @GET /token
155+
* @param limit The number of tokens to return per page. No more than 50.
156+
* @param page The page number. No more than 2³² (4294967296).
157+
* @param internal Internal tokens are returned as well if this parameter is present.
158+
* @throws {Cloudnode.Error & {code: "UNAUTHORIZED"}}
159+
* @throws {Cloudnode.Error & {code: "NO_PERMISSION"}}
160+
* @throws {Cloudnode.Error & {code: "RATE_LIMITED"}}
161+
* @throws {Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}}
162+
* @throws {Cloudnode.Error & {code: "MAINTENANCE"}}
163+
*/
164+
list: async (limit = 10, page = 1, internal) => {
165+
return await this.#sendRequest({ "type": "operation", "description": "List tokens of user", "token": "tokens.list.own", "method": "GET", "path": "/token", "parameters": { "query": { "limit": { "description": "The number of tokens to return per page. No more than 50.", "default": "10", "type": "number", "required": false }, "page": { "description": "The page number. No more than 2³² (4294967296).", "default": "1", "type": "number", "required": false }, "internal": { "description": "Internal tokens are returned as well if this parameter is present.", "type": "any", "required": false } } }, "returns": [{ "status": 200, "type": "PartialToken[]" }, { "status": 401, "type": "Error & {code: \"UNAUTHORIZED\"}" }, { "status": 403, "type": "Error & {code: \"NO_PERMISSION\"}" }, { "status": 429, "type": "Error & {code: \"RATE_LIMITED\"}" }, { "status": 500, "type": "Error & {code: \"INTERNAL_SERVER_ERROR\"}" }, { "status": 503, "type": "Error & {code: \"MAINTENANCE\"}" }] }, {}, { limit: `${limit}`, page: `${page}`, internal: `${internal}` }, {});
166+
},
167+
/**
168+
* Create token
169+
* @POST /token
170+
* @param permissions List of permissions to grant to the token. You must already have each of these permissions with your current token.
171+
* @param lifetime Lifetime of the token in seconds. If null, the token will never expire (not recommended). Max: 31560000 (1 year). Min: 60 (1 minute).
172+
* @param note A user-specified note to label the token. Max length: 2⁸ (256) characters.
173+
* @throws {Cloudnode.Error & {code: "INVALID_DATA"}}
174+
* @throws {Cloudnode.Error & {code: "UNAUTHORIZED"}}
175+
* @throws {Cloudnode.Error & {code: "NO_PERMISSION"}}
176+
* @throws {Cloudnode.Error & {code: "RATE_LIMITED"}}
177+
* @throws {Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}}
178+
* @throws {Cloudnode.Error & {code: "MAINTENANCE"}}
179+
*/
180+
create: async (permissions, lifetime, note) => {
181+
return await this.#sendRequest({ "type": "operation", "description": "Create token", "token": "tokens.create.own", "method": "POST", "path": "/token", "parameters": { "body": { "permissions": { "description": "List of permissions to grant to the token. You must already have each of these permissions with your current token.", "type": "string[]", "required": true }, "lifetime": { "description": "Lifetime of the token in seconds. If null, the token will never expire (not recommended). Max: 31560000 (1 year). Min: 60 (1 minute).", "type": "number", "required": true }, "note": { "description": "A user-specified note to label the token. Max length: 2⁸ (256) characters.", "type": "string", "required": false } } }, "returns": [{ "status": 201, "type": "Token" }, { "status": 422, "type": "Error & {code: \"INVALID_DATA\"}" }, { "status": 401, "type": "Error & {code: \"UNAUTHORIZED\"}" }, { "status": 403, "type": "Error & {code: \"NO_PERMISSION\"}" }, { "status": 429, "type": "Error & {code: \"RATE_LIMITED\"}" }, { "status": 500, "type": "Error & {code: \"INTERNAL_SERVER_ERROR\"}" }, { "status": 503, "type": "Error & {code: \"MAINTENANCE\"}" }] }, {}, {}, { permissions, lifetime, note });
182+
},
183+
/**
184+
* Get token details
185+
* @GET /token/:id
186+
* @param id The ID of the token to get. Specify `current` to get information about the token that was used to authenticate the request.
187+
* @throws {Cloudnode.Error & {code: "RESOURCE_NOT_FOUND"}}
188+
* @throws {Cloudnode.Error & {code: "INVALID_DATA"}}
189+
* @throws {Cloudnode.Error & {code: "UNAUTHORIZED"}}
190+
* @throws {Cloudnode.Error & {code: "NO_PERMISSION"}}
191+
* @throws {Cloudnode.Error & {code: "RATE_LIMITED"}}
192+
* @throws {Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}}
193+
* @throws {Cloudnode.Error & {code: "MAINTENANCE"}}
194+
*/
195+
get: async (id) => {
196+
return await this.#sendRequest({ "type": "operation", "description": "Get token details", "token": "tokens.get.own", "method": "GET", "path": "/token/:id", "parameters": { "path": { "id": { "description": "The ID of the token to get. Specify `current` to get information about the token that was used to authenticate the request.", "type": "string", "required": true } } }, "returns": [{ "status": 200, "type": "Token" }, { "status": 404, "type": "Error & {code: \"RESOURCE_NOT_FOUND\"}" }, { "status": 422, "type": "Error & {code: \"INVALID_DATA\"}" }, { "status": 401, "type": "Error & {code: \"UNAUTHORIZED\"}" }, { "status": 403, "type": "Error & {code: \"NO_PERMISSION\"}" }, { "status": 429, "type": "Error & {code: \"RATE_LIMITED\"}" }, { "status": 500, "type": "Error & {code: \"INTERNAL_SERVER_ERROR\"}" }, { "status": 503, "type": "Error & {code: \"MAINTENANCE\"}" }] }, { id: `${id}` }, {}, {});
197+
},
198+
/**
199+
* Revoke token
200+
* @DELETE /token/:id
201+
* @param id The ID of the token to revoke. Specify `current` to revoke the token that was used to authenticate the request.
202+
* @throws {Cloudnode.Error & {code: "RESOURCE_NOT_FOUND"}}
203+
* @throws {Cloudnode.Error & {code: "INVALID_DATA"}}
204+
* @throws {Cloudnode.Error & {code: "MODIFICATION_NOT_ALLOWED"}}
205+
* @throws {Cloudnode.Error & {code: "UNAUTHORIZED"}}
206+
* @throws {Cloudnode.Error & {code: "NO_PERMISSION"}}
207+
* @throws {Cloudnode.Error & {code: "RATE_LIMITED"}}
208+
* @throws {Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}}
209+
* @throws {Cloudnode.Error & {code: "MAINTENANCE"}}
210+
*/
211+
revoke: async (id) => {
212+
return await this.#sendRequest({ "type": "operation", "description": "Revoke token", "token": "tokens.revoke.own", "method": "DELETE", "path": "/token/:id", "parameters": { "path": { "id": { "description": "The ID of the token to revoke. Specify `current` to revoke the token that was used to authenticate the request.", "type": "string", "required": true } } }, "returns": [{ "status": 204, "type": "void" }, { "status": 404, "type": "Error & {code: \"RESOURCE_NOT_FOUND\"}" }, { "status": 422, "type": "Error & {code: \"INVALID_DATA\"}" }, { "status": 400, "type": "Error & {code: \"MODIFICATION_NOT_ALLOWED\"}" }, { "status": 401, "type": "Error & {code: \"UNAUTHORIZED\"}" }, { "status": 403, "type": "Error & {code: \"NO_PERMISSION\"}" }, { "status": 429, "type": "Error & {code: \"RATE_LIMITED\"}" }, { "status": 500, "type": "Error & {code: \"INTERNAL_SERVER_ERROR\"}" }, { "status": 503, "type": "Error & {code: \"MAINTENANCE\"}" }] }, { id: `${id}` }, {}, {});
213+
},
214+
};
215+
tokens = {
216+
/**
217+
* Refresh current token. The token that was used to authenticate the request will be deleted. A new token with a new ID but the same permissions will be created and returned. The lifespan of the new token will be the same as the old one, starting from the time of the request. This operation effectively allows a token to be used indefinitely.
218+
* @POST /token/refresh
219+
* @throws {Cloudnode.Error & {code: "INVALID_DATA"}}
220+
* @throws {Cloudnode.Error & {code: "UNAUTHORIZED"}}
221+
* @throws {Cloudnode.Error & {code: "NO_PERMISSION"}}
222+
* @throws {Cloudnode.Error & {code: "RATE_LIMITED"}}
223+
* @throws {Cloudnode.Error & {code: "INTERNAL_SERVER_ERROR"}}
224+
* @throws {Cloudnode.Error & {code: "MAINTENANCE"}}
225+
*/
226+
refresh: async () => {
227+
return await this.#sendRequest({ "type": "operation", "description": "Refresh current token. The token that was used to authenticate the request will be deleted. A new token with a new ID but the same permissions will be created and returned. The lifespan of the new token will be the same as the old one, starting from the time of the request. This operation effectively allows a token to be used indefinitely.", "token": "token.refresh", "method": "POST", "path": "/token/refresh", "parameters": {}, "returns": [{ "status": 201, "type": "Token" }, { "status": 422, "type": "Error & {code: \"INVALID_DATA\"}" }, { "status": 401, "type": "Error & {code: \"UNAUTHORIZED\"}" }, { "status": 403, "type": "Error & {code: \"NO_PERMISSION\"}" }, { "status": 429, "type": "Error & {code: \"RATE_LIMITED\"}" }, { "status": 500, "type": "Error & {code: \"INTERNAL_SERVER_ERROR\"}" }, { "status": 503, "type": "Error & {code: \"MAINTENANCE\"}" }] }, {}, {}, {});
228+
},
229+
};
151230
}
152231

0 commit comments

Comments
 (0)