@nocobase/plugin-acl 0.8.1-alpha.4 → 0.9.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -201
- package/lib/actions/role-check.js +2 -0
- package/lib/actions/role-collections.js +39 -12
- package/lib/collections/roles.js +4 -0
- package/lib/collections/rolesResourcesActions.js +2 -1
- package/lib/collections/users.js +1 -0
- package/lib/migrations/20221214072638-set-role-snippets.d.ts +5 -0
- package/lib/migrations/20221214072638-set-role-snippets.js +49 -0
- package/lib/model/RoleModel.js +1 -0
- package/lib/model/RoleResourceActionModel.js +9 -3
- package/lib/server.js +393 -28
- package/package.json +7 -13
- package/src/__tests__/acl.test.ts +0 -548
- package/src/__tests__/association-field.test.ts +0 -308
- package/src/__tests__/configuration.test.ts +0 -74
- package/src/__tests__/middleware.test.ts +0 -228
- package/src/__tests__/own.test.ts +0 -133
- package/src/__tests__/prepare.ts +0 -20
- package/src/__tests__/role-check.test.ts +0 -41
- package/src/__tests__/role-resource.test.ts +0 -189
- package/src/__tests__/role-user.test.ts +0 -123
- package/src/__tests__/role.test.ts +0 -99
- package/src/__tests__/scope.test.ts +0 -59
- package/src/__tests__/setCurrentRole.test.ts +0 -83
- package/src/__tests__/users.test.ts +0 -52
- package/src/actions/available-actions.ts +0 -18
- package/src/actions/role-check.ts +0 -41
- package/src/actions/role-collections.ts +0 -65
- package/src/actions/user-setDefaultRole.ts +0 -45
- package/src/collections/roles-users.ts +0 -6
- package/src/collections/roles.ts +0 -79
- package/src/collections/rolesResources.ts +0 -31
- package/src/collections/rolesResourcesActions.ts +0 -28
- package/src/collections/rolesResourcesScopes.ts +0 -23
- package/src/collections/users.ts +0 -30
- package/src/index.ts +0 -2
- package/src/middlewares/setCurrentRole.ts +0 -32
- package/src/model/RoleModel.ts +0 -21
- package/src/model/RoleResourceActionModel.ts +0 -88
- package/src/model/RoleResourceModel.ts +0 -74
- package/src/server.ts +0 -463
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import Database from '@nocobase/database';
|
|
2
|
-
import UsersPlugin from '@nocobase/plugin-users';
|
|
3
|
-
import { MockServer } from '@nocobase/test';
|
|
4
|
-
import { setCurrentRole } from '../middlewares/setCurrentRole';
|
|
5
|
-
import { prepareApp } from './prepare';
|
|
6
|
-
|
|
7
|
-
describe('role', () => {
|
|
8
|
-
let api: MockServer;
|
|
9
|
-
let db: Database;
|
|
10
|
-
|
|
11
|
-
let usersPlugin: UsersPlugin;
|
|
12
|
-
let ctx;
|
|
13
|
-
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
api = await prepareApp();
|
|
16
|
-
|
|
17
|
-
db = api.db;
|
|
18
|
-
usersPlugin = api.getPlugin('users');
|
|
19
|
-
|
|
20
|
-
ctx = {
|
|
21
|
-
db,
|
|
22
|
-
state: {
|
|
23
|
-
currentRole: '',
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
afterEach(async () => {
|
|
29
|
-
await api.destroy();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should set role with X-Role when exists', async () => {
|
|
33
|
-
ctx.state.currentUser = await db.getRepository('users').findOne({
|
|
34
|
-
appends: ['roles'],
|
|
35
|
-
});
|
|
36
|
-
ctx.get = function(name) {
|
|
37
|
-
if (name === 'X-Role') {
|
|
38
|
-
return 'admin';
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
await setCurrentRole(ctx, () => {});
|
|
42
|
-
expect(ctx.state.currentRole).toBe('admin');
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should set role with default', async () => {
|
|
46
|
-
ctx.state.currentUser = await db.getRepository('users').findOne({
|
|
47
|
-
appends: ['roles'],
|
|
48
|
-
});
|
|
49
|
-
ctx.get = function (name) {
|
|
50
|
-
if (name === 'X-Role') {
|
|
51
|
-
return '';
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
await setCurrentRole(ctx, () => {});
|
|
55
|
-
expect(ctx.state.currentRole).toBe('root');
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('should set role with default when x-role does not exist', async () => {
|
|
59
|
-
ctx.state.currentUser = await db.getRepository('users').findOne({
|
|
60
|
-
appends: ['roles'],
|
|
61
|
-
});
|
|
62
|
-
ctx.get = function (name) {
|
|
63
|
-
if (name === 'X-Role') {
|
|
64
|
-
return 'abc';
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
await setCurrentRole(ctx, () => {});
|
|
68
|
-
expect(ctx.state.currentRole).toBe('root');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should set role with anonymous', async () => {
|
|
72
|
-
ctx.state.currentUser = await db.getRepository('users').findOne({
|
|
73
|
-
appends: ['roles'],
|
|
74
|
-
});
|
|
75
|
-
ctx.get = function (name) {
|
|
76
|
-
if (name === 'X-Role') {
|
|
77
|
-
return 'anonymous';
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
await setCurrentRole(ctx, () => {});
|
|
81
|
-
expect(ctx.state.currentRole).toBe('anonymous');
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import Database from '@nocobase/database';
|
|
2
|
-
import { MockServer } from '@nocobase/test';
|
|
3
|
-
import { prepareApp } from './prepare';
|
|
4
|
-
|
|
5
|
-
describe('actions', () => {
|
|
6
|
-
let app: MockServer;
|
|
7
|
-
let db: Database;
|
|
8
|
-
let adminUser;
|
|
9
|
-
let agent;
|
|
10
|
-
let adminAgent;
|
|
11
|
-
let pluginUser;
|
|
12
|
-
|
|
13
|
-
beforeEach(async () => {
|
|
14
|
-
process.env.INIT_ROOT_EMAIL = 'test@nocobase.com';
|
|
15
|
-
process.env.INIT_ROOT_PASSWORD = '123456';
|
|
16
|
-
process.env.INIT_ROOT_NICKNAME = 'Test';
|
|
17
|
-
|
|
18
|
-
app = await prepareApp();
|
|
19
|
-
db = app.db;
|
|
20
|
-
|
|
21
|
-
pluginUser = app.getPlugin('users');
|
|
22
|
-
adminUser = await db.getRepository('users').findOne({
|
|
23
|
-
filter: {
|
|
24
|
-
email: process.env.INIT_ROOT_EMAIL
|
|
25
|
-
},
|
|
26
|
-
appends: ['roles']
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
agent = app.agent();
|
|
30
|
-
adminAgent = app.agent().auth(
|
|
31
|
-
pluginUser.jwtService.sign({
|
|
32
|
-
userId: adminUser.get('id'),
|
|
33
|
-
}),
|
|
34
|
-
{ type: 'bearer' },
|
|
35
|
-
);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
afterEach(async () => {
|
|
39
|
-
await db.close();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('update profile with roles', async () => {
|
|
43
|
-
const res2 = await adminAgent.resource('users').updateProfile({
|
|
44
|
-
filterByTk: adminUser.id,
|
|
45
|
-
values: {
|
|
46
|
-
nickname: 'a',
|
|
47
|
-
roles: adminUser.roles
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
expect(res2.status).toBe(200);
|
|
51
|
-
});
|
|
52
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
const availableActionResource = {
|
|
2
|
-
name: 'availableActions',
|
|
3
|
-
actions: {
|
|
4
|
-
async list(ctx, next) {
|
|
5
|
-
const acl = ctx.app.acl;
|
|
6
|
-
const availableActions = acl.getAvailableActions();
|
|
7
|
-
ctx.body = Array.from(availableActions.entries()).map(([, { name, options }]) => {
|
|
8
|
-
return {
|
|
9
|
-
...options,
|
|
10
|
-
name,
|
|
11
|
-
};
|
|
12
|
-
});
|
|
13
|
-
await next();
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export { availableActionResource };
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const map2obj = (map: Map<string, string>) => {
|
|
2
|
-
const obj = {};
|
|
3
|
-
for(let [key, value] of map){
|
|
4
|
-
obj[key] = value;
|
|
5
|
-
}
|
|
6
|
-
return obj;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export async function checkAction(ctx, next) {
|
|
10
|
-
const currentRole = ctx.state.currentRole;
|
|
11
|
-
if (currentRole) {
|
|
12
|
-
const roleInstance = await ctx.db.getRepository('roles').findOne({
|
|
13
|
-
filter: {
|
|
14
|
-
name: currentRole,
|
|
15
|
-
},
|
|
16
|
-
appends: ['menuUiSchemas'],
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const anonymous = await ctx.db.getRepository('roles').findOne({
|
|
20
|
-
filter: {
|
|
21
|
-
name: 'anonymous',
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const role = ctx.app.acl.getRole(currentRole);
|
|
26
|
-
|
|
27
|
-
ctx.body = {
|
|
28
|
-
...role.toJSON(),
|
|
29
|
-
resources: [...role.resources.keys()],
|
|
30
|
-
actionAlias: map2obj(ctx.app.acl.actionAlias),
|
|
31
|
-
allowAll: currentRole === 'root',
|
|
32
|
-
allowConfigure: roleInstance.get('allowConfigure'),
|
|
33
|
-
allowMenuItemIds: roleInstance.get('menuUiSchemas').map((uiSchema) => uiSchema.get('x-uid')),
|
|
34
|
-
allowAnonymous: !!anonymous,
|
|
35
|
-
};
|
|
36
|
-
} else {
|
|
37
|
-
throw new Error('Role not found');
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
await next();
|
|
41
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { Database } from '@nocobase/database';
|
|
2
|
-
|
|
3
|
-
type UsingConfigType = 'strategy' | 'resourceAction';
|
|
4
|
-
|
|
5
|
-
function totalPage(total, pageSize): number {
|
|
6
|
-
return Math.ceil(total / pageSize);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const roleCollectionsResource = {
|
|
10
|
-
name: 'roles.collections',
|
|
11
|
-
actions: {
|
|
12
|
-
async list(ctx, next) {
|
|
13
|
-
const role = ctx.action.params.associatedIndex;
|
|
14
|
-
const { page = 1, pageSize = 20 } = ctx.action.params;
|
|
15
|
-
|
|
16
|
-
const db: Database = ctx.db;
|
|
17
|
-
const collectionRepository = db.getRepository('collections');
|
|
18
|
-
|
|
19
|
-
// all collections
|
|
20
|
-
const [collections, count] = await collectionRepository.findAndCount({
|
|
21
|
-
filter: ctx.action.params.filter,
|
|
22
|
-
sort: 'sort',
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
// role collections
|
|
26
|
-
const roleResources = await db.getRepository('rolesResources').find({
|
|
27
|
-
filter: {
|
|
28
|
-
roleName: role,
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// role collections
|
|
33
|
-
const roleResourcesNames = roleResources.map((roleResource) => roleResource.get('name'));
|
|
34
|
-
const roleResourceActionResourceNames = roleResources
|
|
35
|
-
.filter((roleResources) => roleResources.get('usingActionsConfig'))
|
|
36
|
-
.map((roleResources) => roleResources.get('name'));
|
|
37
|
-
|
|
38
|
-
ctx.body = {
|
|
39
|
-
count,
|
|
40
|
-
rows: collections.map((collection) => {
|
|
41
|
-
const exists = roleResourcesNames.includes(collection.get('name'));
|
|
42
|
-
|
|
43
|
-
const usingConfig: UsingConfigType = roleResourceActionResourceNames.includes(collection.get('name'))
|
|
44
|
-
? 'resourceAction'
|
|
45
|
-
: 'strategy';
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
name: collection.get('name') as string,
|
|
49
|
-
title: collection.get('title') as string,
|
|
50
|
-
roleName: role,
|
|
51
|
-
usingConfig,
|
|
52
|
-
exists,
|
|
53
|
-
};
|
|
54
|
-
}),
|
|
55
|
-
page: Number(page),
|
|
56
|
-
pageSize: Number(pageSize),
|
|
57
|
-
totalPage: totalPage(count, pageSize),
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
await next();
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export { roleCollectionsResource };
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Context, Next } from '@nocobase/actions';
|
|
2
|
-
|
|
3
|
-
export async function setDefaultRole(ctx: Context, next: Next) {
|
|
4
|
-
const {
|
|
5
|
-
values: { roleName },
|
|
6
|
-
} = ctx.action.params;
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
db,
|
|
10
|
-
state: { currentUser },
|
|
11
|
-
action: { params: { values } }
|
|
12
|
-
} = ctx;
|
|
13
|
-
|
|
14
|
-
if (values.roleName == 'anonymous') {
|
|
15
|
-
return next();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const repository = db.getRepository('rolesUsers');
|
|
19
|
-
|
|
20
|
-
await db.sequelize.transaction(async transaction => {
|
|
21
|
-
await repository.update({
|
|
22
|
-
filter: {
|
|
23
|
-
userId: currentUser.get('id'),
|
|
24
|
-
},
|
|
25
|
-
values: {
|
|
26
|
-
default: false,
|
|
27
|
-
},
|
|
28
|
-
transaction,
|
|
29
|
-
});
|
|
30
|
-
await repository.update({
|
|
31
|
-
filter: {
|
|
32
|
-
userId: currentUser.get('id'),
|
|
33
|
-
roleName,
|
|
34
|
-
},
|
|
35
|
-
values: {
|
|
36
|
-
default: true,
|
|
37
|
-
},
|
|
38
|
-
transaction,
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
ctx.body = 'ok';
|
|
43
|
-
|
|
44
|
-
await next();
|
|
45
|
-
}
|
package/src/collections/roles.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { CollectionOptions } from '@nocobase/database';
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
name: 'roles',
|
|
5
|
-
title: '{{t("Roles")}}',
|
|
6
|
-
autoGenId: false,
|
|
7
|
-
model: 'RoleModel',
|
|
8
|
-
filterTargetKey: 'name',
|
|
9
|
-
// targetKey: 'name',
|
|
10
|
-
sortable: true,
|
|
11
|
-
fields: [
|
|
12
|
-
{
|
|
13
|
-
type: 'uid',
|
|
14
|
-
name: 'name',
|
|
15
|
-
prefix: 'r_',
|
|
16
|
-
primaryKey: true,
|
|
17
|
-
interface: 'input',
|
|
18
|
-
uiSchema: {
|
|
19
|
-
type: 'string',
|
|
20
|
-
title: '{{t("Role UID")}}',
|
|
21
|
-
'x-component': 'Input',
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
type: 'string',
|
|
26
|
-
name: 'title',
|
|
27
|
-
unique: true,
|
|
28
|
-
interface: 'input',
|
|
29
|
-
uiSchema: {
|
|
30
|
-
type: 'string',
|
|
31
|
-
title: '{{t("Role name")}}',
|
|
32
|
-
'x-component': 'Input',
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
type: 'boolean',
|
|
37
|
-
name: 'default',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
type: 'string',
|
|
41
|
-
name: 'description',
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
type: 'json',
|
|
45
|
-
name: 'strategy',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
type: 'boolean',
|
|
49
|
-
name: 'default',
|
|
50
|
-
defaultValue: false,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
type: 'boolean',
|
|
54
|
-
name: 'hidden',
|
|
55
|
-
defaultValue: false,
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
type: 'boolean',
|
|
59
|
-
name: 'allowConfigure',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
type: 'boolean',
|
|
63
|
-
name: 'allowNewMenu',
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
type: 'belongsToMany',
|
|
67
|
-
name: 'menuUiSchemas',
|
|
68
|
-
target: 'uiSchemas',
|
|
69
|
-
targetKey: 'x-uid',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
type: 'hasMany',
|
|
73
|
-
name: 'resources',
|
|
74
|
-
target: 'rolesResources',
|
|
75
|
-
sourceKey: 'name',
|
|
76
|
-
targetKey: 'name',
|
|
77
|
-
},
|
|
78
|
-
],
|
|
79
|
-
} as CollectionOptions;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { CollectionOptions } from '@nocobase/database';
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
name: 'rolesResources',
|
|
5
|
-
model: 'RoleResourceModel',
|
|
6
|
-
indexes: [
|
|
7
|
-
{
|
|
8
|
-
unique: true,
|
|
9
|
-
fields: ['roleName', 'name'],
|
|
10
|
-
},
|
|
11
|
-
],
|
|
12
|
-
fields: [
|
|
13
|
-
{
|
|
14
|
-
type: 'belongsTo',
|
|
15
|
-
name: 'role',
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
type: 'string',
|
|
19
|
-
name: 'name',
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
type: 'boolean',
|
|
23
|
-
name: 'usingActionsConfig',
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
type: 'hasMany',
|
|
27
|
-
name: 'actions',
|
|
28
|
-
target: 'rolesResourcesActions',
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
} as CollectionOptions;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { CollectionOptions } from '@nocobase/database';
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
name: 'rolesResourcesActions',
|
|
5
|
-
model: 'RoleResourceActionModel',
|
|
6
|
-
fields: [
|
|
7
|
-
{
|
|
8
|
-
type: 'belongsTo',
|
|
9
|
-
name: 'resource',
|
|
10
|
-
foreignKey: 'rolesResourceId',
|
|
11
|
-
target: 'rolesResources',
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
type: 'string',
|
|
15
|
-
name: 'name',
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
type: 'array',
|
|
19
|
-
name: 'fields',
|
|
20
|
-
defaultValue: [],
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
type: 'belongsTo',
|
|
24
|
-
name: 'scope',
|
|
25
|
-
target: 'rolesResourcesScopes',
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
} as CollectionOptions;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { CollectionOptions } from '@nocobase/database';
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
name: 'rolesResourcesScopes',
|
|
5
|
-
fields: [
|
|
6
|
-
{
|
|
7
|
-
type: 'uid',
|
|
8
|
-
name: 'key',
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
type: 'string',
|
|
12
|
-
name: 'name',
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
type: 'string',
|
|
16
|
-
name: 'resourceName',
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
type: 'json',
|
|
20
|
-
name: 'scope',
|
|
21
|
-
},
|
|
22
|
-
],
|
|
23
|
-
} as CollectionOptions;
|
package/src/collections/users.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { extend } from '@nocobase/database';
|
|
2
|
-
|
|
3
|
-
export default extend({
|
|
4
|
-
name: 'users',
|
|
5
|
-
fields: [
|
|
6
|
-
{
|
|
7
|
-
interface: 'm2m',
|
|
8
|
-
type: 'belongsToMany',
|
|
9
|
-
name: 'roles',
|
|
10
|
-
target: 'roles',
|
|
11
|
-
foreignKey: 'userId',
|
|
12
|
-
otherKey: 'roleName',
|
|
13
|
-
sourceKey: 'id',
|
|
14
|
-
targetKey: 'name',
|
|
15
|
-
through: 'rolesUsers',
|
|
16
|
-
uiSchema: {
|
|
17
|
-
type: 'array',
|
|
18
|
-
title: '{{t("Roles")}}',
|
|
19
|
-
'x-component': 'RecordPicker',
|
|
20
|
-
'x-component-props': {
|
|
21
|
-
multiple: true,
|
|
22
|
-
fieldNames: {
|
|
23
|
-
label: 'title',
|
|
24
|
-
value: 'name',
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export async function setCurrentRole(ctx, next) {
|
|
2
|
-
let currentRole = ctx.get('X-Role');
|
|
3
|
-
|
|
4
|
-
if (currentRole === 'anonymous') {
|
|
5
|
-
ctx.state.currentRole = currentRole;
|
|
6
|
-
return next();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
if (!ctx.state.currentUser) {
|
|
10
|
-
return next();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const repository = ctx.db.getRepository('users.roles', ctx.state.currentUser.id);
|
|
14
|
-
const roles = await repository.find();
|
|
15
|
-
ctx.state.currentUser.setDataValue('roles', roles);
|
|
16
|
-
|
|
17
|
-
if (roles.length == 1) {
|
|
18
|
-
currentRole = roles[0].name;
|
|
19
|
-
} else if (roles.length > 1) {
|
|
20
|
-
const role = roles.find((item) => item.name === currentRole);
|
|
21
|
-
if (!role) {
|
|
22
|
-
const defaultRole = roles.find((item) => item?.rolesUsers?.default);
|
|
23
|
-
currentRole = (defaultRole || roles[0])?.name;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (currentRole) {
|
|
28
|
-
ctx.state.currentRole = currentRole;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
await next();
|
|
32
|
-
}
|
package/src/model/RoleModel.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Model } from '@nocobase/database';
|
|
2
|
-
import { ACL } from '@nocobase/acl';
|
|
3
|
-
|
|
4
|
-
export class RoleModel extends Model {
|
|
5
|
-
writeToAcl(options: { acl: ACL }) {
|
|
6
|
-
const { acl } = options;
|
|
7
|
-
const roleName = this.get('name') as string;
|
|
8
|
-
let role = acl.getRole(roleName);
|
|
9
|
-
|
|
10
|
-
if (!role) {
|
|
11
|
-
role = acl.define({
|
|
12
|
-
role: roleName,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
role.setStrategy({
|
|
17
|
-
...((this.get('strategy') as object) || {}),
|
|
18
|
-
allowConfigure: this.get('allowConfigure') as boolean,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { ACL, ACLRole } from '@nocobase/acl';
|
|
2
|
-
import { Database, Model } from '@nocobase/database';
|
|
3
|
-
import { AssociationFieldAction, AssociationFieldsActions, GrantHelper } from '../server';
|
|
4
|
-
|
|
5
|
-
export class RoleResourceActionModel extends Model {
|
|
6
|
-
async writeToACL(options: {
|
|
7
|
-
acl: ACL;
|
|
8
|
-
role: ACLRole;
|
|
9
|
-
resourceName: string;
|
|
10
|
-
associationFieldsActions: AssociationFieldsActions;
|
|
11
|
-
grantHelper: GrantHelper;
|
|
12
|
-
}) {
|
|
13
|
-
// @ts-ignore
|
|
14
|
-
const db: Database = this.constructor.database;
|
|
15
|
-
|
|
16
|
-
const { resourceName, role, acl, associationFieldsActions, grantHelper } = options;
|
|
17
|
-
|
|
18
|
-
const actionName = this.get('name') as string;
|
|
19
|
-
|
|
20
|
-
const fields = this.get('fields') as any;
|
|
21
|
-
|
|
22
|
-
const actionPath = `${resourceName}:${actionName}`;
|
|
23
|
-
const actionParams = {
|
|
24
|
-
fields,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
// @ts-ignore
|
|
28
|
-
const scope = await this.getScope();
|
|
29
|
-
|
|
30
|
-
if (scope) {
|
|
31
|
-
actionParams['own'] = scope.get('key') === 'own';
|
|
32
|
-
actionParams['filter'] = scope.get('scope');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
role.grantAction(actionPath, actionParams);
|
|
36
|
-
|
|
37
|
-
const collection = db.getCollection(resourceName);
|
|
38
|
-
|
|
39
|
-
if (!collection) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const availableAction = acl.resolveActionAlias(actionName);
|
|
44
|
-
|
|
45
|
-
for (const field of fields) {
|
|
46
|
-
const collectionField = collection.getField(field);
|
|
47
|
-
|
|
48
|
-
if (!collectionField) {
|
|
49
|
-
console.log(`${field} does not exist`);
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const fieldType = collectionField.get('interface') as string;
|
|
54
|
-
|
|
55
|
-
const fieldActions: AssociationFieldAction = associationFieldsActions?.[fieldType]?.[availableAction];
|
|
56
|
-
|
|
57
|
-
const fieldTarget = collectionField.get('target');
|
|
58
|
-
|
|
59
|
-
if (fieldActions) {
|
|
60
|
-
// grant association actions to role
|
|
61
|
-
const associationActions = fieldActions.associationActions || [];
|
|
62
|
-
associationActions.forEach((associationAction) => {
|
|
63
|
-
const actionName = `${resourceName}.${fieldTarget}:${associationAction}`;
|
|
64
|
-
role.grantAction(actionName);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const targetActions = fieldActions.targetActions || [];
|
|
68
|
-
|
|
69
|
-
targetActions.forEach((targetAction) => {
|
|
70
|
-
const targetActionPath = `${fieldTarget}:${targetAction}`;
|
|
71
|
-
|
|
72
|
-
// set resource target action with current resourceName
|
|
73
|
-
grantHelper.resourceTargetActionMap.set(`${role.name}.${resourceName}`, [
|
|
74
|
-
...(grantHelper.resourceTargetActionMap.get(resourceName) || []),
|
|
75
|
-
targetActionPath,
|
|
76
|
-
]);
|
|
77
|
-
|
|
78
|
-
grantHelper.targetActionResourceMap.set(targetActionPath, [
|
|
79
|
-
...(grantHelper.targetActionResourceMap.get(targetActionPath) || []),
|
|
80
|
-
`${role.name}.${resourceName}`,
|
|
81
|
-
]);
|
|
82
|
-
|
|
83
|
-
role.grantAction(targetActionPath);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|