Fixed resendCarParts label_fa's + OTP

This commit is contained in:
SepehrYahyaee
2026-05-25 14:13:17 +03:30
parent 64fa560f73
commit 680f3c1798
10 changed files with 435 additions and 84 deletions

View File

@@ -7,6 +7,15 @@ import {
} from "src/auth/auth-services/user-auth-error";
import { UserLinkAccessService } from "src/auth/auth-services/user-link-access.service";
import { LoginDtoRs } from "src/auth/dto/user/login.dto";
import {
buildUserLookupByPhone,
normalizeIranMobile,
} from "src/helpers/iran-mobile";
import {
computeOtpExpireMs,
isOtpExpiryActive,
readOtpExpireMinutesFromEnv,
} from "src/helpers/user-otp-expiry";
import { OtpGeneratorService } from "src/sms-orchestration/otp-generator.service";
import { UserDbService } from "src/users/entities/db-service/user.db.service";
import { SmsOrchestrationService } from "src/sms-orchestration/sms-orchestration.service";
@@ -17,7 +26,6 @@ export interface LinkBinding {
linkContext?: string;
}
// TODO FIX REGISTER TO USER.SERVICE AND AUTH IN THIS MODULE
@Injectable()
export class UserAuthService {
private readonly logger = new Logger(UserAuthService.name);
@@ -36,18 +44,21 @@ export class UserAuthService {
pass: string,
binding: LinkBinding = {},
): Promise<any> {
const canonicalMobile = normalizeIranMobile(username) ?? username.trim();
await this.userLinkAccessService.assertMobileAllowed({
mobile: username,
mobile: canonicalMobile,
linkToken: binding.linkToken,
linkContext: binding.linkContext,
});
const user = await this.userDbService.findOne({ username });
const user = await this.userDbService.findOne(
buildUserLookupByPhone(canonicalMobile),
);
if (!user) throwUserAuthError(UserAuthErrorCode.USER_NOT_FOUND);
const now = new Date().getTime();
if (user.otp == null) throwUserAuthError(UserAuthErrorCode.OTP_REQUIRED);
if (user.otpExpire < now) {
if (!isOtpExpiryActive(user.otpExpire)) {
throwUserAuthError(UserAuthErrorCode.OTP_EXPIRED);
}
if (await this.hashService.compare(pass, user.otp)) {
@@ -57,9 +68,10 @@ export class UserAuthService {
}
async login(user: any) {
const userId = String(user._id ?? user.id ?? "");
const payload = {
username: user.username,
sub: user.id,
sub: userId,
role: "user",
};
const accToken = this.jwtService.sign(payload, {
@@ -70,10 +82,11 @@ export class UserAuthService {
{
tokens: { token: accToken },
otp: null,
otpExpire: 0,
},
);
return {
userId: user._id,
userId,
access_token: accToken,
};
}
@@ -82,29 +95,31 @@ export class UserAuthService {
mobile: string,
binding: LinkBinding = {},
): Promise<LoginDtoRs> {
const canonicalMobile = normalizeIranMobile(mobile) ?? mobile.trim();
if (!canonicalMobile) {
throwUserAuthError(UserAuthErrorCode.USER_NOT_FOUND);
}
await this.userLinkAccessService.assertMobileAllowed({
mobile,
mobile: canonicalMobile,
linkToken: binding.linkToken,
linkContext: binding.linkContext,
});
const userExist = await this.userDbService.findOne({
mobile,
});
const userExist = await this.userDbService.findOne(
buildUserLookupByPhone(canonicalMobile),
);
const otp = this.otpCreator.create();
const hashOtp = await this.hashService.hash(otp);
const rawExpireMinutes = Number(process.env.EXP_OTP_TIME ?? "2");
const expireMinutes =
Number.isFinite(rawExpireMinutes) && rawExpireMinutes > 0
? rawExpireMinutes
: 2;
const otpExpire = Date.now() + expireMinutes * 60 * 1000;
const expireMinutes = readOtpExpireMinutesFromEnv();
const nowMs = Date.now();
const otpExpire = computeOtpExpireMs(expireMinutes, nowMs);
if (!userExist) {
await this.smsSender(otp, mobile);
/// create otp request
await this.smsSender(otp, canonicalMobile);
const newUser = await this.userDbService.createUser({
mobile,
username: mobile,
mobile: canonicalMobile,
username: canonicalMobile,
otp: hashOtp,
tokens: {
token: "",
@@ -122,22 +137,22 @@ export class UserAuthService {
});
return new LoginDtoRs(newUser);
}
if (userExist) {
if (userExist.otpExpire > new Date(new Date().getTime()).getTime()) {
throwUserAuthError(UserAuthErrorCode.OTP_REQUEST_TOO_SOON);
}
await this.smsSender(otp, mobile);
const updateTokens = await this.userDbService.findOneAndUpdate(
{
username: userExist.username,
},
{
otp: hashOtp,
otpExpire,
},
);
if (updateTokens) return new LoginDtoRs(userExist);
if (isOtpExpiryActive(userExist.otpExpire, nowMs)) {
throwUserAuthError(UserAuthErrorCode.OTP_REQUEST_TOO_SOON);
}
await this.smsSender(otp, canonicalMobile);
await this.userDbService.findOneAndUpdate(
buildUserLookupByPhone(canonicalMobile),
{
otp: hashOtp,
otpExpire,
mobile: canonicalMobile,
username: userExist.username || canonicalMobile,
},
);
return new LoginDtoRs(userExist);
}
private async smsSender(otp: string, mobile: string) {