diff --git a/.eslintrc b/.eslintrc index 8802eab..3ff5919 100644 --- a/.eslintrc +++ b/.eslintrc @@ -29,6 +29,6 @@ "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/ban-ts-comment": "off", "no-use-before-define": "off", - "@typescript-eslint/no-shadow": ["error"] + "no-shadow": ["error"] } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ade33d..ccfa62b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change log This is the changelog for [Authress SDK](readme.md). +## 1.3 ## +* Add new `Pagination` type which pagination `next.cursor` to enable paging through resources. + ## 1.2 ## * Removed legacy support for RS512 service client tokens. * Add EdDSA support for `tokenVerifier()` class diff --git a/README.md b/README.md index d09419c..fd26fa4 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,43 @@ const temporaryServiceClientAccessToken = await serviceClientTokenProvider.getTo const response = await client.get(url, { 'Authorization': `Bearer: ${temporaryServiceClientAccessToken}` }); ``` +#### Paginating through a collection resource +Some of the resources in the API are paginated. These resources contain a `pagination.next.cursor` property when there is a next page. The cursor can be passed to query to fetch the next page. Here's an example usage: + +```js +const { AuthressClient } = require('authress-sdk'); +const authressClient = new AuthressClient({ baseUrl: 'https://DOMAIN.api-REGION.authress.io' }) + +// on api route +async function (resourceId) { + // Get the user token and pass it to authress + const authorizationToken = request.headers.get('authorization'); + authressClient.setToken(authorizationToken); + + // Get the users resources + const response = await authressClient.userPermissions.getUserResources(userId, `resources/*`, 10, null, 'READ'); + for (const resource of response.data.resources) { + // Iterate on resource + } + + // Get the next page: + const nextPageResponse = await authressClient.userPermissions.getUserResources(userId, `resources/*`, 10, response.data.pagination.next.cursor, 'READ'); + for (const resource of nextPageResponse.data.resources) { + // Iterate on resource + } + + // Get all the next pages: + let cursor = response.data.pagination?.next?.cursor; + while (cursor) { + const response = await authressClient.userPermissions.getUserResources(userId, `resources/*`, 10, cursor, 'READ'); + cursor = response.data.pagination?.next?.cursor; + for (const resource of response.data.resources) { + // Iterate on resource + } + } +} +``` + ## Contributions ### Adding new DTO and methods diff --git a/index.d.ts b/index.d.ts index 5fd79d3..70acf95 100644 --- a/index.d.ts +++ b/index.d.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-empty-interface */ /* eslint-disable no-shadow */ -import { Response } from './src/response'; +import { Response, IPaginated, Links, Cursor } from './src/response'; import { ConnectionsApi } from './src/connections/api'; export * from './src/connections/api'; @@ -123,19 +123,13 @@ export namespace AccessRecord { * @export * @interface AccessRecordCollection */ -export interface AccessRecordCollection { +export interface AccessRecordCollection extends IPaginated { /** * * @type {Array} * @memberof AccessRecordCollection */ records: Array; - /** - * - * @type {CollectionLinks} - * @memberof AccessRecordCollection - */ - links: CollectionLinks; } /** @@ -325,7 +319,7 @@ export interface IdentityRequest { * @export * @interface UserResources */ -export interface UserResources { +export interface UserResources extends IPaginated { /** * * @type {AccountLink} @@ -350,12 +344,6 @@ export interface UserResources { * @memberof UserResources */ accessToAllSubResources?: boolean; - /** - * - * @type {CollectionLinks} - * @memberof UserResources - */ - links?: CollectionLinks; } /** @@ -363,19 +351,13 @@ export interface UserResources { * @export * @interface ServiceClientCollection */ -export interface ServiceClientCollection { +export interface ServiceClientCollection extends IPaginated { /** * A list of clients * @type {Array} * @memberof ServiceClientCollection */ clients: Array; - /** - * - * @type {CollectionLinks} - * @memberof ServiceClientCollection - */ - links: CollectionLinks; } /** * A client configuration. @@ -554,20 +536,13 @@ export interface ResourcePermissionsCollection { * @export * @interface ResourceUsersCollection */ -export interface ResourceUsersCollection { +export interface ResourceUsersCollection extends IPaginated { /** * * @type {Array} * @memberof ResourceUsersCollection */ users: Array; - - /** - * - * @type {CollectionLinks} - * @memberof ResourceUsersCollection - */ - links: CollectionLinks; } /** @@ -616,25 +591,6 @@ export interface Role { permissions: Array; } -/** - * A url linking object that complies to application/links+json RFC. Either is an IANA approved link relation or has a custom rel specified. - * @export - * @interface Link - */ -export interface Link { - /** - * The absolute url pointing to the reference resource. - * @type {string} - * @memberof Link - */ - href: string; - /** - * Optional property indicating the type of link if it is not a default IANA approved global link relation. - * @type {string} - * @memberof Link - */ - rel?: string; -} /** * Metadata and additional properties relevant. * @export @@ -734,38 +690,13 @@ export interface ResourcePermission { * @export * @interface ResourcePermissionCollection */ -export interface ResourcePermissionCollection { +export interface ResourcePermissionCollection extends IPaginated { /** * * @type {Array} * @memberof ResourcePermissionCollection */ resources: Array; - /** - * - * @type {CollectionLinks} - * @memberof ResourcePermissionCollection - */ - links: CollectionLinks; -} -/** - * - * @export - * @interface CollectionLinks - */ -export interface CollectionLinks { - /** - * - * @type {Link} - * @memberof CollectionLinks - */ - self: Link; - /** - * - * @type {Link} - * @memberof CollectionLinks - */ - next?: Link; } /** @@ -858,20 +789,6 @@ export interface ServiceClientOptions { grantMetadataAccess?: boolean; } -/** - * - * @export - * @interface Links - */ -export interface Links { - /** - * - * @type {Link} - * @memberof Links - */ - self: Link; -} - /** * * @export @@ -1039,12 +956,12 @@ export interface AccessRecordsApi { * Billable Returns a paginated records list for the account. Only records the user has access to are returned. * @summary Get all account records. * @param {number} [limit] Max number of results to return - * @param {string} [cursor] Continuation cursor for paging (will automatically be set) + * @param {Cursor} [cursor] Continuation cursor for paging (will automatically be set) * @param {string} [filter] Filter to search records by. This is a case insensitive search through every text field. * @param {string} [status] Filter records by their current status. * @throws {ArgumentRequiredError} */ - getRecords(limit?: number, cursor?: string, filter?: string, status?: string): Promise>; + getRecords(limit?: number, cursor?: Cursor, filter?: string, status?: string): Promise>; /** * Updates an access record adding or removing user permissions to resources. * @summary Update an access record. @@ -1291,11 +1208,11 @@ export interface UserPermissionsApi { * @param {string} [userId] The user to check permissions on * @param {string} [resourceUri] The top level uri path of a resource to query for. Will only match explicit or collection resource sub-resources. Will not partial match resource names. * @param {number} [limit] Max number of results to return - * @param {string} [cursor] Continuation cursor for paging (will automatically be set) + * @param {Cursor} [cursor] Continuation cursor for paging (will automatically be set) * @param {string} [permission] A required ALLOW action to check for. Resources a user does not have this permission will not be returned. * @throws {ArgumentRequiredError} */ - getUserResources(userId?: string, resourceUri?: string, limit?: number, cursor?: string, permission?: string): Promise>; + getUserResources(userId?: string, resourceUri?: string, limit?: number, cursor?: Cursor, permission?: string): Promise>; /** * Billable Get an Authress signed JWT access token using with userId as the sub. Additionally, can be configured to limit the permissions for this particular token and the length of time the token is valid. Token validation is real-time, so deleted tokens are restricted from being used as soon as they are deleted. This gives full control to the user and client creating the token. Client must have access to impersonating the user in order to generate tokens on their behalf. * @summary Request a user token with additional configuration diff --git a/src/response.ts b/src/response.ts index 5fdb465..dd1bcc8 100644 --- a/src/response.ts +++ b/src/response.ts @@ -8,3 +8,109 @@ export interface Response { /** HTTP response status code for success responses */ status: number; } + +/** + * + * @export + * @interface Links + */ +export interface Links { + /** + * + * @type {Link} + * @memberof Links + */ + self: Link; +} + +/** + * A url linking object that complies to application/links+json RFC. Either is an IANA approved link relation or has a custom rel specified. + * @export + * @interface Link + */ +export interface Link { + /** + * The absolute url pointing to the reference resource. + * @type {string} + * @memberof Link + */ + href: string; + /** + * Optional property indicating the type of link if it is not a default IANA approved global link relation. + * @type {string} + * @memberof Link + */ + rel?: string; +} + +/** + * + * @export + * @interface CollectionLinks + */ +export interface CollectionLinks { + /** + * + * @type {Link} + * @memberof CollectionLinks + */ + self: Link; + /** + * + * @type {Link} + * @memberof CollectionLinks + */ + next?: Link; +} + +/** + * + * @export + * @interface IPaginated + */ +// @ts-ignore +export interface IPaginated { + /** + * + * @type {CollectionLinks} + * @memberof IPaginated + */ + links: CollectionLinks; + + /** + * @type {Pagination} + * @memberof IPaginated + * @summary returns the next page of the collection + */ + pagination?: Pagination; +} + +/** + * + * @export + * @interface Pagination + */ +export interface Pagination { + /** + * + * @type {PageMetadata} + * @memberof Pagination + */ + next?: PageMetadata; + } + +/** + * + * @export + * @interface PageMetadata + */ +export interface PageMetadata { + /** + * + * @type {Cursor} + * @memberof PageMetadata + */ + cursor: Cursor; +} + +export type Cursor = string;