UNPKG

@authup/core

Version:

Package containing global constants, types & interfaces.

1 lines 152 kB
{"version":3,"file":"index.cjs","sources":["../src/auth/ability-manager/build.ts","../src/auth/ability-manager/module.ts","../src/auth/constants.ts","../src/error/constants.ts","../src/error/entities/header.ts","../src/auth/error.ts","../src/utils/connection.ts","../src/utils/duplicate-slashes.ts","../src/utils/has-own-property.ts","../src/utils/nanoid.ts","../src/utils/object.ts","../src/utils/object-property.ts","../src/utils/proxy-connection.ts","../src/utils/self-id.ts","../src/utils/serialize.ts","../src/utils/template.ts","../src/utils/url.ts","../src/utils/uuid.ts","../src/auth/openid/utils.ts","../src/auth/utils/sub.ts","../src/auth/utils/sub-kind.ts","../src/domains/key/constants.ts","../src/domains/key/utils.ts","../src/domains/access-token/constants.ts","../src/domains/authorization-code/constants.ts","../src/domains/base.ts","../src/domains/client/api.ts","../src/domains/client-scope/api.ts","../src/domains/identity-provider/utils.ts","../src/domains/identity-provider/api.ts","../src/domains/identity-provider/constants.ts","../src/domains/identity-provider/preset/constants.ts","../src/domains/identity-provider/preset/utils.ts","../src/domains/identity-provider-role/api.ts","../src/domains/permission/api.ts","../src/domains/permission/constants.ts","../src/domains/realm/api.ts","../src/domains/realm/constants.ts","../src/domains/realm/socket.ts","../src/domains/realm/utils.ts","../src/domains/robot/api.ts","../src/domains/robot/error.ts","../src/domains/robot-permission/api.ts","../src/domains/robot-role/api.ts","../src/domains/role/api.ts","../src/domains/role/utils.ts","../src/domains/role-attribute/api.ts","../src/domains/role-permission/api.ts","../src/domains/scope/api.ts","../src/domains/scope/constants.ts","../src/domains/scope/utils.ts","../src/domains/user/api.ts","../src/domains/user/error.ts","../src/domains/user/utils.ts","../src/domains/user-attribute/api.ts","../src/domains/user-permission/api.ts","../src/domains/user-role/api.ts","../src/domains/contstants.ts","../src/domains/utils.ts","../src/http/api-client/module.ts","../src/http/api-client/utils.ts","../src/http/token-creator/constants.ts","../src/http/token-creator/variations/robot.ts","../src/http/token-creator/variations/robot-vault.ts","../src/http/token-creator/variations/user.ts","../src/http/token-creator/module.ts","../src/http/hook/utils.ts","../src/http/hook/module.ts","../src/http/cookies.ts"],"sourcesContent":["/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PermissionRelation } from '../../domains';\nimport type { Ability } from './type';\n\nfunction isStringArray(input: unknown): input is string[] {\n if (!Array.isArray(input)) {\n return false;\n }\n\n const items = input.map((item) => typeof item === 'string');\n\n return items.length === input.length;\n}\n\nfunction buildAbilityFields(input: string | null): string[] | undefined {\n if (!input) {\n return undefined;\n }\n\n const data = JSON.parse(input);\n if (!isStringArray(data) || data.length === 0) {\n return undefined;\n }\n\n return data;\n}\n\n// todo: replace CURRENT_DATE with evaluation of Date.now()\n\nexport function buildAbility(entity: PermissionRelation): Ability {\n if (typeof entity.permission === 'undefined') {\n throw new SyntaxError('The permission relation attribute is mandatory.');\n }\n\n return {\n name: entity.permission.name,\n condition: entity.condition,\n power: entity.power,\n fields: buildAbilityFields(entity.fields),\n inverse: entity.negation,\n target: entity.target,\n };\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { guard } from '@ucast/mongo2js';\n\nimport type {\n Ability, AbilityManagerFilterOptions,\n} from './type';\n\nexport class AbilityManager {\n protected items: Ability[];\n\n // ----------------------------------------------\n\n constructor(input: Ability[] | Ability = []) {\n this.set(input);\n }\n\n // ----------------------------------------------\n\n /**\n * Check if permission is assigned with field and condition restriction.\n */\n satisfy(options: AbilityManagerFilterOptions) : boolean;\n\n satisfy(name: string, options?: AbilityManagerFilterOptions) : boolean;\n\n satisfy(name: AbilityManagerFilterOptions | string, options: AbilityManagerFilterOptions = {}) : boolean {\n let items : Ability[];\n if (typeof name === 'string') {\n options.name = name;\n items = this.find(options);\n } else {\n items = this.find({\n ...name,\n ...options,\n });\n }\n\n return items.length > 0;\n }\n\n /**\n * Check if permission is assigned without any restrictions.\n *\n * @param name\n */\n has(name: string | string[]) : boolean {\n if (Array.isArray(name)) {\n return name.some((item) => this.has(item));\n }\n\n const items = this.find({\n name,\n });\n\n return items.length > 0;\n }\n\n // ----------------------------------------------\n\n /**\n * Find the first matching ability.\n *\n * @param input\n */\n findOne(input?: string | AbilityManagerFilterOptions) : Ability | undefined {\n const items = this.find(input);\n if (items.length === 0) {\n return undefined;\n }\n\n return items[0];\n }\n\n /**\n * Find all matching abilities.\n *\n * @param input\n */\n find(input?: string | AbilityManagerFilterOptions) : Ability[] {\n if (typeof input === 'undefined') {\n return this.items;\n }\n\n let options : AbilityManagerFilterOptions;\n if (typeof input === 'string') {\n options = { name: input };\n } else {\n options = input;\n }\n\n const output : Ability[] = [];\n\n for (let i = 0; i < this.items.length; i++) {\n if (\n options.name &&\n this.items[i].name !== options.name\n ) {\n continue;\n }\n\n if (\n !options.inverse &&\n this.items[i].inverse\n ) {\n continue;\n }\n\n if (\n this.items[i].condition &&\n options.object\n ) {\n const test = guard(this.items[i].condition);\n if (!test(options.object)) {\n continue;\n }\n }\n\n if (options.fn) {\n if (!options.fn(this.items[i])) {\n continue;\n }\n }\n\n if (\n options.field &&\n this.items[i].fields\n ) {\n const fields = Array.isArray(options.field) ?\n options.field :\n [options.field];\n\n let index : number;\n let valid : boolean = true;\n for (let j = 0; j < fields.length; j++) {\n index = this.items[i].fields.indexOf(fields[i]);\n if (index === -1) {\n valid = false;\n break;\n }\n }\n\n if (!valid) {\n continue;\n }\n }\n\n if (\n options.target &&\n this.items[i].target &&\n this.items[i].target !== options.target\n ) {\n continue;\n }\n\n if (\n typeof options.power === 'number' &&\n typeof this.items[i].power === 'number' &&\n options.power > this.items[i].power\n ) {\n continue;\n }\n\n output.push(this.items[i]);\n }\n\n return output;\n }\n\n set(\n input: Ability[] | Ability,\n merge?: boolean,\n ) {\n const items = Array.isArray(input) ?\n input :\n [input];\n\n if (merge) {\n // todo: check if unique !\n this.items = [...this.items, ...items];\n } else {\n this.items = items;\n }\n\n this.items\n .sort((a, b) => {\n if (typeof a.target === 'undefined' || a.target === null) {\n return -1;\n }\n\n if (typeof b.target === 'undefined' || b.target === null) {\n return 1;\n }\n\n return 0;\n })\n .sort((a, b) => b.power - a.power);\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum JWTAlgorithm {\n 'HS256' = 'HS256',\n 'HS384' = 'HS384',\n 'HS512' = 'HS512',\n 'RS256' = 'RS256',\n 'RS384' = 'RS384',\n 'RS512' = 'RS512',\n 'ES256' = 'ES256',\n 'ES384' = 'ES384',\n // 'ES512' = 'ES512',\n 'PS256' = 'PS256',\n 'PS384' = 'PS384',\n 'PS512' = 'PS512',\n}\n\nexport enum OAuth2TokenKind {\n ACCESS = 'access_token',\n ID_TOKEN = 'id_token',\n REFRESH = 'refresh_token',\n}\n\nexport enum OAuth2SubKind {\n CLIENT = 'client',\n USER = 'user',\n ROBOT = 'robot',\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum ErrorCode {\n ABILITY_INVALID = 'invalid_ability',\n\n HEADER_INVALID = 'invalid_header',\n HEADER_AUTH_TYPE_UNSUPPORTED = 'unsupported_auth_header_type',\n\n CREDENTIALS_INVALID = 'invalid_credentials',\n\n ENTITY_INACTIVE = 'inactive_entity',\n\n TOKEN_REDIRECT_URI_MISMATCH = 'redirect_uri_mismatch',\n TOKEN_INVALID = 'invalid_token',\n TOKEN_INACTIVE = 'inactive_token',\n TOKEN_EXPIRED = 'expired_token',\n TOKEN_CLIENT_INVALID = 'invalid_client',\n TOKEN_GRANT_INVALID = 'invalid_grant',\n TOKEN_GRANT_TYPE_UNSUPPORTED = 'unsupported_token_grant_type',\n TOKEN_SCOPE_INVALID = 'invalid_scope',\n TOKEN_SUB_KIND_INVALID = 'invalid_token_sub_kind',\n}\n","/*\n * Copyright (c) 2022-2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Input } from '@ebec/http';\nimport { BadRequestError } from '@ebec/http';\nimport type { AuthorizationHeaderType } from 'hapic';\nimport { ErrorCode } from '../constants';\n\nexport class HeaderError extends BadRequestError {\n constructor(...input: Input[]) {\n super({ code: ErrorCode.HEADER_INVALID }, ...input);\n }\n\n static unsupportedHeaderType(type: `${AuthorizationHeaderType}`) {\n return new HeaderError({\n code: ErrorCode.HEADER_AUTH_TYPE_UNSUPPORTED,\n message: `The authorization header type ${type} is not supported.`,\n });\n }\n}\n","/*\n * Copyright (c) 2022-2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Input } from '@ebec/http';\nimport { BadRequestError } from '@ebec/http';\nimport { ErrorCode } from '../error';\nimport { OAuth2TokenKind } from './constants';\nimport type { OAuth2SubKind } from './constants';\n\nexport class TokenError extends BadRequestError {\n constructor(...input: Input[]) {\n super({\n code: ErrorCode.TOKEN_INVALID,\n message: 'The Token is invalid.',\n statusCode: 400,\n }, ...input);\n }\n\n // -------------------------------------------------\n\n static subKindInvalid() {\n return new TokenError({\n code: ErrorCode.TOKEN_SUB_KIND_INVALID,\n message: 'The token sub kind is invalid.',\n });\n }\n\n static expired(kind?: `${OAuth2TokenKind}`) {\n return new TokenError({\n code: ErrorCode.TOKEN_EXPIRED,\n message: `The ${kind || 'token'} has been expired.`,\n });\n }\n\n static kindInvalid() {\n return new TokenError({\n message: 'The token kind is invalid.',\n });\n }\n\n static notActiveBefore(date?: string | Date) {\n if (typeof date === 'undefined') {\n return new TokenError({\n code: ErrorCode.TOKEN_INACTIVE,\n message: 'The token is not active yet.',\n });\n }\n\n return new TokenError({\n code: ErrorCode.TOKEN_INACTIVE,\n message: `The token is not active before: ${date}.`,\n data: {\n date,\n },\n });\n }\n\n static headerInvalid(message?: string) {\n return new TokenError({\n code: ErrorCode.TOKEN_INVALID,\n message: message || 'The token header is malformed.',\n });\n }\n\n static payloadInvalid(message?: string) {\n return new TokenError({\n code: ErrorCode.TOKEN_INVALID,\n message: message || 'The token payload is malformed.',\n });\n }\n\n // -------------------------------------------------\n\n static accessTokenRequired() {\n return new TokenError({\n message: 'An access token is required to authenticate.',\n });\n }\n\n static clientInvalid() {\n return new TokenError({\n message: 'Client authentication failed.',\n code: ErrorCode.TOKEN_CLIENT_INVALID,\n });\n }\n\n static grantInvalid() {\n return new TokenError({\n message: 'The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token ' +\n 'is invalid, expired, revoked, does not match the redirection URI used in the authorization request, ' +\n 'or was issued to another client.',\n code: ErrorCode.TOKEN_GRANT_INVALID,\n });\n }\n\n static grantTypeUnsupported() {\n return new TokenError({\n message: 'The authorization grant type is not supported by the authorization server.',\n code: ErrorCode.TOKEN_GRANT_TYPE_UNSUPPORTED,\n data: {\n hint: 'Check that all required parameters have been provided',\n },\n });\n }\n\n static tokenInvalid(kind?: `${OAuth2TokenKind}`) {\n return new TokenError({\n message: `The ${kind || 'token'} is invalid.`,\n });\n }\n\n static tokenNotFound(kind: `${OAuth2TokenKind}` = OAuth2TokenKind.ACCESS) {\n return new TokenError({\n message: `The ${kind} was not found.`,\n });\n }\n\n static requestInvalid(message?: string) {\n return new TokenError({\n message: message || 'The request is missing a required parameter, includes an unsupported parameter value, ' +\n 'repeats a parameter, or is otherwise malformed.',\n data: {\n hint: 'Check that all parameters have been provided correctly',\n },\n });\n }\n\n static scopeInvalid() {\n return new TokenError({\n message: ' The requested scope is invalid, unknown or malformed.',\n code: ErrorCode.TOKEN_SCOPE_INVALID,\n });\n }\n\n static redirectUriMismatch() {\n return new TokenError({\n message: 'The redirect URI is missing or do not match',\n code: ErrorCode.TOKEN_REDIRECT_URI_MISMATCH,\n });\n }\n\n static responseTypeUnsupported() {\n return new TokenError({\n message: 'The authorization server does not support obtaining an access token using this method.',\n });\n }\n\n static targetInactive(kind: `${OAuth2SubKind}`) {\n return new TokenError({\n message: `The target token ${kind} is not active.`,\n });\n }\n\n static signingKeyMissing() {\n return new TokenError({\n message: 'A token signing key could not be retrieved.',\n });\n }\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport type ConnectionString = {\n type: 'user' | 'robot' | 'client',\n url: string,\n name: string,\n password: string\n};\n\nconst regex = /(?:(user|robot|client):\\/\\/)(?:(\\w+)(?::(\\w+))@)(.*)$/;\n\nexport function isConnectionString(input: string) : boolean {\n return regex.test(input);\n}\n\nexport function parseConnectionString(\n input: string,\n) : ConnectionString | undefined {\n const match = input.match(regex);\n\n if (!match) {\n return undefined;\n }\n\n return {\n type: match[1] as 'user' | 'robot' | 'client',\n url: match[4],\n name: match[2],\n password: match[3],\n };\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function cleanDoubleSlashes(input: string) : string {\n if (input.indexOf('://') !== -1) {\n return input.split('://')\n .map((str) => cleanDoubleSlashes(str))\n .join('://');\n }\n\n return input.replace(/\\/+/g, '/');\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function hasOwnProperty<X extends {}, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown> {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nexport function isPropertySet<X extends Record<string, any>, K extends keyof X>(\n obj: X,\n prop: K,\n) : boolean {\n return hasOwnProperty(obj, prop);\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { customAlphabet } from 'nanoid';\n\nexport function createNanoID(alphabet?: string) : string;\nexport function createNanoID(len?: number) : string;\nexport function createNanoID(alphabet?: string, len?: number) : string;\nexport function createNanoID(alphabetOrLen?: string | number, len?: number) : string {\n if (typeof alphabetOrLen === 'string') {\n return customAlphabet(alphabetOrLen, len || 21)();\n }\n\n if (typeof alphabetOrLen === 'number') {\n return customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', alphabetOrLen)();\n }\n\n return customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', len || 21)();\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isObject(input: unknown) : input is Record<string, any> {\n return !!input &&\n typeof input === 'object' &&\n !Array.isArray(input);\n}\n\nexport function extendObject<T extends Record<string, any>>(target: T, source: Partial<T>) : T {\n const keys = Object.keys(source);\n for (let i = 0; i < keys.length; i++) {\n target[keys[i] as keyof T] = source[keys[i]];\n }\n\n return target;\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isPropertySet } from './has-own-property';\n\nexport function nullifyEmptyObjectProperties<T extends Record<string, any>>(data: T) : T {\n const keys : (keyof T)[] = Object.keys(data);\n\n for (let i = 0; i < keys.length; i++) {\n if (data[keys[i]] === '') {\n data[keys[i]] = null as T[keyof T];\n }\n }\n\n return data;\n}\n\nexport function deleteUndefinedObjectProperties<T extends Record<string, any>>(data: T) : T {\n const keys : string[] = Object.keys(data);\n\n for (let i = 0; i < keys.length; i++) {\n if (typeof data[keys[i]] === 'undefined') {\n delete data[keys[i]];\n }\n }\n\n return data;\n}\n\nexport function extractObjectProperty<T extends Record<string, any>, K extends keyof T>(\n data: T | undefined,\n key: K,\n) : T[K] | undefined {\n if (!data) {\n return undefined;\n }\n\n if (isPropertySet(data, key)) {\n return data[key];\n }\n\n return undefined;\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport type ProxyConnectionConfig = {\n protocol: 'http' | 'https',\n host: string,\n port: number,\n auth: {\n username: string,\n password: string,\n }\n};\n\nexport function parseProxyConnectionString(\n input: string,\n) : ProxyConnectionConfig | undefined {\n const match = input\n .match(/(?:(https|http):\\/\\/)(?:(\\w+)(?::(\\w+))?@)?(?:([^:]+))(?::(\\d{1,5}))?$/);\n\n if (!match) {\n return undefined;\n }\n\n return {\n protocol: match[1] as 'http' | 'https',\n host: match[4],\n port: parseInt(match[5], 10),\n auth: {\n username: match[2],\n password: match[3],\n },\n };\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isSelfId(id: string) {\n return id === '@me' ||\n id === '@self';\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { destr } from 'destr';\n\nexport function serialize(input: unknown) : string {\n if (typeof input === 'boolean') {\n return input ? 'true' : 'false';\n }\n\n if (typeof input === 'undefined') {\n return 'undefined';\n }\n\n if (input === null) {\n return 'null';\n }\n\n if (typeof input === 'number') {\n return `${input}`;\n }\n\n if (typeof input === 'string') {\n return input;\n }\n\n return JSON.stringify(input);\n}\n\nexport function deserialize<T = any>(input: any) : T {\n return destr(input);\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function template(\n str: string,\n data: Record<string, any>,\n regex = /\\{\\{(.+?)\\}\\}/g,\n) : string {\n return Array.from(str.matchAll(regex))\n .reduce((\n acc,\n match,\n ) => {\n if (typeof data[match[1]] !== 'undefined') {\n return acc.replace(match[0], data[match[1]]);\n }\n\n return acc;\n }, str);\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function makeURLPublicAccessible(url: string) {\n return url.replace('0.0.0.0', '127.0.0.1');\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isUUID(input: string) : boolean {\n // eslint-disable-next-line prefer-regex-literals\n const regexp = new RegExp(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i);\n return regexp.test(input);\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from '../../utils';\nimport type { OAuth2OpenIDProviderMetadata } from './type';\n\nexport function isOAuth2OpenIDProviderMetadata(input: unknown) : input is OAuth2OpenIDProviderMetadata {\n if (!isObject(input)) {\n return false;\n }\n\n if (typeof input.issuer !== 'string') {\n return false;\n }\n\n if (typeof input.authorization_endpoint !== 'string') {\n return false;\n }\n\n if (typeof input.jwks_uri !== 'string') {\n return false;\n }\n\n if (!Array.isArray(input.response_type_supported)) {\n return false;\n }\n\n if (!Array.isArray(input.subject_types_supported)) {\n return false;\n }\n\n if (!Array.isArray(input.id_token_signing_alg_values_supported)) {\n return false;\n }\n\n if (typeof input.token_endpoint !== 'string') {\n return false;\n }\n\n return true;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function getOAuth2SubByEntity<T extends {\n robot_id: string | null,\n user_id: string | null,\n client_id: string | null\n}>(entity: T) : string {\n return entity.robot_id || entity.user_id || entity.client_id;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { OAuth2SubKind } from '../constants';\n\nexport function getOAuth2SubKindByEntity<T extends {\n robot_id: string | null,\n user_id: string | null\n client_id: string | null\n}>(entity: T) : OAuth2SubKind {\n if (entity.robot_id) {\n return OAuth2SubKind.ROBOT;\n }\n\n if (entity.user_id) {\n return OAuth2SubKind.USER;\n }\n\n return OAuth2SubKind.CLIENT;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum KeyType {\n /**\n * Octet/Byte sequence (used to represent symmetric keys)\n */\n OCT = 'oct',\n /**\n * RSA\n */\n RSA = 'rsa',\n /**\n * Elliptic Curve\n */\n EC = 'ec',\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nfunction wrapPem(\n type: 'PRIVATE KEY' | 'PUBLIC KEY',\n input: string | ArrayBuffer | Buffer,\n) {\n if (typeof input !== 'string') {\n input = Buffer.from(input).toString('base64');\n }\n\n return `-----BEGIN ${type}-----\\n${input}\\n-----END ${type}-----`;\n}\n\nexport function wrapPrivateKeyPem(input: string | ArrayBuffer | Buffer) {\n return wrapPem('PRIVATE KEY', input);\n}\n\nexport function wrapPublicKeyPem(input: string | ArrayBuffer | Buffer) {\n return wrapPem('PUBLIC KEY', input);\n}\n\n// ------------------------------------------------------------\n\nfunction unwrapPem(\n type: 'PRIVATE KEY' | 'PUBLIC KEY',\n input: string,\n) {\n if (typeof input !== 'string') {\n input = Buffer.from(input).toString('base64');\n }\n\n input = input.replace(`-----BEGIN ${type}-----\\n`, '');\n\n input = input.replace(`\\n-----END ${type}-----\\n`, '');\n input = input.replace(`-----END ${type}-----\\n`, '');\n input = input.replace(`\\n-----END ${type}-----`, '');\n\n return input;\n}\n\nexport function unwrapPrivateKeyPem(input: string) {\n return unwrapPem('PRIVATE KEY', input);\n}\n\nexport function unwrapPublicKeyPem(input: string) {\n return unwrapPem('PUBLIC KEY', input);\n}\n","/*\n * Copyright (c) 2022-2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum OAuth2TokenGrant {\n AUTHORIZATION_CODE = 'authorization_code',\n CLIENT_CREDENTIALS = 'client_credentials',\n PASSWORD = 'password',\n ROBOT_CREDENTIALS = 'robot_credentials',\n REFRESH_TOKEN = 'refresh_token',\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum OAuth2AuthorizationResponseType {\n NONE = 'none',\n CODE = 'code',\n TOKEN = 'token',\n ID_TOKEN = 'id_token',\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createClient, isClient } from 'hapic';\nimport type { Client, RequestBaseOptions } from 'hapic';\nimport type { BaseAPIContext } from './types-base';\n\nexport class BaseAPI {\n protected client! : Client;\n\n // -----------------------------------------------------------------------------------\n\n constructor(context?: BaseAPIContext) {\n context = context || {};\n\n this.setClient(context.client);\n }\n\n // -----------------------------------------------------------------------------------\n\n setClient(input?: Client | RequestBaseOptions) {\n this.client = isClient(input) ?\n input :\n createClient(input);\n }\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuildInput } from 'rapiq';\nimport { buildQuery } from 'rapiq';\nimport { BaseAPI } from '../base';\nimport type { Client } from './types';\nimport { nullifyEmptyObjectProperties } from '../../utils';\nimport type { CollectionResourceResponse, DomainAPI, SingleResourceResponse } from '../types-base';\n\nexport class ClientAPI extends BaseAPI implements DomainAPI<Client> {\n async getMany(\n options?: BuildInput<Client>,\n ): Promise<CollectionResourceResponse<Client>> {\n const response = await this.client\n .get(`clients${buildQuery(options)}`);\n\n return response.data;\n }\n\n async getOne(\n id: Client['id'],\n options?: BuildInput<Client>,\n ): Promise<SingleResourceResponse<Client>> {\n const response = await this.client\n .get(`clients/${id}${buildQuery(options)}`);\n\n return response.data;\n }\n\n async delete(\n id: Client['id'],\n ): Promise<SingleResourceResponse<Client>> {\n const response = await this.client\n .delete(`clients/${id}`);\n\n return response.data;\n }\n\n async create(\n data: Partial<Client>,\n ): Promise<SingleResourceResponse<Client>> {\n const response = await this.client\n .post('clients', nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n\n async update(\n id: Client['id'],\n data: Partial<Client>,\n ): Promise<SingleResourceResponse<Client>> {\n const response = await this.client.post(`clients/${id}`, nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuildInput } from 'rapiq';\nimport { buildQuery } from 'rapiq';\nimport { BaseAPI } from '../base';\nimport type { ClientScope } from './types';\nimport type { CollectionResourceResponse, DomainAPISlim, SingleResourceResponse } from '../types-base';\n\nexport class ClientScopeAPI extends BaseAPI implements DomainAPISlim<ClientScope> {\n async getMany(data?: BuildInput<ClientScope>) : Promise<CollectionResourceResponse<ClientScope>> {\n const response = await this.client.get(`client-scopes${buildQuery(data)}`);\n return response.data;\n }\n\n async getOne(id: ClientScope['id']) : Promise<SingleResourceResponse<ClientScope>> {\n const response = await this.client.get(`client-scopes/${id}`);\n\n return response.data;\n }\n\n async delete(id: ClientScope['id']) : Promise<SingleResourceResponse<ClientScope>> {\n const response = await this.client.delete(`client-scopes/${id}`);\n\n return response.data;\n }\n\n async create(data: Partial<ClientScope>) : Promise<SingleResourceResponse<ClientScope>> {\n const response = await this.client.post('client-scopes', data);\n\n return response.data;\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function buildIdentityProviderAuthorizeCallbackPath(id: string | number) {\n return `/identity-providers/${id}/authorize-callback`;\n}\n\nexport function buildIdentityProviderAuthorizePath(id: string | number) {\n return `/identity-providers/${id}/authorize-url`;\n}\n\nexport function isValidIdentityProviderSub(sub: string) : boolean {\n return /^[a-z0-9-_]{3,36}$/.test(sub);\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuildInput } from 'rapiq';\nimport { buildQuery } from 'rapiq';\nimport { BaseAPI } from '../base';\nimport type { IdentityProvider } from './types';\nimport { cleanDoubleSlashes, nullifyEmptyObjectProperties } from '../../utils';\nimport type { CollectionResourceResponse, DomainAPI, SingleResourceResponse } from '../types-base';\nimport { buildIdentityProviderAuthorizePath } from './utils';\n\nexport class IdentityProviderAPI extends BaseAPI implements DomainAPI<IdentityProvider> {\n getAuthorizeUri(baseUrl: string, id: IdentityProvider['id']): string {\n return cleanDoubleSlashes(`${baseUrl}/${buildIdentityProviderAuthorizePath(id)}`);\n }\n\n async getMany(record?: BuildInput<IdentityProvider>): Promise<CollectionResourceResponse<IdentityProvider>> {\n const response = await this.client.get(`identity-providers${buildQuery(record)}`);\n\n return response.data;\n }\n\n async getOne(\n id: IdentityProvider['id'],\n record?: BuildInput<IdentityProvider>,\n ): Promise<SingleResourceResponse<IdentityProvider>> {\n const response = await this.client.get(`identity-providers/${id}${buildQuery(record)}`);\n\n return response.data;\n }\n\n async delete(id: IdentityProvider['id']): Promise<SingleResourceResponse<IdentityProvider>> {\n const response = await this.client.delete(`identity-providers/${id}`);\n\n return response.data;\n }\n\n async create(data: Partial<IdentityProvider>): Promise<SingleResourceResponse<IdentityProvider>> {\n const response = await this.client.post('identity-providers', nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n\n async update(id: IdentityProvider['id'], data: Partial<IdentityProvider>): Promise<SingleResourceResponse<IdentityProvider>> {\n const response = await this.client.post(`identity-providers/${id}`, nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum IdentityProviderProtocol {\n LDAP = 'ldap',\n OAUTH2 = 'oauth2',\n OIDC = 'oidc',\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum IdentityProviderPreset {\n FACEBOOK = 'facebook',\n GITHUB = 'github',\n GITLAB = 'gitlab',\n GOOGLE = 'google',\n PAYPAL = 'paypal',\n INSTAGRAM = 'instagram',\n STACKOVERFLOW = 'stackoverflow',\n TWITTER = 'twitter',\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { IdentityProviderProtocol } from '../constants';\nimport { IdentityProviderPreset } from './constants';\n\nexport function getIdentityProviderProtocolForPreset(\n id: `${IdentityProviderPreset}`,\n) : `${IdentityProviderProtocol}` | undefined {\n switch (id) {\n case IdentityProviderPreset.GITHUB:\n case IdentityProviderPreset.GITLAB:\n case IdentityProviderPreset.GOOGLE:\n case IdentityProviderPreset.FACEBOOK:\n case IdentityProviderPreset.INSTAGRAM:\n case IdentityProviderPreset.PAYPAL:\n case IdentityProviderPreset.STACKOVERFLOW:\n case IdentityProviderPreset.TWITTER:\n return IdentityProviderProtocol.OIDC;\n }\n\n return undefined;\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuildInput } from 'rapiq';\nimport { buildQuery } from 'rapiq';\nimport { nullifyEmptyObjectProperties } from '../../utils';\nimport { BaseAPI } from '../base';\nimport type { IdentityProviderRole } from './types';\nimport type { CollectionResourceResponse, DomainAPI, SingleResourceResponse } from '../types-base';\n\nexport class IdentityProviderRoleAPI extends BaseAPI implements DomainAPI<IdentityProviderRole> {\n async getMany(data: BuildInput<IdentityProviderRole>): Promise<CollectionResourceResponse<IdentityProviderRole>> {\n const response = await this.client.get(`identity-provider-roles${buildQuery(data)}`);\n\n return response.data;\n }\n\n async getOne(id: IdentityProviderRole['id']): Promise<SingleResourceResponse<IdentityProviderRole>> {\n const response = await this.client.get(`identity-provider-roles/${id}`);\n\n return response.data;\n }\n\n async delete(id: IdentityProviderRole['id']): Promise<SingleResourceResponse<IdentityProviderRole>> {\n const response = await this.client.delete(`identity-provider-roles/${id}`);\n\n return response.data;\n }\n\n async create(data: Partial<IdentityProviderRole>): Promise<SingleResourceResponse<IdentityProviderRole>> {\n const response = await this.client.post('identity-provider-roles', nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n\n async update(\n id: IdentityProviderRole['id'],\n data: Partial<IdentityProviderRole>,\n ): Promise<SingleResourceResponse<IdentityProviderRole>> {\n const response = await this.client.post(`identity-provider-roles/${id}`, data);\n\n return response.data;\n }\n}\n","/*\n * Copyright (c) 2021-2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuildInput } from 'rapiq';\nimport { buildQuery } from 'rapiq';\nimport { nullifyEmptyObjectProperties } from '../../utils';\nimport { BaseAPI } from '../base';\nimport type { Permission } from './types';\nimport type { CollectionResourceResponse, DomainAPI, SingleResourceResponse } from '../types-base';\n\nexport class PermissionAPI extends BaseAPI implements DomainAPI<Permission> {\n async getMany(data?: BuildInput<Permission>): Promise<CollectionResourceResponse<Permission>> {\n const response = await this.client.get(`permissions${buildQuery(data)}`);\n return response.data;\n }\n\n async delete(id: Permission['id']): Promise<SingleResourceResponse<Permission>> {\n const response = await this.client.delete(`permissions/${id}`);\n\n return response.data;\n }\n\n async getOne(id: Permission['id'], record?: BuildInput<Permission>) {\n const response = await this.client.get(`permissions/${id}${buildQuery(record)}`);\n\n return response.data;\n }\n\n async create(data: Partial<Permission>): Promise<SingleResourceResponse<Permission>> {\n const response = await this.client.post('permissions', nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n\n async update(id: Permission['id'], data: Partial<Permission>): Promise<SingleResourceResponse<Permission>> {\n const response = await this.client.post(`permissions/${id}`, nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum PermissionName {\n CLIENT_ADD = 'client_add',\n CLIENT_DROP = 'client_drop',\n CLIENT_EDIT = 'client_edit',\n\n PROVIDER_ADD = 'provider_add',\n PROVIDER_DROP = 'provider_drop',\n PROVIDER_EDIT = 'provider_edit',\n\n PERMISSION_ADD = 'permission_add',\n PERMISSION_DROP = 'permission_drop',\n PERMISSION_EDIT = 'permission_edit',\n\n REALM_ADD = 'realm_add',\n REALM_DROP = 'realm_drop',\n REALM_EDIT = 'realm_edit',\n\n ROBOT_ADD = 'robot_add',\n ROBOT_DROP = 'robot_drop',\n ROBOT_EDIT = 'robot_edit',\n\n ROBOT_PERMISSION_ADD = 'robot_permission_add',\n ROBOT_PERMISSION_DROP = 'robot_permission_drop',\n\n ROBOT_ROLE_ADD = 'robot_role_add',\n ROBOT_ROLE_DROP = 'robot_role_drop',\n ROBOT_ROLE_EDIT = 'robot_role_edit',\n\n ROLE_ADD = 'role_add',\n ROLE_DROP = 'role_drop',\n ROLE_EDIT = 'role_edit',\n\n ROLE_PERMISSION_ADD = 'role_permission_add',\n ROLE_PERMISSION_DROP = 'role_permission_drop',\n\n SCOPE_ADD = 'scope_add',\n SCOPE_DROP = 'scope_drop',\n SCOPE_EDIT = 'scope_edit',\n\n TOKEN_VERIFY = 'token_verify',\n\n USER_ADD = 'user_add',\n USER_DROP = 'user_drop',\n USER_EDIT = 'user_edit',\n\n USER_PERMISSION_ADD = 'user_permission_add',\n USER_PERMISSION_DROP = 'user_permission_drop',\n\n USER_ROLE_ADD = 'user_role_add',\n USER_ROLE_DROP = 'user_role_drop',\n USER_ROLE_EDIT = 'user_role_edit',\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuildInput } from 'rapiq';\nimport { buildQuery } from 'rapiq';\nimport { nullifyEmptyObjectProperties } from '../../utils';\nimport { BaseAPI } from '../base';\nimport type { Realm } from './types';\nimport type { CollectionResourceResponse, DomainAPI, SingleResourceResponse } from '../types-base';\n\nexport class RealmAPI extends BaseAPI implements DomainAPI<Realm> {\n async getMany(data?: BuildInput<Realm>): Promise<CollectionResourceResponse<Realm>> {\n const response = await this.client.get(`realms${buildQuery(data)}`);\n\n return response.data;\n }\n\n async getOne(id: Realm['id']): Promise<SingleResourceResponse<Realm>> {\n const response = await this.client.get(`realms/${id}`);\n\n return response.data;\n }\n\n async delete(id: Realm['id']): Promise<SingleResourceResponse<Realm>> {\n const response = await this.client.delete(`realms/${id}`);\n\n return response.data;\n }\n\n async create(data: Partial<Realm>): Promise<SingleResourceResponse<Realm>> {\n const response = await this.client.post('realms', nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n\n async update(realmId: Realm['id'], data: Partial<Realm>): Promise<SingleResourceResponse<Realm>> {\n const response = await this.client.post(`realms/${realmId}`, nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport const REALM_MASTER_NAME = 'master';\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Realm } from './types';\n\nexport function buildSocketRealmNamespaceName(realmId: Realm['id']) {\n return `/realm#${realmId}`;\n}\n\nexport function parseSocketRealmNamespaceName(name: string) : string | undefined {\n return name.startsWith('/realm#') ?\n name.substring('/realm#'.length) :\n name;\n}\n","/*\n * Copyright (c) 2021-2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isPropertySet } from '../../utils';\nimport { REALM_MASTER_NAME } from './constants';\n\n/**\n * Check if a realm resource is writable.\n *\n * @param realm\n * @param resourceRealmId\n */\nexport function isRealmResourceWritable(\n realm?: { id?: string, name?: string},\n resourceRealmId?: null | string | string[],\n) : boolean {\n if (Array.isArray(resourceRealmId)) {\n for (let i = 0; i < resourceRealmId.length; i++) {\n if (isRealmResourceWritable(realm, resourceRealmId[i])) {\n return true;\n }\n }\n\n return false;\n }\n\n if (!realm) {\n return false;\n }\n\n if (\n isPropertySet(realm, 'name') &&\n realm.name === REALM_MASTER_NAME\n ) {\n return true;\n }\n\n return realm.id === resourceRealmId;\n}\n\n/**\n * Check if realm resource is readable.\n *\n * @param realm\n * @param resourceRealmId\n */\nexport function isRealmResourceReadable(\n realm?: { id?: string, name?: string },\n resourceRealmId?: string | string[],\n) : boolean {\n if (Array.isArray(resourceRealmId)) {\n if (resourceRealmId.length === 0) {\n return true;\n }\n\n for (let i = 0; i < resourceRealmId.length; i++) {\n if (isRealmResourceReadable(realm, resourceRealmId[i])) {\n return true;\n }\n }\n\n return false;\n }\n\n if (typeof realm === 'undefined') {\n return false;\n }\n\n if (\n isPropertySet(realm, 'name') &&\n realm.name === REALM_MASTER_NAME\n ) {\n return true;\n }\n\n return !resourceRealmId ||\n realm.id === resourceRealmId;\n}\n\nexport function isValidRealmName(name: string) : boolean {\n return /^[a-zA-Z0-9-_]{3,128}$/.test(name);\n}\n","/*\n * Copyright (c) 2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuildInput } from 'rapiq';\nimport { buildQuery } from 'rapiq';\nimport { BaseAPI } from '../base';\nimport type { Robot } from './types';\nimport { nullifyEmptyObjectProperties } from '../../utils';\nimport type { CollectionResourceResponse, DomainAPI, SingleResourceResponse } from '../types-base';\n\nexport class RobotAPI extends BaseAPI implements DomainAPI<Robot> {\n async getMany(\n options?: BuildInput<Robot>,\n ): Promise<CollectionResourceResponse<Robot>> {\n const response = await this.client\n .get(`robots${buildQuery(options)}`);\n\n return response.data;\n }\n\n async getOne(\n id: Robot['id'],\n options?: BuildInput<Robot>,\n ): Promise<SingleResourceResponse<Robot>> {\n const response = await this.client\n .get(`robots/${id}${buildQuery(options)}`);\n\n return response.data;\n }\n\n async delete(\n id: Robot['id'],\n ): Promise<SingleResourceResponse<Robot>> {\n const response = await this.client\n .delete(`robots/${id}`);\n\n return response.data;\n }\n\n async create(\n data: Partial<Robot>,\n ): Promise<SingleResourceResponse<Robot>> {\n const response = await this.client\n .post('robots', nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n\n async update(\n id: Robot['id'],\n data: Partial<Robot>,\n ): Promise<SingleResourceResponse<Robot>> {\n const response = await this.client.post(`robots/${id}`, nullifyEmptyObjectProperties(data));\n\n return response.data;\n }\n\n async integrity(\n id: Robot['id'] | Robot['name'],\n ): Promise<SingleResourceResponse<Robot>> {\n const { data: response } = await this.client\n .get(`robots/${id}/integrity`);\n\n return response;\n }\n}\n","/*\n *