cca-auth-module 0.2.2 → 0.2.21

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/index.js CHANGED
@@ -1063,10 +1063,10 @@ var _AuthRepository = class _AuthRepository extends import_cca_core8.BaseReposit
1063
1063
  return this.repository.save(auth);
1064
1064
  }
1065
1065
  async findByUserOrAdminId(id) {
1066
- return await this.repository.createQueryBuilder("auth").leftJoinAndSelect("auth.user", "user").leftJoinAndSelect("auth.admin", "admin").addSelect("auth.twoFactorSecret").where("user.id = :id", { id }).orWhere("admin.id = :id", { id }).getOne();
1066
+ return await this.repository.createQueryBuilder("auth").leftJoinAndSelect("auth.user", "user").leftJoinAndSelect("auth.admin", "admin").addSelect(["auth.twoFactorSecret", "auth.refreshToken"]).where("user.id = :id", { id }).orWhere("admin.id = :id", { id }).getOne();
1067
1067
  }
1068
1068
  async findByUseAdminId(userId, isAdmin = false) {
1069
- const query = this.repository.createQueryBuilder("auth").addSelect("auth.twoFactorSecret");
1069
+ const query = this.repository.createQueryBuilder("auth").addSelect(["auth.twoFactorSecret", "auth.refreshToken"]);
1070
1070
  if (isAdmin) {
1071
1071
  query.leftJoinAndSelect("auth.admin", "admin").where("admin.id = :userId", { userId });
1072
1072
  } else {
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/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\";\nimport { AuthEntity } from \"cca-entities\";\nimport type { SignOptions } from \"jsonwebtoken\";\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 configData = await createConfigInstance();\n\n const parseExpiry = (value: string): SignOptions[\"expiresIn\"] => {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : (value as SignOptions[\"expiresIn\"]);\n };\n\n const jwtConfig = {\n accessTokenSecret: configData.accessTokenSecret,\n refreshTokenSecret: configData.refreshTokenSecret,\n accessTokenExpiry: parseExpiry(configData.accessTokenExpiry),\n refreshTokenExpiry: parseExpiry(configData.refreshTokenExpiry),\n };\n\n const configuredJwtAuthService = new JwtAuthService(authRepository, jwtConfig);\n container.registerService(\"JwtAuthService\", configuredJwtAuthService);\n\n const twoFactorService = new TwoFactorService(configData);\n container.registerService(\"TwoFactorService\", twoFactorService);\n\n const requireComplete2FA = new RequireComplete2FA(configuredJwtAuthService);\n\n const loginUseCase = new LoginUseCase(authRepository, configuredJwtAuthService);\n const logoutUseCase = new LogoutUseCase(authRepository);\n const registerUseCase = new RegisterUseCase(authRepository);\n const refreshTokenUseCase = new RefreshTokenUseCase(\n authRepository,\n configuredJwtAuthService\n );\n\r\n const twoFactorSetupUseCase = new TwoFactorSetupUseCase(twoFactorService, authRepository);\r\n const twoFactorEnableUseCase = new TwoFactorEnableUseCase(twoFactorService, authRepository);\r\n const twoFactorVerifyUseCase = new TwoFactorVerifyUseCase(\n twoFactorService,\n authRepository,\n configuredJwtAuthService\n );\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 };\n","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\nimport { NotFoundError } from \"../../utils/Errors\";\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): Promise<{ id: string, accessToken: string, expiresAt: number, enabled?: boolean }> {\r\n const isAdmin = !!providedAdminPassword;\r\n\r\n if (isAdmin) {\r\n await validateAdminSecret(providedAdminPassword);\r\n }\r\n\r\n const auth = await validateLoginDTO(loginDTO, this.repository);\r\n\r\n const account = isAdmin ? auth.admin : auth.user;\r\n if (!account) {\r\n throw new NotFoundError(`${isAdmin ? \"Admin\" : \"User\"} account not found or inactive`);\r\n }\r\n\r\n const accessToken = this.jwtService.generateAccessToken(account, auth.role, false);\n const decoded = jwtDecode<IJwtPayload>(accessToken);\n const expiresAt = decoded.exp ?? 0;\n\r\n\r\n return { id: account.id, accessToken, expiresAt, enabled: auth.twoFactorEnabled };\r\n }\r\n}\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\";\n\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\nimport { LoginDTO } from \"../dtos/LoginDTO\";\nimport { createConfigInstance } from \"../service/utils/configInstance\";\nimport crypto from \"crypto\";\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 (\n email: string,\n repository: AuthRepository\n): Promise<AuthEntity> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n const user = await repository.findByEmail(normalizedEmail);\n if (!user) {\n throw new NotFoundError(\n \"The email address or password is incorrect. Please retry\"\n );\n }\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 (\n repository: AuthRepository,\n email: string,\n excludeUserId?: string\n): Promise<void> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n\n const existingUser = await repository.findByEmail(normalizedEmail);\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 (\n secretPassword?: string\n): Promise<void> => {\n if (!secretPassword) {\n throw new ValidationError(\"Admin password is required\");\n }\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 const provided = secretPassword.trim();\n const expected = config.adminSecretPassword.trim();\n if (provided.length !== expected.length) {\n throw new ValidationError(\"Invalid admin password\");\n }\n\n const providedBuf = Buffer.from(provided);\n const expectedBuf = Buffer.from(expected);\n if (!crypto.timingSafeEqual(providedBuf, expectedBuf)) {\n throw new ValidationError(\"Invalid admin password\");\n }\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(userId: string | undefined): Promise<void> {\n try {\n if (!userId) {\n throw new NotFoundError(\"User ID is required\");\n }\n await this.repository.logout(userId);\n } catch (error) {\n if (error instanceof NotFoundError) {\n throw error;\n }\n throw new NotFoundError(\"Auth not found\");\n }\n }\n}\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\n ? mapper.map(dto, RegisterDTO, AdminEntity)\n : mapper.map(dto, RegisterDTO, UserEntity);\n\n userOrAdminEntity.updatedAt = undefined as unknown as Date;\n\n if (isAdmin) {\n authEntity.admin = userOrAdminEntity as AdminEntity;\n } else {\n authEntity.user = userOrAdminEntity as UserEntity;\n }\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> {\n try {\n if (!refreshToken) return null;\n\n const decoded = await this.service.verifyRefreshToken(refreshToken);\n if (!decoded.userId) return null;\n\n const authEntity = await this.repository.findByUserOrAdminId(decoded.userId);\n if (!authEntity) return null;\n if (!authEntity.refreshToken || authEntity.refreshToken !== refreshToken) return null;\n\r\n const account = authEntity.user ?? authEntity.admin;\r\n if (!account) return null;\r\n\r\n const accessToken = this.service.generateAccessToken(\n account,\n authEntity.role,\n !!authEntity.twoFactorEnabled\n );\n const newRefreshToken = this.service.generateRefreshToken(account);\n\r\n await this.repository.update(authEntity.id, { refreshToken: newRefreshToken });\r\n\r\n return { accessToken, refreshToken: newRefreshToken };\r\n } catch (error) {\n return null;\n }\n }\n}\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.findByUserOrAdminId(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> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token, userId } = dto;\n \n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const auth: AuthEntity | null = await this.authRepository.findByUserOrAdminId(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}\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 { NotFoundError, 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.findByUserOrAdminId(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> {\n const account = auth.user ?? auth.admin;\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\n account.lastLoginAt = new Date();\n account.isActive = true;\n await this.authRepository.saveAccount(account);\n }\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 const account = auth.user ?? auth.admin;\r\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\r\n\r\n return {\n accessToken: this.jwtService.generateAccessToken(account, auth.role, true),\n refreshToken: this.jwtService.generateRefreshToken(account)\n };\n }\n}\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> {\n if (this.isInitialized) return;\n \n await Promise.all([\n this.twoFactorService.initialize(),\n validateRepository(this.authRepository, repo => repo.getAll())\n ]);\n\n this.isInitialized = true;\n }\n\n async execute(userId: string, dto: ITwoFactorEnable): Promise<void> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token } = dto;\n\n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const user = await this.authRepository.findByUserOrAdminId(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}\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);\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);\n\n const adminLoginData = {\n accessToken: result.accessToken,\n userId: result.id,\n expiresAt: result.expiresAt,\n auth: this.createAuthData(\n true,\n result.enabled ?? false,\n (result.enabled ?? false) ? AUTH_STATUS.PENDING_VERIFICATION : AUTH_STATUS.BASIC_AUTH,\n false\n ),\n };\n\n this.sendResponse(res, HTTP_STATUS.CREATED, MESSAGES.ADMIN_LOGIN_SUCCESS, adminLoginData);\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> => {\n try {\n const userId = req.auth?.userId ?? req.body.id;\n await this.logoutUseCase.execute(userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n\n const result = await this.twoFactorSetupUseCase.execute(req.auth.userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = { ...req.body, userId: req.auth?.userId };\n await this.twoFactorEnableUseCase.execute(dto);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorVerify = { ...req.body, userId: req.auth.userId };\n const result = await this.twoFactorVerifyUseCase.execute(dto);\n if (!result) {\n throw new Error(\"Two-factor verification failed\");\n }\n\r\n const verifyData = {\r\n token: result.token,\n refreshToken: result.refreshToken,\n user: {\n id: result.data?.id,\n email: result.data?.email,\n name: result.data?.name,\n role: result.data?.role,\n },\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> => {\n try {\n const userId = req.auth?.userId;\n if (!userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = req.body;\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}\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);\n\n if (!decoded.userId) {\n return res.status(401).json({ message: 'Invalid token payload' });\n }\n\n if (!decoded.twoFactorAuthenticated) {\n return res.status(403).json({\n message: 'Two-factor authentication required',\n code: 'REQUIRE_2FA',\n userId: decoded.userId\n });\n }\n\n req.auth = { ...decoded, twoFactorAuthenticated: true };\n next();\n } catch (error) {\r\n return res.status(401).json({ message: 'Invalid or expired token' });\r\n }\r\n }\r\n}\n","import { BaseRepository, IExtendedBaseRepository } from \"cca-core\";\r\nimport { AdminEntity, AuthEntity, UserEntity } from \"cca-entities\";\nimport { Repository } from \"typeorm\";\nimport { NotFoundError } from \"../../utils/Errors\";\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 result = await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect(\"auth.password\")\r\n .where(\"auth.email = :email\", { email })\r\n .getOne();\r\n\r\n return result;\r\n }\r\n\r\n async create(entity: Omit<AuthEntity, \"createdAt\">): Promise<AuthEntity> {\n const now = new Date();\n const auth = this.repository.create({\n ...entity,\n createdAt: now,\n updatedAt: now,\n isDeleted: false,\n } as unknown as AuthEntity);\n\n return this.repository.save(auth);\n }\n\r\n async findByUserOrAdminId(id: string): Promise<AuthEntity | null> {\r\n return await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect(\"auth.twoFactorSecret\")\r\n .where(\"user.id = :id\", { id })\r\n .orWhere(\"admin.id = :id\", { id })\r\n .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> {\n const auth = await this.findByUserOrAdminId(userId);\n\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n const account = auth.user ?? auth.admin;\r\n\r\n if (account) {\n auth.refreshToken = \"\";\n account.isActive = false;\n await this.saveAccount(account);\n }\n\n await this.update(auth.id, auth);\n }\n\r\n async updateTwoFactorSecret(userId: string, secret: string): Promise<void> {\r\n const auth = await this.findByUserOrAdminId(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> {\n auth.twoFactorEnabled = true;\n\n await this.update(auth.id, auth);\n }\n\r\n async disableTwoFactor(auth: AuthEntity): Promise<void> {\n auth.twoFactorEnabled = false;\n auth.twoFactorSecret = null;\n\n await this.update(auth.id, auth);\n }\n\r\n async isTwoFactorEnabled(userId: string): Promise<boolean> {\r\n const auth = await this.findByUserOrAdminId(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> {\n const auth = await this.findByUserOrAdminId(userId);\n if (!auth) {\n throw new NotFoundError(\"Auth not found\");\n }\n\n return auth.twoFactorSecret;\n }\n\n async saveAccount(account: UserEntity | AdminEntity): Promise<void> {\n await this.repository.manager.save(account);\n }\n}\n","import * as jwt from \"jsonwebtoken\";\r\nimport { Secret } from \"jsonwebtoken\";\nimport { IBaseService, validateRepository } from \"cca-core\";\nimport { AdminEntity, UserEntity, UserRole } from \"cca-entities\";\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 { JwtError, UnauthorizedError } from \"../../utils/Errors\";\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nexport class JwtAuthService implements IBaseService, IAuthService {\n private jwtConfig: IJwtConfig | undefined;\n\n constructor(private readonly repository: AuthRepository, config?: IJwtConfig) {\n if (config) {\n this.jwtConfig = {\n accessTokenSecret: config.accessTokenSecret,\n refreshTokenSecret: config.refreshTokenSecret,\n accessTokenExpiry: config.accessTokenExpiry,\n refreshTokenExpiry: config.refreshTokenExpiry,\n };\n }\n\n this.validateConfiguration();\n }\n\n async initialize(): Promise<void> {\n await validateRepository(this.repository, repo => repo.getAll());\n this.validateConfiguration();\n }\n\n private validateConfiguration(): void {\n if (!this.jwtConfig?.accessTokenSecret || !this.jwtConfig?.refreshTokenSecret) {\n throw new JwtError(\"JWT secrets required in config\");\n }\n if (this.jwtConfig.accessTokenExpiry == null || this.jwtConfig.refreshTokenExpiry == null) {\n throw new JwtError(\"JWT expirations required in config\");\n }\n }\n\r\n private verifyJwtConfig() {\r\n if (!this.jwtConfig) throw new JwtError(\"JWT config not loaded\");\r\n }\r\n\r\n generateAccessToken(\n user: UserEntity | AdminEntity,\n role: UserRole,\n twoFactorAuthenticated: boolean = false\n ): string {\n this.verifyJwtConfig();\n return jwt.sign(\n {\n userId: user.id,\n email: user.email,\n role: role,\n twoFactorAuthenticated,\n },\n this.jwtConfig!.accessTokenSecret as Secret,\n { expiresIn: this.jwtConfig!.accessTokenExpiry }\n );\n }\n\r\n generateRefreshToken(user: UserEntity | AdminEntity): 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> {\n try {\n return jwt.verify(token, secret) as IDecodedToken;\n } catch (error) {\n throw new UnauthorizedError();\n }\n }\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) {\n this.config = config;\n\n const parsedTokenWindow = Number.parseInt(config.tokenWindow, 10);\n const parsedSecretLength = Number.parseInt(config.secretLength, 10);\n\n this.twoFactorConfig = {\n tokenWindow: Number.isFinite(parsedTokenWindow) ? parsedTokenWindow : 1,\n secretLength: Number.isFinite(parsedSecretLength) ? parsedSecretLength : 20,\n qrCodeOptions: {\n errorCorrectionLevel: 'M',\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}\n"],"mappings":"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","names":["import_cca_core","import_cca_entities","bcrypt","crypto","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","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\";\nimport { AuthEntity } from \"cca-entities\";\nimport type { SignOptions } from \"jsonwebtoken\";\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 configData = await createConfigInstance();\n\n const parseExpiry = (value: string): SignOptions[\"expiresIn\"] => {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : (value as SignOptions[\"expiresIn\"]);\n };\n\n const jwtConfig = {\n accessTokenSecret: configData.accessTokenSecret,\n refreshTokenSecret: configData.refreshTokenSecret,\n accessTokenExpiry: parseExpiry(configData.accessTokenExpiry),\n refreshTokenExpiry: parseExpiry(configData.refreshTokenExpiry),\n };\n\n const configuredJwtAuthService = new JwtAuthService(authRepository, jwtConfig);\n container.registerService(\"JwtAuthService\", configuredJwtAuthService);\n\n const twoFactorService = new TwoFactorService(configData);\n container.registerService(\"TwoFactorService\", twoFactorService);\n\n const requireComplete2FA = new RequireComplete2FA(configuredJwtAuthService);\n\n const loginUseCase = new LoginUseCase(authRepository, configuredJwtAuthService);\n const logoutUseCase = new LogoutUseCase(authRepository);\n const registerUseCase = new RegisterUseCase(authRepository);\n const refreshTokenUseCase = new RefreshTokenUseCase(\n authRepository,\n configuredJwtAuthService\n );\n\r\n const twoFactorSetupUseCase = new TwoFactorSetupUseCase(twoFactorService, authRepository);\r\n const twoFactorEnableUseCase = new TwoFactorEnableUseCase(twoFactorService, authRepository);\r\n const twoFactorVerifyUseCase = new TwoFactorVerifyUseCase(\n twoFactorService,\n authRepository,\n configuredJwtAuthService\n );\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 };\n","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\nimport { NotFoundError } from \"../../utils/Errors\";\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): Promise<{ id: string, accessToken: string, expiresAt: number, enabled?: boolean }> {\r\n const isAdmin = !!providedAdminPassword;\r\n\r\n if (isAdmin) {\r\n await validateAdminSecret(providedAdminPassword);\r\n }\r\n\r\n const auth = await validateLoginDTO(loginDTO, this.repository);\r\n\r\n const account = isAdmin ? auth.admin : auth.user;\r\n if (!account) {\r\n throw new NotFoundError(`${isAdmin ? \"Admin\" : \"User\"} account not found or inactive`);\r\n }\r\n\r\n const accessToken = this.jwtService.generateAccessToken(account, auth.role, false);\n const decoded = jwtDecode<IJwtPayload>(accessToken);\n const expiresAt = decoded.exp ?? 0;\n\r\n\r\n return { id: account.id, accessToken, expiresAt, enabled: auth.twoFactorEnabled };\r\n }\r\n}\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\";\n\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\nimport { LoginDTO } from \"../dtos/LoginDTO\";\nimport { createConfigInstance } from \"../service/utils/configInstance\";\nimport crypto from \"crypto\";\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 (\n email: string,\n repository: AuthRepository\n): Promise<AuthEntity> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n const user = await repository.findByEmail(normalizedEmail);\n if (!user) {\n throw new NotFoundError(\n \"The email address or password is incorrect. Please retry\"\n );\n }\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 (\n repository: AuthRepository,\n email: string,\n excludeUserId?: string\n): Promise<void> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n\n const existingUser = await repository.findByEmail(normalizedEmail);\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 (\n secretPassword?: string\n): Promise<void> => {\n if (!secretPassword) {\n throw new ValidationError(\"Admin password is required\");\n }\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 const provided = secretPassword.trim();\n const expected = config.adminSecretPassword.trim();\n if (provided.length !== expected.length) {\n throw new ValidationError(\"Invalid admin password\");\n }\n\n const providedBuf = Buffer.from(provided);\n const expectedBuf = Buffer.from(expected);\n if (!crypto.timingSafeEqual(providedBuf, expectedBuf)) {\n throw new ValidationError(\"Invalid admin password\");\n }\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(userId: string | undefined): Promise<void> {\n try {\n if (!userId) {\n throw new NotFoundError(\"User ID is required\");\n }\n await this.repository.logout(userId);\n } catch (error) {\n if (error instanceof NotFoundError) {\n throw error;\n }\n throw new NotFoundError(\"Auth not found\");\n }\n }\n}\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\n ? mapper.map(dto, RegisterDTO, AdminEntity)\n : mapper.map(dto, RegisterDTO, UserEntity);\n\n userOrAdminEntity.updatedAt = undefined as unknown as Date;\n\n if (isAdmin) {\n authEntity.admin = userOrAdminEntity as AdminEntity;\n } else {\n authEntity.user = userOrAdminEntity as UserEntity;\n }\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> {\n try {\n if (!refreshToken) return null;\n\n const decoded = await this.service.verifyRefreshToken(refreshToken);\n if (!decoded.userId) return null;\n\n const authEntity = await this.repository.findByUserOrAdminId(decoded.userId);\n if (!authEntity) return null;\n if (!authEntity.refreshToken || authEntity.refreshToken !== refreshToken) return null;\n\r\n const account = authEntity.user ?? authEntity.admin;\r\n if (!account) return null;\r\n\r\n const accessToken = this.service.generateAccessToken(\n account,\n authEntity.role,\n !!authEntity.twoFactorEnabled\n );\n const newRefreshToken = this.service.generateRefreshToken(account);\n\r\n await this.repository.update(authEntity.id, { refreshToken: newRefreshToken });\r\n\r\n return { accessToken, refreshToken: newRefreshToken };\r\n } catch (error) {\n return null;\n }\n }\n}\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.findByUserOrAdminId(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> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token, userId } = dto;\n \n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const auth: AuthEntity | null = await this.authRepository.findByUserOrAdminId(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}\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 { NotFoundError, 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.findByUserOrAdminId(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> {\n const account = auth.user ?? auth.admin;\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\n account.lastLoginAt = new Date();\n account.isActive = true;\n await this.authRepository.saveAccount(account);\n }\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 const account = auth.user ?? auth.admin;\r\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\r\n\r\n return {\n accessToken: this.jwtService.generateAccessToken(account, auth.role, true),\n refreshToken: this.jwtService.generateRefreshToken(account)\n };\n }\n}\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> {\n if (this.isInitialized) return;\n \n await Promise.all([\n this.twoFactorService.initialize(),\n validateRepository(this.authRepository, repo => repo.getAll())\n ]);\n\n this.isInitialized = true;\n }\n\n async execute(userId: string, dto: ITwoFactorEnable): Promise<void> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token } = dto;\n\n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const user = await this.authRepository.findByUserOrAdminId(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}\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);\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);\n\n const adminLoginData = {\n accessToken: result.accessToken,\n userId: result.id,\n expiresAt: result.expiresAt,\n auth: this.createAuthData(\n true,\n result.enabled ?? false,\n (result.enabled ?? false) ? AUTH_STATUS.PENDING_VERIFICATION : AUTH_STATUS.BASIC_AUTH,\n false\n ),\n };\n\n this.sendResponse(res, HTTP_STATUS.CREATED, MESSAGES.ADMIN_LOGIN_SUCCESS, adminLoginData);\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> => {\n try {\n const userId = req.auth?.userId ?? req.body.id;\n await this.logoutUseCase.execute(userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n\n const result = await this.twoFactorSetupUseCase.execute(req.auth.userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = { ...req.body, userId: req.auth?.userId };\n await this.twoFactorEnableUseCase.execute(dto);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorVerify = { ...req.body, userId: req.auth.userId };\n const result = await this.twoFactorVerifyUseCase.execute(dto);\n if (!result) {\n throw new Error(\"Two-factor verification failed\");\n }\n\r\n const verifyData = {\r\n token: result.token,\n refreshToken: result.refreshToken,\n user: {\n id: result.data?.id,\n email: result.data?.email,\n name: result.data?.name,\n role: result.data?.role,\n },\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> => {\n try {\n const userId = req.auth?.userId;\n if (!userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = req.body;\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}\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);\n\n if (!decoded.userId) {\n return res.status(401).json({ message: 'Invalid token payload' });\n }\n\n if (!decoded.twoFactorAuthenticated) {\n return res.status(403).json({\n message: 'Two-factor authentication required',\n code: 'REQUIRE_2FA',\n userId: decoded.userId\n });\n }\n\n req.auth = { ...decoded, twoFactorAuthenticated: true };\n next();\n } catch (error) {\r\n return res.status(401).json({ message: 'Invalid or expired token' });\r\n }\r\n }\r\n}\n","import { BaseRepository, IExtendedBaseRepository } from \"cca-core\";\r\nimport { AdminEntity, AuthEntity, UserEntity } 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 result = await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect(\"auth.password\")\r\n .where(\"auth.email = :email\", { email })\r\n .getOne();\r\n\r\n return result;\r\n }\r\n\r\n async create(entity: Omit<AuthEntity, \"createdAt\">): Promise<AuthEntity> {\r\n const now = new Date();\r\n const auth = this.repository.create({\r\n ...entity,\r\n createdAt: now,\r\n updatedAt: now,\r\n isDeleted: false,\r\n } as unknown as AuthEntity);\r\n\r\n return this.repository.save(auth);\r\n }\r\n\r\n async findByUserOrAdminId(id: string): Promise<AuthEntity | null> {\r\n return await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect([\"auth.twoFactorSecret\", \"auth.refreshToken\"])\r\n .where(\"user.id = :id\", { id })\r\n .orWhere(\"admin.id = :id\", { id })\r\n .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\", \"auth.refreshToken\"]);\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.findByUserOrAdminId(userId);\r\n\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n const account = auth.user ?? auth.admin;\r\n\r\n if (account) {\r\n auth.refreshToken = \"\";\r\n account.isActive = false;\r\n await this.saveAccount(account);\r\n }\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.findByUserOrAdminId(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 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 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.findByUserOrAdminId(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.findByUserOrAdminId(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 async saveAccount(account: UserEntity | AdminEntity): Promise<void> {\r\n await this.repository.manager.save(account);\r\n }\r\n}\r\n","import * as jwt from \"jsonwebtoken\";\r\nimport { Secret } from \"jsonwebtoken\";\nimport { IBaseService, validateRepository } from \"cca-core\";\nimport { AdminEntity, UserEntity, UserRole } from \"cca-entities\";\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 { JwtError, UnauthorizedError } from \"../../utils/Errors\";\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nexport class JwtAuthService implements IBaseService, IAuthService {\n private jwtConfig: IJwtConfig | undefined;\n\n constructor(private readonly repository: AuthRepository, config?: IJwtConfig) {\n if (config) {\n this.jwtConfig = {\n accessTokenSecret: config.accessTokenSecret,\n refreshTokenSecret: config.refreshTokenSecret,\n accessTokenExpiry: config.accessTokenExpiry,\n refreshTokenExpiry: config.refreshTokenExpiry,\n };\n }\n\n this.validateConfiguration();\n }\n\n async initialize(): Promise<void> {\n await validateRepository(this.repository, repo => repo.getAll());\n this.validateConfiguration();\n }\n\n private validateConfiguration(): void {\n if (!this.jwtConfig?.accessTokenSecret || !this.jwtConfig?.refreshTokenSecret) {\n throw new JwtError(\"JWT secrets required in config\");\n }\n if (this.jwtConfig.accessTokenExpiry == null || this.jwtConfig.refreshTokenExpiry == null) {\n throw new JwtError(\"JWT expirations required in config\");\n }\n }\n\r\n private verifyJwtConfig() {\r\n if (!this.jwtConfig) throw new JwtError(\"JWT config not loaded\");\r\n }\r\n\r\n generateAccessToken(\n user: UserEntity | AdminEntity,\n role: UserRole,\n twoFactorAuthenticated: boolean = false\n ): string {\n this.verifyJwtConfig();\n return jwt.sign(\n {\n userId: user.id,\n email: user.email,\n role: role,\n twoFactorAuthenticated,\n },\n this.jwtConfig!.accessTokenSecret as Secret,\n { expiresIn: this.jwtConfig!.accessTokenExpiry }\n );\n }\n\r\n generateRefreshToken(user: UserEntity | AdminEntity): 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> {\n try {\n return jwt.verify(token, secret) as IDecodedToken;\n } catch (error) {\n throw new UnauthorizedError();\n }\n }\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) {\n this.config = config;\n\n const parsedTokenWindow = Number.parseInt(config.tokenWindow, 10);\n const parsedSecretLength = Number.parseInt(config.secretLength, 10);\n\n this.twoFactorConfig = {\n tokenWindow: Number.isFinite(parsedTokenWindow) ? parsedTokenWindow : 1,\n secretLength: Number.isFinite(parsedSecretLength) ? parsedSecretLength : 20,\n qrCodeOptions: {\n errorCorrectionLevel: 'M',\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}\n"],"mappings":"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","names":["import_cca_core","import_cca_entities","bcrypt","crypto","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","import_cca_core"]}
package/dist/index.mjs CHANGED
@@ -1028,10 +1028,10 @@ var _AuthRepository = class _AuthRepository extends BaseRepository {
1028
1028
  return this.repository.save(auth);
1029
1029
  }
1030
1030
  async findByUserOrAdminId(id) {
1031
- return await this.repository.createQueryBuilder("auth").leftJoinAndSelect("auth.user", "user").leftJoinAndSelect("auth.admin", "admin").addSelect("auth.twoFactorSecret").where("user.id = :id", { id }).orWhere("admin.id = :id", { id }).getOne();
1031
+ return await this.repository.createQueryBuilder("auth").leftJoinAndSelect("auth.user", "user").leftJoinAndSelect("auth.admin", "admin").addSelect(["auth.twoFactorSecret", "auth.refreshToken"]).where("user.id = :id", { id }).orWhere("admin.id = :id", { id }).getOne();
1032
1032
  }
1033
1033
  async findByUseAdminId(userId, isAdmin = false) {
1034
- const query = this.repository.createQueryBuilder("auth").addSelect("auth.twoFactorSecret");
1034
+ const query = this.repository.createQueryBuilder("auth").addSelect(["auth.twoFactorSecret", "auth.refreshToken"]);
1035
1035
  if (isAdmin) {
1036
1036
  query.leftJoinAndSelect("auth.admin", "admin").where("admin.id = :userId", { userId });
1037
1037
  } else {
@@ -1 +1 @@
1
- {"version":3,"sources":["../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 { 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\";\nimport { AuthEntity } from \"cca-entities\";\nimport type { SignOptions } from \"jsonwebtoken\";\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 configData = await createConfigInstance();\n\n const parseExpiry = (value: string): SignOptions[\"expiresIn\"] => {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : (value as SignOptions[\"expiresIn\"]);\n };\n\n const jwtConfig = {\n accessTokenSecret: configData.accessTokenSecret,\n refreshTokenSecret: configData.refreshTokenSecret,\n accessTokenExpiry: parseExpiry(configData.accessTokenExpiry),\n refreshTokenExpiry: parseExpiry(configData.refreshTokenExpiry),\n };\n\n const configuredJwtAuthService = new JwtAuthService(authRepository, jwtConfig);\n container.registerService(\"JwtAuthService\", configuredJwtAuthService);\n\n const twoFactorService = new TwoFactorService(configData);\n container.registerService(\"TwoFactorService\", twoFactorService);\n\n const requireComplete2FA = new RequireComplete2FA(configuredJwtAuthService);\n\n const loginUseCase = new LoginUseCase(authRepository, configuredJwtAuthService);\n const logoutUseCase = new LogoutUseCase(authRepository);\n const registerUseCase = new RegisterUseCase(authRepository);\n const refreshTokenUseCase = new RefreshTokenUseCase(\n authRepository,\n configuredJwtAuthService\n );\n\r\n const twoFactorSetupUseCase = new TwoFactorSetupUseCase(twoFactorService, authRepository);\r\n const twoFactorEnableUseCase = new TwoFactorEnableUseCase(twoFactorService, authRepository);\r\n const twoFactorVerifyUseCase = new TwoFactorVerifyUseCase(\n twoFactorService,\n authRepository,\n configuredJwtAuthService\n );\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 };\n","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\nimport { NotFoundError } from \"../../utils/Errors\";\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): Promise<{ id: string, accessToken: string, expiresAt: number, enabled?: boolean }> {\r\n const isAdmin = !!providedAdminPassword;\r\n\r\n if (isAdmin) {\r\n await validateAdminSecret(providedAdminPassword);\r\n }\r\n\r\n const auth = await validateLoginDTO(loginDTO, this.repository);\r\n\r\n const account = isAdmin ? auth.admin : auth.user;\r\n if (!account) {\r\n throw new NotFoundError(`${isAdmin ? \"Admin\" : \"User\"} account not found or inactive`);\r\n }\r\n\r\n const accessToken = this.jwtService.generateAccessToken(account, auth.role, false);\n const decoded = jwtDecode<IJwtPayload>(accessToken);\n const expiresAt = decoded.exp ?? 0;\n\r\n\r\n return { id: account.id, accessToken, expiresAt, enabled: auth.twoFactorEnabled };\r\n }\r\n}\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\";\n\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\nimport { LoginDTO } from \"../dtos/LoginDTO\";\nimport { createConfigInstance } from \"../service/utils/configInstance\";\nimport crypto from \"crypto\";\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 (\n email: string,\n repository: AuthRepository\n): Promise<AuthEntity> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n const user = await repository.findByEmail(normalizedEmail);\n if (!user) {\n throw new NotFoundError(\n \"The email address or password is incorrect. Please retry\"\n );\n }\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 (\n repository: AuthRepository,\n email: string,\n excludeUserId?: string\n): Promise<void> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n\n const existingUser = await repository.findByEmail(normalizedEmail);\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 (\n secretPassword?: string\n): Promise<void> => {\n if (!secretPassword) {\n throw new ValidationError(\"Admin password is required\");\n }\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 const provided = secretPassword.trim();\n const expected = config.adminSecretPassword.trim();\n if (provided.length !== expected.length) {\n throw new ValidationError(\"Invalid admin password\");\n }\n\n const providedBuf = Buffer.from(provided);\n const expectedBuf = Buffer.from(expected);\n if (!crypto.timingSafeEqual(providedBuf, expectedBuf)) {\n throw new ValidationError(\"Invalid admin password\");\n }\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(userId: string | undefined): Promise<void> {\n try {\n if (!userId) {\n throw new NotFoundError(\"User ID is required\");\n }\n await this.repository.logout(userId);\n } catch (error) {\n if (error instanceof NotFoundError) {\n throw error;\n }\n throw new NotFoundError(\"Auth not found\");\n }\n }\n}\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\n ? mapper.map(dto, RegisterDTO, AdminEntity)\n : mapper.map(dto, RegisterDTO, UserEntity);\n\n userOrAdminEntity.updatedAt = undefined as unknown as Date;\n\n if (isAdmin) {\n authEntity.admin = userOrAdminEntity as AdminEntity;\n } else {\n authEntity.user = userOrAdminEntity as UserEntity;\n }\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> {\n try {\n if (!refreshToken) return null;\n\n const decoded = await this.service.verifyRefreshToken(refreshToken);\n if (!decoded.userId) return null;\n\n const authEntity = await this.repository.findByUserOrAdminId(decoded.userId);\n if (!authEntity) return null;\n if (!authEntity.refreshToken || authEntity.refreshToken !== refreshToken) return null;\n\r\n const account = authEntity.user ?? authEntity.admin;\r\n if (!account) return null;\r\n\r\n const accessToken = this.service.generateAccessToken(\n account,\n authEntity.role,\n !!authEntity.twoFactorEnabled\n );\n const newRefreshToken = this.service.generateRefreshToken(account);\n\r\n await this.repository.update(authEntity.id, { refreshToken: newRefreshToken });\r\n\r\n return { accessToken, refreshToken: newRefreshToken };\r\n } catch (error) {\n return null;\n }\n }\n}\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.findByUserOrAdminId(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> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token, userId } = dto;\n \n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const auth: AuthEntity | null = await this.authRepository.findByUserOrAdminId(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}\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 { NotFoundError, 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.findByUserOrAdminId(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> {\n const account = auth.user ?? auth.admin;\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\n account.lastLoginAt = new Date();\n account.isActive = true;\n await this.authRepository.saveAccount(account);\n }\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 const account = auth.user ?? auth.admin;\r\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\r\n\r\n return {\n accessToken: this.jwtService.generateAccessToken(account, auth.role, true),\n refreshToken: this.jwtService.generateRefreshToken(account)\n };\n }\n}\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> {\n if (this.isInitialized) return;\n \n await Promise.all([\n this.twoFactorService.initialize(),\n validateRepository(this.authRepository, repo => repo.getAll())\n ]);\n\n this.isInitialized = true;\n }\n\n async execute(userId: string, dto: ITwoFactorEnable): Promise<void> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token } = dto;\n\n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const user = await this.authRepository.findByUserOrAdminId(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}\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);\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);\n\n const adminLoginData = {\n accessToken: result.accessToken,\n userId: result.id,\n expiresAt: result.expiresAt,\n auth: this.createAuthData(\n true,\n result.enabled ?? false,\n (result.enabled ?? false) ? AUTH_STATUS.PENDING_VERIFICATION : AUTH_STATUS.BASIC_AUTH,\n false\n ),\n };\n\n this.sendResponse(res, HTTP_STATUS.CREATED, MESSAGES.ADMIN_LOGIN_SUCCESS, adminLoginData);\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> => {\n try {\n const userId = req.auth?.userId ?? req.body.id;\n await this.logoutUseCase.execute(userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n\n const result = await this.twoFactorSetupUseCase.execute(req.auth.userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = { ...req.body, userId: req.auth?.userId };\n await this.twoFactorEnableUseCase.execute(dto);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorVerify = { ...req.body, userId: req.auth.userId };\n const result = await this.twoFactorVerifyUseCase.execute(dto);\n if (!result) {\n throw new Error(\"Two-factor verification failed\");\n }\n\r\n const verifyData = {\r\n token: result.token,\n refreshToken: result.refreshToken,\n user: {\n id: result.data?.id,\n email: result.data?.email,\n name: result.data?.name,\n role: result.data?.role,\n },\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> => {\n try {\n const userId = req.auth?.userId;\n if (!userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = req.body;\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}\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);\n\n if (!decoded.userId) {\n return res.status(401).json({ message: 'Invalid token payload' });\n }\n\n if (!decoded.twoFactorAuthenticated) {\n return res.status(403).json({\n message: 'Two-factor authentication required',\n code: 'REQUIRE_2FA',\n userId: decoded.userId\n });\n }\n\n req.auth = { ...decoded, twoFactorAuthenticated: true };\n next();\n } catch (error) {\r\n return res.status(401).json({ message: 'Invalid or expired token' });\r\n }\r\n }\r\n}\n","import { BaseRepository, IExtendedBaseRepository } from \"cca-core\";\r\nimport { AdminEntity, AuthEntity, UserEntity } from \"cca-entities\";\nimport { Repository } from \"typeorm\";\nimport { NotFoundError } from \"../../utils/Errors\";\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 result = await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect(\"auth.password\")\r\n .where(\"auth.email = :email\", { email })\r\n .getOne();\r\n\r\n return result;\r\n }\r\n\r\n async create(entity: Omit<AuthEntity, \"createdAt\">): Promise<AuthEntity> {\n const now = new Date();\n const auth = this.repository.create({\n ...entity,\n createdAt: now,\n updatedAt: now,\n isDeleted: false,\n } as unknown as AuthEntity);\n\n return this.repository.save(auth);\n }\n\r\n async findByUserOrAdminId(id: string): Promise<AuthEntity | null> {\r\n return await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect(\"auth.twoFactorSecret\")\r\n .where(\"user.id = :id\", { id })\r\n .orWhere(\"admin.id = :id\", { id })\r\n .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> {\n const auth = await this.findByUserOrAdminId(userId);\n\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n const account = auth.user ?? auth.admin;\r\n\r\n if (account) {\n auth.refreshToken = \"\";\n account.isActive = false;\n await this.saveAccount(account);\n }\n\n await this.update(auth.id, auth);\n }\n\r\n async updateTwoFactorSecret(userId: string, secret: string): Promise<void> {\r\n const auth = await this.findByUserOrAdminId(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> {\n auth.twoFactorEnabled = true;\n\n await this.update(auth.id, auth);\n }\n\r\n async disableTwoFactor(auth: AuthEntity): Promise<void> {\n auth.twoFactorEnabled = false;\n auth.twoFactorSecret = null;\n\n await this.update(auth.id, auth);\n }\n\r\n async isTwoFactorEnabled(userId: string): Promise<boolean> {\r\n const auth = await this.findByUserOrAdminId(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> {\n const auth = await this.findByUserOrAdminId(userId);\n if (!auth) {\n throw new NotFoundError(\"Auth not found\");\n }\n\n return auth.twoFactorSecret;\n }\n\n async saveAccount(account: UserEntity | AdminEntity): Promise<void> {\n await this.repository.manager.save(account);\n }\n}\n","import * as jwt from \"jsonwebtoken\";\r\nimport { Secret } from \"jsonwebtoken\";\nimport { IBaseService, validateRepository } from \"cca-core\";\nimport { AdminEntity, UserEntity, UserRole } from \"cca-entities\";\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 { JwtError, UnauthorizedError } from \"../../utils/Errors\";\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nexport class JwtAuthService implements IBaseService, IAuthService {\n private jwtConfig: IJwtConfig | undefined;\n\n constructor(private readonly repository: AuthRepository, config?: IJwtConfig) {\n if (config) {\n this.jwtConfig = {\n accessTokenSecret: config.accessTokenSecret,\n refreshTokenSecret: config.refreshTokenSecret,\n accessTokenExpiry: config.accessTokenExpiry,\n refreshTokenExpiry: config.refreshTokenExpiry,\n };\n }\n\n this.validateConfiguration();\n }\n\n async initialize(): Promise<void> {\n await validateRepository(this.repository, repo => repo.getAll());\n this.validateConfiguration();\n }\n\n private validateConfiguration(): void {\n if (!this.jwtConfig?.accessTokenSecret || !this.jwtConfig?.refreshTokenSecret) {\n throw new JwtError(\"JWT secrets required in config\");\n }\n if (this.jwtConfig.accessTokenExpiry == null || this.jwtConfig.refreshTokenExpiry == null) {\n throw new JwtError(\"JWT expirations required in config\");\n }\n }\n\r\n private verifyJwtConfig() {\r\n if (!this.jwtConfig) throw new JwtError(\"JWT config not loaded\");\r\n }\r\n\r\n generateAccessToken(\n user: UserEntity | AdminEntity,\n role: UserRole,\n twoFactorAuthenticated: boolean = false\n ): string {\n this.verifyJwtConfig();\n return jwt.sign(\n {\n userId: user.id,\n email: user.email,\n role: role,\n twoFactorAuthenticated,\n },\n this.jwtConfig!.accessTokenSecret as Secret,\n { expiresIn: this.jwtConfig!.accessTokenExpiry }\n );\n }\n\r\n generateRefreshToken(user: UserEntity | AdminEntity): 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> {\n try {\n return jwt.verify(token, secret) as IDecodedToken;\n } catch (error) {\n throw new UnauthorizedError();\n }\n }\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) {\n this.config = config;\n\n const parsedTokenWindow = Number.parseInt(config.tokenWindow, 10);\n const parsedSecretLength = Number.parseInt(config.secretLength, 10);\n\n this.twoFactorConfig = {\n tokenWindow: Number.isFinite(parsedTokenWindow) ? parsedTokenWindow : 1,\n secretLength: Number.isFinite(parsedSecretLength) ? parsedSecretLength : 20,\n qrCodeOptions: {\n errorCorrectionLevel: 'M',\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}\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,oBAAoB;;;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,aAAa;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,SAAS,qBAAmC;AAC5C,SAAS,cAAAA,mBAAkB;;;ACD3B,SAAuB,0BAA0B;AACjD,SAAS,iBAAiB;;;ACD1B,YAAY,SAAS;AACrB,SAAqB,gBAAgB;AACrC,OAAO,YAAY;AAYnB,OAAO,YAAY;AAEnB,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,QAAQ,GAAG,wBAAwB;AAC5D;AAEO,IAAM,gBAAgB,8BAC3B,OACA,eACwB;AACxB,MAAI;AACF,UAAM,kBAAkB,OAAO,KAAK,EAAE,YAAY;AAClD,UAAM,QAAQ,MAAM,SAAS,eAAe;AAC5C,UAAM,OAAO,MAAM,WAAW,YAAY,eAAe;AACzD,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,GAjB6B;AAmBtB,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,kBAAkB,OAAO,KAAK,EAAE,YAAY;AAClD,UAAM,QAAQ,MAAM,SAAS,eAAe;AAE5C,UAAM,eAAe,MAAM,WAAW,YAAY,eAAe;AAEjE,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,GArBuC;AAuBhC,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,OAAO,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,UAAM,WAAW,eAAe,KAAK;AACrC,UAAM,WAAW,OAAO,oBAAoB,KAAK;AACjD,QAAI,SAAS,WAAW,SAAS,QAAQ;AACvC,YAAM,IAAI,gBAAgB,wBAAwB;AAAA,IACpD;AAEA,UAAM,cAAc,OAAO,KAAK,QAAQ;AACxC,UAAM,cAAc,OAAO,KAAK,QAAQ;AACxC,QAAI,CAAC,OAAO,gBAAgB,aAAa,WAAW,GAAG;AACrD,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,GA/BmC;;;AD1H5B,IAAM,gBAAN,MAAM,cAAqC;AAAA,EAEhD,YACmB,YACA,YACjB;AAFiB;AACA;AAAA,EACf;AAAA,EAEJ,MAAa,aAA4B;AACvC,UAAM,mBAAmB,KAAK,YAAY,CAAC,SAAyB,KAAK,OAAO,CAAC;AAAA,EACnF;AAAA,EAEA,MAAM,QAAQ,UAAoB,uBAAoH;AACpJ,UAAM,UAAU,CAAC,CAAC;AAElB,QAAI,SAAS;AACX,YAAM,oBAAoB,qBAAqB;AAAA,IACjD;AAEA,UAAM,OAAO,MAAM,iBAAiB,UAAU,KAAK,UAAU;AAE7D,UAAM,UAAU,UAAU,KAAK,QAAQ,KAAK;AAC5C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,cAAc,GAAG,UAAU,UAAU,MAAM,gCAAgC;AAAA,IACvF;AAEA,UAAM,cAAc,KAAK,WAAW,oBAAoB,SAAS,KAAK,MAAM,KAAK;AACjF,UAAM,UAAU,UAAuB,WAAW;AAClD,UAAM,YAAY,QAAQ,OAAO;AAGjC,WAAO,EAAE,IAAI,QAAQ,IAAI,aAAa,WAAW,SAAS,KAAK,iBAAiB;AAAA,EAClF;AACF;AAhCkD;AAA3C,IAAM,eAAN;;;AEXP,SAAuB,sBAAAC,2BAA0B;AAM1C,IAAM,iBAAN,MAAM,eAAsC;AAAA,EAG/C,YAAY,YAA4B;AACpC,SAAK,aAAa;AAAA,EACtB;AAAA,EAEA,MAAa,aAA4B;AACrC,UAAMC,oBAAmB,KAAK,YAAY,CAAC,SAAyB,KAAK,OAAO,CAAC;AAAA,EACrF;AAAA,EAEA,MAAM,QAAQ,QAA2C;AACrD,QAAI;AACA,UAAI,CAAC,QAAQ;AACT,cAAM,IAAI,cAAc,qBAAqB;AAAA,MACjD;AACA,YAAM,KAAK,WAAW,OAAO,MAAM;AAAA,IACvC,SAAS,OAAO;AACZ,UAAI,iBAAiB,eAAe;AAChC,cAAM;AAAA,MACV;AACA,YAAM,IAAI,cAAc,gBAAgB;AAAA,IAC5C;AAAA,EACJ;AACJ;AAxBmD;AAA5C,IAAM,gBAAN;;;ACNP,SAAuB,sBAAAC,2BAA0B;AACjD,YAAYC,aAAY;AACxB,SAAS,eAAAC,cAAa,cAAAC,aAAY,cAAAC,aAAY,YAAAC,iBAAgB;;;ACF9D,SAAS,oBAAoB;AAC7B,SAAS,eAAe;;;ACDxB,SAAiB,WAAW,WAAW,eAAe;AACtD,SAAS,aAAa,cAAAC,aAAY,kBAAkB;;;ACC7C,IAAM,eAAN,MAAM,aAAY;AAMzB;AANyB;AAAlB,IAAM,cAAN;;;ACFP,SAAS,eAAe;AAGjB,IAAM,WAAN,MAAM,SAAQ;AAerB;AAfqB;AAEnB;AAAA,EADC,QAAQ;AAAA,GADE,SAEX;AAGA;AAAA,EADC,QAAQ;AAAA,GAJE,SAKX;AAGA;AAAA,EADC,QAAQ;AAAA,GAPE,SAQX;AAGA;AAAA,EADC,QAAQ;AAAA,GAVE,SAWX;AAGA;AAAA,EADC,QAAQ;AAAA,GAbE,SAcX;AAdK,IAAM,UAAN;;;ACHP,SAAS,WAAAC,gBAAe;AAGjB,IAAM,YAAN,MAAM,UAAS;AActB;AAdsB;AAEpB;AAAA,EADCC,SAAQ;AAAA,GADE,UAEX;AAGA;AAAA,EADCA,SAAQ;AAAA,GAJE,UAKX;AAGA;AAAA,EADCA,SAAQ;AAAA,GAPE,UAQX;AAGA;AAAA,EADCA,SAAQ;AAAA,GAVE,UAWX;AAXK,IAAM,WAAN;;;AHIA,SAAS,mBAAmBC,SAAsB;AACrD;AAAA,IACIA;AAAA,IACA;AAAA,IACAC;AAAA,IACA,UAAU,UAAQ,KAAK,OAAO,QAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,IACvD,UAAU,UAAQ,KAAK,UAAU,QAAQ,SAAO,IAAI,QAAQ,CAAC;AAAA,IAC7D,UAAU,UAAQ,KAAK,MAAM,QAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,EAAC;AAE1D;AAAA,IACID;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,UAAQ,KAAK,MAAM,QAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,IACrD,UAAU,UAAQ,KAAK,OAAO,QAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,EAAC;AAE5D;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,UAAQ,KAAK,MAAM,QAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,IACrD,UAAU,UAAQ,KAAK,OAAO,QAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,EAAC;AAE5D;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,UAAQ,KAAK,IAAI,QAAQ,SAAO,IAAI,EAAE,CAAC;AAAA,IACjD,UAAU,UAAQ,KAAK,MAAM,QAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,IACrD,UAAU,UAAQ,KAAK,OAAO,QAAQ,SAAO,IAAI,KAAK,CAAC;AAAA,IACvD,UAAU,UAAQ,KAAK,iBAAiB,QAAQ,SAAO,mBAAmB,GAAG,CAAC,CAAC;AAAA,EAAC;AAGpF;AAAA,IACIA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,UAAQ,KAAK,IAAI,QAAQ,SAAO,IAAI,EAAE,CAAC;AAAA,IACjD,UAAU,UAAQ,KAAK,MAAM,QAAQ,SAAO,IAAI,IAAI,CAAC;AAAA,IACrD,UAAU,UAAQ,KAAK,OAAO,QAAQ,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,SAAS,aAAa;AAAA,EACjC,qBAAqB,QAAQ;AAC/B,CAAC;AAED,mBAAmB,MAAM;;;ADClB,IAAM,mBAAN,MAAM,iBAAwC;AAAA,EAGnD,YAA6B,YAA4B;AAA5B;AAF7B,SAAiB,cAAc;AAAA,EAE4B;AAAA,EAE3D,MAAa,aAA4B;AACvC,UAAME,oBAAmB,KAAK,YAAY,CAAC,SAAS,KAAK,OAAO,CAAC;AAAA,EACnE;AAAA,EAEA,MAAa,QACX,OACA,MACA,UACA,OAAiBC,UAAS,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,SAASA,UAAS,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,aAAaC,WAAU;AAC1D,UAAM,oBAAoB,UACtB,OAAO,IAAI,KAAK,aAAaC,YAAW,IACxC,OAAO,IAAI,KAAK,aAAaC,WAAU;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,SAAuB,sBAAAC,2BAA0B;AAK1C,IAAM,uBAAN,MAAM,qBAA4C;AAAA,EAIvD,YAAY,YAA4B,SAAyB;AAC/D,SAAK,aAAa;AAClB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAa,aAA4B;AACvC,UAAMC,oBAAmB,KAAK,YAAY,CAAC,SAAyB,KAAK,OAAO,CAAC;AAAA,EACnF;AAAA,EAEA,MAAa,QAAQ,cAAkD;AACrE,QAAI;AACF,UAAI,CAAC,aAAc,QAAO;AAE1B,YAAM,UAAU,MAAM,KAAK,QAAQ,mBAAmB,YAAY;AAClE,UAAI,CAAC,QAAQ,OAAQ,QAAO;AAE5B,YAAM,aAAa,MAAM,KAAK,WAAW,oBAAoB,QAAQ,MAAM;AAC3E,UAAI,CAAC,WAAY,QAAO;AACxB,UAAI,CAAC,WAAW,gBAAgB,WAAW,iBAAiB,aAAc,QAAO;AAEjF,YAAM,UAAU,WAAW,QAAQ,WAAW;AAC9C,UAAI,CAAC,QAAS,QAAO;AAErB,YAAM,cAAc,KAAK,QAAQ;AAAA,QAC/B;AAAA,QACA,WAAW;AAAA,QACX,CAAC,CAAC,WAAW;AAAA,MACf;AACA,YAAM,kBAAkB,KAAK,QAAQ,qBAAqB,OAAO;AAEjE,YAAM,KAAK,WAAW,OAAO,WAAW,IAAI,EAAE,cAAc,gBAAgB,CAAC;AAE7E,aAAO,EAAE,aAAa,cAAc,gBAAgB;AAAA,IACtD,SAAS,OAAO;AACd,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAzCyD;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,oBAAoB,MAAM;AAEjE,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,SAAuB,sBAAAC,2BAA0B;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,MACjCC,oBAAmB,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;AACA,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,eAAe,qBAAqB;AAAA,IAChD;AAEA,UAAM,OAA0B,MAAM,KAAK,eAAe,oBAAoB,MAAM;AAEpF,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;AArD2D;AAApD,IAAM,yBAAN;;;ACRP,SAAuB,sBAAAC,2BAA0B;AACjD,SAAS,eAAAC,cAAyB,cAAAC,mBAAkB;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,MAC3BC,oBAAmB,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,oBAAoB,MAAM;AACpF,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,OAAOC,cAAa,QAAQ;AAAA,EAClD;AAAA,EAEQ,aAAa,MAA2B;AAC5C,WAAO,OAAO,IAAI,MAAMC,aAAY,OAAO;AAAA,EAC/C;AAAA,EAEA,MAAc,iBAAiB,MAAiC;AAC5D,UAAM,UAAU,KAAK,QAAQ,KAAK;AAClC,QAAI,CAAC,QAAS,OAAM,IAAI,cAAc,gDAAgD;AACtF,YAAQ,cAAc,oBAAI,KAAK;AAC/B,YAAQ,WAAW;AACnB,UAAM,KAAK,eAAe,YAAY,OAAO;AAAA,EACjD;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,UAAM,UAAU,KAAK,QAAQ,KAAK;AAClC,QAAI,CAAC,QAAS,OAAM,IAAI,cAAc,gDAAgD;AAEtF,WAAO;AAAA,MACH,aAAa,KAAK,WAAW,oBAAoB,SAAS,KAAK,MAAM,IAAI;AAAA,MACzE,cAAc,KAAK,WAAW,qBAAqB,OAAO;AAAA,IAC9D;AAAA,EACJ;AACJ;AA5F4D;AAArD,IAAM,yBAAN;;;ACbP,SAAuB,sBAAAC,2BAA0B;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,MACjCC,oBAAmB,KAAK,gBAAgB,UAAQ,KAAK,OAAO,CAAC;AAAA,IACjE,CAAC;AAED,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,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,eAAe,mBAAmB;AAAA,IAC9C;AACA,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,eAAe,qBAAqB;AAAA,IAChD;AAEA,UAAM,OAAO,MAAM,KAAK,eAAe,oBAAoB,MAAM;AAEjE,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;AAhD4D;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;;;ACJO,IAAM,kBAAN,MAAM,gBAAe;AAAA,EAU1B,YACE,cACA,eACA,iBACA,qBACA,uBACA,wBACA,wBACA,yBACA;AAoDF,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,aAAa,QAAQ,UAAU,aAAa;AAEtE,cAAM,iBAAiB;AAAA,UACrB,aAAa,OAAO;AAAA,UACpB,QAAQ,OAAO;AAAA,UACf,WAAW,OAAO;AAAA,UAClB,MAAM,KAAK;AAAA,YACT;AAAA,YACA,OAAO,WAAW;AAAA,YACjB,OAAO,WAAW,QAAS,YAAY,uBAAuB,YAAY;AAAA,YAC3E;AAAA,UACF;AAAA,QACF;AAEA,aAAK,aAAa,KAAK,YAAY,SAAS,SAAS,qBAAqB,cAAc;AAAA,MAC1F,SAAS,OAAO;AACd,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,GA1Ba;AA4Bb,kBAAS,8BAAO,KAAc,KAAe,SAAsC;AACjF,UAAI;AACF,cAAM,SAAS,IAAI,MAAM,UAAU,IAAI,KAAK;AAC5C,cAAM,KAAK,cAAc,QAAQ,MAAM;AAEvC,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,GAlBS;AAoBT,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,QAAQ;AACrB,gBAAM,IAAI,eAAe,8BAA8B;AAAA,QACzD;AAEA,cAAM,SAAS,MAAM,KAAK,sBAAsB,QAAQ,IAAI,KAAK,MAAM;AAEvE,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,YAAI,CAAC,IAAI,MAAM,QAAQ;AACrB,gBAAM,IAAI,eAAe,8BAA8B;AAAA,QACzD;AACA,cAAM,MAAwB,EAAE,GAAG,IAAI,MAAM,QAAQ,IAAI,MAAM,OAAO;AACtE,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,GAtBY;AAwBZ,qBAAY,8BAAO,KAAc,KAAe,SAAsC;AACpF,UAAI;AACF,YAAI,CAAC,IAAI,MAAM,QAAQ;AACrB,gBAAM,IAAI,eAAe,8BAA8B;AAAA,QACzD;AACA,cAAM,MAAwB,EAAE,GAAG,IAAI,MAAM,QAAQ,IAAI,KAAK,OAAO;AACrE,cAAM,SAAS,MAAM,KAAK,uBAAuB,QAAQ,GAAG;AAC5D,YAAI,CAAC,QAAQ;AACX,gBAAM,IAAI,MAAM,gCAAgC;AAAA,QAClD;AAEA,cAAM,aAAa;AAAA,UACjB,OAAO,OAAO;AAAA,UACd,cAAc,OAAO;AAAA,UACrB,MAAM;AAAA,YACJ,IAAI,OAAO,MAAM;AAAA,YACjB,OAAO,OAAO,MAAM;AAAA,YACpB,MAAM,OAAO,MAAM;AAAA,YACnB,MAAM,OAAO,MAAM;AAAA,UACrB;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,GAhCY;AAkCZ,sBAAa,8BAAO,KAAc,KAAe,SAAsC;AACrF,UAAI;AACF,cAAM,SAAS,IAAI,MAAM;AACzB,YAAI,CAAC,QAAQ;AACX,gBAAM,IAAI,eAAe,8BAA8B;AAAA,QACzD;AACA,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,GAxBa;AApQX,SAAK,eAAe;AACpB,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;AA4OF;AAjT4B;AAArB,IAAM,iBAAN;;;AClBA,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,QAAQ;AACnB,eAAO,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,SAAS,wBAAwB,CAAC;AAAA,MAClE;AAEA,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;AAnCgC;AAAzB,IAAM,qBAAN;;;ACHP,SAAS,sBAA+C;AAKjD,IAAM,kBAAN,MAAM,wBACH,eACuC;AAAA,EAC/C,YAAY,YAAoC;AAC9C,UAAM,UAAU;AAAA,EAClB;AAAA,EAEA,MAAM,YAAY,OAA2C;AAC3D,UAAM,SAAS,MAAM,KAAK,WACvB,mBAAmB,MAAM,EACzB,kBAAkB,aAAa,MAAM,EACrC,kBAAkB,cAAc,OAAO,EACvC,UAAU,eAAe,EACzB,MAAM,uBAAuB,EAAE,MAAM,CAAC,EACtC,OAAO;AAEV,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OAAO,QAA4D;AACvE,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,OAAO,KAAK,WAAW,OAAO;AAAA,MAClC,GAAG;AAAA,MACH,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAA0B;AAE1B,WAAO,KAAK,WAAW,KAAK,IAAI;AAAA,EAClC;AAAA,EAEA,MAAM,oBAAoB,IAAwC;AAChE,WAAO,MAAM,KAAK,WACf,mBAAmB,MAAM,EACzB,kBAAkB,aAAa,MAAM,EACrC,kBAAkB,cAAc,OAAO,EACvC,UAAU,sBAAsB,EAChC,MAAM,iBAAiB,EAAE,GAAG,CAAC,EAC7B,QAAQ,kBAAkB,EAAE,GAAG,CAAC,EAChC,OAAO;AAAA,EACZ;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,oBAAoB,MAAM;AAElD,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,cAAc,gBAAgB;AAAA,IAC1C;AACA,UAAM,UAAU,KAAK,QAAQ,KAAK;AAElC,QAAI,SAAS;AACX,WAAK,eAAe;AACpB,cAAQ,WAAW;AACnB,YAAM,KAAK,YAAY,OAAO;AAAA,IAChC;AAEA,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,sBAAsB,QAAgB,QAA+B;AACzE,UAAM,OAAO,MAAM,KAAK,oBAAoB,MAAM;AAClD,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;AACrD,SAAK,mBAAmB;AAExB,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,iBAAiB,MAAiC;AACtD,SAAK,mBAAmB;AACxB,SAAK,kBAAkB;AAEvB,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,mBAAmB,QAAkC;AACzD,UAAM,OAAO,MAAM,KAAK,oBAAoB,MAAM;AAClD,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,oBAAoB,MAAM;AAClD,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,cAAc,gBAAgB;AAAA,IAC1C;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,YAAY,SAAkD;AAClE,UAAM,KAAK,WAAW,QAAQ,KAAK,OAAO;AAAA,EAC5C;AACF;AAtHiD;AAF1C,IAAM,iBAAN;;;ACLP,YAAY,SAAS;AAErB,SAAuB,sBAAAC,2BAA0B;AAU1C,IAAM,kBAAN,MAAM,gBAAqD;AAAA,EAGhE,YAA6B,YAA4B,QAAqB;AAAjD;AAC3B,QAAI,QAAQ;AACV,WAAK,YAAY;AAAA,QACf,mBAAmB,OAAO;AAAA,QAC1B,oBAAoB,OAAO;AAAA,QAC3B,mBAAmB,OAAO;AAAA,QAC1B,oBAAoB,OAAO;AAAA,MAC7B;AAAA,IACF;AAEA,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAMC,oBAAmB,KAAK,YAAY,UAAQ,KAAK,OAAO,CAAC;AAC/D,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEQ,wBAA8B;AACpC,QAAI,CAAC,KAAK,WAAW,qBAAqB,CAAC,KAAK,WAAW,oBAAoB;AAC7E,YAAM,IAAI,SAAS,gCAAgC;AAAA,IACrD;AACA,QAAI,KAAK,UAAU,qBAAqB,QAAQ,KAAK,UAAU,sBAAsB,MAAM;AACzF,YAAM,IAAI,SAAS,oCAAoC;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,kBAAkB;AACxB,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,SAAS,uBAAuB;AAAA,EACjE;AAAA,EAEA,oBACE,MACA,MACA,yBAAkC,OAC1B;AACR,SAAK,gBAAgB;AACrB,WAAW;AAAA,MACT;AAAA,QACE,QAAQ,KAAK;AAAA,QACb,OAAO,KAAK;AAAA,QACZ;AAAA,QACA;AAAA,MACF;AAAA,MACA,KAAK,UAAW;AAAA,MAChB,EAAE,WAAW,KAAK,UAAW,kBAAkB;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,qBAAqB,MAAwC;AAC3D,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,aAAW,WAAO,OAAO,MAAM;AAAA,IACjC,SAAS,OAAO;AACd,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;AA9EkE;AAA3D,IAAM,iBAAN;;;ACZP,YAAY,eAAe;AAC3B,YAAY,YAAY;AAMjB,IAAM,oBAAN,MAAM,kBAAyC;AAAA,EASpD,YAAY,QAAiB;AAP7B,SAAQ,cAAuB;AAQ7B,SAAK,SAAS;AAEd,UAAM,oBAAoB,OAAO,SAAS,OAAO,aAAa,EAAE;AAChE,UAAM,qBAAqB,OAAO,SAAS,OAAO,cAAc,EAAE;AAElE,SAAK,kBAAkB;AAAA,MACrB,aAAa,OAAO,SAAS,iBAAiB,IAAI,oBAAoB;AAAA,MACtE,cAAc,OAAO,SAAS,kBAAkB,IAAI,qBAAqB;AAAA,MACzE,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;AA5GsD;AAA/C,IAAM,mBAAN;;;ApBcP,eAAe,oBAAoB,UAAwB;AACzD,QAAM,YAAY,IAAI,cAAc,EAAE,SAAS,CAAC;AAEhD,QAAM,iBAAiB,IAAI;AAAA,IACzB,SAAS,cAAcC,WAAU;AAAA,EACnC;AACA,YAAU,mBAA+B,kBAAkB,cAAc;AAEzE,QAAM,aAAa,MAAM,qBAAqB;AAE9C,QAAM,cAAc,wBAAC,UAA4C;AAC/D,UAAM,UAAU,OAAO,KAAK;AAC5B,WAAO,OAAO,SAAS,OAAO,IAAI,UAAW;AAAA,EAC/C,GAHoB;AAKpB,QAAM,YAAY;AAAA,IAChB,mBAAmB,WAAW;AAAA,IAC9B,oBAAoB,WAAW;AAAA,IAC/B,mBAAmB,YAAY,WAAW,iBAAiB;AAAA,IAC3D,oBAAoB,YAAY,WAAW,kBAAkB;AAAA,EAC/D;AAEA,QAAM,2BAA2B,IAAI,eAAe,gBAAgB,SAAS;AAC7E,YAAU,gBAAgB,kBAAkB,wBAAwB;AAEpE,QAAM,mBAAmB,IAAI,iBAAiB,UAAU;AACxD,YAAU,gBAAgB,oBAAoB,gBAAgB;AAE9D,QAAM,qBAAqB,IAAI,mBAAmB,wBAAwB;AAE1E,QAAM,eAAe,IAAI,aAAa,gBAAgB,wBAAwB;AAC9E,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,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,EACF;AAEA,SAAO,EAAE,WAAW,gBAAgB,mBAAmB;AACzD;AApEe;","names":["AuthEntity","validateRepository","validateRepository","validateRepository","bcrypt","AdminEntity","AuthEntity","UserEntity","UserRole","AuthEntity","AutoMap","AutoMap","mapper","AuthEntity","validateRepository","UserRole","AuthEntity","AdminEntity","UserEntity","validateRepository","validateRepository","validateRepository","validateRepository","validateRepository","AdminEntity","UserEntity","validateRepository","AdminEntity","UserEntity","validateRepository","validateRepository","validateRepository","validateRepository","AuthEntity"]}
1
+ {"version":3,"sources":["../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 { 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\";\nimport { AuthEntity } from \"cca-entities\";\nimport type { SignOptions } from \"jsonwebtoken\";\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 configData = await createConfigInstance();\n\n const parseExpiry = (value: string): SignOptions[\"expiresIn\"] => {\n const numeric = Number(value);\n return Number.isFinite(numeric) ? numeric : (value as SignOptions[\"expiresIn\"]);\n };\n\n const jwtConfig = {\n accessTokenSecret: configData.accessTokenSecret,\n refreshTokenSecret: configData.refreshTokenSecret,\n accessTokenExpiry: parseExpiry(configData.accessTokenExpiry),\n refreshTokenExpiry: parseExpiry(configData.refreshTokenExpiry),\n };\n\n const configuredJwtAuthService = new JwtAuthService(authRepository, jwtConfig);\n container.registerService(\"JwtAuthService\", configuredJwtAuthService);\n\n const twoFactorService = new TwoFactorService(configData);\n container.registerService(\"TwoFactorService\", twoFactorService);\n\n const requireComplete2FA = new RequireComplete2FA(configuredJwtAuthService);\n\n const loginUseCase = new LoginUseCase(authRepository, configuredJwtAuthService);\n const logoutUseCase = new LogoutUseCase(authRepository);\n const registerUseCase = new RegisterUseCase(authRepository);\n const refreshTokenUseCase = new RefreshTokenUseCase(\n authRepository,\n configuredJwtAuthService\n );\n\r\n const twoFactorSetupUseCase = new TwoFactorSetupUseCase(twoFactorService, authRepository);\r\n const twoFactorEnableUseCase = new TwoFactorEnableUseCase(twoFactorService, authRepository);\r\n const twoFactorVerifyUseCase = new TwoFactorVerifyUseCase(\n twoFactorService,\n authRepository,\n configuredJwtAuthService\n );\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 };\n","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\nimport { NotFoundError } from \"../../utils/Errors\";\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): Promise<{ id: string, accessToken: string, expiresAt: number, enabled?: boolean }> {\r\n const isAdmin = !!providedAdminPassword;\r\n\r\n if (isAdmin) {\r\n await validateAdminSecret(providedAdminPassword);\r\n }\r\n\r\n const auth = await validateLoginDTO(loginDTO, this.repository);\r\n\r\n const account = isAdmin ? auth.admin : auth.user;\r\n if (!account) {\r\n throw new NotFoundError(`${isAdmin ? \"Admin\" : \"User\"} account not found or inactive`);\r\n }\r\n\r\n const accessToken = this.jwtService.generateAccessToken(account, auth.role, false);\n const decoded = jwtDecode<IJwtPayload>(accessToken);\n const expiresAt = decoded.exp ?? 0;\n\r\n\r\n return { id: account.id, accessToken, expiresAt, enabled: auth.twoFactorEnabled };\r\n }\r\n}\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\";\n\nimport { RegisterDTO } from \"../dtos/RegisterDTO\";\nimport { LoginDTO } from \"../dtos/LoginDTO\";\nimport { createConfigInstance } from \"../service/utils/configInstance\";\nimport crypto from \"crypto\";\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 (\n email: string,\n repository: AuthRepository\n): Promise<AuthEntity> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n const user = await repository.findByEmail(normalizedEmail);\n if (!user) {\n throw new NotFoundError(\n \"The email address or password is incorrect. Please retry\"\n );\n }\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 (\n repository: AuthRepository,\n email: string,\n excludeUserId?: string\n): Promise<void> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n\n const existingUser = await repository.findByEmail(normalizedEmail);\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 (\n secretPassword?: string\n): Promise<void> => {\n if (!secretPassword) {\n throw new ValidationError(\"Admin password is required\");\n }\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 const provided = secretPassword.trim();\n const expected = config.adminSecretPassword.trim();\n if (provided.length !== expected.length) {\n throw new ValidationError(\"Invalid admin password\");\n }\n\n const providedBuf = Buffer.from(provided);\n const expectedBuf = Buffer.from(expected);\n if (!crypto.timingSafeEqual(providedBuf, expectedBuf)) {\n throw new ValidationError(\"Invalid admin password\");\n }\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(userId: string | undefined): Promise<void> {\n try {\n if (!userId) {\n throw new NotFoundError(\"User ID is required\");\n }\n await this.repository.logout(userId);\n } catch (error) {\n if (error instanceof NotFoundError) {\n throw error;\n }\n throw new NotFoundError(\"Auth not found\");\n }\n }\n}\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\n ? mapper.map(dto, RegisterDTO, AdminEntity)\n : mapper.map(dto, RegisterDTO, UserEntity);\n\n userOrAdminEntity.updatedAt = undefined as unknown as Date;\n\n if (isAdmin) {\n authEntity.admin = userOrAdminEntity as AdminEntity;\n } else {\n authEntity.user = userOrAdminEntity as UserEntity;\n }\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> {\n try {\n if (!refreshToken) return null;\n\n const decoded = await this.service.verifyRefreshToken(refreshToken);\n if (!decoded.userId) return null;\n\n const authEntity = await this.repository.findByUserOrAdminId(decoded.userId);\n if (!authEntity) return null;\n if (!authEntity.refreshToken || authEntity.refreshToken !== refreshToken) return null;\n\r\n const account = authEntity.user ?? authEntity.admin;\r\n if (!account) return null;\r\n\r\n const accessToken = this.service.generateAccessToken(\n account,\n authEntity.role,\n !!authEntity.twoFactorEnabled\n );\n const newRefreshToken = this.service.generateRefreshToken(account);\n\r\n await this.repository.update(authEntity.id, { refreshToken: newRefreshToken });\r\n\r\n return { accessToken, refreshToken: newRefreshToken };\r\n } catch (error) {\n return null;\n }\n }\n}\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.findByUserOrAdminId(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> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token, userId } = dto;\n \n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const auth: AuthEntity | null = await this.authRepository.findByUserOrAdminId(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}\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 { NotFoundError, 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.findByUserOrAdminId(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> {\n const account = auth.user ?? auth.admin;\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\n account.lastLoginAt = new Date();\n account.isActive = true;\n await this.authRepository.saveAccount(account);\n }\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 const account = auth.user ?? auth.admin;\r\n if (!account) throw new NotFoundError(\"User or Admin account not found for AuthEntity\");\r\n\r\n return {\n accessToken: this.jwtService.generateAccessToken(account, auth.role, true),\n refreshToken: this.jwtService.generateRefreshToken(account)\n };\n }\n}\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> {\n if (this.isInitialized) return;\n \n await Promise.all([\n this.twoFactorService.initialize(),\n validateRepository(this.authRepository, repo => repo.getAll())\n ]);\n\n this.isInitialized = true;\n }\n\n async execute(userId: string, dto: ITwoFactorEnable): Promise<void> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n \n const { token } = dto;\n\n if (!token) {\n throw new TwoFactorError('Token is required');\n }\n if (!userId) {\n throw new TwoFactorError('User ID is required');\n }\n \r\n const user = await this.authRepository.findByUserOrAdminId(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}\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);\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);\n\n const adminLoginData = {\n accessToken: result.accessToken,\n userId: result.id,\n expiresAt: result.expiresAt,\n auth: this.createAuthData(\n true,\n result.enabled ?? false,\n (result.enabled ?? false) ? AUTH_STATUS.PENDING_VERIFICATION : AUTH_STATUS.BASIC_AUTH,\n false\n ),\n };\n\n this.sendResponse(res, HTTP_STATUS.CREATED, MESSAGES.ADMIN_LOGIN_SUCCESS, adminLoginData);\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> => {\n try {\n const userId = req.auth?.userId ?? req.body.id;\n await this.logoutUseCase.execute(userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n\n const result = await this.twoFactorSetupUseCase.execute(req.auth.userId);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = { ...req.body, userId: req.auth?.userId };\n await this.twoFactorEnableUseCase.execute(dto);\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> => {\n try {\n if (!req.auth?.userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorVerify = { ...req.body, userId: req.auth.userId };\n const result = await this.twoFactorVerifyUseCase.execute(dto);\n if (!result) {\n throw new Error(\"Two-factor verification failed\");\n }\n\r\n const verifyData = {\r\n token: result.token,\n refreshToken: result.refreshToken,\n user: {\n id: result.data?.id,\n email: result.data?.email,\n name: result.data?.name,\n role: result.data?.role,\n },\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> => {\n try {\n const userId = req.auth?.userId;\n if (!userId) {\n throw new ForbiddenError(\"User authentication required\");\n }\n const dto: ITwoFactorEnable = req.body;\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}\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);\n\n if (!decoded.userId) {\n return res.status(401).json({ message: 'Invalid token payload' });\n }\n\n if (!decoded.twoFactorAuthenticated) {\n return res.status(403).json({\n message: 'Two-factor authentication required',\n code: 'REQUIRE_2FA',\n userId: decoded.userId\n });\n }\n\n req.auth = { ...decoded, twoFactorAuthenticated: true };\n next();\n } catch (error) {\r\n return res.status(401).json({ message: 'Invalid or expired token' });\r\n }\r\n }\r\n}\n","import { BaseRepository, IExtendedBaseRepository } from \"cca-core\";\r\nimport { AdminEntity, AuthEntity, UserEntity } 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 result = await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect(\"auth.password\")\r\n .where(\"auth.email = :email\", { email })\r\n .getOne();\r\n\r\n return result;\r\n }\r\n\r\n async create(entity: Omit<AuthEntity, \"createdAt\">): Promise<AuthEntity> {\r\n const now = new Date();\r\n const auth = this.repository.create({\r\n ...entity,\r\n createdAt: now,\r\n updatedAt: now,\r\n isDeleted: false,\r\n } as unknown as AuthEntity);\r\n\r\n return this.repository.save(auth);\r\n }\r\n\r\n async findByUserOrAdminId(id: string): Promise<AuthEntity | null> {\r\n return await this.repository\r\n .createQueryBuilder(\"auth\")\r\n .leftJoinAndSelect(\"auth.user\", \"user\")\r\n .leftJoinAndSelect(\"auth.admin\", \"admin\")\r\n .addSelect([\"auth.twoFactorSecret\", \"auth.refreshToken\"])\r\n .where(\"user.id = :id\", { id })\r\n .orWhere(\"admin.id = :id\", { id })\r\n .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\", \"auth.refreshToken\"]);\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.findByUserOrAdminId(userId);\r\n\r\n if (!auth) {\r\n throw new NotFoundError(\"Auth not found\");\r\n }\r\n const account = auth.user ?? auth.admin;\r\n\r\n if (account) {\r\n auth.refreshToken = \"\";\r\n account.isActive = false;\r\n await this.saveAccount(account);\r\n }\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.findByUserOrAdminId(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 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 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.findByUserOrAdminId(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.findByUserOrAdminId(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 async saveAccount(account: UserEntity | AdminEntity): Promise<void> {\r\n await this.repository.manager.save(account);\r\n }\r\n}\r\n","import * as jwt from \"jsonwebtoken\";\r\nimport { Secret } from \"jsonwebtoken\";\nimport { IBaseService, validateRepository } from \"cca-core\";\nimport { AdminEntity, UserEntity, UserRole } from \"cca-entities\";\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 { JwtError, UnauthorizedError } from \"../../utils/Errors\";\n\r\nimport { AuthRepository } from \"../repository/AuthRepository\";\r\nexport class JwtAuthService implements IBaseService, IAuthService {\n private jwtConfig: IJwtConfig | undefined;\n\n constructor(private readonly repository: AuthRepository, config?: IJwtConfig) {\n if (config) {\n this.jwtConfig = {\n accessTokenSecret: config.accessTokenSecret,\n refreshTokenSecret: config.refreshTokenSecret,\n accessTokenExpiry: config.accessTokenExpiry,\n refreshTokenExpiry: config.refreshTokenExpiry,\n };\n }\n\n this.validateConfiguration();\n }\n\n async initialize(): Promise<void> {\n await validateRepository(this.repository, repo => repo.getAll());\n this.validateConfiguration();\n }\n\n private validateConfiguration(): void {\n if (!this.jwtConfig?.accessTokenSecret || !this.jwtConfig?.refreshTokenSecret) {\n throw new JwtError(\"JWT secrets required in config\");\n }\n if (this.jwtConfig.accessTokenExpiry == null || this.jwtConfig.refreshTokenExpiry == null) {\n throw new JwtError(\"JWT expirations required in config\");\n }\n }\n\r\n private verifyJwtConfig() {\r\n if (!this.jwtConfig) throw new JwtError(\"JWT config not loaded\");\r\n }\r\n\r\n generateAccessToken(\n user: UserEntity | AdminEntity,\n role: UserRole,\n twoFactorAuthenticated: boolean = false\n ): string {\n this.verifyJwtConfig();\n return jwt.sign(\n {\n userId: user.id,\n email: user.email,\n role: role,\n twoFactorAuthenticated,\n },\n this.jwtConfig!.accessTokenSecret as Secret,\n { expiresIn: this.jwtConfig!.accessTokenExpiry }\n );\n }\n\r\n generateRefreshToken(user: UserEntity | AdminEntity): 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> {\n try {\n return jwt.verify(token, secret) as IDecodedToken;\n } catch (error) {\n throw new UnauthorizedError();\n }\n }\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) {\n this.config = config;\n\n const parsedTokenWindow = Number.parseInt(config.tokenWindow, 10);\n const parsedSecretLength = Number.parseInt(config.secretLength, 10);\n\n this.twoFactorConfig = {\n tokenWindow: Number.isFinite(parsedTokenWindow) ? parsedTokenWindow : 1,\n secretLength: Number.isFinite(parsedSecretLength) ? parsedSecretLength : 20,\n qrCodeOptions: {\n errorCorrectionLevel: 'M',\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}\n"],"mappings":"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","names":["AuthEntity","validateRepository","validateRepository","validateRepository","bcrypt","AdminEntity","AuthEntity","UserEntity","UserRole","AuthEntity","AutoMap","AutoMap","mapper","AuthEntity","validateRepository","UserRole","AuthEntity","AdminEntity","UserEntity","validateRepository","validateRepository","validateRepository","validateRepository","validateRepository","AdminEntity","UserEntity","validateRepository","AdminEntity","UserEntity","validateRepository","validateRepository","validateRepository","validateRepository","AuthEntity"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cca-auth-module",
3
- "version": "0.2.2",
3
+ "version": "0.2.21",
4
4
  "description": "A TypeScript project using pnpm as the package manager.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,10 +8,6 @@
8
8
  "dist",
9
9
  "README.md"
10
10
  ],
11
- "scripts": {
12
- "build:tsup": "tsup src/index.ts --format cjs,esm --dts --metafile",
13
- "test": "vitest run"
14
- },
15
11
  "keywords": [],
16
12
  "author": "",
17
13
  "license": "ISC",
@@ -43,5 +39,9 @@
43
39
  "typeorm": "^0.3.26",
44
40
  "uuid": "^11.1.0",
45
41
  "yup": "^1.7.0"
42
+ },
43
+ "scripts": {
44
+ "build:tsup": "tsup src/index.ts --format cjs,esm --dts --metafile",
45
+ "test": "vitest run"
46
46
  }
47
- }
47
+ }