Loading backend/src/auth/admin/authAdmin.module.ts +4 −2 Original line number Diff line number Diff line Loading @@ -8,11 +8,13 @@ import { AdminService } from 'src/admin/admin.service'; import { JwtService } from '@nestjs/jwt'; import { AuthAdminGuard } from './authAdmin.guard'; import { Town } from 'src/town/entities/town.entity'; import { AdminResetCode } from './entitites/admin-reset-code.entity'; import { EmailService } from 'src/email/email.service'; @Module({ controllers: [AuthAdminController], providers: [AuthAdminService, AdminService, JwtService, EncryptionService, AuthAdminGuard], imports: [TypeOrmModule.forFeature([Admin, Town])], providers: [AuthAdminService, AdminService, JwtService, EncryptionService, AuthAdminGuard, EmailService], imports: [TypeOrmModule.forFeature([Admin, Town, AdminResetCode])], exports: [AuthAdminService], }) export class AuthAdminModule {} backend/src/auth/admin/authAdmin.service.ts +44 −0 Original line number Diff line number Diff line Loading @@ -10,10 +10,16 @@ import { Admin } from 'src/admin/entities/admin.entity'; import { ADMIN_ROLE } from 'src/shared/enum/admin-role.enum'; import { PayloadJwtDto } from 'src/shared/dto/payload-jwt.dto'; import { UpdatePwdDto } from '../user/dto/update-pwd.dto'; import { randomInt } from 'crypto'; import { InjectRepository } from '@nestjs/typeorm'; import { AdminResetCode } from './entitites/admin-reset-code.entity'; import { Repository } from 'typeorm'; import { AdminResetPasswordDto } from './dto/admin-reset-password.dto'; @Injectable() export class AuthAdminService { constructor( @InjectRepository(AdminResetCode) private adminResetCodeRepository: Repository<AdminResetCode>, private adminService: AdminService, private jwtService: JwtService, private encryptionService: EncryptionService, Loading Loading @@ -69,4 +75,42 @@ export class AuthAdminService { const hashedPwd = await this.encryptionService.hashPassword(updatePwdDto.newPassword); await this.adminService.updatePassword(email, hashedPwd); } async getResetPasswordCode(email: string): Promise<string> { const admin: Admin = await this.adminService.findOne(email); if (!admin) throw new UnauthorizedException('Invalid email'); const resetCode: string = randomInt(100000, 999999).toString(); const expirationDate: Date = new Date(); expirationDate.setMinutes(expirationDate.getMinutes() + 10); const existUserCode: AdminResetCode[] = await this.adminResetCodeRepository.findBy({ admin: admin, code: resetCode, }); if (existUserCode.length > 0) { await this.adminResetCodeRepository.delete(existUserCode[0].id); } await this.adminResetCodeRepository.save({ admin, code: resetCode, expirationDate }); return resetCode; } async resetPassword(adminResetPasswordDto: AdminResetPasswordDto): Promise<void> { const admin: Admin = await this.adminService.findOne(adminResetPasswordDto.email); if (!admin) throw new UnauthorizedException('Invalid email'); const adminResetCode: AdminResetCode[] = await this.adminResetCodeRepository.findBy({ admin: admin, code: adminResetPasswordDto.resetCode, }); if (adminResetCode.length === 0) throw new UnauthorizedException('Invalid code'); if (adminResetCode[0].expirationDate < new Date()) throw new UnauthorizedException('Code expired'); const hashedPwd = await this.encryptionService.hashPassword(adminResetPasswordDto.newPassword); await this.adminService.updatePassword(adminResetPasswordDto.email, hashedPwd); await this.adminResetCodeRepository.delete(adminResetCode[0].id); } } backend/src/auth/admin/authAdmincontroller.ts +24 −1 Original line number Diff line number Diff line Loading @@ -9,11 +9,17 @@ import { ADMIN_ROLE, ADMIN_ROLES, SUPERADMIN_ROLES } from 'src/shared/enum/admin import { AuthAdminGuard } from './authAdmin.guard'; import { UpdatePwdDto } from '../user/dto/update-pwd.dto'; import { CustomAdminRequest } from './interface/customAdminReq'; import { AdminRequestCodeBody, AdminResetPasswordBody } from './dto/admin-reset-password.dto'; import { GetResetCode } from './dto/get-reset-code.dto'; import { EmailService } from 'src/email/email.service'; @Controller() @ApiTags('Create admin account and sign in as admin') export class AuthAdminController { constructor(private readonly authAdminService: AuthAdminService) {} constructor( private readonly authAdminService: AuthAdminService, private readonly mailService: EmailService, ) {} @ApiBody({ type: CreateAdminDto }) @ApiCreatedResponse({ Loading Loading @@ -61,4 +67,21 @@ export class AuthAdminController { const email = req.admin.email; return this.authAdminService.changePassword(email, updatePwdDto); } @ApiBody({ type: AdminResetPasswordBody }) @Post('admin/reset-password') async resetPassword(@Body() resetPasswordDto: AdminResetPasswordBody) { return this.authAdminService.resetPassword(resetPasswordDto); } @ApiBody({ type: AdminRequestCodeBody }) @Post('admin/get-reset-code') async getResetCode(@Body() resetPasswordInfo: GetResetCode) { try { const code = await this.authAdminService.getResetPasswordCode(resetPasswordInfo.email); await this.mailService.sendResetPasswordEmail(resetPasswordInfo.email, code); } catch (e) { throw e; } } } Loading
backend/src/auth/admin/authAdmin.module.ts +4 −2 Original line number Diff line number Diff line Loading @@ -8,11 +8,13 @@ import { AdminService } from 'src/admin/admin.service'; import { JwtService } from '@nestjs/jwt'; import { AuthAdminGuard } from './authAdmin.guard'; import { Town } from 'src/town/entities/town.entity'; import { AdminResetCode } from './entitites/admin-reset-code.entity'; import { EmailService } from 'src/email/email.service'; @Module({ controllers: [AuthAdminController], providers: [AuthAdminService, AdminService, JwtService, EncryptionService, AuthAdminGuard], imports: [TypeOrmModule.forFeature([Admin, Town])], providers: [AuthAdminService, AdminService, JwtService, EncryptionService, AuthAdminGuard, EmailService], imports: [TypeOrmModule.forFeature([Admin, Town, AdminResetCode])], exports: [AuthAdminService], }) export class AuthAdminModule {}
backend/src/auth/admin/authAdmin.service.ts +44 −0 Original line number Diff line number Diff line Loading @@ -10,10 +10,16 @@ import { Admin } from 'src/admin/entities/admin.entity'; import { ADMIN_ROLE } from 'src/shared/enum/admin-role.enum'; import { PayloadJwtDto } from 'src/shared/dto/payload-jwt.dto'; import { UpdatePwdDto } from '../user/dto/update-pwd.dto'; import { randomInt } from 'crypto'; import { InjectRepository } from '@nestjs/typeorm'; import { AdminResetCode } from './entitites/admin-reset-code.entity'; import { Repository } from 'typeorm'; import { AdminResetPasswordDto } from './dto/admin-reset-password.dto'; @Injectable() export class AuthAdminService { constructor( @InjectRepository(AdminResetCode) private adminResetCodeRepository: Repository<AdminResetCode>, private adminService: AdminService, private jwtService: JwtService, private encryptionService: EncryptionService, Loading Loading @@ -69,4 +75,42 @@ export class AuthAdminService { const hashedPwd = await this.encryptionService.hashPassword(updatePwdDto.newPassword); await this.adminService.updatePassword(email, hashedPwd); } async getResetPasswordCode(email: string): Promise<string> { const admin: Admin = await this.adminService.findOne(email); if (!admin) throw new UnauthorizedException('Invalid email'); const resetCode: string = randomInt(100000, 999999).toString(); const expirationDate: Date = new Date(); expirationDate.setMinutes(expirationDate.getMinutes() + 10); const existUserCode: AdminResetCode[] = await this.adminResetCodeRepository.findBy({ admin: admin, code: resetCode, }); if (existUserCode.length > 0) { await this.adminResetCodeRepository.delete(existUserCode[0].id); } await this.adminResetCodeRepository.save({ admin, code: resetCode, expirationDate }); return resetCode; } async resetPassword(adminResetPasswordDto: AdminResetPasswordDto): Promise<void> { const admin: Admin = await this.adminService.findOne(adminResetPasswordDto.email); if (!admin) throw new UnauthorizedException('Invalid email'); const adminResetCode: AdminResetCode[] = await this.adminResetCodeRepository.findBy({ admin: admin, code: adminResetPasswordDto.resetCode, }); if (adminResetCode.length === 0) throw new UnauthorizedException('Invalid code'); if (adminResetCode[0].expirationDate < new Date()) throw new UnauthorizedException('Code expired'); const hashedPwd = await this.encryptionService.hashPassword(adminResetPasswordDto.newPassword); await this.adminService.updatePassword(adminResetPasswordDto.email, hashedPwd); await this.adminResetCodeRepository.delete(adminResetCode[0].id); } }
backend/src/auth/admin/authAdmincontroller.ts +24 −1 Original line number Diff line number Diff line Loading @@ -9,11 +9,17 @@ import { ADMIN_ROLE, ADMIN_ROLES, SUPERADMIN_ROLES } from 'src/shared/enum/admin import { AuthAdminGuard } from './authAdmin.guard'; import { UpdatePwdDto } from '../user/dto/update-pwd.dto'; import { CustomAdminRequest } from './interface/customAdminReq'; import { AdminRequestCodeBody, AdminResetPasswordBody } from './dto/admin-reset-password.dto'; import { GetResetCode } from './dto/get-reset-code.dto'; import { EmailService } from 'src/email/email.service'; @Controller() @ApiTags('Create admin account and sign in as admin') export class AuthAdminController { constructor(private readonly authAdminService: AuthAdminService) {} constructor( private readonly authAdminService: AuthAdminService, private readonly mailService: EmailService, ) {} @ApiBody({ type: CreateAdminDto }) @ApiCreatedResponse({ Loading Loading @@ -61,4 +67,21 @@ export class AuthAdminController { const email = req.admin.email; return this.authAdminService.changePassword(email, updatePwdDto); } @ApiBody({ type: AdminResetPasswordBody }) @Post('admin/reset-password') async resetPassword(@Body() resetPasswordDto: AdminResetPasswordBody) { return this.authAdminService.resetPassword(resetPasswordDto); } @ApiBody({ type: AdminRequestCodeBody }) @Post('admin/get-reset-code') async getResetCode(@Body() resetPasswordInfo: GetResetCode) { try { const code = await this.authAdminService.getResetPasswordCode(resetPasswordInfo.email); await this.mailService.sendResetPasswordEmail(resetPasswordInfo.email, code); } catch (e) { throw e; } } }