commit for push

This commit is contained in:
2026-07-26 14:55:37 +03:30
parent cefddfeeda
commit 45464c070f
6 changed files with 108 additions and 15 deletions
+2
View File
@@ -33,6 +33,7 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.15.1",
"joi": "^18.2.3",
"ms": "^2.1.3",
"passport-jwt": "^4.0.1",
"pg": "^8.22.0",
"reflect-metadata": "^0.2.2",
@@ -48,6 +49,7 @@
"@types/bcrypt": "^6.0.0",
"@types/express": "^5.0.0",
"@types/jest": "^30.0.0",
"@types/ms": "^2.1.0",
"@types/node": "^22.10.7",
"@types/passport-jwt": "^4.0.1",
"@types/supertest": "^6.0.2",
+6
View File
@@ -47,6 +47,9 @@ importers:
joi:
specifier: ^18.2.3
version: 18.2.3
ms:
specifier: ^2.1.3
version: 2.1.3
passport-jwt:
specifier: ^4.0.1
version: 4.0.1
@@ -87,6 +90,9 @@ importers:
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
'@types/ms':
specifier: ^2.1.0
version: 2.1.0
'@types/node':
specifier: ^22.10.7
version: 22.20.1
+10
View File
@@ -45,4 +45,14 @@ export class AuthController {
) {
return this.authService.checkLoginCredentials(dto);
}
@Post('verify-login')
@ApiOperation({summary: 'verifies OTP and then login'})
@ApiResponse({status: 200, description: 'User Logged in successfully!'})
@ApiResponse({status: 400, description: 'Bad Request From The User'})
async verifyOtpAndLogin(
@Body() verifyOtpDto: VerifyOtpDto
) {
return this.authService.verifyOtpAndLogin(verifyOtpDto);
}
}
+43 -6
View File
@@ -11,6 +11,7 @@ import { LoginCredentialDto } from './DTO/login-credential.dto';
import { UsersService } from 'src/users/users.service';
import * as bcrypt from 'bcrypt';
import { JwtService } from '@nestjs/jwt';
import ms from 'ms';
@Injectable()
export class AuthService {
@@ -20,7 +21,7 @@ export class AuthService {
private readonly configService: ConfigService,
private readonly OtpRepository: OtpRepository,
private readonly userService: UsersService,
private readonly jwtService: JwtService
private readonly jwtService: JwtService,
) {}
async sendOTP(phone: string) {
@@ -43,7 +44,6 @@ export class AuthService {
{ status: OtpStatus.EXPIRED },
);
await this.OtpRepository.save(
this.OtpRepository.create({
phoneNumber: phone,
@@ -123,9 +123,46 @@ export class AuthService {
await this.sendOTP(phoneNumber);
}
// async VerifyOtpAndLogin(dto: VerifyOtpDto) {
// await this.verifyOTP(dto);
async verifyOtpAndLogin(dto: VerifyOtpDto) {
await this.verifyOTP(dto);
// const user = await this.userService.findOneByPhoneOrFail(dto.phoneNumber);
// }
const user = await this.userService.findUserWithRolesByPhoneOrFail(
dto.phoneNumber,
);
const roles = user.roles.map((r) => r.role);
const payload = {
sub: user.id,
phone: user.phone,
roles,
};
const accessToken = await this.jwtService.signAsync(payload, {
secret: this.configService.getOrThrow<string>('JWT_ACCESS_SECRET'),
expiresIn: this.configService.getOrThrow<string>(
'JWT_ACCESS_EXPIRES',
) as ms.StringValue,
});
const refreshToken = await this.jwtService.signAsync(payload, {
secret: this.configService.getOrThrow<string>('JWT_REFRESH_SECRET'),
expiresIn: this.configService.getOrThrow<string>(
'JWT_REFRESH_EXPIRES',
) as ms.StringValue,
});
await this.userService.updateRefreshToken(user.id, refreshToken);
return {
user: {
userId: user.id,
username: user.firstName + ' ' + user.lastName,
userPhone: user.phone,
userEmail: user.email,
},
accessToken,
refreshToken,
};
}
}
+22 -5
View File
@@ -1,11 +1,28 @@
import { Repository } from "typeorm";
import { User } from "../entities/user.entity";
import { InjectRepository } from "@nestjs/typeorm";
import { Injectable } from "@nestjs/common";
import { Repository } from 'typeorm';
import { User } from '../entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserRepository extends Repository<User> {
constructor(@InjectRepository(User) userRepository: Repository<User>) {
super(userRepository.target, userRepository.manager, userRepository.queryRunner);
super(
userRepository.target,
userRepository.manager,
userRepository.queryRunner,
);
}
findUserWithRolesByPhone(phone: string): Promise<User | null> {
return this.createQueryBuilder('users')
.leftJoinAndSelect('users.roles', 'roles')
.where("users.phone = :phone", {phone})
.select(
[
'users',
'roles.id',
'roles.role'
]
).getOne();
}
}
+22 -1
View File
@@ -30,7 +30,12 @@ export class UsersService {
}
async findOneByPhoneOrFail(phone: string): Promise<User> {
const user = await this.userRepository.findOne({ where: { phone } });
const user = await this.userRepository.findOne({
where: { phone },
relations: {
roles: true,
},
});
if (!user) {
throw new NotFoundException(UserMessages.USER_NOT_FOUND);
@@ -39,6 +44,22 @@ export class UsersService {
return user;
}
async findUserWithRolesByPhoneOrFail(phone: string): Promise<User> {
const user = await this.userRepository.findUserWithRolesByPhone(phone);
if (!user)
throw new NotFoundException(UserMessages.USER_NOT_FOUND);
return user;
}
async updateRefreshToken(id: string, newRefreshToken: string) {
const user = await this.findOneOrFail(id);
user.refreshToken = newRefreshToken;
await this.userRepository.save(user);
}
async createUser(userDto: CreateUserDto): Promise<User> {
const existingUser = await this.userRepository.findOne({
where: [