refactor(plugin-users): improve extendibility of middlewares (#677)
* refactor(plugin-users): improve extendibility of middlewares * fix(plugin-users): fix typo * fix: test error * fix: allowConfigure condition Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
5b61587a39
commit
49a4ab4818
@ -19,7 +19,9 @@ export class AllowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const roleInstance = await ctx.db.getRepository('roles').findOne({
|
const roleInstance = await ctx.db.getRepository('roles').findOne({
|
||||||
name: roleName,
|
filter: {
|
||||||
|
name: roleName
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return roleInstance?.get('allowConfigure');
|
return roleInstance?.get('allowConfigure');
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { ActionName } from './action';
|
import { ActionName } from './action';
|
||||||
import { requireModule } from './utils';
|
import { requireModule } from './utils';
|
||||||
import { HandlerType } from './resourcer';
|
import { HandlerType } from './resourcer';
|
||||||
|
import compose from 'koa-compose';
|
||||||
|
|
||||||
export type MiddlewareType = string | string[] | HandlerType | HandlerType[] | MiddlewareOptions | MiddlewareOptions[];
|
export type MiddlewareType = string | string[] | HandlerType | HandlerType[] | MiddlewareOptions | MiddlewareOptions[];
|
||||||
|
|
||||||
@ -73,3 +74,19 @@ export class Middleware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default Middleware;
|
export default Middleware;
|
||||||
|
|
||||||
|
export class MiddlewareManager {
|
||||||
|
protected middlewares: HandlerType[] = [];
|
||||||
|
|
||||||
|
compose() {
|
||||||
|
return (ctx, next) => compose(this.middlewares)(ctx, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
use(middleware: HandlerType) {
|
||||||
|
this.middlewares.push(middleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
unuse(middleware: HandlerType) {
|
||||||
|
this.middlewares.splice(this.middlewares.indexOf(middleware), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nocobase/acl": "0.7.3-alpha.1",
|
"@nocobase/acl": "0.7.3-alpha.1",
|
||||||
"@nocobase/database": "0.7.3-alpha.1",
|
"@nocobase/database": "0.7.3-alpha.1",
|
||||||
|
"@nocobase/plugin-users": "0.7.3-alpha.1",
|
||||||
"@nocobase/server": "0.7.3-alpha.1"
|
"@nocobase/server": "0.7.3-alpha.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import { ACL } from '@nocobase/acl';
|
import { ACL } from '@nocobase/acl';
|
||||||
import { Database } from '@nocobase/database';
|
import { Database } from '@nocobase/database';
|
||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { changeMockRole, prepareApp } from './prepare';
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
import { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
import { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
||||||
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
describe('acl', () => {
|
describe('acl', () => {
|
||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
let db: Database;
|
let db: Database;
|
||||||
let acl: ACL;
|
let acl: ACL;
|
||||||
|
let admin;
|
||||||
|
let adminAgent;
|
||||||
|
|
||||||
let uiSchemaRepository: UiSchemaRepository;
|
let uiSchemaRepository: UiSchemaRepository;
|
||||||
|
|
||||||
@ -20,38 +23,41 @@ describe('acl', () => {
|
|||||||
db = app.db;
|
db = app.db;
|
||||||
acl = app.acl;
|
acl = app.acl;
|
||||||
|
|
||||||
|
const UserRepo = db.getCollection('users').repository;
|
||||||
|
admin = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['admin']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: admin.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
|
|
||||||
uiSchemaRepository = db.getRepository('uiSchemas');
|
uiSchemaRepository = db.getRepository('uiSchemas');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should works with universal actions', async () => {
|
it('should works with universal actions', async () => {
|
||||||
await db.getRepository('roles').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new'
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const role = await db.getRepository('roles').findOne({
|
|
||||||
filter: {
|
|
||||||
name: 'admin',
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
|
|
||||||
// grant universal action
|
// grant universal action
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles')
|
.resource('roles')
|
||||||
.update({
|
.update({
|
||||||
resourceIndex: 'admin',
|
resourceIndex: 'new',
|
||||||
values: {
|
values: {
|
||||||
strategy: {
|
strategy: {
|
||||||
actions: ['create'],
|
actions: ['create'],
|
||||||
@ -61,31 +67,27 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should deny when resource action has no resource', async () => {
|
it('should deny when resource action has no resource', async () => {
|
||||||
const role = await db.getRepository('roles').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new',
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
strategy: {
|
strategy: {
|
||||||
actions: ['update:own', 'destroy:own', 'create', 'view'],
|
actions: ['update:own', 'destroy:own', 'create', 'view'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
changeMockRole('admin');
|
|
||||||
|
|
||||||
// create c1 collection
|
// create c1 collection
|
||||||
await db.getRepository('collections').create({
|
await db.getRepository('collections').create({
|
||||||
values: {
|
values: {
|
||||||
@ -102,9 +104,8 @@ describe('acl', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
.resource('roles.resources', 'new')
|
||||||
.resource('roles.resources', 'admin')
|
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
name: 'c1',
|
name: 'c1',
|
||||||
@ -115,7 +116,7 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'c1',
|
resource: 'c1',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
}),
|
}),
|
||||||
@ -125,17 +126,13 @@ describe('acl', () => {
|
|||||||
it('should works with resources actions', async () => {
|
it('should works with resources actions', async () => {
|
||||||
const role = await db.getRepository('roles').create({
|
const role = await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new',
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
strategy: {
|
strategy: {
|
||||||
actions: ['list'],
|
actions: ['list'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
changeMockRole('admin');
|
|
||||||
|
|
||||||
// create c1 collection
|
// create c1 collection
|
||||||
await db.getRepository('collections').create({
|
await db.getRepository('collections').create({
|
||||||
values: {
|
values: {
|
||||||
@ -153,8 +150,7 @@ describe('acl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// create c1 published scope
|
// create c1 published scope
|
||||||
await app
|
const { body: { data: publishedScope } } = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('rolesResourcesScopes')
|
.resource('rolesResourcesScopes')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -166,12 +162,11 @@ describe('acl', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const publishedScope = await db.getRepository('rolesResourcesScopes').findOne();
|
// await db.getRepository('rolesResourcesScopes').findOne();
|
||||||
|
|
||||||
// set admin resources
|
// set admin resources
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
.resource('roles.resources', 'new')
|
||||||
.resource('roles.resources', 'admin')
|
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
name: 'c1',
|
name: 'c1',
|
||||||
@ -179,7 +174,7 @@ describe('acl', () => {
|
|||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
name: 'create',
|
name: 'create',
|
||||||
scope: publishedScope.get('id'),
|
scope: publishedScope.id,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'view',
|
name: 'view',
|
||||||
@ -191,12 +186,12 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'c1',
|
resource: 'c1',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'c1',
|
resource: 'c1',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
params: {
|
params: {
|
||||||
@ -206,12 +201,12 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'c1',
|
resource: 'c1',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'c1',
|
resource: 'c1',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
params: {
|
params: {
|
||||||
@ -220,8 +215,7 @@ describe('acl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// revoke action
|
// revoke action
|
||||||
const response = await app
|
const response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources', role.get('name'))
|
.resource('roles.resources', role.get('name'))
|
||||||
.list({
|
.list({
|
||||||
appends: ['actions'],
|
appends: ['actions'],
|
||||||
@ -232,8 +226,7 @@ describe('acl', () => {
|
|||||||
const actions = response.body.data[0].actions;
|
const actions = response.body.data[0].actions;
|
||||||
const collectionName = response.body.data[0].name;
|
const collectionName = response.body.data[0].name;
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources', role.get('name'))
|
.resource('roles.resources', role.get('name'))
|
||||||
.update({
|
.update({
|
||||||
filterByTk: collectionName,
|
filterByTk: collectionName,
|
||||||
@ -251,7 +244,7 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'c1',
|
resource: 'c1',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
@ -259,11 +252,9 @@ describe('acl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should revoke resource when collection destroy', async () => {
|
it('should revoke resource when collection destroy', async () => {
|
||||||
const role = await db.getRepository('roles').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new'
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -281,11 +272,10 @@ describe('acl', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources')
|
.resource('roles.resources')
|
||||||
.create({
|
.create({
|
||||||
associatedIndex: role.get('name') as string,
|
associatedIndex: 'new',
|
||||||
values: {
|
values: {
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
usingActionsConfig: true,
|
usingActionsConfig: true,
|
||||||
@ -300,7 +290,7 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
}),
|
}),
|
||||||
@ -314,7 +304,7 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
}),
|
}),
|
||||||
@ -324,15 +314,7 @@ describe('acl', () => {
|
|||||||
it('should revoke actions when not using actions config', async () => {
|
it('should revoke actions when not using actions config', async () => {
|
||||||
await db.getRepository('roles').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new'
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const role = await db.getRepository('roles').findOne({
|
|
||||||
filter: {
|
|
||||||
name: 'admin',
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -343,11 +325,10 @@ describe('acl', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources')
|
.resource('roles.resources')
|
||||||
.create({
|
.create({
|
||||||
associatedIndex: role.get('name') as string,
|
associatedIndex: 'new',
|
||||||
values: {
|
values: {
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
usingActionsConfig: true,
|
usingActionsConfig: true,
|
||||||
@ -361,25 +342,24 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
.resource('roles.resources', 'new')
|
||||||
.resource('roles.resources', role.get('name'))
|
|
||||||
.update({
|
.update({
|
||||||
filterByTk: (
|
filterByTk: (
|
||||||
await db.getRepository('rolesResources').findOne({
|
await db.getRepository('rolesResources').findOne({
|
||||||
filter: {
|
filter: {
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
roleName: 'admin',
|
roleName: 'new',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
).get('name') as string,
|
).get('name') as string,
|
||||||
@ -390,21 +370,20 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toBeNull();
|
).toBeNull();
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
.resource('roles.resources', 'new')
|
||||||
.resource('roles.resources', role.get('name'))
|
|
||||||
.update({
|
.update({
|
||||||
filterByTk: (
|
filterByTk: (
|
||||||
await db.getRepository('rolesResources').findOne({
|
await db.getRepository('rolesResources').findOne({
|
||||||
filter: {
|
filter: {
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
roleName: 'admin',
|
roleName: 'new',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
).get('name') as string,
|
).get('name') as string,
|
||||||
@ -415,23 +394,21 @@ describe('acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add fields when field created', async () => {
|
it('should add fields when field created', async () => {
|
||||||
const role = await db.getRepository('roles').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new'
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -449,11 +426,10 @@ describe('acl', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources')
|
.resource('roles.resources')
|
||||||
.create({
|
.create({
|
||||||
associatedIndex: role.get('name') as string,
|
associatedIndex: 'new',
|
||||||
values: {
|
values: {
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
usingActionsConfig: true,
|
usingActionsConfig: true,
|
||||||
@ -467,7 +443,7 @@ describe('acl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const allowFields = acl.can({
|
const allowFields = acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
})['params']['fields'];
|
})['params']['fields'];
|
||||||
@ -483,7 +459,7 @@ describe('acl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const newAllowFields = acl.can({
|
const newAllowFields = acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
})['params']['fields'];
|
})['params']['fields'];
|
||||||
@ -494,18 +470,14 @@ describe('acl', () => {
|
|||||||
it('should get role menus', async () => {
|
it('should get role menus', async () => {
|
||||||
const role = await db.getRepository('roles').create({
|
const role = await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new',
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
strategy: {
|
strategy: {
|
||||||
actions: ['view'],
|
actions: ['view'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
changeMockRole('admin');
|
const menuResponse = await adminAgent.resource('roles.menuUiSchemas', 'new').list();
|
||||||
|
|
||||||
const menuResponse = await app.agent().resource('roles.menuUiSchemas', 'admin').list();
|
|
||||||
|
|
||||||
expect(menuResponse.statusCode).toEqual(200);
|
expect(menuResponse.statusCode).toEqual(200);
|
||||||
});
|
});
|
||||||
@ -513,16 +485,23 @@ describe('acl', () => {
|
|||||||
it('should toggle role menus', async () => {
|
it('should toggle role menus', async () => {
|
||||||
const role = await db.getRepository('roles').create({
|
const role = await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new',
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
strategy: {
|
strategy: {
|
||||||
actions: ['*'],
|
actions: ['*'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const UserRepo = db.getCollection('users').repository;
|
||||||
|
const user = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['new']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
changeMockRole('admin');
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
const userAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: user.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
'x-uid': 'test',
|
'x-uid': 'test',
|
||||||
@ -530,9 +509,9 @@ describe('acl', () => {
|
|||||||
|
|
||||||
await uiSchemaRepository.insert(schema);
|
await uiSchemaRepository.insert(schema);
|
||||||
|
|
||||||
const response = await app
|
const response = await userAgent
|
||||||
.agent()
|
// @ts-ignore
|
||||||
.resource('roles.menuUiSchemas', 'admin')
|
.resource('roles.menuUiSchemas', 'new')
|
||||||
.toggle({
|
.toggle({
|
||||||
values: { tk: 'test' },
|
values: { tk: 'test' },
|
||||||
});
|
});
|
||||||
@ -543,9 +522,7 @@ describe('acl', () => {
|
|||||||
it('should sync data to acl before app start', async () => {
|
it('should sync data to acl before app start', async () => {
|
||||||
const role = await db.getRepository('roles').create({
|
const role = await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new',
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
resources: [
|
resources: [
|
||||||
{
|
{
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
@ -562,20 +539,20 @@ describe('acl', () => {
|
|||||||
hooks: false,
|
hooks: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(acl.getRole('admin')).toBeUndefined();
|
expect(acl.getRole('new')).toBeUndefined();
|
||||||
|
|
||||||
await app.start();
|
await app.start();
|
||||||
|
|
||||||
expect(acl.getRole('admin')).toBeDefined();
|
expect(acl.getRole('new')).toBeDefined();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'posts',
|
resource: 'posts',
|
||||||
action: 'view',
|
action: 'view',
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ACL } from '@nocobase/acl';
|
import { ACL } from '@nocobase/acl';
|
||||||
import { Database, HasManyRepository, Model } from '@nocobase/database';
|
import { Database, HasManyRepository } from '@nocobase/database';
|
||||||
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { prepareApp } from './prepare';
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
@ -8,7 +9,10 @@ describe('association field acl', () => {
|
|||||||
let db: Database;
|
let db: Database;
|
||||||
let acl: ACL;
|
let acl: ACL;
|
||||||
|
|
||||||
let role: Model;
|
let user;
|
||||||
|
let userAgent;
|
||||||
|
let admin;
|
||||||
|
let adminAgent;
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await app.destroy();
|
await app.destroy();
|
||||||
@ -19,20 +23,44 @@ describe('association field acl', () => {
|
|||||||
db = app.db;
|
db = app.db;
|
||||||
acl = app.acl;
|
acl = app.acl;
|
||||||
|
|
||||||
role = await db.getRepository('roles').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
name: 'new',
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
allowConfigure: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await db.getRepository('collections').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'users',
|
name: 'testAdmin',
|
||||||
|
allowConfigure: true,
|
||||||
},
|
},
|
||||||
context: {},
|
|
||||||
});
|
});
|
||||||
|
const UserRepo = db.getCollection('users').repository;
|
||||||
|
user = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['new'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
admin = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['testAdmin'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
userAgent = app.agent().auth(
|
||||||
|
userPlugin.jwtService.sign({
|
||||||
|
userId: user.get('id'),
|
||||||
|
}),
|
||||||
|
{ type: 'bearer' },
|
||||||
|
);
|
||||||
|
adminAgent = app.agent().auth(
|
||||||
|
userPlugin.jwtService.sign({
|
||||||
|
userId: admin.get('id'),
|
||||||
|
}),
|
||||||
|
{ type: 'bearer' },
|
||||||
|
);
|
||||||
|
|
||||||
await db.getRepository('collections').create({
|
await db.getRepository('collections').create({
|
||||||
values: {
|
values: {
|
||||||
@ -75,56 +103,48 @@ describe('association field acl', () => {
|
|||||||
context: {},
|
context: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent.resource('roles.resources', 'new').create({
|
||||||
.agent()
|
values: {
|
||||||
.resource('roles.resources')
|
name: 'users',
|
||||||
.create({
|
usingActionsConfig: true,
|
||||||
associatedIndex: 'admin',
|
actions: [
|
||||||
values: {
|
{
|
||||||
name: 'users',
|
name: 'create',
|
||||||
usingActionsConfig: true,
|
fields: ['orders'],
|
||||||
actions: [
|
},
|
||||||
{
|
{
|
||||||
name: 'create',
|
name: 'view',
|
||||||
fields: ['orders'],
|
fields: ['orders'],
|
||||||
},
|
},
|
||||||
{
|
],
|
||||||
name: 'view',
|
},
|
||||||
fields: ['orders'],
|
});
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should revoke target action on association action revoke', async () => {
|
it('should revoke target action on association action revoke', async () => {
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'orders',
|
resource: 'orders',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'orders',
|
resource: 'orders',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent.resource('roles.resources', 'new').update({
|
||||||
.agent()
|
values: {
|
||||||
.resource('roles.resources')
|
name: 'users',
|
||||||
.update({
|
usingActionsConfig: true,
|
||||||
associatedIndex: 'admin',
|
actions: [],
|
||||||
values: {
|
},
|
||||||
name: 'users',
|
});
|
||||||
usingActionsConfig: true,
|
|
||||||
actions: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'orders',
|
resource: 'orders',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
}),
|
}),
|
||||||
@ -134,12 +154,12 @@ describe('association field acl', () => {
|
|||||||
it('should revoke association action on action revoke', async () => {
|
it('should revoke association action on action revoke', async () => {
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users.orders',
|
resource: 'users.orders',
|
||||||
action: 'add',
|
action: 'add',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users.orders',
|
resource: 'users.orders',
|
||||||
action: 'add',
|
action: 'add',
|
||||||
});
|
});
|
||||||
@ -152,27 +172,23 @@ describe('association field acl', () => {
|
|||||||
|
|
||||||
const actionId = viewAction.get('id') as number;
|
const actionId = viewAction.get('id') as number;
|
||||||
|
|
||||||
const response = await app
|
const response = await adminAgent.resource('roles.resources', 'new').update({
|
||||||
.agent()
|
values: {
|
||||||
.resource('roles.resources')
|
name: 'users',
|
||||||
.update({
|
usingActionsConfig: true,
|
||||||
associatedIndex: 'admin',
|
actions: [
|
||||||
values: {
|
{
|
||||||
name: 'users',
|
id: actionId,
|
||||||
usingActionsConfig: true,
|
},
|
||||||
actions: [
|
],
|
||||||
{
|
},
|
||||||
id: actionId,
|
});
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users.orders',
|
resource: 'users.orders',
|
||||||
action: 'add',
|
action: 'add',
|
||||||
}),
|
}),
|
||||||
@ -180,30 +196,26 @@ describe('association field acl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should revoke association action on field deleted', async () => {
|
it('should revoke association action on field deleted', async () => {
|
||||||
await app
|
await adminAgent.resource('roles.resources', 'new').update({
|
||||||
.agent()
|
values: {
|
||||||
.resource('roles.resources')
|
name: 'users',
|
||||||
.update({
|
usingActionsConfig: true,
|
||||||
associatedIndex: 'admin',
|
actions: [
|
||||||
values: {
|
{
|
||||||
name: 'users',
|
name: 'create',
|
||||||
usingActionsConfig: true,
|
fields: ['name', 'age'],
|
||||||
actions: [
|
},
|
||||||
{
|
],
|
||||||
name: 'create',
|
},
|
||||||
fields: ['name', 'age'],
|
});
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users',
|
resource: 'users',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users',
|
resource: 'users',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
params: {
|
params: {
|
||||||
@ -236,12 +248,12 @@ describe('association field acl', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users',
|
resource: 'users',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users',
|
resource: 'users',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
params: {
|
params: {
|
||||||
@ -251,45 +263,44 @@ describe('association field acl', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should allow association fields access', async () => {
|
it('should allow association fields access', async () => {
|
||||||
const createResponse = await app
|
const createResponse = await userAgent.resource('users').create({
|
||||||
.agent()
|
values: {
|
||||||
.resource('users')
|
orders: [
|
||||||
.create({
|
{
|
||||||
values: {
|
content: 'apple',
|
||||||
orders: [
|
},
|
||||||
{
|
],
|
||||||
content: 'apple',
|
},
|
||||||
},
|
});
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(createResponse.statusCode).toEqual(200);
|
expect(createResponse.statusCode).toEqual(200);
|
||||||
|
|
||||||
const user = await db.getRepository('users').findOne();
|
const user = await db.getRepository('users').findOne({
|
||||||
|
filterByTk: createResponse.body.data.id,
|
||||||
|
});
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
expect(await user.countOrders()).toEqual(1);
|
expect(await user.countOrders()).toEqual(1);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users.orders',
|
resource: 'users.orders',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'users.orders',
|
resource: 'users.orders',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
acl.can({
|
acl.can({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'orders',
|
resource: 'orders',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
}),
|
}),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
role: 'admin',
|
role: 'new',
|
||||||
resource: 'orders',
|
resource: 'orders',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
});
|
});
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import { MockServer } from '@nocobase/test';
|
|
||||||
import { Database } from '@nocobase/database';
|
import { Database } from '@nocobase/database';
|
||||||
import { ACL } from '@nocobase/acl';
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
import { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { changeMockRole, prepareApp } from './prepare';
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
describe('configuration', () => {
|
describe('configuration', () => {
|
||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
let db: Database;
|
let db: Database;
|
||||||
let acl: ACL;
|
let admin;
|
||||||
|
let adminAgent;
|
||||||
let uiSchemaRepository: UiSchemaRepository;
|
let user;
|
||||||
|
let userAgent;
|
||||||
|
let guestAgent;
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await app.destroy();
|
await app.destroy();
|
||||||
@ -18,28 +19,56 @@ describe('configuration', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
app = await prepareApp();
|
app = await prepareApp();
|
||||||
db = app.db;
|
db = app.db;
|
||||||
acl = app.acl;
|
|
||||||
|
|
||||||
uiSchemaRepository = db.getRepository('uiSchemas');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should list collections', async () => {
|
|
||||||
expect((await app.agent().resource('collections').create()).statusCode).toEqual(403);
|
|
||||||
expect((await app.agent().resource('collections').list()).statusCode).toEqual(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow when role has allowConfigure with true value', async () => {
|
|
||||||
await db.getRepository('roles').create({
|
await db.getRepository('roles').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin1',
|
name: 'test1',
|
||||||
title: 'admin allowConfigure',
|
|
||||||
allowConfigure: true,
|
allowConfigure: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
changeMockRole('admin1');
|
await db.getRepository('roles').create({
|
||||||
|
values: {
|
||||||
|
name: 'test2',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
expect((await app.agent().resource('collections').create()).statusCode).toEqual(200);
|
const UserRepo = db.getCollection('users').repository;
|
||||||
expect((await app.agent().resource('collections').list()).statusCode).toEqual(200);
|
admin = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['test1']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
user = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['test2']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: admin.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
|
|
||||||
|
userAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: user.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
|
|
||||||
|
guestAgent = app.agent();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should list collections', async () => {
|
||||||
|
expect((await userAgent.resource('collections').create()).statusCode).toEqual(403);
|
||||||
|
expect((await userAgent.resource('collections').list()).statusCode).toEqual(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not create/list collections', async () => {
|
||||||
|
expect((await guestAgent.resource('collections').create()).statusCode).toEqual(403);
|
||||||
|
expect((await guestAgent.resource('collections').list()).statusCode).toEqual(403);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow when role has allowConfigure with true value', async () => {
|
||||||
|
expect((await adminAgent.resource('collections').create()).statusCode).toEqual(200);
|
||||||
|
expect((await adminAgent.resource('collections').list()).statusCode).toEqual(200);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,33 +1,40 @@
|
|||||||
import { ACL } from '@nocobase/acl';
|
import { ACL } from '@nocobase/acl';
|
||||||
import { Database, Model } from '@nocobase/database';
|
import { Database, Model } from '@nocobase/database';
|
||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { changeMockUser, prepareApp } from './prepare';
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
describe('middleware', () => {
|
describe('middleware', () => {
|
||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
let role: Model;
|
let role: Model;
|
||||||
let db: Database;
|
let db: Database;
|
||||||
let acl: ACL;
|
let acl: ACL;
|
||||||
|
let admin;
|
||||||
|
let adminAgent;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
app = await prepareApp();
|
app = await prepareApp();
|
||||||
db = app.db;
|
db = app.db;
|
||||||
acl = app.acl;
|
acl = app.acl;
|
||||||
|
|
||||||
await db.getRepository('roles').create({
|
|
||||||
values: {
|
|
||||||
name: 'admin',
|
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
role = await db.getRepository('roles').findOne({
|
role = await db.getRepository('roles').findOne({
|
||||||
filter: {
|
filter: {
|
||||||
name: 'admin',
|
name: 'admin',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const UserRepo = db.getCollection('users').repository;
|
||||||
|
admin = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['admin']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: admin.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
|
|
||||||
await db.getRepository('collections').create({
|
await db.getRepository('collections').create({
|
||||||
values: {
|
values: {
|
||||||
name: 'posts',
|
name: 'posts',
|
||||||
@ -82,7 +89,7 @@ describe('middleware', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await app.agent().resource('posts').create({
|
const response = await adminAgent.resource('posts').create({
|
||||||
values: {},
|
values: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -90,8 +97,7 @@ describe('middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should limit fields on view actions', async () => {
|
it('should limit fields on view actions', async () => {
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources', role.get('name'))
|
.resource('roles.resources', role.get('name'))
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -110,8 +116,7 @@ describe('middleware', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('posts')
|
.resource('posts')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -124,10 +129,10 @@ describe('middleware', () => {
|
|||||||
expect(post.get('title')).toEqual('post-title');
|
expect(post.get('title')).toEqual('post-title');
|
||||||
expect(post.get('description')).toEqual('post-description');
|
expect(post.get('description')).toEqual('post-description');
|
||||||
|
|
||||||
const response = await app.agent().resource('posts').list({});
|
const response = await adminAgent.resource('posts').list({});
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
|
|
||||||
const data = response.body.data[0];
|
const [data] = response.body.data;
|
||||||
|
|
||||||
expect(data['id']).not.toBeUndefined();
|
expect(data['id']).not.toBeUndefined();
|
||||||
expect(data['title']).toEqual('post-title');
|
expect(data['title']).toEqual('post-title');
|
||||||
@ -135,12 +140,7 @@ describe('middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should parse template value on action params', async () => {
|
it('should parse template value on action params', async () => {
|
||||||
changeMockUser({
|
const res = await adminAgent
|
||||||
id: 2,
|
|
||||||
});
|
|
||||||
|
|
||||||
const res = await app
|
|
||||||
.agent()
|
|
||||||
.resource('rolesResourcesScopes')
|
.resource('rolesResourcesScopes')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -151,8 +151,7 @@ describe('middleware', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources', role.get('name'))
|
.resource('roles.resources', role.get('name'))
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -172,8 +171,7 @@ describe('middleware', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('posts')
|
.resource('posts')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -183,8 +181,7 @@ describe('middleware', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('posts')
|
.resource('posts')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -194,14 +191,13 @@ describe('middleware', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await app.agent().resource('posts').list();
|
const response = await adminAgent.resource('posts').list();
|
||||||
const data = response.body.data;
|
const data = response.body.data;
|
||||||
expect(data.length).toEqual(1);
|
expect(data.length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change fields params to whitelist in create action', async () => {
|
it('should change fields params to whitelist in create action', async () => {
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources', role.get('name'))
|
.resource('roles.resources', role.get('name'))
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -216,8 +212,7 @@ describe('middleware', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await app
|
await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('posts')
|
.resource('posts')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import { ACL } from '@nocobase/acl';
|
import { ACL } from '@nocobase/acl';
|
||||||
import { Database } from '@nocobase/database';
|
import { Database } from '@nocobase/database';
|
||||||
import PluginACL from '@nocobase/plugin-acl';
|
|
||||||
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
|
|
||||||
import PluginUiSchema from '@nocobase/plugin-ui-schema-storage';
|
|
||||||
import PluginUser from '@nocobase/plugin-users';
|
import PluginUser from '@nocobase/plugin-users';
|
||||||
import { mockServer, MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import supertest from 'supertest';
|
|
||||||
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
describe('own test', () => {
|
describe('own test', () => {
|
||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
@ -21,28 +19,15 @@ describe('own test', () => {
|
|||||||
|
|
||||||
let role;
|
let role;
|
||||||
let agent;
|
let agent;
|
||||||
|
let adminAgent;
|
||||||
|
let userAgent;
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await app.destroy();
|
await app.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
app = mockServer({
|
app = await prepareApp();
|
||||||
registerActions: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
await app.cleanDb();
|
|
||||||
|
|
||||||
app.plugin(PluginUiSchema);
|
|
||||||
app.plugin(PluginCollectionManager);
|
|
||||||
app.plugin(PluginUser, {
|
|
||||||
jwt: {
|
|
||||||
secret: process.env.APP_KEY || 'test-key',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
app.plugin(PluginACL);
|
|
||||||
await app.loadAndInstall();
|
|
||||||
db = app.db;
|
db = app.db;
|
||||||
|
|
||||||
const PostCollection = db.collection({
|
const PostCollection = db.collection({
|
||||||
@ -68,9 +53,9 @@ describe('own test', () => {
|
|||||||
fields: [{ type: 'string', name: 'name' }],
|
fields: [{ type: 'string', name: 'name' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.db.sync();
|
await db.sync();
|
||||||
|
|
||||||
agent = supertest.agent(app.callback());
|
agent = app.agent();
|
||||||
|
|
||||||
acl = app.acl;
|
acl = app.acl;
|
||||||
|
|
||||||
@ -86,6 +71,8 @@ describe('own test', () => {
|
|||||||
|
|
||||||
adminToken = pluginUser.jwtService.sign({ userId: admin.get('id') });
|
adminToken = pluginUser.jwtService.sign({ userId: admin.get('id') });
|
||||||
|
|
||||||
|
adminAgent = app.agent().auth(adminToken, { type: 'bearer' });
|
||||||
|
|
||||||
user = await db.getRepository('users').create({
|
user = await db.getRepository('users').create({
|
||||||
values: {
|
values: {
|
||||||
nickname: 'test',
|
nickname: 'test',
|
||||||
@ -94,10 +81,12 @@ describe('own test', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
userToken = pluginUser.jwtService.sign({ userId: user.get('id') });
|
userToken = pluginUser.jwtService.sign({ userId: user.get('id') });
|
||||||
|
|
||||||
|
userAgent = app.agent().auth(userToken, { type: 'bearer' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should list without createBy', async () => {
|
it('should list without createBy', async () => {
|
||||||
let response = await agent
|
await adminAgent
|
||||||
.patch('/roles/admin')
|
.patch('/roles/admin')
|
||||||
.send({
|
.send({
|
||||||
strategy: {
|
strategy: {
|
||||||
@ -106,33 +95,38 @@ describe('own test', () => {
|
|||||||
})
|
})
|
||||||
.set({ Authorization: 'Bearer ' + adminToken });
|
.set({ Authorization: 'Bearer ' + adminToken });
|
||||||
|
|
||||||
response = await agent.get('/tests:list').set({ Authorization: 'Bearer ' + userToken });
|
const response = await userAgent.get('/tests:list');
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete with createdBy', async () => {
|
it('should delete with createdBy', async () => {
|
||||||
let response = await agent
|
await adminAgent
|
||||||
.patch('/roles/admin')
|
.resource('roles')
|
||||||
.send({
|
.update({
|
||||||
strategy: {
|
filterByTk: 'admin',
|
||||||
actions: ['view:own', 'create', 'destroy:own'],
|
values: {
|
||||||
},
|
strategy: {
|
||||||
})
|
actions: ['view:own', 'create', 'destroy:own'],
|
||||||
.set({ Authorization: 'Bearer ' + adminToken });
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
response = await agent
|
let response = await userAgent
|
||||||
.get('/posts:create')
|
.resource('posts')
|
||||||
.send({
|
.create({
|
||||||
title: 't1',
|
values: {
|
||||||
})
|
title: 't1',
|
||||||
.set({ Authorization: 'Bearer ' + userToken });
|
}
|
||||||
|
});
|
||||||
|
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
|
|
||||||
const data = response.body;
|
const data = response.body;
|
||||||
const id = data.data['id'];
|
const id = data.data['id'];
|
||||||
|
|
||||||
response = await agent.delete(`/posts/${id}`).set({ Authorization: 'Bearer ' + userToken });
|
response = await userAgent.resource('posts').destroy({
|
||||||
|
filterByTk: id
|
||||||
|
});
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
expect(await db.getRepository('posts').count()).toEqual(0);
|
expect(await db.getRepository('posts').count()).toEqual(0);
|
||||||
});
|
});
|
||||||
|
@ -1,18 +1,10 @@
|
|||||||
|
import PluginUsers from '@nocobase/plugin-users';
|
||||||
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
|
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
|
||||||
import PluginUiSchema from '@nocobase/plugin-ui-schema-storage';
|
import PluginUiSchema from '@nocobase/plugin-ui-schema-storage';
|
||||||
import { mockServer } from '@nocobase/test';
|
import { mockServer } from '@nocobase/test';
|
||||||
import PluginACL from '../server';
|
import PluginACL from '../server';
|
||||||
|
|
||||||
let mockRole: string = 'admin';
|
|
||||||
let mockUser = {};
|
|
||||||
|
|
||||||
export function changeMockRole(role: string) {
|
|
||||||
mockRole = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function changeMockUser(user: any) {
|
|
||||||
mockUser = user;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function prepareApp() {
|
export async function prepareApp() {
|
||||||
const app = mockServer({
|
const app = mockServer({
|
||||||
@ -21,15 +13,10 @@ export async function prepareApp() {
|
|||||||
|
|
||||||
await app.cleanDb();
|
await app.cleanDb();
|
||||||
|
|
||||||
|
app.plugin(PluginUsers);
|
||||||
app.plugin(PluginUiSchema);
|
app.plugin(PluginUiSchema);
|
||||||
app.plugin(PluginCollectionManager);
|
app.plugin(PluginCollectionManager);
|
||||||
|
|
||||||
app.resourcer.use(async (ctx, next) => {
|
|
||||||
ctx.state.currentRole = mockRole;
|
|
||||||
ctx.state.currentUser = mockUser;
|
|
||||||
await next();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.plugin(PluginACL);
|
app.plugin(PluginACL);
|
||||||
await app.loadAndInstall();
|
await app.loadAndInstall();
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { changeMockRole, changeMockUser, prepareApp } from './prepare';
|
|
||||||
import { Database } from '@nocobase/database';
|
import { Database } from '@nocobase/database';
|
||||||
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
|
|
||||||
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
describe('role check action', () => {
|
describe('role check action', () => {
|
||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
@ -21,14 +23,18 @@ describe('role check action', () => {
|
|||||||
name: 'test',
|
name: 'test',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const user = await db.getRepository('users').create({
|
||||||
changeMockUser({
|
values: {
|
||||||
id: 2,
|
roles: ['test']
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
const agent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: user.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
|
|
||||||
changeMockRole('test');
|
// @ts-ignore
|
||||||
|
const response = await agent.resource('roles').check();
|
||||||
const response = await app.agent().get('/roles:check');
|
|
||||||
|
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Database, Model } from '@nocobase/database';
|
import { Database, Model } from '@nocobase/database';
|
||||||
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
|
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
|
||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { prepareApp } from './prepare';
|
import { prepareApp } from './prepare';
|
||||||
@ -7,6 +8,8 @@ describe('role resource api', () => {
|
|||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
let db: Database;
|
let db: Database;
|
||||||
let role: Model;
|
let role: Model;
|
||||||
|
let admin;
|
||||||
|
let adminAgent;
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await app.destroy();
|
await app.destroy();
|
||||||
@ -16,19 +19,23 @@ describe('role resource api', () => {
|
|||||||
app = await prepareApp();
|
app = await prepareApp();
|
||||||
db = app.db;
|
db = app.db;
|
||||||
|
|
||||||
await db.getRepository('roles').create({
|
|
||||||
values: {
|
|
||||||
name: 'admin',
|
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
role = await db.getRepository('roles').findOne({
|
role = await db.getRepository('roles').findOne({
|
||||||
filter: {
|
filter: {
|
||||||
name: 'admin',
|
name: 'admin',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const UserRepo = db.getCollection('users').repository;
|
||||||
|
admin = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['admin']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: admin.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should grant resource by createRepository', async () => {
|
it('should grant resource by createRepository', async () => {
|
||||||
@ -91,8 +98,7 @@ describe('role resource api', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// get collections list
|
// get collections list
|
||||||
let response = await app
|
let response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.collections', 'admin')
|
.resource('roles.collections', 'admin')
|
||||||
.list({
|
.list({
|
||||||
filter: {
|
filter: {
|
||||||
@ -119,8 +125,7 @@ describe('role resource api', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// set resource actions
|
// set resource actions
|
||||||
response = await app
|
response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources', 'admin')
|
.resource('roles.resources', 'admin')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
@ -137,8 +142,7 @@ describe('role resource api', () => {
|
|||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
|
|
||||||
// get collections list
|
// get collections list
|
||||||
response = await app
|
response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.collections')
|
.resource('roles.collections')
|
||||||
.list({
|
.list({
|
||||||
associatedIndex: role.get('name') as string,
|
associatedIndex: role.get('name') as string,
|
||||||
@ -149,8 +153,7 @@ describe('role resource api', () => {
|
|||||||
|
|
||||||
expect(response.body.data[0]['usingConfig']).toEqual('resourceAction');
|
expect(response.body.data[0]['usingConfig']).toEqual('resourceAction');
|
||||||
|
|
||||||
response = await app
|
response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources')
|
.resource('roles.resources')
|
||||||
.list({
|
.list({
|
||||||
associatedIndex: role.get('name') as string,
|
associatedIndex: role.get('name') as string,
|
||||||
@ -164,8 +167,7 @@ describe('role resource api', () => {
|
|||||||
expect(resourceAction['name']).toEqual('create');
|
expect(resourceAction['name']).toEqual('create');
|
||||||
|
|
||||||
// update resource actions
|
// update resource actions
|
||||||
response = await app
|
response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles.resources')
|
.resource('roles.resources')
|
||||||
.update({
|
.update({
|
||||||
associatedIndex: role.get('name') as string,
|
associatedIndex: role.get('name') as string,
|
||||||
|
@ -2,7 +2,6 @@ import Database, { BelongsToManyRepository } from '@nocobase/database';
|
|||||||
import PluginACL from '@nocobase/plugin-acl';
|
import PluginACL from '@nocobase/plugin-acl';
|
||||||
import UsersPlugin from '@nocobase/plugin-users';
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
import { MockServer, mockServer } from '@nocobase/test';
|
import { MockServer, mockServer } from '@nocobase/test';
|
||||||
import { userPluginConfig } from './utils';
|
|
||||||
|
|
||||||
describe('role', () => {
|
describe('role', () => {
|
||||||
let api: MockServer;
|
let api: MockServer;
|
||||||
@ -13,7 +12,7 @@ describe('role', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
api = mockServer();
|
api = mockServer();
|
||||||
await api.cleanDb();
|
await api.cleanDb();
|
||||||
api.plugin(UsersPlugin, userPluginConfig);
|
api.plugin(UsersPlugin);
|
||||||
api.plugin(PluginACL);
|
api.plugin(PluginACL);
|
||||||
await api.loadAndInstall();
|
await api.loadAndInstall();
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
|
|
||||||
import { Database, Model } from '@nocobase/database';
|
import { Database, Model } from '@nocobase/database';
|
||||||
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
|
|
||||||
import { prepareApp } from './prepare';
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
@ -19,32 +19,37 @@ describe('role api', () => {
|
|||||||
|
|
||||||
describe('grant', () => {
|
describe('grant', () => {
|
||||||
let role: Model;
|
let role: Model;
|
||||||
|
let admin: Model;
|
||||||
|
let adminAgent;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await db.getRepository('roles').create({
|
|
||||||
values: {
|
|
||||||
name: 'admin',
|
|
||||||
title: 'Admin User',
|
|
||||||
allowConfigure: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
role = await db.getRepository('roles').findOne({
|
role = await db.getRepository('roles').findOne({
|
||||||
filter: {
|
filter: {
|
||||||
name: 'admin',
|
name: 'admin',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const UserRepo = db.getCollection('users').repository;
|
||||||
|
admin = await UserRepo.create({
|
||||||
|
values: {
|
||||||
|
roles: ['admin']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: admin.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should list actions', async () => {
|
it('should list actions', async () => {
|
||||||
const response = await app.agent().resource('availableActions').list();
|
const response = await adminAgent.resource('availableActions').list();
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should grant universal role actions', async () => {
|
it('should grant universal role actions', async () => {
|
||||||
// grant role actions
|
// grant role actions
|
||||||
const response = await app
|
const response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('roles')
|
.resource('roles')
|
||||||
.update({
|
.update({
|
||||||
values: {
|
values: {
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import { prepareApp } from './prepare';
|
import { prepareApp } from './prepare';
|
||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { Database } from '@nocobase/database';
|
import { Database } from '@nocobase/database';
|
||||||
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
|
|
||||||
describe('scope api', () => {
|
describe('scope api', () => {
|
||||||
let app: MockServer;
|
let app: MockServer;
|
||||||
let db: Database;
|
let db: Database;
|
||||||
|
|
||||||
|
let admin;
|
||||||
|
let adminAgent;
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await app.destroy();
|
await app.destroy();
|
||||||
});
|
});
|
||||||
@ -13,18 +17,22 @@ describe('scope api', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
app = await prepareApp();
|
app = await prepareApp();
|
||||||
db = app.db;
|
db = app.db;
|
||||||
await db.getRepository('roles').create({
|
|
||||||
|
const UserRepo = db.getCollection('users').repository;
|
||||||
|
admin = await UserRepo.create({
|
||||||
values: {
|
values: {
|
||||||
name: 'admin',
|
roles: ['admin']
|
||||||
title: 'Admin User',
|
}
|
||||||
allowConfigure: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const userPlugin = app.getPlugin('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
adminAgent = app.agent().auth(userPlugin.jwtService.sign({
|
||||||
|
userId: admin.get('id'),
|
||||||
|
}), { type: 'bearer' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create scope of resource', async () => {
|
it('should create scope of resource', async () => {
|
||||||
const response = await app
|
const response = await adminAgent
|
||||||
.agent()
|
|
||||||
.resource('rolesResourcesScopes')
|
.resource('rolesResourcesScopes')
|
||||||
.create({
|
.create({
|
||||||
values: {
|
values: {
|
||||||
|
83
packages/plugins/acl/src/__tests__/setCurrentRole.test.ts
Normal file
83
packages/plugins/acl/src/__tests__/setCurrentRole.test.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import Database from '@nocobase/database';
|
||||||
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
|
import { MockServer } from '@nocobase/test';
|
||||||
|
import { setCurrentRole } from '../middlewares/setCurrentRole';
|
||||||
|
import { prepareApp } from './prepare';
|
||||||
|
|
||||||
|
describe('role', () => {
|
||||||
|
let api: MockServer;
|
||||||
|
let db: Database;
|
||||||
|
|
||||||
|
let usersPlugin: UsersPlugin;
|
||||||
|
let ctx;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
api = await prepareApp();
|
||||||
|
|
||||||
|
db = api.db;
|
||||||
|
usersPlugin = api.getPlugin('@nocobase/plugin-users');
|
||||||
|
|
||||||
|
ctx = {
|
||||||
|
db,
|
||||||
|
state: {
|
||||||
|
currentRole: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await api.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set role with X-Role when exists', async () => {
|
||||||
|
ctx.state.currentUser = await db.getRepository('users').findOne({
|
||||||
|
appends: ['roles'],
|
||||||
|
});
|
||||||
|
ctx.get = function(name) {
|
||||||
|
if (name === 'X-Role') {
|
||||||
|
return 'admin';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await setCurrentRole(ctx, () => {});
|
||||||
|
expect(ctx.state.currentRole).toBe('admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set role with default', async () => {
|
||||||
|
ctx.state.currentUser = await db.getRepository('users').findOne({
|
||||||
|
appends: ['roles'],
|
||||||
|
});
|
||||||
|
ctx.get = function (name) {
|
||||||
|
if (name === 'X-Role') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await setCurrentRole(ctx, () => {});
|
||||||
|
expect(ctx.state.currentRole).toBe('root');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set role with default when x-role does not exist', async () => {
|
||||||
|
ctx.state.currentUser = await db.getRepository('users').findOne({
|
||||||
|
appends: ['roles'],
|
||||||
|
});
|
||||||
|
ctx.get = function (name) {
|
||||||
|
if (name === 'X-Role') {
|
||||||
|
return 'abc';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await setCurrentRole(ctx, () => {});
|
||||||
|
expect(ctx.state.currentRole).toBe('root');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set role with anonymous', async () => {
|
||||||
|
ctx.state.currentUser = await db.getRepository('users').findOne({
|
||||||
|
appends: ['roles'],
|
||||||
|
});
|
||||||
|
ctx.get = function (name) {
|
||||||
|
if (name === 'X-Role') {
|
||||||
|
return 'anonymous';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await setCurrentRole(ctx, () => {});
|
||||||
|
expect(ctx.state.currentRole).toBe('anonymous');
|
||||||
|
});
|
||||||
|
});
|
45
packages/plugins/acl/src/actions/user-setDefaultRole.ts
Normal file
45
packages/plugins/acl/src/actions/user-setDefaultRole.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { Context, Next } from '@nocobase/actions';
|
||||||
|
|
||||||
|
export async function setDefaultRole(ctx: Context, next: Next) {
|
||||||
|
const {
|
||||||
|
values: { roleName },
|
||||||
|
} = ctx.action.params;
|
||||||
|
|
||||||
|
const {
|
||||||
|
db,
|
||||||
|
state: { currentUser },
|
||||||
|
action: { params: { values } }
|
||||||
|
} = ctx;
|
||||||
|
|
||||||
|
if (values.roleName == 'anonymous') {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const repository = db.getRepository('rolesUsers');
|
||||||
|
|
||||||
|
await db.sequelize.transaction(async transaction => {
|
||||||
|
await repository.update({
|
||||||
|
filter: {
|
||||||
|
userId: currentUser.get('id'),
|
||||||
|
},
|
||||||
|
values: {
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
await repository.update({
|
||||||
|
filter: {
|
||||||
|
userId: currentUser.get('id'),
|
||||||
|
roleName,
|
||||||
|
},
|
||||||
|
values: {
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.body = 'ok';
|
||||||
|
|
||||||
|
await next();
|
||||||
|
}
|
30
packages/plugins/acl/src/collections/users.ts
Normal file
30
packages/plugins/acl/src/collections/users.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { extend } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default extend({
|
||||||
|
name: 'users',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
interface: 'm2m',
|
||||||
|
type: 'belongsToMany',
|
||||||
|
name: 'roles',
|
||||||
|
target: 'roles',
|
||||||
|
foreignKey: 'userId',
|
||||||
|
otherKey: 'roleName',
|
||||||
|
sourceKey: 'id',
|
||||||
|
targetKey: 'name',
|
||||||
|
through: 'rolesUsers',
|
||||||
|
uiSchema: {
|
||||||
|
type: 'array',
|
||||||
|
title: '{{t("Roles")}}',
|
||||||
|
'x-component': 'RecordPicker',
|
||||||
|
'x-component-props': {
|
||||||
|
multiple: true,
|
||||||
|
fieldNames: {
|
||||||
|
label: 'title',
|
||||||
|
value: 'name',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
35
packages/plugins/acl/src/middlewares/setCurrentRole.ts
Normal file
35
packages/plugins/acl/src/middlewares/setCurrentRole.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
export async function setCurrentRole(ctx, next) {
|
||||||
|
if (!ctx.state.currentUser) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentRole = ctx.get('X-Role');
|
||||||
|
|
||||||
|
if (currentRole === 'anonymous') {
|
||||||
|
ctx.state.currentRole = currentRole;
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const RolesUsers = ctx.db.getCollection('rolesUsers').model;
|
||||||
|
const userRoles = await RolesUsers.findAll({
|
||||||
|
where: {
|
||||||
|
userId: ctx.state.currentUser.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (userRoles.length == 1) {
|
||||||
|
currentRole = userRoles[0].roleName;
|
||||||
|
} else if (userRoles.length > 1) {
|
||||||
|
const role = userRoles.find((item) => item.roleName === currentRole);
|
||||||
|
if (!role) {
|
||||||
|
const defaultRole = userRoles.find((item) => item.default);
|
||||||
|
currentRole = (defaultRole || userRoles[0])?.roleName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRole) {
|
||||||
|
ctx.state.currentRole = currentRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
}
|
@ -1,10 +1,13 @@
|
|||||||
import { Context } from '@nocobase/actions';
|
import { Context } from '@nocobase/actions';
|
||||||
import { Collection } from '@nocobase/database';
|
import { Collection } from '@nocobase/database';
|
||||||
|
import UsersPlugin from '@nocobase/plugin-users';
|
||||||
import { Plugin } from '@nocobase/server';
|
import { Plugin } from '@nocobase/server';
|
||||||
import { resolve } from 'path';
|
import { resolve } from 'path';
|
||||||
import { availableActionResource } from './actions/available-actions';
|
import { availableActionResource } from './actions/available-actions';
|
||||||
import { checkAction } from './actions/role-check';
|
import { checkAction } from './actions/role-check';
|
||||||
import { roleCollectionsResource } from './actions/role-collections';
|
import { roleCollectionsResource } from './actions/role-collections';
|
||||||
|
import { setDefaultRole } from './actions/user-setDefaultRole';
|
||||||
|
import { setCurrentRole } from './middlewares/setCurrentRole';
|
||||||
import { RoleModel } from './model/RoleModel';
|
import { RoleModel } from './model/RoleModel';
|
||||||
import { RoleResourceActionModel } from './model/RoleResourceActionModel';
|
import { RoleResourceActionModel } from './model/RoleResourceActionModel';
|
||||||
import { RoleResourceModel } from './model/RoleResourceModel';
|
import { RoleResourceModel } from './model/RoleResourceModel';
|
||||||
@ -134,6 +137,22 @@ export class PluginACL extends Plugin {
|
|||||||
|
|
||||||
this.app.resourcer.registerActionHandler('roles:check', checkAction);
|
this.app.resourcer.registerActionHandler('roles:check', checkAction);
|
||||||
|
|
||||||
|
this.app.resourcer.registerActionHandler(`users:setDefaultRole`, setDefaultRole);
|
||||||
|
|
||||||
|
this.db.on('users.afterCreateWithAssociations', async (model, options) => {
|
||||||
|
const { transaction } = options;
|
||||||
|
const repository = this.app.db.getRepository('roles');
|
||||||
|
const defaultRole = await repository.findOne({
|
||||||
|
filter: {
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
if (defaultRole && (await model.countRoles({ transaction })) == 0) {
|
||||||
|
await model.addRoles(defaultRole, { transaction });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.app.db.on('roles.afterSaveWithAssociations', async (model, options) => {
|
this.app.db.on('roles.afterSaveWithAssociations', async (model, options) => {
|
||||||
const { transaction } = options;
|
const { transaction } = options;
|
||||||
|
|
||||||
@ -271,7 +290,7 @@ export class PluginACL extends Plugin {
|
|||||||
title: '{{t("Admin")}}',
|
title: '{{t("Admin")}}',
|
||||||
allowConfigure: true,
|
allowConfigure: true,
|
||||||
allowNewMenu: true,
|
allowNewMenu: true,
|
||||||
strategy: { actions: ['create', 'export', 'view', 'update', 'destroy'] },
|
strategy: { actions: ['create', 'view', 'update', 'destroy'] },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'member',
|
name: 'member',
|
||||||
@ -301,6 +320,11 @@ export class PluginACL extends Plugin {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const usersPlugin = this.app.pm.get('@nocobase/plugin-users') as UsersPlugin;
|
||||||
|
usersPlugin.tokenMiddleware.use(setCurrentRole);
|
||||||
|
|
||||||
|
this.app.acl.allow('users', 'setDefaultRole', 'loggedIn');
|
||||||
|
|
||||||
this.app.acl.allow('roles', 'check', 'loggedIn');
|
this.app.acl.allow('roles', 'check', 'loggedIn');
|
||||||
this.app.acl.allow('roles', ['create', 'update', 'destroy'], 'allowConfigure');
|
this.app.acl.allow('roles', ['create', 'update', 'destroy'], 'allowConfigure');
|
||||||
|
|
||||||
@ -392,6 +416,24 @@ export class PluginACL extends Plugin {
|
|||||||
if (repo) {
|
if (repo) {
|
||||||
await repo.db2cm('roles');
|
await repo.db2cm('roles');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const User = this.db.getCollection('users');
|
||||||
|
await User.repository.update({
|
||||||
|
values: {
|
||||||
|
roles: ['root', 'admin', 'member']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const RolesUsers = this.db.getCollection('rolesUsers');
|
||||||
|
await RolesUsers.repository.update({
|
||||||
|
filter: {
|
||||||
|
userId: 1,
|
||||||
|
roleName: 'root'
|
||||||
|
},
|
||||||
|
values: {
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { BelongsToManyRepository, Database } from '@nocobase/database';
|
import { BelongsToManyRepository, Database } from '@nocobase/database';
|
||||||
|
import PluginUsers from '@nocobase/plugin-users';
|
||||||
import PluginACL from '@nocobase/plugin-acl';
|
import PluginACL from '@nocobase/plugin-acl';
|
||||||
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
|
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
|
||||||
import UiSchemaStoragePlugin, { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
import UiSchemaStoragePlugin, { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
||||||
@ -24,6 +25,7 @@ describe('server hooks', () => {
|
|||||||
|
|
||||||
app.plugin(UiSchemaStoragePlugin);
|
app.plugin(UiSchemaStoragePlugin);
|
||||||
app.plugin(PluginCollectionManager);
|
app.plugin(PluginCollectionManager);
|
||||||
|
app.plugin(PluginUsers);
|
||||||
app.plugin(PluginACL);
|
app.plugin(PluginACL);
|
||||||
|
|
||||||
await app.loadAndInstall();
|
await app.loadAndInstall();
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
import Database from '@nocobase/database';
|
|
||||||
import PluginACL from '@nocobase/plugin-acl';
|
|
||||||
import UsersPlugin from '@nocobase/plugin-users';
|
|
||||||
import { MockServer, mockServer } from '@nocobase/test';
|
|
||||||
import { setCurrentRole } from '../middlewares/parseToken';
|
|
||||||
import { userPluginConfig } from './utils';
|
|
||||||
|
|
||||||
describe('role', () => {
|
|
||||||
let api: MockServer;
|
|
||||||
let db: Database;
|
|
||||||
|
|
||||||
let usersPlugin: UsersPlugin;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
api = mockServer();
|
|
||||||
await api.cleanDb();
|
|
||||||
api.plugin(UsersPlugin, userPluginConfig);
|
|
||||||
api.plugin(PluginACL);
|
|
||||||
await api.loadAndInstall();
|
|
||||||
|
|
||||||
db = api.db;
|
|
||||||
usersPlugin = api.getPlugin('@nocobase/plugin-users');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
await api.destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set role with X-Role when exists', async () => {
|
|
||||||
const currentUser = await db.getRepository('users').findOne({
|
|
||||||
appends: ['roles'],
|
|
||||||
});
|
|
||||||
const ctx = {
|
|
||||||
get(name) {
|
|
||||||
if (name === 'X-Role') {
|
|
||||||
return 'admin';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
currentUser,
|
|
||||||
currentRole: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCurrentRole(ctx);
|
|
||||||
expect(ctx.state.currentRole).toBe('admin');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set role with default', async () => {
|
|
||||||
const currentUser = await db.getRepository('users').findOne({
|
|
||||||
appends: ['roles'],
|
|
||||||
});
|
|
||||||
const ctx = {
|
|
||||||
get(name) {
|
|
||||||
if (name === 'X-Role') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
currentUser,
|
|
||||||
currentRole: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCurrentRole(ctx);
|
|
||||||
expect(ctx.state.currentRole).toBe('root');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set role with default when x-role does not exist', async () => {
|
|
||||||
const currentUser = await db.getRepository('users').findOne({
|
|
||||||
appends: ['roles'],
|
|
||||||
});
|
|
||||||
const ctx = {
|
|
||||||
get(name) {
|
|
||||||
if (name === 'X-Role') {
|
|
||||||
return 'abc';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
currentUser,
|
|
||||||
currentRole: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCurrentRole(ctx);
|
|
||||||
expect(ctx.state.currentRole).toBe('root');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set role with anonymous', async () => {
|
|
||||||
const currentUser = await db.getRepository('users').findOne({
|
|
||||||
appends: ['roles'],
|
|
||||||
});
|
|
||||||
const ctx = {
|
|
||||||
get(name) {
|
|
||||||
if (name === 'X-Role') {
|
|
||||||
return 'anonymous';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
currentUser,
|
|
||||||
currentRole: '',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCurrentRole(ctx);
|
|
||||||
expect(ctx.state.currentRole).toBe('anonymous');
|
|
||||||
});
|
|
||||||
});
|
|
@ -150,15 +150,3 @@ export async function changePassword(ctx: Context, next: Next) {
|
|||||||
ctx.body = ctx.state.currentUser.toJSON();
|
ctx.body = ctx.state.currentUser.toJSON();
|
||||||
await next();
|
await next();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setDefaultRole(ctx: Context, next: Next) {
|
|
||||||
const {
|
|
||||||
values: { roleName },
|
|
||||||
} = ctx.action.params;
|
|
||||||
|
|
||||||
await ctx.state.currentUser.setDefaultRole(roleName);
|
|
||||||
|
|
||||||
ctx.body = 'ok';
|
|
||||||
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
|
@ -51,29 +51,6 @@ export default {
|
|||||||
'x-component': 'Password',
|
'x-component': 'Password',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
interface: 'm2m',
|
|
||||||
type: 'belongsToMany',
|
|
||||||
name: 'roles',
|
|
||||||
target: 'roles',
|
|
||||||
foreignKey: 'userId',
|
|
||||||
otherKey: 'roleName',
|
|
||||||
sourceKey: 'id',
|
|
||||||
targetKey: 'name',
|
|
||||||
through: 'rolesUsers',
|
|
||||||
uiSchema: {
|
|
||||||
type: 'array',
|
|
||||||
title: '{{t("Roles")}}',
|
|
||||||
'x-component': 'RecordPicker',
|
|
||||||
'x-component-props': {
|
|
||||||
multiple: true,
|
|
||||||
fieldNames: {
|
|
||||||
label: 'title',
|
|
||||||
value: 'name',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: 'string',
|
type: 'string',
|
||||||
name: 'appLang',
|
name: 'appLang',
|
||||||
|
@ -1,40 +1,17 @@
|
|||||||
import { Context, Next } from '@nocobase/actions';
|
import { Context, Next } from '@nocobase/actions';
|
||||||
|
import { MiddlewareManager } from '@nocobase/resourcer';
|
||||||
import UsersPlugin from '../server';
|
import UsersPlugin from '../server';
|
||||||
|
|
||||||
export function parseToken(options?: { plugin: UsersPlugin }) {
|
export function parseToken(options?: { plugin: UsersPlugin }) {
|
||||||
return async function parseToken(ctx: Context, next: Next) {
|
const middleware = new MiddlewareManager();
|
||||||
|
middleware.use(async function (ctx: Context, next: Next) {
|
||||||
const user = await findUserByToken(ctx, options.plugin);
|
const user = await findUserByToken(ctx, options.plugin);
|
||||||
if (user) {
|
if (user) {
|
||||||
ctx.state.currentUser = user;
|
ctx.state.currentUser = user;
|
||||||
setCurrentRole(ctx);
|
|
||||||
}
|
}
|
||||||
return next();
|
return next();
|
||||||
};
|
});
|
||||||
}
|
return middleware;
|
||||||
|
|
||||||
export function setCurrentRole(ctx) {
|
|
||||||
let currentRole = ctx.get('X-Role');
|
|
||||||
|
|
||||||
if (currentRole === 'anonymous') {
|
|
||||||
ctx.state.currentRole = currentRole;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userRoles = ctx.state.currentUser.roles;
|
|
||||||
|
|
||||||
if (userRoles.length == 1) {
|
|
||||||
currentRole = userRoles[0].name;
|
|
||||||
} else if (userRoles.length > 1) {
|
|
||||||
const role = userRoles.find((role) => role.name === currentRole);
|
|
||||||
if (!role) {
|
|
||||||
const defaultRole = userRoles.find((role) => role?.rolesUsers?.default);
|
|
||||||
currentRole = (defaultRole || userRoles[0])?.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentRole) {
|
|
||||||
ctx.state.currentRole = currentRole;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findUserByToken(ctx: Context, plugin: UsersPlugin) {
|
async function findUserByToken(ctx: Context, plugin: UsersPlugin) {
|
||||||
@ -46,7 +23,7 @@ async function findUserByToken(ctx: Context, plugin: UsersPlugin) {
|
|||||||
try {
|
try {
|
||||||
const { userId } = await plugin.jwtService.decode(token);
|
const { userId } = await plugin.jwtService.decode(token);
|
||||||
const collection = ctx.db.getCollection('users');
|
const collection = ctx.db.getCollection('users');
|
||||||
const appends = ['roles'];
|
const appends = [];
|
||||||
for (const [, field] of collection.fields) {
|
for (const [, field] of collection.fields) {
|
||||||
if (field.type === 'belongsTo') {
|
if (field.type === 'belongsTo') {
|
||||||
appends.push(field.name);
|
appends.push(field.name);
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
import Database, { Model, Transactionable } from '@nocobase/database';
|
|
||||||
|
|
||||||
export class UserModel extends Model {
|
|
||||||
async setDefaultRole(roleName: string, options: Transactionable = {}) {
|
|
||||||
if (roleName == 'anonymous') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const db = (this.constructor as any).database as Database;
|
|
||||||
const repository = db.getRepository('rolesUsers');
|
|
||||||
if (!repository) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const transaction = options.transaction || (await db.sequelize.transaction());
|
|
||||||
|
|
||||||
try {
|
|
||||||
await repository.update({
|
|
||||||
filter: {
|
|
||||||
userId: this.get('id'),
|
|
||||||
},
|
|
||||||
values: {
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
await repository.update({
|
|
||||||
filter: {
|
|
||||||
userId: this.get('id'),
|
|
||||||
roleName,
|
|
||||||
},
|
|
||||||
values: {
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,6 @@ import * as actions from './actions/users';
|
|||||||
import { JwtOptions, JwtService } from './jwt-service';
|
import { JwtOptions, JwtService } from './jwt-service';
|
||||||
import { enUS, zhCN } from './locale';
|
import { enUS, zhCN } from './locale';
|
||||||
import * as middlewares from './middlewares';
|
import * as middlewares from './middlewares';
|
||||||
import { UserModel } from './models/UserModel';
|
|
||||||
|
|
||||||
export interface UserPluginConfig {
|
export interface UserPluginConfig {
|
||||||
jwt: JwtOptions;
|
jwt: JwtOptions;
|
||||||
@ -16,9 +15,12 @@ export interface UserPluginConfig {
|
|||||||
export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
||||||
public jwtService: JwtService;
|
public jwtService: JwtService;
|
||||||
|
|
||||||
|
public tokenMiddleware;
|
||||||
|
|
||||||
constructor(app, options) {
|
constructor(app, options) {
|
||||||
super(app, options);
|
super(app, options);
|
||||||
this.jwtService = new JwtService(options?.jwt || {});
|
this.jwtService = new JwtService(options?.jwt || {});
|
||||||
|
this.tokenMiddleware = middlewares.parseToken({ plugin: this });
|
||||||
}
|
}
|
||||||
|
|
||||||
async beforeLoad() {
|
async beforeLoad() {
|
||||||
@ -43,23 +45,6 @@ export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.db.registerModels({ UserModel });
|
|
||||||
this.db.on('users.afterCreateWithAssociations', async (model, options) => {
|
|
||||||
const { transaction } = options;
|
|
||||||
const repository = this.app.db.getRepository('roles');
|
|
||||||
if (!repository) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const defaultRole = await repository.findOne({
|
|
||||||
filter: {
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
if (defaultRole && (await model.countRoles({ transaction })) == 0) {
|
|
||||||
await model.addRoles(defaultRole, { transaction });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.db.on('afterDefineCollection', (collection: Collection) => {
|
this.db.on('afterDefineCollection', (collection: Collection) => {
|
||||||
let { createdBy, updatedBy } = collection.options;
|
let { createdBy, updatedBy } = collection.options;
|
||||||
@ -100,10 +85,10 @@ export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
|||||||
this.app.resourcer.registerActionHandler(`users:${key}`, action);
|
this.app.resourcer.registerActionHandler(`users:${key}`, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.app.resourcer.use(middlewares.parseToken({ plugin: this }));
|
this.app.resourcer.use(this.tokenMiddleware.compose());
|
||||||
|
|
||||||
const publicActions = ['check', 'signin', 'signup', 'lostpassword', 'resetpassword', 'getUserByResetToken'];
|
const publicActions = ['check', 'signin', 'signup', 'lostpassword', 'resetpassword', 'getUserByResetToken'];
|
||||||
const loggedInActions = ['signout', 'updateProfile', 'changePassword', 'setDefaultRole'];
|
const loggedInActions = ['signout', 'updateProfile', 'changePassword'];
|
||||||
|
|
||||||
publicActions.forEach((action) => this.app.acl.allow('users', action));
|
publicActions.forEach((action) => this.app.acl.allow('users', action));
|
||||||
loggedInActions.forEach((action) => this.app.acl.allow('users', action, 'loggedIn'));
|
loggedInActions.forEach((action) => this.app.acl.allow('users', action, 'loggedIn'));
|
||||||
@ -132,17 +117,14 @@ export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
|||||||
async install(options) {
|
async install(options) {
|
||||||
const { rootNickname, rootPassword, rootEmail } = this.getInstallingData(options);
|
const { rootNickname, rootPassword, rootEmail } = this.getInstallingData(options);
|
||||||
const User = this.db.getCollection('users');
|
const User = this.db.getCollection('users');
|
||||||
const user = await User.repository.create<UserModel>({
|
const user = await User.repository.create({
|
||||||
values: {
|
values: {
|
||||||
email: rootEmail,
|
email: rootEmail,
|
||||||
password: rootPassword,
|
password: rootPassword,
|
||||||
nickname: rootNickname,
|
nickname: rootNickname
|
||||||
roles: ['root', 'admin', 'member'],
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await user.setDefaultRole('root');
|
|
||||||
|
|
||||||
const repo = this.db.getRepository<any>('collections');
|
const repo = this.db.getRepository<any>('collections');
|
||||||
if (repo) {
|
if (repo) {
|
||||||
await repo.db2cm('users');
|
await repo.db2cm('users');
|
||||||
|
Loading…
Reference in New Issue
Block a user