cca-auth-module 0.2.21 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/validators/authValidation.d.ts +3 -3
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +31 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -8
- package/dist/index.mjs.map +1 -1
- package/dist/infrastructure/repository/AuthRepository.d.ts +6 -1
- package/package.json +6 -6
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AuthEntity } from "cca-entities";
|
|
2
|
-
import { AuthRepository } from "../../infrastructure/repository/AuthRepository";
|
|
2
|
+
import { AuthRepository, FindByEmailOptions } from "../../infrastructure/repository/AuthRepository";
|
|
3
3
|
import { RegisterDTO } from "../dtos/RegisterDTO";
|
|
4
4
|
import { LoginDTO } from "../dtos/LoginDTO";
|
|
5
|
-
export declare const validateEmail: (email: string, repository: AuthRepository) => Promise<AuthEntity>;
|
|
5
|
+
export declare const validateEmail: (email: string, repository: AuthRepository, findOptions?: FindByEmailOptions) => Promise<AuthEntity>;
|
|
6
6
|
export declare const validatePassword: (password?: string) => Promise<void>;
|
|
7
7
|
export declare const validateEmailUniqueness: (repository: AuthRepository, email: string, excludeUserId?: string) => Promise<void>;
|
|
8
8
|
export declare const validateRegisterDTO: (auth: RegisterDTO, repository: AuthRepository) => Promise<void>;
|
|
9
|
-
export declare const validateLoginDTO: (data: LoginDTO, repository: AuthRepository) => Promise<AuthEntity>;
|
|
9
|
+
export declare const validateLoginDTO: (data: LoginDTO, repository: AuthRepository, isAdmin: boolean) => Promise<AuthEntity>;
|
|
10
10
|
export declare const validateAdminSecret: (secretPassword?: string) => Promise<void>;
|
package/dist/index.d.mts
CHANGED
|
@@ -20,9 +20,14 @@ type ConfigSource = () => Promise<IConfig>;
|
|
|
20
20
|
|
|
21
21
|
declare const authConfig: (configSource: ConfigSource) => void;
|
|
22
22
|
|
|
23
|
+
interface FindByEmailOptions {
|
|
24
|
+
includeUser?: boolean;
|
|
25
|
+
includeAdmin?: boolean;
|
|
26
|
+
includePassword?: boolean;
|
|
27
|
+
}
|
|
23
28
|
declare class AuthRepository extends BaseRepository<AuthEntity> implements IExtendedBaseRepository<AuthEntity> {
|
|
24
29
|
constructor(repository: Repository<AuthEntity>);
|
|
25
|
-
findByEmail(email: string): Promise<AuthEntity | null>;
|
|
30
|
+
findByEmail(email: string, options?: FindByEmailOptions): Promise<AuthEntity | null>;
|
|
26
31
|
create(entity: Omit<AuthEntity, "createdAt">): Promise<AuthEntity>;
|
|
27
32
|
findByUserOrAdminId(id: string): Promise<AuthEntity | null>;
|
|
28
33
|
findByUseAdminId(userId: string, isAdmin?: boolean): Promise<AuthEntity | null>;
|
package/dist/index.d.ts
CHANGED
|
@@ -20,9 +20,14 @@ type ConfigSource = () => Promise<IConfig>;
|
|
|
20
20
|
|
|
21
21
|
declare const authConfig: (configSource: ConfigSource) => void;
|
|
22
22
|
|
|
23
|
+
interface FindByEmailOptions {
|
|
24
|
+
includeUser?: boolean;
|
|
25
|
+
includeAdmin?: boolean;
|
|
26
|
+
includePassword?: boolean;
|
|
27
|
+
}
|
|
23
28
|
declare class AuthRepository extends BaseRepository<AuthEntity> implements IExtendedBaseRepository<AuthEntity> {
|
|
24
29
|
constructor(repository: Repository<AuthEntity>);
|
|
25
|
-
findByEmail(email: string): Promise<AuthEntity | null>;
|
|
30
|
+
findByEmail(email: string, options?: FindByEmailOptions): Promise<AuthEntity | null>;
|
|
26
31
|
create(entity: Omit<AuthEntity, "createdAt">): Promise<AuthEntity>;
|
|
27
32
|
findByUserOrAdminId(id: string): Promise<AuthEntity | null>;
|
|
28
33
|
findByUseAdminId(userId: string, isAdmin?: boolean): Promise<AuthEntity | null>;
|
package/dist/index.js
CHANGED
|
@@ -185,11 +185,11 @@ var schemas = {
|
|
|
185
185
|
),
|
|
186
186
|
role: yup.string().oneOf(Object.values(import_cca_entities.UserRole), "Invalid role specified")
|
|
187
187
|
};
|
|
188
|
-
var validateEmail = /* @__PURE__ */ __name(async (email, repository) => {
|
|
188
|
+
var validateEmail = /* @__PURE__ */ __name(async (email, repository, findOptions) => {
|
|
189
189
|
try {
|
|
190
190
|
const normalizedEmail = email?.trim().toLowerCase();
|
|
191
191
|
await schemas.email.validate(normalizedEmail);
|
|
192
|
-
const user = await repository.findByEmail(normalizedEmail);
|
|
192
|
+
const user = await repository.findByEmail(normalizedEmail, findOptions);
|
|
193
193
|
if (!user) {
|
|
194
194
|
throw new NotFoundError(
|
|
195
195
|
"The email address or password is incorrect. Please retry"
|
|
@@ -213,7 +213,11 @@ var validateEmailUniqueness = /* @__PURE__ */ __name(async (repository, email, e
|
|
|
213
213
|
try {
|
|
214
214
|
const normalizedEmail = email?.trim().toLowerCase();
|
|
215
215
|
await schemas.email.validate(normalizedEmail);
|
|
216
|
-
const existingUser = await repository.findByEmail(normalizedEmail
|
|
216
|
+
const existingUser = await repository.findByEmail(normalizedEmail, {
|
|
217
|
+
includeUser: false,
|
|
218
|
+
includeAdmin: false,
|
|
219
|
+
includePassword: false
|
|
220
|
+
});
|
|
217
221
|
if (!existingUser) return;
|
|
218
222
|
if (existingUser.id === excludeUserId) return;
|
|
219
223
|
throw new ValidationError(`Email ${email} is already in use.`);
|
|
@@ -233,13 +237,17 @@ var validateRegisterDTO = /* @__PURE__ */ __name(async (auth, repository) => {
|
|
|
233
237
|
validatePassword(password)
|
|
234
238
|
]);
|
|
235
239
|
}, "validateRegisterDTO");
|
|
236
|
-
var validateLoginDTO = /* @__PURE__ */ __name(async (data, repository) => {
|
|
240
|
+
var validateLoginDTO = /* @__PURE__ */ __name(async (data, repository, isAdmin) => {
|
|
237
241
|
const { email, role, password } = data;
|
|
238
242
|
if (role) {
|
|
239
243
|
await schemas.role.validate(role);
|
|
240
244
|
}
|
|
241
245
|
await schemas.password.validate(password);
|
|
242
|
-
const auth = await validateEmail(email, repository
|
|
246
|
+
const auth = await validateEmail(email, repository, {
|
|
247
|
+
includeUser: !isAdmin,
|
|
248
|
+
includeAdmin: isAdmin,
|
|
249
|
+
includePassword: true
|
|
250
|
+
});
|
|
243
251
|
if (!auth || !auth.password) {
|
|
244
252
|
throw new NotFoundError("Invalid credentials");
|
|
245
253
|
}
|
|
@@ -290,7 +298,7 @@ var _LoginUseCase = class _LoginUseCase {
|
|
|
290
298
|
if (isAdmin) {
|
|
291
299
|
await validateAdminSecret(providedAdminPassword);
|
|
292
300
|
}
|
|
293
|
-
const auth = await validateLoginDTO(loginDTO, this.repository);
|
|
301
|
+
const auth = await validateLoginDTO(loginDTO, this.repository, isAdmin);
|
|
294
302
|
const account = isAdmin ? auth.admin : auth.user;
|
|
295
303
|
if (!account) {
|
|
296
304
|
throw new NotFoundError(`${isAdmin ? "Admin" : "User"} account not found or inactive`);
|
|
@@ -1048,8 +1056,23 @@ var _AuthRepository = class _AuthRepository extends import_cca_core8.BaseReposit
|
|
|
1048
1056
|
constructor(repository) {
|
|
1049
1057
|
super(repository);
|
|
1050
1058
|
}
|
|
1051
|
-
async findByEmail(email) {
|
|
1052
|
-
const
|
|
1059
|
+
async findByEmail(email, options = {}) {
|
|
1060
|
+
const {
|
|
1061
|
+
includeUser = true,
|
|
1062
|
+
includeAdmin = true,
|
|
1063
|
+
includePassword = true
|
|
1064
|
+
} = options;
|
|
1065
|
+
const query = this.repository.createQueryBuilder("auth");
|
|
1066
|
+
if (includeUser) {
|
|
1067
|
+
query.leftJoinAndSelect("auth.user", "user");
|
|
1068
|
+
}
|
|
1069
|
+
if (includeAdmin) {
|
|
1070
|
+
query.leftJoinAndSelect("auth.admin", "admin");
|
|
1071
|
+
}
|
|
1072
|
+
if (includePassword) {
|
|
1073
|
+
query.addSelect("auth.password");
|
|
1074
|
+
}
|
|
1075
|
+
const result = await query.where("auth.email = :email", { email }).getOne();
|
|
1053
1076
|
return result;
|
|
1054
1077
|
}
|
|
1055
1078
|
async create(entity) {
|
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\";\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"]}
|
|
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, isAdmin);\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 {\n AuthRepository,\n FindByEmailOptions,\n} 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 findOptions?: FindByEmailOptions\n): Promise<AuthEntity> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n const user = await repository.findByEmail(normalizedEmail, findOptions);\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 includeUser: false,\n includeAdmin: false,\n includePassword: false,\n });\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 (\n data: LoginDTO,\n repository: AuthRepository,\n isAdmin: boolean\n): Promise<AuthEntity> => {\n const { email, role, password } = data;\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, {\n includeUser: !isAdmin,\n includeAdmin: isAdmin,\n includePassword: true,\n });\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\";\nimport { NotFoundError } from \"../../utils/Errors\";\n\nexport interface FindByEmailOptions {\n includeUser?: boolean;\n includeAdmin?: boolean;\n includePassword?: boolean;\n}\n\nexport class AuthRepository\n extends BaseRepository<AuthEntity>\n implements IExtendedBaseRepository<AuthEntity> {\n constructor(repository: Repository<AuthEntity>) {\r\n super(repository);\r\n }\r\n\r\n async findByEmail(\n email: string,\n options: FindByEmailOptions = {}\n ): Promise<AuthEntity | null> {\n const {\n includeUser = true,\n includeAdmin = true,\n includePassword = true,\n } = options;\n\n const query = this.repository.createQueryBuilder(\"auth\");\n\n if (includeUser) {\n query.leftJoinAndSelect(\"auth.user\", \"user\");\n }\n\n if (includeAdmin) {\n query.leftJoinAndSelect(\"auth.admin\", \"admin\");\n }\n\n if (includePassword) {\n query.addSelect(\"auth.password\");\n }\n\n const result = await query.where(\"auth.email = :email\", { email }).getOne();\n\n return result;\n }\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
|
@@ -150,11 +150,11 @@ var schemas = {
|
|
|
150
150
|
),
|
|
151
151
|
role: yup.string().oneOf(Object.values(UserRole), "Invalid role specified")
|
|
152
152
|
};
|
|
153
|
-
var validateEmail = /* @__PURE__ */ __name(async (email, repository) => {
|
|
153
|
+
var validateEmail = /* @__PURE__ */ __name(async (email, repository, findOptions) => {
|
|
154
154
|
try {
|
|
155
155
|
const normalizedEmail = email?.trim().toLowerCase();
|
|
156
156
|
await schemas.email.validate(normalizedEmail);
|
|
157
|
-
const user = await repository.findByEmail(normalizedEmail);
|
|
157
|
+
const user = await repository.findByEmail(normalizedEmail, findOptions);
|
|
158
158
|
if (!user) {
|
|
159
159
|
throw new NotFoundError(
|
|
160
160
|
"The email address or password is incorrect. Please retry"
|
|
@@ -178,7 +178,11 @@ var validateEmailUniqueness = /* @__PURE__ */ __name(async (repository, email, e
|
|
|
178
178
|
try {
|
|
179
179
|
const normalizedEmail = email?.trim().toLowerCase();
|
|
180
180
|
await schemas.email.validate(normalizedEmail);
|
|
181
|
-
const existingUser = await repository.findByEmail(normalizedEmail
|
|
181
|
+
const existingUser = await repository.findByEmail(normalizedEmail, {
|
|
182
|
+
includeUser: false,
|
|
183
|
+
includeAdmin: false,
|
|
184
|
+
includePassword: false
|
|
185
|
+
});
|
|
182
186
|
if (!existingUser) return;
|
|
183
187
|
if (existingUser.id === excludeUserId) return;
|
|
184
188
|
throw new ValidationError(`Email ${email} is already in use.`);
|
|
@@ -198,13 +202,17 @@ var validateRegisterDTO = /* @__PURE__ */ __name(async (auth, repository) => {
|
|
|
198
202
|
validatePassword(password)
|
|
199
203
|
]);
|
|
200
204
|
}, "validateRegisterDTO");
|
|
201
|
-
var validateLoginDTO = /* @__PURE__ */ __name(async (data, repository) => {
|
|
205
|
+
var validateLoginDTO = /* @__PURE__ */ __name(async (data, repository, isAdmin) => {
|
|
202
206
|
const { email, role, password } = data;
|
|
203
207
|
if (role) {
|
|
204
208
|
await schemas.role.validate(role);
|
|
205
209
|
}
|
|
206
210
|
await schemas.password.validate(password);
|
|
207
|
-
const auth = await validateEmail(email, repository
|
|
211
|
+
const auth = await validateEmail(email, repository, {
|
|
212
|
+
includeUser: !isAdmin,
|
|
213
|
+
includeAdmin: isAdmin,
|
|
214
|
+
includePassword: true
|
|
215
|
+
});
|
|
208
216
|
if (!auth || !auth.password) {
|
|
209
217
|
throw new NotFoundError("Invalid credentials");
|
|
210
218
|
}
|
|
@@ -255,7 +263,7 @@ var _LoginUseCase = class _LoginUseCase {
|
|
|
255
263
|
if (isAdmin) {
|
|
256
264
|
await validateAdminSecret(providedAdminPassword);
|
|
257
265
|
}
|
|
258
|
-
const auth = await validateLoginDTO(loginDTO, this.repository);
|
|
266
|
+
const auth = await validateLoginDTO(loginDTO, this.repository, isAdmin);
|
|
259
267
|
const account = isAdmin ? auth.admin : auth.user;
|
|
260
268
|
if (!account) {
|
|
261
269
|
throw new NotFoundError(`${isAdmin ? "Admin" : "User"} account not found or inactive`);
|
|
@@ -1013,8 +1021,23 @@ var _AuthRepository = class _AuthRepository extends BaseRepository {
|
|
|
1013
1021
|
constructor(repository) {
|
|
1014
1022
|
super(repository);
|
|
1015
1023
|
}
|
|
1016
|
-
async findByEmail(email) {
|
|
1017
|
-
const
|
|
1024
|
+
async findByEmail(email, options = {}) {
|
|
1025
|
+
const {
|
|
1026
|
+
includeUser = true,
|
|
1027
|
+
includeAdmin = true,
|
|
1028
|
+
includePassword = true
|
|
1029
|
+
} = options;
|
|
1030
|
+
const query = this.repository.createQueryBuilder("auth");
|
|
1031
|
+
if (includeUser) {
|
|
1032
|
+
query.leftJoinAndSelect("auth.user", "user");
|
|
1033
|
+
}
|
|
1034
|
+
if (includeAdmin) {
|
|
1035
|
+
query.leftJoinAndSelect("auth.admin", "admin");
|
|
1036
|
+
}
|
|
1037
|
+
if (includePassword) {
|
|
1038
|
+
query.addSelect("auth.password");
|
|
1039
|
+
}
|
|
1040
|
+
const result = await query.where("auth.email = :email", { email }).getOne();
|
|
1018
1041
|
return result;
|
|
1019
1042
|
}
|
|
1020
1043
|
async create(entity) {
|
package/dist/index.mjs.map
CHANGED
|
@@ -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\";\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"]}
|
|
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, isAdmin);\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 {\n AuthRepository,\n FindByEmailOptions,\n} 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 findOptions?: FindByEmailOptions\n): Promise<AuthEntity> => {\n try {\n const normalizedEmail = email?.trim().toLowerCase();\n await schemas.email.validate(normalizedEmail);\n const user = await repository.findByEmail(normalizedEmail, findOptions);\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 includeUser: false,\n includeAdmin: false,\n includePassword: false,\n });\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 (\n data: LoginDTO,\n repository: AuthRepository,\n isAdmin: boolean\n): Promise<AuthEntity> => {\n const { email, role, password } = data;\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, {\n includeUser: !isAdmin,\n includeAdmin: isAdmin,\n includePassword: true,\n });\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\";\nimport { NotFoundError } from \"../../utils/Errors\";\n\nexport interface FindByEmailOptions {\n includeUser?: boolean;\n includeAdmin?: boolean;\n includePassword?: boolean;\n}\n\nexport class AuthRepository\n extends BaseRepository<AuthEntity>\n implements IExtendedBaseRepository<AuthEntity> {\n constructor(repository: Repository<AuthEntity>) {\r\n super(repository);\r\n }\r\n\r\n async findByEmail(\n email: string,\n options: FindByEmailOptions = {}\n ): Promise<AuthEntity | null> {\n const {\n includeUser = true,\n includeAdmin = true,\n includePassword = true,\n } = options;\n\n const query = this.repository.createQueryBuilder(\"auth\");\n\n if (includeUser) {\n query.leftJoinAndSelect(\"auth.user\", \"user\");\n }\n\n if (includeAdmin) {\n query.leftJoinAndSelect(\"auth.admin\", \"admin\");\n }\n\n if (includePassword) {\n query.addSelect(\"auth.password\");\n }\n\n const result = await query.where(\"auth.email = :email\", { email }).getOne();\n\n return result;\n }\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"]}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { BaseRepository, IExtendedBaseRepository } from "cca-core";
|
|
2
2
|
import { AdminEntity, AuthEntity, UserEntity } from "cca-entities";
|
|
3
3
|
import { Repository } from "typeorm";
|
|
4
|
+
export interface FindByEmailOptions {
|
|
5
|
+
includeUser?: boolean;
|
|
6
|
+
includeAdmin?: boolean;
|
|
7
|
+
includePassword?: boolean;
|
|
8
|
+
}
|
|
4
9
|
export declare class AuthRepository extends BaseRepository<AuthEntity> implements IExtendedBaseRepository<AuthEntity> {
|
|
5
10
|
constructor(repository: Repository<AuthEntity>);
|
|
6
|
-
findByEmail(email: string): Promise<AuthEntity | null>;
|
|
11
|
+
findByEmail(email: string, options?: FindByEmailOptions): Promise<AuthEntity | null>;
|
|
7
12
|
create(entity: Omit<AuthEntity, "createdAt">): Promise<AuthEntity>;
|
|
8
13
|
findByUserOrAdminId(id: string): Promise<AuthEntity | null>;
|
|
9
14
|
findByUseAdminId(userId: string, isAdmin?: boolean): Promise<AuthEntity | null>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cca-auth-module",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.22",
|
|
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,6 +8,10 @@
|
|
|
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
|
+
},
|
|
11
15
|
"keywords": [],
|
|
12
16
|
"author": "",
|
|
13
17
|
"license": "ISC",
|
|
@@ -39,9 +43,5 @@
|
|
|
39
43
|
"typeorm": "^0.3.26",
|
|
40
44
|
"uuid": "^11.1.0",
|
|
41
45
|
"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
|
+
}
|