mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
fix(migration): permissions issue (#6177)
* fix(migration): permissions issue * feat: add new migration
This commit is contained in:
parent
1c1b9a3fe6
commit
17541f94d1
@ -0,0 +1,111 @@
|
||||
import { MockServer, createMockServer } from '@nocobase/test';
|
||||
import Migration, { getIds, schemaToRoutes } from '../migrations/2024122912211-transform-menu-schema-to-routes';
|
||||
|
||||
describe('transform-menu-schema-to-routes', () => {
|
||||
let app: MockServer;
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await createMockServer({
|
||||
plugins: ['nocobase'],
|
||||
});
|
||||
await app.version.update('1.5.0');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
});
|
||||
|
||||
describe('migration', () => {
|
||||
test('should skip if desktop routes already exist', async () => {
|
||||
const desktopRoutes = app.db.getRepository('desktopRoutes');
|
||||
await desktopRoutes.create({
|
||||
type: 'page',
|
||||
title: 'Test Page',
|
||||
} as any);
|
||||
|
||||
const migration = new Migration({
|
||||
db: app.db,
|
||||
app: app,
|
||||
} as any);
|
||||
|
||||
await migration.up();
|
||||
const count = await desktopRoutes.count();
|
||||
expect(count).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('schemaToRoutes', () => {
|
||||
test('should transform group menu item', async () => {
|
||||
const schema = {
|
||||
properties: {
|
||||
group1: {
|
||||
'x-component': 'Menu.SubMenu',
|
||||
title: 'Group 1',
|
||||
'x-uid': 'group-1',
|
||||
'x-component-props': {
|
||||
icon: 'GroupIcon',
|
||||
},
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const routes = await schemaToRoutes(schema, app.db.getRepository('uiSchemas'));
|
||||
expect(routes[0]).toMatchObject({
|
||||
type: 'group',
|
||||
title: 'Group 1',
|
||||
icon: 'GroupIcon',
|
||||
schemaUid: 'group-1',
|
||||
hideInMenu: false,
|
||||
});
|
||||
});
|
||||
|
||||
test('should transform link menu item', async () => {
|
||||
const schema = {
|
||||
properties: {
|
||||
link1: {
|
||||
'x-component': 'Menu.URL',
|
||||
title: 'Link 1',
|
||||
'x-uid': 'link-1',
|
||||
'x-component-props': {
|
||||
icon: 'LinkIcon',
|
||||
href: 'https://example.com',
|
||||
params: { foo: 'bar' },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const routes = await schemaToRoutes(schema, app.db.getRepository('uiSchemas'));
|
||||
expect(routes[0]).toMatchObject({
|
||||
type: 'link',
|
||||
title: 'Link 1',
|
||||
icon: 'LinkIcon',
|
||||
options: {
|
||||
href: 'https://example.com',
|
||||
params: { foo: 'bar' },
|
||||
},
|
||||
schemaUid: 'link-1',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getIds', () => {
|
||||
test('should correctly identify ids to add and remove', () => {
|
||||
const desktopRoutes = [
|
||||
{ id: 1, type: 'page', menuSchemaUid: 'page-1' },
|
||||
{ id: 2, type: 'page', menuSchemaUid: 'page-2' },
|
||||
{ id: 3, type: 'tabs', parentId: 1 },
|
||||
];
|
||||
|
||||
const menuUiSchemas = [
|
||||
{ 'x-uid': 'page-1' },
|
||||
];
|
||||
|
||||
const { needRemoveIds, needAddIds } = getIds(desktopRoutes, menuUiSchemas);
|
||||
expect(needRemoveIds).toContain(2);
|
||||
expect(needAddIds).toContain(1);
|
||||
expect(needAddIds).toContain(3);
|
||||
});
|
||||
});
|
||||
});
|
@ -35,24 +35,30 @@ export default class extends Migration {
|
||||
// 2. 将旧版的权限配置,转换为新版的权限配置
|
||||
|
||||
const roles = await rolesRepository.find({
|
||||
appends: ['desktopRoutes', 'menuUiSchemas'],
|
||||
appends: ['menuUiSchemas'],
|
||||
transaction,
|
||||
});
|
||||
const allDesktopRoutes = await desktopRoutes.find({ transaction });
|
||||
|
||||
for (const role of roles) {
|
||||
const menuUiSchemas = role.menuUiSchemas || [];
|
||||
const desktopRoutes = role.desktopRoutes || [];
|
||||
const needRemoveIds = getNeedRemoveIds(desktopRoutes, menuUiSchemas);
|
||||
const { needRemoveIds, needAddIds } = getIds(allDesktopRoutes, menuUiSchemas);
|
||||
|
||||
if (needRemoveIds.length === 0) {
|
||||
continue;
|
||||
if (needRemoveIds.length > 0) {
|
||||
// @ts-ignore
|
||||
await this.db.getRepository('roles.desktopRoutes', role.name).remove({
|
||||
tk: needRemoveIds,
|
||||
transaction,
|
||||
});
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
await this.db.getRepository('roles.desktopRoutes', role.name).remove({
|
||||
tk: needRemoveIds,
|
||||
transaction,
|
||||
});
|
||||
if (needAddIds.length > 0) {
|
||||
// @ts-ignore
|
||||
await this.db.getRepository('roles.desktopRoutes', role.name).add({
|
||||
tk: needAddIds,
|
||||
transaction,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,9 +176,9 @@ export async function schemaToRoutes(schema: any, uiSchemas: any) {
|
||||
return Promise.all(result);
|
||||
}
|
||||
|
||||
function getNeedRemoveIds(desktopRoutes: any[], menuUiSchemas: any[]) {
|
||||
export function getIds(desktopRoutes: any[], menuUiSchemas: any[]) {
|
||||
const uidList = menuUiSchemas.map((item) => item['x-uid']);
|
||||
return desktopRoutes
|
||||
const needRemoveIds = desktopRoutes
|
||||
.filter((item) => {
|
||||
// 之前是不支持配置 tab 的权限的,所以所有的 tab 都不会存在于旧版的 menuUiSchemas 中
|
||||
if (item.type === 'tabs') {
|
||||
@ -189,4 +195,7 @@ function getNeedRemoveIds(desktopRoutes: any[], menuUiSchemas: any[]) {
|
||||
return !uidList.includes(item?.schemaUid);
|
||||
})
|
||||
.map((item) => item?.id);
|
||||
const needAddIds = desktopRoutes.map((item) => item?.id).filter((id) => !needRemoveIds.includes(id));
|
||||
|
||||
return { needRemoveIds, needAddIds };
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { Migration } from '@nocobase/server';
|
||||
|
||||
export default class extends Migration {
|
||||
appVersion = '<1.6.0';
|
||||
async up() {
|
||||
const desktopRoutes = this.db.getRepository('desktopRoutes');
|
||||
const count = await desktopRoutes.count();
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
const rolesRepository = this.db.getRepository('roles');
|
||||
|
||||
try {
|
||||
await this.db.sequelize.transaction(async (transaction) => {
|
||||
const roles = await rolesRepository.find({
|
||||
appends: ['menuUiSchemas'],
|
||||
transaction,
|
||||
});
|
||||
const allDesktopRoutes = await desktopRoutes.find({ transaction });
|
||||
|
||||
for (const role of roles) {
|
||||
const menuUiSchemas = role.menuUiSchemas || [];
|
||||
const { needAddIds } = getIds(allDesktopRoutes, menuUiSchemas);
|
||||
|
||||
if (needAddIds.length > 0) {
|
||||
// @ts-ignore
|
||||
await this.db.getRepository('roles.desktopRoutes', role.name).add({
|
||||
tk: needAddIds,
|
||||
transaction,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Migration failed:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getIds(desktopRoutes: any[], menuUiSchemas: any[]) {
|
||||
const uidList = menuUiSchemas.map((item) => item['x-uid']);
|
||||
const needRemoveIds = desktopRoutes
|
||||
.filter((item) => {
|
||||
// 之前是不支持配置 tab 的权限的,所以所有的 tab 都不会存在于旧版的 menuUiSchemas 中
|
||||
if (item.type === 'tabs') {
|
||||
// tab 的父节点就是一个 page
|
||||
const page = desktopRoutes.find((route) => route?.id === item?.parentId);
|
||||
// tab 要不要过滤掉,和它的父节点(page)有关
|
||||
return !uidList.includes(page?.menuSchemaUid);
|
||||
}
|
||||
|
||||
if (item.type === 'page') {
|
||||
return !uidList.includes(item?.menuSchemaUid);
|
||||
}
|
||||
|
||||
return !uidList.includes(item?.schemaUid);
|
||||
})
|
||||
.map((item) => item?.id);
|
||||
const needAddIds = desktopRoutes.map((item) => item?.id).filter((id) => !needRemoveIds.includes(id));
|
||||
|
||||
return { needRemoveIds, needAddIds };
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user