From 0e39579ae6b5506b9aba8914a1f0b97bc94d51a2 Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Tue, 8 Oct 2024 21:20:35 +0800 Subject: [PATCH] fix: sync role snippets (#5371) --- .../src/server/__tests__/cluster.test.ts | 53 +++++++++++++++++++ .../@nocobase/plugin-acl/src/server/server.ts | 30 +++++++++++ 2 files changed, 83 insertions(+) create mode 100644 packages/plugins/@nocobase/plugin-acl/src/server/__tests__/cluster.test.ts diff --git a/packages/plugins/@nocobase/plugin-acl/src/server/__tests__/cluster.test.ts b/packages/plugins/@nocobase/plugin-acl/src/server/__tests__/cluster.test.ts new file mode 100644 index 0000000000..8881d5d786 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-acl/src/server/__tests__/cluster.test.ts @@ -0,0 +1,53 @@ +/** + * 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 { createMockCluster, MockCluster, sleep } from '@nocobase/test'; + +describe('cluster', () => { + let cluster: MockCluster; + beforeEach(async () => { + cluster = await createMockCluster({ + plugins: ['acl', 'field-sort', 'error-handler', 'data-source-main', 'data-source-manager', 'ui-schema-storage'], + acl: false, + }); + }); + + afterEach(async () => { + await cluster.destroy(); + }); + + it('should sync roles when snippet update', async () => { + const [app1, app2] = cluster.nodes; + + await app1.db.getRepository('roles').create({ + values: { + name: 'role1', + snippets: ['test1'], + }, + }); + + const role1 = app1.acl.getRole('role1'); + expect(role1.snippets.has('test1')).toBeTruthy(); + + // update snippet + await app1.db.getRepository('roles').update({ + filter: { + name: 'role1', + }, + values: { + snippets: ['test2'], + }, + }); + await sleep(2000); + expect(role1.snippets.has('test2')).toBeTruthy(); + + const role1InApp2 = app2.acl.getRole('role1'); + expect(role1InApp2.snippets.has('test2')).toBeTruthy(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-acl/src/server/server.ts b/packages/plugins/@nocobase/plugin-acl/src/server/server.ts index 97d486e37e..a4b28dc007 100644 --- a/packages/plugins/@nocobase/plugin-acl/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-acl/src/server/server.ts @@ -45,6 +45,26 @@ export class PluginACLServer extends Plugin { }); } + async handleSyncMessage(message) { + const { type } = message; + if (type === 'syncRole') { + const { roleName } = message; + const role = await this.app.db.getRepository('roles').findOne({ + filter: { + name: roleName, + }, + }); + + await this.writeRoleToACL(role, { + withOutResources: true, + }); + + await this.app.emitAsync('acl:writeResources', { + roleName: role.get('name'), + }); + } + } + async writeRolesToACL(options) { const roles = (await this.app.db.getRepository('roles').find({ appends: ['resources', 'resources.actions'], @@ -213,6 +233,16 @@ export class PluginACLServer extends Plugin { transaction, }); } + + this.sendSyncMessage( + { + type: 'syncRole', + roleName: model.get('name'), + }, + { + transaction: options.transaction, + }, + ); }); this.app.db.on('roles.afterDestroy', (model) => {