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({
|
||||
name: roleName,
|
||||
filter: {
|
||||
name: roleName
|
||||
},
|
||||
});
|
||||
|
||||
return roleInstance?.get('allowConfigure');
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { ActionName } from './action';
|
||||
import { requireModule } from './utils';
|
||||
import { HandlerType } from './resourcer';
|
||||
import compose from 'koa-compose';
|
||||
|
||||
export type MiddlewareType = string | string[] | HandlerType | HandlerType[] | MiddlewareOptions | MiddlewareOptions[];
|
||||
|
||||
@ -73,3 +74,19 @@ export class 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": {
|
||||
"@nocobase/acl": "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"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { ACL } from '@nocobase/acl';
|
||||
import { Database } from '@nocobase/database';
|
||||
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 { prepareApp } from './prepare';
|
||||
|
||||
describe('acl', () => {
|
||||
let app: MockServer;
|
||||
let db: Database;
|
||||
let acl: ACL;
|
||||
let admin;
|
||||
let adminAgent;
|
||||
|
||||
let uiSchemaRepository: UiSchemaRepository;
|
||||
|
||||
@ -20,38 +23,41 @@ describe('acl', () => {
|
||||
db = app.db;
|
||||
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');
|
||||
});
|
||||
|
||||
it('should works with universal actions', async () => {
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
},
|
||||
});
|
||||
|
||||
const role = await db.getRepository('roles').findOne({
|
||||
filter: {
|
||||
name: 'admin',
|
||||
name: 'new'
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
// grant universal action
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles')
|
||||
.update({
|
||||
resourceIndex: 'admin',
|
||||
resourceIndex: 'new',
|
||||
values: {
|
||||
strategy: {
|
||||
actions: ['create'],
|
||||
@ -61,31 +67,27 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
});
|
||||
});
|
||||
|
||||
it('should deny when resource action has no resource', async () => {
|
||||
const role = await db.getRepository('roles').create({
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
name: 'new',
|
||||
strategy: {
|
||||
actions: ['update:own', 'destroy:own', 'create', 'view'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
changeMockRole('admin');
|
||||
|
||||
// create c1 collection
|
||||
await db.getRepository('collections').create({
|
||||
values: {
|
||||
@ -102,9 +104,8 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
.resource('roles.resources', 'admin')
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.create({
|
||||
values: {
|
||||
name: 'c1',
|
||||
@ -115,7 +116,7 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'c1',
|
||||
action: 'list',
|
||||
}),
|
||||
@ -125,17 +126,13 @@ describe('acl', () => {
|
||||
it('should works with resources actions', async () => {
|
||||
const role = await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
name: 'new',
|
||||
strategy: {
|
||||
actions: ['list'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
changeMockRole('admin');
|
||||
|
||||
// create c1 collection
|
||||
await db.getRepository('collections').create({
|
||||
values: {
|
||||
@ -153,8 +150,7 @@ describe('acl', () => {
|
||||
});
|
||||
|
||||
// create c1 published scope
|
||||
await app
|
||||
.agent()
|
||||
const { body: { data: publishedScope } } = await adminAgent
|
||||
.resource('rolesResourcesScopes')
|
||||
.create({
|
||||
values: {
|
||||
@ -166,12 +162,11 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const publishedScope = await db.getRepository('rolesResourcesScopes').findOne();
|
||||
// await db.getRepository('rolesResourcesScopes').findOne();
|
||||
|
||||
// set admin resources
|
||||
await app
|
||||
.agent()
|
||||
.resource('roles.resources', 'admin')
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.create({
|
||||
values: {
|
||||
name: 'c1',
|
||||
@ -179,7 +174,7 @@ describe('acl', () => {
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
scope: publishedScope.get('id'),
|
||||
scope: publishedScope.id,
|
||||
},
|
||||
{
|
||||
name: 'view',
|
||||
@ -191,12 +186,12 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'c1',
|
||||
action: 'create',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'c1',
|
||||
action: 'create',
|
||||
params: {
|
||||
@ -206,12 +201,12 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'c1',
|
||||
action: 'view',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'c1',
|
||||
action: 'view',
|
||||
params: {
|
||||
@ -220,8 +215,7 @@ describe('acl', () => {
|
||||
});
|
||||
|
||||
// revoke action
|
||||
const response = await app
|
||||
.agent()
|
||||
const response = await adminAgent
|
||||
.resource('roles.resources', role.get('name'))
|
||||
.list({
|
||||
appends: ['actions'],
|
||||
@ -232,8 +226,7 @@ describe('acl', () => {
|
||||
const actions = response.body.data[0].actions;
|
||||
const collectionName = response.body.data[0].name;
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles.resources', role.get('name'))
|
||||
.update({
|
||||
filterByTk: collectionName,
|
||||
@ -251,7 +244,7 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'c1',
|
||||
action: 'create',
|
||||
}),
|
||||
@ -259,11 +252,9 @@ describe('acl', () => {
|
||||
});
|
||||
|
||||
it('should revoke resource when collection destroy', async () => {
|
||||
const role = await db.getRepository('roles').create({
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
name: 'new'
|
||||
},
|
||||
});
|
||||
|
||||
@ -281,11 +272,10 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles.resources')
|
||||
.create({
|
||||
associatedIndex: role.get('name') as string,
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
@ -300,7 +290,7 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'view',
|
||||
}),
|
||||
@ -314,7 +304,7 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'view',
|
||||
}),
|
||||
@ -324,15 +314,7 @@ describe('acl', () => {
|
||||
it('should revoke actions when not using actions config', async () => {
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
},
|
||||
});
|
||||
|
||||
const role = await db.getRepository('roles').findOne({
|
||||
filter: {
|
||||
name: 'admin',
|
||||
name: 'new'
|
||||
},
|
||||
});
|
||||
|
||||
@ -343,11 +325,10 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles.resources')
|
||||
.create({
|
||||
associatedIndex: role.get('name') as string,
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
@ -361,25 +342,24 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
.resource('roles.resources', role.get('name'))
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.update({
|
||||
filterByTk: (
|
||||
await db.getRepository('rolesResources').findOne({
|
||||
filter: {
|
||||
name: 'posts',
|
||||
roleName: 'admin',
|
||||
roleName: 'new',
|
||||
},
|
||||
})
|
||||
).get('name') as string,
|
||||
@ -390,21 +370,20 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
}),
|
||||
).toBeNull();
|
||||
|
||||
await app
|
||||
.agent()
|
||||
.resource('roles.resources', role.get('name'))
|
||||
await adminAgent
|
||||
.resource('roles.resources', 'new')
|
||||
.update({
|
||||
filterByTk: (
|
||||
await db.getRepository('rolesResources').findOne({
|
||||
filter: {
|
||||
name: 'posts',
|
||||
roleName: 'admin',
|
||||
roleName: 'new',
|
||||
},
|
||||
})
|
||||
).get('name') as string,
|
||||
@ -415,23 +394,21 @@ describe('acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'create',
|
||||
});
|
||||
});
|
||||
|
||||
it('should add fields when field created', async () => {
|
||||
const role = await db.getRepository('roles').create({
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
name: 'new'
|
||||
},
|
||||
});
|
||||
|
||||
@ -449,11 +426,10 @@ describe('acl', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles.resources')
|
||||
.create({
|
||||
associatedIndex: role.get('name') as string,
|
||||
associatedIndex: 'new',
|
||||
values: {
|
||||
name: 'posts',
|
||||
usingActionsConfig: true,
|
||||
@ -467,7 +443,7 @@ describe('acl', () => {
|
||||
});
|
||||
|
||||
const allowFields = acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'view',
|
||||
})['params']['fields'];
|
||||
@ -483,7 +459,7 @@ describe('acl', () => {
|
||||
});
|
||||
|
||||
const newAllowFields = acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'view',
|
||||
})['params']['fields'];
|
||||
@ -494,18 +470,14 @@ describe('acl', () => {
|
||||
it('should get role menus', async () => {
|
||||
const role = await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
name: 'new',
|
||||
strategy: {
|
||||
actions: ['view'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
changeMockRole('admin');
|
||||
|
||||
const menuResponse = await app.agent().resource('roles.menuUiSchemas', 'admin').list();
|
||||
const menuResponse = await adminAgent.resource('roles.menuUiSchemas', 'new').list();
|
||||
|
||||
expect(menuResponse.statusCode).toEqual(200);
|
||||
});
|
||||
@ -513,16 +485,23 @@ describe('acl', () => {
|
||||
it('should toggle role menus', async () => {
|
||||
const role = await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
name: 'new',
|
||||
strategy: {
|
||||
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 = {
|
||||
'x-uid': 'test',
|
||||
@ -530,9 +509,9 @@ describe('acl', () => {
|
||||
|
||||
await uiSchemaRepository.insert(schema);
|
||||
|
||||
const response = await app
|
||||
.agent()
|
||||
.resource('roles.menuUiSchemas', 'admin')
|
||||
const response = await userAgent
|
||||
// @ts-ignore
|
||||
.resource('roles.menuUiSchemas', 'new')
|
||||
.toggle({
|
||||
values: { tk: 'test' },
|
||||
});
|
||||
@ -543,9 +522,7 @@ describe('acl', () => {
|
||||
it('should sync data to acl before app start', async () => {
|
||||
const role = await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
name: 'new',
|
||||
resources: [
|
||||
{
|
||||
name: 'posts',
|
||||
@ -562,20 +539,20 @@ describe('acl', () => {
|
||||
hooks: false,
|
||||
});
|
||||
|
||||
expect(acl.getRole('admin')).toBeUndefined();
|
||||
expect(acl.getRole('new')).toBeUndefined();
|
||||
|
||||
await app.start();
|
||||
|
||||
expect(acl.getRole('admin')).toBeDefined();
|
||||
expect(acl.getRole('new')).toBeDefined();
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'view',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'posts',
|
||||
action: 'view',
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
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 { prepareApp } from './prepare';
|
||||
|
||||
@ -8,7 +9,10 @@ describe('association field acl', () => {
|
||||
let db: Database;
|
||||
let acl: ACL;
|
||||
|
||||
let role: Model;
|
||||
let user;
|
||||
let userAgent;
|
||||
let admin;
|
||||
let adminAgent;
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
@ -19,20 +23,44 @@ describe('association field acl', () => {
|
||||
db = app.db;
|
||||
acl = app.acl;
|
||||
|
||||
role = await db.getRepository('roles').create({
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
name: 'new',
|
||||
allowConfigure: true,
|
||||
},
|
||||
});
|
||||
|
||||
await db.getRepository('collections').create({
|
||||
await db.getRepository('roles').create({
|
||||
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({
|
||||
values: {
|
||||
@ -75,56 +103,48 @@ describe('association field acl', () => {
|
||||
context: {},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
.resource('roles.resources')
|
||||
.create({
|
||||
associatedIndex: 'admin',
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
fields: ['orders'],
|
||||
},
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['orders'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', 'new').create({
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
fields: ['orders'],
|
||||
},
|
||||
{
|
||||
name: 'view',
|
||||
fields: ['orders'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should revoke target action on association action revoke', async () => {
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'orders',
|
||||
action: 'list',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'orders',
|
||||
action: 'list',
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
.resource('roles.resources')
|
||||
.update({
|
||||
associatedIndex: 'admin',
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', 'new').update({
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [],
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'orders',
|
||||
action: 'list',
|
||||
}),
|
||||
@ -134,12 +154,12 @@ describe('association field acl', () => {
|
||||
it('should revoke association action on action revoke', async () => {
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users.orders',
|
||||
action: 'add',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users.orders',
|
||||
action: 'add',
|
||||
});
|
||||
@ -152,27 +172,23 @@ describe('association field acl', () => {
|
||||
|
||||
const actionId = viewAction.get('id') as number;
|
||||
|
||||
const response = await app
|
||||
.agent()
|
||||
.resource('roles.resources')
|
||||
.update({
|
||||
associatedIndex: 'admin',
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
id: actionId,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const response = await adminAgent.resource('roles.resources', 'new').update({
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
id: actionId,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users.orders',
|
||||
action: 'add',
|
||||
}),
|
||||
@ -180,30 +196,26 @@ describe('association field acl', () => {
|
||||
});
|
||||
|
||||
it('should revoke association action on field deleted', async () => {
|
||||
await app
|
||||
.agent()
|
||||
.resource('roles.resources')
|
||||
.update({
|
||||
associatedIndex: 'admin',
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
fields: ['name', 'age'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
await adminAgent.resource('roles.resources', 'new').update({
|
||||
values: {
|
||||
name: 'users',
|
||||
usingActionsConfig: true,
|
||||
actions: [
|
||||
{
|
||||
name: 'create',
|
||||
fields: ['name', 'age'],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users',
|
||||
action: 'create',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users',
|
||||
action: 'create',
|
||||
params: {
|
||||
@ -236,12 +248,12 @@ describe('association field acl', () => {
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users',
|
||||
action: 'create',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users',
|
||||
action: 'create',
|
||||
params: {
|
||||
@ -251,45 +263,44 @@ describe('association field acl', () => {
|
||||
});
|
||||
|
||||
it('should allow association fields access', async () => {
|
||||
const createResponse = await app
|
||||
.agent()
|
||||
.resource('users')
|
||||
.create({
|
||||
values: {
|
||||
orders: [
|
||||
{
|
||||
content: 'apple',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
const createResponse = await userAgent.resource('users').create({
|
||||
values: {
|
||||
orders: [
|
||||
{
|
||||
content: 'apple',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
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
|
||||
expect(await user.countOrders()).toEqual(1);
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users.orders',
|
||||
action: 'list',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'users.orders',
|
||||
action: 'list',
|
||||
});
|
||||
|
||||
expect(
|
||||
acl.can({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'orders',
|
||||
action: 'list',
|
||||
}),
|
||||
).toMatchObject({
|
||||
role: 'admin',
|
||||
role: 'new',
|
||||
resource: 'orders',
|
||||
action: 'list',
|
||||
});
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { Database } from '@nocobase/database';
|
||||
import { ACL } from '@nocobase/acl';
|
||||
import { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
||||
import { changeMockRole, prepareApp } from './prepare';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { prepareApp } from './prepare';
|
||||
|
||||
describe('configuration', () => {
|
||||
let app: MockServer;
|
||||
let db: Database;
|
||||
let acl: ACL;
|
||||
|
||||
let uiSchemaRepository: UiSchemaRepository;
|
||||
let admin;
|
||||
let adminAgent;
|
||||
let user;
|
||||
let userAgent;
|
||||
let guestAgent;
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
@ -18,28 +19,56 @@ describe('configuration', () => {
|
||||
beforeEach(async () => {
|
||||
app = await prepareApp();
|
||||
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({
|
||||
values: {
|
||||
name: 'admin1',
|
||||
title: 'admin allowConfigure',
|
||||
name: 'test1',
|
||||
allowConfigure: true,
|
||||
},
|
||||
});
|
||||
|
||||
changeMockRole('admin1');
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'test2',
|
||||
},
|
||||
});
|
||||
|
||||
expect((await app.agent().resource('collections').create()).statusCode).toEqual(200);
|
||||
expect((await app.agent().resource('collections').list()).statusCode).toEqual(200);
|
||||
const UserRepo = db.getCollection('users').repository;
|
||||
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 { Database, Model } from '@nocobase/database';
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { changeMockUser, prepareApp } from './prepare';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
import { prepareApp } from './prepare';
|
||||
|
||||
describe('middleware', () => {
|
||||
let app: MockServer;
|
||||
let role: Model;
|
||||
let db: Database;
|
||||
let acl: ACL;
|
||||
let admin;
|
||||
let adminAgent;
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await prepareApp();
|
||||
db = app.db;
|
||||
acl = app.acl;
|
||||
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
},
|
||||
});
|
||||
|
||||
role = await db.getRepository('roles').findOne({
|
||||
filter: {
|
||||
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({
|
||||
values: {
|
||||
name: 'posts',
|
||||
@ -82,7 +89,7 @@ describe('middleware', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const response = await app.agent().resource('posts').create({
|
||||
const response = await adminAgent.resource('posts').create({
|
||||
values: {},
|
||||
});
|
||||
|
||||
@ -90,8 +97,7 @@ describe('middleware', () => {
|
||||
});
|
||||
|
||||
it('should limit fields on view actions', async () => {
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles.resources', role.get('name'))
|
||||
.create({
|
||||
values: {
|
||||
@ -110,8 +116,7 @@ describe('middleware', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('posts')
|
||||
.create({
|
||||
values: {
|
||||
@ -124,10 +129,10 @@ describe('middleware', () => {
|
||||
expect(post.get('title')).toEqual('post-title');
|
||||
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);
|
||||
|
||||
const data = response.body.data[0];
|
||||
const [data] = response.body.data;
|
||||
|
||||
expect(data['id']).not.toBeUndefined();
|
||||
expect(data['title']).toEqual('post-title');
|
||||
@ -135,12 +140,7 @@ describe('middleware', () => {
|
||||
});
|
||||
|
||||
it('should parse template value on action params', async () => {
|
||||
changeMockUser({
|
||||
id: 2,
|
||||
});
|
||||
|
||||
const res = await app
|
||||
.agent()
|
||||
const res = await adminAgent
|
||||
.resource('rolesResourcesScopes')
|
||||
.create({
|
||||
values: {
|
||||
@ -151,8 +151,7 @@ describe('middleware', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles.resources', role.get('name'))
|
||||
.create({
|
||||
values: {
|
||||
@ -172,8 +171,7 @@ describe('middleware', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('posts')
|
||||
.create({
|
||||
values: {
|
||||
@ -183,8 +181,7 @@ describe('middleware', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('posts')
|
||||
.create({
|
||||
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;
|
||||
expect(data.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should change fields params to whitelist in create action', async () => {
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('roles.resources', role.get('name'))
|
||||
.create({
|
||||
values: {
|
||||
@ -216,8 +212,7 @@ describe('middleware', () => {
|
||||
},
|
||||
});
|
||||
|
||||
await app
|
||||
.agent()
|
||||
await adminAgent
|
||||
.resource('posts')
|
||||
.create({
|
||||
values: {
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { ACL } from '@nocobase/acl';
|
||||
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 { mockServer, MockServer } from '@nocobase/test';
|
||||
import supertest from 'supertest';
|
||||
import { MockServer } from '@nocobase/test';
|
||||
|
||||
import { prepareApp } from './prepare';
|
||||
|
||||
describe('own test', () => {
|
||||
let app: MockServer;
|
||||
@ -21,28 +19,15 @@ describe('own test', () => {
|
||||
|
||||
let role;
|
||||
let agent;
|
||||
let adminAgent;
|
||||
let userAgent;
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
app = mockServer({
|
||||
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();
|
||||
app = await prepareApp();
|
||||
db = app.db;
|
||||
|
||||
const PostCollection = db.collection({
|
||||
@ -68,9 +53,9 @@ describe('own test', () => {
|
||||
fields: [{ type: 'string', name: 'name' }],
|
||||
});
|
||||
|
||||
await app.db.sync();
|
||||
await db.sync();
|
||||
|
||||
agent = supertest.agent(app.callback());
|
||||
agent = app.agent();
|
||||
|
||||
acl = app.acl;
|
||||
|
||||
@ -86,6 +71,8 @@ describe('own test', () => {
|
||||
|
||||
adminToken = pluginUser.jwtService.sign({ userId: admin.get('id') });
|
||||
|
||||
adminAgent = app.agent().auth(adminToken, { type: 'bearer' });
|
||||
|
||||
user = await db.getRepository('users').create({
|
||||
values: {
|
||||
nickname: 'test',
|
||||
@ -94,10 +81,12 @@ describe('own test', () => {
|
||||
});
|
||||
|
||||
userToken = pluginUser.jwtService.sign({ userId: user.get('id') });
|
||||
|
||||
userAgent = app.agent().auth(userToken, { type: 'bearer' });
|
||||
});
|
||||
|
||||
it('should list without createBy', async () => {
|
||||
let response = await agent
|
||||
await adminAgent
|
||||
.patch('/roles/admin')
|
||||
.send({
|
||||
strategy: {
|
||||
@ -106,33 +95,38 @@ describe('own test', () => {
|
||||
})
|
||||
.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);
|
||||
});
|
||||
|
||||
it('should delete with createdBy', async () => {
|
||||
let response = await agent
|
||||
.patch('/roles/admin')
|
||||
.send({
|
||||
strategy: {
|
||||
actions: ['view:own', 'create', 'destroy:own'],
|
||||
},
|
||||
})
|
||||
.set({ Authorization: 'Bearer ' + adminToken });
|
||||
await adminAgent
|
||||
.resource('roles')
|
||||
.update({
|
||||
filterByTk: 'admin',
|
||||
values: {
|
||||
strategy: {
|
||||
actions: ['view:own', 'create', 'destroy:own'],
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
response = await agent
|
||||
.get('/posts:create')
|
||||
.send({
|
||||
title: 't1',
|
||||
})
|
||||
.set({ Authorization: 'Bearer ' + userToken });
|
||||
let response = await userAgent
|
||||
.resource('posts')
|
||||
.create({
|
||||
values: {
|
||||
title: 't1',
|
||||
}
|
||||
});
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
const data = response.body;
|
||||
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(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 PluginUiSchema from '@nocobase/plugin-ui-schema-storage';
|
||||
import { mockServer } from '@nocobase/test';
|
||||
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() {
|
||||
const app = mockServer({
|
||||
@ -21,15 +13,10 @@ export async function prepareApp() {
|
||||
|
||||
await app.cleanDb();
|
||||
|
||||
app.plugin(PluginUsers);
|
||||
app.plugin(PluginUiSchema);
|
||||
app.plugin(PluginCollectionManager);
|
||||
|
||||
app.resourcer.use(async (ctx, next) => {
|
||||
ctx.state.currentRole = mockRole;
|
||||
ctx.state.currentUser = mockUser;
|
||||
await next();
|
||||
});
|
||||
|
||||
app.plugin(PluginACL);
|
||||
await app.loadAndInstall();
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { changeMockRole, changeMockUser, prepareApp } from './prepare';
|
||||
import { Database } from '@nocobase/database';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
|
||||
import { prepareApp } from './prepare';
|
||||
|
||||
describe('role check action', () => {
|
||||
let app: MockServer;
|
||||
@ -21,14 +23,18 @@ describe('role check action', () => {
|
||||
name: 'test',
|
||||
},
|
||||
});
|
||||
|
||||
changeMockUser({
|
||||
id: 2,
|
||||
const user = await db.getRepository('users').create({
|
||||
values: {
|
||||
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');
|
||||
|
||||
const response = await app.agent().get('/roles:check');
|
||||
// @ts-ignore
|
||||
const response = await agent.resource('roles').check();
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Database, Model } from '@nocobase/database';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { prepareApp } from './prepare';
|
||||
@ -7,6 +8,8 @@ describe('role resource api', () => {
|
||||
let app: MockServer;
|
||||
let db: Database;
|
||||
let role: Model;
|
||||
let admin;
|
||||
let adminAgent;
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
@ -16,19 +19,23 @@ describe('role resource api', () => {
|
||||
app = await prepareApp();
|
||||
db = app.db;
|
||||
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
},
|
||||
});
|
||||
|
||||
role = await db.getRepository('roles').findOne({
|
||||
filter: {
|
||||
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 () => {
|
||||
@ -91,8 +98,7 @@ describe('role resource api', () => {
|
||||
});
|
||||
|
||||
// get collections list
|
||||
let response = await app
|
||||
.agent()
|
||||
let response = await adminAgent
|
||||
.resource('roles.collections', 'admin')
|
||||
.list({
|
||||
filter: {
|
||||
@ -119,8 +125,7 @@ describe('role resource api', () => {
|
||||
]);
|
||||
|
||||
// set resource actions
|
||||
response = await app
|
||||
.agent()
|
||||
response = await adminAgent
|
||||
.resource('roles.resources', 'admin')
|
||||
.create({
|
||||
values: {
|
||||
@ -137,8 +142,7 @@ describe('role resource api', () => {
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
// get collections list
|
||||
response = await app
|
||||
.agent()
|
||||
response = await adminAgent
|
||||
.resource('roles.collections')
|
||||
.list({
|
||||
associatedIndex: role.get('name') as string,
|
||||
@ -149,8 +153,7 @@ describe('role resource api', () => {
|
||||
|
||||
expect(response.body.data[0]['usingConfig']).toEqual('resourceAction');
|
||||
|
||||
response = await app
|
||||
.agent()
|
||||
response = await adminAgent
|
||||
.resource('roles.resources')
|
||||
.list({
|
||||
associatedIndex: role.get('name') as string,
|
||||
@ -164,8 +167,7 @@ describe('role resource api', () => {
|
||||
expect(resourceAction['name']).toEqual('create');
|
||||
|
||||
// update resource actions
|
||||
response = await app
|
||||
.agent()
|
||||
response = await adminAgent
|
||||
.resource('roles.resources')
|
||||
.update({
|
||||
associatedIndex: role.get('name') as string,
|
||||
|
@ -2,7 +2,6 @@ import Database, { BelongsToManyRepository } from '@nocobase/database';
|
||||
import PluginACL from '@nocobase/plugin-acl';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
import { MockServer, mockServer } from '@nocobase/test';
|
||||
import { userPluginConfig } from './utils';
|
||||
|
||||
describe('role', () => {
|
||||
let api: MockServer;
|
||||
@ -13,7 +12,7 @@ describe('role', () => {
|
||||
beforeEach(async () => {
|
||||
api = mockServer();
|
||||
await api.cleanDb();
|
||||
api.plugin(UsersPlugin, userPluginConfig);
|
||||
api.plugin(UsersPlugin);
|
||||
api.plugin(PluginACL);
|
||||
await api.loadAndInstall();
|
||||
|
||||
@ -113,7 +112,7 @@ describe('role', () => {
|
||||
.set({
|
||||
Authorization: `Bearer ${userToken}`,
|
||||
});
|
||||
|
||||
|
||||
expect(response.statusCode).toEqual(200);
|
||||
|
||||
const userRoles = await userRolesRepo.find();
|
@ -1,6 +1,6 @@
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
|
||||
import { Database, Model } from '@nocobase/database';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
|
||||
import { prepareApp } from './prepare';
|
||||
|
||||
@ -19,32 +19,37 @@ describe('role api', () => {
|
||||
|
||||
describe('grant', () => {
|
||||
let role: Model;
|
||||
let admin: Model;
|
||||
let adminAgent;
|
||||
|
||||
beforeEach(async () => {
|
||||
await db.getRepository('roles').create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
},
|
||||
});
|
||||
|
||||
role = await db.getRepository('roles').findOne({
|
||||
filter: {
|
||||
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 () => {
|
||||
const response = await app.agent().resource('availableActions').list();
|
||||
const response = await adminAgent.resource('availableActions').list();
|
||||
expect(response.statusCode).toEqual(200);
|
||||
});
|
||||
|
||||
it('should grant universal role actions', async () => {
|
||||
// grant role actions
|
||||
const response = await app
|
||||
.agent()
|
||||
const response = await adminAgent
|
||||
.resource('roles')
|
||||
.update({
|
||||
values: {
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { prepareApp } from './prepare';
|
||||
import { MockServer } from '@nocobase/test';
|
||||
import { Database } from '@nocobase/database';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
|
||||
describe('scope api', () => {
|
||||
let app: MockServer;
|
||||
let db: Database;
|
||||
|
||||
let admin;
|
||||
let adminAgent;
|
||||
|
||||
afterEach(async () => {
|
||||
await app.destroy();
|
||||
});
|
||||
@ -13,18 +17,22 @@ describe('scope api', () => {
|
||||
beforeEach(async () => {
|
||||
app = await prepareApp();
|
||||
db = app.db;
|
||||
await db.getRepository('roles').create({
|
||||
|
||||
const UserRepo = db.getCollection('users').repository;
|
||||
admin = await UserRepo.create({
|
||||
values: {
|
||||
name: 'admin',
|
||||
title: 'Admin User',
|
||||
allowConfigure: true,
|
||||
},
|
||||
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 create scope of resource', async () => {
|
||||
const response = await app
|
||||
.agent()
|
||||
const response = await adminAgent
|
||||
.resource('rolesResourcesScopes')
|
||||
.create({
|
||||
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 { Collection } from '@nocobase/database';
|
||||
import UsersPlugin from '@nocobase/plugin-users';
|
||||
import { Plugin } from '@nocobase/server';
|
||||
import { resolve } from 'path';
|
||||
import { availableActionResource } from './actions/available-actions';
|
||||
import { checkAction } from './actions/role-check';
|
||||
import { roleCollectionsResource } from './actions/role-collections';
|
||||
import { setDefaultRole } from './actions/user-setDefaultRole';
|
||||
import { setCurrentRole } from './middlewares/setCurrentRole';
|
||||
import { RoleModel } from './model/RoleModel';
|
||||
import { RoleResourceActionModel } from './model/RoleResourceActionModel';
|
||||
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(`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) => {
|
||||
const { transaction } = options;
|
||||
|
||||
@ -271,7 +290,7 @@ export class PluginACL extends Plugin {
|
||||
title: '{{t("Admin")}}',
|
||||
allowConfigure: true,
|
||||
allowNewMenu: true,
|
||||
strategy: { actions: ['create', 'export', 'view', 'update', 'destroy'] },
|
||||
strategy: { actions: ['create', 'view', 'update', 'destroy'] },
|
||||
},
|
||||
{
|
||||
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', ['create', 'update', 'destroy'], 'allowConfigure');
|
||||
|
||||
@ -392,6 +416,24 @@ export class PluginACL extends Plugin {
|
||||
if (repo) {
|
||||
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() {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { BelongsToManyRepository, Database } from '@nocobase/database';
|
||||
import PluginUsers from '@nocobase/plugin-users';
|
||||
import PluginACL from '@nocobase/plugin-acl';
|
||||
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
|
||||
import UiSchemaStoragePlugin, { UiSchemaRepository } from '@nocobase/plugin-ui-schema-storage';
|
||||
@ -24,6 +25,7 @@ describe('server hooks', () => {
|
||||
|
||||
app.plugin(UiSchemaStoragePlugin);
|
||||
app.plugin(PluginCollectionManager);
|
||||
app.plugin(PluginUsers);
|
||||
app.plugin(PluginACL);
|
||||
|
||||
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();
|
||||
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',
|
||||
},
|
||||
},
|
||||
{
|
||||
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',
|
||||
name: 'appLang',
|
||||
|
@ -1,40 +1,17 @@
|
||||
import { Context, Next } from '@nocobase/actions';
|
||||
import { MiddlewareManager } from '@nocobase/resourcer';
|
||||
import UsersPlugin from '../server';
|
||||
|
||||
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);
|
||||
if (user) {
|
||||
ctx.state.currentUser = user;
|
||||
setCurrentRole(ctx);
|
||||
}
|
||||
return next();
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
return middleware;
|
||||
}
|
||||
|
||||
async function findUserByToken(ctx: Context, plugin: UsersPlugin) {
|
||||
@ -46,7 +23,7 @@ async function findUserByToken(ctx: Context, plugin: UsersPlugin) {
|
||||
try {
|
||||
const { userId } = await plugin.jwtService.decode(token);
|
||||
const collection = ctx.db.getCollection('users');
|
||||
const appends = ['roles'];
|
||||
const appends = [];
|
||||
for (const [, field] of collection.fields) {
|
||||
if (field.type === 'belongsTo') {
|
||||
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 { enUS, zhCN } from './locale';
|
||||
import * as middlewares from './middlewares';
|
||||
import { UserModel } from './models/UserModel';
|
||||
|
||||
export interface UserPluginConfig {
|
||||
jwt: JwtOptions;
|
||||
@ -16,9 +15,12 @@ export interface UserPluginConfig {
|
||||
export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
||||
public jwtService: JwtService;
|
||||
|
||||
public tokenMiddleware;
|
||||
|
||||
constructor(app, options) {
|
||||
super(app, options);
|
||||
this.jwtService = new JwtService(options?.jwt || {});
|
||||
this.tokenMiddleware = middlewares.parseToken({ plugin: this });
|
||||
}
|
||||
|
||||
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) => {
|
||||
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.use(middlewares.parseToken({ plugin: this }));
|
||||
this.app.resourcer.use(this.tokenMiddleware.compose());
|
||||
|
||||
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));
|
||||
loggedInActions.forEach((action) => this.app.acl.allow('users', action, 'loggedIn'));
|
||||
@ -132,17 +117,14 @@ export default class UsersPlugin extends Plugin<UserPluginConfig> {
|
||||
async install(options) {
|
||||
const { rootNickname, rootPassword, rootEmail } = this.getInstallingData(options);
|
||||
const User = this.db.getCollection('users');
|
||||
const user = await User.repository.create<UserModel>({
|
||||
const user = await User.repository.create({
|
||||
values: {
|
||||
email: rootEmail,
|
||||
password: rootPassword,
|
||||
nickname: rootNickname,
|
||||
roles: ['root', 'admin', 'member'],
|
||||
nickname: rootNickname
|
||||
},
|
||||
});
|
||||
|
||||
await user.setDefaultRole('root');
|
||||
|
||||
const repo = this.db.getRepository<any>('collections');
|
||||
if (repo) {
|
||||
await repo.db2cm('users');
|
||||
|
Loading…
Reference in New Issue
Block a user