b626db5d84
Unify product/store visibility on HQ whitelist, mark isTest snapshots, and fix SUPER_ADMIN access for the new module.
131 lines
4.5 KiB
TypeScript
131 lines
4.5 KiB
TypeScript
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
|
import {
|
|
HQ_PERMISSION_CATALOG,
|
|
HQ_ROLE_DEFAULT_PERMISSIONS,
|
|
LEGACY_SYSTEM_SETTINGS_KEY,
|
|
expandHqPermissionKeys,
|
|
type HqPermissionKey,
|
|
} from '@dukang/shared-types';
|
|
import { PrismaService } from '../../common/prisma/prisma.module';
|
|
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
|
|
|
const VALID_PERMISSION_KEYS = new Set<string>([
|
|
...HQ_PERMISSION_CATALOG.map((p) => p.key),
|
|
LEGACY_SYSTEM_SETTINGS_KEY,
|
|
]);
|
|
|
|
function assertPermissionKeys(keys: string[]) {
|
|
const invalid = keys.filter((key) => !VALID_PERMISSION_KEYS.has(key));
|
|
if (invalid.length) {
|
|
throw new BadRequestException(`无效权限项: ${invalid.join(', ')}`);
|
|
}
|
|
}
|
|
|
|
@Injectable()
|
|
export class AdminHqPermissionsService {
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
catalog() {
|
|
return {
|
|
permissions: HQ_PERMISSION_CATALOG,
|
|
roles: Object.entries(HQ_ROLE_DEFAULT_PERMISSIONS).map(([role, permissionKeys]) => ({
|
|
role,
|
|
permissionKeys,
|
|
})),
|
|
};
|
|
}
|
|
|
|
async getRolePermissions(role: string) {
|
|
const rows = await this.prisma.hqRolePermission.findMany({
|
|
where: { adminRole: role as 'SUPER_ADMIN' | 'OPS' | 'FINANCE' | 'CUSTOMER_SERVICE' },
|
|
select: { permissionKey: true },
|
|
});
|
|
const permissionKeys =
|
|
rows.length > 0
|
|
? expandHqPermissionKeys(rows.map((r) => r.permissionKey))
|
|
: [...(HQ_ROLE_DEFAULT_PERMISSIONS[role] ?? [])];
|
|
return { role, permissionKeys };
|
|
}
|
|
|
|
async saveRolePermissions(role: string, permissionKeys: string[]) {
|
|
if (role === 'SUPER_ADMIN') {
|
|
throw new BadRequestException('超级管理员基础权限固定,危险操作请按用户单独授权');
|
|
}
|
|
assertPermissionKeys(permissionKeys);
|
|
const normalized = expandHqPermissionKeys(permissionKeys);
|
|
const adminRole = role as 'OPS' | 'FINANCE' | 'CUSTOMER_SERVICE';
|
|
await this.prisma.$transaction([
|
|
this.prisma.hqRolePermission.deleteMany({ where: { adminRole } }),
|
|
...(normalized.length
|
|
? [
|
|
this.prisma.hqRolePermission.createMany({
|
|
data: normalized.map((permissionKey) => ({ adminRole, permissionKey })),
|
|
}),
|
|
]
|
|
: []),
|
|
]);
|
|
return this.getRolePermissions(role);
|
|
}
|
|
|
|
async getAccountPermissions(accountId: bigint) {
|
|
const account = await this.prisma.hqAccount.findUnique({
|
|
where: { id: accountId },
|
|
select: { id: true, name: true, phone: true, loginName: true, adminRole: true, status: true },
|
|
});
|
|
if (!account) throw new NotFoundException('HQ 账号不存在');
|
|
|
|
const userPerms = await this.prisma.hqAccountPermission.findMany({
|
|
where: { hqAccountId: accountId },
|
|
select: { permissionKey: true },
|
|
});
|
|
const userPermissionKeys = expandHqPermissionKeys(userPerms.map((p) => p.permissionKey));
|
|
|
|
if (account.adminRole === 'SUPER_ADMIN') {
|
|
const rolePermissionKeys = HQ_PERMISSION_CATALOG.map(
|
|
(p) => p.key,
|
|
) as HqPermissionKey[];
|
|
const effectivePermissionKeys = [
|
|
...new Set([...rolePermissionKeys, ...userPermissionKeys]),
|
|
] as HqPermissionKey[];
|
|
return serializeBigInt({
|
|
account,
|
|
permissionKeys: userPermissionKeys,
|
|
rolePermissionKeys,
|
|
userPermissionKeys,
|
|
effectivePermissionKeys,
|
|
});
|
|
}
|
|
|
|
const rolePerms = await this.getRolePermissions(account.adminRole);
|
|
const effectivePermissionKeys = [
|
|
...new Set([...rolePerms.permissionKeys, ...userPermissionKeys]),
|
|
] as HqPermissionKey[];
|
|
|
|
return serializeBigInt({
|
|
account,
|
|
permissionKeys: userPermissionKeys,
|
|
rolePermissionKeys: rolePerms.permissionKeys,
|
|
userPermissionKeys,
|
|
effectivePermissionKeys,
|
|
});
|
|
}
|
|
|
|
async saveAccountPermissions(accountId: bigint, permissionKeys: string[]) {
|
|
const account = await this.prisma.hqAccount.findUnique({ where: { id: accountId } });
|
|
if (!account) throw new NotFoundException('HQ 账号不存在');
|
|
assertPermissionKeys(permissionKeys);
|
|
const normalized = expandHqPermissionKeys(permissionKeys);
|
|
await this.prisma.$transaction([
|
|
this.prisma.hqAccountPermission.deleteMany({ where: { hqAccountId: accountId } }),
|
|
...(normalized.length
|
|
? [
|
|
this.prisma.hqAccountPermission.createMany({
|
|
data: normalized.map((permissionKey) => ({ hqAccountId: accountId, permissionKey })),
|
|
}),
|
|
]
|
|
: []),
|
|
]);
|
|
return this.getAccountPermissions(accountId);
|
|
}
|
|
}
|