|
|
|
@ -7,6 +7,8 @@ import { ConfigService } from "@nestjs/config"; |
|
|
|
|
import { CreateUserDto } from "./dto/create-user.dto"; |
|
|
|
|
import { LoginUserDto } from "./dto/login-user.dto"; |
|
|
|
|
import { UpdateUserDto } from "./dto/update-user.dto"; |
|
|
|
|
import { v4 as uuidv4 } from "uuid"; |
|
|
|
|
import { RedisService } from "src/redis/redis.service"; |
|
|
|
|
|
|
|
|
|
@Injectable() |
|
|
|
|
export class UsersService { |
|
|
|
@ -14,6 +16,7 @@ export class UsersService { |
|
|
|
|
@InjectModel(User) private readonly userModel: typeof User, |
|
|
|
|
private readonly jwtService: JwtService, |
|
|
|
|
private readonly configService: ConfigService, |
|
|
|
|
private readonly redisService: RedisService, |
|
|
|
|
) {} |
|
|
|
|
|
|
|
|
|
// Register method
|
|
|
|
@ -46,7 +49,6 @@ export class UsersService { |
|
|
|
|
const user = await this.userModel.findOne({ |
|
|
|
|
where: { email: createUserDto.email }, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const refreshToken = this.jwtService.sign( |
|
|
|
|
{ id: user.id }, |
|
|
|
|
{ |
|
|
|
@ -54,9 +56,6 @@ export class UsersService { |
|
|
|
|
expiresIn: this.configService.get<string | number>("JWT_REFRESH_EXPIRES") || "7d", |
|
|
|
|
}, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
await this.userModel.update({ refreshToken }, { where: { id: user.id } }); |
|
|
|
|
|
|
|
|
|
return { message: "User registered successfully." }; |
|
|
|
|
} catch (error) { |
|
|
|
|
if (error instanceof HttpException) { |
|
|
|
@ -73,7 +72,7 @@ export class UsersService { |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
if (!user) { |
|
|
|
|
throw new UnauthorizedException("Invalid email , username or password."); |
|
|
|
|
throw new UnauthorizedException("Invalid email, username or password."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const passwordMatch = await bcrypt.compare(loginUserDto.password, user.password); |
|
|
|
@ -81,8 +80,9 @@ export class UsersService { |
|
|
|
|
throw new UnauthorizedException("Invalid email or password."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const jti = uuidv4(); |
|
|
|
|
const accessToken = this.jwtService.sign( |
|
|
|
|
{ id: user.id, role: user.role }, |
|
|
|
|
{ id: user.id, role: user.role, jti }, |
|
|
|
|
{ |
|
|
|
|
secret: this.configService.get<string>("JWT_SECRET"), |
|
|
|
|
expiresIn: this.configService.get<string | number>("JWT_EXPIRES") || "1h", |
|
|
|
@ -90,17 +90,13 @@ export class UsersService { |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const refreshToken = this.jwtService.sign( |
|
|
|
|
{ id: user.id }, |
|
|
|
|
{ id: user.id, jti }, |
|
|
|
|
{ |
|
|
|
|
secret: this.configService.get<string>("JWT_REFRESH_SECRET"), |
|
|
|
|
expiresIn: this.configService.get<string | number>("JWT_REFRESH_EXPIRES") || "7d", |
|
|
|
|
}, |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
await this.userModel.update( |
|
|
|
|
{ refreshToken }, //
|
|
|
|
|
{ where: { id: user.id } }, |
|
|
|
|
); |
|
|
|
|
await this.redisService.addToWhitelist(user.id, jti, 3600); |
|
|
|
|
|
|
|
|
|
return { accessToken, refreshToken }; |
|
|
|
|
} catch (error) { |
|
|
|
@ -127,38 +123,30 @@ export class UsersService { |
|
|
|
|
if (!user) { |
|
|
|
|
throw new HttpException("User not found.", HttpStatus.NOT_FOUND); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (user.refreshToken !== refreshToken) { |
|
|
|
|
throw new HttpException("Invalid refresh token.", HttpStatus.FORBIDDEN); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const jti = uuidv4(); |
|
|
|
|
const accessToken = this.jwtService.sign( |
|
|
|
|
{ id: user.id, role: user.role }, |
|
|
|
|
{ id: user.id, role: user.role, jti }, |
|
|
|
|
{ |
|
|
|
|
secret: this.configService.get<string>("JWT_SECRET"), |
|
|
|
|
expiresIn: this.configService.get<string | number>("JWT_EXPIRES") || "1h", |
|
|
|
|
}, |
|
|
|
|
); |
|
|
|
|
await this.redisService.addToWhitelist(user.id, jti, 3600); |
|
|
|
|
|
|
|
|
|
return { accessToken }; |
|
|
|
|
} |
|
|
|
|
//logout (delete refresh token from database)
|
|
|
|
|
async logout(userId: number) { |
|
|
|
|
if (!userId) { |
|
|
|
|
throw new HttpException("User ID is required.", HttpStatus.BAD_REQUEST); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async logout(user: any) { |
|
|
|
|
try { |
|
|
|
|
const user = await this.userModel.findOne({ where: { id: userId } }); |
|
|
|
|
if (!user) { |
|
|
|
|
throw new HttpException("User not found.", HttpStatus.NOT_FOUND); |
|
|
|
|
} |
|
|
|
|
const jti = user.jti; |
|
|
|
|
const userId = user.id; |
|
|
|
|
|
|
|
|
|
await this.userModel.update({ refreshToken: null }, { where: { id: userId } }); |
|
|
|
|
await this.redisService.deleteFromWhitelist(userId, jti); |
|
|
|
|
|
|
|
|
|
return { message: "Logout is successful." }; |
|
|
|
|
return { message: "Logged out successfully." }; |
|
|
|
|
} catch (error) { |
|
|
|
|
throw new HttpException("An error occurred while logging out.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
throw new UnauthorizedException("An error occurred during logout."); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
//get information user method
|
|
|
|
@ -166,7 +154,7 @@ export class UsersService { |
|
|
|
|
try { |
|
|
|
|
const user = await this.userModel.findOne({ |
|
|
|
|
where: { id: userId }, |
|
|
|
|
attributes: { exclude: ["password","refreshToken"] }, |
|
|
|
|
attributes: { exclude: ["password", "refreshToken"] }, |
|
|
|
|
}); |
|
|
|
|
if (!user) { |
|
|
|
|
throw new HttpException("User not found.", HttpStatus.NOT_FOUND); |
|
|
|
@ -252,14 +240,14 @@ export class UsersService { |
|
|
|
|
|
|
|
|
|
return users; |
|
|
|
|
} catch (error) { |
|
|
|
|
if(error instanceof HttpException){ |
|
|
|
|
throw error |
|
|
|
|
if (error instanceof HttpException) { |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
throw new HttpException("An unexpected error occurred while fetching users.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
//get users list
|
|
|
|
|
async findSpecificUserInfoByUser(userId: number){ |
|
|
|
|
async findSpecificUserInfoByUser(userId: number) { |
|
|
|
|
try { |
|
|
|
|
const user = await this.userModel.findByPk(userId, { |
|
|
|
|
attributes: { exclude: ["refreshToken", "password"] }, |
|
|
|
@ -269,8 +257,8 @@ export class UsersService { |
|
|
|
|
} |
|
|
|
|
return user; |
|
|
|
|
} catch (error) { |
|
|
|
|
if(error instanceof HttpException){ |
|
|
|
|
throw error |
|
|
|
|
if (error instanceof HttpException) { |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
throw new HttpException("An unexpected error occurred while fetching user information.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
} |
|
|
|
@ -292,8 +280,8 @@ export class UsersService { |
|
|
|
|
|
|
|
|
|
return { message: "User deleted successfully." }; |
|
|
|
|
} catch (error) { |
|
|
|
|
if(error instanceof HttpException){ |
|
|
|
|
throw error |
|
|
|
|
if (error instanceof HttpException) { |
|
|
|
|
throw error; |
|
|
|
|
} |
|
|
|
|
throw new HttpException("An error occurred while deleting the user.", HttpStatus.INTERNAL_SERVER_ERROR); |
|
|
|
|
} |
|
|
|
|