feat: 支持动态角色权限分配
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
import type { PoolConnection, RowDataPacket } from "mysql2/promise";
|
||||
import { pool } from "../../db/pool";
|
||||
|
||||
type DbExecutor = typeof pool | PoolConnection;
|
||||
|
||||
export interface RolePermissionRecord {
|
||||
roleId: number;
|
||||
roleCode: string;
|
||||
roleName: string;
|
||||
roleDescription: string | null;
|
||||
isSystem: boolean;
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
interface RolePermissionRow extends RowDataPacket {
|
||||
role_id: number;
|
||||
role_code: string;
|
||||
role_name: string;
|
||||
role_description: string | null;
|
||||
is_system: number;
|
||||
permission_code: string | null;
|
||||
}
|
||||
|
||||
interface PermissionCodeRow extends RowDataPacket {
|
||||
permission_code: string;
|
||||
}
|
||||
|
||||
function toRolePermissionRecords(
|
||||
rows: RolePermissionRow[],
|
||||
): RolePermissionRecord[] {
|
||||
const records = new Map<number, RolePermissionRecord>();
|
||||
|
||||
for (const row of rows) {
|
||||
const record = records.get(row.role_id) ?? {
|
||||
roleId: row.role_id,
|
||||
roleCode: row.role_code,
|
||||
roleName: row.role_name,
|
||||
roleDescription: row.role_description,
|
||||
isSystem: row.is_system === 1,
|
||||
permissions: [],
|
||||
};
|
||||
|
||||
if (row.permission_code) {
|
||||
record.permissions.push(row.permission_code);
|
||||
}
|
||||
|
||||
records.set(row.role_id, record);
|
||||
}
|
||||
|
||||
return [...records.values()];
|
||||
}
|
||||
|
||||
export const permissionRepository = {
|
||||
async withTransaction<T>(
|
||||
handler: (connection: PoolConnection) => Promise<T>,
|
||||
): Promise<T> {
|
||||
const connection = await pool.getConnection();
|
||||
|
||||
try {
|
||||
await connection.beginTransaction();
|
||||
const result = await handler(connection);
|
||||
await connection.commit();
|
||||
return result;
|
||||
} catch (error) {
|
||||
await connection.rollback();
|
||||
throw error;
|
||||
} finally {
|
||||
connection.release();
|
||||
}
|
||||
},
|
||||
|
||||
async listRolePermissions(
|
||||
db: DbExecutor = pool,
|
||||
): Promise<RolePermissionRecord[]> {
|
||||
const [rows] = await db.execute<RolePermissionRow[]>(
|
||||
`
|
||||
SELECT
|
||||
r.id AS role_id,
|
||||
r.code AS role_code,
|
||||
r.name AS role_name,
|
||||
r.description AS role_description,
|
||||
r.is_system,
|
||||
rp.permission_code
|
||||
FROM roles r
|
||||
LEFT JOIN role_permissions rp ON rp.role_id = r.id
|
||||
ORDER BY r.id ASC, rp.permission_code ASC
|
||||
`,
|
||||
);
|
||||
|
||||
return toRolePermissionRecords(rows);
|
||||
},
|
||||
|
||||
async findRolePermissionsByRoleId(
|
||||
roleId: number,
|
||||
db: DbExecutor = pool,
|
||||
): Promise<RolePermissionRecord | null> {
|
||||
const [rows] = await db.execute<RolePermissionRow[]>(
|
||||
`
|
||||
SELECT
|
||||
r.id AS role_id,
|
||||
r.code AS role_code,
|
||||
r.name AS role_name,
|
||||
r.description AS role_description,
|
||||
r.is_system,
|
||||
rp.permission_code
|
||||
FROM roles r
|
||||
LEFT JOIN role_permissions rp ON rp.role_id = r.id
|
||||
WHERE r.id = ?
|
||||
ORDER BY rp.permission_code ASC
|
||||
`,
|
||||
[roleId],
|
||||
);
|
||||
|
||||
return toRolePermissionRecords(rows)[0] ?? null;
|
||||
},
|
||||
|
||||
async findPermissionCodesByRoleCodes(roleCodes: string[]): Promise<string[]> {
|
||||
if (roleCodes.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const placeholders = roleCodes.map(() => "?").join(", ");
|
||||
const [rows] = await pool.execute<PermissionCodeRow[]>(
|
||||
`
|
||||
SELECT DISTINCT rp.permission_code
|
||||
FROM role_permissions rp
|
||||
INNER JOIN roles r ON r.id = rp.role_id
|
||||
WHERE r.code IN (${placeholders})
|
||||
ORDER BY rp.permission_code ASC
|
||||
`,
|
||||
roleCodes,
|
||||
);
|
||||
|
||||
return rows.map((row) => row.permission_code);
|
||||
},
|
||||
|
||||
async replaceRolePermissions(
|
||||
roleId: number,
|
||||
permissionCodes: string[],
|
||||
db: DbExecutor = pool,
|
||||
): Promise<void> {
|
||||
await db.execute("DELETE FROM role_permissions WHERE role_id = ?", [roleId]);
|
||||
|
||||
if (permissionCodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
await db.execute(
|
||||
`
|
||||
INSERT INTO role_permissions (role_id, permission_code)
|
||||
VALUES ${permissionCodes.map(() => "(?, ?)").join(", ")}
|
||||
`,
|
||||
permissionCodes.flatMap((permissionCode) => [roleId, permissionCode]),
|
||||
);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user