|
|
@ -8,11 +8,22 @@ import { Snowflake } from '@service/snowflake/snowflake.service'; |
|
|
|
import { ConfigService } from '@nestjs/config'; |
|
|
|
import { ConfigService } from '@nestjs/config'; |
|
|
|
import { PacInfoType } from '@utils/myType'; |
|
|
|
import { PacInfoType } from '@utils/myType'; |
|
|
|
import { isExistKey, isTrueEnum } from '@utils/boolean.enum'; |
|
|
|
import { isExistKey, isTrueEnum } from '@utils/boolean.enum'; |
|
|
|
import { pacAuthDept, pacAuthLinkRoleDept, pacAuthLinkRoleMenu, pacAuthRole, pacAuthUser, pacCoreDict, pacCoreMenu } from '@entities/schema'; |
|
|
|
import { |
|
|
|
import { and, asc, desc, eq, isNull, like, or, sql } from 'drizzle-orm'; |
|
|
|
pacAuthDept, |
|
|
|
import { GetPacAuthRoleAllDto } from '@app/auth-role/dto/get-auth-role.dto'; |
|
|
|
pacAuthLinkRoleDept, |
|
|
|
|
|
|
|
pacAuthLinkRoleMenu, |
|
|
|
|
|
|
|
pacAuthLinkUserRole, |
|
|
|
|
|
|
|
pacAuthRole, |
|
|
|
|
|
|
|
pacAuthUser, |
|
|
|
|
|
|
|
pacCoreDict, |
|
|
|
|
|
|
|
pacCoreMenu, |
|
|
|
|
|
|
|
} from '@entities/schema'; |
|
|
|
|
|
|
|
import { and, asc, desc, eq, inArray, isNull, like, or, SQL, sql } from 'drizzle-orm'; |
|
|
|
|
|
|
|
import { GetPacAuthRoleAllDto, GetUserForRoleDto } from '@app/auth-role/dto/get-auth-role.dto'; |
|
|
|
import { likeQuery } from '@utils/likeQuery'; |
|
|
|
import { likeQuery } from '@utils/likeQuery'; |
|
|
|
import { alias } from 'drizzle-orm/mysql-core'; |
|
|
|
import { alias, QueryBuilder } from 'drizzle-orm/mysql-core'; |
|
|
|
|
|
|
|
import { customDrizzleRowWithRecursive } from '@utils/customDrizzleRowWithRecursive'; |
|
|
|
|
|
|
|
import { RoleLinkUserDto } from '@app/auth-role/dto/roleLinkUser.dto'; |
|
|
|
|
|
|
|
|
|
|
|
@Injectable() |
|
|
|
@Injectable() |
|
|
|
export class AuthRoleService { |
|
|
|
export class AuthRoleService { |
|
|
@ -38,28 +49,6 @@ export class AuthRoleService { |
|
|
|
updatetime: pacAuthRole.updatetime, |
|
|
|
updatetime: pacAuthRole.updatetime, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// 角色详细信息
|
|
|
|
|
|
|
|
private readonly roleMoreType = { |
|
|
|
|
|
|
|
roleId: pacAuthRole.roleId, |
|
|
|
|
|
|
|
pid: pacAuthRole.pid, |
|
|
|
|
|
|
|
roleName: pacAuthRole.roleName, |
|
|
|
|
|
|
|
roleKey: pacAuthRole.roleKey, |
|
|
|
|
|
|
|
roleDesc: pacAuthRole.roleDesc, |
|
|
|
|
|
|
|
roleType: pacAuthRole.roleType, |
|
|
|
|
|
|
|
roleTypeName: pacCoreDict.dictName, |
|
|
|
|
|
|
|
roleTypeKey: pacCoreDict.dictKey, |
|
|
|
|
|
|
|
deptScope: pacAuthRole.deptScope, |
|
|
|
|
|
|
|
root: pacAuthRole.root, |
|
|
|
|
|
|
|
orderNum: pacAuthRole.orderNum, |
|
|
|
|
|
|
|
status: pacAuthRole.status, |
|
|
|
|
|
|
|
createby: pacAuthRole.createby, |
|
|
|
|
|
|
|
createName: pacAuthUser.nickname, |
|
|
|
|
|
|
|
createtime: pacAuthRole.createtime, |
|
|
|
|
|
|
|
updateby: pacAuthRole.updateby, |
|
|
|
|
|
|
|
updateName: pacAuthUser.nickname, |
|
|
|
|
|
|
|
updatetime: pacAuthRole.updatetime, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 角色列表/数信息
|
|
|
|
// 角色列表/数信息
|
|
|
|
private readonly roleListType = { |
|
|
|
private readonly roleListType = { |
|
|
|
roleId: pacAuthRole.roleId, |
|
|
|
roleId: pacAuthRole.roleId, |
|
|
@ -163,6 +152,25 @@ export class AuthRoleService { |
|
|
|
return this.getRoleMore(id); |
|
|
|
return this.getRoleMore(id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Service |
|
|
|
|
|
|
|
* NAME: findTree |
|
|
|
|
|
|
|
* DESC: 获取角色树结构信息 |
|
|
|
|
|
|
|
* DATE: 2024-06-27 14:23:36 - |
|
|
|
|
|
|
|
* */ |
|
|
|
|
|
|
|
public async findTree(pid: string) { |
|
|
|
|
|
|
|
const [result] = await this.getRoleTree(pid); |
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Service |
|
|
|
|
|
|
|
* NAME: findUserByRoleId |
|
|
|
|
|
|
|
* DESC: 获取角色下的关联账户 |
|
|
|
|
|
|
|
* DATE: 2024-06-27 14:49:42 - |
|
|
|
|
|
|
|
* */ |
|
|
|
|
|
|
|
public async findUserByRoleId(roleId: string, getUserForRoleDto: GetUserForRoleDto) { |
|
|
|
|
|
|
|
return await this.getRoleUser(roleId, getUserForRoleDto); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public async update(roleId: string, updateAuthRoleDto: UpdateAuthRoleDto, pacInfo: PacInfoType) { |
|
|
|
public async update(roleId: string, updateAuthRoleDto: UpdateAuthRoleDto, pacInfo: PacInfoType) { |
|
|
|
// ! 查找角色信息
|
|
|
|
// ! 查找角色信息
|
|
|
|
const roleData = await this.getRoleForRoleId(roleId); |
|
|
|
const roleData = await this.getRoleForRoleId(roleId); |
|
|
@ -232,6 +240,24 @@ export class AuthRoleService { |
|
|
|
return await this.deleteRole(roleId, pacInfo.userId as any); |
|
|
|
return await this.deleteRole(roleId, pacInfo.userId as any); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Service |
|
|
|
|
|
|
|
* NAME: linkUser |
|
|
|
|
|
|
|
* DESC: 关联账户给角色 |
|
|
|
|
|
|
|
* DATE: 2024-06-27 15:38:50 - |
|
|
|
|
|
|
|
* */ |
|
|
|
|
|
|
|
public async linkUser(roleLinkUserDto: RoleLinkUserDto, pacInfo: PacInfoType) { |
|
|
|
|
|
|
|
return this.linkUserForRole(roleLinkUserDto, pacInfo); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Service |
|
|
|
|
|
|
|
* NAME: unlinkUser |
|
|
|
|
|
|
|
* DESC: 取消关联账户给角色 |
|
|
|
|
|
|
|
* DATE: 2024-06-27 15:38:54 - |
|
|
|
|
|
|
|
* */ |
|
|
|
|
|
|
|
public async unlinkUser(roleLinkUserDto: RoleLinkUserDto) { |
|
|
|
|
|
|
|
return this.unlinkUserForRole(roleLinkUserDto); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// DB 通过roleKey查找角色信息
|
|
|
|
// DB 通过roleKey查找角色信息
|
|
|
|
private getRoleForRoleKey(key: string) { |
|
|
|
private getRoleForRoleKey(key: string) { |
|
|
|
return this.mysqlService.db |
|
|
|
return this.mysqlService.db |
|
|
@ -387,11 +413,41 @@ export class AuthRoleService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// DB 查角色树
|
|
|
|
// DB 查角色树
|
|
|
|
getRoleTree() {} |
|
|
|
private getRoleTree(pid: string) { |
|
|
|
|
|
|
|
// ! 基础层级
|
|
|
|
|
|
|
|
const baseQueryBuilder = new QueryBuilder(); |
|
|
|
|
|
|
|
const baseQuery = baseQueryBuilder |
|
|
|
|
|
|
|
.select({ |
|
|
|
|
|
|
|
...this.roleListType, |
|
|
|
|
|
|
|
level: sql`0`.as('level'), |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.from(pacAuthRole) |
|
|
|
|
|
|
|
.leftJoin(pacCoreDict, eq(pacAuthRole.roleType, pacCoreDict.dictId)) |
|
|
|
|
|
|
|
.where(and(isNull(pacAuthRole.deleteby), eq(pacAuthRole.pid, pid))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 递归层级
|
|
|
|
|
|
|
|
const recursiveQueryBuilder = new QueryBuilder(); |
|
|
|
|
|
|
|
const recursiveQuery = recursiveQueryBuilder |
|
|
|
|
|
|
|
.select({ |
|
|
|
|
|
|
|
...this.roleListType, |
|
|
|
|
|
|
|
level: sql`roleHierarchy.level + 1`.as('level'), |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.from(pacAuthRole) |
|
|
|
|
|
|
|
.leftJoin(pacCoreDict, eq(pacAuthRole.roleType, pacCoreDict.dictId)) |
|
|
|
|
|
|
|
.where(isNull(pacAuthRole.deleteby)) |
|
|
|
|
|
|
|
.innerJoin(sql`roleHierarchy`, sql`roleHierarchy.roleId = ${pacAuthRole.pid}`); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const rowName: SQL = customDrizzleRowWithRecursive(this.roleListType); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 执行原始SQL查询
|
|
|
|
|
|
|
|
return this.mysqlService.db.execute( |
|
|
|
|
|
|
|
sql`WITH RECURSIVE roleHierarchy(${rowName}) AS(${baseQuery} UNION ALL ${recursiveQuery}) SELECT * FROM roleHierarchy`, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// DB 查角色详细信息
|
|
|
|
// DB 查角色详细信息
|
|
|
|
private async getRoleMore(roleId: string) { |
|
|
|
private async getRoleMore(roleId: string) { |
|
|
|
// ! 定义2次连表查询的用户表
|
|
|
|
// ! 定义2次连表查询的账户表
|
|
|
|
const userTable1 = alias(pacAuthUser, 'userTable1'); |
|
|
|
const userTable1 = alias(pacAuthUser, 'userTable1'); |
|
|
|
|
|
|
|
|
|
|
|
// ! 查询目标角色信息
|
|
|
|
// ! 查询目标角色信息
|
|
|
@ -514,4 +570,129 @@ export class AuthRoleService { |
|
|
|
}) |
|
|
|
}) |
|
|
|
.where(eq(pacAuthRole.roleId, roleId)); |
|
|
|
.where(eq(pacAuthRole.roleId, roleId)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DB 查找角色下的账户查询构建
|
|
|
|
|
|
|
|
private getRoleUserQuery(roleId: string, getUserForRoleDto: GetUserForRoleDto, selectData = null) { |
|
|
|
|
|
|
|
const query = this.mysqlService.db |
|
|
|
|
|
|
|
.select(selectData) |
|
|
|
|
|
|
|
.from(pacAuthUser) |
|
|
|
|
|
|
|
.orderBy(isTrueEnum(getUserForRoleDto.isAsc) ? asc(pacAuthUser.userId) : desc(pacAuthUser.userId)) |
|
|
|
|
|
|
|
.leftJoin(pacCoreDict, eq(pacAuthUser.userType, pacCoreDict.dictId)) |
|
|
|
|
|
|
|
.leftJoin(pacAuthLinkUserRole, eq(pacAuthLinkUserRole.userId, pacAuthUser.userId)) |
|
|
|
|
|
|
|
.$dynamic(); |
|
|
|
|
|
|
|
const wl = []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ? 未删除
|
|
|
|
|
|
|
|
wl.push(isNull(pacAuthUser.deleteby)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ? 模糊查询
|
|
|
|
|
|
|
|
wl.push( |
|
|
|
|
|
|
|
or( |
|
|
|
|
|
|
|
like(pacAuthUser.nickname, likeQuery(getUserForRoleDto.userInfo)), |
|
|
|
|
|
|
|
like(pacAuthUser.userDesc, likeQuery(getUserForRoleDto.userInfo)), |
|
|
|
|
|
|
|
like(pacAuthUser.userEmail, likeQuery(getUserForRoleDto.userInfo)), |
|
|
|
|
|
|
|
like(pacAuthUser.userPhone, likeQuery(getUserForRoleDto.userInfo)), |
|
|
|
|
|
|
|
like(pacAuthUser.username, likeQuery(getUserForRoleDto.userInfo)), |
|
|
|
|
|
|
|
).if(isExistKey(getUserForRoleDto, 'userInfo')), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ? 目标roleId
|
|
|
|
|
|
|
|
wl.push(eq(pacAuthLinkUserRole.roleId, roleId)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ? 用户类型
|
|
|
|
|
|
|
|
wl.push(eq(pacAuthUser.userType, getUserForRoleDto.userType).if(isExistKey(getUserForRoleDto, 'userType'))); |
|
|
|
|
|
|
|
query.where(and(...wl)); |
|
|
|
|
|
|
|
return query; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DB 查找角色下的账户
|
|
|
|
|
|
|
|
private async getRoleUser(roleId: string, getUserForRoleDto: GetUserForRoleDto) { |
|
|
|
|
|
|
|
const offset = (getUserForRoleDto.pageNumber - 1) * getUserForRoleDto.pageSize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 使用基础查询构建查询总记录数
|
|
|
|
|
|
|
|
const totalCountQuery = this.getRoleData(getUserForRoleDto, { |
|
|
|
|
|
|
|
totalCount: sql`COUNT(*)`, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 使用基础查询构建分页查询
|
|
|
|
|
|
|
|
// 重命名表
|
|
|
|
|
|
|
|
const userTable1 = alias(pacAuthUser, 'userTable1'); |
|
|
|
|
|
|
|
const userTable2 = alias(pacAuthUser, 'userTable2'); |
|
|
|
|
|
|
|
const paginatedQuery = this.getRoleUserQuery(roleId, getUserForRoleDto, { |
|
|
|
|
|
|
|
userId: pacAuthUser.userId, |
|
|
|
|
|
|
|
username: pacAuthUser.username, |
|
|
|
|
|
|
|
nickname: pacAuthUser.nickname, |
|
|
|
|
|
|
|
userType: pacAuthUser.userType, |
|
|
|
|
|
|
|
userTypeName: pacCoreDict.dictName, |
|
|
|
|
|
|
|
userTypeKey: pacCoreDict.dictKey, |
|
|
|
|
|
|
|
userEmail: pacAuthUser.userEmail, |
|
|
|
|
|
|
|
avatar: pacAuthUser.avatar, |
|
|
|
|
|
|
|
userPhone: pacAuthUser.userPhone, |
|
|
|
|
|
|
|
userDesc: pacAuthUser.userDesc, |
|
|
|
|
|
|
|
haveChildren: pacAuthUser.haveChildren, |
|
|
|
|
|
|
|
createby: pacAuthUser.createby, |
|
|
|
|
|
|
|
createName: userTable2.nickname, |
|
|
|
|
|
|
|
createtime: pacAuthUser.createtime, |
|
|
|
|
|
|
|
updateName: userTable1.nickname, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.leftJoin(userTable2, eq(pacAuthUser.createby, userTable2.userId)) |
|
|
|
|
|
|
|
.leftJoin(userTable1, eq(pacAuthUser.updateby, userTable1.userId)) |
|
|
|
|
|
|
|
.limit(getUserForRoleDto.pageSize) |
|
|
|
|
|
|
|
.offset(offset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
total: (await totalCountQuery)[0].totalCount, |
|
|
|
|
|
|
|
rowData: await paginatedQuery, |
|
|
|
|
|
|
|
searchData: getUserForRoleDto, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DB 查找角色账户关联数据
|
|
|
|
|
|
|
|
private async getRoleLinkUser(roleId: string, userIdList: string[]) { |
|
|
|
|
|
|
|
return this.mysqlService.db |
|
|
|
|
|
|
|
.select({ |
|
|
|
|
|
|
|
id: pacAuthLinkUserRole.userId, |
|
|
|
|
|
|
|
index: pacAuthLinkUserRole.index, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
.from(pacAuthLinkUserRole) |
|
|
|
|
|
|
|
.where(and(eq(pacAuthLinkUserRole.roleId, roleId), inArray(pacAuthLinkUserRole.userId, userIdList))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DB 给角色关联上账户
|
|
|
|
|
|
|
|
private async linkUserForRole(roleLinkUserDto: RoleLinkUserDto, pacInfo: PacInfoType) { |
|
|
|
|
|
|
|
// ! 去重账户ID
|
|
|
|
|
|
|
|
const deduplicateUserId = Array.from(new Set(roleLinkUserDto.userIdList)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 查找角色是否存在这些账户
|
|
|
|
|
|
|
|
const existUser = await this.getRoleLinkUser(roleLinkUserDto.roleId, deduplicateUserId); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 获取已存在的账户Id
|
|
|
|
|
|
|
|
const existUserIdList = existUser.map((user) => user.id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 过滤已经存在的账户
|
|
|
|
|
|
|
|
const userIdList = roleLinkUserDto.userIdList.filter((i) => !existUserIdList.includes(i)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return await this.mysqlService.db.insert(pacAuthLinkUserRole).values( |
|
|
|
|
|
|
|
userIdList.map((i) => ({ |
|
|
|
|
|
|
|
roleId: roleLinkUserDto.roleId, |
|
|
|
|
|
|
|
userId: i, |
|
|
|
|
|
|
|
createby: pacInfo.userId, |
|
|
|
|
|
|
|
createtime: sql`now()` as any, |
|
|
|
|
|
|
|
})), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DB 取消角色关联的账户
|
|
|
|
|
|
|
|
private async unlinkUserForRole(roleLinkUserDto: RoleLinkUserDto) { |
|
|
|
|
|
|
|
// ! 去重账户ID
|
|
|
|
|
|
|
|
const deduplicateUserId = Array.from(new Set(roleLinkUserDto.userIdList)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 查找角色是否存在这些账户
|
|
|
|
|
|
|
|
const existUser = await this.getRoleLinkUser(roleLinkUserDto.roleId, deduplicateUserId); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ! 获取已存在的账户Id
|
|
|
|
|
|
|
|
const existUserIndexList = existUser.map((user) => user.index); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return await this.mysqlService.db.delete(pacAuthLinkUserRole).where(inArray(pacAuthLinkUserRole.index, existUserIndexList)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|