tansci-boot/antdv-next-admin/mock/handlers/permission.mock.ts

343 lines
8.8 KiB
TypeScript

import type { Permission } from '@/types/auth';
import { faker } from '@faker-js/faker';
import { defineMock } from 'vite-plugin-mock-dev-server';
import { mockPermissions } from '../data/permissions.data';
const permissionStore: Permission[] = JSON.parse(JSON.stringify(mockPermissions));
const deepClone = <T>(value: T): T => JSON.parse(JSON.stringify(value));
function findPermissionById(
permissions: Permission[],
id: string,
parent: Permission | null = null,
): { permission: Permission | null; parent: Permission | null } {
for (const permission of permissions) {
if (permission.id === id) {
return { permission, parent };
}
if (permission.children && permission.children.length > 0) {
const result = findPermissionById(permission.children, id, permission);
if (result.permission) {
return result;
}
}
}
return { permission: null, parent: null };
}
function removePermissionById(permissions: Permission[], id: string): boolean {
const index = permissions.findIndex((permission) => permission.id === id);
if (index !== -1) {
permissions.splice(index, 1);
return true;
}
return permissions.some((permission) => {
if (!permission.children || permission.children.length === 0) {
return false;
}
const removed = removePermissionById(permission.children, id);
if (removed && permission.children.length === 0) {
delete permission.children;
}
return removed;
});
}
function appendPermission(
permissions: Permission[],
permission: Permission,
parentId?: string,
): boolean {
if (!parentId) {
permissions.push(permission);
return true;
}
const { permission: parentPermission } = findPermissionById(permissions, parentId);
if (!parentPermission) {
return false;
}
if (!parentPermission.children) {
parentPermission.children = [];
}
parentPermission.children.push(permission);
return true;
}
function filterPermissionTree(
permissions: Permission[],
keyword?: string,
type?: string,
status?: string,
): Permission[] {
const normalizedKeyword = keyword?.toLowerCase().trim();
return permissions.reduce<Permission[]>((result, permission) => {
const children = permission.children
? filterPermissionTree(permission.children, keyword, type, status)
: [];
const matchedKeyword =
!normalizedKeyword ||
permission.name.toLowerCase().includes(normalizedKeyword) ||
String(permission.code || '')
.toLowerCase()
.includes(normalizedKeyword) ||
(permission.path || '').toLowerCase().includes(normalizedKeyword);
const matchedType = !type || permission.type === type;
const matchedStatus = !status || (permission.status || 'active') === status;
const matchedSelf = matchedKeyword && matchedType && matchedStatus;
if (matchedSelf || children.length > 0) {
result.push({
...permission,
children: children.length > 0 ? children : undefined,
});
}
return result;
}, []);
}
function normalizeQueryValue(value: unknown): string | undefined {
if (Array.isArray(value)) {
return normalizeQueryValue(value[0]);
}
if (typeof value !== 'string') {
return undefined;
}
const trimmed = value.trim();
return trimmed ? trimmed : undefined;
}
export default defineMock([
// Get permission list (tree structure)
{
url: '/api/permissions',
method: 'GET',
body: (req) => {
const query = req.query || {};
const keyword = normalizeQueryValue(query.keyword);
const type = normalizeQueryValue(query.type);
const status = normalizeQueryValue(query.status);
const filtered = filterPermissionTree(permissionStore, keyword, type, status);
return {
code: 200,
message: 'Success',
data: deepClone(filtered),
success: true,
};
},
},
// Get permission tree (for menu)
{
url: '/api/permissions/tree',
method: 'GET',
body: () => {
return {
code: 200,
message: 'Success',
data: deepClone(permissionStore),
success: true,
};
},
},
// Get permission by ID
{
url: '/api/permissions/:id',
method: 'GET',
body: (req) => {
const { id } = req.params;
const { permission } = findPermissionById(permissionStore, id);
if (!permission) {
return {
code: 404,
message: 'Permission not found',
data: null,
success: false,
};
}
return {
code: 200,
message: 'Success',
data: deepClone(permission),
success: true,
};
},
},
// Create permission
{
url: '/api/permissions',
method: 'POST',
body: (req) => {
const payload = req.body || {};
const permission: Permission = {
id: faker.string.uuid(),
name: payload.name,
code: payload.code,
description: payload.description || '',
resource: payload.resource || payload.path || payload.code,
action: payload.action || (payload.type === 'menu' ? 'view' : '*'),
type: payload.type || 'menu',
parentId: payload.parentId,
path: payload.path,
component: payload.component,
icon: payload.icon,
sort: payload.sort ?? 0,
status: payload.status || 'active',
visible: payload.visible ?? true,
children: payload.children && payload.children.length > 0 ? payload.children : undefined,
};
const appended = appendPermission(permissionStore, permission, payload.parentId);
if (!appended) {
return {
code: 400,
message: 'Parent permission not found',
data: null,
success: false,
};
}
return {
code: 200,
message: 'Permission created successfully',
data: deepClone(permission),
success: true,
};
},
},
// Update permission
{
url: '/api/permissions/:id',
method: 'PUT',
body: (req) => {
const { id } = req.params;
const payload = req.body || {};
const { permission, parent } = findPermissionById(permissionStore, id);
if (!permission) {
return {
code: 404,
message: 'Permission not found',
data: null,
success: false,
};
}
if (payload.parentId !== undefined && payload.parentId !== permission.parentId) {
const movedPermission = deepClone(permission);
removePermissionById(permissionStore, id);
movedPermission.parentId = payload.parentId;
movedPermission.children = permission.children || [];
const appended = appendPermission(permissionStore, movedPermission, payload.parentId);
if (!appended) {
appendPermission(permissionStore, movedPermission, parent?.id);
return {
code: 400,
message: 'Parent permission not found',
data: null,
success: false,
};
}
}
const { permission: nextPermission } = findPermissionById(permissionStore, id);
if (!nextPermission) {
return {
code: 404,
message: 'Permission not found',
data: null,
success: false,
};
}
const children = nextPermission.children;
Object.assign(nextPermission, payload, { children });
return {
code: 200,
message: 'Permission updated successfully',
data: deepClone(nextPermission),
success: true,
};
},
},
// Delete permission
{
url: '/api/permissions/:id',
method: 'DELETE',
body: (req) => {
const { id } = req.params;
const removed = removePermissionById(permissionStore, id);
if (!removed) {
return {
code: 404,
message: 'Permission not found',
data: null,
success: false,
};
}
return {
code: 200,
message: 'Permission deleted successfully',
data: null,
success: true,
};
},
},
// Get user permissions
{
url: '/api/permissions/user',
method: 'GET',
body: (req) => {
// In a real app, this would be based on the user's roles
// For now, return all permissions for admin
const token = req.headers.authorization?.replace('Bearer ', '');
const userId = token?.split('-')[2];
if (userId === '1') {
// Admin - all permissions
return {
code: 200,
message: 'Success',
data: deepClone(permissionStore),
success: true,
};
} else {
// Regular user - limited permissions
return {
code: 200,
message: 'Success',
data: deepClone(
permissionStore.filter((permission) => permission.code === 'dashboard.view'),
),
success: true,
};
}
},
},
]);