Tidied up the packages and unused modules

This commit is contained in:
SepehrYahyaee
2026-05-25 14:59:37 +03:30
parent 680f3c1798
commit 48cc4d8a8d
13 changed files with 409 additions and 8398 deletions

8319
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,50 +20,31 @@
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@arashioz/errjson-talieh": "^2.2.5",
"@fraybabak/kavenegar_nest": "^1.0.5",
"@nestjs-modules/mailer": "^1.8.1",
"@nestjs/axios": "^3.1.3",
"@nestjs/common": "^10.4.15",
"@nestjs/config": "^4.0.4",
"@nestjs/core": "^10.4.15",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "*",
"@nestjs/mongoose": "^10.1.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.4.15",
"@nestjs/platform-fastify": "^10.4.15",
"@nestjs/platform-socket.io": "^10.4.15",
"@nestjs/schedule": "^4.1.2",
"@nestjs/serve-static": "^4.0.2",
"@nestjs/swagger": "^7.4.2",
"@nestjs/websockets": "^10.4.15",
"@types/uuid": "^10.0.0",
"axios": "^1.9.0",
"bcrypt": "^5.1.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"crypto": "^1.0.1",
"dotenv": "^16.4.7",
"express": "^4.22.1",
"express-basic-auth": "^1.2.1",
"fastest-levenshtein": "^1.0.16",
"form-data": "^4.0.2",
"jalali-moment": "^3.3.11",
"kavenegar": "^1.1.4",
"mongoose": "^8.9.2",
"nestjs-command": "^3.1.4",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"short-unique-id": "^5.2.0",
"standard": "^17.1.2",
"standardjs": "^1.0.0-alpha",
"svg-captcha": "^1.4.0",
"uuid": "^11.0.3",
"yargs": "^17.7.2"
"uuid": "^11.0.3"
},
"devDependencies": {
"@nestjs/cli": "^11.0.14",
@@ -73,9 +54,6 @@
"@types/jest": "^29.5.14",
"@types/multer": "^1.4.12",
"@types/node": "^22.10.2",
"@types/passport-jwt": "^4.0.1",
"@types/supertest": "^6.0.2",
"@types/yargs": "^17.0.33",
"@typescript-eslint/eslint-plugin": "^8.18.1",
"@typescript-eslint/parser": "^8.18.1",
"eslint": "^9.17.0",
@@ -83,12 +61,8 @@
"eslint-plugin-prettier": "^5.2.1",
"jest": "^29.7.0",
"prettier": "^3.4.2",
"source-map-support": "^0.5.21",
"supertest": "^7.0.0",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"ts-standard": "^12.0.2",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.7.2"
},

View File

@@ -6,7 +6,6 @@ import { MongooseModule } from "@nestjs/mongoose";
import { ScheduleModule } from "@nestjs/schedule";
import { ServeStaticModule } from "@nestjs/serve-static";
import * as dotenv from "dotenv";
import { CommandModule } from "nestjs-command";
import { AiModule } from "./ai/ai.module";
import { AuthModule } from "./auth/auth.module";
import { ClaimRequestManagementModule } from "./claim-request-management/claim-request-management.module";
@@ -31,7 +30,6 @@ dotenv.config({ path: `.${process.env.NODE_ENV}.env` });
@Module({
imports: [
CommandModule,
ScheduleModule.forRoot(),
CronModule,
ServeStaticModule.forRoot({

View File

@@ -28,7 +28,6 @@ import { ExpertDbService } from "src/users/entities/db-service/expert.db.service
import { FieldExpertDbService } from "src/users/entities/db-service/field-expert.db.service";
import { RegistrarDbService } from "src/users/entities/db-service/registrar.db.service";
import { HashService } from "src/utils/hash/hash.service";
// import { MailService } from "src/utils/mail/mail.service";
import { OtpGeneratorService } from "src/sms-orchestration/otp-generator.service";
function pick(obj: Record<string, any>, keys: string[]) {
@@ -50,7 +49,6 @@ export class ActorAuthService {
private readonly fieldExpertDbService: FieldExpertDbService,
private readonly registrarDbService: RegistrarDbService,
private readonly insurerExpertDbService: InsurerExpertDbService,
// private readonly mailService: MailService, // Mailer disabled not used
private readonly clientDbService: ClientDbService,
private readonly otpService: OtpGeneratorService,
private readonly captchaChallengeService: CaptchaChallengeService,

View File

@@ -1,9 +1,8 @@
import { Module } from "@nestjs/common";
import { Global, Module } from "@nestjs/common";
import { JwtModule, JwtService } from "@nestjs/jwt";
import { MongooseModule } from "@nestjs/mongoose";
import { PassportModule } from "@nestjs/passport";
import { LocalStrategy } from "src/auth/stratregys/local.strategy";
import { LocalActorStrategy } from "src/auth/stratregys/local-actor.strategy";
import { LocalActorAuthGuard } from "src/auth/guards/actor-local.guard";
import { LocalUserAuthGuard } from "src/auth/guards/user-local.guard";
import { ActorAuthController } from "src/auth/auth-controllers/actor/actor.auth.controller";
import { UserAuthController } from "src/auth/auth-controllers/user/user.auth.controller";
import { ActorAuthService } from "src/auth/auth-services/actor.auth.service";
@@ -28,18 +27,17 @@ import {
} from "src/request-management/entities/schema/request-management.schema";
import { UsersModule } from "src/users/users.module";
import { HashModule } from "src/utils/hash/hash.module";
// import { MailModule } from "src/utils/mail/mail.module";
import { SmsOrchestrationModule } from "src/sms-orchestration/sms-orchestration.module";
import { CaptchaModule } from "src/captcha/captcha.module";
/** Auth services and guards are app-wide (avoids importing AuthModule in every feature module). */
@Global()
@Module({
imports: [
// MailModule, // Mailer disabled not used
UsersModule,
ClientModule,
HashModule,
CaptchaModule,
PassportModule,
SmsOrchestrationModule,
MongooseModule.forFeature([
{ name: RequestManagementModel.name, schema: RequestManagementSchema },
@@ -60,11 +58,17 @@ import { CaptchaModule } from "src/captcha/captcha.module";
UserAuthService,
UserLinkAccessService,
ActorAuthService,
LocalStrategy,
LocalActorStrategy,
JwtService,
LocalActorAuthGuard,
LocalUserAuthGuard,
],
exports: [
UserAuthService,
ActorAuthService,
JwtService,
LocalActorAuthGuard,
LocalUserAuthGuard,
],
exports: [LocalStrategy, UserAuthService, ActorAuthService, JwtService],
controllers: [UserAuthController, ActorAuthController],
})
export class AuthModule {}

View File

@@ -1,26 +1,23 @@
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import { AuthGuard } from "@nestjs/passport";
import { ActorAuthService } from "src/auth/auth-services/actor.auth.service";
import { RoleEnum } from "src/Types&Enums/role.enum";
@Injectable()
export class LocalActorAuthGuard extends AuthGuard("actor") {
export class LocalActorAuthGuard implements CanActivate {
constructor(
private readonly actorAuthService: ActorAuthService,
private readonly jwtService: JwtService,
) {
super();
}
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractTokenFromHeader(request);
const path = request.url;
if (!token) {
if (this.isActorLoginRequest(request)) {
@@ -30,9 +27,8 @@ export class LocalActorAuthGuard extends AuthGuard("actor") {
request.user = loginData;
request.identity = loginData;
return true;
} else {
throw new UnauthorizedException("Token not found");
}
throw new UnauthorizedException("Token not found");
}
try {
@@ -72,9 +68,10 @@ export class LocalActorAuthGuard extends AuthGuard("actor") {
return path === "/actor/login" || path.endsWith("/actor/login");
}
private extractTokenFromHeader(request: Request): string | undefined {
//@ts-ignore
const [type, token] = request.headers.authorization?.split(" ") ?? [];
private extractTokenFromHeader(request: {
headers?: { authorization?: string };
}): string | undefined {
const [type, token] = request.headers?.authorization?.split(" ") ?? [];
return type === "Bearer" ? token : undefined;
}
}

View File

@@ -1,5 +1,8 @@
import { ExecutionContext, Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import {
CanActivate,
ExecutionContext,
Injectable,
} from "@nestjs/common";
import {
UserAuthErrorCode,
throwUserAuthError,
@@ -7,13 +10,12 @@ import {
import { UserAuthService } from "src/auth/auth-services/user.auth.service";
@Injectable()
export class LocalUserAuthGuard extends AuthGuard("local") {
constructor(private readonly userAuthService: UserAuthService) {
super();
}
export class LocalUserAuthGuard implements CanActivate {
constructor(private readonly userAuthService: UserAuthService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const { username, password, linkToken, linkContext } = request.body;
const { username, password, linkToken, linkContext } = request.body ?? {};
const isValidUser = await this.userAuthService.validateUser(
username,
password,
@@ -22,7 +24,7 @@ export class LocalUserAuthGuard extends AuthGuard("local") {
if (!isValidUser) {
throwUserAuthError(UserAuthErrorCode.OTP_INVALID);
}
request["user"] = isValidUser;
request.user = isValidUser;
return true;
}
}

View File

@@ -1,22 +0,0 @@
import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { Strategy } from "passport-local";
import { ActorAuthService } from "src/auth/auth-services/actor.auth.service";
@Injectable()
export class LocalActorStrategy extends PassportStrategy(Strategy, "actor") {
constructor(private readonly actorAuthService: ActorAuthService) {
super();
}
// async validate(username, password): Promise<any> {
// const user = await this.actorAuthService.validateActor(
// username,
// password,
// );
// if (!user) {
// throw new UnauthorizedException("user not found");
// }
// return user;
// }
}

View File

@@ -1,23 +0,0 @@
import { Injectable } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { Strategy } from "passport-local";
import {
UserAuthErrorCode,
throwUserAuthError,
} from "src/auth/auth-services/user-auth-error";
import { UserAuthService } from "src/auth/auth-services/user.auth.service";
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(private readonly userAuthService: UserAuthService) {
super();
}
async validate(username: string, password: string): Promise<any> {
const user = await this.userAuthService.validateUser(username, password);
if (!user) {
throwUserAuthError(UserAuthErrorCode.OTP_INVALID);
}
return user;
}
}

View File

@@ -113,33 +113,33 @@ export class ExpertInitiatedController {
);
}
@ApiOperation({ deprecated: true })
@Post("create")
@ApiOperation({
summary: "Create expert-initiated blame file",
description:
"Expert creates an initial incomplete blame file. Can be IN_PERSON (expert fills all info) or LINK (expert sends link to users).",
})
@ApiBody({ type: CreateExpertInitiatedFileDto })
@ApiResponse({
status: 201,
description: "File created successfully",
schema: {
type: "object",
properties: {
requestId: { type: "string" },
},
},
})
async createExpertInitiatedFile(
@CurrentUser() expert: any,
@Body() dto: CreateExpertInitiatedFileDto,
) {
return await this.requestManagementService.createExpertInitiatedFile(
expert,
dto,
);
}
// @ApiOperation({ deprecated: true })
// @Post("create")
// @ApiOperation({
// summary: "Create expert-initiated blame file",
// description:
// "Expert creates an initial incomplete blame file. Can be IN_PERSON (expert fills all info) or LINK (expert sends link to users).",
// })
// @ApiBody({ type: CreateExpertInitiatedFileDto })
// @ApiResponse({
// status: 201,
// description: "File created successfully",
// schema: {
// type: "object",
// properties: {
// requestId: { type: "string" },
// },
// },
// })
// async createExpertInitiatedFile(
// @CurrentUser() expert: any,
// @Body() dto: CreateExpertInitiatedFileDto,
// ) {
// return await this.requestManagementService.createExpertInitiatedFile(
// expert,
// dto,
// );
// }
@ApiOperation({ deprecated: true })
@Post("complete-form-third-party/:requestId")

View File

@@ -12,7 +12,6 @@ import {
} from "@nestjs/common";
import { ExternalExceptionFilter } from "@nestjs/core/exceptions/external-exception-filter";
import { Types } from "mongoose";
import ShortUniqueId from "short-unique-id";
import { ClientService } from "src/client/client.service";
import { AddPlateDto } from "src/profile/dto/user/AddPlateDto";
import {
@@ -1588,28 +1587,28 @@ export class RequestManagementService {
}
}
async createRequest(user, type) {
const reqNumber = new ShortUniqueId({ counter: 1 });
const publicId = await this.publicIdService.generateRequestPublicId();
const createRequest = await this.requestManagementDbService.create({
firstPartyDetails: {
firstPartyId: user.sub,
firstPartyPhoneNumber: user.username,
firstPartyCertificate: null,
},
currentStep: StepsEnum.createRequest,
nextStep:
type === "THIRD_PARTY"
? StepsEnum.F_InitialForm
: StepsEnum.CarBodyForm,
requestNumber: reqNumber.rnd(),
publicId,
blameStatus: ReqBlameStatus.PendingForFirstParty,
lockFile: false,
type,
});
return { requestId: createRequest["_id"] };
}
// async createRequest(user, type) {
// const reqNumber = new ShortUniqueId({ counter: 1 });
// const publicId = await this.publicIdService.generateRequestPublicId();
// const createRequest = await this.requestManagementDbService.create({
// firstPartyDetails: {
// firstPartyId: user.sub,
// firstPartyPhoneNumber: user.username,
// firstPartyCertificate: null,
// },
// currentStep: StepsEnum.createRequest,
// nextStep:
// type === "THIRD_PARTY"
// ? StepsEnum.F_InitialForm
// : StepsEnum.CarBodyForm,
// requestNumber: reqNumber.rnd(),
// publicId,
// blameStatus: ReqBlameStatus.PendingForFirstParty,
// lockFile: false,
// type,
// });
// return { requestId: createRequest["_id"] };
// }
async initialFormStep(
reqBody: InitialFormDto,
@@ -3617,106 +3616,106 @@ export class RequestManagementService {
/**
* Expert creates an initial blame file (incomplete, waiting for completion)
*/
async createExpertInitiatedFile(
expert: any,
dto: CreateExpertInitiatedFileDto,
): Promise<{ requestId: string }> {
const reqNumber = new ShortUniqueId({ counter: 1 });
const expertId = new Types.ObjectId(expert.sub);
const publicId = await this.publicIdService.generateRequestPublicId();
// async createExpertInitiatedFile(
// expert: any,
// dto: CreateExpertInitiatedFileDto,
// ): Promise<{ requestId: string }> {
// const reqNumber = new ShortUniqueId({ counter: 1 });
// const expertId = new Types.ObjectId(expert.sub);
// const publicId = await this.publicIdService.generateRequestPublicId();
// For LINK method, validate phone numbers are provided
if (dto.creationMethod === CreationMethod.LINK) {
if (!dto.firstPartyPhoneNumber) {
throw new BadRequestException(
"First party phone number is required for LINK method",
);
}
if (dto.type === "THIRD_PARTY" && !dto.secondPartyPhoneNumber) {
throw new BadRequestException(
"Second party phone number is required for LINK method with THIRD_PARTY type",
);
}
if (
dto.type === "THIRD_PARTY" &&
dto.firstPartyPhoneNumber === dto.secondPartyPhoneNumber
) {
throw new BadRequestException(
"First and second party phone numbers must be different",
);
}
}
// // For LINK method, validate phone numbers are provided
// if (dto.creationMethod === CreationMethod.LINK) {
// if (!dto.firstPartyPhoneNumber) {
// throw new BadRequestException(
// "First party phone number is required for LINK method",
// );
// }
// if (dto.type === "THIRD_PARTY" && !dto.secondPartyPhoneNumber) {
// throw new BadRequestException(
// "Second party phone number is required for LINK method with THIRD_PARTY type",
// );
// }
// if (
// dto.type === "THIRD_PARTY" &&
// dto.firstPartyPhoneNumber === dto.secondPartyPhoneNumber
// ) {
// throw new BadRequestException(
// "First and second party phone numbers must be different",
// );
// }
// }
// For LINK method, create/get users and set their IDs
let firstPartyUserId: Types.ObjectId | undefined;
let secondPartyUserId: Types.ObjectId | undefined;
let firstPartyDetails: any = {};
let secondPartyDetails: any = {};
// // For LINK method, create/get users and set their IDs
// let firstPartyUserId: Types.ObjectId | undefined;
// let secondPartyUserId: Types.ObjectId | undefined;
// let firstPartyDetails: any = {};
// let secondPartyDetails: any = {};
if (dto.creationMethod === CreationMethod.LINK) {
// Get or create first party user
firstPartyUserId = await this.getOrCreateUserByPhoneNumber(
dto.firstPartyPhoneNumber,
);
firstPartyDetails = {
firstPartyId: firstPartyUserId,
firstPartyPhoneNumber: dto.firstPartyPhoneNumber,
};
// if (dto.creationMethod === CreationMethod.LINK) {
// // Get or create first party user
// firstPartyUserId = await this.getOrCreateUserByPhoneNumber(
// dto.firstPartyPhoneNumber,
// );
// firstPartyDetails = {
// firstPartyId: firstPartyUserId,
// firstPartyPhoneNumber: dto.firstPartyPhoneNumber,
// };
// Get or create second party user for THIRD_PARTY
if (dto.type === "THIRD_PARTY" && dto.secondPartyPhoneNumber) {
secondPartyUserId = await this.getOrCreateUserByPhoneNumber(
dto.secondPartyPhoneNumber,
);
secondPartyDetails = {
secondPartyId: secondPartyUserId,
secondPartyPhoneNumber: dto.secondPartyPhoneNumber,
};
}
}
// // Get or create second party user for THIRD_PARTY
// if (dto.type === "THIRD_PARTY" && dto.secondPartyPhoneNumber) {
// secondPartyUserId = await this.getOrCreateUserByPhoneNumber(
// dto.secondPartyPhoneNumber,
// );
// secondPartyDetails = {
// secondPartyId: secondPartyUserId,
// secondPartyPhoneNumber: dto.secondPartyPhoneNumber,
// };
// }
// }
const createRequest = await this.requestManagementDbService.create({
requestNumber: reqNumber.rnd(),
publicId,
type: dto.type,
expertInitiated: true,
initiatedBy: expertId,
creationMethod: dto.creationMethod,
filledBy: dto.creationMethod === CreationMethod.IN_PERSON ? FilledBy.EXPERT : FilledBy.CUSTOMER,
currentStep: StepsEnum.createRequest,
nextStep:
dto.type === "THIRD_PARTY"
? StepsEnum.F_InitialForm
: StepsEnum.CarBodyForm,
blameStatus: ReqBlameStatus.PendingForFirstParty,
lockFile: false,
history: [],
assignedExpertId: expertId, // Auto-assign to initiating expert
...(dto.creationMethod === CreationMethod.LINK && {
firstPartyDetails,
...(dto.type === "THIRD_PARTY" && { secondPartyDetails }),
}),
});
// const createRequest = await this.requestManagementDbService.create({
// requestNumber: reqNumber.rnd(),
// publicId,
// type: dto.type,
// expertInitiated: true,
// initiatedBy: expertId,
// creationMethod: dto.creationMethod,
// filledBy: dto.creationMethod === CreationMethod.IN_PERSON ? FilledBy.EXPERT : FilledBy.CUSTOMER,
// currentStep: StepsEnum.createRequest,
// nextStep:
// dto.type === "THIRD_PARTY"
// ? StepsEnum.F_InitialForm
// : StepsEnum.CarBodyForm,
// blameStatus: ReqBlameStatus.PendingForFirstParty,
// lockFile: false,
// history: [],
// assignedExpertId: expertId, // Auto-assign to initiating expert
// ...(dto.creationMethod === CreationMethod.LINK && {
// firstPartyDetails,
// ...(dto.type === "THIRD_PARTY" && { secondPartyDetails }),
// }),
// });
const requestId = (createRequest as any)._id.toString();
// const requestId = (createRequest as any)._id.toString();
// Add history event
await this.addHistoryEvent(
requestId,
"FILE_CREATED_BY_EXPERT",
expertId,
`${expert.firstName} ${expert.lastName}`,
"expert",
{
creationMethod: dto.creationMethod,
type: dto.type,
},
);
// // Add history event
// await this.addHistoryEvent(
// requestId,
// "FILE_CREATED_BY_EXPERT",
// expertId,
// `${expert.firstName} ${expert.lastName}`,
// "expert",
// {
// creationMethod: dto.creationMethod,
// type: dto.type,
// },
// );
return {
requestId,
};
}
// return {
// requestId,
// };
// }
/**
* V2: Field expert creates an expert-initiated blame file (BlameRequest with workflow).

View File

@@ -1,26 +0,0 @@
import { Module } from "@nestjs/common";
import { MailerModule } from "@nestjs-modules/mailer";
import { MailService } from "./mail.service";
@Module({
providers: [MailService],
exports: [MailService],
imports: [
MailerModule.forRoot({
transport: {
service: "gmail",
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
user: "balali.arash@gmail.com",
pass: "macujakosnsqbgdm",
},
},
defaults: {
from: "KSG <modules@nestjs.com>",
},
}),
],
})
export class MailModule {}

View File

@@ -1,41 +0,0 @@
import { Injectable } from "@nestjs/common";
import { MailerService } from "@nestjs-modules/mailer";
@Injectable()
export class MailService {
constructor(private readonly mailerService: MailerService) {}
async sendMail(email, otp: string): Promise<any> {
let status: object;
await this.mailerService
.sendMail({
to: email,
from: "noreply@yara724.com",
subject: "YARA724 Company",
text: "welcome",
html: `
<h1 style="text-align:center">yara724 verificateion </h1>
<h3 style="background:#FFA500;width:150px; margin:0 auto; padding:10px; font-size:25px; border-radius:15px; text-align:center;">
<div style="color:white">
${otp}
</div>
</h3>
`,
})
.then((success) => {
if (success) {
status = {
message: "email was sent successfully",
code: 200,
emailSent: true,
};
}
})
.catch((err) => {
if (err) {
status = { message: "please try again", code: 500, emailSent: false };
}
});
return status;
}
}