import { PermissionStructure } from '@axinom/mosaic-id-utils'; import { MosaicError, MosaicErrors, ensureError, } from '@axinom/mosaic-service-common'; import { getGqlClient } from '../common/gql-client'; import { IdLinkBeErrors } from '../common/id-link-be-errors'; import { TokenResult } from '../common/types'; import { DevGenerateUserAccessTokenWithPermissionsDocument, DevGenerateUserAccessTokenWithPermissionsMutation, DevGenerateUserAccessTokenWithPermissionsMutationVariables, } from '../generated/graphql.types'; import { getWellKnownEndpoints } from '../well-known-endpoints'; /** * This function returns a User Token with a given permission structure. Depending on the param enforceValidPermissionStructure, if * any invalid permission(s) exists, the method will throw an error. * * @param authEndpoint URL for id-service authEndpoint. * @param accessToken A valid token with permission for DEV_GENERATE_USER_ACCESS_TOKEN_WITH_PERMISSIONS granted. * @param permissions The list of permissions to be assigned to the user access token. This is an array of shape { serviceId: string, permissions: string[] }. * @param email Email address the user token will be generated for. If this is provided, it must be connected to an existing user. * If unspecified, a pseudo-user with the following metadata will be used for generating the token. * * name: `**DEV**` * email: `dev@domain.local` * id: `00000000-0000-0000-0000-000000000000` * @param tokenExpirationInSeconds Token expiration time in seconds. If not given, will be defaulted to 2592000 (30 days). * @param enforceValidPermissionStructure A boolean indicating if the permissions passed should be validated against existing permissions. * @returns {TokenResult} {accessToken: string, expiresInSeconds: number, tokenType: string}. */ export const devGenerateUserAccessTokenWithPermissions = async ( authEndpoint: string, accessToken: string, permissions: PermissionStructure[], email?: string, tokenExpirationInSeconds?: number, enforceValidPermissionStructure = true, ): Promise => { try { // Authenticate using the token const client = getGqlClient( (await getWellKnownEndpoints(authEndpoint)).authGraphQlEndpoint, accessToken, ); const result = await client.mutate< DevGenerateUserAccessTokenWithPermissionsMutation, DevGenerateUserAccessTokenWithPermissionsMutationVariables >({ mutation: DevGenerateUserAccessTokenWithPermissionsDocument, variables: { input: { email: email, permissionStructure: permissions, enforceValidPermissionStructure: enforceValidPermissionStructure, tokenExpirationInSeconds: tokenExpirationInSeconds, }, }, errorPolicy: 'all', fetchPolicy: 'no-cache', }); if (!result.errors) { if (result.data?.devGenerateUserAccessTokenWithPermissions) { const tokenResult: TokenResult = { accessToken: result.data.devGenerateUserAccessTokenWithPermissions.accessToken, expiresInSeconds: result.data.devGenerateUserAccessTokenWithPermissions .expiresInSeconds, tokenType: result.data.devGenerateUserAccessTokenWithPermissions.tokenType, }; return tokenResult; } throw new MosaicError({ code: MosaicErrors.UnexpectedNullUndefined.code, message: `Unexpected null or undefined value received for 'devGenerateUserAccessTokenWithPermissions' result.`, }); } else { const aggregatedErrorMessage = result.errors?.reduce( (aggregatedError, gqlError) => { return (aggregatedError += gqlError.message); }, '', ); throw new MosaicError({ ...IdLinkBeErrors.AccessTokenGenerationError, details: { originalError: aggregatedErrorMessage, }, }); } } catch (e) { const error = ensureError(e); throw new MosaicError({ ...IdLinkBeErrors.AccessTokenGenerationError, details: { originalError: error.message, }, }); } };