33 * @module module/admin/service
44 */
55
6+ import bcrypt from 'bcryptjs'
67import { Injectable , UnauthorizedException , BadRequestException } from '@nestjs/common'
78import { InjectModel } from '@app/transformers/model.transformer'
89import { MongooseModel } from '@app/interfaces/mongoose.interface'
910import { AuthService } from '@app/core/auth/auth.service'
10- import { decodeBase64 , decodeMD5 } from '@app/transformers/codec.transformer'
11+ import { decodeBase64 } from '@app/transformers/codec.transformer'
1112import { Admin , DEFAULT_ADMIN_PROFILE } from './admin.model'
1213import { TokenResult } from './admin.interface'
1314import { AdminUpdateDTO } from './admin.dto'
@@ -20,22 +21,31 @@ export class AdminService {
2021 @InjectModel ( Admin ) private readonly adminModel : MongooseModel < Admin >
2122 ) { }
2223
23- private async getExistedPassword ( ) : Promise < string > {
24- const auth = await this . adminModel . findOne ( undefined , '+password' ) . exec ( )
25- return auth ?. password || decodeMD5 ( APP_BIZ . AUTH . defaultPassword )
24+ /**
25+ * Validate the provided plain password against the stored password.
26+ * - If a hashed password exists in the database, verify with bcrypt.
27+ * - If no password exists (e.g., initial state), fall back to comparing with the default password.
28+ */
29+ private async validatePassword ( plainPassword : string ) : Promise < boolean > {
30+ const existedProfile = await this . adminModel . findOne ( undefined , '+password' ) . exec ( )
31+ if ( existedProfile ?. password ) {
32+ // Password exists in database → validate using bcrypt
33+ return await bcrypt . compare ( plainPassword , existedProfile . password )
34+ } else {
35+ // No password in database → compare directly with default password (no hashing)
36+ return plainPassword === APP_BIZ . PASSWORD . defaultPassword
37+ }
2638 }
2739
2840 public createToken ( ) : TokenResult {
2941 return {
3042 access_token : this . authService . signToken ( ) ,
31- expires_in : APP_BIZ . AUTH . expiresIn
43+ expires_in : APP_BIZ . AUTH_JWT . expiresIn
3244 }
3345 }
3446
35- public async login ( password : string ) : Promise < TokenResult > {
36- const existedPassword = await this . getExistedPassword ( )
37- const loginPassword = decodeMD5 ( decodeBase64 ( password ) )
38- if ( loginPassword === existedPassword ) {
47+ public async login ( base64Password : string ) : Promise < TokenResult > {
48+ if ( await this . validatePassword ( decodeBase64 ( base64Password ) ) ) {
3949 return this . createToken ( )
4050 } else {
4151 throw new UnauthorizedException ( 'Password incorrect' )
@@ -48,32 +58,31 @@ export class AdminService {
4858 }
4959
5060 public async updateProfile ( adminProfile : AdminUpdateDTO ) : Promise < Admin > {
51- const { password, new_password, ...profile } = adminProfile
52- const payload : Admin = { ...profile }
61+ const { password : inputOldPassword , new_password : inputNewPassword , ...profile } = adminProfile
62+ const newProfile : Admin = { ...profile }
5363
54- // verify password
55- if ( password || new_password ) {
56- if ( ! password || ! new_password ) {
64+ // Verify password
65+ if ( inputOldPassword || inputNewPassword ) {
66+ if ( ! inputOldPassword || ! inputNewPassword ) {
5767 throw new BadRequestException ( 'Incomplete passwords' )
5868 }
59- if ( password === new_password ) {
69+ if ( inputOldPassword === inputNewPassword ) {
6070 throw new BadRequestException ( 'Old password and new password cannot be the same' )
6171 }
62- const oldPassword = decodeMD5 ( decodeBase64 ( password ) )
63- const existedPassword = await this . getExistedPassword ( )
64- if ( oldPassword !== existedPassword ) {
72+ if ( ! ( await this . validatePassword ( decodeBase64 ( inputOldPassword ) ) ) ) {
6573 throw new BadRequestException ( 'Old password incorrect' )
6674 }
67- // set new password
68- payload . password = decodeMD5 ( decodeBase64 ( new_password ) )
75+ // Set new password
76+ const plainNewPassword = decodeBase64 ( inputNewPassword )
77+ newProfile . password = await bcrypt . hash ( plainNewPassword , APP_BIZ . PASSWORD . bcryptSaltRounds )
6978 }
7079
7180 // save
72- const existedAuth = await this . adminModel . findOne ( undefined , '+password' ) . exec ( )
73- if ( existedAuth ) {
74- await Object . assign ( existedAuth , payload ) . save ( )
81+ const existedProfile = await this . adminModel . findOne ( undefined , '+password' ) . exec ( )
82+ if ( existedProfile ) {
83+ await Object . assign ( existedProfile , newProfile ) . save ( )
7584 } else {
76- await this . adminModel . create ( payload )
85+ await this . adminModel . create ( newProfile )
7786 }
7887
7988 return this . getProfile ( )
0 commit comments