cca-auth-module 0.1.90 → 0.1.91
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/application/useCase/LoginUseCase.d.ts +1 -1
- package/dist/index.d.mts +2 -10
- package/dist/index.d.ts +2 -10
- package/dist/index.js +25 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -42
- package/dist/index.mjs.map +1 -1
- package/dist/presentation/controller/AuthController.d.ts +1 -3
- package/package.json +1 -1
- package/dist/application/useCase/LoginAdminUseCase.d.ts +0 -9
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/application/config/ConfigManager.ts","../src/utils/Errors.ts","../src/application/service/utils/configInstance.ts","../src/infrastructure/container/createAuthContainer.ts","../src/application/useCase/LoginUseCase.ts","../src/application/validators/authValidation.ts","../src/application/useCase/LoginAdminUseCase.ts","../src/application/useCase/LogoutUseCase.ts","../src/application/useCase/RegisterUseCase.ts","../src/application/mappers/utils/mapper.ts","../src/application/mappers/createUserMappings.ts","../src/application/dtos/RegisterDTO.ts","../src/application/dtos/UserDTO.ts","../src/application/dtos/AdminDTO.ts","../src/application/useCase/RefreshTokenUseCase.ts","../src/application/useCase/TwoFactorSetupUseCase.ts","../src/application/useCase/TwoFactorEnableUseCase.ts","../src/application/useCase/TwoFactorVerifyUseCase.ts","../src/application/useCase/TwoFactorDisableUseCase.ts","../src/presentation/constants/constants.ts","../src/presentation/controller/AuthController.ts","../src/presentation/middleware/RequireComplete2FA.ts","../src/infrastructure/repository/AuthRepository.ts","../src/infrastructure/services/JwtAuthService.ts","../src/infrastructure/services/TwoFactorService.ts"],"sourcesContent":["import { authConfig } from \"./application/service/utils/configInstance\";\r\nimport { ConfigSource, IConfig } from \"./domain/interfaces/configTypes\";\r\nimport { createAuthContainer } from \"./infrastructure/container/createAuthContainer\";\r\nimport { AuthController } from \"./presentation/controller/AuthController\";\r\n\r\nexport { createAuthContainer, AuthController, authConfig, ConfigSource, IConfig };\r\n","import { EventEmitter } from \"events\";\r\nimport { IConfig, ConfigSource } from \"../../domain/interfaces/configTypes\";\r\nimport { ConfigNotFoundException } from \"../../utils/Errors\";\r\n\r\nexport class ConfigManager extends EventEmitter {\r\n private config?: IConfig;\r\n private configSource?: ConfigSource;\r\n\r\n setConfigSource(source: ConfigSource): void {\r\n this.configSource = source;\r\n }\r\n\r\n setConfig(cfg: IConfig): void {\r\n this.config = { ...cfg };\r\n this.emit(\"configAvailable\", this.config);\r\n }\r\n\r\n getConfig(): IConfig | undefined {\r\n return this.config;\r\n }\r\n\r\n async loadConfig(): Promise<IConfig> {\r\n if (!this.configSource) {\r\n throw new ConfigNotFoundException(\"Config source not set\");\r\n }\r\n try {\r\n const config = await this.configSource();\r\n this.setConfig(config);\r\n return config;\r\n } catch (error) {\r\n throw new ConfigNotFoundException(\"Error loading configuration\");\r\n }\r\n }\r\n}\r\n\r\nexport const configManager = new ConfigManager();\r\n","export class AppError extends Error {\r\n constructor(\r\n public message: string,\r\n public statusCode: number = 500,\r\n public name: string = \"AppError\"\r\n ) {\r\n super(message);\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n Error.captureStackTrace(this);\r\n }\r\n}\r\n\r\nexport class ValidationError extends AppError {\r\n constructor(message: string) {\r\n super(message, 400);\r\n this.name = \"ValidationError\";\r\n }\r\n}\r\n\r\nexport class ConfigNotFoundException extends AppError {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"ConfigNotFoundException\";\r\n }\r\n}\r\n\r\nexport class NotFoundError extends AppError {\r\n constructor(message: string) {\r\n super(message, 404, \"UserNotFoundError\");\r\n }\r\n}\r\n\r\nexport class ForbiddenError extends AppError {\r\n constructor(message: string = \"Forbidden access\") {\r\n super(message, 403);\r\n this.name = \"ForbiddenError\";\r\n }\r\n}\r\n\r\nexport class UnauthorizedError extends AppError {\r\n constructor(message: string = \"Unauthorized access\") {\r\n super(message, 401);\r\n this.name = \"UnauthorizedError\";\r\n }\r\n}\r\n\r\nexport class JwtError extends AppError {\r\n constructor(message: string) {\r\n super(message, 401);\r\n this.name = \"JwtError\";\r\n }\r\n}\r\n\r\nexport class RegistrationError extends AppError {\r\n constructor(message: string) {\r\n super(message, 400);\r\n this.name = \"RegistrationError\";\r\n }\r\n}\r\n\r\nexport class TwoFactorError extends AppError {\r\n constructor(message: string) {\r\n super(message, 400);\r\n this.name = \"TwoFactorERROR\";\r\n }\r\n}","import { configManager } from \"../../config/ConfigManager\";\r\nimport { IConfig, ConfigSource } from \"../../../domain/interfaces/configTypes\";\r\n\r\nexport const authConfig = (configSource: ConfigSource): void => {\r\n configManager.setConfigSource(configSource);\r\n};\r\n\r\nexport const createConfigInstance = async (): Promise<IConfig> => {\r\n return configManager.getConfig() ?? (await configManager.loadConfig());\r\n};\r\n","import { BaseContainer, BaseDatabase } from \"cca-core\";\r\nimport { AuthEntity } from \"cca-entities\";\r\n\r\nimport { LoginUseCase } from \"../../application/useCase/LoginUseCase\";\r\nimport { LoginAdminUseCase } from \"../../application/useCase/LoginAdminUseCase\";\r\nimport { LogoutUseCase } from \"../../application/useCase/LogoutUseCase\";\r\nimport { RegisterUseCase } from \"../../application/useCase/RegisterUseCase\";\r\nimport { RefreshTokenUseCase } from \"../../application/useCase/RefreshTokenUseCase\";\r\nimport { TwoFactorSetupUseCase } from \"../../application/useCase/TwoFactorSetupUseCase\";\r\nimport { TwoFactorEnableUseCase } from \"../../application/useCase/TwoFactorEnableUseCase\";\r\nimport { TwoFactorVerifyUseCase } from \"../../application/useCase/TwoFactorVerifyUseCase\";\r\nimport { TwoFactorDisableUseCase } from \"../../application/useCase/TwoFactorDisableUseCase\";\r\n\r\nimport { AuthController } from \"../../presentation/controller/AuthController\";\r\nimport { RequireComplete2FA } from \"../../presentation/middleware/RequireComplete2FA\";\r\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nimport { JwtAuthService } from \"../services/JwtAuthService\";\r\nimport { TwoFactorService } from \"../services/TwoFactorService\";\r\nimport { createConfigInstance } from \"../../application/service/utils/configInstance\";\r\n\r\nasync function createAuthContainer(database: BaseDatabase) {\r\n const container = new BaseContainer({ database });\r\n\r\n const authRepository = new AuthRepository(\r\n database.getRepository(AuthEntity)\r\n );\r\n container.registerRepository<AuthEntity>(\"AuthRepository\", authRepository);\r\n\r\n const jwtAuthService = new JwtAuthService(authRepository);\r\n container.registerService(\"JwtAuthService\", jwtAuthService);\r\n\r\n const configData = await createConfigInstance();\r\n\r\n const twoFactorService = new TwoFactorService(configData);\r\n container.registerService(\"TwoFactorService\", twoFactorService);\r\n\r\n const requireComplete2FA = new RequireComplete2FA(jwtAuthService);\r\n\r\n const loginUseCase = new LoginUseCase(authRepository, jwtAuthService);\r\n const loginAdminUseCase = new LoginAdminUseCase(\r\n authRepository\r\n );\r\n const logoutUseCase = new LogoutUseCase(authRepository);\r\n const registerUseCase = new RegisterUseCase(authRepository);\r\n const refreshTokenUseCase = new RefreshTokenUseCase(\r\n authRepository,\r\n jwtAuthService\r\n );\r\n\r\n const twoFactorSetupUseCase = new TwoFactorSetupUseCase(twoFactorService, authRepository);\r\n const twoFactorEnableUseCase = new TwoFactorEnableUseCase(twoFactorService, authRepository);\r\n const twoFactorVerifyUseCase = new TwoFactorVerifyUseCase(\r\n twoFactorService,\r\n authRepository,\r\n jwtAuthService\r\n );\r\n const twoFactorDisableUseCase = new TwoFactorDisableUseCase(twoFactorService, authRepository);\r\n\r\n container.registerService(\"LoginUseCase\", loginUseCase);\r\n container.registerService(\"LoginAdminUseCase\", loginAdminUseCase);\r\n container.registerService(\"LogoutUseCase\", logoutUseCase);\r\n container.registerService(\"RegisterUseCase\", registerUseCase);\r\n container.registerService(\"RefreshTokenUseCase\", refreshTokenUseCase);\r\n container.registerService(\"TwoFactorSetupUseCase\", twoFactorSetupUseCase);\r\n container.registerService(\"TwoFactorEnableUseCase\", twoFactorEnableUseCase);\r\n container.registerService(\"TwoFactorVerifyUseCase\", twoFactorVerifyUseCase);\r\n container.registerService(\"TwoFactorDisableUseCase\", twoFactorDisableUseCase);\r\n\r\n const authController = new AuthController(\r\n loginUseCase,\r\n loginAdminUseCase,\r\n logoutUseCase,\r\n registerUseCase,\r\n refreshTokenUseCase,\r\n twoFactorSetupUseCase,\r\n twoFactorEnableUseCase,\r\n twoFactorVerifyUseCase,\r\n twoFactorDisableUseCase\r\n );\r\n\r\n return { container, authController, requireComplete2FA };\r\n}\r\n\r\nexport { createAuthContainer };","import { IBaseService, validateRepository } from \"cca-core\";\r\nimport { jwtDecode } from \"jwt-decode\";\r\n\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { LoginDTO } from \"../dtos/LoginDTO\";\r\nimport { validateLoginDTO } from \"../validators/authValidation\";\r\nimport { JwtAuthService } from \"../../infrastructure/services/JwtAuthService\";\r\nimport { IJwtPayload } from \"../../domain/interfaces/IJwtPayload\";\r\n\r\n\r\nexport class LoginUseCase implements IBaseService {\r\n\r\n constructor(\r\n private readonly repository: AuthRepository,\r\n private readonly jwtService: JwtAuthService\r\n ) { }\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo: AuthRepository) => repo.getAll());\r\n }\r\n\r\n async execute(loginDTO: LoginDTO): Promise<{ id: string, accessToken: string, expiresAt: number, enabled?: boolean }> {\r\n const auth = await validateLoginDTO(loginDTO, this.repository);\r\n\r\n const accessToken = this.jwtService.generateAccessToken(auth.user, auth.role);\r\n const expiresAt = jwtDecode<IJwtPayload>(accessToken).exp;\r\n\r\n return { id: auth.user.id, accessToken: accessToken, expiresAt: expiresAt, enabled: auth.twoFactorEnabled };\r\n }\r\n}","import * as yup from \"yup\";\r\nimport { AuthEntity, UserRole } from \"cca-entities\";\r\nimport bcrypt from \"bcrypt\";\r\n\r\nimport {\r\n ForbiddenError,\r\n NotFoundError,\r\n ValidationError,\r\n} from \"../../utils/Errors\";\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\n\r\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\r\nimport { LoginDTO } from \"../dtos/LoginDTO\";\r\nimport { createConfigInstance } from \"../service/utils/configInstance\";\r\n\r\nconst schemas = {\r\n id: yup.string().uuid(\"Invalid user ID format\"),\r\n email: yup\r\n .string()\r\n .email(\"Invalid email format\")\r\n .max(255, \"Email cannot exceed 255 characters\"),\r\n name: yup\r\n .string()\r\n .required(\"Name is required\")\r\n .min(2, \"Name must be at least 2 characters long\")\r\n .max(50, \"Name cannot exceed 50 characters\")\r\n .matches(/^[a-zA-Z\\s]+$/, \"Name must only contain letters and spaces\"),\r\n password: yup\r\n .string()\r\n .required(\"Password required\")\r\n .min(8, \"Password too short\")\r\n .max(100, \"Password too long\")\r\n .matches(\r\n /^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]/,\r\n \"Password must contain uppercase, lowercase, number and special character\"\r\n ),\r\n role: yup\r\n .string()\r\n .oneOf(Object.values(UserRole), \"Invalid role specified\"),\r\n};\r\n\r\nexport const validateEmail = async (\r\n email: string,\r\n repository: AuthRepository\r\n): Promise<AuthEntity> => {\r\n try {\r\n await schemas.email.validate(email?.trim().toLowerCase());\r\n const user = await repository.findByEmail(email);\r\n if (!user) {\r\n throw new NotFoundError(\r\n \"The email address or password is incorrect. Please retry\"\r\n );\r\n }\r\n return user;\r\n } catch (error: any) {\r\n throw new ValidationError(error.message || \"Invalid email format\");\r\n }\r\n};\r\n\r\nexport const validatePassword = async (password?: string): Promise<void> => {\r\n if (password) {\r\n try {\r\n await schemas.password.validate(password);\r\n } catch (error: any) {\r\n throw new ValidationError(error.message || \"Invalid password format\");\r\n }\r\n }\r\n};\r\n\r\nexport const validateEmailUniqueness = async (\r\n repository: AuthRepository,\r\n email: string,\r\n excludeUserId?: string\r\n): Promise<void> => {\r\n try {\r\n await schemas.email.validate(email?.trim().toLowerCase());\r\n\r\n const existingUser = await repository.findByEmail(email);\r\n\r\n if (!existingUser) return;\r\n if (existingUser.id === excludeUserId) return;\r\n\r\n throw new ValidationError(`Email ${email} is already in use.`);\r\n } catch (error: any) {\r\n if (error instanceof ValidationError) {\r\n throw error;\r\n }\r\n throw new ValidationError(\"user email validation failed\");\r\n }\r\n};\r\n\r\nexport const validateRegisterDTO = async (\r\n auth: RegisterDTO,\r\n repository: AuthRepository\r\n): Promise<void> => {\r\n const { name, email, role, password } = auth;\r\n\r\n await Promise.all([\r\n schemas.name.validate(name),\r\n schemas.role.validate(role),\r\n validateEmailUniqueness(repository, email),\r\n validatePassword(password),\r\n ]);\r\n};\r\n\r\nexport const validateLoginDTO = async (\r\n data: LoginDTO,\r\n repository: AuthRepository\r\n): Promise<AuthEntity> => {\r\n const { email, role, password } = data;\r\n\r\n if (role) {\r\n await schemas.role.validate(role);\r\n }\r\n\r\n await schemas.password.validate(password);\r\n\r\n const auth = await validateEmail(email, repository);\r\n if (!auth || !auth.password) {\r\n throw new NotFoundError(\"Invalid credentials\");\r\n }\r\n\r\n const isMatch = await bcrypt.compare(password, auth.password);\r\n if (!isMatch) {\r\n throw new ForbiddenError(\"Invalid credentials\");\r\n }\r\n\r\n return auth;\r\n};\r\n\r\nexport const validateAdminSecret = async (\r\n secretPassword?: string\r\n): Promise<void> => {\r\n if (!secretPassword) {\r\n throw new ValidationError(\"Admin password is required\");\r\n }\r\n\r\n try {\r\n const config = await createConfigInstance();\r\n\r\n if (!config.adminSecretPassword) {\r\n throw new ValidationError(\"ADMIN_SECRET_PASSWORD not found in config\");\r\n }\r\n\r\n if (parseInt(secretPassword) !== parseInt(config.adminSecretPassword)) {\r\n throw new ValidationError(\"Invalid admin password\");\r\n }\r\n } catch (error) {\r\n if (error instanceof ValidationError) {\r\n throw error;\r\n }\r\n throw new ValidationError(\"Error validating admin password\");\r\n }\r\n};\r\n","import { IBaseService, validateRepository } from \"cca-core\";\r\nimport { AuthEntity } from \"cca-entities\";\r\n\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { LoginDTO } from \"../dtos/LoginDTO\";\r\nimport { validateAdminSecret, validateLoginDTO } from \"../validators/authValidation\";\r\n\r\nexport class LoginAdminUseCase implements IBaseService {\r\n private readonly repository: AuthRepository;\r\n\r\n constructor(\r\n repository: AuthRepository\r\n ) {\r\n this.repository = repository;\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo: AuthRepository) => repo.getAll());\r\n }\r\n\r\n async execute(loginDTO: LoginDTO, adminPassword: string): Promise<string> {\r\n const auth = await validateLoginDTO(loginDTO, this.repository);\r\n\r\n await validateAdminSecret(adminPassword);\r\n\r\n return auth.user.id;\r\n }\r\n}","import { IBaseService, validateRepository } from \"cca-core\";\r\n\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { NotFoundError } from \"../../utils/Errors\";\r\n\r\n\r\nexport class LogoutUseCase implements IBaseService {\r\n private readonly repository: AuthRepository\r\n\r\n constructor(repository: AuthRepository) {\r\n this.repository = repository;\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo: AuthRepository) => repo.getAll());\r\n }\r\n\r\n async execute(authId: string): Promise<void> {\r\n try {\r\n await this.repository.logout(authId);\r\n } catch (error) {\r\n new NotFoundError(\"Auth not found\");\r\n }\r\n }\r\n}","import { IBaseService, validateRepository } from \"cca-core\";\r\nimport * as bcrypt from \"bcrypt\";\r\nimport { AdminEntity, AuthEntity, UserEntity, UserRole } from \"cca-entities\";\r\n\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { RegistrationError, UnauthorizedError } from \"../../utils/Errors\";\r\nimport { mapper } from \"../mappers/utils/mapper\";\r\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\r\nimport { validateAdminSecret, validateRegisterDTO } from \"../validators/authValidation\";\r\n\r\nexport class RegisterUseCase implements IBaseService {\r\n private readonly SALT_ROUNDS = 10;\r\n\r\n constructor(private readonly repository: AuthRepository) {}\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo) => repo.getAll());\r\n }\r\n\r\n public async execute(\r\n email: string,\r\n name: string,\r\n password: string,\r\n role: UserRole = UserRole.GUEST,\r\n adminPassword?: string\r\n ): Promise<AuthEntity | undefined> {\r\n try {\r\n const normalizedDTO = this._normalizeInput({ email, name, password, role, adminPassword });\r\n\r\n const isAdminUser = await this._validateAdminRegistration(\r\n normalizedDTO.role,\r\n normalizedDTO.adminPassword\r\n );\r\n\r\n await validateRegisterDTO(normalizedDTO, this.repository);\r\n\r\n const hashedPassword = await this._hashPassword(normalizedDTO.password);\r\n const authEntity = this._buildMappedAuthEntity(normalizedDTO, hashedPassword, isAdminUser);\r\n\r\n return this.repository.create(authEntity);\r\n } catch (error) {\r\n throw new RegistrationError(\r\n `Registration failed: ${error instanceof Error ? error.message : \"Unknown error\"}`\r\n );\r\n }\r\n }\r\n\r\n private _normalizeInput(dto: RegisterDTO): RegisterDTO {\r\n return {\r\n name: dto.name.trim(),\r\n email: dto.email.trim().toLowerCase(),\r\n password: dto.password.trim(),\r\n role: dto.role,\r\n adminPassword: dto.adminPassword?.trim()\r\n };\r\n }\r\n\r\n private async _hashPassword(password: string): Promise<string> {\r\n return bcrypt.hash(password, this.SALT_ROUNDS);\r\n }\r\n\r\n private async _validateAdminRegistration(\r\n role: UserRole,\r\n adminPassword?: string\r\n ): Promise<boolean> {\r\n if (role !== UserRole.ADMIN) return false;\r\n\r\n if (!adminPassword) {\r\n throw new UnauthorizedError(\"Admin password is required for admin registration\");\r\n }\r\n\r\n await validateAdminSecret(adminPassword);\r\n return true;\r\n }\r\n\r\n private _buildMappedAuthEntity(\r\n dto: RegisterDTO,\r\n hashedPassword: string,\r\n isAdmin: boolean\r\n ): AuthEntity {\r\n const authEntity = mapper.map(dto, RegisterDTO, AuthEntity);\r\n const userOrAdminEntity = isAdmin\r\n ? mapper.map(dto, RegisterDTO, AdminEntity)\r\n : mapper.map(dto, RegisterDTO, UserEntity);\r\n\r\n userOrAdminEntity.updatedAt = undefined as unknown as Date;\r\n\r\n if (isAdmin) {\r\n authEntity.admin = userOrAdminEntity;\r\n } else {\r\n authEntity.user = userOrAdminEntity;\r\n }\r\n\r\n authEntity.password = hashedPassword;\r\n authEntity.refreshToken = \"\";\r\n\r\n return authEntity;\r\n }\r\n}\r\n","import { createMapper } from '@automapper/core';\r\nimport { classes } from '@automapper/classes';\r\n\r\nimport { createUserMappings } from '../createUserMappings';\r\n\r\nexport const mapper = createMapper({\r\n strategyInitializer: classes(),\r\n});\r\n\r\ncreateUserMappings(mapper);\r\n","import { Mapper, createMap, forMember, mapFrom } from '@automapper/core';\r\nimport { AdminEntity, AuthEntity, UserEntity } from 'cca-entities';\r\n\r\nimport { RegisterDTO } from '../dtos/RegisterDTO';\r\nimport { UserDTO } from '../dtos/UserDTO';\r\nimport { AdminDTO } from '../dtos/AdminDTO';\r\n\r\nexport function createUserMappings(mapper: Mapper): void {\r\n createMap(\r\n mapper,\r\n RegisterDTO,\r\n AuthEntity,\r\n forMember(dest => dest.email, mapFrom(src => src.email)),\r\n forMember(dest => dest.password, mapFrom(src => src.password)),\r\n forMember(dest => dest.role, mapFrom(src => src.role)));\r\n\r\n createMap(\r\n mapper,\r\n RegisterDTO,\r\n UserEntity,\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)));\r\n\r\n createMap(\r\n mapper,\r\n RegisterDTO,\r\n AdminEntity,\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)));\r\n\r\n createMap(\r\n mapper,\r\n UserEntity,\r\n UserDTO,\r\n forMember(dest => dest.id, mapFrom(src => src.id)),\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)),\r\n forMember(dest => dest.profileImageUrl, mapFrom(src => getProfileImageUrl(src))));\r\n\r\n\r\n createMap(\r\n mapper,\r\n AdminEntity,\r\n AdminDTO,\r\n forMember(dest => dest.id, mapFrom(src => src.id)),\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)));\r\n\r\n const getProfileImageUrl = (src: UserEntity): string | undefined => {\r\n const image = src.images?.[0];\r\n if (!image) return undefined;\r\n return image.mdUrl ?? image.smUrl ?? image.lgUrl ?? image.thumbUrl ?? image.originalUrl ?? image.xlUrl;\r\n };\r\n}","import { UserRole } from \"cca-entities\";\r\n\r\nexport class RegisterDTO {\r\n email!: string;\r\n name!: string;\r\n password!: string;\r\n role!: UserRole;\r\n adminPassword?: string;\r\n}\r\n","import { AutoMap } from \"@automapper/classes\";\r\nimport { UserRole } from \"cca-entities\";\r\n\r\nexport class UserDTO {\r\n @AutoMap()\r\n id!: string;\r\n\r\n @AutoMap()\r\n name!: string;\r\n\r\n @AutoMap()\r\n email!: string;\r\n\r\n @AutoMap()\r\n role!: UserRole;\r\n\r\n @AutoMap()\r\n profileImageUrl?: string;\r\n}","import { AutoMap } from \"@automapper/classes\";\r\nimport { UserRole } from \"cca-entities\";\r\n\r\nexport class AdminDTO {\r\n @AutoMap()\r\n id!: string;\r\n\r\n @AutoMap()\r\n name!: string;\r\n\r\n @AutoMap()\r\n email!: string;\r\n\r\n @AutoMap()\r\n role!: UserRole;\r\n\r\n adminPassword!: string;\r\n}","import { IBaseService, validateRepository } from \"cca-core\";\r\nimport { JwtAuthService } from \"../../infrastructure/services/JwtAuthService\";\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { ITokenPair } from \"../../domain/interfaces/ITokenPair\";\r\n\r\nexport class RefreshTokenUseCase implements IBaseService {\r\n private readonly repository: AuthRepository;\r\n private readonly service: JwtAuthService;\r\n\r\n constructor(repository: AuthRepository, service: JwtAuthService) {\r\n this.repository = repository;\r\n this.service = service;\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo: AuthRepository) => repo.getAll());\r\n }\r\n\r\n public async execute(refreshToken: string): Promise<ITokenPair | null> {\r\n try {\r\n const decoded = await this.service.verifyRefreshToken(refreshToken);\r\n\r\n if (!decoded.userId) {\r\n return null;\r\n }\r\n\r\n let authEntity = await this.repository.findByUseAdminId(decoded.userId);\r\n\r\n if (!authEntity) {\r\n authEntity = await this.repository.findByUseAdminId(decoded.userId, true);\r\n }\r\n\r\n if (!authEntity) {\r\n return null;\r\n }\r\n\r\n const user = authEntity.role === \"admin\" ? authEntity.admin : authEntity.user;\r\n\r\n const accessToken = this.service.generateAccessToken(user, authEntity.role);\r\n const newRefreshToken = this.service.generateRefreshToken(user);\r\n\r\n await this.repository.update(authEntity.id, {\r\n refreshToken: newRefreshToken\r\n });\r\n\r\n return {\r\n accessToken,\r\n refreshToken: newRefreshToken\r\n };\r\n } catch (error) {\r\n return null;\r\n }\r\n }\r\n}","import { IBaseService } from 'cca-core';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { ITwoFactorSetupResponse } from '../../domain/interfaces/ITwoFactorSetupResponse';\r\n\r\nimport { ForbiddenError, TwoFactorError } from '../../utils/Errors';\r\n\r\nexport class TwoFactorSetupUseCase implements IBaseService {\r\n private twoFactorService: TwoFactorService;\r\n private authRepository: AuthRepository;\r\n private isInitialized = false;\r\n\r\n constructor(twoFactorService: TwoFactorService, authRepository: AuthRepository) {\r\n this.twoFactorService = twoFactorService;\r\n this.authRepository = authRepository;\r\n }\r\n async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n\r\n await Promise.all([\r\n this.twoFactorService.initialize()\r\n ]);\r\n\r\n this.isInitialized = true;\r\n }\r\n\r\n async execute(userId: string): Promise<ITwoFactorSetupResponse> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n\r\n const user = await this.authRepository.findByUserId(userId);\r\n\r\n if (!user) {\r\n throw new ForbiddenError('User not found');\r\n }\r\n\r\n if (user.twoFactorEnabled) {\r\n throw new TwoFactorError('Two-factor authentication is already enabled');\r\n }\r\n\r\n const { secret, otpAuthUrl } = this.twoFactorService.generateSecret(user.email);\r\n const qrCodeUrl = await this.twoFactorService.generateQRCode(otpAuthUrl);\r\n\r\n await this.authRepository.updateTwoFactorSecret(userId, secret);\r\n\r\n return { qrCodeUrl };\r\n }\r\n}","import { IBaseService, validateRepository } from 'cca-core';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { ITwoFactorEnable } from '../../domain/interfaces/ITwoFactorEnable';\r\nimport { TwoFactorError } from '../../utils/Errors';\r\nimport { AuthEntity } from 'cca-entities';\r\n\r\nexport class TwoFactorEnableUseCase implements IBaseService{\r\n private twoFactorService: TwoFactorService;\r\n private authRepository: AuthRepository;\r\n private isInitialized = false;\r\n\r\n constructor(twoFactorService: TwoFactorService, authRepository: AuthRepository) {\r\n this.twoFactorService = twoFactorService;\r\n this.authRepository = authRepository;\r\n \r\n }\r\n async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n \r\n await Promise.all([\r\n this.twoFactorService.initialize(),\r\n validateRepository(this.authRepository, repo => repo.getAll())\r\n ]);\r\n \r\n this.isInitialized = true;\r\n }\r\n\r\n async execute( dto: ITwoFactorEnable): Promise<void> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n \r\n const { token, userId } = dto;\r\n \r\n if (!token) {\r\n throw new TwoFactorError('Token is required');\r\n }\r\n \r\n const auth: AuthEntity | null = await this.authRepository.findByUserId(userId); \r\n \r\n if (!auth || !auth.twoFactorSecret) {\r\n throw new TwoFactorError('Please set up two-factor authentication first');\r\n }\r\n \r\n if (auth.twoFactorEnabled) {\r\n throw new TwoFactorError('Two-factor authentication is already enabled');\r\n }\r\n \r\n const isValid = this.twoFactorService.verifyToken(token, auth.twoFactorSecret);\r\n \r\n if (!isValid) {\r\n throw new TwoFactorError('Invalid verification code');\r\n }\r\n \r\n await this.authRepository.enableTwoFactor(auth);\r\n }\r\n}","import { IBaseService, validateRepository } from 'cca-core';\r\nimport { AdminEntity, AuthEntity, UserEntity } from 'cca-entities';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { JwtAuthService } from '../../infrastructure/services/JwtAuthService';\r\nimport { ITwoFactorVerify } from '../../domain/interfaces/ITwoFactorVerify';\r\nimport { ITokenPair } from '../../domain/interfaces/ITokenPair';\r\nimport { TwoFactorError } from '../../utils/Errors';\r\nimport { AdminDTO } from '../dtos/AdminDTO';\r\nimport { UserDTO } from '../dtos/UserDTO';\r\nimport { mapper } from '../mappers/utils/mapper';\r\n\r\nexport class TwoFactorVerifyUseCase implements IBaseService {\r\n private isInitialized = false;\r\n\r\n constructor(\r\n private readonly twoFactorService: TwoFactorService,\r\n private readonly authRepository: AuthRepository,\r\n private readonly jwtService: JwtAuthService\r\n ) { }\r\n\r\n public async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n await Promise.all([\r\n this.twoFactorService.initialize(),\r\n this.jwtService.initialize(),\r\n validateRepository(this.authRepository, repo => repo.getAll())\r\n ]);\r\n this.isInitialized = true;\r\n }\r\n\r\n public async execute(dto: ITwoFactorVerify): Promise<{ token: string; refreshToken: string; data?: AdminDTO | UserDTO } | null> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n\r\n const { userId, token } = dto;\r\n if (!userId || !token) {\r\n throw new TwoFactorError('User ID and token are required.');\r\n }\r\n\r\n const auth: AuthEntity | null = await this.authRepository.findByUserId(userId);\r\n if (!auth || !auth.twoFactorSecret || !auth.twoFactorEnabled) {\r\n throw new TwoFactorError('Invalid request.');\r\n }\r\n\r\n const isValid = this.twoFactorService.verifyToken(token, auth.twoFactorSecret);\r\n if (!isValid) {\r\n throw new TwoFactorError('Invalid verification code.');\r\n }\r\n\r\n const tokenPair: ITokenPair = this.generateTokens(auth);\r\n await this.updateUserStatus(auth);\r\n await this.updateUserRefreshToken(auth, tokenPair.refreshToken);\r\n\r\n if (auth.admin) {\r\n return {\r\n token: tokenPair.accessToken,\r\n refreshToken: tokenPair.refreshToken,\r\n data: this.mapAdminToDTO(auth.admin)\r\n };\r\n }\r\n\r\n if (auth.user) {\r\n return {\r\n token: tokenPair.accessToken,\r\n refreshToken: tokenPair.refreshToken,\r\n data: this.mapUserToDTO(auth.user)\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private mapAdminToDTO(admin: AdminEntity): AdminDTO {\r\n return mapper.map(admin, AdminEntity, AdminDTO);\r\n }\r\n\r\n private mapUserToDTO(user: UserEntity): UserDTO {\r\n return mapper.map(user, UserEntity, UserDTO);\r\n }\r\n\r\n private async updateUserStatus(auth: AuthEntity): Promise<void> {\r\n auth.user.lastLoginAt = new Date();\r\n auth.user.isActive = true;\r\n await this.authRepository.update(auth.id, auth);\r\n }\r\n\r\n private async updateUserRefreshToken(auth: AuthEntity, refreshToken: string): Promise<void> {\r\n auth.refreshToken = refreshToken;\r\n await this.authRepository.update(auth.id, { refreshToken });\r\n }\r\n\r\n private generateTokens(auth: AuthEntity): ITokenPair {\r\n return {\r\n accessToken: this.jwtService.generateAccessToken(auth.user, auth.role),\r\n refreshToken: this.jwtService.generateRefreshToken(auth.user)\r\n };\r\n }\r\n}\r\n","import { IBaseService, validateRepository } from 'cca-core';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { ITwoFactorEnable } from '../../domain/interfaces/ITwoFactorEnable';\r\n\r\nimport { TwoFactorError } from '../../utils/Errors';\r\n\r\nexport class TwoFactorDisableUseCase implements IBaseService{\r\n private twoFactorService: TwoFactorService;\r\n private authRepository: AuthRepository;\r\n private isInitialized = false;\r\n\r\n constructor(twoFactorService: TwoFactorService, authRepository: AuthRepository) {\r\n this.twoFactorService = twoFactorService;\r\n this.authRepository = authRepository;\r\n }\r\n async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n \r\n await Promise.all([\r\n this.twoFactorService.initialize(),\r\n validateRepository(this.authRepository, repo => repo.getAll())\r\n ]);\r\n4\r\n this.isInitialized = true;\r\n }\r\n\r\n async execute(userId: string, dto: ITwoFactorEnable): Promise<void> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n \r\n const { token } = dto; \r\n \r\n const user = await this.authRepository.findByUserId(userId); \r\n \r\n if (!user || !user.twoFactorSecret || !user.twoFactorEnabled) {\r\n throw new TwoFactorError('Two-factor authentication is not enabled');\r\n }\r\n \r\n const isValid = this.twoFactorService.verifyToken(token, user.twoFactorSecret);\r\n \r\n if (!isValid) {\r\n throw new TwoFactorError('Invalid verification code');\r\n }\r\n \r\n await this.authRepository.disableTwoFactor(user);\r\n }\r\n}","export const HTTP_STATUS = {\r\n OK: 200,\r\n CREATED: 201,\r\n} as const;\r\n\r\nexport const AUTH_STATUS = {\r\n BASIC_AUTH: \"basic_auth\",\r\n NEEDS_SETUP: \"needs_setup\",\r\n PENDING_VERIFICATION: \"pending_verification\",\r\n FULL_AUTH: \"full_auth\",\r\n LOGGED_OUT:\"logged_out\",\r\n REGISTERED:\"registered\",\r\n TOKEN_REFRESHED:\"token_refreshed\"\r\n} as const;\r\n\r\nexport const MESSAGES = {\r\n LOGIN_SUCCESS: \"Login successful\",\r\n ADMIN_LOGIN_SUCCESS: \"Admin login successful\",\r\n LOGOUT_SUCCESS: \"Logged out successfully\",\r\n REGISTER_SUCCESS: \"User registered successfully\",\r\n TOKEN_REFRESH_SUCCESS: \"Token refreshed successfully\",\r\n TWO_FA_SETUP_SUCCESS: \"Two-factor authentication setup initiated\",\r\n TWO_FA_ENABLE_SUCCESS: \"Two-factor authentication enabled\",\r\n TWO_FA_VERIFY_SUCCESS: \"Two-factor authentication verified successfully\",\r\n TWO_FA_DISABLE_SUCCESS: \"Two-factor authentication disabled\",\r\n} as const;","import { NextFunction, Request, Response } from \"express\";\r\n\r\nimport { LoginDTO } from \"../../application/dtos/LoginDTO\";\r\nimport { RegisterDTO } from \"../../application/dtos/RegisterDTO\";\r\n\r\nimport { RegisterUseCase } from \"../../application/useCase/RegisterUseCase\";\r\nimport { LoginUseCase } from \"../../application/useCase/LoginUseCase\";\r\nimport { LoginAdminUseCase } from \"../../application/useCase/LoginAdminUseCase\";\r\nimport { LogoutUseCase } from \"../../application/useCase/LogoutUseCase\";\r\nimport { RefreshTokenUseCase } from \"../../application/useCase/RefreshTokenUseCase\";\r\nimport { TwoFactorSetupUseCase } from \"../../application/useCase/TwoFactorSetupUseCase\";\r\nimport { TwoFactorEnableUseCase } from \"../../application/useCase/TwoFactorEnableUseCase\";\r\nimport { TwoFactorVerifyUseCase } from \"../../application/useCase/TwoFactorVerifyUseCase\";\r\nimport { TwoFactorDisableUseCase } from \"../../application/useCase/TwoFactorDisableUseCase\";\r\n\r\nimport { IRefreshTokenRequest } from \"../../domain/interfaces/IRefreshTokenRequest\";\r\nimport { ITwoFactorEnable } from \"../../domain/interfaces/ITwoFactorEnable\";\r\nimport { ITwoFactorVerify } from \"../../domain/interfaces/ITwoFactorVerify\";\r\nimport { ForbiddenError } from \"../../utils/Errors\";\r\nimport { ApiResponse, AuthData } from \"../../domain/interfaces/ApiResponse\";\r\nimport { AUTH_STATUS, HTTP_STATUS, MESSAGES } from \"../constants/constants\";\r\n\r\nexport class AuthController {\r\n private readonly loginUseCase: LoginUseCase;\r\n private readonly adminLoginUseCase: LoginAdminUseCase;\r\n private readonly logoutUseCase: LogoutUseCase;\r\n private readonly registerUseCase: RegisterUseCase;\r\n private readonly refreshTokenUseCase: RefreshTokenUseCase;\r\n private readonly twoFactorSetupUseCase: TwoFactorSetupUseCase;\r\n private readonly twoFactorEnableUseCase: TwoFactorEnableUseCase;\r\n private readonly twoFactorVerifyUseCase: TwoFactorVerifyUseCase;\r\n private readonly twoFactorDisableUseCase: TwoFactorDisableUseCase;\r\n\r\n constructor(\r\n loginUseCase: LoginUseCase,\r\n adminLoginUseCase: LoginAdminUseCase,\r\n logoutUseCase: LogoutUseCase,\r\n registerUseCase: RegisterUseCase,\r\n refreshTokenUseCase: RefreshTokenUseCase,\r\n twoFactorSetupUseCase: TwoFactorSetupUseCase,\r\n twoFactorEnableUseCase: TwoFactorEnableUseCase,\r\n twoFactorVerifyUseCase: TwoFactorVerifyUseCase,\r\n twoFactorDisableUseCase: TwoFactorDisableUseCase\r\n ) {\r\n this.loginUseCase = loginUseCase;\r\n this.adminLoginUseCase = adminLoginUseCase;\r\n this.logoutUseCase = logoutUseCase;\r\n this.registerUseCase = registerUseCase;\r\n this.refreshTokenUseCase = refreshTokenUseCase;\r\n this.twoFactorSetupUseCase = twoFactorSetupUseCase;\r\n this.twoFactorEnableUseCase = twoFactorEnableUseCase;\r\n this.twoFactorVerifyUseCase = twoFactorVerifyUseCase;\r\n this.twoFactorDisableUseCase = twoFactorDisableUseCase;\r\n }\r\n\r\n private createResponse<T>(\r\n message: string,\r\n data?: T,\r\n meta?: Record<string, any>\r\n ): ApiResponse<T> {\r\n return {\r\n success: true,\r\n message,\r\n data,\r\n meta: {\r\n timestamp: new Date().toISOString(),\r\n ...meta,\r\n },\r\n };\r\n }\r\n\r\n private createAuthData(\r\n hasAccessToken: boolean,\r\n enabled: boolean,\r\n status: string,\r\n verified?: boolean\r\n ): AuthData {\r\n return {\r\n hasAccessToken,\r\n enabled,\r\n status,\r\n ...(verified !== undefined && { verified }),\r\n };\r\n }\r\n\r\n private sendResponse<T>(\r\n res: Response,\r\n statusCode: number,\r\n message: string,\r\n data?: T,\r\n meta?: Record<string, any>\r\n ): void {\r\n const response = this.createResponse(message, data, meta);\r\n res.status(statusCode).json(response);\r\n }\r\n\r\n login = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const loginDTO: LoginDTO = req.body;\r\n const result = await this.loginUseCase.execute(loginDTO);\r\n\r\n const twoFactorEnabled = result.enabled ?? false;\r\n\r\n const loginData = {\r\n accessToken: result.accessToken,\r\n userId: result.id,\r\n expiresAt: result.expiresAt,\r\n auth: this.createAuthData(\r\n true, // hasAccessToken\r\n twoFactorEnabled, // enable (2FA enabled status)\r\n twoFactorEnabled ? AUTH_STATUS.PENDING_VERIFICATION : AUTH_STATUS.BASIC_AUTH,\r\n false // verified - always false for basic login\r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.LOGIN_SUCCESS, loginData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n adminLogin = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const { adminPassword, ...loginDTO }: LoginDTO = req.body;\r\n\r\n if (!adminPassword) {\r\n throw new ForbiddenError(\"Admin password is required\");\r\n }\r\n\r\n const result = await this.adminLoginUseCase.execute(loginDTO, adminPassword);\r\n\r\n const adminLoginData = {\r\n message: result, \r\n auth: this.createAuthData(\r\n true, \r\n false, \r\n AUTH_STATUS.BASIC_AUTH,\r\n false \r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.CREATED, MESSAGES.ADMIN_LOGIN_SUCCESS, adminLoginData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n logout = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n await this.logoutUseCase.execute(req.body.id);\r\n\r\n const logoutData = {\r\n auth: this.createAuthData(\r\n false, \r\n false,\r\n AUTH_STATUS.LOGGED_OUT,\r\n false \r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.LOGOUT_SUCCESS, logoutData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n register = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const { email, name, password, role, adminPassword }: RegisterDTO = req.body;\r\n\r\n await this.registerUseCase.execute(email, name, password, role, adminPassword);\r\n\r\n const registerData = {\r\n auth: this.createAuthData(\r\n false, \r\n false, \r\n AUTH_STATUS.REGISTERED,\r\n false \r\n ),\r\n };\r\n\r\n this.sendResponse(\r\n res,\r\n HTTP_STATUS.OK,\r\n MESSAGES.REGISTER_SUCCESS,\r\n registerData,\r\n { status: true }\r\n );\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n refreshToken = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const { refreshToken }: IRefreshTokenRequest = req.body;\r\n\r\n const result = await this.refreshTokenUseCase.execute(refreshToken);\r\n\r\n if (!result) {\r\n throw new Error(\"Failed to refresh token\");\r\n }\r\n\r\n const refreshData = {\r\n accessToken: result.accessToken,\r\n refreshToken: result.refreshToken,\r\n auth: this.createAuthData(\r\n true, \r\n false, \r\n AUTH_STATUS.BASIC_AUTH,\r\n false \r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TOKEN_REFRESH_SUCCESS, refreshData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n setup2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n if (!req.auth?.id) {\r\n throw new ForbiddenError(\"User authentication required\");\r\n }\r\n\r\n const result = await this.twoFactorSetupUseCase.execute(req.auth.id);\r\n\r\n const setupData = {\r\n qrCode: result.qrCodeUrl,\r\n auth: this.createAuthData(true, false, AUTH_STATUS.NEEDS_SETUP),\r\n };\r\n\r\n const meta = {\r\n nextStep: \"Scan the QR code and enter your first code to verify\",\r\n redirectTo: \"/2fa-enable\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_SETUP_SUCCESS, setupData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n enable2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const dto: ITwoFactorEnable = { ...req.body, userId: req.auth?.id };\r\n await this.twoFactorEnableUseCase.execute(dto);\r\n\r\n const enableData = {\r\n enabledAt: new Date().toISOString(),\r\n auth: this.createAuthData(true, true, AUTH_STATUS.PENDING_VERIFICATION),\r\n };\r\n\r\n const meta = {\r\n nextStep: \"Proceed to verify with a valid 2FA token\",\r\n redirectTo: \"/verify-2fa\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_ENABLE_SUCCESS, enableData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n verify2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const dto: ITwoFactorVerify = req.body;\r\n const result = await this.twoFactorVerifyUseCase.execute(dto);\r\n\r\n const verifyData = {\r\n token: result?.token,\r\n refreshToken: result?.refreshToken,\r\n user: {\r\n id: result?.data?.id,\r\n email: result?.data?.email,\r\n name: result?.data?.name,\r\n role: result?.data?.role,\r\n },\r\n auth: this.createAuthData(true, true, AUTH_STATUS.FULL_AUTH, true),\r\n };\r\n\r\n const meta = {\r\n recommendation: \"You're fully authenticated\",\r\n redirectTo: \"/\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_VERIFY_SUCCESS, verifyData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n disable2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const userId = req.auth!.id;\r\n const dto: ITwoFactorEnable = req.body;\r\n\r\n await this.twoFactorDisableUseCase.execute(userId, dto);\r\n\r\n const disableData = {\r\n disabledAt: new Date().toISOString(),\r\n auth: this.createAuthData(true, false, AUTH_STATUS.BASIC_AUTH, false),\r\n };\r\n\r\n const meta = {\r\n securityNote: \"Account now relies only on password. Re-enable 2FA for better security.\",\r\n redirectTo: \"/login\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_DISABLE_SUCCESS, disableData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n}","import { NextFunction, Request, Response } from 'express';\r\nimport { JwtAuthService } from '../../infrastructure/services/JwtAuthService';\r\n\r\nexport class RequireComplete2FA {\r\n private readonly jwtService: JwtAuthService;\r\n\r\n constructor(jwtService: JwtAuthService) {\r\n this.jwtService = jwtService;\r\n }\r\n\r\n public async execute(req: Request, res: Response, next: NextFunction) {\r\n try {\r\n const token = req.headers.authorization?.split(' ')[1];\r\n\r\n if (!token) {\r\n return res.status(401).json({ message: 'Authentication required' });\r\n }\r\n\r\n const decoded = await this.jwtService.verifyAccessToken(token);\r\n\r\n if (!decoded.twoFactorAuthenticated) {\r\n return res.status(403).json({\r\n message: 'Two-factor authentication required',\r\n code: 'REQUIRE_2FA',\r\n userId: decoded.id\r\n });\r\n }\r\n\r\n req.auth = { ...decoded, twoFactorAuthenticated: true };\r\n next();\r\n } catch (error) {\r\n return res.status(401).json({ message: 'Invalid or expired token' });\r\n }\r\n }\r\n}","import { BaseRepository, IExtendedBaseRepository } from \"cca-core\";\r\nimport { AuthEntity } from \"cca-entities\";\r\nimport { Repository } from \"typeorm\";\r\nimport { NotFoundError } from \"../../utils/Errors\";\r\n\r\nexport class AuthRepository\r\n extends BaseRepository<AuthEntity>\r\n implements IExtendedBaseRepository<AuthEntity> {\r\n constructor(repository: Repository<AuthEntity>) {\r\n super(repository);\r\n }\r\n\r\n async findByEmail(email: string): Promise<AuthEntity | null> {\r\n const query = this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .addSelect(\"auth.password\")\r\n .where(\"auth.email = :email\", { email });\r\n\r\n return await query.getOne();\r\n }\r\n\r\n async create(entity: Omit<AuthEntity, \"createdAt\">): Promise<AuthEntity> {\r\n return super.create(entity);\r\n }\r\n\r\n async findByUserId(userId: string): Promise<AuthEntity | null> {\r\n const query = this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .addSelect(\"auth.twoFactorSecret\")\r\n .where(\"user.id = :userId\", { userId });\r\n\r\n return await query.getOne();;\r\n }\r\n\r\n async findByUseAdminId(userId: string, isAdmin: boolean = false): Promise<AuthEntity | null> {\r\n const query = this.repository\r\n .createQueryBuilder(\"auth\")\r\n .addSelect(\"auth.twoFactorSecret\");\r\n\r\n if (isAdmin) {\r\n query.leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .where(\"admin.id = :userId\", { userId });\r\n } else {\r\n query.leftJoinAndSelect(\"auth.user\", \"user\")\r\n .where(\"user.id = :userId\", { userId });\r\n }\r\n\r\n return await query.getOne();\r\n }\r\n\r\n async logout(userId: string): Promise<void> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n auth.refreshToken = \"\";\r\n auth.user.isActive = false;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async updateTwoFactorSecret(userId: string, secret: string): Promise<void> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n auth.twoFactorSecret = secret;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async enableTwoFactor(auth: AuthEntity): Promise<void> {\r\n\r\n auth.twoFactorEnabled = true;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async disableTwoFactor(auth: AuthEntity): Promise<void> {\r\n\r\n auth.twoFactorEnabled = false;\r\n auth.twoFactorSecret = null;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async isTwoFactorEnabled(userId: string): Promise<boolean> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n return !!auth.twoFactorEnabled;\r\n }\r\n\r\n async getTwoFactorSecret(userId: string): Promise<string | null> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n return auth.twoFactorSecret;\r\n }\r\n}\r\n","import * as jwt from \"jsonwebtoken\";\r\nimport { Secret, SignOptions } from \"jsonwebtoken\";\r\nimport * as bcrypt from \"bcrypt\";\r\nimport { IBaseService, validateRepository } from \"cca-core\";\r\nimport { AuthEntity, UserEntity, UserRole } from \"cca-entities\";\r\n\r\nimport { IJwtConfig } from \"../../domain/interfaces/IJwtConfig\";\r\nimport { IAuthService } from \"../../domain/interfaces/IAuthService\";\r\nimport { IDecodedToken } from \"../../domain/interfaces/IDecodedToken\";\r\n\r\nimport {\r\n ForbiddenError,\r\n JwtError,\r\n NotFoundError,\r\n UnauthorizedError,\r\n} from \"../../utils/Errors\";\r\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nimport { createConfigInstance } from \"../../application/service/utils/configInstance\";\r\nimport { log } from \"console\";\r\n\r\nexport class JwtAuthService implements IBaseService, IAuthService {\r\n private jwtConfig: IJwtConfig | undefined;\r\n\r\n constructor(private readonly repository: AuthRepository, config?: IJwtConfig) {\r\n this.loadConfig(config);\r\n }\r\n\r\n private async loadConfig(config?: IJwtConfig) {\r\n const configData = await createConfigInstance();\r\n\r\n this.jwtConfig = {\r\n accessTokenSecret: configData.accessTokenSecret,\r\n refreshTokenSecret: configData.refreshTokenSecret,\r\n accessTokenExpiry: parseInt(configData.accessTokenExpiry, 10),\r\n refreshTokenExpiry: parseInt(configData.refreshTokenExpiry, 10),\r\n ...config,\r\n };\r\n\r\n this.validateConfiguration();\r\n }\r\n\r\n async initialize(): Promise<void> {\r\n await validateRepository(this.repository, repo => repo.getAll());\r\n }\r\n\r\n private validateConfiguration(): void {\r\n if (!this.jwtConfig?.accessTokenSecret || !this.jwtConfig?.refreshTokenSecret) {\r\n throw new JwtError(\"JWT secrets required in config\");\r\n }\r\n }\r\n\r\n async validateUser(email: string, password: string): Promise<AuthEntity | null> {\r\n const user = await this.repository.findByEmail(email);\r\n if (!user) {\r\n throw new NotFoundError(\"Invalid credentials\");\r\n }\r\n\r\n const validPassword = await bcrypt.compare(password, user.password);\r\n if (!validPassword) {\r\n throw new ForbiddenError(\"Invalid credentials\");\r\n }\r\n\r\n return user;\r\n }\r\n\r\n private verifyJwtConfig() {\r\n if (!this.jwtConfig) throw new JwtError(\"JWT config not loaded\");\r\n }\r\n\r\n generateAccessToken(user: UserEntity, role : UserRole): string {\r\n this.verifyJwtConfig();\r\n return jwt.sign(\r\n { userId: user.id, email: user.email, role: role },\r\n this.jwtConfig!.accessTokenSecret as Secret,\r\n { expiresIn: this.jwtConfig!.accessTokenExpiry }\r\n );\r\n }\r\n\r\n generateRefreshToken(user: UserEntity): string {\r\n this.verifyJwtConfig();\r\n return jwt.sign(\r\n { userId: user.id },\r\n this.jwtConfig!.refreshTokenSecret as Secret,\r\n { expiresIn: this.jwtConfig!.refreshTokenExpiry }\r\n );\r\n }\r\n\r\n async verifyToken(token: string, secret: string): Promise<IDecodedToken> {\r\n try {\r\n console.log(\"Verifying token:\", token);\r\n console.log(\"Using secret:\", secret);\r\n \r\n return jwt.verify(token, secret) as IDecodedToken;\r\n } catch(error) {\r\n console.error(\"Error verifying token:\", error);\r\n throw new UnauthorizedError();\r\n }\r\n }\r\n\r\n async verifyAccessToken(token: string): Promise<IDecodedToken> {\r\n this.verifyJwtConfig();\r\n return this.verifyToken(token, this.jwtConfig!.accessTokenSecret);\r\n }\r\n\r\n async verifyRefreshToken(token: string): Promise<IDecodedToken> {\r\n this.verifyJwtConfig();\r\n return this.verifyToken(token, this.jwtConfig!.refreshTokenSecret);\r\n }\r\n}\r\n","import * as speakeasy from 'speakeasy';\r\nimport * as QRCode from 'qrcode';\r\nimport { IBaseService } from 'cca-core';\r\n\r\nimport { IConfig } from '../../domain/interfaces/configTypes';\r\nimport { TwoFactorError } from '../../utils/Errors';\r\n\r\nexport class TwoFactorService implements IBaseService {\r\n private readonly config: IConfig;\r\n private initialized: boolean = false;\r\n private readonly twoFactorConfig: {\r\n tokenWindow: number;\r\n secretLength: number;\r\n qrCodeOptions: QRCode.QRCodeToDataURLOptions;\r\n };\r\n\r\n constructor(config: IConfig) {\r\n this.config = config;\r\n \r\n this.twoFactorConfig = {\r\n tokenWindow: parseInt(config.tokenWindow) ?? 1,\r\n secretLength: parseInt(config.secretLength) ?? 20,\r\n qrCodeOptions: {\r\n errorCorrectionLevel: 'M',\r\n margin: 4,\r\n scale: 4,\r\n color: {\r\n dark: '#000000',\r\n light: '#ffffff'\r\n }\r\n }\r\n };\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n if (this.initialized) return;\r\n\r\n try {\r\n this.validateConfiguration();\r\n this.initialized = true;\r\n } catch (error) {\r\n console.error('TwoFactorService initialization failed:', error);\r\n throw new TwoFactorError('Failed to initialize TwoFactorService');\r\n }\r\n }\r\n\r\n private validateConfiguration(): void {\r\n if (!this.config.app_name?.trim()) {\r\n throw new TwoFactorError('Application name (appName) is required in configuration');\r\n }\r\n\r\n if (this.twoFactorConfig.secretLength < 16) {\r\n throw new TwoFactorError('Secret length must be at least 16 characters');\r\n }\r\n\r\n if (this.twoFactorConfig.tokenWindow < 0 || this.twoFactorConfig.tokenWindow > 5) {\r\n throw new TwoFactorError('Token verification window must be between 0 and 5');\r\n }\r\n }\r\n\r\n private ensureInitialized(): void {\r\n if (!this.initialized) {\r\n throw new TwoFactorError('TwoFactorService must be initialized before use');\r\n }\r\n }\r\n\r\n public generateSecret(email: string): { secret: string; otpAuthUrl: string } {\r\n this.ensureInitialized();\r\n\r\n try {\r\n const secretObj = speakeasy.generateSecret({\r\n length: this.twoFactorConfig.secretLength,\r\n name: `${this.config.app_name}:${email}`,\r\n issuer: this.config.app_name\r\n });\r\n \r\n return {\r\n secret: secretObj.base32,\r\n otpAuthUrl: secretObj.otpauth_url || ''\r\n };\r\n } catch (error) {\r\n console.error('Error generating 2FA secret:', error);\r\n throw new TwoFactorError('Failed to generate 2FA secret');\r\n }\r\n }\r\n\r\n public async generateQRCode(otpAuthUrl: string): Promise<string> {\r\n this.ensureInitialized();\r\n\r\n try {\r\n return await QRCode.toDataURL(otpAuthUrl, this.twoFactorConfig.qrCodeOptions);\r\n } catch (error) {\r\n console.error('QR code generation failed:', error);\r\n throw new TwoFactorError('Failed to generate QR code');\r\n }\r\n }\r\n\r\n public verifyToken(token: string, secret: string): boolean {\r\n this.ensureInitialized();\r\n\r\n try {\r\n return speakeasy.totp.verify({\r\n secret,\r\n encoding: 'base32',\r\n token,\r\n window: this.twoFactorConfig.tokenWindow\r\n });\r\n } catch (error) {\r\n console.error('Token verification failed:', error);\r\n throw new TwoFactorError('Failed to verify 2FA token');\r\n }\r\n }\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA6B;;;ACAtB,IAAM,YAAN,MAAM,kBAAiB,MAAM;AAAA,EAClC,YACS,SACA,aAAqB,KACrB,OAAe,YACtB;AACA,UAAM,OAAO;AAJN;AACA;AACA;AAGP,WAAO,eAAe,MAAM,WAAW,SAAS;AAChD,UAAM,kBAAkB,IAAI;AAAA,EAC9B;AACF;AAVoC;AAA7B,IAAM,WAAN;AAYA,IAAM,mBAAN,MAAM,yBAAwB,SAAS;AAAA,EAC5C,YAAY,SAAiB;AAC3B,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAL8C;AAAvC,IAAM,kBAAN;AAOA,IAAM,2BAAN,MAAM,iCAAgC,SAAS;AAAA,EACpD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AALsD;AAA/C,IAAM,0BAAN;AAOA,IAAM,iBAAN,MAAM,uBAAsB,SAAS;AAAA,EAC1C,YAAY,SAAiB;AAC3B,UAAM,SAAS,KAAK,mBAAmB;AAAA,EACzC;AACF;AAJ4C;AAArC,IAAM,gBAAN;AAMA,IAAM,kBAAN,MAAM,wBAAuB,SAAS;AAAA,EAC3C,YAAY,UAAkB,oBAAoB;AAChD,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAL6C;AAAtC,IAAM,iBAAN;AAOA,IAAM,qBAAN,MAAM,2BAA0B,SAAS;AAAA,EAC9C,YAAY,UAAkB,uBAAuB;AACnD,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AALgD;AAAzC,IAAM,oBAAN;AAOA,IAAM,YAAN,MAAM,kBAAiB,SAAS;AAAA,EACrC,YAAY,SAAiB;AAC3B,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AALuC;AAAhC,IAAM,WAAN;AAOA,IAAM,qBAAN,MAAM,2BAA0B,SAAS;AAAA,EAC9C,YAAY,SAAiB;AAC3B,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AALgD;AAAzC,IAAM,oBAAN;AAOA,IAAM,kBAAN,MAAM,wBAAuB,SAAS;AAAA,EAC3C,YAAY,SAAiB;AAC3B,UAAM,SAAS,GAAG;AAClB,SAAK,OAAO;AAAA,EACd;AACF;AAL6C;AAAtC,IAAM,iBAAN;;;ADxDA,IAAM,iBAAN,MAAM,uBAAsB,2BAAa;AAAA,EAI5C,gBAAgB,QAA4B;AACxC,SAAK,eAAe;AAAA,EACxB;AAAA,EAEA,UAAU,KAAoB;AAC1B,SAAK,SAAS,EAAE,GAAG,IAAI;AACvB,SAAK,KAAK,mBAAmB,KAAK,MAAM;AAAA,EAC5C;AAAA,EAEA,YAAiC;AAC7B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,aAA+B;AACjC,QAAI,CAAC,KAAK,cAAc;AACpB,YAAM,IAAI,wBAAwB,uBAAuB;AAAA,IAC7D;AACA,QAAI;AACA,YAAM,SAAS,MAAM,KAAK,aAAa;AACvC,WAAK,UAAU,MAAM;AACrB,aAAO;AAAA,IACX,SAAS,OAAO;AACZ,YAAM,IAAI,wBAAwB,6BAA6B;AAAA,IACnE;AAAA,EACJ;AACJ;AA7BgD;AAAzC,IAAM,gBAAN;AA+BA,IAAM,gBAAgB,IAAI,cAAc;;;AEhCxC,IAAM,aAAa,wBAAC,iBAAqC;AAC9D,gBAAc,gBAAgB,YAAY;AAC5C,GAF0B;AAInB,IAAM,uBAAuB,mCAA8B;AAChE,SAAO,cAAc,UAAU,KAAM,MAAM,cAAc,WAAW;AACtE,GAFoC;;;ACPpC,IAAAA,oBAA4C;AAC5C,IAAAC,uBAA2B;;;ACD3B,sBAAiD;AACjD,wBAA0B;;;ACD1B,UAAqB;AACrB,0BAAqC;AACrC,oBAAmB;AAanB,IAAM,UAAU;AAAA,EACd,IAAQ,WAAO,EAAE,KAAK,wBAAwB;AAAA,EAC9C,OACG,WAAO,EACP,MAAM,sBAAsB,EAC5B,IAAI,KAAK,oCAAoC;AAAA,EAChD,MACG,WAAO,EACP,SAAS,kBAAkB,EAC3B,IAAI,GAAG,yCAAyC,EAChD,IAAI,IAAI,kCAAkC,EAC1C,QAAQ,iBAAiB,2CAA2C;AAAA,EACvE,UACG,WAAO,EACP,SAAS,mBAAmB,EAC5B,IAAI,GAAG,oBAAoB,EAC3B,IAAI,KAAK,mBAAmB,EAC5B;AAAA,IACC;AAAA,IACA;AAAA,EACF;AAAA,EACF,MACG,WAAO,EACP,MAAM,OAAO,OAAO,4BAAQ,GAAG,wBAAwB;AAC5D;AAEO,IAAM,gBAAgB,8BAC3B,OACA,eACwB;AACxB,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,OAAO,KAAK,EAAE,YAAY,CAAC;AACxD,UAAM,OAAO,MAAM,WAAW,YAAY,KAAK;AAC/C,QAAI,CAAC,MAAM;AACT,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,SAAS,OAAY;AACnB,UAAM,IAAI,gBAAgB,MAAM,WAAW,sBAAsB;AAAA,EACnE;AACF,GAhB6B;AAkBtB,IAAM,mBAAmB,8BAAO,aAAqC;AAC1E,MAAI,UAAU;AACZ,QAAI;AACF,YAAM,QAAQ,SAAS,SAAS,QAAQ;AAAA,IAC1C,SAAS,OAAY;AACnB,YAAM,IAAI,gBAAgB,MAAM,WAAW,yBAAyB;AAAA,IACtE;AAAA,EACF;AACF,GARgC;AAUzB,IAAM,0BAA0B,8BACrC,YACA,OACA,kBACkB;AAClB,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,OAAO,KAAK,EAAE,YAAY,CAAC;AAExD,UAAM,eAAe,MAAM,WAAW,YAAY,KAAK;AAEvD,QAAI,CAAC,aAAc;AACnB,QAAI,aAAa,OAAO,cAAe;AAEvC,UAAM,IAAI,gBAAgB,SAAS,KAAK,qBAAqB;AAAA,EAC/D,SAAS,OAAY;AACnB,QAAI,iBAAiB,iBAAiB;AACpC,YAAM;AAAA,IACR;AACA,UAAM,IAAI,gBAAgB,8BAA8B;AAAA,EAC1D;AACF,GApBuC;AAsBhC,IAAM,sBAAsB,8BACjC,MACA,eACkB;AAClB,QAAM,EAAE,MAAM,OAAO,MAAM,SAAS,IAAI;AAExC,QAAM,QAAQ,IAAI;AAAA,IAChB,QAAQ,KAAK,SAAS,IAAI;AAAA,IAC1B,QAAQ,KAAK,SAAS,IAAI;AAAA,IAC1B,wBAAwB,YAAY,KAAK;AAAA,IACzC,iBAAiB,QAAQ;AAAA,EAC3B,CAAC;AACH,GAZmC;AAc5B,IAAM,mBAAmB,8BAC9B,MACA,eACwB;AACxB,QAAM,EAAE,OAAO,MAAM,SAAS,IAAI;AAElC,MAAI,MAAM;AACR,UAAM,QAAQ,KAAK,SAAS,IAAI;AAAA,EAClC;AAEA,QAAM,QAAQ,SAAS,SAAS,QAAQ;AAExC,QAAM,OAAO,MAAM,cAAc,OAAO,UAAU;AAClD,MAAI,CAAC,QAAQ,CAAC,KAAK,UAAU;AAC3B,UAAM,IAAI,cAAc,qBAAqB;AAAA,EAC/C;AAEA,QAAM,UAAU,MAAM,cAAAC,QAAO,QAAQ,UAAU,KAAK,QAAQ;AAC5D,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,eAAe,qBAAqB;AAAA,EAChD;AAEA,SAAO;AACT,GAvBgC;AAyBzB,IAAM,sBAAsB,8BACjC,mBACkB;AAClB,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAI,gBAAgB,4BAA4B;AAAA,EACxD;AAEA,MAAI;AACF,UAAM,SAAS,MAAM,qBAAqB;AAE1C,QAAI,CAAC,OAAO,qBAAqB;AAC/B,YAAM,IAAI,gBAAgB,2CAA2C;AAAA,IACvE;AAEA,QAAI,SAAS,cAAc,MAAM,SAAS,OAAO,mBAAmB,GAAG;AACrE,YAAM,IAAI,gBAAgB,wBAAwB;AAAA,IACpD;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,iBAAiB;AACpC,YAAM;AAAA,IACR;AACA,UAAM,IAAI,gBAAgB,iCAAiC;AAAA,EAC7D;AACF,GAvBmC;;;ADxH5B,IAAM,gBAAN,MAAM,cAAqC;AAAA,EAEhD,YACmB,YACA,YACjB;AAFiB;AACA;AAAA,EACf;AAAA,EAEJ,MAAa,aAA4B;AACvC,cAAM,oCAAmB,KAAK,YAAY,CAAC,SAAyB,KAAK,OAAO,CAAC;AAAA,EACnF;AAAA,EAEA,MAAM,QAAQ,UAAwG;AACpH,UAAM,OAAO,MAAM,iBAAiB,UAAU,KAAK,UAAU;AAE7D,UAAM,cAAc,KAAK,WAAW,oBAAoB,KAAK,MAAM,KAAK,IAAI;AAC5E,UAAM,gBAAY,6BAAuB,WAAW,EAAE;AAEtD,WAAO,EAAE,IAAI,KAAK,KAAK,IAAI,aAA0B,WAAsB,SAAS,KAAK,iBAAiB;AAAA,EAC5G;AACF;AAnBkD;AAA3C,IAAM,eAAN;;;AEVP,IAAAC,mBAAiD;AAO1C,IAAM,qBAAN,MAAM,mBAA0C;AAAA,EAGrD,YACE,YACA;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAa,aAA4B;AACvC,cAAM,qCAAmB,KAAK,YAAY,CAAC,SAAyB,KAAK,OAAO,CAAC;AAAA,EACnF;AAAA,EAEA,MAAM,QAAQ,UAAoB,eAAwC;AACxE,UAAM,OAAO,MAAM,iBAAiB,UAAU,KAAK,UAAU;AAE7D,UAAM,oBAAoB,aAAa;AAEvC,WAAO,KAAK,KAAK;AAAA,EACnB;AACF;AApBuD;AAAhD,IAAM,oBAAN;;;ACPP,IAAAC,mBAAiD;AAM1C,IAAM,iBAAN,MAAM,eAAsC;AAAA,EAG/C,YAAY,YAA4B;AACpC,SAAK,aAAa;AAAA,EACtB;AAAA,EAEA,MAAa,aAA4B;AACrC,cAAM,qCAAmB,KAAK,YAAY,CAAC,SAAyB,KAAK,OAAO,CAAC;AAAA,EACrF;AAAA,EAEA,MAAM,QAAQ,QAA+B;AACzC,QAAI;AACA,YAAM,KAAK,WAAW,OAAO,MAAM;AAAA,IACvC,SAAS,OAAO;AACZ,UAAI,cAAc,gBAAgB;AAAA,IACtC;AAAA,EACJ;AACJ;AAlBmD;AAA5C,IAAM,gBAAN;;;ACNP,IAAAC,mBAAiD;AACjD,IAAAC,UAAwB;AACxB,IAAAC,uBAA8D;;;ACF9D,IAAAC,eAA6B;AAC7B,IAAAC,kBAAwB;;;ACDxB,kBAAsD;AACtD,IAAAC,uBAAoD;;;ACC7C,IAAM,eAAN,MAAM,aAAY;AAMzB;AANyB;AAAlB,IAAM,cAAN;;;ACFP,qBAAwB;AAGjB,IAAM,WAAN,MAAM,SAAQ;AAerB;AAfqB;AAEnB;AAAA,MADC,wBAAQ;AAAA,GADE,SAEX;AAGA;AAAA,MADC,wBAAQ;AAAA,GAJE,SAKX;AAGA;AAAA,MADC,wBAAQ;AAAA,GAPE,SAQX;AAGA;AAAA,MADC,wBAAQ;AAAA,GAVE,SAWX;AAGA;AAAA,MADC,wBAAQ;AAAA,GAbE,SAcX;AAdK,IAAM,UAAN;;;ACHP,IAAAC,kBAAwB;AAGjB,IAAM,YAAN,MAAM,UAAS;AActB;AAdsB;AAEpB;AAAA,MADC,yBAAQ;AAAA,GADE,UAEX;AAGA;AAAA,MADC,yBAAQ;AAAA,GAJE,UAKX;AAGA;AAAA,MADC,yBAAQ;AAAA,GAPE,UAQX;AAGA;AAAA,MADC,yBAAQ;AAAA,GAVE,UAWX;AAXK,IAAM,WAAN;;;AHIA,SAAS,mBAAmBC,SAAsB;AACrD;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,QACA,uBAAU,UAAQ,KAAK,WAAO,qBAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,QACvD,uBAAU,UAAQ,KAAK,cAAU,qBAAQ,SAAO,IAAI,QAAQ,CAAC;AAAA,QAC7D,uBAAU,UAAQ,KAAK,UAAM,qBAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,EAAC;AAE1D;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,QACA,uBAAU,UAAQ,KAAK,UAAM,qBAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,QACrD,uBAAU,UAAQ,KAAK,WAAO,qBAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,EAAC;AAE5D;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,QACA,uBAAU,UAAQ,KAAK,UAAM,qBAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,QACrD,uBAAU,UAAQ,KAAK,WAAO,qBAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,EAAC;AAE5D;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,QACA,uBAAU,UAAQ,KAAK,QAAI,qBAAQ,SAAO,IAAI,EAAE,CAAC;AAAA,QACjD,uBAAU,UAAQ,KAAK,UAAM,qBAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,QACrD,uBAAU,UAAQ,KAAK,WAAO,qBAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,QACvD,uBAAU,UAAQ,KAAK,qBAAiB,qBAAQ,SAAO,mBAAmB,GAAG,CAAC,CAAC;AAAA,EAAC;AAGpF;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,QACA,uBAAU,UAAQ,KAAK,QAAI,qBAAQ,SAAO,IAAI,EAAE,CAAC;AAAA,QACjD,uBAAU,UAAQ,KAAK,UAAM,qBAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,QACrD,uBAAU,UAAQ,KAAK,WAAO,qBAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,EAAC;AAE5D,QAAM,qBAAqB,wBAAC,QAAwC;AAChE,UAAM,QAAQ,IAAI,SAAS,CAAC;AAC5B,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,MAAM,SAAS,MAAM,SAAS,MAAM,SAAS,MAAM,YAAY,MAAM,eAAe,MAAM;AAAA,EACrG,GAJ2B;AAK/B;AA9CgB;;;ADFT,IAAM,aAAS,2BAAa;AAAA,EACjC,yBAAqB,yBAAQ;AAC/B,CAAC;AAED,mBAAmB,MAAM;;;ADClB,IAAM,mBAAN,MAAM,iBAAwC;AAAA,EAGnD,YAA6B,YAA4B;AAA5B;AAF7B,SAAiB,cAAc;AAAA,EAE2B;AAAA,EAE1D,MAAa,aAA4B;AACvC,cAAM,qCAAmB,KAAK,YAAY,CAAC,SAAS,KAAK,OAAO,CAAC;AAAA,EACnE;AAAA,EAEA,MAAa,QACX,OACA,MACA,UACA,OAAiB,8BAAS,OAC1B,eACiC;AACjC,QAAI;AACF,YAAM,gBAAgB,KAAK,gBAAgB,EAAE,OAAO,MAAM,UAAU,MAAM,cAAc,CAAC;AAEzF,YAAM,cAAc,MAAM,KAAK;AAAA,QAC7B,cAAc;AAAA,QACd,cAAc;AAAA,MAChB;AAEA,YAAM,oBAAoB,eAAe,KAAK,UAAU;AAExD,YAAM,iBAAiB,MAAM,KAAK,cAAc,cAAc,QAAQ;AACtE,YAAM,aAAa,KAAK,uBAAuB,eAAe,gBAAgB,WAAW;AAEzF,aAAO,KAAK,WAAW,OAAO,UAAU;AAAA,IAC1C,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MAClF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,KAA+B;AACrD,WAAO;AAAA,MACL,MAAM,IAAI,KAAK,KAAK;AAAA,MACpB,OAAO,IAAI,MAAM,KAAK,EAAE,YAAY;AAAA,MACpC,UAAU,IAAI,SAAS,KAAK;AAAA,MAC5B,MAAM,IAAI;AAAA,MACV,eAAe,IAAI,eAAe,KAAK;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,UAAmC;AAC7D,WAAc,aAAK,UAAU,KAAK,WAAW;AAAA,EAC/C;AAAA,EAEA,MAAc,2BACZ,MACA,eACkB;AAClB,QAAI,SAAS,8BAAS,MAAO,QAAO;AAEpC,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,kBAAkB,mDAAmD;AAAA,IACjF;AAEA,UAAM,oBAAoB,aAAa;AACvC,WAAO;AAAA,EACT;AAAA,EAEQ,uBACN,KACA,gBACA,SACY;AACZ,UAAM,aAAa,OAAO,IAAI,KAAK,aAAa,+BAAU;AAC1D,UAAM,oBAAoB,UACtB,OAAO,IAAI,KAAK,aAAa,gCAAW,IACxC,OAAO,IAAI,KAAK,aAAa,+BAAU;AAE3C,sBAAkB,YAAY;AAE9B,QAAI,SAAS;AACX,iBAAW,QAAQ;AAAA,IACrB,OAAO;AACL,iBAAW,OAAO;AAAA,IACpB;AAEA,eAAW,WAAW;AACtB,eAAW,eAAe;AAE1B,WAAO;AAAA,EACT;AACF;AAxFqD;AAA9C,IAAM,kBAAN;;;AMVP,IAAAC,mBAAiD;AAK1C,IAAM,uBAAN,MAAM,qBAA4C;AAAA,EAIvD,YAAY,YAA4B,SAAyB;AAC/D,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAa,aAA4B;AACvC,cAAM,qCAAmB,KAAK,YAAY,CAAC,SAAyB,KAAK,OAAO,CAAC;AAAA,EACnF;AAAA,EAEA,MAAa,QAAQ,cAAkD;AACrE,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,QAAQ,mBAAmB,YAAY;AAElE,UAAI,CAAC,QAAQ,QAAQ;AACnB,eAAO;AAAA,MACT;AAEA,UAAI,aAAa,MAAM,KAAK,WAAW,iBAAiB,QAAQ,MAAM;AAEtE,UAAI,CAAC,YAAY;AACf,qBAAa,MAAM,KAAK,WAAW,iBAAiB,QAAQ,QAAQ,IAAI;AAAA,MAC1E;AAEA,UAAI,CAAC,YAAY;AACf,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,WAAW,SAAS,UAAU,WAAW,QAAQ,WAAW;AAEzE,YAAM,cAAc,KAAK,QAAQ,oBAAoB,MAAM,WAAW,IAAI;AAC1E,YAAM,kBAAkB,KAAK,QAAQ,qBAAqB,IAAI;AAE9D,YAAM,KAAK,WAAW,OAAO,WAAW,IAAI;AAAA,QAC1C,cAAc;AAAA,MAChB,CAAC;AAED,aAAO;AAAA,QACL;AAAA,QACA,cAAc;AAAA,MAChB;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAhDyD;AAAlD,IAAM,sBAAN;;;ACGA,IAAM,yBAAN,MAAM,uBAA8C;AAAA,EAKzD,YAAY,kBAAoC,gBAAgC;AAFhF,SAAQ,gBAAgB;AAGtB,SAAK,mBAAmB;AACxB,SAAK,iBAAiB;AAAA,EACxB;AAAA,EACA,MAAM,aAA4B;AAChC,QAAI,KAAK,cAAe;AAExB,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,iBAAiB,WAAW;AAAA,IACnC,CAAC;AAED,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAM,QAAQ,QAAkD;AAC9D,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,UAAM,OAAO,MAAM,KAAK,eAAe,aAAa,MAAM;AAE1D,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,eAAe,gBAAgB;AAAA,IAC3C;AAEA,QAAI,KAAK,kBAAkB;AACzB,YAAM,IAAI,eAAe,8CAA8C;AAAA,IACzE;AAEA,UAAM,EAAE,QAAQ,WAAW,IAAI,KAAK,iBAAiB,eAAe,KAAK,KAAK;AAC9E,UAAM,YAAY,MAAM,KAAK,iBAAiB,eAAe,UAAU;AAEvE,UAAM,KAAK,eAAe,sBAAsB,QAAQ,MAAM;AAE9D,WAAO,EAAE,UAAU;AAAA,EACrB;AACF;AAzC2D;AAApD,IAAM,wBAAN;;;ACRP,IAAAC,mBAAiD;AAQ1C,IAAM,0BAAN,MAAM,wBAA8C;AAAA,EAKzD,YAAY,kBAAoC,gBAAgC;AAFhF,SAAQ,gBAAgB;AAGtB,SAAK,mBAAmB;AACxB,SAAK,iBAAiB;AAAA,EAExB;AAAA,EACA,MAAM,aAA4B;AAC9B,QAAI,KAAK,cAAe;AAExB,UAAM,QAAQ,IAAI;AAAA,MACd,KAAK,iBAAiB,WAAW;AAAA,UACjC,qCAAmB,KAAK,gBAAgB,UAAQ,KAAK,OAAO,CAAC;AAAA,IACjE,CAAC;AAED,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEF,MAAM,QAAS,KAAsC;AACnD,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,UAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,eAAe,mBAAmB;AAAA,IAC9C;AAEA,UAAM,OAA0B,MAAM,KAAK,eAAe,aAAa,MAAM;AAE7E,QAAI,CAAC,QAAQ,CAAC,KAAK,iBAAiB;AAClC,YAAM,IAAI,eAAe,+CAA+C;AAAA,IAC1E;AAEA,QAAI,KAAK,kBAAkB;AACzB,YAAM,IAAI,eAAe,8CAA8C;AAAA,IACzE;AAEA,UAAM,UAAU,KAAK,iBAAiB,YAAY,OAAO,KAAK,eAAe;AAE7E,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,eAAe,2BAA2B;AAAA,IACtD;AAEA,UAAM,KAAK,eAAe,gBAAgB,IAAI;AAAA,EAChD;AACF;AAlD2D;AAApD,IAAM,yBAAN;;;ACRP,IAAAC,mBAAiD;AACjD,IAAAC,uBAAoD;AAY7C,IAAM,0BAAN,MAAM,wBAA+C;AAAA,EAGxD,YACqB,kBACA,gBACA,YACnB;AAHmB;AACA;AACA;AALrB,SAAQ,gBAAgB;AAAA,EAMpB;AAAA,EAEJ,MAAa,aAA4B;AACrC,QAAI,KAAK,cAAe;AACxB,UAAM,QAAQ,IAAI;AAAA,MACd,KAAK,iBAAiB,WAAW;AAAA,MACjC,KAAK,WAAW,WAAW;AAAA,UAC3B,qCAAmB,KAAK,gBAAgB,UAAQ,KAAK,OAAO,CAAC;AAAA,IACjE,CAAC;AACD,SAAK,gBAAgB;AAAA,EACzB;AAAA,EAEA,MAAa,QAAQ,KAA2G;AAC5H,QAAI,CAAC,KAAK,eAAe;AACrB,YAAM,KAAK,WAAW;AAAA,IAC1B;AAEA,UAAM,EAAE,QAAQ,MAAM,IAAI;AAC1B,QAAI,CAAC,UAAU,CAAC,OAAO;AACnB,YAAM,IAAI,eAAe,iCAAiC;AAAA,IAC9D;AAEA,UAAM,OAA0B,MAAM,KAAK,eAAe,aAAa,MAAM;AAC7E,QAAI,CAAC,QAAQ,CAAC,KAAK,mBAAmB,CAAC,KAAK,kBAAkB;AAC1D,YAAM,IAAI,eAAe,kBAAkB;AAAA,IAC/C;AAEA,UAAM,UAAU,KAAK,iBAAiB,YAAY,OAAO,KAAK,eAAe;AAC7E,QAAI,CAAC,SAAS;AACV,YAAM,IAAI,eAAe,4BAA4B;AAAA,IACzD;AAEA,UAAM,YAAwB,KAAK,eAAe,IAAI;AACtD,UAAM,KAAK,iBAAiB,IAAI;AAChC,UAAM,KAAK,uBAAuB,MAAM,UAAU,YAAY;AAE9D,QAAI,KAAK,OAAO;AACZ,aAAO;AAAA,QACH,OAAO,UAAU;AAAA,QACjB,cAAc,UAAU;AAAA,QACxB,MAAM,KAAK,cAAc,KAAK,KAAK;AAAA,MACvC;AAAA,IACJ;AAEA,QAAI,KAAK,MAAM;AACX,aAAO;AAAA,QACH,OAAO,UAAU;AAAA,QACjB,cAAc,UAAU;AAAA,QACxB,MAAM,KAAK,aAAa,KAAK,IAAI;AAAA,MACrC;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAAA,EAEQ,cAAc,OAA8B;AAChD,WAAO,OAAO,IAAI,OAAO,kCAAa,QAAQ;AAAA,EAClD;AAAA,EAEQ,aAAa,MAA2B;AAC5C,WAAO,OAAO,IAAI,MAAM,iCAAY,OAAO;AAAA,EAC/C;AAAA,EAEA,MAAc,iBAAiB,MAAiC;AAC5D,SAAK,KAAK,cAAc,oBAAI,KAAK;AACjC,SAAK,KAAK,WAAW;AACrB,UAAM,KAAK,eAAe,OAAO,KAAK,IAAI,IAAI;AAAA,EAClD;AAAA,EAEA,MAAc,uBAAuB,MAAkB,cAAqC;AACxF,SAAK,eAAe;AACpB,UAAM,KAAK,eAAe,OAAO,KAAK,IAAI,EAAE,aAAa,CAAC;AAAA,EAC9D;AAAA,EAEQ,eAAe,MAA8B;AACjD,WAAO;AAAA,MACH,aAAa,KAAK,WAAW,oBAAoB,KAAK,MAAM,KAAK,IAAI;AAAA,MACrE,cAAc,KAAK,WAAW,qBAAqB,KAAK,IAAI;AAAA,IAChE;AAAA,EACJ;AACJ;AAvF4D;AAArD,IAAM,yBAAN;;;ACbP,IAAAC,mBAAiD;AAQ1C,IAAM,2BAAN,MAAM,yBAA+C;AAAA,EAK1D,YAAY,kBAAoC,gBAAgC;AAFhF,SAAQ,gBAAgB;AAGtB,SAAK,mBAAmB;AACxB,SAAK,iBAAiB;AAAA,EACxB;AAAA,EACA,MAAM,aAA4B;AAChC,QAAI,KAAK,cAAe;AAExB,UAAM,QAAQ,IAAI;AAAA,MACd,KAAK,iBAAiB,WAAW;AAAA,UACjC,qCAAmB,KAAK,gBAAgB,UAAQ,KAAK,OAAO,CAAC;AAAA,IACjE,CAAC;AACL;AACI,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAM,QAAQ,QAAgB,KAAsC;AAClE,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,KAAK,WAAW;AAAA,IACxB;AAEA,UAAM,EAAE,MAAM,IAAI;AAElB,UAAM,OAAO,MAAM,KAAK,eAAe,aAAa,MAAM;AAE1D,QAAI,CAAC,QAAQ,CAAC,KAAK,mBAAmB,CAAC,KAAK,kBAAkB;AAC5D,YAAM,IAAI,eAAe,0CAA0C;AAAA,IACrE;AAEA,UAAM,UAAU,KAAK,iBAAiB,YAAY,OAAO,KAAK,eAAe;AAE7E,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,eAAe,2BAA2B;AAAA,IACtD;AAEA,UAAM,KAAK,eAAe,iBAAiB,IAAI;AAAA,EACjD;AACF;AAzC4D;AAArD,IAAM,0BAAN;;;ACRA,IAAM,cAAc;AAAA,EACzB,IAAI;AAAA,EACJ,SAAS;AACX;AAEO,IAAM,cAAc;AAAA,EACzB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,WAAW;AAAA,EACX,YAAW;AAAA,EACX,YAAW;AAAA,EACX,iBAAgB;AAClB;AAEO,IAAM,WAAW;AAAA,EACtB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,wBAAwB;AAC1B;;;ACHO,IAAM,kBAAN,MAAM,gBAAe;AAAA,EAW1B,YACE,cACA,mBACA,eACA,iBACA,qBACA,uBACA,wBACA,wBACA,yBACA;AAqDF,iBAAQ,8BAAO,KAAc,KAAe,SAAsC;AAChF,UAAI;AACF,cAAM,WAAqB,IAAI;AAC/B,cAAM,SAAS,MAAM,KAAK,aAAa,QAAQ,QAAQ;AAEvD,cAAM,mBAAmB,OAAO,WAAW;AAE3C,cAAM,YAAY;AAAA,UAChB,aAAa,OAAO;AAAA,UACpB,QAAQ,OAAO;AAAA,UACf,WAAW,OAAO;AAAA,UAClB,MAAM,KAAK;AAAA,YACT;AAAA;AAAA,YACA;AAAA;AAAA,YACA,mBAAmB,YAAY,uBAAuB,YAAY;AAAA,YAClE;AAAA;AAAA,UACF;AAAA,QACF;AAEA,aAAK,aAAa,KAAK,YAAY,IAAI,SAAS,eAAe,SAAS;AAAA,MAC1E,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAvBQ;AAyBR,sBAAa,8BAAO,KAAc,KAAe,SAAsC;AACrF,UAAI;AACF,cAAM,EAAE,eAAe,GAAG,SAAS,IAAc,IAAI;AAErD,YAAI,CAAC,eAAe;AAClB,gBAAM,IAAI,eAAe,4BAA4B;AAAA,QACvD;AAEA,cAAM,SAAS,MAAM,KAAK,kBAAkB,QAAQ,UAAU,aAAa;AAE3E,cAAM,iBAAiB;AAAA,UACrB,SAAS;AAAA,UACT,MAAM,KAAK;AAAA,YACT;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAEA,aAAK,aAAa,KAAK,YAAY,SAAS,SAAS,qBAAqB,cAAc;AAAA,MAC1F,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAxBa;AA0Bb,kBAAS,8BAAO,KAAc,KAAe,SAAsC;AACjF,UAAI;AACF,cAAM,KAAK,cAAc,QAAQ,IAAI,KAAK,EAAE;AAE5C,cAAM,aAAa;AAAA,UACjB,MAAM,KAAK;AAAA,YACT;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAEA,aAAK,aAAa,KAAK,YAAY,IAAI,SAAS,gBAAgB,UAAU;AAAA,MAC5E,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAjBS;AAmBT,oBAAW,8BAAO,KAAc,KAAe,SAAsC;AACnF,UAAI;AACF,cAAM,EAAE,OAAO,MAAM,UAAU,MAAM,cAAc,IAAiB,IAAI;AAExE,cAAM,KAAK,gBAAgB,QAAQ,OAAO,MAAM,UAAU,MAAM,aAAa;AAE7E,cAAM,eAAe;AAAA,UACnB,MAAM,KAAK;AAAA,YACT;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAEA,aAAK;AAAA,UACH;AAAA,UACA,YAAY;AAAA,UACZ,SAAS;AAAA,UACT;AAAA,UACA,EAAE,QAAQ,KAAK;AAAA,QACjB;AAAA,MACF,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAzBW;AA2BX,wBAAe,8BAAO,KAAc,KAAe,SAAsC;AACvF,UAAI;AACF,cAAM,EAAE,aAAa,IAA0B,IAAI;AAEnD,cAAM,SAAS,MAAM,KAAK,oBAAoB,QAAQ,YAAY;AAElE,YAAI,CAAC,QAAQ;AACX,gBAAM,IAAI,MAAM,yBAAyB;AAAA,QAC3C;AAEA,cAAM,cAAc;AAAA,UAClB,aAAa,OAAO;AAAA,UACpB,cAAc,OAAO;AAAA,UACrB,MAAM,KAAK;AAAA,YACT;AAAA,YACA;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAEA,aAAK,aAAa,KAAK,YAAY,IAAI,SAAS,uBAAuB,WAAW;AAAA,MACpF,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAzBe;AA2Bf,oBAAW,8BAAO,KAAc,KAAe,SAAsC;AACnF,UAAI;AACF,YAAI,CAAC,IAAI,MAAM,IAAI;AACjB,gBAAM,IAAI,eAAe,8BAA8B;AAAA,QACzD;AAEA,cAAM,SAAS,MAAM,KAAK,sBAAsB,QAAQ,IAAI,KAAK,EAAE;AAEnE,cAAM,YAAY;AAAA,UAChB,QAAQ,OAAO;AAAA,UACf,MAAM,KAAK,eAAe,MAAM,OAAO,YAAY,WAAW;AAAA,QAChE;AAEA,cAAM,OAAO;AAAA,UACX,UAAU;AAAA,UACV,YAAY;AAAA,QACd;AAEA,aAAK,aAAa,KAAK,YAAY,IAAI,SAAS,sBAAsB,WAAW,IAAI;AAAA,MACvF,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAtBW;AAwBX,qBAAY,8BAAO,KAAc,KAAe,SAAsC;AACpF,UAAI;AACF,cAAM,MAAwB,EAAE,GAAG,IAAI,MAAM,QAAQ,IAAI,MAAM,GAAG;AAClE,cAAM,KAAK,uBAAuB,QAAQ,GAAG;AAE7C,cAAM,aAAa;AAAA,UACjB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,UAClC,MAAM,KAAK,eAAe,MAAM,MAAM,YAAY,oBAAoB;AAAA,QACxE;AAEA,cAAM,OAAO;AAAA,UACX,UAAU;AAAA,UACV,YAAY;AAAA,QACd;AAEA,aAAK,aAAa,KAAK,YAAY,IAAI,SAAS,uBAAuB,YAAY,IAAI;AAAA,MACzF,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GAnBY;AAqBZ,qBAAY,8BAAO,KAAc,KAAe,SAAsC;AACpF,UAAI;AACF,cAAM,MAAwB,IAAI;AAClC,cAAM,SAAS,MAAM,KAAK,uBAAuB,QAAQ,GAAG;AAE5D,cAAM,aAAa;AAAA,UACjB,OAAO,QAAQ;AAAA,UACf,cAAc,QAAQ;AAAA,UACtB,MAAM;AAAA,YACJ,IAAI,QAAQ,MAAM;AAAA,YAClB,OAAO,QAAQ,MAAM;AAAA,YACrB,MAAM,QAAQ,MAAM;AAAA,YACpB,MAAM,QAAQ,MAAM;AAAA,UACtB;AAAA,UACA,MAAM,KAAK,eAAe,MAAM,MAAM,YAAY,WAAW,IAAI;AAAA,QACnE;AAEA,cAAM,OAAO;AAAA,UACX,gBAAgB;AAAA,UAChB,YAAY;AAAA,QACd;AAEA,aAAK,aAAa,KAAK,YAAY,IAAI,SAAS,uBAAuB,YAAY,IAAI;AAAA,MACzF,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GA1BY;AA4BZ,sBAAa,8BAAO,KAAc,KAAe,SAAsC;AACrF,UAAI;AACF,cAAM,SAAS,IAAI,KAAM;AACzB,cAAM,MAAwB,IAAI;AAElC,cAAM,KAAK,wBAAwB,QAAQ,QAAQ,GAAG;AAEtD,cAAM,cAAc;AAAA,UAClB,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,UACnC,MAAM,KAAK,eAAe,MAAM,OAAO,YAAY,YAAY,KAAK;AAAA,QACtE;AAEA,cAAM,OAAO;AAAA,UACX,cAAc;AAAA,UACd,YAAY;AAAA,QACd;AAEA,aAAK,aAAa,KAAK,YAAY,IAAI,SAAS,wBAAwB,aAAa,IAAI;AAAA,MAC3F,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GArBa;AAzPX,SAAK,eAAe;AACpB,SAAK,oBAAoB;AACzB,SAAK,gBAAgB;AACrB,SAAK,kBAAkB;AACvB,SAAK,sBAAsB;AAC3B,SAAK,wBAAwB;AAC7B,SAAK,yBAAyB;AAC9B,SAAK,yBAAyB;AAC9B,SAAK,0BAA0B;AAAA,EACjC;AAAA,EAEQ,eACN,SACA,MACA,MACgB;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,MAAM;AAAA,QACJ,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eACN,gBACA,SACA,QACA,UACU;AACV,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,IAC3C;AAAA,EACF;AAAA,EAEQ,aACN,KACA,YACA,SACA,MACA,MACM;AACN,UAAM,WAAW,KAAK,eAAe,SAAS,MAAM,IAAI;AACxD,QAAI,OAAO,UAAU,EAAE,KAAK,QAAQ;AAAA,EACtC;AA6NF;AArS4B;AAArB,IAAM,iBAAN;;;ACnBA,IAAM,sBAAN,MAAM,oBAAmB;AAAA,EAG9B,YAAY,YAA4B;AACtC,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAa,QAAQ,KAAc,KAAe,MAAoB;AACpE,QAAI;AACF,YAAM,QAAQ,IAAI,QAAQ,eAAe,MAAM,GAAG,EAAE,CAAC;AAErD,UAAI,CAAC,OAAO;AACV,eAAO,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,SAAS,0BAA0B,CAAC;AAAA,MACpE;AAEA,YAAM,UAAU,MAAM,KAAK,WAAW,kBAAkB,KAAK;AAE7D,UAAI,CAAC,QAAQ,wBAAwB;AACnC,eAAO,IAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UAC1B,SAAS;AAAA,UACT,MAAM;AAAA,UACN,QAAQ,QAAQ;AAAA,QAClB,CAAC;AAAA,MACH;AAEA,UAAI,OAAO,EAAE,GAAG,SAAS,wBAAwB,KAAK;AACtD,WAAK;AAAA,IACP,SAAS,OAAO;AACd,aAAO,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,SAAS,2BAA2B,CAAC;AAAA,IACrE;AAAA,EACF;AACF;AA/BgC;AAAzB,IAAM,qBAAN;;;ACHP,IAAAC,mBAAwD;AAKjD,IAAM,kBAAN,MAAM,wBACH,gCACuC;AAAA,EAC/C,YAAY,YAAoC;AAC9C,UAAM,UAAU;AAAA,EAClB;AAAA,EAEA,MAAM,YAAY,OAA2C;AAC3D,UAAM,QAAQ,KAAK,WAChB,mBAAmB,MAAM,EACzB,kBAAkB,aAAa,MAAM,EACrC,UAAU,eAAe,EACzB,MAAM,uBAAuB,EAAE,MAAM,CAAC;AAEzC,WAAO,MAAM,MAAM,OAAO;AAAA,EAC5B;AAAA,EAEA,MAAM,OAAO,QAA4D;AACvE,WAAO,MAAM,OAAO,MAAM;AAAA,EAC5B;AAAA,EAEA,MAAM,aAAa,QAA4C;AAC7D,UAAM,QAAQ,KAAK,WAChB,mBAAmB,MAAM,EACzB,kBAAkB,aAAa,MAAM,EACrC,UAAU,sBAAsB,EAChC,MAAM,qBAAqB,EAAE,OAAO,CAAC;AAExC,WAAO,MAAM,MAAM,OAAO;AAAE;AAAA,EAC9B;AAAA,EAEA,MAAM,iBAAiB,QAAgB,UAAmB,OAAmC;AAC3F,UAAM,QAAQ,KAAK,WAChB,mBAAmB,MAAM,EACzB,UAAU,sBAAsB;AAEnC,QAAI,SAAS;AACX,YAAM,kBAAkB,cAAc,OAAO,EAC1C,MAAM,sBAAsB,EAAE,OAAO,CAAC;AAAA,IAC3C,OAAO;AACL,YAAM,kBAAkB,aAAa,MAAM,EACxC,MAAM,qBAAqB,EAAE,OAAO,CAAC;AAAA,IAC1C;AAEA,WAAO,MAAM,MAAM,OAAO;AAAA,EAC5B;AAAA,EAEA,MAAM,OAAO,QAA+B;AAC1C,UAAM,OAAO,MAAM,KAAK,aAAa,MAAM;AAC3C,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,cAAc,gBAAgB;AAAA,IAC1C;AAEA,SAAK,eAAe;AACpB,SAAK,KAAK,WAAW;AAErB,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,sBAAsB,QAAgB,QAA+B;AACzE,UAAM,OAAO,MAAM,KAAK,aAAa,MAAM;AAC3C,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,cAAc,gBAAgB;AAAA,IAC1C;AAEA,SAAK,kBAAkB;AAEvB,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,gBAAgB,MAAiC;AAErD,SAAK,mBAAmB;AAExB,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,iBAAiB,MAAiC;AAEtD,SAAK,mBAAmB;AACxB,SAAK,kBAAkB;AAEvB,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,mBAAmB,QAAkC;AACzD,UAAM,OAAO,MAAM,KAAK,aAAa,MAAM;AAC3C,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,cAAc,gBAAgB;AAAA,IAC1C;AAEA,WAAO,CAAC,CAAC,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,mBAAmB,QAAwC;AAC/D,UAAM,OAAO,MAAM,KAAK,aAAa,MAAM;AAC3C,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,cAAc,gBAAgB;AAAA,IAC1C;AAEA,WAAO,KAAK;AAAA,EACd;AACF;AApGiD;AAF1C,IAAM,iBAAN;;;ACLP,UAAqB;AAErB,IAAAC,UAAwB;AACxB,IAAAC,oBAAiD;AAkB1C,IAAM,kBAAN,MAAM,gBAAqD;AAAA,EAGhE,YAA6B,YAA4B,QAAqB;AAAjD;AAC3B,SAAK,WAAW,MAAM;AAAA,EACxB;AAAA,EAEA,MAAc,WAAW,QAAqB;AAC5C,UAAM,aAAa,MAAM,qBAAqB;AAE9C,SAAK,YAAY;AAAA,MACf,mBAAmB,WAAW;AAAA,MAC9B,oBAAoB,WAAW;AAAA,MAC/B,mBAAoB,SAAS,WAAW,mBAAmB,EAAE;AAAA,MAC7D,oBAAoB,SAAS,WAAW,oBAAoB,EAAE;AAAA,MAC9D,GAAG;AAAA,IACL;AAEA,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,MAAM,aAA4B;AAChC,cAAM,sCAAmB,KAAK,YAAY,UAAQ,KAAK,OAAO,CAAC;AAAA,EACjE;AAAA,EAEQ,wBAA8B;AACpC,QAAI,CAAC,KAAK,WAAW,qBAAqB,CAAC,KAAK,WAAW,oBAAoB;AAC7E,YAAM,IAAI,SAAS,gCAAgC;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,OAAe,UAA8C;AAC9E,UAAM,OAAO,MAAM,KAAK,WAAW,YAAY,KAAK;AACpD,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,cAAc,qBAAqB;AAAA,IAC/C;AAEA,UAAM,gBAAgB,MAAa,gBAAQ,UAAU,KAAK,QAAQ;AAClE,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,eAAe,qBAAqB;AAAA,IAChD;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB;AACxB,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,SAAS,uBAAuB;AAAA,EACjE;AAAA,EAEA,oBAAoB,MAAkB,MAAyB;AAC7D,SAAK,gBAAgB;AACrB,WAAW;AAAA,MACT,EAAE,QAAQ,KAAK,IAAI,OAAO,KAAK,OAAO,KAAW;AAAA,MACjD,KAAK,UAAW;AAAA,MAChB,EAAE,WAAW,KAAK,UAAW,kBAAkB;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,qBAAqB,MAA0B;AAC7C,SAAK,gBAAgB;AACrB,WAAW;AAAA,MACT,EAAE,QAAQ,KAAK,GAAG;AAAA,MAClB,KAAK,UAAW;AAAA,MAChB,EAAE,WAAW,KAAK,UAAW,mBAAmB;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,OAAe,QAAwC;AACvE,QAAI;AACF,cAAQ,IAAI,oBAAoB,KAAK;AACrC,cAAQ,IAAI,iBAAiB,MAAM;AAEnC,aAAW,WAAO,OAAO,MAAM;AAAA,IACjC,SAAQ,OAAO;AACb,cAAQ,MAAM,0BAA0B,KAAK;AAC7C,YAAM,IAAI,kBAAkB;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,OAAuC;AAC7D,SAAK,gBAAgB;AACrB,WAAO,KAAK,YAAY,OAAO,KAAK,UAAW,iBAAiB;AAAA,EAClE;AAAA,EAEA,MAAM,mBAAmB,OAAuC;AAC9D,SAAK,gBAAgB;AACrB,WAAO,KAAK,YAAY,OAAO,KAAK,UAAW,kBAAkB;AAAA,EACnE;AACF;AAxFkE;AAA3D,IAAM,iBAAN;;;ACrBP,gBAA2B;AAC3B,aAAwB;AAMjB,IAAM,oBAAN,MAAM,kBAAyC;AAAA,EASpD,YAAY,QAAiB;AAP7B,SAAQ,cAAuB;AAQ7B,SAAK,SAAS;AAEd,SAAK,kBAAkB;AAAA,MACrB,aAAa,SAAS,OAAO,WAAW,KAAK;AAAA,MAC7C,cAAc,SAAS,OAAO,YAAY,KAAK;AAAA,MAC/C,eAAe;AAAA,QACb,sBAAsB;AAAA,QACtB,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,OAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,aAA4B;AACvC,QAAI,KAAK,YAAa;AAEtB,QAAI;AACF,WAAK,sBAAsB;AAC3B,WAAK,cAAc;AAAA,IACrB,SAAS,OAAO;AACd,cAAQ,MAAM,2CAA2C,KAAK;AAC9D,YAAM,IAAI,eAAe,uCAAuC;AAAA,IAClE;AAAA,EACF;AAAA,EAEQ,wBAA8B;AACpC,QAAI,CAAC,KAAK,OAAO,UAAU,KAAK,GAAG;AACjC,YAAM,IAAI,eAAe,yDAAyD;AAAA,IACpF;AAEA,QAAI,KAAK,gBAAgB,eAAe,IAAI;AAC1C,YAAM,IAAI,eAAe,8CAA8C;AAAA,IACzE;AAEA,QAAI,KAAK,gBAAgB,cAAc,KAAK,KAAK,gBAAgB,cAAc,GAAG;AAChF,YAAM,IAAI,eAAe,mDAAmD;AAAA,IAC9E;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAChC,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI,eAAe,iDAAiD;AAAA,IAC5E;AAAA,EACF;AAAA,EAEO,eAAe,OAAuD;AAC3E,SAAK,kBAAkB;AAEvB,QAAI;AACF,YAAM,YAAsB,yBAAe;AAAA,QACzC,QAAQ,KAAK,gBAAgB;AAAA,QAC7B,MAAM,GAAG,KAAK,OAAO,QAAQ,IAAI,KAAK;AAAA,QACtC,QAAQ,KAAK,OAAO;AAAA,MACtB,CAAC;AAED,aAAO;AAAA,QACL,QAAQ,UAAU;AAAA,QAClB,YAAY,UAAU,eAAe;AAAA,MACvC;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,gCAAgC,KAAK;AACnD,YAAM,IAAI,eAAe,+BAA+B;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAa,eAAe,YAAqC;AAC/D,SAAK,kBAAkB;AAEvB,QAAI;AACF,aAAO,MAAa,iBAAU,YAAY,KAAK,gBAAgB,aAAa;AAAA,IAC9E,SAAS,OAAO;AACd,cAAQ,MAAM,8BAA8B,KAAK;AACjD,YAAM,IAAI,eAAe,4BAA4B;AAAA,IACvD;AAAA,EACF;AAAA,EAEO,YAAY,OAAe,QAAyB;AACzD,SAAK,kBAAkB;AAEvB,QAAI;AACF,aAAiB,eAAK,OAAO;AAAA,QAC3B;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,QAAQ,KAAK,gBAAgB;AAAA,MAC/B,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,8BAA8B,KAAK;AACjD,YAAM,IAAI,eAAe,4BAA4B;AAAA,IACvD;AAAA,EACF;AACF;AAzGsD;AAA/C,IAAM,mBAAN;;;ArBcP,eAAe,oBAAoB,UAAwB;AACzD,QAAM,YAAY,IAAI,gCAAc,EAAE,SAAS,CAAC;AAEhD,QAAM,iBAAiB,IAAI;AAAA,IACzB,SAAS,cAAc,+BAAU;AAAA,EACnC;AACA,YAAU,mBAA+B,kBAAkB,cAAc;AAEzE,QAAM,iBAAiB,IAAI,eAAe,cAAc;AACxD,YAAU,gBAAgB,kBAAkB,cAAc;AAE1D,QAAM,aAAa,MAAM,qBAAqB;AAE9C,QAAM,mBAAmB,IAAI,iBAAiB,UAAU;AACxD,YAAU,gBAAgB,oBAAoB,gBAAgB;AAE9D,QAAM,qBAAqB,IAAI,mBAAmB,cAAc;AAEhE,QAAM,eAAe,IAAI,aAAa,gBAAgB,cAAc;AACpE,QAAM,oBAAoB,IAAI;AAAA,IAC5B;AAAA,EACF;AACA,QAAM,gBAAgB,IAAI,cAAc,cAAc;AACtD,QAAM,kBAAkB,IAAI,gBAAgB,cAAc;AAC1D,QAAM,sBAAsB,IAAI;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,QAAM,wBAAwB,IAAI,sBAAsB,kBAAkB,cAAc;AACxF,QAAM,yBAAyB,IAAI,uBAAuB,kBAAkB,cAAc;AAC1F,QAAM,yBAAyB,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,0BAA0B,IAAI,wBAAwB,kBAAkB,cAAc;AAE5F,YAAU,gBAAgB,gBAAgB,YAAY;AACtD,YAAU,gBAAgB,qBAAqB,iBAAiB;AAChE,YAAU,gBAAgB,iBAAiB,aAAa;AACxD,YAAU,gBAAgB,mBAAmB,eAAe;AAC5D,YAAU,gBAAgB,uBAAuB,mBAAmB;AACpE,YAAU,gBAAgB,yBAAyB,qBAAqB;AACxE,YAAU,gBAAgB,0BAA0B,sBAAsB;AAC1E,YAAU,gBAAgB,0BAA0B,sBAAsB;AAC1E,YAAU,gBAAgB,2BAA2B,uBAAuB;AAE5E,QAAM,iBAAiB,IAAI;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,EAAE,WAAW,gBAAgB,mBAAmB;AACzD;AA7De;","names":["import_cca_core","import_cca_entities","bcrypt","import_cca_core","import_cca_core","import_cca_core","bcrypt","import_cca_entities","import_core","import_classes","import_cca_entities","import_classes","mapper","import_cca_core","import_cca_core","import_cca_core","import_cca_entities","import_cca_core","import_cca_core","bcrypt","import_cca_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/application/config/ConfigManager.ts","../src/utils/Errors.ts","../src/application/service/utils/configInstance.ts","../src/infrastructure/container/createAuthContainer.ts","../src/application/useCase/LoginUseCase.ts","../src/application/validators/authValidation.ts","../src/application/useCase/LogoutUseCase.ts","../src/application/useCase/RegisterUseCase.ts","../src/application/mappers/utils/mapper.ts","../src/application/mappers/createUserMappings.ts","../src/application/dtos/RegisterDTO.ts","../src/application/dtos/UserDTO.ts","../src/application/dtos/AdminDTO.ts","../src/application/useCase/RefreshTokenUseCase.ts","../src/application/useCase/TwoFactorSetupUseCase.ts","../src/application/useCase/TwoFactorEnableUseCase.ts","../src/application/useCase/TwoFactorVerifyUseCase.ts","../src/application/useCase/TwoFactorDisableUseCase.ts","../src/presentation/constants/constants.ts","../src/presentation/controller/AuthController.ts","../src/presentation/middleware/RequireComplete2FA.ts","../src/infrastructure/repository/AuthRepository.ts","../src/infrastructure/services/JwtAuthService.ts","../src/infrastructure/services/TwoFactorService.ts"],"sourcesContent":["import { authConfig } from \"./application/service/utils/configInstance\";\r\nimport { ConfigSource, IConfig } from \"./domain/interfaces/configTypes\";\r\nimport { createAuthContainer } from \"./infrastructure/container/createAuthContainer\";\r\nimport { AuthController } from \"./presentation/controller/AuthController\";\r\n\r\nexport { createAuthContainer, AuthController, authConfig, ConfigSource, IConfig };\r\n","import { EventEmitter } from \"events\";\r\nimport { IConfig, ConfigSource } from \"../../domain/interfaces/configTypes\";\r\nimport { ConfigNotFoundException } from \"../../utils/Errors\";\r\n\r\nexport class ConfigManager extends EventEmitter {\r\n private config?: IConfig;\r\n private configSource?: ConfigSource;\r\n\r\n setConfigSource(source: ConfigSource): void {\r\n this.configSource = source;\r\n }\r\n\r\n setConfig(cfg: IConfig): void {\r\n this.config = { ...cfg };\r\n this.emit(\"configAvailable\", this.config);\r\n }\r\n\r\n getConfig(): IConfig | undefined {\r\n return this.config;\r\n }\r\n\r\n async loadConfig(): Promise<IConfig> {\r\n if (!this.configSource) {\r\n throw new ConfigNotFoundException(\"Config source not set\");\r\n }\r\n try {\r\n const config = await this.configSource();\r\n this.setConfig(config);\r\n return config;\r\n } catch (error) {\r\n throw new ConfigNotFoundException(\"Error loading configuration\");\r\n }\r\n }\r\n}\r\n\r\nexport const configManager = new ConfigManager();\r\n","export class AppError extends Error {\r\n constructor(\r\n public message: string,\r\n public statusCode: number = 500,\r\n public name: string = \"AppError\"\r\n ) {\r\n super(message);\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n Error.captureStackTrace(this);\r\n }\r\n}\r\n\r\nexport class ValidationError extends AppError {\r\n constructor(message: string) {\r\n super(message, 400);\r\n this.name = \"ValidationError\";\r\n }\r\n}\r\n\r\nexport class ConfigNotFoundException extends AppError {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"ConfigNotFoundException\";\r\n }\r\n}\r\n\r\nexport class NotFoundError extends AppError {\r\n constructor(message: string) {\r\n super(message, 404, \"UserNotFoundError\");\r\n }\r\n}\r\n\r\nexport class ForbiddenError extends AppError {\r\n constructor(message: string = \"Forbidden access\") {\r\n super(message, 403);\r\n this.name = \"ForbiddenError\";\r\n }\r\n}\r\n\r\nexport class UnauthorizedError extends AppError {\r\n constructor(message: string = \"Unauthorized access\") {\r\n super(message, 401);\r\n this.name = \"UnauthorizedError\";\r\n }\r\n}\r\n\r\nexport class JwtError extends AppError {\r\n constructor(message: string) {\r\n super(message, 401);\r\n this.name = \"JwtError\";\r\n }\r\n}\r\n\r\nexport class RegistrationError extends AppError {\r\n constructor(message: string) {\r\n super(message, 400);\r\n this.name = \"RegistrationError\";\r\n }\r\n}\r\n\r\nexport class TwoFactorError extends AppError {\r\n constructor(message: string) {\r\n super(message, 400);\r\n this.name = \"TwoFactorERROR\";\r\n }\r\n}","import { configManager } from \"../../config/ConfigManager\";\r\nimport { IConfig, ConfigSource } from \"../../../domain/interfaces/configTypes\";\r\n\r\nexport const authConfig = (configSource: ConfigSource): void => {\r\n configManager.setConfigSource(configSource);\r\n};\r\n\r\nexport const createConfigInstance = async (): Promise<IConfig> => {\r\n return configManager.getConfig() ?? (await configManager.loadConfig());\r\n};\r\n","import { BaseContainer, BaseDatabase } from \"cca-core\";\r\nimport { AuthEntity } from \"cca-entities\";\r\n\r\nimport { LoginUseCase } from \"../../application/useCase/LoginUseCase\";\r\nimport { LogoutUseCase } from \"../../application/useCase/LogoutUseCase\";\r\nimport { RegisterUseCase } from \"../../application/useCase/RegisterUseCase\";\r\nimport { RefreshTokenUseCase } from \"../../application/useCase/RefreshTokenUseCase\";\r\nimport { TwoFactorSetupUseCase } from \"../../application/useCase/TwoFactorSetupUseCase\";\r\nimport { TwoFactorEnableUseCase } from \"../../application/useCase/TwoFactorEnableUseCase\";\r\nimport { TwoFactorVerifyUseCase } from \"../../application/useCase/TwoFactorVerifyUseCase\";\r\nimport { TwoFactorDisableUseCase } from \"../../application/useCase/TwoFactorDisableUseCase\";\r\n\r\nimport { AuthController } from \"../../presentation/controller/AuthController\";\r\nimport { RequireComplete2FA } from \"../../presentation/middleware/RequireComplete2FA\";\r\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nimport { JwtAuthService } from \"../services/JwtAuthService\";\r\nimport { TwoFactorService } from \"../services/TwoFactorService\";\r\nimport { createConfigInstance } from \"../../application/service/utils/configInstance\";\r\n\r\nasync function createAuthContainer(database: BaseDatabase) {\r\n const container = new BaseContainer({ database });\r\n\r\n const authRepository = new AuthRepository(\r\n database.getRepository(AuthEntity)\r\n );\r\n container.registerRepository<AuthEntity>(\"AuthRepository\", authRepository);\r\n\r\n const jwtAuthService = new JwtAuthService(authRepository);\r\n container.registerService(\"JwtAuthService\", jwtAuthService);\r\n\r\n const configData = await createConfigInstance();\r\n\r\n const twoFactorService = new TwoFactorService(configData);\r\n container.registerService(\"TwoFactorService\", twoFactorService);\r\n\r\n const requireComplete2FA = new RequireComplete2FA(jwtAuthService);\r\n\r\n const loginUseCase = new LoginUseCase(authRepository, jwtAuthService);\r\n const logoutUseCase = new LogoutUseCase(authRepository);\r\n const registerUseCase = new RegisterUseCase(authRepository);\r\n const refreshTokenUseCase = new RefreshTokenUseCase(\r\n authRepository,\r\n jwtAuthService\r\n );\r\n\r\n const twoFactorSetupUseCase = new TwoFactorSetupUseCase(twoFactorService, authRepository);\r\n const twoFactorEnableUseCase = new TwoFactorEnableUseCase(twoFactorService, authRepository);\r\n const twoFactorVerifyUseCase = new TwoFactorVerifyUseCase(\r\n twoFactorService,\r\n authRepository,\r\n jwtAuthService\r\n );\r\n const twoFactorDisableUseCase = new TwoFactorDisableUseCase(twoFactorService, authRepository);\r\n\r\n container.registerService(\"LoginUseCase\", loginUseCase);\r\n container.registerService(\"LogoutUseCase\", logoutUseCase);\r\n container.registerService(\"RegisterUseCase\", registerUseCase);\r\n container.registerService(\"RefreshTokenUseCase\", refreshTokenUseCase);\r\n container.registerService(\"TwoFactorSetupUseCase\", twoFactorSetupUseCase);\r\n container.registerService(\"TwoFactorEnableUseCase\", twoFactorEnableUseCase);\r\n container.registerService(\"TwoFactorVerifyUseCase\", twoFactorVerifyUseCase);\r\n container.registerService(\"TwoFactorDisableUseCase\", twoFactorDisableUseCase);\r\n\r\n const authController = new AuthController(\r\n loginUseCase,\r\n logoutUseCase,\r\n registerUseCase,\r\n refreshTokenUseCase,\r\n twoFactorSetupUseCase,\r\n twoFactorEnableUseCase,\r\n twoFactorVerifyUseCase,\r\n twoFactorDisableUseCase\r\n );\r\n\r\n return { container, authController, requireComplete2FA };\r\n}\r\n\r\nexport { createAuthContainer };","import { IBaseService, validateRepository } from \"cca-core\";\r\nimport { jwtDecode } from \"jwt-decode\";\r\n\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { LoginDTO } from \"../dtos/LoginDTO\";\r\nimport { validateAdminSecret, validateLoginDTO } from \"../validators/authValidation\";\r\nimport { JwtAuthService } from \"../../infrastructure/services/JwtAuthService\";\r\nimport { IJwtPayload } from \"../../domain/interfaces/IJwtPayload\";\r\n\r\n\r\nexport class LoginUseCase implements IBaseService {\r\n\r\n constructor(\r\n private readonly repository: AuthRepository,\r\n private readonly jwtService: JwtAuthService\r\n ) { }\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo: AuthRepository) => repo.getAll());\r\n }\r\n\r\n async execute(loginDTO: LoginDTO, providedAdminPassword: string, admin: boolean): Promise<{ id: string, accessToken: string, expiresAt: number, enabled?: boolean }> {\r\n if (admin) {\r\n await validateAdminSecret(providedAdminPassword);\r\n }\r\n \r\n const auth = await validateLoginDTO(loginDTO, this.repository);\r\n\r\n const accessToken = this.jwtService.generateAccessToken(auth.user, auth.role);\r\n const expiresAt = jwtDecode<IJwtPayload>(accessToken).exp;\r\n\r\n return { id: auth.user.id, accessToken: accessToken, expiresAt: expiresAt, enabled: auth.twoFactorEnabled };\r\n }\r\n}","import * as yup from \"yup\";\r\nimport { AuthEntity, UserRole } from \"cca-entities\";\r\nimport bcrypt from \"bcrypt\";\r\n\r\nimport {\r\n ForbiddenError,\r\n NotFoundError,\r\n ValidationError,\r\n} from \"../../utils/Errors\";\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\n\r\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\r\nimport { LoginDTO } from \"../dtos/LoginDTO\";\r\nimport { createConfigInstance } from \"../service/utils/configInstance\";\r\n\r\nconst schemas = {\r\n id: yup.string().uuid(\"Invalid user ID format\"),\r\n email: yup\r\n .string()\r\n .email(\"Invalid email format\")\r\n .max(255, \"Email cannot exceed 255 characters\"),\r\n name: yup\r\n .string()\r\n .required(\"Name is required\")\r\n .min(2, \"Name must be at least 2 characters long\")\r\n .max(50, \"Name cannot exceed 50 characters\")\r\n .matches(/^[a-zA-Z\\s]+$/, \"Name must only contain letters and spaces\"),\r\n password: yup\r\n .string()\r\n .required(\"Password required\")\r\n .min(8, \"Password too short\")\r\n .max(100, \"Password too long\")\r\n .matches(\r\n /^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]/,\r\n \"Password must contain uppercase, lowercase, number and special character\"\r\n ),\r\n role: yup\r\n .string()\r\n .oneOf(Object.values(UserRole), \"Invalid role specified\"),\r\n};\r\n\r\nexport const validateEmail = async (\r\n email: string,\r\n repository: AuthRepository\r\n): Promise<AuthEntity> => {\r\n try {\r\n await schemas.email.validate(email?.trim().toLowerCase());\r\n const user = await repository.findByEmail(email);\r\n if (!user) {\r\n throw new NotFoundError(\r\n \"The email address or password is incorrect. Please retry\"\r\n );\r\n }\r\n return user;\r\n } catch (error: any) {\r\n throw new ValidationError(error.message || \"Invalid email format\");\r\n }\r\n};\r\n\r\nexport const validatePassword = async (password?: string): Promise<void> => {\r\n if (password) {\r\n try {\r\n await schemas.password.validate(password);\r\n } catch (error: any) {\r\n throw new ValidationError(error.message || \"Invalid password format\");\r\n }\r\n }\r\n};\r\n\r\nexport const validateEmailUniqueness = async (\r\n repository: AuthRepository,\r\n email: string,\r\n excludeUserId?: string\r\n): Promise<void> => {\r\n try {\r\n await schemas.email.validate(email?.trim().toLowerCase());\r\n\r\n const existingUser = await repository.findByEmail(email);\r\n\r\n if (!existingUser) return;\r\n if (existingUser.id === excludeUserId) return;\r\n\r\n throw new ValidationError(`Email ${email} is already in use.`);\r\n } catch (error: any) {\r\n if (error instanceof ValidationError) {\r\n throw error;\r\n }\r\n throw new ValidationError(\"user email validation failed\");\r\n }\r\n};\r\n\r\nexport const validateRegisterDTO = async (\r\n auth: RegisterDTO,\r\n repository: AuthRepository\r\n): Promise<void> => {\r\n const { name, email, role, password } = auth;\r\n\r\n await Promise.all([\r\n schemas.name.validate(name),\r\n schemas.role.validate(role),\r\n validateEmailUniqueness(repository, email),\r\n validatePassword(password),\r\n ]);\r\n};\r\n\r\nexport const validateLoginDTO = async (\r\n data: LoginDTO,\r\n repository: AuthRepository\r\n): Promise<AuthEntity> => {\r\n const { email, role, password } = data;\r\n\r\n if (role) {\r\n await schemas.role.validate(role);\r\n }\r\n\r\n await schemas.password.validate(password);\r\n\r\n const auth = await validateEmail(email, repository);\r\n if (!auth || !auth.password) {\r\n throw new NotFoundError(\"Invalid credentials\");\r\n }\r\n\r\n const isMatch = await bcrypt.compare(password, auth.password);\r\n if (!isMatch) {\r\n throw new ForbiddenError(\"Invalid credentials\");\r\n }\r\n\r\n return auth;\r\n};\r\n\r\nexport const validateAdminSecret = async (\r\n secretPassword?: string\r\n): Promise<void> => {\r\n if (!secretPassword) {\r\n throw new ValidationError(\"Admin password is required\");\r\n }\r\n\r\n try {\r\n const config = await createConfigInstance();\r\n\r\n if (!config.adminSecretPassword) {\r\n throw new ValidationError(\"ADMIN_SECRET_PASSWORD not found in config\");\r\n }\r\n\r\n if (parseInt(secretPassword) !== parseInt(config.adminSecretPassword)) {\r\n throw new ValidationError(\"Invalid admin password\");\r\n }\r\n } catch (error) {\r\n if (error instanceof ValidationError) {\r\n throw error;\r\n }\r\n throw new ValidationError(\"Error validating admin password\");\r\n }\r\n};\r\n","import { IBaseService, validateRepository } from \"cca-core\";\r\n\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { NotFoundError } from \"../../utils/Errors\";\r\n\r\n\r\nexport class LogoutUseCase implements IBaseService {\r\n private readonly repository: AuthRepository\r\n\r\n constructor(repository: AuthRepository) {\r\n this.repository = repository;\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo: AuthRepository) => repo.getAll());\r\n }\r\n\r\n async execute(authId: string): Promise<void> {\r\n try {\r\n await this.repository.logout(authId);\r\n } catch (error) {\r\n new NotFoundError(\"Auth not found\");\r\n }\r\n }\r\n}","import { IBaseService, validateRepository } from \"cca-core\";\r\nimport * as bcrypt from \"bcrypt\";\r\nimport { AdminEntity, AuthEntity, UserEntity, UserRole } from \"cca-entities\";\r\n\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { RegistrationError, UnauthorizedError } from \"../../utils/Errors\";\r\nimport { mapper } from \"../mappers/utils/mapper\";\r\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\r\nimport { validateAdminSecret, validateRegisterDTO } from \"../validators/authValidation\";\r\n\r\nexport class RegisterUseCase implements IBaseService {\r\n private readonly SALT_ROUNDS = 10;\r\n\r\n constructor(private readonly repository: AuthRepository) {}\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo) => repo.getAll());\r\n }\r\n\r\n public async execute(\r\n email: string,\r\n name: string,\r\n password: string,\r\n role: UserRole = UserRole.GUEST,\r\n adminPassword?: string\r\n ): Promise<AuthEntity | undefined> {\r\n try {\r\n const normalizedDTO = this._normalizeInput({ email, name, password, role, adminPassword });\r\n\r\n const isAdminUser = await this._validateAdminRegistration(\r\n normalizedDTO.role,\r\n normalizedDTO.adminPassword\r\n );\r\n\r\n await validateRegisterDTO(normalizedDTO, this.repository);\r\n\r\n const hashedPassword = await this._hashPassword(normalizedDTO.password);\r\n const authEntity = this._buildMappedAuthEntity(normalizedDTO, hashedPassword, isAdminUser);\r\n\r\n return this.repository.create(authEntity);\r\n } catch (error) {\r\n throw new RegistrationError(\r\n `Registration failed: ${error instanceof Error ? error.message : \"Unknown error\"}`\r\n );\r\n }\r\n }\r\n\r\n private _normalizeInput(dto: RegisterDTO): RegisterDTO {\r\n return {\r\n name: dto.name.trim(),\r\n email: dto.email.trim().toLowerCase(),\r\n password: dto.password.trim(),\r\n role: dto.role,\r\n adminPassword: dto.adminPassword?.trim()\r\n };\r\n }\r\n\r\n private async _hashPassword(password: string): Promise<string> {\r\n return bcrypt.hash(password, this.SALT_ROUNDS);\r\n }\r\n\r\n private async _validateAdminRegistration(\r\n role: UserRole,\r\n adminPassword?: string\r\n ): Promise<boolean> {\r\n if (role !== UserRole.ADMIN) return false;\r\n\r\n if (!adminPassword) {\r\n throw new UnauthorizedError(\"Admin password is required for admin registration\");\r\n }\r\n\r\n await validateAdminSecret(adminPassword);\r\n return true;\r\n }\r\n\r\n private _buildMappedAuthEntity(\r\n dto: RegisterDTO,\r\n hashedPassword: string,\r\n isAdmin: boolean\r\n ): AuthEntity {\r\n const authEntity = mapper.map(dto, RegisterDTO, AuthEntity);\r\n const userOrAdminEntity = isAdmin\r\n ? mapper.map(dto, RegisterDTO, AdminEntity)\r\n : mapper.map(dto, RegisterDTO, UserEntity);\r\n\r\n userOrAdminEntity.updatedAt = undefined as unknown as Date;\r\n\r\n if (isAdmin) {\r\n authEntity.admin = userOrAdminEntity;\r\n } else {\r\n authEntity.user = userOrAdminEntity;\r\n }\r\n\r\n authEntity.password = hashedPassword;\r\n authEntity.refreshToken = \"\";\r\n\r\n return authEntity;\r\n }\r\n}\r\n","import { createMapper } from '@automapper/core';\r\nimport { classes } from '@automapper/classes';\r\n\r\nimport { createUserMappings } from '../createUserMappings';\r\n\r\nexport const mapper = createMapper({\r\n strategyInitializer: classes(),\r\n});\r\n\r\ncreateUserMappings(mapper);\r\n","import { Mapper, createMap, forMember, mapFrom } from '@automapper/core';\r\nimport { AdminEntity, AuthEntity, UserEntity } from 'cca-entities';\r\n\r\nimport { RegisterDTO } from '../dtos/RegisterDTO';\r\nimport { UserDTO } from '../dtos/UserDTO';\r\nimport { AdminDTO } from '../dtos/AdminDTO';\r\n\r\nexport function createUserMappings(mapper: Mapper): void {\r\n createMap(\r\n mapper,\r\n RegisterDTO,\r\n AuthEntity,\r\n forMember(dest => dest.email, mapFrom(src => src.email)),\r\n forMember(dest => dest.password, mapFrom(src => src.password)),\r\n forMember(dest => dest.role, mapFrom(src => src.role)));\r\n\r\n createMap(\r\n mapper,\r\n RegisterDTO,\r\n UserEntity,\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)));\r\n\r\n createMap(\r\n mapper,\r\n RegisterDTO,\r\n AdminEntity,\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)));\r\n\r\n createMap(\r\n mapper,\r\n UserEntity,\r\n UserDTO,\r\n forMember(dest => dest.id, mapFrom(src => src.id)),\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)),\r\n forMember(dest => dest.profileImageUrl, mapFrom(src => getProfileImageUrl(src))));\r\n\r\n\r\n createMap(\r\n mapper,\r\n AdminEntity,\r\n AdminDTO,\r\n forMember(dest => dest.id, mapFrom(src => src.id)),\r\n forMember(dest => dest.name, mapFrom(src => src.name)),\r\n forMember(dest => dest.email, mapFrom(src => src.email)));\r\n\r\n const getProfileImageUrl = (src: UserEntity): string | undefined => {\r\n const image = src.images?.[0];\r\n if (!image) return undefined;\r\n return image.mdUrl ?? image.smUrl ?? image.lgUrl ?? image.thumbUrl ?? image.originalUrl ?? image.xlUrl;\r\n };\r\n}","import { UserRole } from \"cca-entities\";\r\n\r\nexport class RegisterDTO {\r\n email!: string;\r\n name!: string;\r\n password!: string;\r\n role!: UserRole;\r\n adminPassword?: string;\r\n}\r\n","import { AutoMap } from \"@automapper/classes\";\r\nimport { UserRole } from \"cca-entities\";\r\n\r\nexport class UserDTO {\r\n @AutoMap()\r\n id!: string;\r\n\r\n @AutoMap()\r\n name!: string;\r\n\r\n @AutoMap()\r\n email!: string;\r\n\r\n @AutoMap()\r\n role!: UserRole;\r\n\r\n @AutoMap()\r\n profileImageUrl?: string;\r\n}","import { AutoMap } from \"@automapper/classes\";\r\nimport { UserRole } from \"cca-entities\";\r\n\r\nexport class AdminDTO {\r\n @AutoMap()\r\n id!: string;\r\n\r\n @AutoMap()\r\n name!: string;\r\n\r\n @AutoMap()\r\n email!: string;\r\n\r\n @AutoMap()\r\n role!: UserRole;\r\n\r\n adminPassword!: string;\r\n}","import { IBaseService, validateRepository } from \"cca-core\";\r\nimport { JwtAuthService } from \"../../infrastructure/services/JwtAuthService\";\r\nimport { AuthRepository } from \"../../infrastructure/repository/AuthRepository\";\r\nimport { ITokenPair } from \"../../domain/interfaces/ITokenPair\";\r\n\r\nexport class RefreshTokenUseCase implements IBaseService {\r\n private readonly repository: AuthRepository;\r\n private readonly service: JwtAuthService;\r\n\r\n constructor(repository: AuthRepository, service: JwtAuthService) {\r\n this.repository = repository;\r\n this.service = service;\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n await validateRepository(this.repository, (repo: AuthRepository) => repo.getAll());\r\n }\r\n\r\n public async execute(refreshToken: string): Promise<ITokenPair | null> {\r\n try {\r\n const decoded = await this.service.verifyRefreshToken(refreshToken);\r\n\r\n if (!decoded.userId) {\r\n return null;\r\n }\r\n\r\n let authEntity = await this.repository.findByUseAdminId(decoded.userId);\r\n\r\n if (!authEntity) {\r\n authEntity = await this.repository.findByUseAdminId(decoded.userId, true);\r\n }\r\n\r\n if (!authEntity) {\r\n return null;\r\n }\r\n\r\n const user = authEntity.role === \"admin\" ? authEntity.admin : authEntity.user;\r\n\r\n const accessToken = this.service.generateAccessToken(user, authEntity.role);\r\n const newRefreshToken = this.service.generateRefreshToken(user);\r\n\r\n await this.repository.update(authEntity.id, {\r\n refreshToken: newRefreshToken\r\n });\r\n\r\n return {\r\n accessToken,\r\n refreshToken: newRefreshToken\r\n };\r\n } catch (error) {\r\n return null;\r\n }\r\n }\r\n}","import { IBaseService } from 'cca-core';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { ITwoFactorSetupResponse } from '../../domain/interfaces/ITwoFactorSetupResponse';\r\n\r\nimport { ForbiddenError, TwoFactorError } from '../../utils/Errors';\r\n\r\nexport class TwoFactorSetupUseCase implements IBaseService {\r\n private twoFactorService: TwoFactorService;\r\n private authRepository: AuthRepository;\r\n private isInitialized = false;\r\n\r\n constructor(twoFactorService: TwoFactorService, authRepository: AuthRepository) {\r\n this.twoFactorService = twoFactorService;\r\n this.authRepository = authRepository;\r\n }\r\n async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n\r\n await Promise.all([\r\n this.twoFactorService.initialize()\r\n ]);\r\n\r\n this.isInitialized = true;\r\n }\r\n\r\n async execute(userId: string): Promise<ITwoFactorSetupResponse> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n\r\n const user = await this.authRepository.findByUserId(userId);\r\n\r\n if (!user) {\r\n throw new ForbiddenError('User not found');\r\n }\r\n\r\n if (user.twoFactorEnabled) {\r\n throw new TwoFactorError('Two-factor authentication is already enabled');\r\n }\r\n\r\n const { secret, otpAuthUrl } = this.twoFactorService.generateSecret(user.email);\r\n const qrCodeUrl = await this.twoFactorService.generateQRCode(otpAuthUrl);\r\n\r\n await this.authRepository.updateTwoFactorSecret(userId, secret);\r\n\r\n return { qrCodeUrl };\r\n }\r\n}","import { IBaseService, validateRepository } from 'cca-core';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { ITwoFactorEnable } from '../../domain/interfaces/ITwoFactorEnable';\r\nimport { TwoFactorError } from '../../utils/Errors';\r\nimport { AuthEntity } from 'cca-entities';\r\n\r\nexport class TwoFactorEnableUseCase implements IBaseService{\r\n private twoFactorService: TwoFactorService;\r\n private authRepository: AuthRepository;\r\n private isInitialized = false;\r\n\r\n constructor(twoFactorService: TwoFactorService, authRepository: AuthRepository) {\r\n this.twoFactorService = twoFactorService;\r\n this.authRepository = authRepository;\r\n \r\n }\r\n async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n \r\n await Promise.all([\r\n this.twoFactorService.initialize(),\r\n validateRepository(this.authRepository, repo => repo.getAll())\r\n ]);\r\n \r\n this.isInitialized = true;\r\n }\r\n\r\n async execute( dto: ITwoFactorEnable): Promise<void> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n \r\n const { token, userId } = dto;\r\n \r\n if (!token) {\r\n throw new TwoFactorError('Token is required');\r\n }\r\n \r\n const auth: AuthEntity | null = await this.authRepository.findByUserId(userId); \r\n \r\n if (!auth || !auth.twoFactorSecret) {\r\n throw new TwoFactorError('Please set up two-factor authentication first');\r\n }\r\n \r\n if (auth.twoFactorEnabled) {\r\n throw new TwoFactorError('Two-factor authentication is already enabled');\r\n }\r\n \r\n const isValid = this.twoFactorService.verifyToken(token, auth.twoFactorSecret);\r\n \r\n if (!isValid) {\r\n throw new TwoFactorError('Invalid verification code');\r\n }\r\n \r\n await this.authRepository.enableTwoFactor(auth);\r\n }\r\n}","import { IBaseService, validateRepository } from 'cca-core';\r\nimport { AdminEntity, AuthEntity, UserEntity } from 'cca-entities';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { JwtAuthService } from '../../infrastructure/services/JwtAuthService';\r\nimport { ITwoFactorVerify } from '../../domain/interfaces/ITwoFactorVerify';\r\nimport { ITokenPair } from '../../domain/interfaces/ITokenPair';\r\nimport { TwoFactorError } from '../../utils/Errors';\r\nimport { AdminDTO } from '../dtos/AdminDTO';\r\nimport { UserDTO } from '../dtos/UserDTO';\r\nimport { mapper } from '../mappers/utils/mapper';\r\n\r\nexport class TwoFactorVerifyUseCase implements IBaseService {\r\n private isInitialized = false;\r\n\r\n constructor(\r\n private readonly twoFactorService: TwoFactorService,\r\n private readonly authRepository: AuthRepository,\r\n private readonly jwtService: JwtAuthService\r\n ) { }\r\n\r\n public async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n await Promise.all([\r\n this.twoFactorService.initialize(),\r\n this.jwtService.initialize(),\r\n validateRepository(this.authRepository, repo => repo.getAll())\r\n ]);\r\n this.isInitialized = true;\r\n }\r\n\r\n public async execute(dto: ITwoFactorVerify): Promise<{ token: string; refreshToken: string; data?: AdminDTO | UserDTO } | null> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n\r\n const { userId, token } = dto;\r\n if (!userId || !token) {\r\n throw new TwoFactorError('User ID and token are required.');\r\n }\r\n\r\n const auth: AuthEntity | null = await this.authRepository.findByUserId(userId);\r\n if (!auth || !auth.twoFactorSecret || !auth.twoFactorEnabled) {\r\n throw new TwoFactorError('Invalid request.');\r\n }\r\n\r\n const isValid = this.twoFactorService.verifyToken(token, auth.twoFactorSecret);\r\n if (!isValid) {\r\n throw new TwoFactorError('Invalid verification code.');\r\n }\r\n\r\n const tokenPair: ITokenPair = this.generateTokens(auth);\r\n await this.updateUserStatus(auth);\r\n await this.updateUserRefreshToken(auth, tokenPair.refreshToken);\r\n\r\n if (auth.admin) {\r\n return {\r\n token: tokenPair.accessToken,\r\n refreshToken: tokenPair.refreshToken,\r\n data: this.mapAdminToDTO(auth.admin)\r\n };\r\n }\r\n\r\n if (auth.user) {\r\n return {\r\n token: tokenPair.accessToken,\r\n refreshToken: tokenPair.refreshToken,\r\n data: this.mapUserToDTO(auth.user)\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private mapAdminToDTO(admin: AdminEntity): AdminDTO {\r\n return mapper.map(admin, AdminEntity, AdminDTO);\r\n }\r\n\r\n private mapUserToDTO(user: UserEntity): UserDTO {\r\n return mapper.map(user, UserEntity, UserDTO);\r\n }\r\n\r\n private async updateUserStatus(auth: AuthEntity): Promise<void> {\r\n auth.user.lastLoginAt = new Date();\r\n auth.user.isActive = true;\r\n await this.authRepository.update(auth.id, auth);\r\n }\r\n\r\n private async updateUserRefreshToken(auth: AuthEntity, refreshToken: string): Promise<void> {\r\n auth.refreshToken = refreshToken;\r\n await this.authRepository.update(auth.id, { refreshToken });\r\n }\r\n\r\n private generateTokens(auth: AuthEntity): ITokenPair {\r\n return {\r\n accessToken: this.jwtService.generateAccessToken(auth.user, auth.role),\r\n refreshToken: this.jwtService.generateRefreshToken(auth.user)\r\n };\r\n }\r\n}\r\n","import { IBaseService, validateRepository } from 'cca-core';\r\n\r\nimport { TwoFactorService } from '../../infrastructure/services/TwoFactorService';\r\nimport { AuthRepository } from '../../infrastructure/repository/AuthRepository';\r\nimport { ITwoFactorEnable } from '../../domain/interfaces/ITwoFactorEnable';\r\n\r\nimport { TwoFactorError } from '../../utils/Errors';\r\n\r\nexport class TwoFactorDisableUseCase implements IBaseService{\r\n private twoFactorService: TwoFactorService;\r\n private authRepository: AuthRepository;\r\n private isInitialized = false;\r\n\r\n constructor(twoFactorService: TwoFactorService, authRepository: AuthRepository) {\r\n this.twoFactorService = twoFactorService;\r\n this.authRepository = authRepository;\r\n }\r\n async initialize(): Promise<void> {\r\n if (this.isInitialized) return;\r\n \r\n await Promise.all([\r\n this.twoFactorService.initialize(),\r\n validateRepository(this.authRepository, repo => repo.getAll())\r\n ]);\r\n4\r\n this.isInitialized = true;\r\n }\r\n\r\n async execute(userId: string, dto: ITwoFactorEnable): Promise<void> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n \r\n const { token } = dto; \r\n \r\n const user = await this.authRepository.findByUserId(userId); \r\n \r\n if (!user || !user.twoFactorSecret || !user.twoFactorEnabled) {\r\n throw new TwoFactorError('Two-factor authentication is not enabled');\r\n }\r\n \r\n const isValid = this.twoFactorService.verifyToken(token, user.twoFactorSecret);\r\n \r\n if (!isValid) {\r\n throw new TwoFactorError('Invalid verification code');\r\n }\r\n \r\n await this.authRepository.disableTwoFactor(user);\r\n }\r\n}","export const HTTP_STATUS = {\r\n OK: 200,\r\n CREATED: 201,\r\n} as const;\r\n\r\nexport const AUTH_STATUS = {\r\n BASIC_AUTH: \"basic_auth\",\r\n NEEDS_SETUP: \"needs_setup\",\r\n PENDING_VERIFICATION: \"pending_verification\",\r\n FULL_AUTH: \"full_auth\",\r\n LOGGED_OUT:\"logged_out\",\r\n REGISTERED:\"registered\",\r\n TOKEN_REFRESHED:\"token_refreshed\"\r\n} as const;\r\n\r\nexport const MESSAGES = {\r\n LOGIN_SUCCESS: \"Login successful\",\r\n ADMIN_LOGIN_SUCCESS: \"Admin login successful\",\r\n LOGOUT_SUCCESS: \"Logged out successfully\",\r\n REGISTER_SUCCESS: \"User registered successfully\",\r\n TOKEN_REFRESH_SUCCESS: \"Token refreshed successfully\",\r\n TWO_FA_SETUP_SUCCESS: \"Two-factor authentication setup initiated\",\r\n TWO_FA_ENABLE_SUCCESS: \"Two-factor authentication enabled\",\r\n TWO_FA_VERIFY_SUCCESS: \"Two-factor authentication verified successfully\",\r\n TWO_FA_DISABLE_SUCCESS: \"Two-factor authentication disabled\",\r\n} as const;","import { NextFunction, Request, Response } from \"express\";\r\n\r\nimport { LoginDTO } from \"../../application/dtos/LoginDTO\";\r\nimport { RegisterDTO } from \"../../application/dtos/RegisterDTO\";\r\n\r\nimport { RegisterUseCase } from \"../../application/useCase/RegisterUseCase\";\r\nimport { LoginUseCase } from \"../../application/useCase/LoginUseCase\";\r\nimport { LogoutUseCase } from \"../../application/useCase/LogoutUseCase\";\r\nimport { RefreshTokenUseCase } from \"../../application/useCase/RefreshTokenUseCase\";\r\nimport { TwoFactorSetupUseCase } from \"../../application/useCase/TwoFactorSetupUseCase\";\r\nimport { TwoFactorEnableUseCase } from \"../../application/useCase/TwoFactorEnableUseCase\";\r\nimport { TwoFactorVerifyUseCase } from \"../../application/useCase/TwoFactorVerifyUseCase\";\r\nimport { TwoFactorDisableUseCase } from \"../../application/useCase/TwoFactorDisableUseCase\";\r\n\r\nimport { IRefreshTokenRequest } from \"../../domain/interfaces/IRefreshTokenRequest\";\r\nimport { ITwoFactorEnable } from \"../../domain/interfaces/ITwoFactorEnable\";\r\nimport { ITwoFactorVerify } from \"../../domain/interfaces/ITwoFactorVerify\";\r\nimport { ForbiddenError } from \"../../utils/Errors\";\r\nimport { ApiResponse, AuthData } from \"../../domain/interfaces/ApiResponse\";\r\nimport { AUTH_STATUS, HTTP_STATUS, MESSAGES } from \"../constants/constants\";\r\n\r\nexport class AuthController {\r\n private readonly loginUseCase: LoginUseCase;\r\n private readonly logoutUseCase: LogoutUseCase;\r\n private readonly registerUseCase: RegisterUseCase;\r\n private readonly refreshTokenUseCase: RefreshTokenUseCase;\r\n private readonly twoFactorSetupUseCase: TwoFactorSetupUseCase;\r\n private readonly twoFactorEnableUseCase: TwoFactorEnableUseCase;\r\n private readonly twoFactorVerifyUseCase: TwoFactorVerifyUseCase;\r\n private readonly twoFactorDisableUseCase: TwoFactorDisableUseCase;\r\n\r\n constructor(\r\n loginUseCase: LoginUseCase,\r\n logoutUseCase: LogoutUseCase,\r\n registerUseCase: RegisterUseCase,\r\n refreshTokenUseCase: RefreshTokenUseCase,\r\n twoFactorSetupUseCase: TwoFactorSetupUseCase,\r\n twoFactorEnableUseCase: TwoFactorEnableUseCase,\r\n twoFactorVerifyUseCase: TwoFactorVerifyUseCase,\r\n twoFactorDisableUseCase: TwoFactorDisableUseCase\r\n ) {\r\n this.loginUseCase = loginUseCase;\r\n this.logoutUseCase = logoutUseCase;\r\n this.registerUseCase = registerUseCase;\r\n this.refreshTokenUseCase = refreshTokenUseCase;\r\n this.twoFactorSetupUseCase = twoFactorSetupUseCase;\r\n this.twoFactorEnableUseCase = twoFactorEnableUseCase;\r\n this.twoFactorVerifyUseCase = twoFactorVerifyUseCase;\r\n this.twoFactorDisableUseCase = twoFactorDisableUseCase;\r\n }\r\n\r\n private createResponse<T>(\r\n message: string,\r\n data?: T,\r\n meta?: Record<string, any>\r\n ): ApiResponse<T> {\r\n return {\r\n success: true,\r\n message,\r\n data,\r\n meta: {\r\n timestamp: new Date().toISOString(),\r\n ...meta,\r\n },\r\n };\r\n }\r\n\r\n private createAuthData(\r\n hasAccessToken: boolean,\r\n enabled: boolean,\r\n status: string,\r\n verified?: boolean\r\n ): AuthData {\r\n return {\r\n hasAccessToken,\r\n enabled,\r\n status,\r\n ...(verified !== undefined && { verified }),\r\n };\r\n }\r\n\r\n private sendResponse<T>(\r\n res: Response,\r\n statusCode: number,\r\n message: string,\r\n data?: T,\r\n meta?: Record<string, any>\r\n ): void {\r\n const response = this.createResponse(message, data, meta);\r\n res.status(statusCode).json(response);\r\n }\r\n\r\n login = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const loginDTO: LoginDTO = req.body;\r\n const result = await this.loginUseCase.execute(loginDTO, \"\", false);\r\n\r\n const twoFactorEnabled = result.enabled ?? false;\r\n\r\n const loginData = {\r\n accessToken: result.accessToken,\r\n userId: result.id,\r\n expiresAt: result.expiresAt,\r\n auth: this.createAuthData(\r\n true, // hasAccessToken\r\n twoFactorEnabled, // enable (2FA enabled status)\r\n twoFactorEnabled ? AUTH_STATUS.PENDING_VERIFICATION : AUTH_STATUS.BASIC_AUTH,\r\n false // verified - always false for basic login\r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.LOGIN_SUCCESS, loginData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n adminLogin = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const { adminPassword, ...loginDTO }: LoginDTO = req.body;\r\n\r\n if (!adminPassword) {\r\n throw new ForbiddenError(\"Admin password is required\");\r\n }\r\n\r\n const result = await this.loginUseCase.execute(loginDTO, adminPassword, true);\r\n\r\n const adminLoginData = {\r\n message: result,\r\n auth: this.createAuthData(\r\n true,\r\n false,\r\n AUTH_STATUS.BASIC_AUTH,\r\n false\r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.CREATED, MESSAGES.ADMIN_LOGIN_SUCCESS, adminLoginData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n logout = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n await this.logoutUseCase.execute(req.body.id);\r\n\r\n const logoutData = {\r\n auth: this.createAuthData(\r\n false,\r\n false,\r\n AUTH_STATUS.LOGGED_OUT,\r\n false\r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.LOGOUT_SUCCESS, logoutData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n register = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const { email, name, password, role, adminPassword }: RegisterDTO = req.body;\r\n\r\n await this.registerUseCase.execute(email, name, password, role, adminPassword);\r\n\r\n const registerData = {\r\n auth: this.createAuthData(\r\n false,\r\n false,\r\n AUTH_STATUS.REGISTERED,\r\n false\r\n ),\r\n };\r\n\r\n this.sendResponse(\r\n res,\r\n HTTP_STATUS.OK,\r\n MESSAGES.REGISTER_SUCCESS,\r\n registerData,\r\n { status: true }\r\n );\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n refreshToken = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const { refreshToken }: IRefreshTokenRequest = req.body;\r\n\r\n const result = await this.refreshTokenUseCase.execute(refreshToken);\r\n\r\n if (!result) {\r\n throw new Error(\"Failed to refresh token\");\r\n }\r\n\r\n const refreshData = {\r\n accessToken: result.accessToken,\r\n refreshToken: result.refreshToken,\r\n auth: this.createAuthData(\r\n true,\r\n false,\r\n AUTH_STATUS.BASIC_AUTH,\r\n false\r\n ),\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TOKEN_REFRESH_SUCCESS, refreshData);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n setup2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n if (!req.auth?.id) {\r\n throw new ForbiddenError(\"User authentication required\");\r\n }\r\n\r\n const result = await this.twoFactorSetupUseCase.execute(req.auth.id);\r\n\r\n const setupData = {\r\n qrCode: result.qrCodeUrl,\r\n auth: this.createAuthData(true, false, AUTH_STATUS.NEEDS_SETUP),\r\n };\r\n\r\n const meta = {\r\n nextStep: \"Scan the QR code and enter your first code to verify\",\r\n redirectTo: \"/2fa-enable\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_SETUP_SUCCESS, setupData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n enable2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const dto: ITwoFactorEnable = { ...req.body, userId: req.auth?.id };\r\n await this.twoFactorEnableUseCase.execute(dto);\r\n\r\n const enableData = {\r\n enabledAt: new Date().toISOString(),\r\n auth: this.createAuthData(true, true, AUTH_STATUS.PENDING_VERIFICATION),\r\n };\r\n\r\n const meta = {\r\n nextStep: \"Proceed to verify with a valid 2FA token\",\r\n redirectTo: \"/verify-2fa\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_ENABLE_SUCCESS, enableData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n verify2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const dto: ITwoFactorVerify = req.body;\r\n const result = await this.twoFactorVerifyUseCase.execute(dto);\r\n\r\n const verifyData = {\r\n token: result?.token,\r\n refreshToken: result?.refreshToken,\r\n user: {\r\n id: result?.data?.id,\r\n email: result?.data?.email,\r\n name: result?.data?.name,\r\n role: result?.data?.role,\r\n },\r\n auth: this.createAuthData(true, true, AUTH_STATUS.FULL_AUTH, true),\r\n };\r\n\r\n const meta = {\r\n recommendation: \"You're fully authenticated\",\r\n redirectTo: \"/\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_VERIFY_SUCCESS, verifyData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n\r\n disable2FA = async (req: Request, res: Response, next: NextFunction): Promise<void> => {\r\n try {\r\n const userId = req.auth!.id;\r\n const dto: ITwoFactorEnable = req.body;\r\n\r\n await this.twoFactorDisableUseCase.execute(userId, dto);\r\n\r\n const disableData = {\r\n disabledAt: new Date().toISOString(),\r\n auth: this.createAuthData(true, false, AUTH_STATUS.BASIC_AUTH, false),\r\n };\r\n\r\n const meta = {\r\n securityNote: \"Account now relies only on password. Re-enable 2FA for better security.\",\r\n redirectTo: \"/login\",\r\n };\r\n\r\n this.sendResponse(res, HTTP_STATUS.OK, MESSAGES.TWO_FA_DISABLE_SUCCESS, disableData, meta);\r\n } catch (error) {\r\n next(error);\r\n }\r\n };\r\n}","import { NextFunction, Request, Response } from 'express';\r\nimport { JwtAuthService } from '../../infrastructure/services/JwtAuthService';\r\n\r\nexport class RequireComplete2FA {\r\n private readonly jwtService: JwtAuthService;\r\n\r\n constructor(jwtService: JwtAuthService) {\r\n this.jwtService = jwtService;\r\n }\r\n\r\n public async execute(req: Request, res: Response, next: NextFunction) {\r\n try {\r\n const token = req.headers.authorization?.split(' ')[1];\r\n\r\n if (!token) {\r\n return res.status(401).json({ message: 'Authentication required' });\r\n }\r\n\r\n const decoded = await this.jwtService.verifyAccessToken(token);\r\n\r\n if (!decoded.twoFactorAuthenticated) {\r\n return res.status(403).json({\r\n message: 'Two-factor authentication required',\r\n code: 'REQUIRE_2FA',\r\n userId: decoded.id\r\n });\r\n }\r\n\r\n req.auth = { ...decoded, twoFactorAuthenticated: true };\r\n next();\r\n } catch (error) {\r\n return res.status(401).json({ message: 'Invalid or expired token' });\r\n }\r\n }\r\n}","import { BaseRepository, IExtendedBaseRepository } from \"cca-core\";\r\nimport { AuthEntity } from \"cca-entities\";\r\nimport { Repository } from \"typeorm\";\r\nimport { NotFoundError } from \"../../utils/Errors\";\r\n\r\nexport class AuthRepository\r\n extends BaseRepository<AuthEntity>\r\n implements IExtendedBaseRepository<AuthEntity> {\r\n constructor(repository: Repository<AuthEntity>) {\r\n super(repository);\r\n }\r\n\r\n async findByEmail(email: string): Promise<AuthEntity | null> {\r\n const query = this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .addSelect(\"auth.password\")\r\n .where(\"auth.email = :email\", { email });\r\n\r\n return await query.getOne();\r\n }\r\n\r\n async create(entity: Omit<AuthEntity, \"createdAt\">): Promise<AuthEntity> {\r\n return super.create(entity);\r\n }\r\n\r\n async findByUserId(userId: string): Promise<AuthEntity | null> {\r\n const query = this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .addSelect(\"auth.twoFactorSecret\")\r\n .where(\"user.id = :userId\", { userId });\r\n\r\n return await query.getOne();;\r\n }\r\n\r\n async findByUseAdminId(userId: string, isAdmin: boolean = false): Promise<AuthEntity | null> {\r\n const query = this.repository\r\n .createQueryBuilder(\"auth\")\r\n .addSelect(\"auth.twoFactorSecret\");\r\n\r\n if (isAdmin) {\r\n query.leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .where(\"admin.id = :userId\", { userId });\r\n } else {\r\n query.leftJoinAndSelect(\"auth.user\", \"user\")\r\n .where(\"user.id = :userId\", { userId });\r\n }\r\n\r\n return await query.getOne();\r\n }\r\n\r\n async logout(userId: string): Promise<void> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n auth.refreshToken = \"\";\r\n auth.user.isActive = false;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async updateTwoFactorSecret(userId: string, secret: string): Promise<void> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n auth.twoFactorSecret = secret;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async enableTwoFactor(auth: AuthEntity): Promise<void> {\r\n\r\n auth.twoFactorEnabled = true;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async disableTwoFactor(auth: AuthEntity): Promise<void> {\r\n\r\n auth.twoFactorEnabled = false;\r\n auth.twoFactorSecret = null;\r\n\r\n await this.update(auth.id, auth);\r\n }\r\n\r\n async isTwoFactorEnabled(userId: string): Promise<boolean> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n return !!auth.twoFactorEnabled;\r\n }\r\n\r\n async getTwoFactorSecret(userId: string): Promise<string | null> {\r\n const auth = await this.findByUserId(userId);\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n\r\n return auth.twoFactorSecret;\r\n }\r\n}\r\n","import * as jwt from \"jsonwebtoken\";\r\nimport { Secret, SignOptions } from \"jsonwebtoken\";\r\nimport * as bcrypt from \"bcrypt\";\r\nimport { IBaseService, validateRepository } from \"cca-core\";\r\nimport { AuthEntity, UserEntity, UserRole } from \"cca-entities\";\r\n\r\nimport { IJwtConfig } from \"../../domain/interfaces/IJwtConfig\";\r\nimport { IAuthService } from \"../../domain/interfaces/IAuthService\";\r\nimport { IDecodedToken } from \"../../domain/interfaces/IDecodedToken\";\r\n\r\nimport {\r\n ForbiddenError,\r\n JwtError,\r\n NotFoundError,\r\n UnauthorizedError,\r\n} from \"../../utils/Errors\";\r\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nimport { createConfigInstance } from \"../../application/service/utils/configInstance\";\r\nimport { log } from \"console\";\r\n\r\nexport class JwtAuthService implements IBaseService, IAuthService {\r\n private jwtConfig: IJwtConfig | undefined;\r\n\r\n constructor(private readonly repository: AuthRepository, config?: IJwtConfig) {\r\n this.loadConfig(config);\r\n }\r\n\r\n private async loadConfig(config?: IJwtConfig) {\r\n const configData = await createConfigInstance();\r\n\r\n this.jwtConfig = {\r\n accessTokenSecret: configData.accessTokenSecret,\r\n refreshTokenSecret: configData.refreshTokenSecret,\r\n accessTokenExpiry: parseInt(configData.accessTokenExpiry, 10),\r\n refreshTokenExpiry: parseInt(configData.refreshTokenExpiry, 10),\r\n ...config,\r\n };\r\n\r\n this.validateConfiguration();\r\n }\r\n\r\n async initialize(): Promise<void> {\r\n await validateRepository(this.repository, repo => repo.getAll());\r\n }\r\n\r\n private validateConfiguration(): void {\r\n if (!this.jwtConfig?.accessTokenSecret || !this.jwtConfig?.refreshTokenSecret) {\r\n throw new JwtError(\"JWT secrets required in config\");\r\n }\r\n }\r\n\r\n async validateUser(email: string, password: string): Promise<AuthEntity | null> {\r\n const user = await this.repository.findByEmail(email);\r\n if (!user) {\r\n throw new NotFoundError(\"Invalid credentials\");\r\n }\r\n\r\n const validPassword = await bcrypt.compare(password, user.password);\r\n if (!validPassword) {\r\n throw new ForbiddenError(\"Invalid credentials\");\r\n }\r\n\r\n return user;\r\n }\r\n\r\n private verifyJwtConfig() {\r\n if (!this.jwtConfig) throw new JwtError(\"JWT config not loaded\");\r\n }\r\n\r\n generateAccessToken(user: UserEntity, role : UserRole): string {\r\n this.verifyJwtConfig();\r\n return jwt.sign(\r\n { userId: user.id, email: user.email, role: role },\r\n this.jwtConfig!.accessTokenSecret as Secret,\r\n { expiresIn: this.jwtConfig!.accessTokenExpiry }\r\n );\r\n }\r\n\r\n generateRefreshToken(user: UserEntity): string {\r\n this.verifyJwtConfig();\r\n return jwt.sign(\r\n { userId: user.id },\r\n this.jwtConfig!.refreshTokenSecret as Secret,\r\n { expiresIn: this.jwtConfig!.refreshTokenExpiry }\r\n );\r\n }\r\n\r\n async verifyToken(token: string, secret: string): Promise<IDecodedToken> {\r\n try {\r\n console.log(\"Verifying token:\", token);\r\n console.log(\"Using secret:\", secret);\r\n \r\n return jwt.verify(token, secret) as IDecodedToken;\r\n } catch(error) {\r\n console.error(\"Error verifying token:\", error);\r\n throw new UnauthorizedError();\r\n }\r\n }\r\n\r\n async verifyAccessToken(token: string): Promise<IDecodedToken> {\r\n this.verifyJwtConfig();\r\n return this.verifyToken(token, this.jwtConfig!.accessTokenSecret);\r\n }\r\n\r\n async verifyRefreshToken(token: string): Promise<IDecodedToken> {\r\n this.verifyJwtConfig();\r\n return this.verifyToken(token, this.jwtConfig!.refreshTokenSecret);\r\n }\r\n}\r\n","import * as speakeasy from 'speakeasy';\r\nimport * as QRCode from 'qrcode';\r\nimport { IBaseService } from 'cca-core';\r\n\r\nimport { IConfig } from '../../domain/interfaces/configTypes';\r\nimport { TwoFactorError } from '../../utils/Errors';\r\n\r\nexport class TwoFactorService implements IBaseService {\r\n private readonly config: IConfig;\r\n private initialized: boolean = false;\r\n private readonly twoFactorConfig: {\r\n tokenWindow: number;\r\n secretLength: number;\r\n qrCodeOptions: QRCode.QRCodeToDataURLOptions;\r\n };\r\n\r\n constructor(config: IConfig) {\r\n this.config = config;\r\n \r\n this.twoFactorConfig = {\r\n tokenWindow: parseInt(config.tokenWindow) ?? 1,\r\n secretLength: parseInt(config.secretLength) ?? 20,\r\n qrCodeOptions: {\r\n errorCorrectionLevel: 'M',\r\n margin: 4,\r\n scale: 4,\r\n color: {\r\n dark: '#000000',\r\n light: '#ffffff'\r\n }\r\n }\r\n };\r\n }\r\n\r\n public async initialize(): Promise<void> {\r\n if (this.initialized) return;\r\n\r\n try {\r\n this.validateConfiguration();\r\n this.initialized = true;\r\n } catch (error) {\r\n console.error('TwoFactorService initialization failed:', error);\r\n throw new TwoFactorError('Failed to initialize TwoFactorService');\r\n }\r\n }\r\n\r\n private validateConfiguration(): void {\r\n if (!this.config.app_name?.trim()) {\r\n throw new TwoFactorError('Application name (appName) is required in configuration');\r\n }\r\n\r\n if (this.twoFactorConfig.secretLength < 16) {\r\n throw new TwoFactorError('Secret length must be at least 16 characters');\r\n }\r\n\r\n if (this.twoFactorConfig.tokenWindow < 0 || this.twoFactorConfig.tokenWindow > 5) {\r\n throw new TwoFactorError('Token verification window must be between 0 and 5');\r\n }\r\n }\r\n\r\n private ensureInitialized(): void {\r\n if (!this.initialized) {\r\n throw new TwoFactorError('TwoFactorService must be initialized before use');\r\n }\r\n }\r\n\r\n public generateSecret(email: string): { secret: string; otpAuthUrl: string } {\r\n this.ensureInitialized();\r\n\r\n try {\r\n const secretObj = speakeasy.generateSecret({\r\n length: this.twoFactorConfig.secretLength,\r\n name: `${this.config.app_name}:${email}`,\r\n issuer: this.config.app_name\r\n });\r\n \r\n return {\r\n secret: secretObj.base32,\r\n otpAuthUrl: secretObj.otpauth_url || ''\r\n };\r\n } catch (error) {\r\n console.error('Error generating 2FA secret:', error);\r\n throw new TwoFactorError('Failed to generate 2FA secret');\r\n }\r\n }\r\n\r\n public async generateQRCode(otpAuthUrl: string): Promise<string> {\r\n this.ensureInitialized();\r\n\r\n try {\r\n return await QRCode.toDataURL(otpAuthUrl, this.twoFactorConfig.qrCodeOptions);\r\n } catch (error) {\r\n console.error('QR code generation failed:', error);\r\n throw new TwoFactorError('Failed to generate QR code');\r\n }\r\n }\r\n\r\n public verifyToken(token: string, secret: string): boolean {\r\n this.ensureInitialized();\r\n\r\n try {\r\n return speakeasy.totp.verify({\r\n secret,\r\n encoding: 'base32',\r\n token,\r\n window: this.twoFactorConfig.tokenWindow\r\n });\r\n } catch (error) {\r\n console.error('Token verification failed:', error);\r\n throw new TwoFactorError('Failed to verify 2FA token');\r\n }\r\n }\r\n}"],"mappings":"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","names":["import_cca_core","import_cca_entities","bcrypt","import_cca_core","import_cca_core","bcrypt","import_cca_entities","import_core","import_classes","import_cca_entities","import_classes","mapper","import_cca_core","import_cca_core","import_cca_core","import_cca_entities","import_cca_core","import_cca_core","bcrypt","import_cca_core"]}
|
package/dist/index.mjs
CHANGED
|
@@ -240,7 +240,10 @@ var _LoginUseCase = class _LoginUseCase {
|
|
|
240
240
|
async initialize() {
|
|
241
241
|
await validateRepository(this.repository, (repo) => repo.getAll());
|
|
242
242
|
}
|
|
243
|
-
async execute(loginDTO) {
|
|
243
|
+
async execute(loginDTO, providedAdminPassword, admin) {
|
|
244
|
+
if (admin) {
|
|
245
|
+
await validateAdminSecret(providedAdminPassword);
|
|
246
|
+
}
|
|
244
247
|
const auth = await validateLoginDTO(loginDTO, this.repository);
|
|
245
248
|
const accessToken = this.jwtService.generateAccessToken(auth.user, auth.role);
|
|
246
249
|
const expiresAt = jwtDecode(accessToken).exp;
|
|
@@ -250,32 +253,14 @@ var _LoginUseCase = class _LoginUseCase {
|
|
|
250
253
|
__name(_LoginUseCase, "LoginUseCase");
|
|
251
254
|
var LoginUseCase = _LoginUseCase;
|
|
252
255
|
|
|
253
|
-
// src/application/useCase/LoginAdminUseCase.ts
|
|
254
|
-
import { validateRepository as validateRepository2 } from "cca-core";
|
|
255
|
-
var _LoginAdminUseCase = class _LoginAdminUseCase {
|
|
256
|
-
constructor(repository) {
|
|
257
|
-
this.repository = repository;
|
|
258
|
-
}
|
|
259
|
-
async initialize() {
|
|
260
|
-
await validateRepository2(this.repository, (repo) => repo.getAll());
|
|
261
|
-
}
|
|
262
|
-
async execute(loginDTO, adminPassword) {
|
|
263
|
-
const auth = await validateLoginDTO(loginDTO, this.repository);
|
|
264
|
-
await validateAdminSecret(adminPassword);
|
|
265
|
-
return auth.user.id;
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
__name(_LoginAdminUseCase, "LoginAdminUseCase");
|
|
269
|
-
var LoginAdminUseCase = _LoginAdminUseCase;
|
|
270
|
-
|
|
271
256
|
// src/application/useCase/LogoutUseCase.ts
|
|
272
|
-
import { validateRepository as
|
|
257
|
+
import { validateRepository as validateRepository2 } from "cca-core";
|
|
273
258
|
var _LogoutUseCase = class _LogoutUseCase {
|
|
274
259
|
constructor(repository) {
|
|
275
260
|
this.repository = repository;
|
|
276
261
|
}
|
|
277
262
|
async initialize() {
|
|
278
|
-
await
|
|
263
|
+
await validateRepository2(this.repository, (repo) => repo.getAll());
|
|
279
264
|
}
|
|
280
265
|
async execute(authId) {
|
|
281
266
|
try {
|
|
@@ -289,7 +274,7 @@ __name(_LogoutUseCase, "LogoutUseCase");
|
|
|
289
274
|
var LogoutUseCase = _LogoutUseCase;
|
|
290
275
|
|
|
291
276
|
// src/application/useCase/RegisterUseCase.ts
|
|
292
|
-
import { validateRepository as
|
|
277
|
+
import { validateRepository as validateRepository3 } from "cca-core";
|
|
293
278
|
import * as bcrypt2 from "bcrypt";
|
|
294
279
|
import { AdminEntity as AdminEntity2, AuthEntity as AuthEntity3, UserEntity as UserEntity2, UserRole as UserRole2 } from "cca-entities";
|
|
295
280
|
|
|
@@ -410,7 +395,7 @@ var _RegisterUseCase = class _RegisterUseCase {
|
|
|
410
395
|
this.SALT_ROUNDS = 10;
|
|
411
396
|
}
|
|
412
397
|
async initialize() {
|
|
413
|
-
await
|
|
398
|
+
await validateRepository3(this.repository, (repo) => repo.getAll());
|
|
414
399
|
}
|
|
415
400
|
async execute(email, name, password, role = UserRole2.GUEST, adminPassword) {
|
|
416
401
|
try {
|
|
@@ -467,14 +452,14 @@ __name(_RegisterUseCase, "RegisterUseCase");
|
|
|
467
452
|
var RegisterUseCase = _RegisterUseCase;
|
|
468
453
|
|
|
469
454
|
// src/application/useCase/RefreshTokenUseCase.ts
|
|
470
|
-
import { validateRepository as
|
|
455
|
+
import { validateRepository as validateRepository4 } from "cca-core";
|
|
471
456
|
var _RefreshTokenUseCase = class _RefreshTokenUseCase {
|
|
472
457
|
constructor(repository, service) {
|
|
473
458
|
this.repository = repository;
|
|
474
459
|
this.service = service;
|
|
475
460
|
}
|
|
476
461
|
async initialize() {
|
|
477
|
-
await
|
|
462
|
+
await validateRepository4(this.repository, (repo) => repo.getAll());
|
|
478
463
|
}
|
|
479
464
|
async execute(refreshToken) {
|
|
480
465
|
try {
|
|
@@ -542,7 +527,7 @@ __name(_TwoFactorSetupUseCase, "TwoFactorSetupUseCase");
|
|
|
542
527
|
var TwoFactorSetupUseCase = _TwoFactorSetupUseCase;
|
|
543
528
|
|
|
544
529
|
// src/application/useCase/TwoFactorEnableUseCase.ts
|
|
545
|
-
import { validateRepository as
|
|
530
|
+
import { validateRepository as validateRepository5 } from "cca-core";
|
|
546
531
|
var _TwoFactorEnableUseCase = class _TwoFactorEnableUseCase {
|
|
547
532
|
constructor(twoFactorService, authRepository) {
|
|
548
533
|
this.isInitialized = false;
|
|
@@ -553,7 +538,7 @@ var _TwoFactorEnableUseCase = class _TwoFactorEnableUseCase {
|
|
|
553
538
|
if (this.isInitialized) return;
|
|
554
539
|
await Promise.all([
|
|
555
540
|
this.twoFactorService.initialize(),
|
|
556
|
-
|
|
541
|
+
validateRepository5(this.authRepository, (repo) => repo.getAll())
|
|
557
542
|
]);
|
|
558
543
|
this.isInitialized = true;
|
|
559
544
|
}
|
|
@@ -583,7 +568,7 @@ __name(_TwoFactorEnableUseCase, "TwoFactorEnableUseCase");
|
|
|
583
568
|
var TwoFactorEnableUseCase = _TwoFactorEnableUseCase;
|
|
584
569
|
|
|
585
570
|
// src/application/useCase/TwoFactorVerifyUseCase.ts
|
|
586
|
-
import { validateRepository as
|
|
571
|
+
import { validateRepository as validateRepository6 } from "cca-core";
|
|
587
572
|
import { AdminEntity as AdminEntity3, UserEntity as UserEntity3 } from "cca-entities";
|
|
588
573
|
var _TwoFactorVerifyUseCase = class _TwoFactorVerifyUseCase {
|
|
589
574
|
constructor(twoFactorService, authRepository, jwtService) {
|
|
@@ -597,7 +582,7 @@ var _TwoFactorVerifyUseCase = class _TwoFactorVerifyUseCase {
|
|
|
597
582
|
await Promise.all([
|
|
598
583
|
this.twoFactorService.initialize(),
|
|
599
584
|
this.jwtService.initialize(),
|
|
600
|
-
|
|
585
|
+
validateRepository6(this.authRepository, (repo) => repo.getAll())
|
|
601
586
|
]);
|
|
602
587
|
this.isInitialized = true;
|
|
603
588
|
}
|
|
@@ -662,7 +647,7 @@ __name(_TwoFactorVerifyUseCase, "TwoFactorVerifyUseCase");
|
|
|
662
647
|
var TwoFactorVerifyUseCase = _TwoFactorVerifyUseCase;
|
|
663
648
|
|
|
664
649
|
// src/application/useCase/TwoFactorDisableUseCase.ts
|
|
665
|
-
import { validateRepository as
|
|
650
|
+
import { validateRepository as validateRepository7 } from "cca-core";
|
|
666
651
|
var _TwoFactorDisableUseCase = class _TwoFactorDisableUseCase {
|
|
667
652
|
constructor(twoFactorService, authRepository) {
|
|
668
653
|
this.isInitialized = false;
|
|
@@ -673,7 +658,7 @@ var _TwoFactorDisableUseCase = class _TwoFactorDisableUseCase {
|
|
|
673
658
|
if (this.isInitialized) return;
|
|
674
659
|
await Promise.all([
|
|
675
660
|
this.twoFactorService.initialize(),
|
|
676
|
-
|
|
661
|
+
validateRepository7(this.authRepository, (repo) => repo.getAll())
|
|
677
662
|
]);
|
|
678
663
|
4;
|
|
679
664
|
this.isInitialized = true;
|
|
@@ -725,11 +710,11 @@ var MESSAGES = {
|
|
|
725
710
|
|
|
726
711
|
// src/presentation/controller/AuthController.ts
|
|
727
712
|
var _AuthController = class _AuthController {
|
|
728
|
-
constructor(loginUseCase,
|
|
713
|
+
constructor(loginUseCase, logoutUseCase, registerUseCase, refreshTokenUseCase, twoFactorSetupUseCase, twoFactorEnableUseCase, twoFactorVerifyUseCase, twoFactorDisableUseCase) {
|
|
729
714
|
this.login = /* @__PURE__ */ __name(async (req, res, next) => {
|
|
730
715
|
try {
|
|
731
716
|
const loginDTO = req.body;
|
|
732
|
-
const result = await this.loginUseCase.execute(loginDTO);
|
|
717
|
+
const result = await this.loginUseCase.execute(loginDTO, "", false);
|
|
733
718
|
const twoFactorEnabled = result.enabled ?? false;
|
|
734
719
|
const loginData = {
|
|
735
720
|
accessToken: result.accessToken,
|
|
@@ -756,7 +741,7 @@ var _AuthController = class _AuthController {
|
|
|
756
741
|
if (!adminPassword) {
|
|
757
742
|
throw new ForbiddenError("Admin password is required");
|
|
758
743
|
}
|
|
759
|
-
const result = await this.
|
|
744
|
+
const result = await this.loginUseCase.execute(loginDTO, adminPassword, true);
|
|
760
745
|
const adminLoginData = {
|
|
761
746
|
message: result,
|
|
762
747
|
auth: this.createAuthData(
|
|
@@ -911,7 +896,6 @@ var _AuthController = class _AuthController {
|
|
|
911
896
|
}
|
|
912
897
|
}, "disable2FA");
|
|
913
898
|
this.loginUseCase = loginUseCase;
|
|
914
|
-
this.adminLoginUseCase = adminLoginUseCase;
|
|
915
899
|
this.logoutUseCase = logoutUseCase;
|
|
916
900
|
this.registerUseCase = registerUseCase;
|
|
917
901
|
this.refreshTokenUseCase = refreshTokenUseCase;
|
|
@@ -1050,7 +1034,7 @@ var AuthRepository = _AuthRepository;
|
|
|
1050
1034
|
// src/infrastructure/services/JwtAuthService.ts
|
|
1051
1035
|
import * as jwt from "jsonwebtoken";
|
|
1052
1036
|
import * as bcrypt3 from "bcrypt";
|
|
1053
|
-
import { validateRepository as
|
|
1037
|
+
import { validateRepository as validateRepository8 } from "cca-core";
|
|
1054
1038
|
var _JwtAuthService = class _JwtAuthService {
|
|
1055
1039
|
constructor(repository, config) {
|
|
1056
1040
|
this.repository = repository;
|
|
@@ -1068,7 +1052,7 @@ var _JwtAuthService = class _JwtAuthService {
|
|
|
1068
1052
|
this.validateConfiguration();
|
|
1069
1053
|
}
|
|
1070
1054
|
async initialize() {
|
|
1071
|
-
await
|
|
1055
|
+
await validateRepository8(this.repository, (repo) => repo.getAll());
|
|
1072
1056
|
}
|
|
1073
1057
|
validateConfiguration() {
|
|
1074
1058
|
if (!this.jwtConfig?.accessTokenSecret || !this.jwtConfig?.refreshTokenSecret) {
|
|
@@ -1232,9 +1216,6 @@ async function createAuthContainer(database) {
|
|
|
1232
1216
|
container.registerService("TwoFactorService", twoFactorService);
|
|
1233
1217
|
const requireComplete2FA = new RequireComplete2FA(jwtAuthService);
|
|
1234
1218
|
const loginUseCase = new LoginUseCase(authRepository, jwtAuthService);
|
|
1235
|
-
const loginAdminUseCase = new LoginAdminUseCase(
|
|
1236
|
-
authRepository
|
|
1237
|
-
);
|
|
1238
1219
|
const logoutUseCase = new LogoutUseCase(authRepository);
|
|
1239
1220
|
const registerUseCase = new RegisterUseCase(authRepository);
|
|
1240
1221
|
const refreshTokenUseCase = new RefreshTokenUseCase(
|
|
@@ -1250,7 +1231,6 @@ async function createAuthContainer(database) {
|
|
|
1250
1231
|
);
|
|
1251
1232
|
const twoFactorDisableUseCase = new TwoFactorDisableUseCase(twoFactorService, authRepository);
|
|
1252
1233
|
container.registerService("LoginUseCase", loginUseCase);
|
|
1253
|
-
container.registerService("LoginAdminUseCase", loginAdminUseCase);
|
|
1254
1234
|
container.registerService("LogoutUseCase", logoutUseCase);
|
|
1255
1235
|
container.registerService("RegisterUseCase", registerUseCase);
|
|
1256
1236
|
container.registerService("RefreshTokenUseCase", refreshTokenUseCase);
|
|
@@ -1260,7 +1240,6 @@ async function createAuthContainer(database) {
|
|
|
1260
1240
|
container.registerService("TwoFactorDisableUseCase", twoFactorDisableUseCase);
|
|
1261
1241
|
const authController = new AuthController(
|
|
1262
1242
|
loginUseCase,
|
|
1263
|
-
loginAdminUseCase,
|
|
1264
1243
|
logoutUseCase,
|
|
1265
1244
|
registerUseCase,
|
|
1266
1245
|
refreshTokenUseCase,
|