feat(ops): add global test whitelist and exclude test accounts from settlement

Unify product/store visibility on HQ whitelist, mark isTest snapshots, and fix SUPER_ADMIN access for the new module.
This commit is contained in:
2026-08-07 15:46:23 +08:00
parent 10fa361983
commit b626db5d84
47 changed files with 1823 additions and 308 deletions
@@ -7,11 +7,10 @@ import {
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import {
HQ_DANGEROUS_PERMISSION_KEYS,
HQ_PERMISSION_CATALOG,
HQ_ROLE_DEFAULT_PERMISSIONS,
expandHqPermissionKeys,
hasAnySystemSettingsPermission,
hqBasePermissionKeys,
type HqPermissionKey,
} from '@dukang/shared-types';
import { PrismaService } from '../prisma/prisma.module';
@@ -28,7 +27,7 @@ export const RequireAnySystemSettings = () =>
export class HqPermissionsResolver {
constructor(private readonly prisma: PrismaService) {}
async resolveEffectiveKeys(actorId: bigint): Promise<HqPermissionKey[]> {
private async loadActiveAccount(actorId: bigint) {
const account = await this.prisma.hqAccount.findUnique({
where: { id: actorId },
select: { adminRole: true, status: true },
@@ -36,6 +35,14 @@ export class HqPermissionsResolver {
if (!account || account.status !== 'ACTIVE') {
throw new ForbiddenException('HQ 账号不可用');
}
return account;
}
async resolveAccess(actorId: bigint): Promise<{
keys: HqPermissionKey[];
isSuperAdmin: boolean;
}> {
const account = await this.loadActiveAccount(actorId);
const userRows = await this.prisma.hqAccountPermission.findMany({
where: { hqAccountId: actorId },
@@ -44,12 +51,14 @@ export class HqPermissionsResolver {
const userKeys = userRows.map((r) => r.permissionKey);
if (account.adminRole === 'SUPER_ADMIN') {
// 超管含危险操作(删用户/订单/城市);其他角色仍需在权限分配中显式勾选
return expandHqPermissionKeys([
...hqBasePermissionKeys(),
...HQ_DANGEROUS_PERMISSION_KEYS,
...userKeys,
]);
// 超管拥有权限目录内全部项(含后续新增),另含危险操作与用户级附加项
return {
isSuperAdmin: true,
keys: expandHqPermissionKeys([
...HQ_PERMISSION_CATALOG.map((p) => p.key),
...userKeys,
]),
};
}
const roleRows = await this.prisma.hqRolePermission.findMany({
@@ -62,7 +71,15 @@ export class HqPermissionsResolver {
? roleRows.map((r) => r.permissionKey)
: [...(HQ_ROLE_DEFAULT_PERMISSIONS[account.adminRole] ?? [])];
return expandHqPermissionKeys([...roleKeys, ...userKeys]);
return {
isSuperAdmin: false,
keys: expandHqPermissionKeys([...roleKeys, ...userKeys]),
};
}
async resolveEffectiveKeys(actorId: bigint): Promise<HqPermissionKey[]> {
const { keys } = await this.resolveAccess(actorId);
return keys;
}
}
@@ -79,7 +96,7 @@ export class HqPermissionGuard implements CanActivate {
if (!user || user.actorType !== 'HQ') {
throw new ForbiddenException('需要 HQ 权限');
}
const keys = await this.resolver.resolveEffectiveKeys(user.actorId);
const { keys, isSuperAdmin } = await this.resolver.resolveAccess(user.actorId);
req.hqPermissionKeys = keys;
const required =
@@ -89,6 +106,7 @@ export class HqPermissionGuard implements CanActivate {
]) ?? [];
if (!required.length) return true;
if (isSuperAdmin) return true;
if (required.includes('__any_system_settings__')) {
if (!hasAnySystemSettingsPermission(keys)) {
throw new ForbiddenException('无系统设置权限');