tachybase_todo/packages/plugin-acl/src/__tests__/acl.test.ts

445 lines
9.1 KiB
TypeScript

import { MockServer } from '@nocobase/test';
import { prepareApp } from './prepare';
import { Database } from '@nocobase/database';
import { ACL } from '@nocobase/acl';
import PluginACL from '../server';
describe('acl', () => {
let app: MockServer;
let db: Database;
let acl: ACL;
afterEach(async () => {
await app.destroy();
});
beforeEach(async () => {
app = await prepareApp();
db = app.db;
const aclPlugin = app.getPlugin<PluginACL>('PluginACL');
acl = aclPlugin.getACL();
});
it('should works with universal actions', async () => {
await db.getRepository('roles').create({
values: {
name: 'admin',
title: 'Admin User',
allowConfigure: true,
},
});
const role = await db.getRepository('roles').findOne({
filter: {
name: 'admin',
},
});
expect(
acl.can({
role: 'admin',
resource: 'posts',
action: 'create',
}),
).toBeNull();
// grant universal action
await app
.agent()
.resource('roles')
.update({
resourceIndex: 'admin',
values: {
strategy: {
actions: ['create'],
},
},
});
expect(
acl.can({
role: 'admin',
resource: 'posts',
action: 'create',
}),
).toMatchObject({
role: 'admin',
resource: 'posts',
action: 'create',
});
});
it('should works with resources actions', async () => {
await db.getRepository('roles').create({
values: {
name: 'admin',
title: 'Admin User',
allowConfigure: true,
},
});
const role = await db.getRepository('roles').findOne({
filter: {
name: 'admin',
},
});
await db.getRepository('collections').create({
values: {
name: 'c1',
title: 'table1',
},
});
await db.getRepository('collections').create({
values: {
name: 'c2',
title: 'table2',
},
});
await app
.agent()
.resource('rolesResourcesScopes')
.create({
values: {
resourceName: 'c1',
name: 'published',
scope: {
published: true,
},
},
});
const publishedScope = await db.getRepository('rolesResourcesScopes').findOne();
await app
.agent()
.resource('roles.resources')
.create({
associatedIndex: role.get('name') as string,
values: {
name: 'c1',
usingActionsConfig: true,
actions: [
{
name: 'create',
scope: publishedScope.get('id'),
},
{
name: 'view',
fields: ['title', 'age'],
},
],
},
});
expect(
acl.can({
role: 'admin',
resource: 'c1',
action: 'create',
}),
).toMatchObject({
role: 'admin',
resource: 'c1',
action: 'create',
params: {
filter: { published: true },
},
});
expect(
acl.can({
role: 'admin',
resource: 'c1',
action: 'view',
}),
).toMatchObject({
role: 'admin',
resource: 'c1',
action: 'view',
params: {
fields: ['age', 'title', 'id', 'createdAt', 'updatedAt'],
},
});
// revoke action
const response = await app
.agent()
.resource('roles.resources')
.list({
associatedIndex: role.get('name') as string,
appends: ['actions'],
});
const actions = response.body.data[0].actions;
const resourceId = response.body.data[0].id;
const viewActionId = actions.find((action) => action.name === 'view').id;
await app
.agent()
.resource('roles.resources')
.update({
associatedIndex: role.get('name') as string,
resourceIndex: resourceId,
values: {
name: 'c1',
usingActionsConfig: true,
actions: [
{
id: viewActionId,
name: 'view',
fields: ['title', 'age'],
},
],
},
});
expect(
acl.can({
role: 'admin',
resource: 'c1',
action: 'create',
}),
).toBeNull();
});
it('should revoke resource when collection destroy', async () => {
const role = await db.getRepository('roles').create({
values: {
name: 'admin',
title: 'Admin User',
allowConfigure: true,
},
});
await db.getRepository('collections').create({
values: {
name: 'posts',
},
});
await db.getRepository('fields').create({
values: {
collectionName: 'posts',
type: 'string',
name: 'title',
},
});
await app
.agent()
.resource('roles.resources')
.create({
associatedIndex: role.get('name') as string,
values: {
name: 'posts',
usingActionsConfig: true,
actions: [
{
name: 'view',
fields: ['title'],
},
],
},
});
expect(
acl.can({
role: 'admin',
resource: 'posts',
action: 'view',
}),
).not.toBeNull();
await db.getRepository('collections').destroy({
filter: {
name: 'posts',
},
});
expect(
acl.can({
role: 'admin',
resource: 'posts',
action: 'view',
}),
).toBeNull();
});
it('should revoke actions when not using actions config', async () => {
await db.getRepository('roles').create({
values: {
name: 'admin',
title: 'Admin User',
allowConfigure: true,
},
});
const role = await db.getRepository('roles').findOne({
filter: {
name: 'admin',
},
});
await db.getRepository('collections').create({
values: {
name: 'posts',
title: 'posts',
},
});
await app
.agent()
.resource('roles.resources')
.create({
associatedIndex: role.get('name') as string,
values: {
name: 'posts',
usingActionsConfig: true,
actions: [
{
name: 'create',
},
],
},
});
expect(
acl.can({
role: 'admin',
resource: 'posts',
action: 'create',
}),
).toMatchObject({
role: 'admin',
resource: 'posts',
action: 'create',
});
await app
.agent()
.resource('roles.resources')
.update({
associatedIndex: role.get('name') as string,
resourceIndex: (
await db.getRepository('rolesResources').findOne({
filter: {
name: 'posts',
roleName: 'admin',
},
})
).get('id') as string,
values: {
usingActionsConfig: false,
},
});
expect(
acl.can({
role: 'admin',
resource: 'posts',
action: 'create',
}),
).toBeNull();
await app
.agent()
.resource('roles.resources')
.update({
associatedIndex: role.get('name') as string,
resourceIndex: (
await db.getRepository('rolesResources').findOne({
filter: {
name: 'posts',
roleName: 'admin',
},
})
).get('id') as string,
values: {
usingActionsConfig: true,
},
});
expect(
acl.can({
role: 'admin',
resource: 'posts',
action: 'create',
}),
).toMatchObject({
role: 'admin',
resource: 'posts',
action: 'create',
});
});
it('should add fields when field created', async () => {
const role = await db.getRepository('roles').create({
values: {
name: 'admin',
title: 'Admin User',
allowConfigure: true,
},
});
await db.getRepository('collections').create({
values: {
name: 'posts',
},
});
await db.getRepository('fields').create({
values: {
collectionName: 'posts',
type: 'string',
name: 'title',
},
});
await app
.agent()
.resource('roles.resources')
.create({
associatedIndex: role.get('name') as string,
values: {
name: 'posts',
usingActionsConfig: true,
actions: [
{
name: 'view',
fields: ['title'],
},
],
},
});
const allowFields = acl.can({
role: 'admin',
resource: 'posts',
action: 'view',
})['params']['fields'];
expect(allowFields.includes('title')).toBeTruthy();
await db.getRepository('fields').create({
values: {
collectionName: 'posts',
type: 'string',
name: 'description',
},
});
const newAllowFields = acl.can({
role: 'admin',
resource: 'posts',
action: 'view',
})['params']['fields'];
expect(newAllowFields.includes('description')).toBeTruthy();
});
});