diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bdf55e..6cc6912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change log This is the changelog for [Authress SDK](readme.md). +## 3.0 ## +* [Breaking] UserId is now required in all `userPermissions` apis. This improves **Security By Default** requiring explicit check on who the user is. +* [Breaking] Removal of property `accessToAllSubResources`. + ## 2.3 ## * Require minimum Node version to be 16. * Improve support for collectionConfiguration to skip `accessToAllSubResources` check when using `INCLUDE_NESTED` in the query. diff --git a/src/userPermissions/api.ts b/src/userPermissions/api.ts index eaf692c..61aef2e 100644 --- a/src/userPermissions/api.ts +++ b/src/userPermissions/api.ts @@ -10,45 +10,45 @@ export interface UserPermissionsApi { /** * Billable Does the user have the specified permissions to the resource? * @summary Check to see if a user has permissions to a resource. - * @param {string} [userId] The user to check permissions on + * @param {string} userId The user to check permissions on * @param {string} resourceUri The uri path of a resource to validate, must be URL encoded, uri segments are allowed, the resource must be a full path, and permissions are not inherited by sub-resources. * @param {string} permission Permission to check, '*' and scoped permissions can also be checked here. * @throws {ArgumentRequiredError} * @throws {UnauthorizedError} */ // @ts-ignore - authorizeUser(userId?: string | null, resourceUri: string, permission: string): Promise>; + authorizeUser(userId: string, resourceUri: string, permission: string): Promise>; /** * Billable Permanently disable a token. To be used after the token has completed its use. Should be called on all tokens to ensure they are not active indefinitely. * @summary Disable a token - * @param {string} [userId] The user to create an impersonation token for. + * @param {string} userId The user to create an impersonation token for. * @param {string} tokenId The relevant token identifier * @throws {ArgumentRequiredError} */ // @ts-ignore - disableUserToken(userId?: string | null, tokenId: string): Promise>; + disableUserToken(userId: string, tokenId: string): Promise>; /** * Billable Get a summary of the permissions a user has to a particular resource. * @summary Get the permissions a user has to a resource. - * @param {string} [userId] The user to check permissions on + * @param {string} userId The user to check permissions on * @param {string} resourceUri The uri path of a resource to validate, must be URL encoded, uri segments are allowed. * @throws {ArgumentRequiredError} */ // @ts-ignore - getUserPermissionsForResource(userId?: string | null, resourceUri: string): Promise>; + getUserPermissionsForResource(userId: string, resourceUri: string): Promise>; /** * Billable Get a summary of the roles a user has to a particular resource. Users can be assigned roles from multiple access records, this may cause the same role to appear in the list more than once.
READ: Authress:UserPermissions/{userId} * @summary Get the roles a user has to a resource. - * @param {string} [userId] The user to get roles for. + * @param {string} userId The user to get roles for. * @param {string} resourceUri The uri path of a resource to get roles for, must be URL encoded. Checks for explicit resource roles, roles attached to parent resources are not returned. * @throws {ArgumentRequiredError} */ // @ts-ignore - getUserRolesForResource(userId?: string | null, resourceUri: string): Promise>; + getUserRolesForResource(userId: string, resourceUri: string): Promise>; /** - * Billable Get the users resources. Get the users resources. This result is a list of resource uris that a user has an explicit permission to, a user with * access to all sub resources will return an empty list and {accessToAllSubResources} will be populated. To get a user's list of resources in these cases, it is recommended to also check explicit access to the collection resource, using the authorizeUser endpoint. In the case that the user only has access to a subset of resources in a collection, the list will be paginated. + * Get the users resources. This result is a list of resource uris that a user has an permission to. By default only the top level matching resources are returned. To get a user's list of deeply nested resources, set the {@link collectionConfiguration} to be {@link collectionConfiguration.INCLUDE_NESTED}. This collection is paginated. * @summary Get the resources a user has to permission to. - * @param {string} [userId] The user to check permissions on + * @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 {Cursor} [cursor] Continuation cursor for paging (will automatically be set) @@ -57,6 +57,6 @@ export interface UserPermissionsApi { INCLUDE_NESTED - will return all sub-resources as well as deeply nested resources that the user has the specified permission to. A query to resourceUri=Collection will return Collection/namespaces/ns/resources/resource_1. To return matching resources for nested resources, set this parameter to INCLUDE_NESTED. * @throws {ArgumentRequiredError} */ - getUserResources(userId?: string | null, resourceUri?: string, limit?: number, cursor?: Cursor, permission?: string, collectionConfiguration?: GetUserResourcesParams.CollectionConfiguration): + getUserResources(userId: string, resourceUri?: string, limit?: number, cursor?: Cursor, permission?: string, collectionConfiguration?: GetUserResourcesParams.CollectionConfiguration): Promise>; } diff --git a/src/userPermissions/dtos.ts b/src/userPermissions/dtos.ts index 9e6a82a..031fdce 100644 --- a/src/userPermissions/dtos.ts +++ b/src/userPermissions/dtos.ts @@ -120,13 +120,6 @@ export interface UserResources extends IPaginated { * @memberof UserResources */ resources?: Array; - /** - * If the user has access to all sub-resources, then instead of resources being a list, this property will be populated `true`. - * @type {Array} - * @memberof UserResources - * @deprecated This property will always be false in later versions. To know if a user has access to all sub-resources, either call {@link authorizerUser} or specify the {@link collectionConfiguration} as {@link collectionConfiguration.INCLUDE_NESTED}. - */ - accessToAllSubResources?: boolean; } /** diff --git a/src/userPermissionsApi.js b/src/userPermissionsApi.js index 13627e4..2f49437 100644 --- a/src/userPermissionsApi.js +++ b/src/userPermissionsApi.js @@ -17,9 +17,8 @@ class UserPermissionsApi { async authorizeUser(userId, resourceUri, permission) { // verify required parameter 'userId' is not null or undefined - let tokenUserId = userId; if (userId === null || userId === undefined) { - tokenUserId = await getFallbackUser(this.client); + throw new ArgumentRequiredError('userId', 'Required parameter userId was null or undefined when calling authorizeUser.'); } // verify required parameter 'resourceUri' is not null or undefined if (resourceUri === null || resourceUri === undefined) { @@ -29,13 +28,13 @@ class UserPermissionsApi { if (permission === null || permission === undefined) { throw new ArgumentRequiredError('permission', 'Required parameter permission was null or undefined when calling authorizeUser.'); } - const url = `/v1/users/${encodeURIComponent(String(tokenUserId))}/resources/${encodeURIComponent(String(resourceUri))}/permissions/${encodeURIComponent(String(permission))}`; + const url = `/v1/users/${encodeURIComponent(String(userId))}/resources/${encodeURIComponent(String(resourceUri))}/permissions/${encodeURIComponent(String(permission))}`; try { const response = await this.client.get(url); return response; } catch (error) { if (error.status === 404) { - throw new UnauthorizedError(tokenUserId, resourceUri, permission); + throw new UnauthorizedError(userId, resourceUri, permission); } throw error; } @@ -43,77 +42,54 @@ class UserPermissionsApi { async disableUserToken(userId, tokenId) { // verify required parameter 'userId' is not null or undefined - let tokenUserId = userId; if (userId === null || userId === undefined) { - tokenUserId = await getFallbackUser(this.client); + throw new ArgumentRequiredError('userId', 'Required parameter userId was null or undefined when calling disableUserToken.'); } // verify required parameter 'tokenId' is not null or undefined if (tokenId === null || tokenId === undefined) { throw new ArgumentRequiredError('tokenId', 'Required parameter tokenId was null or undefined when calling disableUserToken.'); } - const url = `/v1/users/${encodeURIComponent(String(tokenUserId))}/tokens/${encodeURIComponent(String(tokenId))}`; + const url = `/v1/users/${encodeURIComponent(String(userId))}/tokens/${encodeURIComponent(String(tokenId))}`; const response = await this.client.delete(url); return response; } async getUserPermissionsForResource(userId, resourceUri) { // verify required parameter 'userId' is not null or undefined - let tokenUserId = userId; if (userId === null || userId === undefined) { - tokenUserId = await getFallbackUser(this.client); + throw new ArgumentRequiredError('userId', 'Required parameter userId was null or undefined when calling getUserPermissionsForResource.'); } // verify required parameter 'resourceUri' is not null or undefined if (resourceUri === null || resourceUri === undefined) { throw new ArgumentRequiredError('resourceUri', 'Required parameter resourceUri was null or undefined when calling getUserPermissionsForResource.'); } - const url = `/v1/users/${encodeURIComponent(String(tokenUserId))}/resources/${encodeURIComponent(String(resourceUri))}/permissions`; + const url = `/v1/users/${encodeURIComponent(String(userId))}/resources/${encodeURIComponent(String(resourceUri))}/permissions`; const response = await this.client.get(url); return response; } async getUserRolesForResource(userId, resourceUri) { - let tokenUserId = userId; if (userId === null || userId === undefined) { - tokenUserId = await getFallbackUser(this.client); + throw new ArgumentRequiredError('userId', 'Required parameter userId was null or undefined when calling getUserRolesForResource.'); } // verify required parameter 'resourceUri' is not null or undefined if (resourceUri === null || resourceUri === undefined) { throw new ArgumentRequiredError('resourceUri', 'Required parameter resourceUri was null or undefined when calling getUserRolesForResource.'); } - const url = `/v1/users/${encodeURIComponent(String(tokenUserId))}/resources/${encodeURIComponent(String(resourceUri))}/roles`; + const url = `/v1/users/${encodeURIComponent(String(userId))}/resources/${encodeURIComponent(String(resourceUri))}/roles`; const response = await this.client.get(url); return response; } async getUserResources(userId, resourceUri, limit, cursor, permission, collectionConfiguration) { // verify required parameter 'userId' is not null or undefined - let tokenUserId = userId; if (userId === null || userId === undefined) { - tokenUserId = await getFallbackUser(this.client); + throw new ArgumentRequiredError('userId', 'Required parameter userId was null or undefined when calling getUserResources.'); } - // If just checking the top level or the collectionConfiguration isn't set then assume we need to check for explicit top level. - // * Otherwise we can recurse down using the collectionConfiguration type. - if (!collectionConfiguration || collectionConfiguration === 'TOP_LEVEL_ONLY') { - try { - await this.authorizeUser(userId, resourceUri, permission); - return { - status: 200, - headers: {}, - data: { - userId: tokenUserId, - accessToAllSubResources: true, - resources: null - } - }; - } catch (error) { - // If the user doesn't have permission to everything, then use the query API. - } - } - - const url = new URL(`${this.client.baseUrl}/v1/users/${encodeURIComponent(String(tokenUserId))}/resources`); + const url = new URL(`${this.client.baseUrl}/v1/users/${encodeURIComponent(String(userId))}/resources`); const qs = { resourceUri }; if (limit) { qs.limit = limit; } if (cursor) { qs.cursor = cursor; }