@authup/server-core 1.0.0-beta.37 → 1.0.0-beta.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/database/data-source/options/module.mjs +16 -16
- package/dist/adapters/database/domains/client/index.d.ts +0 -1
- package/dist/adapters/database/domains/client/index.d.ts.map +1 -1
- package/dist/adapters/database/domains/client/index.mjs +1 -2
- package/dist/adapters/database/domains/index.mjs +26 -28
- package/dist/adapters/database/domains/policy/repository.mjs +1 -1
- package/dist/adapters/database/domains/robot/index.d.ts +0 -1
- package/dist/adapters/database/domains/robot/index.d.ts.map +1 -1
- package/dist/adapters/database/domains/robot/index.mjs +1 -2
- package/dist/adapters/database/domains/role/repository.d.ts +0 -6
- package/dist/adapters/database/domains/role/repository.d.ts.map +1 -1
- package/dist/adapters/database/domains/role/repository.mjs +1 -58
- package/dist/adapters/database/domains/role/repository.mjs.map +1 -1
- package/dist/adapters/database/domains/role-permission/entity.mjs +1 -1
- package/dist/adapters/database/domains/user/repository.d.ts +1 -5
- package/dist/adapters/database/domains/user/repository.d.ts.map +1 -1
- package/dist/adapters/database/domains/user/repository.mjs +0 -60
- package/dist/adapters/database/domains/user/repository.mjs.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/repository.d.ts.map +1 -1
- package/dist/adapters/database/extra-attribute-repository/tree/repository.mjs +1 -0
- package/dist/adapters/database/extra-attribute-repository/tree/repository.mjs.map +1 -1
- package/dist/adapters/database/index.mjs +18 -20
- package/dist/adapters/http/adapters/index.mjs +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.d.ts +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.mjs +10 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/authorize.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/client-credentials.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/client-credentials.mjs +5 -13
- package/dist/adapters/http/adapters/oauth2/grant-types/client-credentials.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/index.mjs +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/password.d.ts +2 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/password.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/password.mjs +11 -2
- package/dist/adapters/http/adapters/oauth2/grant-types/password.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.d.ts +5 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs +19 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/types.d.ts +6 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/types.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.d.ts +15 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.d.ts.map +1 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.mjs +57 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.mjs.map +1 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/guess.mjs +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/index.d.ts +1 -0
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/index.d.ts.map +1 -1
- package/dist/adapters/http/adapters/oauth2/grant-types/utils/index.mjs +2 -1
- package/dist/adapters/http/adapters/oauth2/index.mjs +2 -1
- package/dist/adapters/http/controllers/entities/client/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/client/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/client/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/identity-provider/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/permission/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/attributes-validator.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/validation.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/validation.mjs +1 -1
- package/dist/adapters/http/controllers/entities/policy/utils/validation.mjs.map +1 -1
- package/dist/adapters/http/controllers/entities/robot/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/entities/robot/module.mjs +1 -1
- package/dist/adapters/http/controllers/entities/robot/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs +5 -6
- package/dist/adapters/http/controllers/workflows/authorize/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.d.ts.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/module.mjs +4 -1
- package/dist/adapters/http/controllers/workflows/token/module.mjs.map +1 -1
- package/dist/adapters/http/controllers/workflows/token/types.d.ts +2 -1
- package/dist/adapters/http/controllers/workflows/token/types.d.ts.map +1 -1
- package/dist/adapters/http/index.mjs +2 -1
- package/dist/adapters/http/middleware/built-in/assets.mjs +3 -3
- package/dist/adapters/http/middleware/built-in/assets.mjs.map +1 -1
- package/dist/app/modules/database/repositories/bindings.d.ts +17 -0
- package/dist/app/modules/database/repositories/bindings.d.ts.map +1 -0
- package/dist/app/modules/database/repositories/bindings.mjs +40 -0
- package/dist/app/modules/database/repositories/bindings.mjs.map +1 -0
- package/dist/app/modules/database/repositories/client/repository.d.ts +5 -1
- package/dist/app/modules/database/repositories/client/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/client/repository.mjs +69 -1
- package/dist/app/modules/database/repositories/client/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/permission/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/permission/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/policy/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/policy/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/realm/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/realm/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/robot/repository.d.ts +5 -1
- package/dist/app/modules/database/repositories/robot/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/robot/repository.mjs +61 -1
- package/dist/app/modules/database/repositories/robot/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/role/repository.d.ts +3 -0
- package/dist/app/modules/database/repositories/role/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/role/repository.mjs +17 -1
- package/dist/app/modules/database/repositories/role/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/scope/repository.mjs +1 -1
- package/dist/app/modules/database/repositories/scope/repository.mjs.map +1 -1
- package/dist/app/modules/database/repositories/user/repository.d.ts +4 -1
- package/dist/app/modules/database/repositories/user/repository.d.ts.map +1 -1
- package/dist/app/modules/database/repositories/user/repository.mjs +31 -2
- package/dist/app/modules/database/repositories/user/repository.mjs.map +1 -1
- package/dist/app/modules/http/modules/controller.d.ts +1 -2
- package/dist/app/modules/http/modules/controller.d.ts.map +1 -1
- package/dist/app/modules/http/modules/controller.mjs +32 -34
- package/dist/app/modules/http/modules/controller.mjs.map +1 -1
- package/dist/app/modules/http/modules/middleware.d.ts.map +1 -1
- package/dist/app/modules/http/modules/middleware.mjs +2 -15
- package/dist/app/modules/http/modules/middleware.mjs.map +1 -1
- package/dist/app/modules/identity/constants.d.ts +3 -1
- package/dist/app/modules/identity/constants.d.ts.map +1 -1
- package/dist/app/modules/identity/constants.mjs +2 -0
- package/dist/app/modules/identity/constants.mjs.map +1 -1
- package/dist/app/modules/identity/module.d.ts.map +1 -1
- package/dist/app/modules/identity/module.mjs +42 -5
- package/dist/app/modules/identity/module.mjs.map +1 -1
- package/dist/app/modules/identity/repositories/client.d.ts +2 -2
- package/dist/app/modules/identity/repositories/client.d.ts.map +1 -1
- package/dist/app/modules/identity/repositories/client.mjs.map +1 -1
- package/dist/app/modules/identity/repositories/robot.d.ts +2 -2
- package/dist/app/modules/identity/repositories/robot.d.ts.map +1 -1
- package/dist/app/modules/identity/repositories/robot.mjs.map +1 -1
- package/dist/app/modules/oauth2/module.d.ts.map +1 -1
- package/dist/app/modules/oauth2/module.mjs +5 -2
- package/dist/app/modules/oauth2/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/module.mjs +14 -9
- package/dist/app/modules/provisioning/module.mjs.map +1 -1
- package/dist/app/modules/provisioning/sources/default/module.d.ts.map +1 -1
- package/dist/app/modules/provisioning/sources/default/module.mjs +66 -10
- package/dist/app/modules/provisioning/sources/default/module.mjs.map +1 -1
- package/dist/components/database/unique-entries/module.mjs +1 -1
- package/dist/core/entities/client/service.d.ts +1 -1
- package/dist/core/entities/client/service.d.ts.map +1 -1
- package/dist/core/entities/client/service.mjs +27 -23
- package/dist/core/entities/client/service.mjs.map +1 -1
- package/dist/core/entities/client/types.d.ts +6 -2
- package/dist/core/entities/client/types.d.ts.map +1 -1
- package/dist/core/entities/client-scope/service.d.ts.map +1 -1
- package/dist/core/entities/client-scope/service.mjs +2 -0
- package/dist/core/entities/client-scope/service.mjs.map +1 -1
- package/dist/core/entities/identity-provider-role-mapping/service.d.ts.map +1 -1
- package/dist/core/entities/identity-provider-role-mapping/service.mjs +2 -0
- package/dist/core/entities/identity-provider-role-mapping/service.mjs.map +1 -1
- package/dist/core/entities/permission/service.mjs +1 -1
- package/dist/core/entities/policy/attributes-validator.mjs +1 -1
- package/dist/core/entities/policy/service.mjs +1 -1
- package/dist/core/entities/realm/service.mjs +1 -1
- package/dist/core/entities/robot/service.d.ts +1 -1
- package/dist/core/entities/robot/service.d.ts.map +1 -1
- package/dist/core/entities/robot/service.mjs +41 -26
- package/dist/core/entities/robot/service.mjs.map +1 -1
- package/dist/core/entities/robot/types.d.ts +6 -2
- package/dist/core/entities/robot/types.d.ts.map +1 -1
- package/dist/core/entities/role/service.mjs +1 -1
- package/dist/core/entities/role/types.d.ts +3 -0
- package/dist/core/entities/role/types.d.ts.map +1 -1
- package/dist/core/entities/role-attribute/service.d.ts +2 -0
- package/dist/core/entities/role-attribute/service.d.ts.map +1 -1
- package/dist/core/entities/role-attribute/service.mjs +7 -3
- package/dist/core/entities/role-attribute/service.mjs.map +1 -1
- package/dist/core/entities/scope/service.mjs +1 -1
- package/dist/core/entities/user/service.d.ts.map +1 -1
- package/dist/core/entities/user/service.mjs +20 -25
- package/dist/core/entities/user/service.mjs.map +1 -1
- package/dist/core/entities/user/types.d.ts +4 -1
- package/dist/core/entities/user/types.d.ts.map +1 -1
- package/dist/core/entities/user-attribute/service.d.ts +3 -1
- package/dist/core/entities/user-attribute/service.d.ts.map +1 -1
- package/dist/core/entities/user-attribute/service.mjs +44 -17
- package/dist/core/entities/user-attribute/service.mjs.map +1 -1
- package/dist/core/identity/index.d.ts +1 -0
- package/dist/core/identity/index.d.ts.map +1 -1
- package/dist/core/identity/index.mjs +2 -1
- package/dist/core/identity/password-recovery/service.d.ts.map +1 -1
- package/dist/core/identity/password-recovery/service.mjs +4 -4
- package/dist/core/identity/password-recovery/service.mjs.map +1 -1
- package/dist/core/identity/permission/module.d.ts +12 -6
- package/dist/core/identity/permission/module.d.ts.map +1 -1
- package/dist/core/identity/permission/module.mjs +11 -19
- package/dist/core/identity/permission/module.mjs.map +1 -1
- package/dist/core/identity/permission/types.d.ts +11 -13
- package/dist/core/identity/permission/types.d.ts.map +1 -1
- package/dist/core/identity/provider/account/module.d.ts.map +1 -1
- package/dist/core/identity/provider/account/module.mjs +3 -2
- package/dist/core/identity/provider/account/module.mjs.map +1 -1
- package/dist/core/identity/role/index.d.ts +3 -0
- package/dist/core/identity/role/index.d.ts.map +1 -0
- package/dist/core/identity/role/index.mjs +2 -0
- package/dist/core/identity/role/module.d.ts +15 -0
- package/dist/core/identity/role/module.d.ts.map +1 -0
- package/dist/core/identity/role/module.mjs +27 -0
- package/dist/core/identity/role/module.mjs.map +1 -0
- package/dist/core/identity/role/types.d.ts +14 -0
- package/dist/core/identity/role/types.d.ts.map +1 -0
- package/dist/core/identity/role/types.mjs +1 -0
- package/dist/core/index.mjs +3 -1
- package/dist/core/oauth2/authorization/code/verifier/module.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code/verifier/module.mjs +8 -4
- package/dist/core/oauth2/authorization/code/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/authorization/code/verifier/types.d.ts +2 -0
- package/dist/core/oauth2/authorization/code/verifier/types.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.d.ts.map +1 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs +7 -1
- package/dist/core/oauth2/authorization/code-request/verifier/module.mjs.map +1 -1
- package/dist/core/oauth2/client/authenticator.d.ts +17 -0
- package/dist/core/oauth2/client/authenticator.d.ts.map +1 -0
- package/dist/core/oauth2/client/authenticator.mjs +34 -0
- package/dist/core/oauth2/client/authenticator.mjs.map +1 -0
- package/dist/core/oauth2/client/index.d.ts +1 -0
- package/dist/core/oauth2/client/index.d.ts.map +1 -1
- package/dist/core/oauth2/client/index.mjs +2 -1
- package/dist/core/oauth2/grant-types/password.d.ts +7 -3
- package/dist/core/oauth2/grant-types/password.d.ts.map +1 -1
- package/dist/core/oauth2/grant-types/password.mjs +9 -7
- package/dist/core/oauth2/grant-types/password.mjs.map +1 -1
- package/dist/core/oauth2/index.mjs +3 -1
- package/dist/core/oauth2/token/issuer/access/module.d.ts +4 -1
- package/dist/core/oauth2/token/issuer/access/module.d.ts.map +1 -1
- package/dist/core/oauth2/token/issuer/access/module.mjs +24 -2
- package/dist/core/oauth2/token/issuer/access/module.mjs.map +1 -1
- package/dist/core/oauth2/token/issuer/base.d.ts.map +1 -1
- package/dist/core/oauth2/token/issuer/base.mjs +3 -2
- package/dist/core/oauth2/token/issuer/base.mjs.map +1 -1
- package/dist/core/provisioning/entities/permission/types.d.ts +8 -0
- package/dist/core/provisioning/entities/permission/types.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/permission/module.d.ts +5 -1
- package/dist/core/provisioning/synchronizer/permission/module.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/permission/module.mjs +23 -0
- package/dist/core/provisioning/synchronizer/permission/module.mjs.map +1 -1
- package/dist/core/provisioning/synchronizer/permission/types.d.ts +4 -1
- package/dist/core/provisioning/synchronizer/permission/types.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/policy/module.d.ts.map +1 -1
- package/dist/core/provisioning/synchronizer/policy/module.mjs +4 -2
- package/dist/core/provisioning/synchronizer/policy/module.mjs.map +1 -1
- package/dist/index.mjs +19 -20
- package/dist/path.d.ts +2 -1
- package/dist/path.d.ts.map +1 -1
- package/dist/path.mjs +3 -2
- package/dist/path.mjs.map +1 -1
- package/dist/swagger.json +14 -0
- package/dist/ui/client/.vite/ssr-manifest.json +2777 -0
- package/dist/ui/client/assets/fa-brands-400-BP5tdqmh.woff2 +0 -0
- package/dist/ui/client/assets/fa-regular-400-nyy7hhHF.woff2 +0 -0
- package/dist/ui/client/assets/fa-solid-900-DRAAbZTg.woff2 +0 -0
- package/dist/ui/client/assets/index-BVfayRKv.css +1 -0
- package/dist/ui/client/assets/index-Noe7uiOY.js +41 -0
- package/dist/ui/client/index.html +22 -0
- package/dist/ui/server/assets/multipart-parser-pHQi-kA6.js +166 -0
- package/dist/ui/server/server.js +79116 -0
- package/package.json +30 -13
- package/dist/adapters/database/domains/client/repository.d.ts +0 -13
- package/dist/adapters/database/domains/client/repository.d.ts.map +0 -1
- package/dist/adapters/database/domains/client/repository.mjs +0 -75
- package/dist/adapters/database/domains/client/repository.mjs.map +0 -1
- package/dist/adapters/database/domains/robot/repository.d.ts +0 -13
- package/dist/adapters/database/domains/robot/repository.d.ts.map +0 -1
- package/dist/adapters/database/domains/robot/repository.mjs +0 -75
- package/dist/adapters/database/domains/robot/repository.mjs.map +0 -1
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.d.ts +0 -4
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.d.ts.map +0 -1
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.mjs +0 -35
- package/dist/adapters/http/controllers/entities/user-attribute/utils/authorization.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.mjs","names":["BadRequestError","NotFoundError","createValidationChain","createValidator","randomBytes","Container","UserCredentialsService","PasswordRecoveryService","options","repository","realmRepository","mailClient","ctx","forgotPassword","data","passwordRecoveryEnabled","emailVerificationEnabled","validated","runForgotPasswordValidator","realm","resolve","realm_id","where","name","email","id","entity","findOneByWithEmail","merged","merge","reset_expires","Date","now","toISOString","reset_hash","toString","save","send","to","subject","html","resetPassword","runResetPasswordValidator","validateJoinColumns","token","findOneBy","credentialsService","hashedPassword","protect","password","reset_at","validator","oneOfContainer","oneOf","mount","chain","exists","notEmpty","isEmail","isString","optional","isUUID","values","run","isLength","min","max"],"sources":["../../../../src/core/identity/password-recovery/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\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 { BadRequestError, NotFoundError } from '@ebec/http';\nimport { createValidationChain, createValidator } from '@validup/adapter-validator';\nimport { randomBytes } from 'node:crypto';\nimport { Container } from 'validup';\nimport { UserCredentialsService } from '../../authentication/credential/entities/user/module.ts';\nimport type {\n IPasswordRecoveryService,\n PasswordForgotResult,\n PasswordRecoveryServiceContext,\n PasswordRecoveryServiceOptions,\n PasswordResetResult,\n} from './types.ts';\nimport type { IMailClient } from '../../mail/types.ts';\nimport type { IRealmRepository, IUserRepository } from '../../entities/index.ts';\n\nexport class PasswordRecoveryService implements IPasswordRecoveryService {\n protected options: PasswordRecoveryServiceOptions;\n\n protected repository: IUserRepository;\n\n protected realmRepository: IRealmRepository;\n\n protected mailClient: IMailClient;\n\n constructor(ctx: PasswordRecoveryServiceContext) {\n this.options = ctx.options;\n this.repository = ctx.repository;\n this.realmRepository = ctx.realmRepository;\n this.mailClient = ctx.mailClient;\n }\n\n async forgotPassword(data: Record<string, any>): Promise<PasswordForgotResult> {\n if (!this.options.passwordRecoveryEnabled) {\n throw new BadRequestError('Password recovery is not enabled.');\n }\n\n if (!this.options.emailVerificationEnabled) {\n throw new BadRequestError('Email verification is not enabled, but required to reset a password.');\n }\n\n const validated = await this.runForgotPasswordValidator(data);\n\n const realm = await this.realmRepository.resolve(validated.realm_id, true);\n\n const where: Record<string, any> = {\n ...(validated.name ? { name: validated.name } : {}),\n ...(validated.email ? { email: validated.email } : {}),\n realm_id: realm.id,\n };\n\n const entity = await this.repository.findOneByWithEmail(where);\n\n if (!entity) {\n throw new NotFoundError();\n }\n\n const merged = this.repository.merge(entity, {\n reset_expires: new Date(Date.now() + (1000 * 60 * 30)).toISOString(),\n reset_hash: randomBytes(32).toString('hex'),\n });\n\n await this.repository.save(merged);\n\n try {\n await this.mailClient.send({\n to: entity.email,\n subject: 'Forgot Password - Reset code',\n html: `\n <p>Please use the code below to reset your account password.</p>\n <p>${merged.reset_hash}</p>\n `,\n });\n } catch {\n this.repository.merge(merged, {\n reset_hash: null,\n reset_expires: null,\n });\n await this.repository.save(merged);\n\n throw new BadRequestError('Password recovery failed. Could not send reset email.');\n }\n\n return { reset_expires: merged.reset_expires! };\n }\n\n async resetPassword(data: Record<string, any>): Promise<PasswordResetResult> {\n if (!this.options.passwordRecoveryEnabled) {\n throw new BadRequestError('Password recovery is not enabled.');\n }\n\n const validated = await this.runResetPasswordValidator(data);\n\n await this.repository.validateJoinColumns(validated);\n\n const realm = await this.realmRepository.resolve(validated.realm_id, true);\n\n const where: Record<string, any> = {\n ...(validated.name ? { name: validated.name } : {}),\n ...(validated.email ? { email: validated.email } : {}),\n reset_hash: validated.token,\n realm_id: realm.id,\n };\n\n const entity = await this.repository.findOneBy(where);\n if (!entity) {\n throw new NotFoundError();\n }\n\n if (!entity.reset_expires || new Date(entity.reset_expires) < new Date()) {\n throw new BadRequestError('Reset token has expired.');\n }\n\n const credentialsService = new UserCredentialsService();\n const hashedPassword = await credentialsService.protect(validated.password);\n\n const merged = this.repository.merge(entity, {\n reset_at: new Date().toISOString(),\n reset_hash: null,\n reset_expires: null,\n password: hashedPassword,\n });\n\n await this.repository.save(merged);\n\n return { reset_at: merged.reset_at! };\n }\n\n private async runForgotPasswordValidator(data: Record<string, any>) {\n const validator = new Container<any>({});\n\n const oneOfContainer = new Container({ oneOf: true });\n\n oneOfContainer.mount('email', createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isEmail();\n }));\n\n oneOfContainer.mount(\n 'name',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isString();\n }),\n );\n\n validator.mount(oneOfContainer);\n\n validator.mount(\n 'realm_id',\n { optional: true },\n createValidator(() => {\n const chain = createValidationChain();\n return chain.exists()\n .isUUID()\n .optional({ values: 'null' });\n }),\n );\n\n return validator.run(data);\n }\n\n private async runResetPasswordValidator(data: Record<string, any>) {\n const validator = new Container<any>({});\n\n const oneOfContainer = new Container({ oneOf: true });\n oneOfContainer.mount(\n 'email',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isEmail();\n }),\n );\n oneOfContainer.mount(\n 'name',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isString();\n }),\n );\n\n validator.mount(oneOfContainer);\n\n validator.mount(\n 'realm_id',\n { optional: true },\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .isUUID()\n .optional({ values: 'null' });\n }),\n );\n\n validator.mount(\n 'token',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isLength({\n min: 3,\n max: 256, \n });\n }),\n );\n\n validator.mount(\n 'password',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isLength({\n min: 5,\n max: 512, \n });\n }),\n );\n\n return validator.run(data);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service.mjs","names":["BadRequestError","NotFoundError","createValidationChain","createValidator","randomBytes","Container","UserCredentialsService","PasswordRecoveryService","options","repository","realmRepository","mailClient","ctx","forgotPassword","data","passwordRecoveryEnabled","emailVerificationEnabled","validated","runForgotPasswordValidator","realm","resolve","realm_id","where","name","email","id","entity","findOneByWithEmail","merged","merge","reset_expires","Date","now","toISOString","reset_hash","toString","save","send","to","subject","html","resetPassword","runResetPasswordValidator","validateJoinColumns","token","findOneBy","credentialsService","hashedPassword","protect","password","reset_at","validator","oneOfContainer","oneOf","mount","chain","exists","notEmpty","trim","toLowerCase","isEmail","matches","withMessage","isString","optional","isUUID","values","run","isLength","min","max"],"sources":["../../../../src/core/identity/password-recovery/service.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\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 { BadRequestError, NotFoundError } from '@ebec/http';\nimport { createValidationChain, createValidator } from '@validup/adapter-validator';\nimport { randomBytes } from 'node:crypto';\nimport { Container } from 'validup';\nimport { UserCredentialsService } from '../../authentication/credential/entities/user/module.ts';\nimport type {\n IPasswordRecoveryService,\n PasswordForgotResult,\n PasswordRecoveryServiceContext,\n PasswordRecoveryServiceOptions,\n PasswordResetResult,\n} from './types.ts';\nimport type { IMailClient } from '../../mail/types.ts';\nimport type { IRealmRepository, IUserRepository } from '../../entities/index.ts';\n\nexport class PasswordRecoveryService implements IPasswordRecoveryService {\n protected options: PasswordRecoveryServiceOptions;\n\n protected repository: IUserRepository;\n\n protected realmRepository: IRealmRepository;\n\n protected mailClient: IMailClient;\n\n constructor(ctx: PasswordRecoveryServiceContext) {\n this.options = ctx.options;\n this.repository = ctx.repository;\n this.realmRepository = ctx.realmRepository;\n this.mailClient = ctx.mailClient;\n }\n\n async forgotPassword(data: Record<string, any>): Promise<PasswordForgotResult> {\n if (!this.options.passwordRecoveryEnabled) {\n throw new BadRequestError('Password recovery is not enabled.');\n }\n\n if (!this.options.emailVerificationEnabled) {\n throw new BadRequestError('Email verification is not enabled, but required to reset a password.');\n }\n\n const validated = await this.runForgotPasswordValidator(data);\n\n const realm = await this.realmRepository.resolve(validated.realm_id, true);\n\n const where: Record<string, any> = {\n ...(validated.name ? { name: validated.name } : {}),\n ...(validated.email ? { email: validated.email } : {}),\n realm_id: realm.id,\n };\n\n const entity = await this.repository.findOneByWithEmail(where);\n\n if (!entity) {\n throw new NotFoundError();\n }\n\n const merged = this.repository.merge(entity, {\n reset_expires: new Date(Date.now() + (1000 * 60 * 30)).toISOString(),\n reset_hash: randomBytes(32).toString('hex'),\n });\n\n await this.repository.save(merged);\n\n try {\n await this.mailClient.send({\n to: entity.email,\n subject: 'Forgot Password - Reset code',\n html: `\n <p>Please use the code below to reset your account password.</p>\n <p>${merged.reset_hash}</p>\n `,\n });\n } catch {\n this.repository.merge(merged, {\n reset_hash: null,\n reset_expires: null,\n });\n await this.repository.save(merged);\n\n throw new BadRequestError('Password recovery failed. Could not send reset email.');\n }\n\n return { reset_expires: merged.reset_expires! };\n }\n\n async resetPassword(data: Record<string, any>): Promise<PasswordResetResult> {\n if (!this.options.passwordRecoveryEnabled) {\n throw new BadRequestError('Password recovery is not enabled.');\n }\n\n const validated = await this.runResetPasswordValidator(data);\n\n await this.repository.validateJoinColumns(validated);\n\n const realm = await this.realmRepository.resolve(validated.realm_id, true);\n\n const where: Record<string, any> = {\n ...(validated.name ? { name: validated.name } : {}),\n ...(validated.email ? { email: validated.email } : {}),\n reset_hash: validated.token,\n realm_id: realm.id,\n };\n\n const entity = await this.repository.findOneBy(where);\n if (!entity) {\n throw new NotFoundError();\n }\n\n if (!entity.reset_expires || new Date(entity.reset_expires) < new Date()) {\n throw new BadRequestError('Reset token has expired.');\n }\n\n const credentialsService = new UserCredentialsService();\n const hashedPassword = await credentialsService.protect(validated.password);\n\n const merged = this.repository.merge(entity, {\n reset_at: new Date().toISOString(),\n reset_hash: null,\n reset_expires: null,\n password: hashedPassword,\n });\n\n await this.repository.save(merged);\n\n return { reset_at: merged.reset_at! };\n }\n\n private async runForgotPasswordValidator(data: Record<string, any>) {\n const validator = new Container<any>({});\n\n const oneOfContainer = new Container({ oneOf: true });\n\n oneOfContainer.mount('email', createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .trim()\n .toLowerCase()\n .isEmail()\n .matches(/^[^A-Z]+$/)\n .withMessage('Email must be lowercase.');\n }));\n\n oneOfContainer.mount(\n 'name',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isString()\n .trim()\n .toLowerCase();\n }),\n );\n\n validator.mount(oneOfContainer);\n\n validator.mount(\n 'realm_id',\n { optional: true },\n createValidator(() => {\n const chain = createValidationChain();\n return chain.exists()\n .isUUID()\n .optional({ values: 'null' });\n }),\n );\n\n return validator.run(data);\n }\n\n private async runResetPasswordValidator(data: Record<string, any>) {\n const validator = new Container<any>({});\n\n const oneOfContainer = new Container({ oneOf: true });\n oneOfContainer.mount(\n 'email',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .trim()\n .toLowerCase()\n .isEmail()\n .matches(/^[^A-Z]+$/)\n .withMessage('Email must be lowercase.');\n }),\n );\n oneOfContainer.mount(\n 'name',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isString()\n .trim()\n .toLowerCase();\n }),\n );\n\n validator.mount(oneOfContainer);\n\n validator.mount(\n 'realm_id',\n { optional: true },\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .isUUID()\n .optional({ values: 'null' });\n }),\n );\n\n validator.mount(\n 'token',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isLength({\n min: 3,\n max: 256, \n });\n }),\n );\n\n validator.mount(\n 'password',\n createValidator(() => {\n const chain = createValidationChain();\n return chain\n .exists()\n .notEmpty()\n .isLength({\n min: 5,\n max: 512, \n });\n }),\n );\n\n return validator.run(data);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import type { IdentityPolicyData, PermissionPolicyBinding } from '@authup/access';
|
|
2
2
|
import type { Policy } from '@authup/core-kit';
|
|
3
|
-
import type {
|
|
3
|
+
import type { IClientRepository } from '../../entities/client/types.ts';
|
|
4
|
+
import type { IRobotRepository } from '../../entities/robot/types.ts';
|
|
5
|
+
import type { IRoleRepository } from '../../entities/role/types.ts';
|
|
6
|
+
import type { IUserRepository } from '../../entities/user/types.ts';
|
|
7
|
+
import type { IIdentityRoleProvider } from '../role/types.ts';
|
|
8
|
+
import type { IIdentityPermissionProvider, IdentityPermissionProviderContext, ResolveJunctionPolicyOptions } from './types.ts';
|
|
4
9
|
export declare class IdentityPermissionProvider implements IIdentityPermissionProvider {
|
|
5
|
-
protected clientRepository:
|
|
6
|
-
protected userRepository:
|
|
7
|
-
protected roleRepository:
|
|
8
|
-
protected robotRepository:
|
|
10
|
+
protected clientRepository: IClientRepository;
|
|
11
|
+
protected userRepository: IUserRepository;
|
|
12
|
+
protected roleRepository: IRoleRepository;
|
|
13
|
+
protected robotRepository: IRobotRepository;
|
|
14
|
+
protected roleProvider: IIdentityRoleProvider;
|
|
9
15
|
constructor(ctx: IdentityPermissionProviderContext);
|
|
10
16
|
isSuperset(parent: IdentityPolicyData, child: IdentityPolicyData): Promise<boolean>;
|
|
11
17
|
resolveJunctionPolicy(identity: IdentityPolicyData, options: ResolveJunctionPolicyOptions): Promise<Policy | undefined>;
|
|
@@ -14,7 +20,7 @@ export declare class IdentityPermissionProvider implements IIdentityPermissionPr
|
|
|
14
20
|
getForUser(identity: IdentityPolicyData): Promise<PermissionPolicyBinding[]>;
|
|
15
21
|
getForRobot(identity: IdentityPolicyData): Promise<PermissionPolicyBinding[]>;
|
|
16
22
|
getForRole(identity: IdentityPolicyData): Promise<PermissionPolicyBinding[]>;
|
|
23
|
+
private combineWithRoleBindings;
|
|
17
24
|
private reduceBindingsByIdentityClient;
|
|
18
|
-
private reduceEntitiesByIdentityClient;
|
|
19
25
|
}
|
|
20
26
|
//# sourceMappingURL=module.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/permission/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACR,kBAAkB,EAClB,uBAAuB,EAC1B,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/permission/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACR,kBAAkB,EAClB,uBAAuB,EAC1B,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,KAAK,EACR,2BAA2B,EAC3B,iCAAiC,EACjC,4BAA4B,EAC/B,MAAM,YAAY,CAAC;AAEpB,qBAAa,0BAA2B,YAAW,2BAA2B;IAC1E,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAE9C,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC;IAE1C,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC;IAE1C,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;IAE5C,SAAS,CAAC,YAAY,EAAE,qBAAqB,CAAC;gBAElC,GAAG,EAAE,iCAAiC;IAQ5C,UAAU,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,GAAI,OAAO,CAAC,OAAO,CAAC;IA2BpF,qBAAqB,CACvB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,4BAA4B,GACtC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAsCxB,MAAM,CAAC,QAAQ,EAAE,kBAAkB,GAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAmBzE,YAAY,CAAC,QAAQ,EAAE,kBAAkB,GAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAO/E,UAAU,CAAC,QAAQ,EAAE,kBAAkB,GAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAQ7E,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAQ9E,UAAU,CAAC,QAAQ,EAAE,kBAAkB,GAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;YAKrE,uBAAuB;IAmBrC,OAAO,CAAC,8BAA8B;CAUzC"}
|
|
@@ -6,11 +6,13 @@ var IdentityPermissionProvider = class {
|
|
|
6
6
|
userRepository;
|
|
7
7
|
roleRepository;
|
|
8
8
|
robotRepository;
|
|
9
|
+
roleProvider;
|
|
9
10
|
constructor(ctx) {
|
|
10
11
|
this.clientRepository = ctx.clientRepository;
|
|
11
12
|
this.userRepository = ctx.userRepository;
|
|
12
13
|
this.roleRepository = ctx.roleRepository;
|
|
13
14
|
this.robotRepository = ctx.robotRepository;
|
|
15
|
+
this.roleProvider = ctx.roleProvider;
|
|
14
16
|
}
|
|
15
17
|
async isSuperset(parent, child) {
|
|
16
18
|
const parentBindings = await this.getFor(parent);
|
|
@@ -52,37 +54,27 @@ var IdentityPermissionProvider = class {
|
|
|
52
54
|
return [];
|
|
53
55
|
}
|
|
54
56
|
async getForClient(identity) {
|
|
55
|
-
|
|
56
|
-
const roles = await this.clientRepository.getBoundRoles(identity.id);
|
|
57
|
-
const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);
|
|
58
|
-
if (roleBindings.length === 0) return bindings;
|
|
59
|
-
return [...bindings, ...roleBindings];
|
|
57
|
+
return this.combineWithRoleBindings(this.clientRepository.getBoundPermissions(identity.id), identity);
|
|
60
58
|
}
|
|
61
59
|
async getForUser(identity) {
|
|
62
|
-
|
|
63
|
-
const roles = await this.userRepository.getBoundRoles(identity.id).then((data) => this.reduceEntitiesByIdentityClient(data, identity));
|
|
64
|
-
const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);
|
|
65
|
-
if (roleBindings.length === 0) return bindings;
|
|
66
|
-
return [...bindings, ...roleBindings];
|
|
60
|
+
return this.combineWithRoleBindings(this.userRepository.getBoundPermissions(identity.id).then((data) => this.reduceBindingsByIdentityClient(data, identity)), identity);
|
|
67
61
|
}
|
|
68
62
|
async getForRobot(identity) {
|
|
69
|
-
|
|
70
|
-
const roles = await this.robotRepository.getBoundRoles(identity.id).then((data) => this.reduceEntitiesByIdentityClient(data, identity));
|
|
71
|
-
const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);
|
|
72
|
-
if (roleBindings.length === 0) return bindings;
|
|
73
|
-
return [...bindings, ...roleBindings];
|
|
63
|
+
return this.combineWithRoleBindings(this.robotRepository.getBoundPermissions(identity.id).then((data) => this.reduceBindingsByIdentityClient(data, identity)), identity);
|
|
74
64
|
}
|
|
75
65
|
async getForRole(identity) {
|
|
76
66
|
return this.roleRepository.getBoundPermissions(identity.id).then((data) => this.reduceBindingsByIdentityClient(data, identity));
|
|
77
67
|
}
|
|
68
|
+
async combineWithRoleBindings(bindingsPromise, identity) {
|
|
69
|
+
const [bindings, roles] = await Promise.all([bindingsPromise, this.roleProvider.getRolesFor(identity)]);
|
|
70
|
+
const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);
|
|
71
|
+
if (roleBindings.length === 0) return bindings;
|
|
72
|
+
return [...bindings, ...roleBindings];
|
|
73
|
+
}
|
|
78
74
|
reduceBindingsByIdentityClient(bindings, identity) {
|
|
79
75
|
if (!identity.clientId) return bindings;
|
|
80
76
|
return bindings.filter((binding) => binding.permission.client_id === identity.clientId);
|
|
81
77
|
}
|
|
82
|
-
reduceEntitiesByIdentityClient(entities, identity) {
|
|
83
|
-
if (!identity.clientId) return entities;
|
|
84
|
-
return entities.filter((entity) => entity.client_id === identity.clientId);
|
|
85
|
-
}
|
|
86
78
|
};
|
|
87
79
|
//#endregion
|
|
88
80
|
export { IdentityPermissionProvider };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.mjs","names":["isPermissionPolicyBindingEqual","mergePermissionPolicyBindings","isPolicy","IdentityPermissionProvider","clientRepository","userRepository","roleRepository","robotRepository","ctx","isSuperset","parent","child","parentBindings","getFor","childBindings","parentMerged","childMerged","childItem","parentItem","find","p","policies","length","resolveJunctionPolicy","identity","options","bindings","matching","filter","b","permission","name","realmId","realm_id","clientId","client_id","undefined","merged","policy","type","getForClient","getForUser","getForRobot","getForRole","getBoundPermissions","id","roles","getBoundRoles","roleBindings","getBoundPermissionsForMany","then","data","reduceBindingsByIdentityClient","reduceEntitiesByIdentityClient","binding","entities","entity"],"sources":["../../../../src/core/identity/permission/module.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 {\n IdentityPolicyData,\n PermissionPolicyBinding,\n} from '@authup/access';\nimport { isPermissionPolicyBindingEqual, mergePermissionPolicyBindings } from '@authup/access';\nimport type { Policy } from '@authup/core-kit';\nimport { isPolicy } from '@authup/core-kit';\nimport type {\n IIdentityBindingRepository,\n IIdentityPermissionProvider,\n IRoleBindingRepository,\n IdentityPermissionProviderContext,\n ResolveJunctionPolicyOptions,\n} from './types.ts';\n\nexport class IdentityPermissionProvider implements IIdentityPermissionProvider {\n protected clientRepository: IIdentityBindingRepository;\n\n protected userRepository: IIdentityBindingRepository;\n\n protected roleRepository: IRoleBindingRepository;\n\n protected robotRepository: IIdentityBindingRepository;\n\n constructor(ctx: IdentityPermissionProviderContext) {\n this.clientRepository = ctx.clientRepository;\n this.userRepository = ctx.userRepository;\n this.roleRepository = ctx.roleRepository;\n this.robotRepository = ctx.robotRepository;\n }\n\n async isSuperset(parent: IdentityPolicyData, child: IdentityPolicyData) : Promise<boolean> {\n const parentBindings = await this.getFor(parent);\n const childBindings = await this.getFor(child);\n\n const parentMerged = mergePermissionPolicyBindings(parentBindings);\n const childMerged = mergePermissionPolicyBindings(childBindings);\n\n for (const childItem of childMerged) {\n const parentItem = parentMerged.find(\n (p) => isPermissionPolicyBindingEqual(p, childItem),\n );\n\n if (!parentItem) {\n return false;\n }\n\n if (\n parentItem.policies && parentItem.policies.length > 0 &&\n (!childItem.policies || childItem.policies.length === 0)\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n async resolveJunctionPolicy(\n identity: IdentityPolicyData,\n options: ResolveJunctionPolicyOptions,\n ): Promise<Policy | undefined> {\n const bindings = await this.getFor(identity);\n const matching = bindings.filter((b) => {\n if (b.permission.name !== options.name) {\n return false;\n }\n\n if (typeof options.realmId !== 'undefined') {\n if ((b.permission.realm_id ?? null) !== (options.realmId ?? null)) {\n return false;\n }\n }\n\n if (typeof options.clientId !== 'undefined') {\n if ((b.permission.client_id ?? null) !== (options.clientId ?? null)) {\n return false;\n }\n }\n\n return true;\n });\n\n if (matching.length === 0) {\n return undefined;\n }\n\n const merged = mergePermissionPolicyBindings(matching);\n\n if (merged.length > 0 && merged[0].policies && merged[0].policies.length > 0) {\n const policy = merged[0].policies[0];\n if (isPolicy(policy)) {\n return policy;\n }\n }\n\n return undefined;\n }\n\n async getFor(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n switch (identity.type) {\n case 'client': {\n return this.getForClient(identity);\n }\n case 'user': {\n return this.getForUser(identity);\n }\n case 'robot': {\n return this.getForRobot(identity);\n }\n case 'role': {\n return this.getForRole(identity);\n }\n }\n\n return [];\n }\n\n async getForClient(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n const bindings = await this.clientRepository.getBoundPermissions(identity.id);\n const roles = await this.clientRepository.getBoundRoles(identity.id);\n const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);\n if (roleBindings.length === 0) {\n return bindings;\n }\n\n return [\n ...bindings,\n ...roleBindings,\n ];\n }\n\n async getForUser(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n const bindings = await this.userRepository.getBoundPermissions(identity.id)\n .then((data) => this.reduceBindingsByIdentityClient(data, identity));\n\n const roles = await this.userRepository.getBoundRoles(identity.id)\n .then((data) => this.reduceEntitiesByIdentityClient(data, identity));\n\n const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);\n if (roleBindings.length === 0) {\n return bindings;\n }\n\n return [\n ...bindings,\n ...roleBindings,\n ];\n }\n\n async getForRobot(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n const bindings = await this.robotRepository.getBoundPermissions(identity.id)\n .then((data) => this.reduceBindingsByIdentityClient(data, identity));\n\n const roles = await this.robotRepository.getBoundRoles(identity.id)\n .then((data) => this.reduceEntitiesByIdentityClient(data, identity));\n\n const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);\n if (roleBindings.length === 0) {\n return bindings;\n }\n\n return [\n ...bindings,\n ...roleBindings,\n ];\n }\n\n async getForRole(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n return this.roleRepository.getBoundPermissions(identity.id)\n .then((data) => this.reduceBindingsByIdentityClient(data, identity));\n }\n\n private reduceBindingsByIdentityClient(\n bindings: PermissionPolicyBinding[],\n identity: IdentityPolicyData,\n ): PermissionPolicyBinding[] {\n if (!identity.clientId) {\n return bindings;\n }\n\n return bindings.filter((binding) => binding.permission.client_id === identity.clientId);\n }\n\n private reduceEntitiesByIdentityClient<T extends { client_id?: string | null }>(\n entities: T[],\n identity: IdentityPolicyData,\n ): T[] {\n if (!identity.clientId) {\n return entities;\n }\n\n return entities.filter((entity) => entity.client_id === identity.clientId);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"module.mjs","names":["isPermissionPolicyBindingEqual","mergePermissionPolicyBindings","isPolicy","IdentityPermissionProvider","clientRepository","userRepository","roleRepository","robotRepository","roleProvider","ctx","isSuperset","parent","child","parentBindings","getFor","childBindings","parentMerged","childMerged","childItem","parentItem","find","p","policies","length","resolveJunctionPolicy","identity","options","bindings","matching","filter","b","permission","name","realmId","realm_id","clientId","client_id","undefined","merged","policy","type","getForClient","getForUser","getForRobot","getForRole","combineWithRoleBindings","getBoundPermissions","id","then","data","reduceBindingsByIdentityClient","bindingsPromise","roles","Promise","all","getRolesFor","roleBindings","getBoundPermissionsForMany","binding"],"sources":["../../../../src/core/identity/permission/module.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 {\n IdentityPolicyData,\n PermissionPolicyBinding,\n} from '@authup/access';\nimport { isPermissionPolicyBindingEqual, mergePermissionPolicyBindings } from '@authup/access';\nimport type { Policy } from '@authup/core-kit';\nimport { isPolicy } from '@authup/core-kit';\nimport type { IClientRepository } from '../../entities/client/types.ts';\nimport type { IRobotRepository } from '../../entities/robot/types.ts';\nimport type { IRoleRepository } from '../../entities/role/types.ts';\nimport type { IUserRepository } from '../../entities/user/types.ts';\nimport type { IIdentityRoleProvider } from '../role/types.ts';\nimport type {\n IIdentityPermissionProvider,\n IdentityPermissionProviderContext,\n ResolveJunctionPolicyOptions,\n} from './types.ts';\n\nexport class IdentityPermissionProvider implements IIdentityPermissionProvider {\n protected clientRepository: IClientRepository;\n\n protected userRepository: IUserRepository;\n\n protected roleRepository: IRoleRepository;\n\n protected robotRepository: IRobotRepository;\n\n protected roleProvider: IIdentityRoleProvider;\n\n constructor(ctx: IdentityPermissionProviderContext) {\n this.clientRepository = ctx.clientRepository;\n this.userRepository = ctx.userRepository;\n this.roleRepository = ctx.roleRepository;\n this.robotRepository = ctx.robotRepository;\n this.roleProvider = ctx.roleProvider;\n }\n\n async isSuperset(parent: IdentityPolicyData, child: IdentityPolicyData) : Promise<boolean> {\n const parentBindings = await this.getFor(parent);\n const childBindings = await this.getFor(child);\n\n const parentMerged = mergePermissionPolicyBindings(parentBindings);\n const childMerged = mergePermissionPolicyBindings(childBindings);\n\n for (const childItem of childMerged) {\n const parentItem = parentMerged.find(\n (p) => isPermissionPolicyBindingEqual(p, childItem),\n );\n\n if (!parentItem) {\n return false;\n }\n\n if (\n parentItem.policies && parentItem.policies.length > 0 &&\n (!childItem.policies || childItem.policies.length === 0)\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n async resolveJunctionPolicy(\n identity: IdentityPolicyData,\n options: ResolveJunctionPolicyOptions,\n ): Promise<Policy | undefined> {\n const bindings = await this.getFor(identity);\n const matching = bindings.filter((b) => {\n if (b.permission.name !== options.name) {\n return false;\n }\n\n if (typeof options.realmId !== 'undefined') {\n if ((b.permission.realm_id ?? null) !== (options.realmId ?? null)) {\n return false;\n }\n }\n\n if (typeof options.clientId !== 'undefined') {\n if ((b.permission.client_id ?? null) !== (options.clientId ?? null)) {\n return false;\n }\n }\n\n return true;\n });\n\n if (matching.length === 0) {\n return undefined;\n }\n\n const merged = mergePermissionPolicyBindings(matching);\n\n if (merged.length > 0 && merged[0].policies && merged[0].policies.length > 0) {\n const policy = merged[0].policies[0];\n if (isPolicy(policy)) {\n return policy;\n }\n }\n\n return undefined;\n }\n\n async getFor(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n switch (identity.type) {\n case 'client': {\n return this.getForClient(identity);\n }\n case 'user': {\n return this.getForUser(identity);\n }\n case 'robot': {\n return this.getForRobot(identity);\n }\n case 'role': {\n return this.getForRole(identity);\n }\n }\n\n return [];\n }\n\n async getForClient(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n return this.combineWithRoleBindings(\n this.clientRepository.getBoundPermissions(identity.id),\n identity,\n );\n }\n\n async getForUser(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n return this.combineWithRoleBindings(\n this.userRepository.getBoundPermissions(identity.id)\n .then((data) => this.reduceBindingsByIdentityClient(data, identity)),\n identity,\n );\n }\n\n async getForRobot(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n return this.combineWithRoleBindings(\n this.robotRepository.getBoundPermissions(identity.id)\n .then((data) => this.reduceBindingsByIdentityClient(data, identity)),\n identity,\n );\n }\n\n async getForRole(identity: IdentityPolicyData) : Promise<PermissionPolicyBinding[]> {\n return this.roleRepository.getBoundPermissions(identity.id)\n .then((data) => this.reduceBindingsByIdentityClient(data, identity));\n }\n\n private async combineWithRoleBindings(\n bindingsPromise: Promise<PermissionPolicyBinding[]>,\n identity: IdentityPolicyData,\n ): Promise<PermissionPolicyBinding[]> {\n const [bindings, roles] = await Promise.all([\n bindingsPromise,\n this.roleProvider.getRolesFor(identity),\n ]);\n const roleBindings = await this.roleRepository.getBoundPermissionsForMany(roles);\n if (roleBindings.length === 0) {\n return bindings;\n }\n\n return [\n ...bindings,\n ...roleBindings,\n ];\n }\n\n private reduceBindingsByIdentityClient(\n bindings: PermissionPolicyBinding[],\n identity: IdentityPolicyData,\n ): PermissionPolicyBinding[] {\n if (!identity.clientId) {\n return bindings;\n }\n\n return bindings.filter((binding) => binding.permission.client_id === identity.clientId);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import type { Policy
|
|
1
|
+
import type { Policy } from '@authup/core-kit';
|
|
2
2
|
import type { IdentityPolicyData, PermissionPolicyBinding } from '@authup/access';
|
|
3
|
+
import type { IClientRepository } from '../../entities/client/types.ts';
|
|
4
|
+
import type { IRobotRepository } from '../../entities/robot/types.ts';
|
|
5
|
+
import type { IRoleRepository } from '../../entities/role/types.ts';
|
|
6
|
+
import type { IUserRepository } from '../../entities/user/types.ts';
|
|
7
|
+
import type { IIdentityRoleProvider } from '../role/types.ts';
|
|
3
8
|
export type ResolveJunctionPolicyOptions = {
|
|
4
9
|
name: string;
|
|
5
10
|
realmId?: string | null;
|
|
@@ -10,18 +15,11 @@ export interface IIdentityPermissionProvider {
|
|
|
10
15
|
isSuperset(parent: IdentityPolicyData, child: IdentityPolicyData): Promise<boolean>;
|
|
11
16
|
resolveJunctionPolicy(identity: IdentityPolicyData, options: ResolveJunctionPolicyOptions): Promise<Policy | undefined>;
|
|
12
17
|
}
|
|
13
|
-
export interface IIdentityBindingRepository {
|
|
14
|
-
getBoundPermissions(entity: string): Promise<PermissionPolicyBinding[]>;
|
|
15
|
-
getBoundRoles(entity: string): Promise<Role[]>;
|
|
16
|
-
}
|
|
17
|
-
export interface IRoleBindingRepository {
|
|
18
|
-
getBoundPermissions(entity: string | Role): Promise<PermissionPolicyBinding[]>;
|
|
19
|
-
getBoundPermissionsForMany(entities: (string | Role)[]): Promise<PermissionPolicyBinding[]>;
|
|
20
|
-
}
|
|
21
18
|
export type IdentityPermissionProviderContext = {
|
|
22
|
-
clientRepository:
|
|
23
|
-
userRepository:
|
|
24
|
-
robotRepository:
|
|
25
|
-
roleRepository:
|
|
19
|
+
clientRepository: IClientRepository;
|
|
20
|
+
userRepository: IUserRepository;
|
|
21
|
+
robotRepository: IRobotRepository;
|
|
22
|
+
roleRepository: IRoleRepository;
|
|
23
|
+
roleProvider: IIdentityRoleProvider;
|
|
26
24
|
};
|
|
27
25
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/permission/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/permission/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EACR,kBAAkB,EAClB,uBAAuB,EAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE9D,MAAM,MAAM,4BAA4B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,2BAA2B;IACxC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAC;IACzE,UAAU,CAAC,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,qBAAqB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,OAAO,EAAE,4BAA4B,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAC3H;AAED,MAAM,MAAM,iCAAiC,GAAG;IAC5C,gBAAgB,EAAE,iBAAiB,CAAC;IACpC,cAAc,EAAE,eAAe,CAAC;IAChC,eAAe,EAAE,gBAAgB,CAAC;IAClC,cAAc,EAAE,eAAe,CAAC;IAChC,YAAY,EAAE,qBAAqB,CAAC;CACvC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../../src/core/identity/provider/account/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACH,aAAa,EAIhB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEvE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,+BAA+B,EAAE,kCAAkC,EAAE,qCAAqC,EAAE,MAAM,YAAY,CAAC;AAE7I,qBAAa,8BAA+B,YAAW,+BAA+B;IAClF,SAAS,CAAC,gBAAgB,EAAG,uBAAuB,CAAC;IAErD,SAAS,CAAC,gBAAgB,EAAG,uBAAuB,CAAC;IAErD,SAAS,CAAC,UAAU,EAAG,uBAAuB,CAAC;IAE/C,SAAS,CAAC,UAAU,EAAG,kCAAkC,CAAC;IAE1D,SAAS,CAAC,cAAc,EAAE,uBAAuB,CAAC;IAElD,SAAS,CAAC,aAAa,EAAG,aAAa,CAAC;gBAE5B,GAAG,EAAE,qCAAqC;IAUhD,IAAI,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAmC1E,QAAQ,CACV,QAAQ,EAAE,wBAAwB,EAClC,IAAI,CAAC,EAAE,IAAI,GACZ,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../../src/core/identity/provider/account/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACH,aAAa,EAIhB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEvE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,+BAA+B,EAAE,kCAAkC,EAAE,qCAAqC,EAAE,MAAM,YAAY,CAAC;AAE7I,qBAAa,8BAA+B,YAAW,+BAA+B;IAClF,SAAS,CAAC,gBAAgB,EAAG,uBAAuB,CAAC;IAErD,SAAS,CAAC,gBAAgB,EAAG,uBAAuB,CAAC;IAErD,SAAS,CAAC,UAAU,EAAG,uBAAuB,CAAC;IAE/C,SAAS,CAAC,UAAU,EAAG,kCAAkC,CAAC;IAE1D,SAAS,CAAC,cAAc,EAAE,uBAAuB,CAAC;IAElD,SAAS,CAAC,aAAa,EAAG,aAAa,CAAC;gBAE5B,GAAG,EAAE,qCAAqC;IAUhD,IAAI,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAmC1E,QAAQ,CACV,QAAQ,EAAE,wBAAwB,EAClC,IAAI,CAAC,EAAE,IAAI,GACZ,OAAO,CAAC,IAAI,CAAC;IA0FV,kBAAkB,CACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,QAAQ,EAAE,wBAAwB,EAClC,QAAQ,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IA+ElB,eAAe,CACjB,QAAQ,EAAE,wBAAwB,EAClC,IAAI,EAAE,IAAI;IAOR,SAAS,CACX,QAAQ,EAAE,wBAAwB,EAClC,IAAI,EAAE,IAAI;CAMjB"}
|
|
@@ -67,19 +67,20 @@ var IdentityProviderAccountManager = class {
|
|
|
67
67
|
let output;
|
|
68
68
|
if (user) output = extendObject(user, attributesSelf);
|
|
69
69
|
else output = attributesSelf;
|
|
70
|
+
if (typeof output.name === "string") output.name = output.name.trim().toLowerCase();
|
|
70
71
|
let attempts = Math.max((identity.attributeCandidates?.name?.length || 0) + 1, 10);
|
|
71
72
|
while (attempts > 0) try {
|
|
72
73
|
return await this.userRepository.saveOneWithEA(output, attributesExtra);
|
|
73
74
|
} catch {
|
|
74
75
|
const names = identity.attributeCandidates?.name || [];
|
|
75
76
|
if (names.length > 0) while (names.length > 0) {
|
|
76
|
-
output.name = `${names.shift()}
|
|
77
|
+
output.name = `${names.shift()}`.trim().toLowerCase();
|
|
77
78
|
try {
|
|
78
79
|
await this.userValidator.run(output, { group: identity.operation === IdentityProviderIdentityOperation.CREATE ? ValidatorGroup.CREATE : ValidatorGroup.UPDATE });
|
|
79
80
|
break;
|
|
80
81
|
} catch {}
|
|
81
82
|
}
|
|
82
|
-
else output.name = createNanoID("
|
|
83
|
+
else output.name = createNanoID("0123456789abcdefghijklmnopqrstuvwxyz-_", 10);
|
|
83
84
|
if (isUserFakeEmail(output.email)) output.email = buildUserFakeEmail(output.name);
|
|
84
85
|
attempts -= 1;
|
|
85
86
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.mjs","names":["UserValidator","ValidatorGroup","buildUserFakeEmail","isUserFakeEmail","createNanoID","extendObject","isValidupError","stringifyPath","IdentityProviderIdentityOperation","IdentityProviderMapperOperation","IdentityProviderAccountManager","attributesMapper","permissionMapper","roleMapper","repository","userRepository","userValidator","ctx","attributeMapper","save","identity","account","findOneByProviderIdentity","operation","UPDATE","user","saveUser","saveRoles","savePermissions","CREATE","provider_id","provider","id","provider_user_id","provider_user_name","name","provider_realm_id","realm_id","user_id","user_realm_id","attributes","execute","entity","attribute","key","value","active","name_locked","client_id","clientId","attributesSelf","validateAttributes","Error","attributesSelfKeys","Object","keys","attributesExtra","entityKeys","entityKey","index","indexOf","output","attempts","Math","max","attributeCandidates","length","saveOneWithEA","names","shift","run","group","email","e","retry","i","issues","child","pathNormalized","path","Array","isArray","first","rest","push","entities"],"sources":["../../../../../src/core/identity/provider/account/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\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 { IdentityProviderAccount, User } from '@authup/core-kit';\nimport {\n UserValidator, \n ValidatorGroup,\n buildUserFakeEmail, \n isUserFakeEmail,\n} from '@authup/core-kit';\nimport { createNanoID, extendObject } from '@authup/kit';\nimport { isValidupError, stringifyPath } from 'validup';\nimport type { IUserIdentityRepository } from '../../entities/index.ts';\nimport { IdentityProviderIdentityOperation } from '../constants.ts';\nimport type { IIdentityProviderMapper } from '../mapper/index.ts';\nimport { IdentityProviderMapperOperation } from '../mapper/index.ts';\nimport type { IdentityProviderIdentity } from '../types.ts';\nimport type { IIdentityProviderAccountManager, IIdentityProviderAccountRepository, IdentityProviderAccountManagerContext } from './types.ts';\n\nexport class IdentityProviderAccountManager implements IIdentityProviderAccountManager {\n protected attributesMapper : IIdentityProviderMapper;\n\n protected permissionMapper : IIdentityProviderMapper;\n\n protected roleMapper : IIdentityProviderMapper;\n\n protected repository : IIdentityProviderAccountRepository;\n\n protected userRepository: IUserIdentityRepository;\n\n protected userValidator : UserValidator;\n\n constructor(ctx: IdentityProviderAccountManagerContext) {\n this.attributesMapper = ctx.attributeMapper;\n this.permissionMapper = ctx.permissionMapper;\n this.roleMapper = ctx.roleMapper;\n this.repository = ctx.repository;\n this.userRepository = ctx.userRepository;\n\n this.userValidator = new UserValidator();\n }\n\n async save(identity: IdentityProviderIdentity): Promise<IdentityProviderAccount> {\n let account = await this.repository.findOneByProviderIdentity(identity);\n if (account) {\n identity.operation = IdentityProviderIdentityOperation.UPDATE;\n\n account.user = await this.saveUser(identity, account.user);\n\n await this.repository.save(account);\n\n await this.saveRoles(identity, account.user);\n await this.savePermissions(identity, account.user);\n\n return account;\n }\n\n identity.operation = IdentityProviderIdentityOperation.CREATE;\n\n const user = await this.saveUser(identity);\n\n account = await this.repository.save({\n provider_id: identity.provider.id,\n provider_user_id: identity.id,\n provider_user_name: user.name, // todo: parse identity.name\n provider_realm_id: identity.provider.realm_id,\n user,\n user_id: user.id,\n user_realm_id: user.realm_id,\n });\n\n await this.saveRoles(identity, account.user);\n await this.savePermissions(identity, account.user);\n\n return account;\n }\n\n async saveUser(\n identity: IdentityProviderIdentity,\n user?: User,\n ): Promise<User> {\n const attributes = await this.attributesMapper.execute(\n identity,\n );\n\n const entity : Record<string, any> = {};\n for (const attribute of attributes) {\n if (\n attribute.key &&\n attribute.operation === IdentityProviderMapperOperation.CREATE\n ) {\n // attribute value might be object, array, ...\n entity[attribute.key] = attribute.value;\n }\n }\n\n if (!user) {\n entity.realm_id = identity.provider.realm_id;\n entity.active = true;\n entity.name_locked = true;\n entity.client_id = identity.clientId || null;\n }\n\n const attributesSelf = await this.validateAttributes(entity, identity, 10);\n if (!attributesSelf) {\n // todo: better error name\n throw new Error('Identity provider attributes could not be validated.');\n }\n const attributesSelfKeys = Object.keys(attributesSelf);\n\n const attributesExtra : Record<string, any> = {};\n\n const entityKeys = Object.keys(entity);\n for (const entityKey of entityKeys) {\n const index = attributesSelfKeys.indexOf(entityKey);\n if (index !== -1) {\n continue;\n }\n\n attributesExtra[entityKey] = entity[entityKey];\n }\n\n let output : User;\n if (user) {\n output = extendObject(user, attributesSelf);\n } else {\n output = attributesSelf;\n }\n\n let attempts = Math.max((identity.attributeCandidates?.name?.length || 0) + 1, 10);\n while (attempts > 0) {\n try {\n // todo: we also need to remove existing ones via idp login flow ( but not other attributes!)\n return await this.userRepository.saveOneWithEA(output, attributesExtra);\n } catch {\n const names = identity.attributeCandidates?.name || [];\n if (names.length > 0) {\n while (names.length > 0) {\n output.name = `${names.shift()}`;\n\n try {\n await this.userValidator.run(output, {\n group: identity.operation === IdentityProviderIdentityOperation.CREATE ?\n ValidatorGroup.CREATE :\n ValidatorGroup.UPDATE,\n });\n break;\n } catch {\n // todo: do nothing.\n }\n }\n } else {\n output.name = createNanoID('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_', 10);\n }\n\n if (isUserFakeEmail(output.email)) {\n output.email = buildUserFakeEmail(output.name);\n }\n\n attempts -= 1;\n }\n }\n\n throw new Error('The user account could not be created due a conflict error.');\n }\n\n async validateAttributes(\n entity: Record<string, any>,\n identity: IdentityProviderIdentity,\n attempts: number,\n ) : Promise<User | null> {\n attempts--;\n if (attempts <= 0) {\n return null;\n }\n\n try {\n return await this.userValidator.run(entity, {\n group: identity.operation === IdentityProviderIdentityOperation.CREATE ?\n ValidatorGroup.CREATE :\n ValidatorGroup.UPDATE,\n });\n } catch (e: any) {\n if (!isValidupError(e)) {\n return null;\n }\n\n let retry = false;\n for (let i = 0; i < e.issues.length; i++) {\n const child = e.issues[i];\n\n const pathNormalized = stringifyPath(child.path);\n\n if (\n Array.isArray(entity[pathNormalized]) &&\n entity[pathNormalized].length > 0\n ) {\n const [first, ...rest] = entity[pathNormalized];\n entity[pathNormalized] = first;\n\n if (rest.length > 0) {\n if (!identity.attributeCandidates) {\n identity.attributeCandidates = {};\n }\n\n if (!identity.attributeCandidates[pathNormalized]) {\n identity.attributeCandidates[pathNormalized] = [];\n }\n\n identity.attributeCandidates[pathNormalized]!.push(...rest);\n }\n\n retry = true;\n break;\n }\n\n if (\n identity.attributeCandidates &&\n identity.attributeCandidates[pathNormalized] &&\n identity.attributeCandidates[pathNormalized]!.length > 0\n ) {\n entity[pathNormalized] = identity.attributeCandidates[pathNormalized]!.shift();\n retry = true;\n break;\n }\n\n if (\n entity.name &&\n pathNormalized === 'email'\n ) {\n entity[pathNormalized] = buildUserFakeEmail(entity.name);\n retry = true;\n break;\n }\n\n if (entity[pathNormalized]) {\n entity[pathNormalized] = null;\n break;\n }\n }\n\n if (retry) {\n return this.validateAttributes(entity, identity, attempts);\n }\n\n return null;\n }\n }\n\n async savePermissions(\n identity: IdentityProviderIdentity,\n user: User,\n ) {\n const entities = await this.permissionMapper.execute(identity);\n\n await this.userRepository.savePermissions(user, entities);\n }\n\n async saveRoles(\n identity: IdentityProviderIdentity,\n user: User,\n ) {\n const entities = await this.roleMapper.execute(identity);\n\n await this.userRepository.saveRoles(user, entities);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"module.mjs","names":["UserValidator","ValidatorGroup","buildUserFakeEmail","isUserFakeEmail","createNanoID","extendObject","isValidupError","stringifyPath","IdentityProviderIdentityOperation","IdentityProviderMapperOperation","IdentityProviderAccountManager","attributesMapper","permissionMapper","roleMapper","repository","userRepository","userValidator","ctx","attributeMapper","save","identity","account","findOneByProviderIdentity","operation","UPDATE","user","saveUser","saveRoles","savePermissions","CREATE","provider_id","provider","id","provider_user_id","provider_user_name","name","provider_realm_id","realm_id","user_id","user_realm_id","attributes","execute","entity","attribute","key","value","active","name_locked","client_id","clientId","attributesSelf","validateAttributes","Error","attributesSelfKeys","Object","keys","attributesExtra","entityKeys","entityKey","index","indexOf","output","trim","toLowerCase","attempts","Math","max","attributeCandidates","length","saveOneWithEA","names","shift","run","group","email","e","retry","i","issues","child","pathNormalized","path","Array","isArray","first","rest","push","entities"],"sources":["../../../../../src/core/identity/provider/account/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\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 { IdentityProviderAccount, User } from '@authup/core-kit';\nimport {\n UserValidator, \n ValidatorGroup,\n buildUserFakeEmail, \n isUserFakeEmail,\n} from '@authup/core-kit';\nimport { createNanoID, extendObject } from '@authup/kit';\nimport { isValidupError, stringifyPath } from 'validup';\nimport type { IUserIdentityRepository } from '../../entities/index.ts';\nimport { IdentityProviderIdentityOperation } from '../constants.ts';\nimport type { IIdentityProviderMapper } from '../mapper/index.ts';\nimport { IdentityProviderMapperOperation } from '../mapper/index.ts';\nimport type { IdentityProviderIdentity } from '../types.ts';\nimport type { IIdentityProviderAccountManager, IIdentityProviderAccountRepository, IdentityProviderAccountManagerContext } from './types.ts';\n\nexport class IdentityProviderAccountManager implements IIdentityProviderAccountManager {\n protected attributesMapper : IIdentityProviderMapper;\n\n protected permissionMapper : IIdentityProviderMapper;\n\n protected roleMapper : IIdentityProviderMapper;\n\n protected repository : IIdentityProviderAccountRepository;\n\n protected userRepository: IUserIdentityRepository;\n\n protected userValidator : UserValidator;\n\n constructor(ctx: IdentityProviderAccountManagerContext) {\n this.attributesMapper = ctx.attributeMapper;\n this.permissionMapper = ctx.permissionMapper;\n this.roleMapper = ctx.roleMapper;\n this.repository = ctx.repository;\n this.userRepository = ctx.userRepository;\n\n this.userValidator = new UserValidator();\n }\n\n async save(identity: IdentityProviderIdentity): Promise<IdentityProviderAccount> {\n let account = await this.repository.findOneByProviderIdentity(identity);\n if (account) {\n identity.operation = IdentityProviderIdentityOperation.UPDATE;\n\n account.user = await this.saveUser(identity, account.user);\n\n await this.repository.save(account);\n\n await this.saveRoles(identity, account.user);\n await this.savePermissions(identity, account.user);\n\n return account;\n }\n\n identity.operation = IdentityProviderIdentityOperation.CREATE;\n\n const user = await this.saveUser(identity);\n\n account = await this.repository.save({\n provider_id: identity.provider.id,\n provider_user_id: identity.id,\n provider_user_name: user.name, // todo: parse identity.name\n provider_realm_id: identity.provider.realm_id,\n user,\n user_id: user.id,\n user_realm_id: user.realm_id,\n });\n\n await this.saveRoles(identity, account.user);\n await this.savePermissions(identity, account.user);\n\n return account;\n }\n\n async saveUser(\n identity: IdentityProviderIdentity,\n user?: User,\n ): Promise<User> {\n const attributes = await this.attributesMapper.execute(\n identity,\n );\n\n const entity : Record<string, any> = {};\n for (const attribute of attributes) {\n if (\n attribute.key &&\n attribute.operation === IdentityProviderMapperOperation.CREATE\n ) {\n // attribute value might be object, array, ...\n entity[attribute.key] = attribute.value;\n }\n }\n\n if (!user) {\n entity.realm_id = identity.provider.realm_id;\n entity.active = true;\n entity.name_locked = true;\n entity.client_id = identity.clientId || null;\n }\n\n const attributesSelf = await this.validateAttributes(entity, identity, 10);\n if (!attributesSelf) {\n // todo: better error name\n throw new Error('Identity provider attributes could not be validated.');\n }\n const attributesSelfKeys = Object.keys(attributesSelf);\n\n const attributesExtra : Record<string, any> = {};\n\n const entityKeys = Object.keys(entity);\n for (const entityKey of entityKeys) {\n const index = attributesSelfKeys.indexOf(entityKey);\n if (index !== -1) {\n continue;\n }\n\n attributesExtra[entityKey] = entity[entityKey];\n }\n\n let output : User;\n if (user) {\n output = extendObject(user, attributesSelf);\n } else {\n output = attributesSelf;\n }\n\n if (typeof output.name === 'string') {\n output.name = output.name.trim().toLowerCase();\n }\n\n let attempts = Math.max((identity.attributeCandidates?.name?.length || 0) + 1, 10);\n while (attempts > 0) {\n try {\n // todo: we also need to remove existing ones via idp login flow ( but not other attributes!)\n return await this.userRepository.saveOneWithEA(output, attributesExtra);\n } catch {\n const names = identity.attributeCandidates?.name || [];\n if (names.length > 0) {\n while (names.length > 0) {\n output.name = `${names.shift()}`.trim().toLowerCase();\n\n try {\n await this.userValidator.run(output, {\n group: identity.operation === IdentityProviderIdentityOperation.CREATE ?\n ValidatorGroup.CREATE :\n ValidatorGroup.UPDATE,\n });\n break;\n } catch {\n // todo: do nothing.\n }\n }\n } else {\n output.name = createNanoID('0123456789abcdefghijklmnopqrstuvwxyz-_', 10);\n }\n\n if (isUserFakeEmail(output.email)) {\n output.email = buildUserFakeEmail(output.name);\n }\n\n attempts -= 1;\n }\n }\n\n throw new Error('The user account could not be created due a conflict error.');\n }\n\n async validateAttributes(\n entity: Record<string, any>,\n identity: IdentityProviderIdentity,\n attempts: number,\n ) : Promise<User | null> {\n attempts--;\n if (attempts <= 0) {\n return null;\n }\n\n try {\n return await this.userValidator.run(entity, {\n group: identity.operation === IdentityProviderIdentityOperation.CREATE ?\n ValidatorGroup.CREATE :\n ValidatorGroup.UPDATE,\n });\n } catch (e: any) {\n if (!isValidupError(e)) {\n return null;\n }\n\n let retry = false;\n for (let i = 0; i < e.issues.length; i++) {\n const child = e.issues[i];\n\n const pathNormalized = stringifyPath(child.path);\n\n if (\n Array.isArray(entity[pathNormalized]) &&\n entity[pathNormalized].length > 0\n ) {\n const [first, ...rest] = entity[pathNormalized];\n entity[pathNormalized] = first;\n\n if (rest.length > 0) {\n if (!identity.attributeCandidates) {\n identity.attributeCandidates = {};\n }\n\n if (!identity.attributeCandidates[pathNormalized]) {\n identity.attributeCandidates[pathNormalized] = [];\n }\n\n identity.attributeCandidates[pathNormalized]!.push(...rest);\n }\n\n retry = true;\n break;\n }\n\n if (\n identity.attributeCandidates &&\n identity.attributeCandidates[pathNormalized] &&\n identity.attributeCandidates[pathNormalized]!.length > 0\n ) {\n entity[pathNormalized] = identity.attributeCandidates[pathNormalized]!.shift();\n retry = true;\n break;\n }\n\n if (\n entity.name &&\n pathNormalized === 'email'\n ) {\n entity[pathNormalized] = buildUserFakeEmail(entity.name);\n retry = true;\n break;\n }\n\n if (entity[pathNormalized]) {\n entity[pathNormalized] = null;\n break;\n }\n }\n\n if (retry) {\n return this.validateAttributes(entity, identity, attempts);\n }\n\n return null;\n }\n }\n\n async savePermissions(\n identity: IdentityProviderIdentity,\n user: User,\n ) {\n const entities = await this.permissionMapper.execute(identity);\n\n await this.userRepository.savePermissions(user, entities);\n }\n\n async saveRoles(\n identity: IdentityProviderIdentity,\n user: User,\n ) {\n const entities = await this.roleMapper.execute(identity);\n\n await this.userRepository.saveRoles(user, entities);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/role/index.ts"],"names":[],"mappings":"AAOA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Role } from '@authup/core-kit';
|
|
2
|
+
import type { IdentityPolicyData } from '@authup/access';
|
|
3
|
+
import type { IClientRepository } from '../../entities/client/types.ts';
|
|
4
|
+
import type { IRobotRepository } from '../../entities/robot/types.ts';
|
|
5
|
+
import type { IUserRepository } from '../../entities/user/types.ts';
|
|
6
|
+
import type { IIdentityRoleProvider, IdentityRoleProviderContext } from './types.ts';
|
|
7
|
+
export declare class IdentityRoleProvider implements IIdentityRoleProvider {
|
|
8
|
+
protected clientRepository: IClientRepository;
|
|
9
|
+
protected userRepository: IUserRepository;
|
|
10
|
+
protected robotRepository: IRobotRepository;
|
|
11
|
+
constructor(ctx: IdentityRoleProviderContext);
|
|
12
|
+
getRolesFor(identity: IdentityPolicyData): Promise<Role[]>;
|
|
13
|
+
private reduceByIdentityClient;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/role/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAErF,qBAAa,oBAAqB,YAAW,qBAAqB;IAC9D,SAAS,CAAC,gBAAgB,EAAE,iBAAiB,CAAC;IAE9C,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC;IAE1C,SAAS,CAAC,eAAe,EAAE,gBAAgB,CAAC;gBAEhC,GAAG,EAAE,2BAA2B;IAMtC,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAkBjE,OAAO,CAAC,sBAAsB;CAUjC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/core/identity/role/module.ts
|
|
2
|
+
var IdentityRoleProvider = class {
|
|
3
|
+
clientRepository;
|
|
4
|
+
userRepository;
|
|
5
|
+
robotRepository;
|
|
6
|
+
constructor(ctx) {
|
|
7
|
+
this.clientRepository = ctx.clientRepository;
|
|
8
|
+
this.userRepository = ctx.userRepository;
|
|
9
|
+
this.robotRepository = ctx.robotRepository;
|
|
10
|
+
}
|
|
11
|
+
async getRolesFor(identity) {
|
|
12
|
+
switch (identity.type) {
|
|
13
|
+
case "client": return this.clientRepository.getBoundRoles(identity.id);
|
|
14
|
+
case "user": return this.userRepository.getBoundRoles(identity.id).then((data) => this.reduceByIdentityClient(data, identity));
|
|
15
|
+
case "robot": return this.robotRepository.getBoundRoles(identity.id).then((data) => this.reduceByIdentityClient(data, identity));
|
|
16
|
+
}
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
reduceByIdentityClient(entities, identity) {
|
|
20
|
+
if (!identity.clientId) return entities;
|
|
21
|
+
return entities.filter((entity) => entity.client_id === identity.clientId);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { IdentityRoleProvider };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=module.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.mjs","names":["IdentityRoleProvider","clientRepository","userRepository","robotRepository","ctx","getRolesFor","identity","type","getBoundRoles","id","then","data","reduceByIdentityClient","entities","clientId","filter","entity","client_id"],"sources":["../../../../src/core/identity/role/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\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 { Role } from '@authup/core-kit';\nimport type { IdentityPolicyData } from '@authup/access';\nimport type { IClientRepository } from '../../entities/client/types.ts';\nimport type { IRobotRepository } from '../../entities/robot/types.ts';\nimport type { IUserRepository } from '../../entities/user/types.ts';\nimport type { IIdentityRoleProvider, IdentityRoleProviderContext } from './types.ts';\n\nexport class IdentityRoleProvider implements IIdentityRoleProvider {\n protected clientRepository: IClientRepository;\n\n protected userRepository: IUserRepository;\n\n protected robotRepository: IRobotRepository;\n\n constructor(ctx: IdentityRoleProviderContext) {\n this.clientRepository = ctx.clientRepository;\n this.userRepository = ctx.userRepository;\n this.robotRepository = ctx.robotRepository;\n }\n\n async getRolesFor(identity: IdentityPolicyData) : Promise<Role[]> {\n switch (identity.type) {\n case 'client': {\n return this.clientRepository.getBoundRoles(identity.id);\n }\n case 'user': {\n return this.userRepository.getBoundRoles(identity.id)\n .then((data) => this.reduceByIdentityClient(data, identity));\n }\n case 'robot': {\n return this.robotRepository.getBoundRoles(identity.id)\n .then((data) => this.reduceByIdentityClient(data, identity));\n }\n }\n\n return [];\n }\n\n private reduceByIdentityClient<T extends { client_id?: string | null }>(\n entities: T[],\n identity: IdentityPolicyData,\n ): T[] {\n if (!identity.clientId) {\n return entities;\n }\n\n return entities.filter((entity) => entity.client_id === identity.clientId);\n }\n}\n"],"mappings":";AAcA,IAAaA,uBAAb,MAAaA;CACCC;CAEAC;CAEAC;CAEV,YAAYC,KAAkC;AAC1C,OAAKH,mBAAmBG,IAAIH;AAC5B,OAAKC,iBAAiBE,IAAIF;AAC1B,OAAKC,kBAAkBC,IAAID;;CAG/B,MAAME,YAAYC,UAAgD;AAC9D,UAAQA,SAASC,MAAjB;GACI,KAAK,SACD,QAAO,KAAKN,iBAAiBO,cAAcF,SAASG,GAAE;GAE1D,KAAK,OACD,QAAO,KAAKP,eAAeM,cAAcF,SAASG,GAAE,CAC/CC,MAAMC,SAAS,KAAKC,uBAAuBD,MAAML,SAAAA,CAAAA;GAE1D,KAAK,QACD,QAAO,KAAKH,gBAAgBK,cAAcF,SAASG,GAAE,CAChDC,MAAMC,SAAS,KAAKC,uBAAuBD,MAAML,SAAAA,CAAAA;;AAI9D,SAAO,EAAE;;CAGLM,uBACJC,UACAP,UACG;AACH,MAAI,CAACA,SAASQ,SACV,QAAOD;AAGX,SAAOA,SAASE,QAAQC,WAAWA,OAAOC,cAAcX,SAASQ,SAAQ"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Role } from '@authup/core-kit';
|
|
2
|
+
import type { IdentityPolicyData } from '@authup/access';
|
|
3
|
+
import type { IClientRepository } from '../../entities/client/types.ts';
|
|
4
|
+
import type { IRobotRepository } from '../../entities/robot/types.ts';
|
|
5
|
+
import type { IUserRepository } from '../../entities/user/types.ts';
|
|
6
|
+
export interface IIdentityRoleProvider {
|
|
7
|
+
getRolesFor(identity: IdentityPolicyData): Promise<Role[]>;
|
|
8
|
+
}
|
|
9
|
+
export type IdentityRoleProviderContext = {
|
|
10
|
+
clientRepository: IClientRepository;
|
|
11
|
+
userRepository: IUserRepository;
|
|
12
|
+
robotRepository: IRobotRepository;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/identity/role/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,WAAW,qBAAqB;IAClC,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;CAC9D;AAED,MAAM,MAAM,2BAA2B,GAAG;IACtC,gBAAgB,EAAE,iBAAiB,CAAC;IACpC,cAAc,EAAE,eAAe,CAAC;IAChC,eAAe,EAAE,gBAAgB,CAAC;CACrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/core/index.mjs
CHANGED
|
@@ -37,6 +37,7 @@ import { OAuth2AuthorizationCodeRequestVerifier } from "./oauth2/authorization/c
|
|
|
37
37
|
import { OAuth2AuthorizationCodeRequestValidator } from "./oauth2/authorization/code-request/validator.mjs";
|
|
38
38
|
import { OAuth2AuthorizationStateManager } from "./oauth2/authorization/state/module.mjs";
|
|
39
39
|
import { OAuth2Authorization } from "./oauth2/authorization/module.mjs";
|
|
40
|
+
import { OAuth2ClientAuthenticator } from "./oauth2/client/authenticator.mjs";
|
|
40
41
|
import { buildOAuth2BearerTokenResponse } from "./oauth2/response/bearer.mjs";
|
|
41
42
|
import { OAuth2AuthorizeGrant } from "./oauth2/grant-types/authorize.mjs";
|
|
42
43
|
import { ClientCredentialsGrant } from "./oauth2/grant-types/client-credentials.mjs";
|
|
@@ -74,6 +75,7 @@ import { IDENTITY_PROVIDER_LDAP_COLLECTION_AUTHENTICATOR_TOKEN } from "./identit
|
|
|
74
75
|
import { createIdentityProviderOAuth2Authenticator } from "./identity/provider/authentication/factory.mjs";
|
|
75
76
|
import { RegistrationService } from "./identity/registration/service.mjs";
|
|
76
77
|
import { IdentityResolver } from "./identity/resolver/module.mjs";
|
|
78
|
+
import { IdentityRoleProvider } from "./identity/role/module.mjs";
|
|
77
79
|
import "./identity/index.mjs";
|
|
78
80
|
import { ProvisioningEntityStrategyType } from "./provisioning/strategy/constants.mjs";
|
|
79
81
|
import { normalizeEntityProvisioningStrategy } from "./provisioning/strategy/normalize.mjs";
|
|
@@ -101,4 +103,4 @@ import "./provisioning/index.mjs";
|
|
|
101
103
|
import { PermissionBindingPolicyEvaluator } from "./security/policy/evaluator.mjs";
|
|
102
104
|
import { PolicyEngine } from "./security/policy/engine.mjs";
|
|
103
105
|
import "./security/index.mjs";
|
|
104
|
-
export { AbstractEntityService, BaseCredentialsAuthenticator, ClientAuthenticator, ClientCredentialsGrant, ClientCredentialsService, ClientPermissionService, ClientProvisioningSynchronizer, ClientProvisioningValidator, ClientRoleService, ClientScopeService, ClientService, CredentialsAuthenticator, GraphProvisioningSynchronizer, IDENTITY_PROVIDER_LDAP_COLLECTION_AUTHENTICATOR_TOKEN, IdentityGrantType, IdentityPermissionProvider, IdentityProviderAccountBaseMapper, IdentityProviderAccountManager, IdentityProviderAttributeMapper, IdentityProviderFacebookAuthenticator, IdentityProviderGithubAuthenticator, IdentityProviderGoogleAuthenticator, IdentityProviderInstagramAuthenticator, IdentityProviderLdapAuthenticator, IdentityProviderLdapCollectionAuthenticator, IdentityProviderMapperOperation, IdentityProviderOAuth2Authenticator, IdentityProviderOpenIDAuthenticator, IdentityProviderPaypalAuthenticator, IdentityProviderPermissionMapper, IdentityProviderRoleMapper, IdentityProviderRoleMappingService, IdentityResolver, OAuth2AccessTokenIssuer, OAuth2Authorization, OAuth2AuthorizationCodeIssuer, OAuth2AuthorizationCodeRequestValidator, OAuth2AuthorizationCodeRequestVerifier, OAuth2AuthorizationCodeVerifier, OAuth2AuthorizationStateManager, OAuth2AuthorizeGrant, OAuth2OpenIDClaimsBuilder, OAuth2OpenIDTokenIssuer, OAuth2RefreshTokenGrant, OAuth2RefreshTokenIssuer, OAuth2ScopeAttributesResolver, OAuth2TokenRevoker, OAuth2TokenSigner, OAuth2TokenVerifier, PasswordGrantType, PasswordRecoveryService, PermissionBindingPolicyEvaluator, PermissionPolicyService, PermissionProvisioningSynchronizer, PermissionProvisioningValidator, PermissionService, PolicyEngine, PolicyProvisioningSynchronizer, PolicyService, ProvisioningEntityResolver, ProvisioningEntityStrategyType, ProvisioningJunctionSynchronizer, ProvisioningStrategyValidator, RealmProvisioningSynchronizer, RealmProvisioningValidator, RealmService, RegistrationService, RobotAuthenticator, RobotCredentialsGrant, RobotCredentialsService, RobotPermissionService, RobotProvisioningSynchronizer, RobotProvisioningValidator, RobotRoleService, RobotService, RoleAttributeService, RolePermissionService, RoleProvisioningSynchronizer, RoleProvisioningValidator, RoleService, RootProvisioningValidator, ScopeProvisioningSynchronizer, ScopeProvisioningValidator, ScopeService, SessionManager, UserAttributeService, UserAuthenticator, UserCredentialsService, UserPermissionService, UserProvisioningSynchronizer, UserProvisioningValidator, UserRoleService, UserService, base64URLEncode, buildOAuth2BearerTokenResponse, buildOAuth2CodeChallenge, buildOAuth2TokenHash, createIdentityProviderOAuth2Authenticator, generateOAuth2CodeVerifier, normalizeEntityProvisioningStrategy };
|
|
106
|
+
export { AbstractEntityService, BaseCredentialsAuthenticator, ClientAuthenticator, ClientCredentialsGrant, ClientCredentialsService, ClientPermissionService, ClientProvisioningSynchronizer, ClientProvisioningValidator, ClientRoleService, ClientScopeService, ClientService, CredentialsAuthenticator, GraphProvisioningSynchronizer, IDENTITY_PROVIDER_LDAP_COLLECTION_AUTHENTICATOR_TOKEN, IdentityGrantType, IdentityPermissionProvider, IdentityProviderAccountBaseMapper, IdentityProviderAccountManager, IdentityProviderAttributeMapper, IdentityProviderFacebookAuthenticator, IdentityProviderGithubAuthenticator, IdentityProviderGoogleAuthenticator, IdentityProviderInstagramAuthenticator, IdentityProviderLdapAuthenticator, IdentityProviderLdapCollectionAuthenticator, IdentityProviderMapperOperation, IdentityProviderOAuth2Authenticator, IdentityProviderOpenIDAuthenticator, IdentityProviderPaypalAuthenticator, IdentityProviderPermissionMapper, IdentityProviderRoleMapper, IdentityProviderRoleMappingService, IdentityResolver, IdentityRoleProvider, OAuth2AccessTokenIssuer, OAuth2Authorization, OAuth2AuthorizationCodeIssuer, OAuth2AuthorizationCodeRequestValidator, OAuth2AuthorizationCodeRequestVerifier, OAuth2AuthorizationCodeVerifier, OAuth2AuthorizationStateManager, OAuth2AuthorizeGrant, OAuth2ClientAuthenticator, OAuth2OpenIDClaimsBuilder, OAuth2OpenIDTokenIssuer, OAuth2RefreshTokenGrant, OAuth2RefreshTokenIssuer, OAuth2ScopeAttributesResolver, OAuth2TokenRevoker, OAuth2TokenSigner, OAuth2TokenVerifier, PasswordGrantType, PasswordRecoveryService, PermissionBindingPolicyEvaluator, PermissionPolicyService, PermissionProvisioningSynchronizer, PermissionProvisioningValidator, PermissionService, PolicyEngine, PolicyProvisioningSynchronizer, PolicyService, ProvisioningEntityResolver, ProvisioningEntityStrategyType, ProvisioningJunctionSynchronizer, ProvisioningStrategyValidator, RealmProvisioningSynchronizer, RealmProvisioningValidator, RealmService, RegistrationService, RobotAuthenticator, RobotCredentialsGrant, RobotCredentialsService, RobotPermissionService, RobotProvisioningSynchronizer, RobotProvisioningValidator, RobotRoleService, RobotService, RoleAttributeService, RolePermissionService, RoleProvisioningSynchronizer, RoleProvisioningValidator, RoleService, RootProvisioningValidator, ScopeProvisioningSynchronizer, ScopeProvisioningValidator, ScopeService, SessionManager, UserAttributeService, UserAuthenticator, UserCredentialsService, UserPermissionService, UserProvisioningSynchronizer, UserProvisioningValidator, UserRoleService, UserService, base64URLEncode, buildOAuth2BearerTokenResponse, buildOAuth2CodeChallenge, buildOAuth2TokenHash, createIdentityProviderOAuth2Authenticator, generateOAuth2CodeVerifier, normalizeEntityProvisioningStrategy };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../../../src/core/oauth2/authorization/code/verifier/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAIhE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,KAAK,EAAE,gCAAgC,EAAE,qCAAqC,EAAE,MAAM,YAAY,CAAC;AAE1G,qBAAa,+BAAgC,YAAW,gCAAgC;IACpF,SAAS,CAAC,UAAU,EAAG,kCAAkC,CAAC;gBAE9C,UAAU,EAAE,kCAAkC;IAIpD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qCAAqC,GAAI,OAAO,CAAC,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../../../src/core/oauth2/authorization/code/verifier/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAIhE,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,wBAAwB,CAAC;AACjF,OAAO,KAAK,EAAE,gCAAgC,EAAE,qCAAqC,EAAE,MAAM,YAAY,CAAC;AAE1G,qBAAa,+BAAgC,YAAW,gCAAgC;IACpF,SAAS,CAAC,UAAU,EAAG,kCAAkC,CAAC;gBAE9C,UAAU,EAAE,kCAAkC;IAIpD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qCAAqC,GAAI,OAAO,CAAC,uBAAuB,CAAC;CAiDhH"}
|
|
@@ -9,14 +9,18 @@ var OAuth2AuthorizationCodeVerifier = class {
|
|
|
9
9
|
async verify(code, options) {
|
|
10
10
|
const entity = await this.repository.popOneById(code);
|
|
11
11
|
if (!entity) throw OAuth2Error.grantInvalid();
|
|
12
|
+
if (entity.client_id) {
|
|
13
|
+
if (!options.clientId || options.clientId !== entity.client_id) throw OAuth2Error.grantInvalid();
|
|
14
|
+
}
|
|
12
15
|
if (entity.redirect_uri) {
|
|
13
16
|
if (!options.redirectUri || entity.redirect_uri !== options.redirectUri) throw OAuth2Error.redirectUriMismatch();
|
|
14
17
|
}
|
|
15
|
-
if (entity.code_challenge)
|
|
16
|
-
|
|
17
|
-
} else {
|
|
18
|
+
if (options.clientIsPublic && !entity.code_challenge) throw OAuth2Error.grantInvalid("PKCE is required for public clients.");
|
|
19
|
+
if (entity.code_challenge) {
|
|
18
20
|
if (!options.codeVerifier) throw OAuth2Error.grantInvalid("Code verifier invalid.");
|
|
19
|
-
if (
|
|
21
|
+
if (entity.code_challenge_method === OAuth2AuthorizationCodeChallengeMethod.SHA_256) {
|
|
22
|
+
if (await buildOAuth2CodeChallenge(options.codeVerifier) !== entity.code_challenge) throw OAuth2Error.grantInvalid("PKCE code_verifier mismatch.");
|
|
23
|
+
} else if (options.codeVerifier !== entity.code_challenge) throw OAuth2Error.grantInvalid("PKCE code_verifier mismatch.");
|
|
20
24
|
}
|
|
21
25
|
return entity;
|
|
22
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.mjs","names":["OAuth2AuthorizationCodeChallengeMethod","OAuth2Error","buildOAuth2CodeChallenge","OAuth2AuthorizationCodeVerifier","repository","verify","code","options","entity","popOneById","grantInvalid","redirect_uri","redirectUri","redirectUriMismatch","code_challenge","
|
|
1
|
+
{"version":3,"file":"module.mjs","names":["OAuth2AuthorizationCodeChallengeMethod","OAuth2Error","buildOAuth2CodeChallenge","OAuth2AuthorizationCodeVerifier","repository","verify","code","options","entity","popOneById","grantInvalid","client_id","clientId","redirect_uri","redirectUri","redirectUriMismatch","clientIsPublic","code_challenge","codeVerifier","code_challenge_method","SHA_256","codeVerifierHash"],"sources":["../../../../../../src/core/oauth2/authorization/code/verifier/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2025.\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 { OAuth2AuthorizationCode } from '@authup/core-kit';\nimport { OAuth2AuthorizationCodeChallengeMethod, OAuth2Error } from '@authup/specs';\nimport { buildOAuth2CodeChallenge } from '../../helpers.ts';\n\nimport type { IOAuth2AuthorizationCodeRepository } from '../repository/index.ts';\nimport type { IOAuth2AuthorizationCodeVerifier, IOAuth2AuthorizationCodeVerifyOptions } from './types.ts';\n\nexport class OAuth2AuthorizationCodeVerifier implements IOAuth2AuthorizationCodeVerifier {\n protected repository : IOAuth2AuthorizationCodeRepository;\n\n constructor(repository: IOAuth2AuthorizationCodeRepository) {\n this.repository = repository;\n }\n\n async verify(code: string, options: IOAuth2AuthorizationCodeVerifyOptions) : Promise<OAuth2AuthorizationCode> {\n const entity = await this.repository.popOneById(code);\n if (!entity) {\n throw OAuth2Error.grantInvalid();\n }\n\n // RFC 6749 §4.1.3: if the client was issued a client_id, verify the\n // authorization code was issued to the authenticated client. Always\n // require a clientId to be supplied so a malformed token request can't\n // bypass the binding by omitting it.\n if (entity.client_id) {\n if (!options.clientId || options.clientId !== entity.client_id) {\n throw OAuth2Error.grantInvalid();\n }\n }\n\n if (entity.redirect_uri) {\n if (!options.redirectUri || entity.redirect_uri !== options.redirectUri) {\n throw OAuth2Error.redirectUriMismatch();\n }\n }\n\n // Public clients MUST use PKCE (RFC 7636). Defense in depth in case\n // the authorize-side check was bypassed or the client's\n // is_confidential flag changed between authorize and token.\n if (options.clientIsPublic && !entity.code_challenge) {\n throw OAuth2Error.grantInvalid('PKCE is required for public clients.');\n }\n\n if (entity.code_challenge) {\n if (!options.codeVerifier) {\n throw OAuth2Error.grantInvalid('Code verifier invalid.');\n }\n\n // RFC 7636 §4.3: code_challenge_method defaults to \"plain\" when\n // absent. Only treat the challenge as S256 when the client\n // explicitly sent code_challenge_method=S256.\n if (entity.code_challenge_method === OAuth2AuthorizationCodeChallengeMethod.SHA_256) {\n const codeVerifierHash = await buildOAuth2CodeChallenge(options.codeVerifier);\n if (codeVerifierHash !== entity.code_challenge) {\n throw OAuth2Error.grantInvalid('PKCE code_verifier mismatch.');\n }\n } else if (options.codeVerifier !== entity.code_challenge) {\n throw OAuth2Error.grantInvalid('PKCE code_verifier mismatch.');\n }\n }\n\n return entity;\n }\n}\n"],"mappings":";;;AAcA,IAAaG,kCAAb,MAAaA;CACCC;CAEV,YAAYA,YAAgD;AACxD,OAAKA,aAAaA;;CAGtB,MAAMC,OAAOC,MAAcC,SAAmF;EAC1G,MAAMC,SAAS,MAAM,KAAKJ,WAAWK,WAAWH,KAAAA;AAChD,MAAI,CAACE,OACD,OAAMP,YAAYS,cAAY;AAOlC,MAAIF,OAAOG;OACH,CAACJ,QAAQK,YAAYL,QAAQK,aAAaJ,OAAOG,UACjD,OAAMV,YAAYS,cAAY;;AAItC,MAAIF,OAAOK;OACH,CAACN,QAAQO,eAAeN,OAAOK,iBAAiBN,QAAQO,YACxD,OAAMb,YAAYc,qBAAmB;;AAO7C,MAAIR,QAAQS,kBAAkB,CAACR,OAAOS,eAClC,OAAMhB,YAAYS,aAAa,uCAAA;AAGnC,MAAIF,OAAOS,gBAAgB;AACvB,OAAI,CAACV,QAAQW,aACT,OAAMjB,YAAYS,aAAa,yBAAA;AAMnC,OAAIF,OAAOW,0BAA0BnB,uCAAuCoB;QAEpEC,MAD2BnB,yBAAyBK,QAAQW,aAAY,KACnDV,OAAOS,eAC5B,OAAMhB,YAAYS,aAAa,+BAAA;cAE5BH,QAAQW,iBAAiBV,OAAOS,eACvC,OAAMhB,YAAYS,aAAa,+BAAA;;AAIvC,SAAOF"}
|
|
@@ -2,6 +2,8 @@ import type { OAuth2AuthorizationCode } from '@authup/core-kit';
|
|
|
2
2
|
export type IOAuth2AuthorizationCodeVerifyOptions = {
|
|
3
3
|
redirectUri?: string;
|
|
4
4
|
codeVerifier?: string;
|
|
5
|
+
clientId?: string;
|
|
6
|
+
clientIsPublic?: boolean;
|
|
5
7
|
};
|
|
6
8
|
export interface IOAuth2AuthorizationCodeVerifier {
|
|
7
9
|
verify(code: string, options: IOAuth2AuthorizationCodeVerifyOptions): Promise<OAuth2AuthorizationCode>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/core/oauth2/authorization/code/verifier/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,MAAM,MAAM,qCAAqC,GAAG;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/core/oauth2/authorization/code/verifier/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAEhE,MAAM,MAAM,qCAAqC,GAAG;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,WAAW,gCAAgC;IAC7C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qCAAqC,GAAI,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC3G"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../../../src/core/oauth2/authorization/code-request/verifier/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../../../src/core/oauth2/authorization/code-request/verifier/module.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAQvE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,EACR,uCAAuC,EACvC,gDAAgD,EAChD,6CAA6C,EAChD,MAAM,YAAY,CAAC;AASpB,qBAAa,sCAAuC,YAAW,uCAAuC;IAClG,SAAS,CAAC,gBAAgB,EAAE,uBAAuB,CAAC;IAEpD,SAAS,CAAC,eAAe,EAAE,sBAAsB,CAAC;gBAEtC,GAAG,EAAE,6CAA6C;IAK9D;;;OAGG;IACG,MAAM,CACR,IAAI,EAAE,8BAA8B,GACpC,OAAO,CAAC,gDAAgD,CAAC;CA6DhE"}
|