chore(acl): write role to acl if it exists in database and not found … (#2001)

* chore(acl): write role to acl if it exists in database and not found in acl

* fix: test
This commit is contained in:
ChengLei Shao 2023-06-07 15:01:50 +08:00 committed by GitHub
parent c3c02d8925
commit 43f3cb7cfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 107 additions and 41 deletions

View File

@ -99,7 +99,7 @@ describe('actions', () => {
const rolesCheckResponse2 = (await loggedAgent.set('Accept', 'application/json').get('/roles:check')) as any;
expect(rolesCheckResponse2.status).toEqual(500);
expect(rolesCheckResponse2.body.errors[0].message).toEqual('Role not found');
expect(rolesCheckResponse2.body.errors[0].message).toEqual('User role not found');
});
it('should destroy through table record when destroy role', async () => {

View File

@ -0,0 +1,48 @@
import { MockServer } from '@nocobase/test';
import { Database } from '@nocobase/database';
import { prepareApp } from './prepare';
import UsersPlugin from '@nocobase/plugin-users';
describe('write role to acl', () => {
let app: MockServer;
let db: Database;
beforeEach(async () => {
app = await prepareApp();
db = app.db;
});
afterEach(async () => {
await app.destroy();
});
it('should write role to acl if role instance exists in db', async () => {
const role = await db.getRepository('roles').create({
values: {
name: 'test',
},
});
// remove role from acl
app.acl.removeRole('test');
const user = await db.getRepository('users').create({
values: {
roles: ['test'],
},
});
const userPlugin = app.getPlugin('users') as UsersPlugin;
const agent = app.agent().auth(
userPlugin.jwtService.sign({
userId: user.get('id'),
}),
{ type: 'bearer' },
);
// @ts-ignore
const response = await agent.resource('roles').check();
expect(response.statusCode).toEqual(200);
});
});

View File

@ -8,7 +8,10 @@ const map2obj = (map: Map<string, string>) => {
export async function checkAction(ctx, next) {
const currentRole = ctx.state.currentRole;
if (currentRole) {
if (!currentRole) {
throw new Error('User role not found');
}
const roleInstance = await ctx.db.getRepository('roles').findOne({
filter: {
name: currentRole,
@ -16,13 +19,23 @@ export async function checkAction(ctx, next) {
appends: ['menuUiSchemas'],
});
if (!roleInstance) {
throw new Error(`Role ${currentRole} not exists`);
}
const anonymous = await ctx.db.getRepository('roles').findOne({
filter: {
name: 'anonymous',
},
});
const role = ctx.app.acl.getRole(currentRole);
let role = ctx.app.acl.getRole(currentRole);
if (!role) {
await ctx.app.emit('acl:writeRoleToACL', roleInstance);
role = ctx.app.acl.getRole(currentRole);
}
const availableActions = ctx.app.acl.getAvailableActions();
ctx.body = {
@ -35,9 +48,6 @@ export async function checkAction(ctx, next) {
allowMenuItemIds: roleInstance.get('menuUiSchemas').map((uiSchema) => uiSchema.get('x-uid')),
allowAnonymous: !!anonymous,
};
} else {
throw new Error('Role not found');
}
await next();
}

View File

@ -128,11 +128,21 @@ export class PluginACL extends Plugin {
})) as RoleModel[];
for (const role of roles) {
await this.writeRoleToACL(role);
}
}
async writeRoleToACL(role: RoleModel, transaction: any = null) {
role.writeToAcl({ acl: this.acl });
for (const resource of role.get('resources') as RoleResourceModel[]) {
await this.writeResourceToACL(resource, null);
let resources = role.get('resources') as RoleResourceModel[];
if (!resources) {
resources = await role.getResources({ transaction });
}
for (const resource of resources as RoleResourceModel[]) {
await this.writeResourceToACL(resource, transaction);
}
}
@ -217,16 +227,14 @@ export class PluginACL extends Plugin {
}
});
this.app.on('acl:writeRoleToACL', async (roleModel: RoleModel) => {
await this.writeRoleToACL(roleModel);
});
this.app.db.on('roles.afterSaveWithAssociations', async (model, options) => {
const { transaction } = options;
model.writeToAcl({
acl: this.acl,
});
for (const resource of (await model.getResources({ transaction })) as RoleResourceModel[]) {
await this.writeResourceToACL(resource, transaction);
}
await this.writeRoleToACL(model, transaction);
// model is default
if (model.get('default')) {