UNPKG

@rytass/member-base-nestjs-module

Version:

Rytass Member System NestJS Base Module

210 lines (207 loc) 7.41 kB
import { randomBytes } from 'node:crypto'; import { LOGIN_FAILED_BAN_THRESHOLD, MEMBER_BASE_MODULE_OPTIONS, RESET_PASSWORD_TOKEN_EXPIRATION, RESET_PASSWORD_TOKEN_SECRET, PROVIDE_MEMBER_ENTITY, ACCESS_TOKEN_SECRET, ACCESS_TOKEN_EXPIRATION, REFRESH_TOKEN_SECRET, REFRESH_TOKEN_EXPIRATION, ENABLE_GLOBAL_GUARD, CASBIN_ENFORCER, CASBIN_PERMISSION_DECORATOR, CASBIN_PERMISSION_CHECKER, PASSWORD_SHOULD_INCLUDE_UPPERCASE, PASSWORD_SHOULD_INCLUDE_LOWERCASE, PASSWORD_SHOULD_INCLUDE_DIGIT, PASSWORD_SHOULD_INCLUDE_SPECIAL_CHARACTER, PASSWORD_MIN_LENGTH, PASSWORD_POLICY_REGEXP, PASSWORD_HISTORY_LIMIT, PASSWORD_AGE_LIMIT_IN_DAYS, ONLY_RESET_REFRESH_TOKEN_EXPIRATION_BY_PASSWORD, FORCE_REJECT_LOGIN_ON_PASSWORD_EXPIRED, CUSTOMIZED_JWT_PAYLOAD, OAUTH2_PROVIDERS, OAUTH2_CLIENT_DEST_URL, COOKIE_MODE, LOGIN_FAILED_AUTO_UNLOCK_SECONDS } from '../typings/member-base-providers.js'; import { newEnforcer, newModelFromString } from 'casbin'; import { CASBIN_MODEL } from './casbin-models/rbac-with-domains.js'; import { AllowActions } from '../decorators/action.decorator.js'; import { DEFAULT_CASBIN_DOMAIN } from './default-casbin-domain.js'; const TypeORMAdapter = require('typeorm-adapter').default; const OptionProviders = [ { provide: LOGIN_FAILED_BAN_THRESHOLD, useFactory: (options)=>options?.loginFailedBanThreshold ?? 5, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: RESET_PASSWORD_TOKEN_EXPIRATION, useFactory: (options)=>options?.resetPasswordTokenExpiration ?? 60 * 60 * 1, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: RESET_PASSWORD_TOKEN_SECRET, useFactory: (options)=>options?.resetPasswordTokenSecret ?? randomBytes(16).toString('hex'), inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PROVIDE_MEMBER_ENTITY, useFactory: (options)=>options?.memberEntity ?? null, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: ACCESS_TOKEN_SECRET, useFactory: (options)=>options?.accessTokenSecret ?? randomBytes(16).toString('hex'), inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: ACCESS_TOKEN_EXPIRATION, useFactory: (options)=>options?.accessTokenExpiration ?? 60 * 15, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: REFRESH_TOKEN_SECRET, useFactory: (options)=>options?.refreshTokenSecret ?? randomBytes(16).toString('hex'), inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: REFRESH_TOKEN_EXPIRATION, useFactory: (options)=>options?.refreshTokenExpiration ?? 60 * 60 * 24 * 90, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: ENABLE_GLOBAL_GUARD, useFactory: (options)=>options?.enableGlobalGuard ?? true, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: CASBIN_ENFORCER, useFactory: async (options)=>{ if (!options?.casbinAdapterOptions) return null; const adapter = await TypeORMAdapter.newAdapter(options.casbinAdapterOptions); const enforcer = await newEnforcer(); const model = newModelFromString(options.casbinModelString || CASBIN_MODEL); await enforcer.initWithModelAndAdapter(model, adapter); await enforcer.loadPolicy(); return enforcer; }, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: CASBIN_PERMISSION_DECORATOR, useFactory: async (options)=>options?.casbinPermissionDecorator ?? AllowActions, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: CASBIN_PERMISSION_CHECKER, useFactory: async (options)=>options?.casbinPermissionChecker ? options.casbinPermissionChecker : ({ enforcer, payload, actions })=>Promise.all(actions.map(([subject, action])=>enforcer.enforce(payload.id, payload.domain ?? DEFAULT_CASBIN_DOMAIN, subject, action))).then((results)=>results.some((result)=>result)), inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_SHOULD_INCLUDE_UPPERCASE, useFactory: (options)=>options?.passwordShouldIncludeUppercase ?? true, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_SHOULD_INCLUDE_LOWERCASE, useFactory: (options)=>options?.passwordShouldIncludeLowercase ?? true, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_SHOULD_INCLUDE_DIGIT, useFactory: (options)=>options?.passwordShouldIncludeDigit ?? true, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_SHOULD_INCLUDE_SPECIAL_CHARACTER, useFactory: (options)=>options?.passwordShouldIncludeSpecialCharacters ?? false, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_MIN_LENGTH, useFactory: (options)=>options?.passwordMinLength ?? 8, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_POLICY_REGEXP, useFactory: (options)=>options?.passwordPolicyRegExp ?? undefined, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_HISTORY_LIMIT, useFactory: (options)=>options?.passwordHistoryLimit ?? undefined, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: PASSWORD_AGE_LIMIT_IN_DAYS, useFactory: (options)=>options?.passwordAgeLimitInDays ?? undefined, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: ONLY_RESET_REFRESH_TOKEN_EXPIRATION_BY_PASSWORD, useFactory: (options)=>options?.onlyResetRefreshTokenExpirationByPassword ?? false, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: FORCE_REJECT_LOGIN_ON_PASSWORD_EXPIRED, useFactory: (options)=>options?.forceRejectLoginOnPasswordExpired ?? false, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: CUSTOMIZED_JWT_PAYLOAD, useFactory: (options)=>options?.customizedJwtPayload ?? ((member)=>({ id: member.id, account: member.account })) }, { provide: OAUTH2_PROVIDERS, useFactory: (options)=>options?.oauth2Providers ?? [], inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: OAUTH2_CLIENT_DEST_URL, useFactory: (options)=>options?.oauth2ClientDestUrl ?? '/login', inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: COOKIE_MODE, useFactory: (options)=>options?.cookieMode ?? false, inject: [ MEMBER_BASE_MODULE_OPTIONS ] }, { provide: LOGIN_FAILED_AUTO_UNLOCK_SECONDS, useFactory: (options)=>options?.loginFailedAutoUnlockSeconds ?? null, inject: [ MEMBER_BASE_MODULE_OPTIONS ] } ]; export { OptionProviders };