From ad853c326e08e16eb7611dc11cbd79090b550ee3 Mon Sep 17 00:00:00 2001 From: expressgy Date: Sun, 30 Jun 2024 22:18:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90Token=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/application/app.module.ts | 8 +- .../auth-dept/auth-dept.controller.ts | 20 +-- .../auth-dept/auth-dept.service.ts | 22 +-- .../auth-post/auth-post.controller.ts | 16 +- .../auth-post/auth-post.service.ts | 14 +- .../auth-role/auth-role.controller.ts | 20 +-- .../auth-role/auth-role.service.ts | 34 ++-- .../auth-user/auth-user.controller.ts | 42 +++-- src/application/auth-user/auth-user.module.ts | 3 +- .../auth-user/auth-user.service.ts | 169 +++++++++++------- .../core-dict/core-dict.controller.ts | 18 +- .../core-dict/core-dict.service.ts | 30 ++-- .../core-env/core-env.controller.ts | 18 +- src/application/core-env/core-env.service.ts | 30 ++-- .../core-menu/core-menu.controller.ts | 20 +-- .../core-menu/core-menu.service.ts | 50 +++--- .../core-service/core-service.controller.ts | 16 +- .../core-service/core-service.service.ts | 32 ++-- src/application/global.module.ts | 5 +- .../decorator/pac-info/pac-info.decorator.ts | 17 +- src/common/guard/auth/auth.guard.ts | 82 +++++++++ src/common/service/jwt/jwt.service.ts | 2 +- src/config/configuration.ts | 5 +- src/utils/key.ts | 32 ++++ src/utils/myType.d.ts | 2 +- 25 files changed, 440 insertions(+), 267 deletions(-) create mode 100644 src/common/guard/auth/auth.guard.ts create mode 100644 src/utils/key.ts diff --git a/src/application/app.module.ts b/src/application/app.module.ts index 054044a..9d5cc74 100644 --- a/src/application/app.module.ts +++ b/src/application/app.module.ts @@ -4,7 +4,7 @@ import configuration from '@config/configuration'; import { LogRequestInfoMiddleware } from '@common/middleware/log-request-info/log-request-info.middleware'; import { TestModule } from '@app/test/test.module'; import { UserOperationLogInterceptor } from '@common/interceptor/user-operation-log/user-operation-log.interceptor'; -import { APP_INTERCEPTOR } from '@nestjs/core'; +import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core'; import { AppController } from '@app/app.controller'; import { AppService } from '@app/app.service'; import { UserAgentMiddleware } from '@common/middleware/useragent/useragent.middleware'; @@ -18,6 +18,7 @@ import { AuthRoleModule } from './auth-role/auth-role.module'; import { AuthDeptModule } from './auth-dept/auth-dept.module'; import { AuthPostModule } from './auth-post/auth-post.module'; import { AuthUserModule } from './auth-user/auth-user.module'; +import { AuthGuard } from '@common/guard/auth/auth.guard'; @Module({ imports: [ @@ -49,6 +50,11 @@ import { AuthUserModule } from './auth-user/auth-user.module'; useExisting: UserOperationLogInterceptor, }, AppService, + { + // 这样写是全局路由守卫,使用APP_GUARD令牌 + provide: APP_GUARD, + useClass: AuthGuard, + }, ], }) export class AppModule implements NestModule { diff --git a/src/application/auth-dept/auth-dept.controller.ts b/src/application/auth-dept/auth-dept.controller.ts index 0f54d6e..f4b3112 100644 --- a/src/application/auth-dept/auth-dept.controller.ts +++ b/src/application/auth-dept/auth-dept.controller.ts @@ -3,8 +3,8 @@ import { AuthDeptService } from './auth-dept.service'; import { CreateAuthDeptDto } from './dto/create-auth-dept.dto'; import { UpdateAuthDeptDto } from './dto/update-auth-dept.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { GetAuthDeptDto } from '@app/auth-dept/dto/get-auth-dept.dto'; import { GetUserForAttDto } from '@dto/GetUserForAtt.dto'; import { DeptLinkUserDto } from '@dto/AttLinkUser.dto'; @@ -20,8 +20,8 @@ export class AuthDeptController { }) @ApiProduces('application/json') @Post() - create(@Body() createAuthDeptDto: CreateAuthDeptDto, @PacInfo() pacInfo: PacInfoType) { - return this.authDeptService.create(createAuthDeptDto, pacInfo); + create(@Body() createAuthDeptDto: CreateAuthDeptDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authDeptService.create(createAuthDeptDto, guardInfo); } @ApiOperation({ @@ -60,8 +60,8 @@ export class AuthDeptController { }) @ApiProduces('application/json') @Patch(':id') - update(@Param('id') id: string, @Body() updateAuthDeptDto: UpdateAuthDeptDto, @PacInfo() pacInfo: PacInfoType) { - return this.authDeptService.update(id, updateAuthDeptDto, pacInfo); + update(@Param('id') id: string, @Body() updateAuthDeptDto: UpdateAuthDeptDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authDeptService.update(id, updateAuthDeptDto, guardInfo); } @ApiOperation({ @@ -70,8 +70,8 @@ export class AuthDeptController { }) @ApiProduces('application/json') @Delete(':id') - remove(@Param('id') id: string, @PacInfo() pacInfo: PacInfoType) { - return this.authDeptService.remove(id, pacInfo); + remove(@Param('id') id: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authDeptService.remove(id, guardInfo); } @ApiOperation({ @@ -90,8 +90,8 @@ export class AuthDeptController { }) @ApiProduces('application/json') @Post('/user') - linkUser(@Body() deptLinkUserDto: DeptLinkUserDto, @PacInfo() pacInfo: PacInfoType) { - return this.authDeptService.linkUser(deptLinkUserDto, pacInfo); + linkUser(@Body() deptLinkUserDto: DeptLinkUserDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authDeptService.linkUser(deptLinkUserDto, guardInfo); } @ApiOperation({ diff --git a/src/application/auth-dept/auth-dept.service.ts b/src/application/auth-dept/auth-dept.service.ts index 70e2948..49df2f9 100644 --- a/src/application/auth-dept/auth-dept.service.ts +++ b/src/application/auth-dept/auth-dept.service.ts @@ -2,7 +2,7 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { CreateAuthDeptDto } from './dto/create-auth-dept.dto'; import { UpdateAuthDeptDto } from './dto/update-auth-dept.dto'; import { GetAuthDeptDto } from '@app/auth-dept/dto/get-auth-dept.dto'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; import { LoggerService } from '@service/logger/logger.service'; import { MysqlService } from '@common/service/mysql/mysql.service'; import { RedisService } from '@common/service/redis/redis.service'; @@ -70,7 +70,7 @@ export class AuthDeptService { * DESC: 创建部门信息 * DATE: 2024-06-25 15:53:04 - * */ - public async create(createAuthDeptDto: CreateAuthDeptDto, pacInfo: PacInfoType) { + public async create(createAuthDeptDto: CreateAuthDeptDto, guardInfo: GuardInfo) { // ! 加目标锁,同级,而不是全局 const lock = await this.redisService.distributedLock('DEPT' + createAuthDeptDto.pid + '-' + createAuthDeptDto.deptName, createAuthDeptDto.deptName); @@ -95,7 +95,7 @@ export class AuthDeptService { } // ! 添加部门数据 - const newPacCoreDict = await this.addDeptData(createAuthDeptDto, pGrade + 1, pacInfo.userId); + const newPacCoreDict = await this.addDeptData(createAuthDeptDto, pGrade + 1, guardInfo.userId); // ! 解锁 lock(); @@ -151,7 +151,7 @@ export class AuthDeptService { * DESC: 更新部门信息 * DATE: 2024-06-28 11:30:50 - * */ - public async update(id: string, updateAuthDeptDto: UpdateAuthDeptDto, pacInfo: PacInfoType) { + public async update(id: string, updateAuthDeptDto: UpdateAuthDeptDto, guardInfo: GuardInfo) { // ! 获取部门信息 const dept = await this.getDeptForDeptId(id); @@ -177,7 +177,7 @@ export class AuthDeptService { lock(); // ! 返回结果 - return await this.updateDept(id, updateAuthDeptDto, pacInfo.userId); + return await this.updateDept(id, updateAuthDeptDto, guardInfo.userId); } catch (e) { // ! 解锁 lock(); @@ -192,8 +192,8 @@ export class AuthDeptService { * DESC: 删除部门信息 * DATE: 2024-06-28 11:30:54 - * */ - public async remove(id: string, pacInfo: PacInfoType) { - return await this.deleteDept(id, pacInfo.userId); + public async remove(id: string, guardInfo: GuardInfo) { + return await this.deleteDept(id, guardInfo.userId); } /** Service @@ -210,8 +210,8 @@ export class AuthDeptService { * DESC: 关联账户给部门 * DATE: 2024-06-28 17:17:16 - * */ - public async linkUser(deptLinkUserDto: DeptLinkUserDto, pacInfo: PacInfoType) { - return this.linkUserForDept(deptLinkUserDto, pacInfo); + public async linkUser(deptLinkUserDto: DeptLinkUserDto, guardInfo: GuardInfo) { + return this.linkUserForDept(deptLinkUserDto, guardInfo); } /** Service @@ -550,7 +550,7 @@ export class AuthDeptService { } // DB 给部门关联上账户 - private async linkUserForDept(deptLinkUserDto: DeptLinkUserDto, pacInfo: PacInfoType) { + private async linkUserForDept(deptLinkUserDto: DeptLinkUserDto, guardInfo: GuardInfo) { // ! 去重账户ID const deduplicateUserId = Array.from(new Set(deptLinkUserDto.userIdList)); @@ -567,7 +567,7 @@ export class AuthDeptService { userIdList.map((i) => ({ deptId: deptLinkUserDto.deptId, userId: i, - createby: pacInfo.userId, + createby: guardInfo.userId, createtime: sql`now()` as any, })), ); diff --git a/src/application/auth-post/auth-post.controller.ts b/src/application/auth-post/auth-post.controller.ts index 83b1991..1c4ffc0 100644 --- a/src/application/auth-post/auth-post.controller.ts +++ b/src/application/auth-post/auth-post.controller.ts @@ -3,8 +3,8 @@ import { AuthPostService } from './auth-post.service'; import { CreateAuthPostDto } from './dto/create-auth-post.dto'; import { UpdateAuthPostDto } from './dto/update-auth-post.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { GetAuthPostDto } from '@app/auth-post/dto/get-auth-post.dto'; @ApiTags('岗位服务') @@ -18,8 +18,8 @@ export class AuthPostController { }) @ApiProduces('application/json') @Post() - create(@Body() createAuthPostDto: CreateAuthPostDto, @PacInfo() pacInfo: PacInfoType) { - return this.authPostService.create(createAuthPostDto, pacInfo); + create(@Body() createAuthPostDto: CreateAuthPostDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authPostService.create(createAuthPostDto, guardInfo); } @ApiOperation({ @@ -48,8 +48,8 @@ export class AuthPostController { }) @ApiProduces('application/json') @Patch(':id') - update(@Param('id') id: string, @Body() updateAuthPostDto: UpdateAuthPostDto, @PacInfo() pacInfo: PacInfoType) { - return this.authPostService.update(id, updateAuthPostDto, pacInfo); + update(@Param('id') id: string, @Body() updateAuthPostDto: UpdateAuthPostDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authPostService.update(id, updateAuthPostDto, guardInfo); } @ApiOperation({ @@ -58,7 +58,7 @@ export class AuthPostController { }) @ApiProduces('application/json') @Delete(':id') - remove(@Param('id') id: string, @PacInfo() pacInfo: PacInfoType) { - return this.authPostService.remove(id, pacInfo); + remove(@Param('id') id: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authPostService.remove(id, guardInfo); } } diff --git a/src/application/auth-post/auth-post.service.ts b/src/application/auth-post/auth-post.service.ts index 4d0e853..4d0f741 100644 --- a/src/application/auth-post/auth-post.service.ts +++ b/src/application/auth-post/auth-post.service.ts @@ -8,7 +8,7 @@ import { Snowflake } from '@service/snowflake/snowflake.service'; import { ConfigService } from '@nestjs/config'; import { pacAuthDept, pacAuthPost, pacAuthUser, pacCoreDict } from '@entities/schema'; import { and, asc, desc, eq, isNull, like, or, sql } from 'drizzle-orm'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; import { isExistKey, isTrueEnum } from '@utils/boolean.enum'; import { GetAuthPostDto } from '@app/auth-post/dto/get-auth-post.dto'; import { likeQuery } from '@utils/likeQuery'; @@ -56,7 +56,7 @@ export class AuthPostService { * DESC: 创建岗位信息 * DATE: 2024-06-29 13:13:44 - * */ - public async create(createAuthPostDto: CreateAuthPostDto, pacInfo: PacInfoType) { + public async create(createAuthPostDto: CreateAuthPostDto, guardInfo: GuardInfo) { // ! 加目标锁,同级,而不是全局 const lock = await this.redisService.distributedLock('POST' + createAuthPostDto.postKey, createAuthPostDto.postKey); @@ -73,7 +73,7 @@ export class AuthPostService { if (result.length > 0) throw new HttpException('岗位标识重复!', HttpStatus.CONFLICT); // ! 添加岗位数据 - const newPacCoreDict = await this.addPost(createAuthPostDto, pacInfo.userId as any); + const newPacCoreDict = await this.addPost(createAuthPostDto, guardInfo.userId as any); // ! 解锁 lock(); @@ -116,8 +116,8 @@ export class AuthPostService { * DESC: 更新岗位信息 * DATE: 2024-06-29 13:13:52 - * */ - public async update(id: string, updateAuthPostDto: UpdateAuthPostDto, pacInfo: PacInfoType) { - return await this.updatePost(id, updateAuthPostDto, pacInfo.userId as any); + public async update(id: string, updateAuthPostDto: UpdateAuthPostDto, guardInfo: GuardInfo) { + return await this.updatePost(id, updateAuthPostDto, guardInfo.userId as any); } /** Service @@ -125,8 +125,8 @@ export class AuthPostService { * DESC: 删除岗位信息 * DATE: 2024-06-29 13:13:55 - * */ - public remove(id: string, pacInfo: PacInfoType) { - return this.deletePost(id, pacInfo.userId as any); + public remove(id: string, guardInfo: GuardInfo) { + return this.deletePost(id, guardInfo.userId as any); } // DB 查重Key diff --git a/src/application/auth-role/auth-role.controller.ts b/src/application/auth-role/auth-role.controller.ts index a0098ca..2a94c54 100644 --- a/src/application/auth-role/auth-role.controller.ts +++ b/src/application/auth-role/auth-role.controller.ts @@ -3,8 +3,8 @@ import { AuthRoleService } from './auth-role.service'; import { CreateAuthRoleDto } from './dto/create-auth-role.dto'; import { UpdateAuthRoleDto } from './dto/update-auth-role.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { query } from 'express'; import { GetPacAuthRoleAllDto } from '@app/auth-role/dto/get-auth-role.dto'; import { GetUserForAttDto } from '@dto/GetUserForAtt.dto'; @@ -21,8 +21,8 @@ export class AuthRoleController { }) @ApiProduces('application/json') @Post() - create(@Body() createAuthRoleDto: CreateAuthRoleDto, @PacInfo() pacInfo: PacInfoType) { - return this.authRoleService.create(createAuthRoleDto, pacInfo); + create(@Body() createAuthRoleDto: CreateAuthRoleDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authRoleService.create(createAuthRoleDto, guardInfo); } @ApiOperation({ @@ -61,8 +61,8 @@ export class AuthRoleController { }) @ApiProduces('application/json') @Patch(':id') - update(@Param('id') id: string, @Body() updateAuthRoleDto: UpdateAuthRoleDto, @PacInfo() pacInfo: PacInfoType) { - return this.authRoleService.update(id, updateAuthRoleDto, pacInfo); + update(@Param('id') id: string, @Body() updateAuthRoleDto: UpdateAuthRoleDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authRoleService.update(id, updateAuthRoleDto, guardInfo); } @ApiOperation({ @@ -71,8 +71,8 @@ export class AuthRoleController { }) @ApiProduces('application/json') @Delete(':id') - remove(@Param('id') id: string, @PacInfo() pacInfo: PacInfoType) { - return this.authRoleService.remove(id, pacInfo); + remove(@Param('id') id: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authRoleService.remove(id, guardInfo); } @ApiOperation({ @@ -91,8 +91,8 @@ export class AuthRoleController { }) @ApiProduces('application/json') @Post('/user') - linkUser(@Body() roleLinkUserDto: RoleLinkUserDto, @PacInfo() pacInfo: PacInfoType) { - return this.authRoleService.linkUser(roleLinkUserDto, pacInfo); + linkUser(@Body() roleLinkUserDto: RoleLinkUserDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authRoleService.linkUser(roleLinkUserDto, guardInfo); } @ApiOperation({ diff --git a/src/application/auth-role/auth-role.service.ts b/src/application/auth-role/auth-role.service.ts index b857201..e39db64 100644 --- a/src/application/auth-role/auth-role.service.ts +++ b/src/application/auth-role/auth-role.service.ts @@ -6,7 +6,7 @@ import { MysqlService } from '@common/service/mysql/mysql.service'; import { RedisService } from '@common/service/redis/redis.service'; import { Snowflake } from '@service/snowflake/snowflake.service'; import { ConfigService } from '@nestjs/config'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; import { isExistKey, isTrueEnum } from '@utils/boolean.enum'; import { pacAuthDept, @@ -74,9 +74,9 @@ export class AuthRoleService { * DESC: 创建角色信息 * DATE: 2024-06-25 15:53:04 - * */ - public async create(createAuthRoleDto: CreateAuthRoleDto, pacInfo: PacInfoType) { + public async create(createAuthRoleDto: CreateAuthRoleDto, guardInfo: GuardInfo) { // ! 判断是否是root账户,非root账户无法设置为root - if (this.config.get('masterId') !== pacInfo.userId && isTrueEnum(createAuthRoleDto.root)) { + if (this.config.get('masterId') !== guardInfo.userId && isTrueEnum(createAuthRoleDto.root)) { throw new HttpException('没有权限创建原始角色!', HttpStatus.UNAUTHORIZED); } @@ -95,20 +95,20 @@ export class AuthRoleService { if (result.length > 0) throw new HttpException('角色标识重复!', HttpStatus.CONFLICT); // ! 添加角色数据 - const newRoleResult = await this.addRoleData(createAuthRoleDto, pacInfo.userId).catch((e) => { + const newRoleResult = await this.addRoleData(createAuthRoleDto, guardInfo.userId).catch((e) => { this.logger.error(e.message + e.track.toString()); throw new HttpException('角色写入错误!', HttpStatus.INTERNAL_SERVER_ERROR); }); // ! 增加关联菜单 - await this.createMenuLink(newRoleResult.roleId, createAuthRoleDto.menuList, pacInfo.userId as any).catch((e) => { + await this.createMenuLink(newRoleResult.roleId, createAuthRoleDto.menuList, guardInfo.userId as any).catch((e) => { this.logger.error(e.message + e.track.toString()); throw new HttpException('添加菜单关系出现错误,角色写入错误!', HttpStatus.INTERNAL_SERVER_ERROR); }); // ! 增加关联部门 if (createAuthRoleDto.deptScope == 5) { - await this.createDeptLink(newRoleResult.roleId, createAuthRoleDto.deptList, pacInfo.userId as any).catch((e) => { + await this.createDeptLink(newRoleResult.roleId, createAuthRoleDto.deptList, guardInfo.userId as any).catch((e) => { this.logger.error(e.message + e.track.toString()); throw new HttpException('添加部门数据范围关系出现错误,角色写入错误!', HttpStatus.INTERNAL_SERVER_ERROR); }); @@ -172,7 +172,7 @@ export class AuthRoleService { return await this.getRoleUser(roleId, getUserForRoleDto); } - public async update(roleId: string, updateAuthRoleDto: UpdateAuthRoleDto, pacInfo: PacInfoType) { + public async update(roleId: string, updateAuthRoleDto: UpdateAuthRoleDto, guardInfo: GuardInfo) { // ! 查找角色信息 const roleData = await this.getRoleForRoleId(roleId); @@ -182,7 +182,7 @@ export class AuthRoleService { } // ! 判断是否是root账户,非root账户无法设置为root - if (this.config.get('masterId') !== pacInfo.userId && isTrueEnum(roleData[0].root)) { + if (this.config.get('masterId') !== guardInfo.userId && isTrueEnum(roleData[0].root)) { throw new HttpException('没有权限创建原始角色!', HttpStatus.UNAUTHORIZED); } @@ -201,19 +201,19 @@ export class AuthRoleService { if (checkRepeat.length > 0 && checkRepeat[0].id != roleId) throw new HttpException('角色标识重复!', HttpStatus.CONFLICT); // ! 修改角色数据 - const result = await this.updateRole(roleId, updateAuthRoleDto, pacInfo.userId as any).catch((e) => { + const result = await this.updateRole(roleId, updateAuthRoleDto, guardInfo.userId as any).catch((e) => { this.logger.error(e.message + e.track.toString()); throw new HttpException('角色写入错误!', HttpStatus.INTERNAL_SERVER_ERROR); }); // ! 增加关联菜单 - await this.createMenuLink(roleData[0].roleId, updateAuthRoleDto.menuList, pacInfo.userId as any).catch((e) => { + await this.createMenuLink(roleData[0].roleId, updateAuthRoleDto.menuList, guardInfo.userId as any).catch((e) => { this.logger.error(e.message + e.track.toString()); throw new HttpException('添加菜单关系出现错误,角色写入错误!', HttpStatus.INTERNAL_SERVER_ERROR); }); // ! 增加关联部门 - await this.createDeptLink(roleData[0].roleId, updateAuthRoleDto.deptList, pacInfo.userId as any).catch((e) => { + await this.createDeptLink(roleData[0].roleId, updateAuthRoleDto.deptList, guardInfo.userId as any).catch((e) => { this.logger.error(e.message + e.track); throw new HttpException('添加部门数据范围关系出现错误,角色写入错误!', HttpStatus.INTERNAL_SERVER_ERROR); }); @@ -237,8 +237,8 @@ export class AuthRoleService { * DESC: 删除角色信息 * DATE: 2024-06-26 16:16:55 - * */ - public async remove(roleId: string, pacInfo: PacInfoType) { - return await this.deleteRole(roleId, pacInfo.userId as any); + public async remove(roleId: string, guardInfo: GuardInfo) { + return await this.deleteRole(roleId, guardInfo.userId as any); } /** Service @@ -246,8 +246,8 @@ export class AuthRoleService { * DESC: 关联账户给角色 * DATE: 2024-06-27 15:38:50 - * */ - public async linkUser(roleLinkUserDto: RoleLinkUserDto, pacInfo: PacInfoType) { - return this.linkUserForRole(roleLinkUserDto, pacInfo); + public async linkUser(roleLinkUserDto: RoleLinkUserDto, guardInfo: GuardInfo) { + return this.linkUserForRole(roleLinkUserDto, guardInfo); } /** Service @@ -660,7 +660,7 @@ export class AuthRoleService { } // DB 给角色关联上账户 - private async linkUserForRole(roleLinkUserDto: RoleLinkUserDto, pacInfo: PacInfoType) { + private async linkUserForRole(roleLinkUserDto: RoleLinkUserDto, guardInfo: GuardInfo) { // ! 去重账户ID const deduplicateUserId = Array.from(new Set(roleLinkUserDto.userIdList)); @@ -677,7 +677,7 @@ export class AuthRoleService { userIdList.map((i) => ({ roleId: roleLinkUserDto.roleId, userId: i, - createby: pacInfo.userId, + createby: guardInfo.userId, createtime: sql`now()` as any, })), ); diff --git a/src/application/auth-user/auth-user.controller.ts b/src/application/auth-user/auth-user.controller.ts index cbc64d3..dbc1c75 100644 --- a/src/application/auth-user/auth-user.controller.ts +++ b/src/application/auth-user/auth-user.controller.ts @@ -3,12 +3,12 @@ import { AuthUserService } from './auth-user.service'; import { CreateAuthUserDto } from './dto/create-auth-user.dto'; import { UpdateAuthUserDto } from './dto/update-auth-user.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { GetPacAuthUserAllDto } from '@app/auth-user/dto/get-auth-user.dto'; import { PasswordDto } from '@app/auth-user/dto/password.dto'; import { UpdateLinkDto } from '@app/auth-user/dto/updateLink.dto'; -import {UsernameSignInDto} from "@app/auth-user/dto/signin.dto"; +import { UsernameSignInDto } from '@app/auth-user/dto/signin.dto'; @ApiTags('账户服务') @Controller('authUser') @@ -21,8 +21,8 @@ export class AuthUserController { }) @ApiProduces('application/json') @Post() - create(@Body() createAuthUserDto: CreateAuthUserDto, @PacInfo() pacInfo: PacInfoType) { - return this.authUserService.create(createAuthUserDto, pacInfo); + create(@Body() createAuthUserDto: CreateAuthUserDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authUserService.create(createAuthUserDto, guardInfo); } @ApiOperation({ @@ -51,8 +51,8 @@ export class AuthUserController { }) @ApiProduces('application/json') @Patch(':id') - update(@Param('id') id: string, @Body() updateAuthUserDto: UpdateAuthUserDto, @PacInfo() pacInfo: PacInfoType) { - return this.authUserService.update(id, updateAuthUserDto, pacInfo); + update(@Param('id') id: string, @Body() updateAuthUserDto: UpdateAuthUserDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authUserService.update(id, updateAuthUserDto, guardInfo); } @ApiOperation({ @@ -61,8 +61,8 @@ export class AuthUserController { }) @ApiProduces('application/json') @Delete(':id') - remove(@Param('id') id: string, @PacInfo() pacInfo: PacInfoType) { - return this.authUserService.remove(id, pacInfo); + remove(@Param('id') id: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authUserService.remove(id, guardInfo); } @ApiOperation({ @@ -91,8 +91,8 @@ export class AuthUserController { }) @ApiProduces('application/json') @Patch('/role/:id') - updateLinkRole(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @PacInfo() pacInfo: PacInfoType) { - return this.authUserService.updateLinkRole(id, updateLinkDto, pacInfo); + updateLinkRole(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authUserService.updateLinkRole(id, updateLinkDto, guardInfo); } @ApiOperation({ @@ -101,8 +101,8 @@ export class AuthUserController { }) @ApiProduces('application/json') @Patch('/dept/:id') - updateLinkDept(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @PacInfo() pacInfo: PacInfoType) { - return this.authUserService.updateLinkDept(id, updateLinkDto, pacInfo); + updateLinkDept(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authUserService.updateLinkDept(id, updateLinkDto, guardInfo); } @ApiOperation({ @@ -111,8 +111,8 @@ export class AuthUserController { }) @ApiProduces('application/json') @Patch('/post/:id') - updateLinkPost(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @PacInfo() pacInfo: PacInfoType) { - return this.authUserService.updateLinkPost(id, updateLinkDto, pacInfo); + updateLinkPost(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.authUserService.updateLinkPost(id, updateLinkDto, guardInfo); } @ApiOperation({ @@ -120,8 +120,18 @@ export class AuthUserController { description: '登陆系统', }) @ApiProduces('application/json') - @Post('/signin') + @Post('/sign/in') signin(@Body() usernameSignInDto: UsernameSignInDto) { return this.authUserService.signin(usernameSignInDto); } + + @ApiOperation({ + summary: '登陆系统', + description: '登陆系统', + }) + @ApiProduces('application/json') + @Post('/sign/refresh') + refreshToken(@UserInfoDecorator() guardInfo: GuardInfo) { + return this.authUserService.refreshToken(guardInfo); + } } diff --git a/src/application/auth-user/auth-user.module.ts b/src/application/auth-user/auth-user.module.ts index f1ba91e..fad31f9 100644 --- a/src/application/auth-user/auth-user.module.ts +++ b/src/application/auth-user/auth-user.module.ts @@ -1,10 +1,9 @@ import { Module } from '@nestjs/common'; import { AuthUserService } from './auth-user.service'; import { AuthUserController } from './auth-user.controller'; -import { JwtService } from '@common/service/jwt/jwt.service'; @Module({ controllers: [AuthUserController], - providers: [AuthUserService, JwtService], + providers: [AuthUserService], }) export class AuthUserModule {} diff --git a/src/application/auth-user/auth-user.service.ts b/src/application/auth-user/auth-user.service.ts index a921de7..34c173a 100644 --- a/src/application/auth-user/auth-user.service.ts +++ b/src/application/auth-user/auth-user.service.ts @@ -1,7 +1,7 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { CreateAuthUserDto } from './dto/create-auth-user.dto'; import { UpdateAuthUserDto } from './dto/update-auth-user.dto'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; import { LoggerService } from '@service/logger/logger.service'; import { MysqlService } from '@common/service/mysql/mysql.service'; import { RedisService } from '@common/service/redis/redis.service'; @@ -31,6 +31,7 @@ import { UpdateLinkDto } from '@app/auth-user/dto/updateLink.dto'; import { UsernameSignInDto } from '@app/auth-user/dto/signin.dto'; import { JwtService } from '@common/service/jwt/jwt.service'; import MD5 from '@utils/MD5'; +import { KEY } from '@utils/key'; @Injectable() export class AuthUserService { @@ -79,7 +80,7 @@ export class AuthUserService { * DESC: 创建账户 * DATE: 2024-06-29 13:13:55 - * */ - public async create(createAuthUserDto: CreateAuthUserDto, pacInfo: PacInfoType) { + public async create(createAuthUserDto: CreateAuthUserDto, guardInfo: GuardInfo) { // ! 加目标锁,同级,而不是全局 const lock = await this.redisService.distributedLock('USER' + createAuthUserDto.username, createAuthUserDto.username); @@ -94,7 +95,7 @@ export class AuthUserService { if (result.length > 0) throw new HttpException('用户名重复!', HttpStatus.CONFLICT); // ! 添加账户数据 - const newPacCoreDict = await this.addUser(createAuthUserDto, pacInfo); + const newPacCoreDict = await this.addUser(createAuthUserDto, guardInfo); // ! 解锁 lock(); @@ -103,17 +104,17 @@ export class AuthUserService { // ! 关联角色 if (createAuthUserDto.roleList && createAuthUserDto.roleList.length > 0) { - insertList.push(this.updateUserRole(newPacCoreDict.userId as any, createAuthUserDto.roleList, pacInfo)); + insertList.push(this.updateUserRole(newPacCoreDict.userId as any, createAuthUserDto.roleList, guardInfo)); } // ! 关联部门 if (createAuthUserDto.deptList && createAuthUserDto.deptList.length > 0) { - insertList.push(this.updateUserDept(newPacCoreDict.userId as any, createAuthUserDto.deptList, pacInfo)); + insertList.push(this.updateUserDept(newPacCoreDict.userId as any, createAuthUserDto.deptList, guardInfo)); } // ! 关联岗位 if (createAuthUserDto.postList && createAuthUserDto.postList.length > 0) { - insertList.push(this.updateUserPost(newPacCoreDict.userId as any, createAuthUserDto.postList, pacInfo)); + insertList.push(this.updateUserPost(newPacCoreDict.userId as any, createAuthUserDto.postList, guardInfo)); } // ! 执行关联 @@ -165,8 +166,8 @@ export class AuthUserService { * DESC: 修改账户信息 * DATE: 2024-06-29 13:13:55 - * */ - public update(id: string, updateAuthUserDto: UpdateAuthUserDto, pacInfo: PacInfoType) { - return this.updateUser(id, updateAuthUserDto, pacInfo); + public update(id: string, updateAuthUserDto: UpdateAuthUserDto, guardInfo: GuardInfo) { + return this.updateUser(id, updateAuthUserDto, guardInfo); } /** Service @@ -174,8 +175,8 @@ export class AuthUserService { * DESC: 移除账户 * DATE: 2024-06-29 13:13:55 - * */ - public remove(id: string, pacInfo: PacInfoType) { - return this.deleteUser(id, pacInfo.userId as any); + public remove(id: string, guardInfo: GuardInfo) { + return this.deleteUser(id, guardInfo.userId as any); } /** Service @@ -210,10 +211,10 @@ export class AuthUserService { * DESC: 修改目标账户角色关联 * DATE: 2024-06-29 13:13:55 - * */ - public async updateLinkRole(id: string, updateLinkDto: UpdateLinkDto, pacInfo: PacInfoType) { + public async updateLinkRole(id: string, updateLinkDto: UpdateLinkDto, guardInfo: GuardInfo) { await this.checkUserExist(id); if (updateLinkDto) { - return this.updateUserRole(id, updateLinkDto.list, pacInfo); + return this.updateUserRole(id, updateLinkDto.list, guardInfo); } else { return; } @@ -224,10 +225,10 @@ export class AuthUserService { * DESC: 修改目标账户部门关联 * DATE: 2024-06-29 13:13:55 - * */ - public async updateLinkDept(id: string, updateLinkDto: UpdateLinkDto, pacInfo: PacInfoType) { + public async updateLinkDept(id: string, updateLinkDto: UpdateLinkDto, guardInfo: GuardInfo) { await this.checkUserExist(id); if (updateLinkDto) { - return this.updateUserDept(id, updateLinkDto.list, pacInfo); + return this.updateUserDept(id, updateLinkDto.list, guardInfo); } else { return; } @@ -238,10 +239,10 @@ export class AuthUserService { * DESC: 修改目标账户岗位关联 * DATE: 2024-06-29 13:13:55 - * */ - public async updateLinkPost(id: string, updateLinkDto: UpdateLinkDto, pacInfo: PacInfoType) { + public async updateLinkPost(id: string, updateLinkDto: UpdateLinkDto, guardInfo: GuardInfo) { await this.checkUserExist(id); if (updateLinkDto) { - return this.updateUserPost(id, updateLinkDto.list, pacInfo); + return this.updateUserPost(id, updateLinkDto.list, guardInfo); } else { return; } @@ -249,14 +250,27 @@ export class AuthUserService { /** Service * NAME: updateLinkPost - * DESC: 修改目标账户岗位关联 + * DESC: 登录 * DATE: 2024-06-29 13:13:55 - * */ public async signin(usernameSignInDto: UsernameSignInDto) { - // 登陆检测 + // 登录检测 return await this.signinDetection(usernameSignInDto); } + /** Service + * NAME: refreshToken + * DESC: 刷新Token + * DATE: 2024-06-29 13:13:55 - + * */ + public async refreshToken(guardInfo: GuardInfo) { + const token = this.jwt.token({ type: 'token', username: guardInfo.username, userId: guardInfo.userId, timestamp: new Date().getTime() }); + await this.redisService.redis.set(KEY.REDIS_TOKEN + guardInfo.userId + '-' + MD5(token), 0, { + EX: this.config.get('system.signin.tokenTime'), + }); + return { token }; + } + // DB 同级查重 private checkRepeatForUsername(username: string) { return this.mysqlService.db @@ -278,7 +292,7 @@ export class AuthUserService { } // DB 添加账户 - private async addUser(createAuthUserDto: CreateAuthUserDto, pacInfo: PacInfoType) { + private async addUser(createAuthUserDto: CreateAuthUserDto, guardInfo: GuardInfo) { // ! 生成雪花id,用于账户id const id = await this.snowflake.generate(); @@ -309,7 +323,7 @@ export class AuthUserService { avatar: createAuthUserDto.avatar, userPhone: createAuthUserDto.userPhone, userDesc: createAuthUserDto.userDesc, - createby: pacInfo.userId as any, + createby: guardInfo.userId as any, createtime: sql`now()` as any, }; return { @@ -324,7 +338,7 @@ export class AuthUserService { } // COMMON 向目标表插入列 - private async insertKeyValueForUserLink(table, list, key, userId, pacInfo: PacInfoType) { + private async insertKeyValueForUserLink(table, list, key, userId, guardInfo: GuardInfo) { // ! 清空曾经的关联 await this.mysqlService.db.delete(table).where(eq(table.userId as any, userId)); @@ -336,25 +350,25 @@ export class AuthUserService { arr.map((i) => ({ userId: userId, [key]: i, - createby: pacInfo.userId as any, + createby: guardInfo.userId as any, createtime: sql`now()` as any, })), ); } // DB 修改用户角色 - private async updateUserRole(userId: string, roleIdList: string[], pacInfo: PacInfoType) { - return await this.insertKeyValueForUserLink(pacAuthLinkUserRole, roleIdList, 'roleId', userId, pacInfo); + private async updateUserRole(userId: string, roleIdList: string[], guardInfo: GuardInfo) { + return await this.insertKeyValueForUserLink(pacAuthLinkUserRole, roleIdList, 'roleId', userId, guardInfo); } // DB 修改账户部门 - private async updateUserDept(userId: string, deptIdList: string[], pacInfo: PacInfoType) { - return await this.insertKeyValueForUserLink(pacAuthLinkUserDept, deptIdList, 'deptId', userId, pacInfo); + private async updateUserDept(userId: string, deptIdList: string[], guardInfo: GuardInfo) { + return await this.insertKeyValueForUserLink(pacAuthLinkUserDept, deptIdList, 'deptId', userId, guardInfo); } // DB修改账户岗位 - private async updateUserPost(userId: string, postIdList: string[], pacInfo: PacInfoType) { - return await this.insertKeyValueForUserLink(pacAuthLinkUserPost, postIdList, 'postId', userId, pacInfo); + private async updateUserPost(userId: string, postIdList: string[], guardInfo: GuardInfo) { + return await this.insertKeyValueForUserLink(pacAuthLinkUserPost, postIdList, 'postId', userId, guardInfo); } // 查询构建器 @@ -561,7 +575,7 @@ export class AuthUserService { } // DB 更新账户 - private async updateUser(id: string, updateAuthUserDto: UpdateAuthUserDto, pacInfo: PacInfoType) { + private async updateUser(id: string, updateAuthUserDto: UpdateAuthUserDto, guardInfo: GuardInfo) { const user = await this.mysqlService.db .select({ id: pacAuthUser.userId, pid: pacAuthUser.pid }) .from(pacAuthUser) @@ -571,13 +585,13 @@ export class AuthUserService { // 用户名不修改不需要查重 if (updateAuthUserDto.roleList) { - await this.updateUserRole(id, updateAuthUserDto.roleList, pacInfo); + await this.updateUserRole(id, updateAuthUserDto.roleList, guardInfo); } if (updateAuthUserDto.deptList) { - await this.updateUserDept(id, updateAuthUserDto.deptList, pacInfo); + await this.updateUserDept(id, updateAuthUserDto.deptList, guardInfo); } if (updateAuthUserDto.postList) { - await this.updateUserPost(id, updateAuthUserDto.postList, pacInfo); + await this.updateUserPost(id, updateAuthUserDto.postList, guardInfo); } return await this.mysqlService.db @@ -590,7 +604,7 @@ export class AuthUserService { userPhone: updateAuthUserDto.userPhone, userDesc: updateAuthUserDto.userDesc, status: updateAuthUserDto.status, - updateby: pacInfo.userId, + updateby: guardInfo.userId, updatetime: sql`now()`, }) .where(eq(pacAuthUser.userId, id)); @@ -634,7 +648,7 @@ export class AuthUserService { return user[0]; } - // DB 登陆检测 + // DB 登录检测 private async signinDetection(usernameSignInDto: UsernameSignInDto) { const user = await this.mysqlService.db .select({ userId: pacAuthUser.userId, pid: pacAuthUser.pid, password: pacAuthUser.password }) @@ -642,50 +656,79 @@ export class AuthUserService { .where(and(isNull(pacAuthUser.deleteby), eq(pacAuthUser.username, usernameSignInDto.username))); if (user.length == 0) throw new HttpException('该用户不存在!', HttpStatus.BAD_REQUEST); - // ! 判断是否超过最大登录次数 - const number = await this.redisService.get('SIGNIN_NUM' + user[0].userId); - let maxNumberFieldsigninForRedis = (await this.redisService.get('CONFIG_MAX_NUMBER_FIELD_SIGNIN')) as any; - if (!maxNumberFieldsigninForRedis) { - maxNumberFieldsigninForRedis = this.config.get('system.signin.maxNumberFieldsignin'); - } - if (Number(number) >= maxNumberFieldsigninForRedis) { + // ! 当前账户的userID + const userId = user[0].userId; + + // ! 当前账户的密码 + const password = user[0].password; + + // ? 判断是否超过最大错误登录次数 + // ! 获取当前用户已经登录失败的次数 + const number = await this.redisService.get(KEY.REDIS_FIELD_SIGNIN_NUM + userId); + + // ! 从Redis获取系统允许的最大错误次数 + let maxField = (await this.redisService.get(KEY.REDIS_MAX_FIELD_SIGNIN_NUM)) as any; + + // ? 判断Redis中是否有存储 || 如果不存在,从配置文件取 + maxField = maxField ? maxField : this.config.get('system.signin.maxNumberFieldsignin'); + + // ? 如果当前账户已经错误登录多次,抛出错误 + if (Number(number) >= maxField) { throw new HttpException(`登录错误次数过多:${number}次!`, HttpStatus.BAD_REQUEST); } // ! 验证密码 - const pass = cryptoPassword(usernameSignInDto.password, this.config.get('system.passwordSalt')); - if (pass != user[0].password) { - let maxTimeFieldsignin = (await this.redisService.get('CONFIG_MAX_TIME_FIELD_SIGNIN')) as any; - if (!maxTimeFieldsignin) { - maxTimeFieldsignin = this.config.get('system.signin.maxTimeFieldsignin'); - } - await this.redisService.redis.SET('SIGNIN_NUM' + user[0].userId, Number(number) ? Number(number) + 1 : 1, { - PX: maxTimeFieldsignin, + // ! 加密登录时的密码 + const nowPassword = cryptoPassword(usernameSignInDto.password, this.config.get('system.passwordSalt')); + + // ! 如果登录密码和设置的密码不匹配 + if (nowPassword != password) { + // ! 从Redis获取冷却时间,(超过最大登陆错误次数后的等待时间) + let waitTime = (await this.redisService.get(KEY.REDIS_WAITING_SIGNIN_TIME)) as any; + + // ? 如果Redis中没有,从环境变量取 + waitTime = waitTime ? waitTime : this.config.get('system.signin.maxTimeFieldsignin'); + + // ? 将Redis中的错误次数加1 + await this.redisService.redis.SET(KEY.REDIS_FIELD_SIGNIN_NUM + userId, Number(number) ? Number(number) + 1 : 1, { + PX: waitTime, }); throw new HttpException(`用户名或密码错误:${Number(number) + 1}次!`, HttpStatus.BAD_REQUEST); } // ! 判断是否是最大登录数 - const clientList = await this.redisService.redis.keys('CLIENT-' + user[0].userId + '-*'); - let maxSigninClient = (await this.redisService.get('CONFIG_MAX_SIGNIN_CLIENT')) as any; - if (!maxSigninClient) { - maxSigninClient = this.config.get('system.signin.maxSigninClient'); - } - console.log(maxSigninClient, clientList.length >= maxSigninClient) - if (clientList.length >= maxSigninClient) { - throw new HttpException('已登陆的客户端超过限制!', HttpStatus.BAD_REQUEST); + // ! 从Redis中获取当前客户端数量,以长Token为准 + const clientList = await this.redisService.redis.keys(KEY.REDIS_REFRESH_TOKEN + userId + '-*'); + + // ! 从Redis获取允许的最大客户端数量 + let maxClient = (await this.redisService.get(KEY.REDIS_MAX_CLIENT)) as any; + + // ? 如果不存在从配置文件取 + maxClient = maxClient ? maxClient : this.config.get('system.signin.maxSigninClient'); + + // ? 判断当前账户登录数是否超过最大登录数 + if (clientList.length >= maxClient) { + throw new HttpException('已登录的客户端超过限制!', HttpStatus.BAD_REQUEST); } // ! 签发Token - const token = this.jwt.token({ username: usernameSignInDto.username, userId: user[0].userId, timestamp: new Date().getTime() }); - const refreshToken = this.jwt.refreshToken({ username: usernameSignInDto.username, userId: user[0].userId, timestamp: new Date().getTime() }); + // ! 长期Token refreshToken,只用于刷新Token + const refreshToken = this.jwt.refreshToken({ + type: 'refreshToken', + username: usernameSignInDto.username, + userId, + timestamp: new Date().getTime(), + }); + + // ! 短期Token token,用于各种业务请求 + const token = this.jwt.token({ type: 'token', username: usernameSignInDto.username, userId, timestamp: new Date().getTime() }); - // 将登陆的账户放进Redis - await this.redisService.redis.set('CLIENT-' + user[0].userId + '-' + MD5(refreshToken), 0, { + // ! 将登录的账户放进Redis + await this.redisService.redis.set(KEY.REDIS_REFRESH_TOKEN + userId + '-' + MD5(refreshToken), 0, { EX: this.config.get('system.signin.refreshTokenTime'), }); - await this.redisService.redis.set('CLIENT-ONLINE-' + user[0].userId + '-' + MD5(token), 0, { - EX: this.config.get('system.signin.refreshTokenTime'), + await this.redisService.redis.set(KEY.REDIS_TOKEN + userId + '-' + MD5(token), 0, { + EX: this.config.get('system.signin.tokenTime'), }); return { diff --git a/src/application/core-dict/core-dict.controller.ts b/src/application/core-dict/core-dict.controller.ts index 37e1935..85b98bf 100644 --- a/src/application/core-dict/core-dict.controller.ts +++ b/src/application/core-dict/core-dict.controller.ts @@ -3,8 +3,8 @@ import { CoreDictService } from './core-dict.service'; import { CreateCoreDictDto } from './dto/create-core-dict.dto'; import { UpdateCoreDictDto } from './dto/update-core-dict.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { GetPacCoreDictAllDto, PacCoreDictTargetListDto } from '@app/core-dict/dto/get-core-dict.dto'; @ApiTags('字典服务') @@ -18,8 +18,8 @@ export class CoreDictController { }) @ApiProduces('application/json') @Post() - create(@Body() createCoreDictDto: CreateCoreDictDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreDictService.create(createCoreDictDto, pacInfo); + create(@Body() createCoreDictDto: CreateCoreDictDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreDictService.create(createCoreDictDto, guardInfo); } @ApiOperation({ @@ -28,7 +28,7 @@ export class CoreDictController { }) @ApiProduces('application/json') @Get() - findAll(@Query() getCoreDictAllDto: GetPacCoreDictAllDto, @PacInfo() pacInfo: PacInfoType) { + findAll(@Query() getCoreDictAllDto: GetPacCoreDictAllDto, @UserInfoDecorator() guardInfo: GuardInfo) { return this.coreDictService.findAll(getCoreDictAllDto); } @@ -58,8 +58,8 @@ export class CoreDictController { }) @ApiProduces('application/json') @Patch(':dictId') - update(@Param('dictId') dictId: string, @Body() updateCoreDictDto: UpdateCoreDictDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreDictService.update(dictId, updateCoreDictDto, pacInfo); + update(@Param('dictId') dictId: string, @Body() updateCoreDictDto: UpdateCoreDictDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreDictService.update(dictId, updateCoreDictDto, guardInfo); } @ApiOperation({ @@ -68,7 +68,7 @@ export class CoreDictController { }) @ApiProduces('application/json') @Delete(':dictId') - remove(@Param('dictId') dictId: string, @PacInfo() pacInfo: PacInfoType) { - return this.coreDictService.remove(dictId, pacInfo); + remove(@Param('dictId') dictId: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreDictService.remove(dictId, guardInfo); } } diff --git a/src/application/core-dict/core-dict.service.ts b/src/application/core-dict/core-dict.service.ts index 5e9e92b..5e5aab3 100644 --- a/src/application/core-dict/core-dict.service.ts +++ b/src/application/core-dict/core-dict.service.ts @@ -11,7 +11,7 @@ import { GetPacCoreDictAllDto, PacCoreDictTargetListDto } from '@app/core-dict/d import { ConfigService } from '@nestjs/config'; import { likeQuery } from '@utils/likeQuery'; import { alias, QueryBuilder } from 'drizzle-orm/mysql-core'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; import { isTrueEnum, isExistKey } from '@utils/boolean.enum'; import { customDrizzleRowWithRecursive } from '@utils/customDrizzleRowWithRecursive'; @@ -63,9 +63,9 @@ export class CoreDictService { * DESC: 创建字典内容 * DATE: 2024-05-31 19:12:47 - * */ - public async create(createCoreDictDto: CreateCoreDictDto, pacInfo: PacInfoType) { + public async create(createCoreDictDto: CreateCoreDictDto, guardInfo: GuardInfo) { // ! 判断是否是root账户,非root账户无法设置为root - if (this.config.get('masterId') !== pacInfo.userId && isTrueEnum(createCoreDictDto.root)) { + if (this.config.get('masterId') !== guardInfo.userId && isTrueEnum(createCoreDictDto.root)) { throw new HttpException('没有权限创建原始字典!', HttpStatus.UNAUTHORIZED); } @@ -84,7 +84,7 @@ export class CoreDictService { if (result.length > 0) throw new HttpException('字典标识重复!', HttpStatus.CONFLICT); // ! 添加字典数据 - const newPacCoreDict = await this.addDictData(createCoreDictDto, pacInfo.userId); + const newPacCoreDict = await this.addDictData(createCoreDictDto, guardInfo.userId); // ! 解锁 lock(); @@ -145,9 +145,9 @@ export class CoreDictService { * DESC: 更新字典 * DATE: 2024-06-04 23:24:18 - * */ - public async update(dictId: string, updateCoreDictDto: UpdateCoreDictDto, pacInfo: PacInfoType) { + public async update(dictId: string, updateCoreDictDto: UpdateCoreDictDto, guardInfo: GuardInfo) { // ! 判断是否是root账户,非root账户无法设置为root - if (this.config.get('masterId') !== pacInfo.userId && updateCoreDictDto.root !== undefined) { + if (this.config.get('masterId') !== guardInfo.userId && updateCoreDictDto.root !== undefined) { throw new HttpException('没有权限修改原始字典!', HttpStatus.UNAUTHORIZED); } @@ -156,7 +156,7 @@ export class CoreDictService { if (oldDict.length == 0) throw new HttpException('未找到目标字典,无法修改!', HttpStatus.BAD_REQUEST); // ! root数据,非root用户不允许修改 - if (oldDict[0].root && this.config.get('masterId') !== pacInfo.userId) { + if (oldDict[0].root && this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('原始字典,权限不足无法修改!', HttpStatus.BAD_REQUEST); } @@ -177,7 +177,7 @@ export class CoreDictService { } // ! 更新数据 - const result = await this.updateDictData(dictId, updateCoreDictDto, pacInfo); + const result = await this.updateDictData(dictId, updateCoreDictDto, guardInfo); // ! 解锁 lock(); @@ -198,7 +198,7 @@ export class CoreDictService { * DESC: 删除字典 * DATE: 2024-06-04 22:01:11 - * */ - public async remove(dictId: string, pacInfo: PacInfoType) { + public async remove(dictId: string, guardInfo: GuardInfo) { // ! 查看目标字典项 const result = await this.getMore(dictId); @@ -208,7 +208,7 @@ export class CoreDictService { } // ! root数据,非root用户不允许删除 - if (result[0].root && this.config.get('masterId') !== pacInfo.userId) { + if (result[0].root && this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('原始字典,权限不足无法删除!', HttpStatus.BAD_REQUEST); } @@ -217,7 +217,7 @@ export class CoreDictService { // ? 判断是否存在子项 if (result[0].haveChildren == 0) { // ! 删除字典 - await this.deleteDictItem(dictId, pacInfo); + await this.deleteDictItem(dictId, guardInfo); } else { throw new HttpException('该字典存在子项!', HttpStatus.BAD_REQUEST); } @@ -409,18 +409,18 @@ export class CoreDictService { } // DB 通过ID删除字典项 - private deleteDictItem(dictId: string, pacInfo: PacInfoType) { + private deleteDictItem(dictId: string, guardInfo: GuardInfo) { return this.mysqlService.db .update(pacCoreDict) .set({ deletetime: sql`now()`, - deleteby: pacInfo.userId, + deleteby: guardInfo.userId, }) .where(eq(pacCoreDict.dictId, dictId)); } // DB 更新字典 - private updateDictData(dictId: string, updateCoreDictDto: UpdateCoreDictDto, pacInfo: PacInfoType) { + private updateDictData(dictId: string, updateCoreDictDto: UpdateCoreDictDto, guardInfo: GuardInfo) { return this.mysqlService.db .update(pacCoreDict) .set({ @@ -433,7 +433,7 @@ export class CoreDictService { status: updateCoreDictDto.status, root: isTrueEnum(updateCoreDictDto.root) ? 1 : 0, serviceKey: updateCoreDictDto.serviceKey, - updateby: pacInfo.userId, + updateby: guardInfo.userId, updatetime: sql`now()`, }) .where(eq(pacCoreDict.dictId, dictId)); diff --git a/src/application/core-env/core-env.controller.ts b/src/application/core-env/core-env.controller.ts index ddff32d..c85ed18 100644 --- a/src/application/core-env/core-env.controller.ts +++ b/src/application/core-env/core-env.controller.ts @@ -3,8 +3,8 @@ import { CoreEnvService } from './core-env.service'; import { CreateCoreEnvDto } from './dto/create-core-env.dto'; import { UpdateCoreEnvDto } from './dto/update-core-env.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { CoreEnvKeyDTO, CoreEnvTargetListDTO, GetCoreEnvDTO } from '@app/core-env/dto/get-core-env.dto'; @ApiTags('环境变量服务') @@ -18,8 +18,8 @@ export class CoreEnvController { }) @ApiProduces('application/json') @Post() - create(@Body() createCoreEnvDto: CreateCoreEnvDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreEnvService.create(createCoreEnvDto, pacInfo); + create(@Body() createCoreEnvDto: CreateCoreEnvDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreEnvService.create(createCoreEnvDto, guardInfo); } @ApiOperation({ @@ -28,7 +28,7 @@ export class CoreEnvController { }) @ApiProduces('application/json') @Get() - findAll(@Query() getCoreEnvDTO: GetCoreEnvDTO, @PacInfo() pacInfo: PacInfoType) { + findAll(@Query() getCoreEnvDTO: GetCoreEnvDTO, @UserInfoDecorator() guardInfo: GuardInfo) { return this.coreEnvService.findAll(getCoreEnvDTO); } @@ -58,8 +58,8 @@ export class CoreEnvController { }) @ApiProduces('application/json') @Patch(':envId') - update(@Param('envId') envId: string, @Body() updateCoreEnvDto: UpdateCoreEnvDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreEnvService.update(envId, updateCoreEnvDto, pacInfo); + update(@Param('envId') envId: string, @Body() updateCoreEnvDto: UpdateCoreEnvDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreEnvService.update(envId, updateCoreEnvDto, guardInfo); } @ApiOperation({ @@ -68,7 +68,7 @@ export class CoreEnvController { }) @ApiProduces('application/json') @Delete(':envId') - remove(@Param('envId') envId: string, @PacInfo() pacInfo: PacInfoType) { - return this.coreEnvService.remove(envId, pacInfo); + remove(@Param('envId') envId: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreEnvService.remove(envId, guardInfo); } } diff --git a/src/application/core-env/core-env.service.ts b/src/application/core-env/core-env.service.ts index 738c163..75e8936 100644 --- a/src/application/core-env/core-env.service.ts +++ b/src/application/core-env/core-env.service.ts @@ -13,7 +13,7 @@ import { CoreEnvKeyDTO, CoreEnvTargetListDTO, GetCoreEnvDTO } from '@app/core-en import { likeQuery } from '@utils/likeQuery'; import { QueryBuilder, alias } from 'drizzle-orm/mysql-core'; import { customDrizzleRowWithRecursive } from '@utils/customDrizzleRowWithRecursive'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; @Injectable() export class CoreEnvService { @@ -70,9 +70,9 @@ export class CoreEnvService { * DESC: 创建环境变量内容 * DATE: 2024-06-05 11:48:04 - * */ - public async create(createCoreEnvDto: CreateCoreEnvDto, pacInfo: PacInfoType) { + public async create(createCoreEnvDto: CreateCoreEnvDto, guardInfo: GuardInfo) { // ! 判断是否是root账户,非root账户无法设置为root - if (this.config.get('masterId') !== pacInfo.userId && isTrueEnum(createCoreEnvDto.root)) { + if (this.config.get('masterId') !== guardInfo.userId && isTrueEnum(createCoreEnvDto.root)) { throw new HttpException('没有权限创建原始变量!', HttpStatus.UNAUTHORIZED); } @@ -91,7 +91,7 @@ export class CoreEnvService { if (result.length > 0) throw new HttpException('环境变量标识重复!', HttpStatus.CONFLICT); // ! 添加环境变量数据 - const newPacCoreEnv = await this.addEnvData(createCoreEnvDto, pacInfo); + const newPacCoreEnv = await this.addEnvData(createCoreEnvDto, guardInfo); // ! 解锁 lock(); @@ -145,9 +145,9 @@ export class CoreEnvService { return result; } - public async update(envId: string, updateCoreEnvDto: UpdateCoreEnvDto, pacInfo: PacInfoType) { + public async update(envId: string, updateCoreEnvDto: UpdateCoreEnvDto, guardInfo: GuardInfo) { // ! 判断是否是root账户,非root账户无法设置为root - if (this.config.get('masterId') !== pacInfo.userId && updateCoreEnvDto.root !== undefined) { + if (this.config.get('masterId') !== guardInfo.userId && updateCoreEnvDto.root !== undefined) { throw new HttpException('没有权限修改原始字典!', HttpStatus.UNAUTHORIZED); } @@ -158,7 +158,7 @@ export class CoreEnvService { } // ! root数据,非root用户不允许修改 - if (oldEnv[0].root && this.config.get('masterId') !== pacInfo.userId) { + if (oldEnv[0].root && this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('原始变量,权限不足无法修改!', HttpStatus.BAD_REQUEST); } @@ -179,7 +179,7 @@ export class CoreEnvService { } // ! 更新数据 - const result = await this.updateEnvData(envId, updateCoreEnvDto, pacInfo); + const result = await this.updateEnvData(envId, updateCoreEnvDto, guardInfo); // ! 解锁 lock(); @@ -200,14 +200,14 @@ export class CoreEnvService { * DESC: 删除环境变量 * DATE: 2024-06-05 17:17:28 - * */ - public async remove(envId: string, pacInfo: PacInfoType) { + public async remove(envId: string, guardInfo: GuardInfo) { // ! 查看目标环境变量 const result = await this.getMore(envId); // ? 判断是否存在 if (result.length > 0) { // ! root数据,非root用户不允许删除 - if (result[0].root && this.config.get('masterId') !== pacInfo.userId) { + if (result[0].root && this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('原始变量,权限不足无法删除!', HttpStatus.BAD_REQUEST); } @@ -216,7 +216,7 @@ export class CoreEnvService { // ? 判断是否存在子项 if (result[0].haveChildren == 0) { // ! 删除目标环境变量 - await this.deleteEnvItem(envId, pacInfo); + await this.deleteEnvItem(envId, guardInfo); } else { throw new HttpException('目标环境变量存在子项!', HttpStatus.BAD_REQUEST); } @@ -424,18 +424,18 @@ export class CoreEnvService { } // DB 通过ID删除Env - private deleteEnvItem(envId: string, pacInfo: PacInfoType) { + private deleteEnvItem(envId: string, guardInfo: GuardInfo) { return this.mysqlService.db .update(pacCoreEnv) .set({ deletetime: sql`now()`, - deleteby: pacInfo.userId, + deleteby: guardInfo.userId, }) .where(eq(pacCoreEnv.envId, envId)); } // DB 更新Env - private updateEnvData(envId: string, updateCoreEnvDto: UpdateCoreEnvDto, pacInfo: PacInfoType) { + private updateEnvData(envId: string, updateCoreEnvDto: UpdateCoreEnvDto, guardInfo: GuardInfo) { return this.mysqlService.db .update(pacCoreEnv) .set({ @@ -448,7 +448,7 @@ export class CoreEnvService { orderNum: updateCoreEnvDto.orderNum, status: updateCoreEnvDto.status, serviceKey: updateCoreEnvDto.serviceKey, - updateby: pacInfo.userId, + updateby: guardInfo.userId, updatetime: sql`now()`, }) .where(eq(pacCoreEnv.envId, envId)); diff --git a/src/application/core-menu/core-menu.controller.ts b/src/application/core-menu/core-menu.controller.ts index b924350..64ea5be 100644 --- a/src/application/core-menu/core-menu.controller.ts +++ b/src/application/core-menu/core-menu.controller.ts @@ -3,8 +3,8 @@ import { CoreMenuService } from './core-menu.service'; import { CreateCoreMenuDto } from './dto/create-core-menu.dto'; import { UpdateCoreMenuDto } from './dto/update-core-menu.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { GetPacCoreMenuAllDto } from '@app/core-menu/dto/get-core-menu.dto'; @ApiTags('菜单服务') @@ -18,8 +18,8 @@ export class CoreMenuController { }) @ApiProduces('application/json') @Post() - create(@Body() createCoreMenuDto: CreateCoreMenuDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreMenuService.create(createCoreMenuDto, pacInfo); + create(@Body() createCoreMenuDto: CreateCoreMenuDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreMenuService.create(createCoreMenuDto, guardInfo); } @ApiOperation({ @@ -28,8 +28,8 @@ export class CoreMenuController { }) @ApiProduces('application/json') @Get() - findAll(@Query() getPacCoreMenuAllDto: GetPacCoreMenuAllDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreMenuService.findAll(getPacCoreMenuAllDto, pacInfo); + findAll(@Query() getPacCoreMenuAllDto: GetPacCoreMenuAllDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreMenuService.findAll(getPacCoreMenuAllDto, guardInfo); } @ApiOperation({ @@ -38,8 +38,8 @@ export class CoreMenuController { }) @ApiProduces('application/json') @Patch(':menuId') - update(@Param('menuId') id: string, @Body() updateCoreMenuDto: UpdateCoreMenuDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreMenuService.update(id, updateCoreMenuDto, pacInfo); + update(@Param('menuId') id: string, @Body() updateCoreMenuDto: UpdateCoreMenuDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreMenuService.update(id, updateCoreMenuDto, guardInfo); } @ApiOperation({ @@ -48,7 +48,7 @@ export class CoreMenuController { }) @ApiProduces('application/json') @Delete(':menuId') - remove(@Param('menuId') id: string, @PacInfo() pacInfo: PacInfoType) { - return this.coreMenuService.remove(id, pacInfo); + remove(@Param('menuId') id: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreMenuService.remove(id, guardInfo); } } diff --git a/src/application/core-menu/core-menu.service.ts b/src/application/core-menu/core-menu.service.ts index 0647e6b..93f2903 100644 --- a/src/application/core-menu/core-menu.service.ts +++ b/src/application/core-menu/core-menu.service.ts @@ -6,7 +6,7 @@ import { MysqlService } from '@common/service/mysql/mysql.service'; import { RedisService } from '@common/service/redis/redis.service'; import { Snowflake } from '@service/snowflake/snowflake.service'; import { ConfigService } from '@nestjs/config'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; import { pacAuthUser, pacCoreDict, pacCoreMenu, pacCoreService } from '@entities/schema'; import { eq, sql, isNull, asc, desc, or, like, and } from 'drizzle-orm'; import { isExistKey, isTrueEnum } from '@utils/boolean.enum'; @@ -77,16 +77,16 @@ export class CoreMenuService { * DESC: 创建菜单内容 * DATE: 2024-06-22 17:57:15 - * */ - public async create(createCoreMenuDto: CreateCoreMenuDto, pacInfo: PacInfoType) { + public async create(createCoreMenuDto: CreateCoreMenuDto, guardInfo: GuardInfo) { // ! 加目标锁,允许同名,所以就不加锁了 // ? 判断是不是pac,不是的话直接退出 - if (this.config.get('masterId') !== pacInfo.userId) { + if (this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('没有权限添加菜单!', HttpStatus.UNAUTHORIZED); } // ! 执行写入 - const newPacCoreMenu = await this.addMenuData(createCoreMenuDto, pacInfo); + const newPacCoreMenu = await this.addMenuData(createCoreMenuDto, guardInfo); // ? 判断是否存在pid,对pid的haveChildren进行变化 await this.haveChildrenSelfIncreasing(createCoreMenuDto.pid); @@ -98,29 +98,29 @@ export class CoreMenuService { * DESC: 获取菜单列表/分页 * DATE: 2024-06-22 18:21:57 - * */ - public async findAll(getPacCoreMenuAllDto: GetPacCoreMenuAllDto, pacInfo: PacInfoType) { + public async findAll(getPacCoreMenuAllDto: GetPacCoreMenuAllDto, guardInfo: GuardInfo) { // ? 是否查询列表 if (isExistKey(getPacCoreMenuAllDto, 'isList') && isTrueEnum(getPacCoreMenuAllDto['isList'])) { // ! 返回列表数据 - return await this.getMenuList(getPacCoreMenuAllDto, pacInfo); + return await this.getMenuList(getPacCoreMenuAllDto, guardInfo); } else { // ! 返回分页数据 - return await this.getMenuPage(getPacCoreMenuAllDto, pacInfo); + return await this.getMenuPage(getPacCoreMenuAllDto, guardInfo); } } - public update(id: string, updateCoreMenuDto: UpdateCoreMenuDto, pacInfo: PacInfoType) { + public update(id: string, updateCoreMenuDto: UpdateCoreMenuDto, guardInfo: GuardInfo) { // ! 比较权限 - if (this.config.get('masterId') !== pacInfo.userId) { + if (this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('没有权限删除菜单!', HttpStatus.UNAUTHORIZED); } // ! 写入数据 } - public async remove(id: string, pacInfo: PacInfoType) { + public async remove(id: string, guardInfo: GuardInfo) { // ! 比较权限 - if (this.config.get('masterId') !== pacInfo.userId) { + if (this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('没有权限删除菜单!', HttpStatus.UNAUTHORIZED); } @@ -131,7 +131,7 @@ export class CoreMenuService { } // ! 执行删除 - await this.deleteMenuItem(id, pacInfo); + await this.deleteMenuItem(id, guardInfo); // ! 更改发节点的子节点数 if (result[0].pid != 0) { @@ -142,7 +142,7 @@ export class CoreMenuService { } // DB 增加菜单 - async addMenuData(createCoreMenuDto: CreateCoreMenuDto, pacInfo: PacInfoType) { + async addMenuData(createCoreMenuDto: CreateCoreMenuDto, guardInfo: GuardInfo) { // ! 生成雪花id,用于字典主键 const id = await this.snowflake.generate(); @@ -161,7 +161,7 @@ export class CoreMenuService { isActivate: isTrueEnum(createCoreMenuDto.isActivate) ? 0 : 1, orderNum: createCoreMenuDto.orderNum, serviceKey: createCoreMenuDto.serviceKey, - createby: pacInfo.userId, + createby: guardInfo.userId, createtime: sql`now()` as any, }; @@ -179,7 +179,7 @@ export class CoreMenuService { } // DB 查菜单数据 - private getMenuData(data: GetPacCoreMenuAllDto, pacInfo: PacInfoType, selectData = undefined) { + private getMenuData(data: GetPacCoreMenuAllDto, guardInfo: GuardInfo, selectData = undefined) { // ! 定义基础查询函数 // 启用动态查询模式 $dynamic const query = this.mysqlService.db @@ -223,7 +223,7 @@ export class CoreMenuService { wl.push(eq(pacCoreMenu.status, data.status as any).if(isExistKey(data, 'status'))); // ? 判断是否是pac查的 - if (this.config.get('masterId') === pacInfo.userId) { + if (this.config.get('masterId') === guardInfo.userId) { // ? 是否要按照激活查 if (isExistKey(data, 'isActivate')) { wl.push(eq(pacCoreMenu.isActivate, isTrueEnum(data['isActivate']) ? 0 : 1)); @@ -238,23 +238,23 @@ export class CoreMenuService { } // DB 查列表数据 - private getMenuList(getMenuData: GetPacCoreMenuAllDto, pacInfo: PacInfoType) { - return this.getMenuData(getMenuData, pacInfo, this.menuListDataType); + private getMenuList(getMenuData: GetPacCoreMenuAllDto, guardInfo: GuardInfo) { + return this.getMenuData(getMenuData, guardInfo, this.menuListDataType); } // DB查分页数据 - private async getMenuPage(getPacCoreMenuAllDto: GetPacCoreMenuAllDto, pacInfo: PacInfoType) { + private async getMenuPage(getPacCoreMenuAllDto: GetPacCoreMenuAllDto, guardInfo: GuardInfo) { const offset = (getPacCoreMenuAllDto.pageNumber - 1) * getPacCoreMenuAllDto.pageSize; // 使用基础查询构建查询总记录数 - const totalCountQuery = this.getMenuData(getPacCoreMenuAllDto, pacInfo, { + const totalCountQuery = this.getMenuData(getPacCoreMenuAllDto, guardInfo, { totalCount: sql`COUNT(*)`, }); // 使用基础查询构建分页查询 // 重命名表 const userTable1 = alias(pacAuthUser, 'userTable1'); - const paginatedQuery = this.getMenuData(getPacCoreMenuAllDto, pacInfo, { ...this.menuMoreDataType, createName: userTable1.nickname }) + const paginatedQuery = this.getMenuData(getPacCoreMenuAllDto, guardInfo, { ...this.menuMoreDataType, createName: userTable1.nickname }) .leftJoin(pacAuthUser, eq(pacCoreMenu.createby, pacAuthUser.userId)) .leftJoin(userTable1, eq(pacCoreMenu.updateby, userTable1.userId)) .limit(getPacCoreMenuAllDto.pageSize) @@ -268,12 +268,12 @@ export class CoreMenuService { } // DB 删除菜单 - private deleteMenuItem(id, pacInfo: PacInfoType) { + private deleteMenuItem(id, guardInfo: GuardInfo) { return this.mysqlService.db .update(pacCoreMenu) .set({ deletetime: sql`now()`, - deleteby: pacInfo.userId, + deleteby: guardInfo.userId, }) .where(eq(pacCoreMenu.menuId, id)); } @@ -290,7 +290,7 @@ export class CoreMenuService { } // DB 更新菜单信息 - private async updateMenuData(id, updateCoreMenuDto: UpdateCoreMenuDto, pacInfo: PacInfoType) { + private async updateMenuData(id, updateCoreMenuDto: UpdateCoreMenuDto, guardInfo: GuardInfo) { return this.mysqlService.db .update(pacCoreMenu) .set({ @@ -307,7 +307,7 @@ export class CoreMenuService { orderNum: updateCoreMenuDto.orderNum, status: updateCoreMenuDto.status, serviceKey: updateCoreMenuDto.serviceKey, - updateby: pacInfo.userId, + updateby: guardInfo.userId, updatetime: sql`now()`, }) .where(eq(pacCoreMenu.menuId, id)); diff --git a/src/application/core-service/core-service.controller.ts b/src/application/core-service/core-service.controller.ts index b93465e..2f49275 100644 --- a/src/application/core-service/core-service.controller.ts +++ b/src/application/core-service/core-service.controller.ts @@ -3,8 +3,8 @@ import { CoreServiceService } from './core-service.service'; import { CreateCoreServiceDto } from './dto/create-core-service.dto'; import { UpdateCoreServiceDto } from './dto/update-core-service.dto'; import { ApiOperation, ApiProduces, ApiTags } from '@nestjs/swagger'; -import { PacInfo } from '@common/decorator/pac-info/pac-info.decorator'; -import { PacInfoType } from '@utils/myType'; +import { UserInfoDecorator } from '@common/decorator/pac-info/pac-info.decorator'; +import { GuardInfo } from '@utils/myType'; import { GetCoreServiceDto } from './dto/get-core-service.dto'; @ApiTags('系统服务') @@ -18,8 +18,8 @@ export class CoreServiceController { }) @ApiProduces('application/json') @Post() - create(@Body() createCoreServiceDto: CreateCoreServiceDto, @PacInfo() pacInfo: PacInfoType): Promise { - return this.coreServiceService.create(createCoreServiceDto, pacInfo); + create(@Body() createCoreServiceDto: CreateCoreServiceDto, @UserInfoDecorator() guardInfo: GuardInfo): Promise { + return this.coreServiceService.create(createCoreServiceDto, guardInfo); } @ApiOperation({ @@ -48,8 +48,8 @@ export class CoreServiceController { }) @ApiProduces('application/json') @Patch(':serviceKey') - update(@Param('serviceKey') serviceKey: string, @Body() updateCoreServiceDto: UpdateCoreServiceDto, @PacInfo() pacInfo: PacInfoType) { - return this.coreServiceService.update(serviceKey, updateCoreServiceDto, pacInfo); + update(@Param('serviceKey') serviceKey: string, @Body() updateCoreServiceDto: UpdateCoreServiceDto, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreServiceService.update(serviceKey, updateCoreServiceDto, guardInfo); } @ApiOperation({ @@ -58,7 +58,7 @@ export class CoreServiceController { }) @ApiProduces('application/json') @Delete(':serviceKey') - remove(@Param('serviceKey') serviceKey: string, @PacInfo() pacInfo: PacInfoType) { - return this.coreServiceService.remove(serviceKey, pacInfo); + remove(@Param('serviceKey') serviceKey: string, @UserInfoDecorator() guardInfo: GuardInfo) { + return this.coreServiceService.remove(serviceKey, guardInfo); } } diff --git a/src/application/core-service/core-service.service.ts b/src/application/core-service/core-service.service.ts index e07888e..2fa8689 100644 --- a/src/application/core-service/core-service.service.ts +++ b/src/application/core-service/core-service.service.ts @@ -5,7 +5,7 @@ import { LoggerService } from '@service/logger/logger.service'; import { MysqlService } from '@common/service/mysql/mysql.service'; import { pacAuthUser, pacCoreService } from '@entities/schema'; import { and, asc, desc, eq, isNull, like, or, sql } from 'drizzle-orm'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; import { GetCoreServiceDto } from '@app/core-service/dto/get-core-service.dto'; import { likeQuery } from '@utils/likeQuery'; import { RedisService } from '@common/service/redis/redis.service'; @@ -27,9 +27,9 @@ export class CoreServiceService { * DATE: 2024-05-30 21:06:24 - * up: 2024-06-23 14:05:20 - 增减只属于root的新增 * */ - public async create(createCoreServiceDto: CreateCoreServiceDto, pacInfo: PacInfoType) { + public async create(createCoreServiceDto: CreateCoreServiceDto, guardInfo: GuardInfo) { // ! 判断是否是root账户 - if (this.config.get('masterId') !== pacInfo.userId) { + if (this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('没有权限删除菜单!', HttpStatus.UNAUTHORIZED); } @@ -48,7 +48,7 @@ export class CoreServiceService { if (result.length > 0) throw new HttpException('服务标识重复!', HttpStatus.CONFLICT); // ! 添加服务数据 - const newPacCoreService = await this.addServiceData(createCoreServiceDto, pacInfo); + const newPacCoreService = await this.addServiceData(createCoreServiceDto, guardInfo); // ! 解锁 lock(); @@ -86,9 +86,9 @@ export class CoreServiceService { * DATE: 2024-05-30 21:20:19 - * up: 2024-06-23 14:17:37 - 增加root权限限制,修改serviceKey数据结构 * */ - public async update(serviceKey: string, updateCoreServiceDto: UpdateCoreServiceDto, pacInfo: PacInfoType) { + public async update(serviceKey: string, updateCoreServiceDto: UpdateCoreServiceDto, guardInfo: GuardInfo) { // ! 判断是否是root账户 - if (this.config.get('masterId') !== pacInfo.userId) { + if (this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('没有权限删除菜单!', HttpStatus.UNAUTHORIZED); } @@ -119,7 +119,7 @@ export class CoreServiceService { // @ 核心业务 try { // ! 更新数据 - const result = await this.updateServiceItem(serviceKey, updateCoreServiceDto, pacInfo); + const result = await this.updateServiceItem(serviceKey, updateCoreServiceDto, guardInfo); // ! 解锁 lock(); @@ -141,14 +141,14 @@ export class CoreServiceService { * DATE: 2024-05-30 21:24:33 - * up: 2024-06-23 14:17:37 - 增加root权限限制 * */ - public async remove(serviceKey: string, pacInfo: PacInfoType) { + public async remove(serviceKey: string, guardInfo: GuardInfo) { // ! 判断是否是root账户 - if (this.config.get('masterId') !== pacInfo.userId) { + if (this.config.get('masterId') !== guardInfo.userId) { throw new HttpException('没有权限删除菜单!', HttpStatus.UNAUTHORIZED); } // ! 执行删除并返回 - return await this.deleteServiceItem(serviceKey, pacInfo); + return await this.deleteServiceItem(serviceKey, guardInfo); } // DB 根据serviceKey查找服务数据 可用于查重 @@ -157,9 +157,9 @@ export class CoreServiceService { } // DB 添加服务数据 - private async addServiceData(createCoreServiceDto: CreateCoreServiceDto, pacInfo: PacInfoType) { + private async addServiceData(createCoreServiceDto: CreateCoreServiceDto, guardInfo: GuardInfo) { const newServiceData: typeof pacCoreService.$inferInsert = { - createby: pacInfo.userId, + createby: guardInfo.userId, createtime: sql`now()` as any, serviceKey: createCoreServiceDto.serviceKey, serviceName: createCoreServiceDto.serviceName, @@ -235,18 +235,18 @@ export class CoreServiceService { } // DB 删除服务 - private async deleteServiceItem(serviceKey: string, pacInfo: PacInfoType) { + private async deleteServiceItem(serviceKey: string, guardInfo: GuardInfo) { return await this.mysqlService.db .update(pacCoreService) .set({ deletetime: sql`now()`, - deleteby: pacInfo.userId, + deleteby: guardInfo.userId, }) .where(eq(pacCoreService.serviceKey, serviceKey)); } // DB 更新服务 - private updateServiceItem(serviceKey: string, updateCoreServiceDto: UpdateCoreServiceDto, pacInfo: PacInfoType) { + private updateServiceItem(serviceKey: string, updateCoreServiceDto: UpdateCoreServiceDto, guardInfo: GuardInfo) { return this.mysqlService.db .update(pacCoreService) .set({ @@ -255,7 +255,7 @@ export class CoreServiceService { serviceVersion: updateCoreServiceDto.serviceVersion, serviceDesc: updateCoreServiceDto.serviceDesc, updatetime: sql`now()`, - updateby: pacInfo.userId, + updateby: guardInfo.userId, }) .where(eq(pacCoreService.serviceKey, serviceKey)); } diff --git a/src/application/global.module.ts b/src/application/global.module.ts index c2794cb..a0b418b 100644 --- a/src/application/global.module.ts +++ b/src/application/global.module.ts @@ -16,11 +16,12 @@ import { LoggerService } from '@service/logger/logger.service'; import { RedisService } from '@common/service/redis/redis.service'; import { MysqlService } from '@common/service/mysql/mysql.service'; import { Snowflake } from '@service/snowflake/snowflake.service'; +import { JwtService } from '@common/service/jwt/jwt.service'; @Global() @Module({ - providers: [LoggerService, RedisService, MysqlService, Snowflake], - exports: [LoggerService, RedisService, MysqlService, Snowflake], + providers: [LoggerService, RedisService, MysqlService, Snowflake, JwtService], + exports: [LoggerService, RedisService, MysqlService, Snowflake, JwtService], imports: [], }) export class GlobalModule {} diff --git a/src/common/decorator/pac-info/pac-info.decorator.ts b/src/common/decorator/pac-info/pac-info.decorator.ts index 545ca65..4dbedd3 100644 --- a/src/common/decorator/pac-info/pac-info.decorator.ts +++ b/src/common/decorator/pac-info/pac-info.decorator.ts @@ -1,15 +1,14 @@ import { createParamDecorator, ExecutionContext, SetMetadata } from '@nestjs/common'; -import { PacInfoType } from '@utils/myType'; +import { GuardInfo } from '@utils/myType'; -// export const PacInfo = (...args: string[]) => SetMetadata('pac-info', args); +// export const UserInfoDecorator = (...args: string[]) => SetMetadata('pac-info', args); -// PacInfo -export const PacInfo = createParamDecorator((data: string, ctx: ExecutionContext) => { - const info: PacInfoType = { - username: 'pac', - userId: 0, +// UserInfoDecorator +export const UserInfoDecorator = createParamDecorator((data: string, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + const info: GuardInfo = { + username: request.guardInfo.username, + userId: request.guardInfo.userId, }; return info; - - // const req = ctx.switchToHttp().getRequest(); }); diff --git a/src/common/guard/auth/auth.guard.ts b/src/common/guard/auth/auth.guard.ts new file mode 100644 index 0000000..140a849 --- /dev/null +++ b/src/common/guard/auth/auth.guard.ts @@ -0,0 +1,82 @@ +import { CanActivate, ExecutionContext, HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { Observable } from 'rxjs'; +import { LoggerService } from '@service/logger/logger.service'; +import { MysqlService } from '@common/service/mysql/mysql.service'; +import { RedisService } from '@common/service/redis/redis.service'; +import { Snowflake } from '@service/snowflake/snowflake.service'; +import { ConfigService } from '@nestjs/config'; +import { JwtService } from '@common/service/jwt/jwt.service'; +import { KEY } from '@utils/key'; +import MD5 from '@utils/MD5'; + +@Injectable() +export class AuthGuard implements CanActivate { + constructor( + private readonly logger: LoggerService, + private readonly mysqlService: MysqlService, + private readonly redisService: RedisService, + private readonly snowflake: Snowflake, + private readonly config: ConfigService, + private readonly jwt: JwtService, + ) {} + canActivate(context: ExecutionContext): boolean | Promise | Observable { + const request = context.switchToHttp().getRequest(); + + // ! 路由白名单 + const whitelist = this.config.get('system.whitelist'); + if (whitelist.some((route) => request.url.startsWith(route))) { + // ! 如果请求的路径在白名单中,允许直接访问 + return true; + } + return new Promise(async (resolve, reject) => { + if (request.headers.authorization) { + let authorization = request.headers.authorization; + if (authorization.indexOf('Bearer ') === 0) { + authorization = authorization.split('Bearer ')[1]; + } + + // ! 获取Token + let token; + try { + token = (await this.jwt.verify(authorization)) as any; + } catch (e) { + token = undefined; + this.logger.warn('令牌解析错误', e, e.track); + } + + // ? 判断Token是否过期 + if (token === undefined) { + return reject(new HttpException('FORBIDDEN | 令牌过期!', HttpStatus.FORBIDDEN)); + } + + // ? 判断redis中是否存在 + const redisTokenKey = + token.type == 'refreshToken' + ? KEY.REDIS_REFRESH_TOKEN + token.userId + '-' + MD5(authorization) + : KEY.REDIS_TOKEN + token.userId + '-' + MD5(authorization); + const redisToken = await this.redisService.get(redisTokenKey); + if (redisToken == null) { + console.log('??????'); + return reject(new HttpException('FORBIDDEN | 令牌过期!', HttpStatus.FORBIDDEN)); + } + + // ? 是否是refreshToken访问非token刷新接口 + if (token.type == 'refreshToken' && request.url !== '/authUser/sign/refresh') { + return reject(new HttpException('BAD_REQUEST | 令牌使用错误!', HttpStatus.BAD_REQUEST)); + } + + // ? 是否是token访问token刷新接口 + + if (token.type == 'token' && request.url == '/authUser/sign/refresh') { + return reject(new HttpException('BAD_REQUEST | 令牌使用错误,非法续约!', HttpStatus.BAD_REQUEST)); + } + + // 假设token有效 + resolve(true); + request.guardInfo = token; + } else { + reject(new HttpException('Unauthorized | 你没有访问权限!', HttpStatus.UNAUTHORIZED)); + } + }); + } +} diff --git a/src/common/service/jwt/jwt.service.ts b/src/common/service/jwt/jwt.service.ts index b18be04..f92f2af 100644 --- a/src/common/service/jwt/jwt.service.ts +++ b/src/common/service/jwt/jwt.service.ts @@ -23,6 +23,6 @@ export class JwtService { } public verify(token: any) { - jwt.verify(token, this.configService.get('system.signin.secretKey')); + return jwt.verify(token, this.configService.get('system.signin.secretKey')); } } diff --git a/src/config/configuration.ts b/src/config/configuration.ts index 56ef0cd..674bf2c 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -68,11 +68,12 @@ export default () => ({ // 客户端在线时间 7天 ========jwt最小单位是s refreshTokenTime: 60 * 60 * 24 * 7, - // 客户端连续在线时间 10min - tokenTime: 60 * 10, + // 客户端连续在线时间 10min 60 * 10 + tokenTime: 10, // token盐 secretKey: '326dea8337e8xsxa24f71ab960ea', }, + whitelist: ['/authUser/sign/in', '/api/login'], }, }); diff --git a/src/utils/key.ts b/src/utils/key.ts new file mode 100644 index 0000000..6fece77 --- /dev/null +++ b/src/utils/key.ts @@ -0,0 +1,32 @@ +// | ------------------------------------------------------------ +// | @版本: version 0.1 +// | @创建人: 【Nie-hotok】 +// | @E-mail: x71291@outlook.com +// | @所在项目: pac-auth +// | @文件描述: key.ts - +// | @创建时间: 2024-06-30 10:44 +// | @更新时间: 2024-06-30 10:44 +// | @修改记录: +// | -*-*-*- (时间--修改人--修改说明) -*-*-*- +// | = +// | ------------------------------------------------------------ +export const KEY = { + // ! 正常请求Token的Redis前缀 + REDIS_TOKEN: 'CLIENT-ONLINE-', + + // ! 刷新Token的Redis前缀 + REDIS_REFRESH_TOKEN: 'CLIENT-', + + // ! 最大客户端登陆数量的Redis前缀 + REDIS_MAX_CLIENT: 'ENV_MAX_SIGNIN_CLIENT', + + // ! 客户端登陆错误的次数 Redis前缀 + REDIS_FIELD_SIGNIN_NUM: 'FIELD_SIGNIN_NUM-', + + // ! 系统允许的最大错误登录数量 + REDIS_MAX_FIELD_SIGNIN_NUM: 'MAX_FIELD_SIGNIN_NUM', + + // ! 最大登录失败后的冷却时间 + REDIS_WAITING_SIGNIN_TIME: 'CONFIG_MAX_TIME_FIELD_SIGNIN', + +}; diff --git a/src/utils/myType.d.ts b/src/utils/myType.d.ts index 068591c..8ea554a 100644 --- a/src/utils/myType.d.ts +++ b/src/utils/myType.d.ts @@ -11,7 +11,7 @@ // | = // | ------------------------------------------------------------ -export interface PacInfoType { +export interface GuardInfo { username: string; userId: number; }