1
0
forked from Yara724/api
Files
yara724-api/src/auth/auth-services/user.auth.service.ts
2026-04-05 16:44:14 +03:30

142 lines
4.1 KiB
TypeScript

import {
BadRequestException,
HttpException,
HttpStatus,
Injectable,
Logger,
NotAcceptableException,
NotFoundException,
} from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import { Types } from "mongoose";
import { LoginDtoRs } from "src/auth/dto/user/login.dto";
import { UserDbService } from "src/users/entities/db-service/user.db.service";
import { HashService } from "src/utils/hash/hash.service";
import { OtpService } from "src/utils/otp/otp.service";
import { SmsManagerService } from "src/utils/sms-manager/sms-manager.service";
// TODO FIX REGISTER TO USER.SERVICE AND AUTH IN THIS MODULE
@Injectable()
export class UserAuthService {
private readonly logger = new Logger(UserAuthService.name);
constructor(
private readonly jwtService: JwtService,
private readonly userDbService: UserDbService,
private readonly hashService: HashService,
private readonly otpCreator: OtpService,
private readonly smsManagerService: SmsManagerService,
) {}
async validateUser(username: string, pass: string): Promise<any> {
const user = await this.userDbService.findOne({ username });
if (!user) throw new NotFoundException("user not found");
const now = new Date().getTime();
if (user.otp == null) throw new NotAcceptableException("please get otp");
if (user.otpExpire < now) {
throw new NotAcceptableException("expire otp");
}
if (await this.hashService.compare(pass, user.otp)) {
return user;
}
return false;
}
async login(user: any) {
const payload = {
username: user.username,
sub: user.id,
role: "user",
};
const accToken = this.jwtService.sign(payload, {
secret: `${process.env.SECRET}`,
});
await this.userDbService.findOneAndUpdate(
{ username: user.username },
{
tokens: { token: accToken },
otp: null,
},
);
return {
userId: user._id,
access_token: accToken,
};
}
async sendOtpRequest(mobile: string): Promise<LoginDtoRs> {
const userExist = await this.userDbService.findOne({
mobile,
});
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;
if (!userExist) {
await this.smsSender(otp, mobile);
/// create otp request
const newUser = await this.userDbService.createUser({
mobile,
username: mobile,
otp: hashOtp,
tokens: {
token: "",
rfToken: "",
},
fullName: "",
nationalCode: "",
lastLogin: new Date(),
clientKey: new Types.ObjectId(),
birthDay: "",
city: "",
address: "",
state: "",
otpExpire,
});
return new LoginDtoRs(newUser);
}
if (userExist) {
if (userExist.otpExpire > new Date(new Date().getTime()).getTime()) throw new BadRequestException("Wait for expiry time to finish");
await this.smsSender(otp, mobile);
const updateTokens = await this.userDbService.findOneAndUpdate(
{
username: userExist.username,
},
{
otp: hashOtp,
otpExpire,
},
);
if (updateTokens) return new LoginDtoRs(userExist);
}
}
private async smsSender(otp: string, mobile: string) {
return this.smsManagerService
.verifyLookUp({
token: otp,
template: process.env.AUTH_SMS_TEMPLATE,
receptor: mobile,
})
.then((smsRes) => {
this.logger.log(
`${"phone : " + mobile + " " + ", status : " + smsRes["return"]?.status + ", otp : " + otp} `,
);
})
.catch((er) => {
this.logger.error(
`${"phone : " + mobile + " " + ", status : " + er["return"]?.status + ", otp : " + otp} `,
);
throw new HttpException(
" auth sms send failed",
HttpStatus.INTERNAL_SERVER_ERROR,
);
});
}
}