parent
1e05f977f6
commit
5e4a81c303
@ -1,34 +1,127 @@ |
|||||||
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; |
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common'; |
||||||
import { AuthUserService } from './auth-user.service'; |
import { AuthUserService } from './auth-user.service'; |
||||||
import { CreateAuthUserDto } from './dto/create-auth-user.dto'; |
import { CreateAuthUserDto } from './dto/create-auth-user.dto'; |
||||||
import { UpdateAuthUserDto } from './dto/update-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 { 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"; |
||||||
|
|
||||||
@Controller('auth-user') |
@ApiTags('账户服务') |
||||||
|
@Controller('authUser') |
||||||
export class AuthUserController { |
export class AuthUserController { |
||||||
constructor(private readonly authUserService: AuthUserService) {} |
constructor(private readonly authUserService: AuthUserService) {} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '添加账户', |
||||||
|
description: '账户', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
@Post() |
@Post() |
||||||
create(@Body() createAuthUserDto: CreateAuthUserDto) { |
create(@Body() createAuthUserDto: CreateAuthUserDto, @PacInfo() pacInfo: PacInfoType) { |
||||||
return this.authUserService.create(createAuthUserDto); |
return this.authUserService.create(createAuthUserDto, pacInfo); |
||||||
} |
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '获取账户列表', |
||||||
|
description: '查询账户分页或者列表', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
@Get() |
@Get() |
||||||
findAll() { |
findAll(@Query() getPacAuthUserAllDto: GetPacAuthUserAllDto) { |
||||||
return this.authUserService.findAll(); |
return this.authUserService.findAll(getPacAuthUserAllDto); |
||||||
} |
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '获取账户详细信息', |
||||||
|
description: '查询账户详细信息,目录菜单列表,数据权限范围', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
@Get(':id') |
@Get(':id') |
||||||
findOne(@Param('id') id: string) { |
findOne(@Param('id') id: string) { |
||||||
return this.authUserService.findOne(+id); |
return this.authUserService.findOne(id); |
||||||
} |
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '更新账户信息', |
||||||
|
description: '更新账户信息', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
@Patch(':id') |
@Patch(':id') |
||||||
update(@Param('id') id: string, @Body() updateAuthUserDto: UpdateAuthUserDto) { |
update(@Param('id') id: string, @Body() updateAuthUserDto: UpdateAuthUserDto, @PacInfo() pacInfo: PacInfoType) { |
||||||
return this.authUserService.update(+id, updateAuthUserDto); |
return this.authUserService.update(id, updateAuthUserDto, pacInfo); |
||||||
} |
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '删除目标账户', |
||||||
|
description: '删除目标账户信息', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
@Delete(':id') |
@Delete(':id') |
||||||
remove(@Param('id') id: string) { |
remove(@Param('id') id: string, @PacInfo() pacInfo: PacInfoType) { |
||||||
return this.authUserService.remove(+id); |
return this.authUserService.remove(id, pacInfo); |
||||||
|
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '重置密码', |
||||||
|
description: '给指定用户将密码恢复为系统默认账户密码', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
|
@Post('/password/:id') |
||||||
|
resetTargetUserPassword(@Param('id') id: string) { |
||||||
|
return this.authUserService.resetTargetUserPassword(id); |
||||||
|
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '修改密码', |
||||||
|
description: '修改自己密码', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
|
@Patch('/password') |
||||||
|
updatePassword(@Param('id') id: string, @Body() passwordDto: PasswordDto) { |
||||||
|
return this.authUserService.updatePassword(id, passwordDto); |
||||||
|
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '更新账户角色', |
||||||
|
description: '更新账户角色', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
|
@Patch('/role/:id') |
||||||
|
updateLinkRole(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @PacInfo() pacInfo: PacInfoType) { |
||||||
|
return this.authUserService.updateLinkRole(id, updateLinkDto, pacInfo); |
||||||
|
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '更新账户部门', |
||||||
|
description: '更新账户部门', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
|
@Patch('/dept/:id') |
||||||
|
updateLinkDept(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @PacInfo() pacInfo: PacInfoType) { |
||||||
|
return this.authUserService.updateLinkDept(id, updateLinkDto, pacInfo); |
||||||
|
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '更新账户岗位', |
||||||
|
description: '更新账户岗位', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
|
@Patch('/post/:id') |
||||||
|
updateLinkPost(@Param('id') id: string, @Body() updateLinkDto: UpdateLinkDto, @PacInfo() pacInfo: PacInfoType) { |
||||||
|
return this.authUserService.updateLinkPost(id, updateLinkDto, pacInfo); |
||||||
|
} |
||||||
|
|
||||||
|
@ApiOperation({ |
||||||
|
summary: '登陆系统', |
||||||
|
description: '登陆系统', |
||||||
|
}) |
||||||
|
@ApiProduces('application/json') |
||||||
|
@Post('/signin') |
||||||
|
signin(@Body() usernameSignInDto: UsernameSignInDto) { |
||||||
|
return this.authUserService.signin(usernameSignInDto); |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,9 +1,10 @@ |
|||||||
import { Module } from '@nestjs/common'; |
import { Module } from '@nestjs/common'; |
||||||
import { AuthUserService } from './auth-user.service'; |
import { AuthUserService } from './auth-user.service'; |
||||||
import { AuthUserController } from './auth-user.controller'; |
import { AuthUserController } from './auth-user.controller'; |
||||||
|
import { JwtService } from '@common/service/jwt/jwt.service'; |
||||||
|
|
||||||
@Module({ |
@Module({ |
||||||
controllers: [AuthUserController], |
controllers: [AuthUserController], |
||||||
providers: [AuthUserService], |
providers: [AuthUserService, JwtService], |
||||||
}) |
}) |
||||||
export class AuthUserModule {} |
export class AuthUserModule {} |
||||||
|
@ -1,26 +1,696 @@ |
|||||||
import { Injectable } from '@nestjs/common'; |
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; |
||||||
import { CreateAuthUserDto } from './dto/create-auth-user.dto'; |
import { CreateAuthUserDto } from './dto/create-auth-user.dto'; |
||||||
import { UpdateAuthUserDto } from './dto/update-auth-user.dto'; |
import { UpdateAuthUserDto } from './dto/update-auth-user.dto'; |
||||||
|
import { PacInfoType } 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'; |
||||||
|
import { Snowflake } from '@service/snowflake/snowflake.service'; |
||||||
|
import { ConfigService } from '@nestjs/config'; |
||||||
|
import { |
||||||
|
pacAuthDept, |
||||||
|
pacAuthLinkRoleMenu, |
||||||
|
pacAuthLinkUserDept, |
||||||
|
pacAuthLinkUserPost, |
||||||
|
pacAuthLinkUserRole, |
||||||
|
pacAuthPost, |
||||||
|
pacAuthRole, |
||||||
|
pacAuthUser, |
||||||
|
pacCoreDict, |
||||||
|
} from '@entities/schema'; |
||||||
|
import { and, asc, desc, eq, gt, isNull, like, or, sql } from 'drizzle-orm'; |
||||||
|
import cryptoPassword from '@utils/cryptoPassword'; |
||||||
|
import { GetPacAuthUserAllDto } from '@app/auth-user/dto/get-auth-user.dto'; |
||||||
|
import { isExistKey, isTrueEnum } from '@utils/boolean.enum'; |
||||||
|
import { likeQuery } from '@utils/likeQuery'; |
||||||
|
import { alias } from 'drizzle-orm/mysql-core'; |
||||||
|
import { from } from 'rxjs'; |
||||||
|
import { UpdateCoreDictDto } from '@app/core-dict/dto/update-core-dict.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 { JwtService } from '@common/service/jwt/jwt.service'; |
||||||
|
import MD5 from '@utils/MD5'; |
||||||
|
|
||||||
@Injectable() |
@Injectable() |
||||||
export class AuthUserService { |
export class AuthUserService { |
||||||
create(createAuthUserDto: CreateAuthUserDto) { |
// 分页数据
|
||||||
|
private readonly userPageType = { |
||||||
|
userId: pacAuthUser.userId, |
||||||
|
username: pacAuthUser.username, |
||||||
|
nickname: pacAuthUser.nickname, |
||||||
|
userType: pacAuthUser.userType, |
||||||
|
userTypeName: pacCoreDict.dictName, |
||||||
|
userTypeKey: pacCoreDict.dictKey, |
||||||
|
userEmail: pacAuthUser.userEmail, |
||||||
|
pid: pacAuthUser.pid, |
||||||
|
wxAppid: pacAuthUser.wxAppid, |
||||||
|
avatar: pacAuthUser.avatar, |
||||||
|
userPhone: pacAuthUser.userPhone, |
||||||
|
userDesc: pacAuthUser.userDesc, |
||||||
|
status: pacAuthUser.status, |
||||||
|
haveChildren: pacAuthUser.haveChildren, |
||||||
|
createby: pacAuthUser.createby, |
||||||
|
createtime: pacAuthUser.createtime, |
||||||
|
updateby: pacAuthUser.updateby, |
||||||
|
updatetime: pacAuthUser.updatetime, |
||||||
|
}; |
||||||
|
|
||||||
|
// 列表数据
|
||||||
|
private readonly userListType = { |
||||||
|
userId: pacAuthUser.userId, |
||||||
|
username: pacAuthUser.username, |
||||||
|
nickname: pacAuthUser.nickname, |
||||||
|
userType: pacAuthUser.userType, |
||||||
|
userTypeName: pacCoreDict.dictName, |
||||||
|
userTypeKey: pacCoreDict.dictKey, |
||||||
|
}; |
||||||
|
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, |
||||||
|
) {} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: create |
||||||
|
* DESC: 创建账户 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async create(createAuthUserDto: CreateAuthUserDto, pacInfo: PacInfoType) { |
||||||
|
// ! 加目标锁,同级,而不是全局
|
||||||
|
const lock = await this.redisService.distributedLock('USER' + createAuthUserDto.username, createAuthUserDto.username); |
||||||
|
|
||||||
|
// ? 存在正在进行写入的账户
|
||||||
|
if (!lock) throw new HttpException('服务繁忙,账户名称重复!', HttpStatus.CONFLICT); |
||||||
|
|
||||||
|
try { |
||||||
|
// ! 用户名查重
|
||||||
|
const result = await this.checkRepeatForUsername(createAuthUserDto.username); |
||||||
|
|
||||||
|
// ? 是否存在重复的账户
|
||||||
|
if (result.length > 0) throw new HttpException('用户名重复!', HttpStatus.CONFLICT); |
||||||
|
|
||||||
|
// ! 添加账户数据
|
||||||
|
const newPacCoreDict = await this.addUser(createAuthUserDto, pacInfo); |
||||||
|
|
||||||
|
// ! 解锁
|
||||||
|
lock(); |
||||||
|
|
||||||
|
const insertList = []; |
||||||
|
|
||||||
|
// ! 关联角色
|
||||||
|
if (createAuthUserDto.roleList && createAuthUserDto.roleList.length > 0) { |
||||||
|
insertList.push(this.updateUserRole(newPacCoreDict.userId as any, createAuthUserDto.roleList, pacInfo)); |
||||||
|
} |
||||||
|
|
||||||
|
// ! 关联部门
|
||||||
|
if (createAuthUserDto.deptList && createAuthUserDto.deptList.length > 0) { |
||||||
|
insertList.push(this.updateUserDept(newPacCoreDict.userId as any, createAuthUserDto.deptList, pacInfo)); |
||||||
|
} |
||||||
|
|
||||||
|
// ! 关联岗位
|
||||||
|
if (createAuthUserDto.postList && createAuthUserDto.postList.length > 0) { |
||||||
|
insertList.push(this.updateUserPost(newPacCoreDict.userId as any, createAuthUserDto.postList, pacInfo)); |
||||||
|
} |
||||||
|
|
||||||
|
// ! 执行关联
|
||||||
|
await Promise.all(insertList).catch((e) => { |
||||||
|
this.logger.error('新增用户时,关联角色、部门、岗位出现错误'); |
||||||
|
this.logger.error(e); |
||||||
|
}); |
||||||
|
|
||||||
|
// !更新父节点的子节点数量
|
||||||
|
await this.haveChildrenSelfIncreasing(createAuthUserDto.pid); |
||||||
|
|
||||||
|
// ! 返回结果
|
||||||
|
return newPacCoreDict; |
||||||
|
} catch (e) { |
||||||
|
// ! 解锁
|
||||||
|
lock(); |
||||||
|
|
||||||
|
// ! 抛出错误
|
||||||
|
throw e; |
||||||
|
} |
||||||
|
|
||||||
return 'This action adds a new authUser'; |
return 'This action adds a new authUser'; |
||||||
} |
} |
||||||
|
|
||||||
findAll() { |
/** Service |
||||||
return `This action returns all authUser`; |
* NAME: findAll |
||||||
|
* DESC: 查找用户分页/列表 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async findAll(getPacAuthUserAllDto: GetPacAuthUserAllDto) { |
||||||
|
if (isTrueEnum(getPacAuthUserAllDto['isList'])) { |
||||||
|
return await this.getList(getPacAuthUserAllDto); |
||||||
|
} else { |
||||||
|
return await this.getPage(getPacAuthUserAllDto); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: findOne |
||||||
|
* DESC: 查用户详细信息 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async findOne(id: string) { |
||||||
|
return await this.getMore(id); |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: update |
||||||
|
* DESC: 修改账户信息 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public update(id: string, updateAuthUserDto: UpdateAuthUserDto, pacInfo: PacInfoType) { |
||||||
|
return this.updateUser(id, updateAuthUserDto, pacInfo); |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: remove |
||||||
|
* DESC: 移除账户 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public remove(id: string, pacInfo: PacInfoType) { |
||||||
|
return this.deleteUser(id, pacInfo.userId as any); |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: resetTargetUserPassword |
||||||
|
* DESC: 充值目标账户密码 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async resetTargetUserPassword(id: string) { |
||||||
|
return this.resetPassword(id, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: updatePassword |
||||||
|
* DESC: 修改自己账户密码 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async updatePassword(id: string, passwordDto: PasswordDto) { |
||||||
|
const user = await this.mysqlService.db |
||||||
|
.select({ |
||||||
|
password: pacAuthUser.password, |
||||||
|
}) |
||||||
|
.from(pacAuthUser) |
||||||
|
.where(eq(pacAuthUser.userId, id)); |
||||||
|
if (user.length == 0) throw new HttpException('未找到目标用户信息,无法修改密码!', HttpStatus.BAD_REQUEST); |
||||||
|
const oldPassword = cryptoPassword(passwordDto.oldPassword, this.config.get<number>('system.passwordSalt')); |
||||||
|
if (oldPassword != user[0].password) throw new HttpException('原密码错误!', HttpStatus.BAD_REQUEST); |
||||||
|
return this.resetPassword(id, passwordDto.newPassword); |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: updatePassword |
||||||
|
* DESC: 修改目标账户角色关联 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async updateLinkRole(id: string, updateLinkDto: UpdateLinkDto, pacInfo: PacInfoType) { |
||||||
|
await this.checkUserExist(id); |
||||||
|
if (updateLinkDto) { |
||||||
|
return this.updateUserRole(id, updateLinkDto.list, pacInfo); |
||||||
|
} else { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: updateLinkDept |
||||||
|
* DESC: 修改目标账户部门关联 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async updateLinkDept(id: string, updateLinkDto: UpdateLinkDto, pacInfo: PacInfoType) { |
||||||
|
await this.checkUserExist(id); |
||||||
|
if (updateLinkDto) { |
||||||
|
return this.updateUserDept(id, updateLinkDto.list, pacInfo); |
||||||
|
} else { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: updateLinkPost |
||||||
|
* DESC: 修改目标账户岗位关联 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async updateLinkPost(id: string, updateLinkDto: UpdateLinkDto, pacInfo: PacInfoType) { |
||||||
|
await this.checkUserExist(id); |
||||||
|
if (updateLinkDto) { |
||||||
|
return this.updateUserPost(id, updateLinkDto.list, pacInfo); |
||||||
|
} else { |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Service |
||||||
|
* NAME: updateLinkPost |
||||||
|
* DESC: 修改目标账户岗位关联 |
||||||
|
* DATE: 2024-06-29 13:13:55 - |
||||||
|
* */ |
||||||
|
public async signin(usernameSignInDto: UsernameSignInDto) { |
||||||
|
// 登陆检测
|
||||||
|
return await this.signinDetection(usernameSignInDto); |
||||||
|
} |
||||||
|
|
||||||
|
// DB 同级查重
|
||||||
|
private checkRepeatForUsername(username: string) { |
||||||
|
return this.mysqlService.db |
||||||
|
.select({ |
||||||
|
id: pacAuthUser.username, |
||||||
|
}) |
||||||
|
.from(pacAuthUser) |
||||||
|
.where(and(isNull(pacAuthUser.deleteby), eq(pacAuthUser.username, username))); |
||||||
|
} |
||||||
|
|
||||||
|
// DB 更新父级子元素数量
|
||||||
|
private async haveChildrenSelfIncreasing(id: string, isAdd = true) { |
||||||
|
return this.mysqlService.db |
||||||
|
.update(pacAuthUser) |
||||||
|
.set({ |
||||||
|
haveChildren: isAdd ? sql`${pacAuthUser.haveChildren} + 1` : sql`${pacAuthUser.haveChildren} - 1`, |
||||||
|
}) |
||||||
|
.where(eq(pacAuthUser.userId as any, id)); |
||||||
|
} |
||||||
|
|
||||||
|
// DB 添加账户
|
||||||
|
private async addUser(createAuthUserDto: CreateAuthUserDto, pacInfo: PacInfoType) { |
||||||
|
// ! 生成雪花id,用于账户id
|
||||||
|
const id = await this.snowflake.generate(); |
||||||
|
|
||||||
|
let password = ''; |
||||||
|
|
||||||
|
// ! 从Redis获取默认密码
|
||||||
|
const defaultPasswordForRedis = await this.redisService.get('ENV_DEFAULT_PASSWORD'); |
||||||
|
|
||||||
|
// ? 判断redis中是否存在默认密码环境变量
|
||||||
|
if (!defaultPasswordForRedis) { |
||||||
|
password = this.config.get<string>('system.defaultPassword'); |
||||||
|
} else { |
||||||
|
password = defaultPasswordForRedis; |
||||||
|
} |
||||||
|
|
||||||
|
// ! 加密密码
|
||||||
|
const pass = cryptoPassword(password, this.config.get<number>('system.passwordSalt')); |
||||||
|
|
||||||
|
// ! 定义写入的账户数据
|
||||||
|
const newUserData: typeof pacAuthUser.$inferInsert = { |
||||||
|
userId: id as any, |
||||||
|
username: createAuthUserDto.username, |
||||||
|
password: pass, |
||||||
|
nickname: createAuthUserDto.nickname, |
||||||
|
userType: createAuthUserDto.userType, |
||||||
|
userEmail: createAuthUserDto.userEmail, |
||||||
|
pid: createAuthUserDto.pid, |
||||||
|
avatar: createAuthUserDto.avatar, |
||||||
|
userPhone: createAuthUserDto.userPhone, |
||||||
|
userDesc: createAuthUserDto.userDesc, |
||||||
|
createby: pacInfo.userId as any, |
||||||
|
createtime: sql`now()` as any, |
||||||
|
}; |
||||||
|
return { |
||||||
|
insert: await this.mysqlService.db.insert(pacAuthUser).values(newUserData), |
||||||
|
userId: id.toString(), |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// COMMON 去重数组
|
||||||
|
private deduplicateArray(arr: string[]) { |
||||||
|
return Array.from(new Set(arr)); |
||||||
} |
} |
||||||
|
|
||||||
findOne(id: number) { |
// COMMON 向目标表插入列
|
||||||
return `This action returns a #${id} authUser`; |
private async insertKeyValueForUserLink(table, list, key, userId, pacInfo: PacInfoType) { |
||||||
|
// ! 清空曾经的关联
|
||||||
|
await this.mysqlService.db.delete(table).where(eq(table.userId as any, userId)); |
||||||
|
|
||||||
|
// ! 去重列表
|
||||||
|
const arr = this.deduplicateArray(list); |
||||||
|
|
||||||
|
// ! 增加新的关联
|
||||||
|
return await this.mysqlService.db.insert(table).values( |
||||||
|
arr.map((i) => ({ |
||||||
|
userId: userId, |
||||||
|
[key]: i, |
||||||
|
createby: pacInfo.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); |
||||||
} |
} |
||||||
|
|
||||||
update(id: number, updateAuthUserDto: UpdateAuthUserDto) { |
// DB 修改账户部门
|
||||||
return `This action updates a #${id} authUser`; |
private async updateUserDept(userId: string, deptIdList: string[], pacInfo: PacInfoType) { |
||||||
|
return await this.insertKeyValueForUserLink(pacAuthLinkUserDept, deptIdList, 'deptId', userId, pacInfo); |
||||||
} |
} |
||||||
|
|
||||||
remove(id: number) { |
// DB修改账户岗位
|
||||||
return `This action removes a #${id} authUser`; |
private async updateUserPost(userId: string, postIdList: string[], pacInfo: PacInfoType) { |
||||||
|
return await this.insertKeyValueForUserLink(pacAuthLinkUserPost, postIdList, 'postId', userId, pacInfo); |
||||||
|
} |
||||||
|
|
||||||
|
// 查询构建器
|
||||||
|
private queryBuilder(getPacAuthUserAllDto: GetPacAuthUserAllDto, selectData) { |
||||||
|
// ! 定义基础查询函数
|
||||||
|
// 启用动态查询模式 $dynamic
|
||||||
|
const query = this.mysqlService.db |
||||||
|
.select(selectData) |
||||||
|
.from(pacAuthUser) |
||||||
|
.orderBy(isTrueEnum(getPacAuthUserAllDto.isAsc) ? asc(pacAuthUser.userId) : desc(pacAuthUser.userId)) |
||||||
|
.leftJoin(pacCoreDict, eq(pacAuthUser.userType, pacCoreDict.dictId)) |
||||||
|
|
||||||
|
// 角色
|
||||||
|
.leftJoin(pacAuthLinkUserRole, eq(pacAuthUser.userId, pacAuthLinkUserRole.userId)) |
||||||
|
|
||||||
|
// 部门
|
||||||
|
.leftJoin(pacAuthLinkUserDept, eq(pacAuthUser.userId, pacAuthLinkUserDept.userId)) |
||||||
|
|
||||||
|
// 岗位
|
||||||
|
.leftJoin(pacAuthLinkUserPost, eq(pacAuthUser.userId, pacAuthLinkUserPost.userId)) |
||||||
|
.$dynamic(); |
||||||
|
|
||||||
|
// 查询条件集合
|
||||||
|
const wl = []; |
||||||
|
|
||||||
|
// ? 未删除
|
||||||
|
wl.push(isNull(pacAuthUser.deleteby)); |
||||||
|
|
||||||
|
// ? 模糊查询
|
||||||
|
wl.push( |
||||||
|
or( |
||||||
|
like(pacAuthUser.username, likeQuery(getPacAuthUserAllDto.userInfo)), |
||||||
|
like(pacAuthUser.nickname, likeQuery(getPacAuthUserAllDto.userInfo)), |
||||||
|
like(pacAuthUser.userEmail, likeQuery(getPacAuthUserAllDto.userInfo)), |
||||||
|
like(pacAuthUser.userPhone, likeQuery(getPacAuthUserAllDto.userInfo)), |
||||||
|
like(pacAuthUser.userDesc, likeQuery(getPacAuthUserAllDto.userInfo)), |
||||||
|
).if(isExistKey(getPacAuthUserAllDto, 'userInfo')), |
||||||
|
); |
||||||
|
|
||||||
|
// ? 按照层级查
|
||||||
|
wl.push(eq(pacAuthUser.pid, getPacAuthUserAllDto.hierarchy).if(isExistKey(getPacAuthUserAllDto, 'hierarchy'))); |
||||||
|
|
||||||
|
// ? 是否查角色类型
|
||||||
|
wl.push(eq(pacAuthUser.userType, getPacAuthUserAllDto.userType).if(isExistKey(getPacAuthUserAllDto, 'userType'))); |
||||||
|
|
||||||
|
// ? 是否查字典状态
|
||||||
|
wl.push(eq(pacAuthUser.status, getPacAuthUserAllDto.status as any).if(isExistKey(getPacAuthUserAllDto, 'status'))); |
||||||
|
|
||||||
|
// ? 是否存在子账户
|
||||||
|
wl.push(gt(pacAuthUser.haveChildren, 0).if(isExistKey(getPacAuthUserAllDto, 'haveChildren') && isTrueEnum(getPacAuthUserAllDto.haveChildren))); |
||||||
|
|
||||||
|
// ? 角色
|
||||||
|
wl.push( |
||||||
|
eq(pacAuthLinkUserRole.roleId, getPacAuthUserAllDto.roleId).if( |
||||||
|
isExistKey(getPacAuthUserAllDto, 'roleId') && !isTrueEnum(getPacAuthUserAllDto.noRole), |
||||||
|
), |
||||||
|
); |
||||||
|
|
||||||
|
// ? 部门
|
||||||
|
wl.push(eq(pacAuthLinkUserDept.deptId, getPacAuthUserAllDto.deptId).if(isExistKey(getPacAuthUserAllDto, 'deptId'))); |
||||||
|
|
||||||
|
// ? 岗位
|
||||||
|
wl.push(eq(pacAuthLinkUserPost.postId, getPacAuthUserAllDto.postId).if(isExistKey(getPacAuthUserAllDto, 'postId'))); |
||||||
|
|
||||||
|
// ? 没有角色
|
||||||
|
wl.push(isNull(pacAuthLinkUserRole.roleId).if(!isExistKey(getPacAuthUserAllDto, 'roleId') && isTrueEnum(getPacAuthUserAllDto.noRole))); |
||||||
|
|
||||||
|
// ? 没有部门
|
||||||
|
wl.push(isNull(pacAuthLinkUserDept.deptId).if(!isExistKey(getPacAuthUserAllDto, 'deptId') && isTrueEnum(getPacAuthUserAllDto.noDept))); |
||||||
|
|
||||||
|
// ? 没有岗位
|
||||||
|
wl.push(isNull(pacAuthLinkUserPost.postId).if(!isExistKey(getPacAuthUserAllDto, 'postId') && isTrueEnum(getPacAuthUserAllDto.noPost))); |
||||||
|
|
||||||
|
query.where(and(...wl)); |
||||||
|
return query; |
||||||
|
} |
||||||
|
|
||||||
|
// DB 查分页
|
||||||
|
private async getPage(getPacAuthUserAllDto: GetPacAuthUserAllDto) { |
||||||
|
const offset = (getPacAuthUserAllDto.pageNumber - 1) * getPacAuthUserAllDto.pageSize; |
||||||
|
|
||||||
|
// ! 使用基础查询构建查询总记录数
|
||||||
|
const totalCountQuery = this.queryBuilder(getPacAuthUserAllDto, { |
||||||
|
totalCount: sql`COUNT(DISTINCT ${pacAuthUser.userId})`, |
||||||
|
}); |
||||||
|
|
||||||
|
// ! 使用基础查询构建分页查询
|
||||||
|
// 重命名表
|
||||||
|
const userTable1 = alias(pacAuthUser, 'userTable1'); |
||||||
|
const userTable2 = alias(pacAuthUser, 'userTable2'); |
||||||
|
const selectObject = { |
||||||
|
...this.userPageType, |
||||||
|
updateName: userTable1.nickname, |
||||||
|
createName: userTable2.nickname, |
||||||
|
}; |
||||||
|
const paginatedQuery = this.queryBuilder(getPacAuthUserAllDto, { |
||||||
|
...selectObject, |
||||||
|
roleList: sql`GROUP_CONCAT(DISTINCT ${pacAuthRole.roleName} ORDER BY ${pacAuthRole.orderNum} DESC SEPARATOR ',')`, |
||||||
|
deptList: sql`GROUP_CONCAT(DISTINCT ${pacAuthDept.deptName} ORDER BY ${pacAuthRole.orderNum} DESC SEPARATOR ',')`, |
||||||
|
postList: sql`GROUP_CONCAT(DISTINCT ${pacAuthPost.postName} ORDER BY ${pacAuthRole.orderNum} DESC SEPARATOR ',')`, |
||||||
|
}) |
||||||
|
.leftJoin(userTable2, eq(pacAuthUser.createby, userTable2.userId)) |
||||||
|
.leftJoin(userTable1, eq(pacAuthUser.updateby, userTable1.userId)) |
||||||
|
.leftJoin(pacAuthRole, eq(pacAuthLinkUserRole.roleId, pacAuthRole.roleId)) |
||||||
|
.leftJoin(pacAuthDept, eq(pacAuthLinkUserDept.deptId, pacAuthDept.deptId)) |
||||||
|
.leftJoin(pacAuthPost, eq(pacAuthLinkUserPost.postId, pacAuthPost.postId)) |
||||||
|
.limit(getPacAuthUserAllDto.pageSize) |
||||||
|
.groupBy(pacAuthUser.userId) |
||||||
|
.offset(offset); |
||||||
|
return { |
||||||
|
total: (await totalCountQuery)[0].totalCount, |
||||||
|
rowData: await paginatedQuery, |
||||||
|
searchData: getPacAuthUserAllDto, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// DB 查列表
|
||||||
|
private async getList(getPacAuthUserAllDto: GetPacAuthUserAllDto) { |
||||||
|
return this.queryBuilder(getPacAuthUserAllDto, this.userListType); |
||||||
|
} |
||||||
|
|
||||||
|
// DB 查详情
|
||||||
|
private async getMore(id: string) { |
||||||
|
const userTable1 = alias(pacAuthUser, 'userTable1'); |
||||||
|
const userTable2 = alias(pacAuthUser, 'userTable2'); |
||||||
|
const user = await this.mysqlService.db |
||||||
|
.select({ |
||||||
|
...this.userPageType, |
||||||
|
updateName: userTable1.nickname, |
||||||
|
createName: userTable2.nickname, |
||||||
|
}) |
||||||
|
.from(pacAuthUser) |
||||||
|
.leftJoin(pacCoreDict, eq(pacAuthUser.userType, pacCoreDict.dictId)) |
||||||
|
.leftJoin(userTable2, eq(pacAuthUser.createby, userTable2.userId)) |
||||||
|
.leftJoin(userTable1, eq(pacAuthUser.updateby, userTable1.userId)) |
||||||
|
.where(and(eq(pacAuthUser.userId, id), isNull(pacAuthUser.deleteby))); |
||||||
|
|
||||||
|
if (user.length == 0) throw new HttpException('未找到目标用户信息!', HttpStatus.BAD_REQUEST); |
||||||
|
const roleList = await this.mysqlService.db |
||||||
|
.select({ |
||||||
|
roleId: pacAuthRole.roleId, |
||||||
|
roleName: pacAuthRole.roleName, |
||||||
|
roleKey: pacAuthRole.roleKey, |
||||||
|
}) |
||||||
|
.from(pacAuthRole) |
||||||
|
.leftJoin(pacAuthLinkUserRole, eq(pacAuthLinkUserRole.roleId, pacAuthRole.roleId)) |
||||||
|
.where(eq(pacAuthLinkUserRole.userId, id)); |
||||||
|
const deptList = await this.mysqlService.db |
||||||
|
.select({ |
||||||
|
deptId: pacAuthDept.deptId, |
||||||
|
deptName: pacAuthDept.deptName, |
||||||
|
}) |
||||||
|
.from(pacAuthDept) |
||||||
|
.leftJoin(pacAuthLinkUserDept, eq(pacAuthLinkUserDept.deptId, pacAuthDept.deptId)) |
||||||
|
.where(eq(pacAuthLinkUserDept.userId, id)); |
||||||
|
const postList = await this.mysqlService.db |
||||||
|
.select({ |
||||||
|
postId: pacAuthPost.postId, |
||||||
|
postName: pacAuthPost.postName, |
||||||
|
postKey: pacAuthPost.postKey, |
||||||
|
}) |
||||||
|
.from(pacAuthPost) |
||||||
|
.leftJoin(pacAuthLinkUserPost, eq(pacAuthLinkUserPost.postId, pacAuthPost.postId)) |
||||||
|
.where(eq(pacAuthLinkUserPost.userId, id)); |
||||||
|
return { |
||||||
|
...user[0], |
||||||
|
roleList, |
||||||
|
deptList, |
||||||
|
postList, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// DB 删除账户
|
||||||
|
private async deleteUser(id: string, userId) { |
||||||
|
const user = await this.mysqlService.db |
||||||
|
.select({ id: pacAuthUser.userId, pid: pacAuthUser.pid }) |
||||||
|
.from(pacAuthUser) |
||||||
|
.where(and(isNull(pacAuthUser.deleteby), eq(pacAuthUser.userId, id))); |
||||||
|
if (user.length == 0) throw new HttpException('未找到目标用户信息,无法删除!', HttpStatus.BAD_REQUEST); |
||||||
|
|
||||||
|
// ! 清理角色菜单关联表
|
||||||
|
await this.mysqlService.db.delete(pacAuthLinkUserRole).where(eq(pacAuthLinkUserRole.userId as any, id)); |
||||||
|
|
||||||
|
// ! 清理部门菜单关联表
|
||||||
|
await this.mysqlService.db.delete(pacAuthLinkUserDept).where(eq(pacAuthLinkUserDept.userId as any, id)); |
||||||
|
|
||||||
|
// ! 清理岗位菜单关联表
|
||||||
|
await this.mysqlService.db.delete(pacAuthLinkUserPost).where(eq(pacAuthLinkUserPost.userId as any, id)); |
||||||
|
|
||||||
|
// ! 判断父节点是否存在
|
||||||
|
if (user[0].pid != 0) { |
||||||
|
// ! 减少父级子节点数量
|
||||||
|
await this.haveChildrenSelfIncreasing(user[0].pid, false); |
||||||
|
} |
||||||
|
|
||||||
|
// ! 删除角色数据
|
||||||
|
return await this.mysqlService.db |
||||||
|
.update(pacAuthUser) |
||||||
|
.set({ |
||||||
|
deletetime: sql`now()`, |
||||||
|
deleteby: userId, |
||||||
|
}) |
||||||
|
.where(eq(pacAuthUser.userId, id)); |
||||||
|
} |
||||||
|
|
||||||
|
// DB 更新账户
|
||||||
|
private async updateUser(id: string, updateAuthUserDto: UpdateAuthUserDto, pacInfo: PacInfoType) { |
||||||
|
const user = await this.mysqlService.db |
||||||
|
.select({ id: pacAuthUser.userId, pid: pacAuthUser.pid }) |
||||||
|
.from(pacAuthUser) |
||||||
|
.where(and(isNull(pacAuthUser.deleteby), eq(pacAuthUser.userId, id))); |
||||||
|
if (user.length == 0) throw new HttpException('未找到目标用户信息,无法修改!', HttpStatus.BAD_REQUEST); |
||||||
|
|
||||||
|
// 用户名不修改不需要查重
|
||||||
|
|
||||||
|
if (updateAuthUserDto.roleList) { |
||||||
|
await this.updateUserRole(id, updateAuthUserDto.roleList, pacInfo); |
||||||
|
} |
||||||
|
if (updateAuthUserDto.deptList) { |
||||||
|
await this.updateUserDept(id, updateAuthUserDto.deptList, pacInfo); |
||||||
|
} |
||||||
|
if (updateAuthUserDto.postList) { |
||||||
|
await this.updateUserPost(id, updateAuthUserDto.postList, pacInfo); |
||||||
|
} |
||||||
|
|
||||||
|
return await this.mysqlService.db |
||||||
|
.update(pacAuthUser) |
||||||
|
.set({ |
||||||
|
nickname: updateAuthUserDto.nickname, |
||||||
|
userType: updateAuthUserDto.userType, |
||||||
|
userEmail: updateAuthUserDto.userEmail, |
||||||
|
avatar: updateAuthUserDto.avatar, |
||||||
|
userPhone: updateAuthUserDto.userPhone, |
||||||
|
userDesc: updateAuthUserDto.userDesc, |
||||||
|
status: updateAuthUserDto.status, |
||||||
|
updateby: pacInfo.userId, |
||||||
|
updatetime: sql`now()`, |
||||||
|
}) |
||||||
|
.where(eq(pacAuthUser.userId, id)); |
||||||
|
} |
||||||
|
|
||||||
|
// DB 修改密码
|
||||||
|
private async resetPassword(id: string, newPassword: string | null) { |
||||||
|
let password = ''; |
||||||
|
if (newPassword != null) { |
||||||
|
password = newPassword; |
||||||
|
} else { |
||||||
|
// ! 从Redis获取默认密码
|
||||||
|
const defaultPasswordForRedis = await this.redisService.get('ENV_DEFAULT_PASSWORD'); |
||||||
|
|
||||||
|
// ? 判断redis中是否存在默认密码环境变量
|
||||||
|
if (!defaultPasswordForRedis) { |
||||||
|
password = this.config.get<string>('system.defaultPassword'); |
||||||
|
} else { |
||||||
|
password = defaultPasswordForRedis; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ! 加密密码
|
||||||
|
const pass = cryptoPassword(password, this.config.get<number>('system.passwordSalt')); |
||||||
|
|
||||||
|
return await this.mysqlService.db |
||||||
|
.update(pacAuthUser) |
||||||
|
.set({ |
||||||
|
password: pass, |
||||||
|
}) |
||||||
|
.where(eq(pacAuthUser.userId, id)); |
||||||
|
} |
||||||
|
|
||||||
|
// DB 查看目标是否存在
|
||||||
|
private async checkUserExist(id: string) { |
||||||
|
const user = await this.mysqlService.db |
||||||
|
.select({ id: pacAuthUser.userId, pid: pacAuthUser.pid }) |
||||||
|
.from(pacAuthUser) |
||||||
|
.where(and(isNull(pacAuthUser.deleteby), eq(pacAuthUser.userId, id))); |
||||||
|
if (user.length == 0) throw new HttpException('未找到目标用户信息,无法修改!', HttpStatus.BAD_REQUEST); |
||||||
|
return user[0]; |
||||||
|
} |
||||||
|
|
||||||
|
// DB 登陆检测
|
||||||
|
private async signinDetection(usernameSignInDto: UsernameSignInDto) { |
||||||
|
const user = await this.mysqlService.db |
||||||
|
.select({ userId: pacAuthUser.userId, pid: pacAuthUser.pid, password: pacAuthUser.password }) |
||||||
|
.from(pacAuthUser) |
||||||
|
.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<number>('system.signin.maxNumberFieldsignin'); |
||||||
|
} |
||||||
|
if (Number(number) >= maxNumberFieldsigninForRedis) { |
||||||
|
throw new HttpException(`登录错误次数过多:${number}次!`, HttpStatus.BAD_REQUEST); |
||||||
|
} |
||||||
|
|
||||||
|
// ! 验证密码
|
||||||
|
const pass = cryptoPassword(usernameSignInDto.password, this.config.get<number>('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<number>('system.signin.maxTimeFieldsignin'); |
||||||
|
} |
||||||
|
await this.redisService.redis.SET('SIGNIN_NUM' + user[0].userId, Number(number) ? Number(number) + 1 : 1, { |
||||||
|
PX: maxTimeFieldsignin, |
||||||
|
}); |
||||||
|
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<number>('system.signin.maxSigninClient'); |
||||||
|
} |
||||||
|
console.log(maxSigninClient, clientList.length >= maxSigninClient) |
||||||
|
if (clientList.length >= maxSigninClient) { |
||||||
|
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() }); |
||||||
|
|
||||||
|
// 将登陆的账户放进Redis
|
||||||
|
await this.redisService.redis.set('CLIENT-' + user[0].userId + '-' + MD5(refreshToken), 0, { |
||||||
|
EX: this.config.get<number>('system.signin.refreshTokenTime'), |
||||||
|
}); |
||||||
|
await this.redisService.redis.set('CLIENT-ONLINE-' + user[0].userId + '-' + MD5(token), 0, { |
||||||
|
EX: this.config.get<number>('system.signin.refreshTokenTime'), |
||||||
|
}); |
||||||
|
|
||||||
|
return { |
||||||
|
token, |
||||||
|
refreshToken, |
||||||
|
}; |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1 +1,161 @@ |
|||||||
export class CreateAuthUserDto {} |
import { ApiProperty } from '@nestjs/swagger'; |
||||||
|
import Trim from '@common/decorator/trim/trim.decorator'; |
||||||
|
import { ArrayMaxSize, ArrayMinSize, IsOptional, IsString, Length } from 'class-validator'; |
||||||
|
import FormatUsername from "@common/decorator/formatUsername/formatUsername"; |
||||||
|
|
||||||
|
export class CreateAuthUserDto { |
||||||
|
@ApiProperty({ |
||||||
|
description: '账户父ID', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 1, |
||||||
|
maxLength: 32, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '部门关联属性应为字符串格式!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly pid?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '头像', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 1, |
||||||
|
maxLength: 255, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '头像应为字符串格式!' }) |
||||||
|
@Length(1, 255, { message: '请将头像长度控制在1到255位之间!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly avatar?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '昵称', |
||||||
|
type: String, |
||||||
|
example: '研发经理', |
||||||
|
required: true, |
||||||
|
minLength: 1, |
||||||
|
maxLength: 32, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '昵称应为字符串格式!' }) |
||||||
|
@Length(1, 32, { message: '昵称长度控制在1到32位之间!' }) |
||||||
|
readonly nickname: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '岗位Id列表', |
||||||
|
type: [String], |
||||||
|
example: ['a'], |
||||||
|
required: true, |
||||||
|
minItems: 0, |
||||||
|
maxItems: 100, |
||||||
|
}) |
||||||
|
@IsString({ each: true, message: '岗位Id格式错误' }) |
||||||
|
@ArrayMinSize(0, { message: '至少需要选择一个岗位' }) |
||||||
|
@ArrayMaxSize(100, { message: '需要绑定的岗位超过限制' }) |
||||||
|
@Length(19, 19, { each: true, message: '岗位Id格式错误' }) |
||||||
|
@IsOptional() |
||||||
|
readonly postList: string[]; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '角色Id列表', |
||||||
|
type: [String], |
||||||
|
example: ['a'], |
||||||
|
required: true, |
||||||
|
minItems: 0, |
||||||
|
maxItems: 100, |
||||||
|
}) |
||||||
|
@IsString({ each: true, message: '角色Id格式错误' }) |
||||||
|
@ArrayMinSize(0, { message: '至少需要选择一个角色' }) |
||||||
|
@ArrayMaxSize(100, { message: '需要绑定的角色超过限制' }) |
||||||
|
@Length(19, 19, { each: true, message: '角色Id格式错误' }) |
||||||
|
@IsOptional() |
||||||
|
readonly roleList?: string[]; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '部门Id列表', |
||||||
|
type: [String], |
||||||
|
example: ['a'], |
||||||
|
required: true, |
||||||
|
minItems: 0, |
||||||
|
maxItems: 100, |
||||||
|
}) |
||||||
|
@IsString({ each: true, message: '部门Id格式错误' }) |
||||||
|
@ArrayMinSize(0, { message: '至少需要选择一个部门' }) |
||||||
|
@ArrayMaxSize(100, { message: '需要绑定的部门超过限制' }) |
||||||
|
@Length(19, 19, { each: true, message: '部门Id格式错误' }) |
||||||
|
@IsOptional() |
||||||
|
readonly deptList: string[]; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '账户描述', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 1, |
||||||
|
maxLength: 255, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '账户描述应为字符串格式!' }) |
||||||
|
@Length(1, 255, { message: '请将账户描述长度控制在1到255位之间!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly userDesc: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '邮箱', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 5, |
||||||
|
maxLength: 255, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '邮箱应为字符串格式!' }) |
||||||
|
@Length(5, 255, { message: '请将邮箱长度控制在5到255位之间!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly userEmail: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '用户名', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 4, |
||||||
|
maxLength: 128, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@FormatUsername() |
||||||
|
@IsString({ message: '用户名应为字符串格式!' }) |
||||||
|
@Length(4, 128, { message: '请将用户名长度控制在4到128位之间!' }) |
||||||
|
readonly username: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '手机号', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 11, |
||||||
|
maxLength: 11, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '手机号格式不正确!' }) |
||||||
|
@Length(11, 11, { message: '手机号格式不正确!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly userPhone: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '账户类型,来自于字典', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 19, |
||||||
|
maxLength: 19, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '账户类型格式不正确!' }) |
||||||
|
@Length(19, 19, { message: '账户类型格式不正确!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly userType: string; |
||||||
|
} |
||||||
|
@ -0,0 +1,175 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-x7129】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: get-auth-role.dto.ts -
|
||||||
|
// | @创建时间: 2024-06-25 17:22
|
||||||
|
// | @更新时间: 2024-06-25 17:22
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
|
||||||
|
import { GetDto } from '@dto/get.dto'; |
||||||
|
import { ApiProperty } from '@nestjs/swagger'; |
||||||
|
import Trim from '@common/decorator/trim/trim.decorator'; |
||||||
|
import { ArrayMaxSize, ArrayMinSize, IsEnum, IsInt, IsOptional, IsString, Length, Max, Min } from 'class-validator'; |
||||||
|
import { BooleanEnum } from '@utils/boolean.enum'; |
||||||
|
import Int from '@common/decorator/int/int.descrator'; |
||||||
|
|
||||||
|
export class GetPacAuthUserAllDto extends GetDto { |
||||||
|
@ApiProperty({ |
||||||
|
description: '账户信息', |
||||||
|
type: String, |
||||||
|
example: '管理员', |
||||||
|
required: false, |
||||||
|
minLength: 1, |
||||||
|
maxLength: 128, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '账户信息应为字符串格式!' }) |
||||||
|
@Length(0, 128, { message: '请将账户信息长度控制在1到128位之间!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly userInfo?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '账户类型,来自于字典', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 19, |
||||||
|
maxLength: 19, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '账户类型格式不正确!' }) |
||||||
|
@Length(19, 19, { message: '账户类型格式不正确!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly userType: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '是否存在子账户', |
||||||
|
type: BooleanEnum, |
||||||
|
enum: BooleanEnum, |
||||||
|
example: 0, |
||||||
|
required: false, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsEnum(BooleanEnum, { message: 'haveChildren参数格式错误' }) |
||||||
|
@IsOptional() |
||||||
|
readonly haveChildren: BooleanEnum; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '账户状态', |
||||||
|
type: Number, |
||||||
|
example: 0, |
||||||
|
required: false, |
||||||
|
minimum: -100, |
||||||
|
maximum: 100, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@Int() |
||||||
|
@IsInt({ |
||||||
|
message: '账户状态必须是整数!', |
||||||
|
}) |
||||||
|
@Min(-100, { |
||||||
|
message: '账户状态需要大于-100!', |
||||||
|
}) |
||||||
|
@Max(100, { |
||||||
|
message: '账户状态不能超过100', |
||||||
|
}) |
||||||
|
@IsOptional() |
||||||
|
readonly status?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '账户层级id', |
||||||
|
type: Number, |
||||||
|
example: 0, |
||||||
|
required: false, |
||||||
|
minimum: 0, |
||||||
|
maximum: 100, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '账户层级id应为字符串格式!' }) |
||||||
|
@Length(1, 20, { message: '账户层级id格式错误!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly hierarchy?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '角色Id', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 19, |
||||||
|
maxLength: 19, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '角色Id类型格式不正确!' }) |
||||||
|
@Length(19, 19, { message: '角色Id类型格式不正确!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly roleId?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '部门Id', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 19, |
||||||
|
maxLength: 19, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '部门Id类型格式不正确!' }) |
||||||
|
@Length(19, 19, { message: '部门Id类型格式不正确!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly deptId?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '岗位Id', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 19, |
||||||
|
maxLength: 19, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsString({ message: '岗位Id类型格式不正确!' }) |
||||||
|
@Length(19, 19, { message: '岗位Id类型格式不正确!' }) |
||||||
|
@IsOptional() |
||||||
|
readonly postId?: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '查没有角色的账户', |
||||||
|
type: BooleanEnum, |
||||||
|
enum: BooleanEnum, |
||||||
|
example: 0, |
||||||
|
required: false, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsEnum(BooleanEnum, { message: 'noRole参数格式错误' }) |
||||||
|
@IsOptional() |
||||||
|
readonly noRole: BooleanEnum; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '查没有部门的账户', |
||||||
|
type: BooleanEnum, |
||||||
|
enum: BooleanEnum, |
||||||
|
example: 0, |
||||||
|
required: false, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsEnum(BooleanEnum, { message: 'noDept参数格式错误' }) |
||||||
|
@IsOptional() |
||||||
|
readonly noDept: BooleanEnum; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '查没有岗位的账户', |
||||||
|
type: BooleanEnum, |
||||||
|
enum: BooleanEnum, |
||||||
|
example: 0, |
||||||
|
required: false, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@IsEnum(BooleanEnum, { message: 'noPost参数格式错误' }) |
||||||
|
@IsOptional() |
||||||
|
readonly noPost: BooleanEnum; |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-hotok】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: password.dto.ts -
|
||||||
|
// | @创建时间: 2024-06-29 22:01
|
||||||
|
// | @更新时间: 2024-06-29 22:01
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
|
||||||
|
import { ApiProperty } from '@nestjs/swagger'; |
||||||
|
import Trim from '@common/decorator/trim/trim.decorator'; |
||||||
|
import FormatUsername from '@common/decorator/formatUsername/formatUsername'; |
||||||
|
import { IsString, Length } from 'class-validator'; |
||||||
|
|
||||||
|
export class PasswordDto { |
||||||
|
@ApiProperty({ |
||||||
|
description: '新密码', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 8, |
||||||
|
maxLength: 128, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@FormatUsername() |
||||||
|
@IsString({ message: '新密码应为字符串格式!' }) |
||||||
|
@Length(8, 128, { message: '请将新密码长度控制在8到128位之间!' }) |
||||||
|
readonly newPassword: string; |
||||||
|
|
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '旧密码', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 6, |
||||||
|
maxLength: 128, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@FormatUsername() |
||||||
|
@IsString({ message: '旧密码应为字符串格式!' }) |
||||||
|
@Length(6, 128, { message: '请将旧密码长度控制在6到128位之间!' }) |
||||||
|
readonly oldPassword: string; |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-hotok】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: signin.dto.ts -
|
||||||
|
// | @创建时间: 2024-06-29 22:30
|
||||||
|
// | @更新时间: 2024-06-29 22:30
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
import { ApiProperty } from '@nestjs/swagger'; |
||||||
|
import Trim from '@common/decorator/trim/trim.decorator'; |
||||||
|
import FormatUsername from '@common/decorator/formatUsername/formatUsername'; |
||||||
|
import { IsString, Length } from 'class-validator'; |
||||||
|
|
||||||
|
export class UsernameSignInDto { |
||||||
|
@ApiProperty({ |
||||||
|
description: '用户名', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 4, |
||||||
|
maxLength: 128, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@FormatUsername() |
||||||
|
@IsString({ message: '用户名应为字符串格式!' }) |
||||||
|
@Length(4, 128, { message: '请将用户名长度控制在4到128位之间!' }) |
||||||
|
readonly username: string; |
||||||
|
|
||||||
|
@ApiProperty({ |
||||||
|
description: '新密码', |
||||||
|
type: String, |
||||||
|
example: '0', |
||||||
|
required: false, |
||||||
|
minLength: 6, |
||||||
|
maxLength: 128, |
||||||
|
}) |
||||||
|
@Trim() |
||||||
|
@FormatUsername() |
||||||
|
@IsString({ message: '新密码应为字符串格式!' }) |
||||||
|
@Length(6, 128, { message: '请将新密码长度控制在6到128位之间!' }) |
||||||
|
readonly password: string; |
||||||
|
} |
@ -1,4 +1,25 @@ |
|||||||
import { PartialType } from '@nestjs/swagger'; |
import { ApiProperty, PartialType } from '@nestjs/swagger'; |
||||||
import { CreateAuthUserDto } from './create-auth-user.dto'; |
import { CreateAuthUserDto } from './create-auth-user.dto'; |
||||||
|
import { IsInt, IsOptional, Max, Min } from 'class-validator'; |
||||||
|
|
||||||
export class UpdateAuthUserDto extends PartialType(CreateAuthUserDto) {} |
export class UpdateAuthUserDto extends PartialType(CreateAuthUserDto) { |
||||||
|
@ApiProperty({ |
||||||
|
description: '状态', |
||||||
|
type: Number, |
||||||
|
example: 10, |
||||||
|
required: false, |
||||||
|
minimum: -100, |
||||||
|
maximum: 100, |
||||||
|
}) |
||||||
|
@IsOptional() |
||||||
|
@IsInt({ |
||||||
|
message: '状态必须是整数!', |
||||||
|
}) |
||||||
|
@Min(-1000, { |
||||||
|
message: '状态不能小于-100!', |
||||||
|
}) |
||||||
|
@Max(1000, { |
||||||
|
message: '状态不能超过100', |
||||||
|
}) |
||||||
|
readonly status: number; |
||||||
|
} |
||||||
|
@ -0,0 +1,31 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-hotok】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: updateLink.dto.ts -
|
||||||
|
// | @创建时间: 2024-06-29 22:07
|
||||||
|
// | @更新时间: 2024-06-29 22:07
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
|
||||||
|
import { ApiProperty } from '@nestjs/swagger'; |
||||||
|
import { ArrayMaxSize, ArrayMinSize, IsString, Length } from 'class-validator'; |
||||||
|
|
||||||
|
export class UpdateLinkDto { |
||||||
|
@ApiProperty({ |
||||||
|
description: 'Id列表', |
||||||
|
type: [String], |
||||||
|
example: ['a'], |
||||||
|
required: true, |
||||||
|
minItems: 0, |
||||||
|
maxItems: 100, |
||||||
|
}) |
||||||
|
@IsString({ each: true, message: 'Id格式错误' }) |
||||||
|
@ArrayMinSize(0, { message: '至少需要选择一个id' }) |
||||||
|
@ArrayMaxSize(100, { message: '需要绑定的id超过限制' }) |
||||||
|
@Length(19, 19, { each: true, message: 'Id格式错误' }) |
||||||
|
readonly list: string[]; |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-hotok】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: formatUsername.ts -
|
||||||
|
// | @创建时间: 2024-06-29 16:20
|
||||||
|
// | @更新时间: 2024-06-29 16:20
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
|
||||||
|
import { Transform } from 'class-transformer'; |
||||||
|
|
||||||
|
export default function FormatUsername() { |
||||||
|
return Transform(({ value }) => { |
||||||
|
if (typeof value === 'string') { |
||||||
|
if (value.trim() == '') { |
||||||
|
return undefined; |
||||||
|
} |
||||||
|
return value.replace(/\s/g, '').toLowerCase(); |
||||||
|
} |
||||||
|
return value; |
||||||
|
}); |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
import { Injectable } from '@nestjs/common'; |
||||||
|
import { ConfigService } from '@nestjs/config'; |
||||||
|
import { LoggerService } from '@service/logger/logger.service'; |
||||||
|
import * as jwt from 'jsonwebtoken'; |
||||||
|
|
||||||
|
@Injectable() |
||||||
|
export class JwtService { |
||||||
|
constructor( |
||||||
|
private readonly configService: ConfigService, |
||||||
|
private readonly logger: LoggerService, |
||||||
|
) {} |
||||||
|
|
||||||
|
public token(payload: any): Promise<any> { |
||||||
|
return jwt.sign(payload, this.configService.get<string>('system.signin.secretKey'), { |
||||||
|
expiresIn: this.configService.get<number>('system.signin.tokenTime'), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public refreshToken(payload: any) { |
||||||
|
return jwt.sign(payload, this.configService.get<string>('system.signin.secretKey'), { |
||||||
|
expiresIn: this.configService.get<number>('system.signin.refreshTokenTime'), |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public verify(token: any) { |
||||||
|
jwt.verify(token, this.configService.get<string>('system.signin.secretKey')); |
||||||
|
} |
||||||
|
} |
@ -1,18 +0,0 @@ |
|||||||
import { Test, TestingModule } from '@nestjs/testing'; |
|
||||||
import { MysqlService } from './mysql.service'; |
|
||||||
|
|
||||||
describe('MysqlService', () => { |
|
||||||
let service: MysqlService; |
|
||||||
|
|
||||||
beforeEach(async () => { |
|
||||||
const module: TestingModule = await Test.createTestingModule({ |
|
||||||
providers: [MysqlService], |
|
||||||
}).compile(); |
|
||||||
|
|
||||||
service = module.get<MysqlService>(MysqlService); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should be defined', () => { |
|
||||||
expect(service).toBeDefined(); |
|
||||||
}); |
|
||||||
}); |
|
@ -1,18 +0,0 @@ |
|||||||
import { Test, TestingModule } from '@nestjs/testing'; |
|
||||||
import { RedisService } from './redis.service'; |
|
||||||
|
|
||||||
describe('RedisService', () => { |
|
||||||
let service: RedisService; |
|
||||||
|
|
||||||
beforeEach(async () => { |
|
||||||
const module: TestingModule = await Test.createTestingModule({ |
|
||||||
providers: [RedisService], |
|
||||||
}).compile(); |
|
||||||
|
|
||||||
service = module.get<RedisService>(RedisService); |
|
||||||
}); |
|
||||||
|
|
||||||
it('should be defined', () => { |
|
||||||
expect(service).toBeDefined(); |
|
||||||
}); |
|
||||||
}); |
|
@ -1,3 +1,2 @@ |
|||||||
import { relations } from "drizzle-orm/relations"; |
import { relations } from 'drizzle-orm/relations'; |
||||||
import { } from "./schema"; |
import {} from './schema'; |
||||||
|
|
||||||
|
@ -0,0 +1,17 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-hotok】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: MD5.ts -
|
||||||
|
// | @创建时间: 2024-06-29 23:50
|
||||||
|
// | @更新时间: 2024-06-29 23:50
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
import * as crypto from 'node:crypto'; |
||||||
|
|
||||||
|
export default function MD5(data) { |
||||||
|
return crypto.createHash('md5').update(data).digest('hex').toUpperCase(); |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-hotok】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: cryptoPassword.ts -
|
||||||
|
// | @创建时间: 2024-06-29 15:44
|
||||||
|
// | @更新时间: 2024-06-29 15:44
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
|
||||||
|
import * as crypto from 'node:crypto'; |
||||||
|
export default function cryptoPassword(str: string, salt) { |
||||||
|
return crypto |
||||||
|
.createHash('sha256') |
||||||
|
.update(salt + str) |
||||||
|
.digest('hex'); |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
// | ------------------------------------------------------------
|
||||||
|
// | @版本: version 0.1
|
||||||
|
// | @创建人: 【Nie-hotok】
|
||||||
|
// | @E-mail: x71291@outlook.com
|
||||||
|
// | @所在项目: pac-auth
|
||||||
|
// | @文件描述: 密码随机盐.js -
|
||||||
|
// | @创建时间: 2024-06-29 15:46
|
||||||
|
// | @更新时间: 2024-06-29 15:46
|
||||||
|
// | @修改记录:
|
||||||
|
// | -*-*-*- (时间--修改人--修改说明) -*-*-*-
|
||||||
|
// | =
|
||||||
|
// | ------------------------------------------------------------
|
||||||
|
const crypto = require('crypto'); |
||||||
|
const salt = crypto.randomBytes(16).toString('hex'); |
||||||
|
|
||||||
|
console.log('A', salt); |
Loading…
Reference in new issue