diff --git a/packages/plugin-permissions-v04/.npmignore b/packages/plugin-permissions-v04/.npmignore new file mode 100644 index 000000000..461574b2f --- /dev/null +++ b/packages/plugin-permissions-v04/.npmignore @@ -0,0 +1,7 @@ +node_modules +*.log +docs +__tests__ +tsconfig.json +src +.fatherrc.ts \ No newline at end of file diff --git a/packages/plugin-permissions-v04/package.json b/packages/plugin-permissions-v04/package.json new file mode 100644 index 000000000..237fe0147 --- /dev/null +++ b/packages/plugin-permissions-v04/package.json @@ -0,0 +1,13 @@ +{ + "name": "@nocobase/plugin-permissions-v04", + "version": "0.4.0-alpha.7", + "main": "lib/index.js", + "license": "MIT", + "dependencies": { + "@nocobase/actions": "^0.4.0-alpha.7", + "@nocobase/database": "^0.4.0-alpha.7", + "@nocobase/resourcer": "^0.4.0-alpha.7", + "@nocobase/server": "^0.4.0-alpha.7" + }, + "gitHead": "f0b335ac30f29f25c95d7d137655fa64d8d67f1e" +} diff --git a/packages/plugin-permissions/src/AccessController.ts b/packages/plugin-permissions-v04/src/AccessController.ts similarity index 100% rename from packages/plugin-permissions/src/AccessController.ts rename to packages/plugin-permissions-v04/src/AccessController.ts diff --git a/packages/plugin-permissions/src/__tests__/AccessController.test.ts b/packages/plugin-permissions-v04/src/__tests__/AccessController.test.ts similarity index 100% rename from packages/plugin-permissions/src/__tests__/AccessController.test.ts rename to packages/plugin-permissions-v04/src/__tests__/AccessController.test.ts diff --git a/packages/plugin-permissions/src/__tests__/index.ts b/packages/plugin-permissions-v04/src/__tests__/index.ts similarity index 100% rename from packages/plugin-permissions/src/__tests__/index.ts rename to packages/plugin-permissions-v04/src/__tests__/index.ts diff --git a/packages/plugin-permissions/src/__tests__/list.test.ts b/packages/plugin-permissions-v04/src/__tests__/list.test.ts similarity index 100% rename from packages/plugin-permissions/src/__tests__/list.test.ts rename to packages/plugin-permissions-v04/src/__tests__/list.test.ts diff --git a/packages/plugin-permissions/src/__tests__/seed.ts b/packages/plugin-permissions-v04/src/__tests__/seed.ts similarity index 100% rename from packages/plugin-permissions/src/__tests__/seed.ts rename to packages/plugin-permissions-v04/src/__tests__/seed.ts diff --git a/packages/plugin-permissions/src/__tests__/tables/categories.ts b/packages/plugin-permissions-v04/src/__tests__/tables/categories.ts similarity index 100% rename from packages/plugin-permissions/src/__tests__/tables/categories.ts rename to packages/plugin-permissions-v04/src/__tests__/tables/categories.ts diff --git a/packages/plugin-permissions/src/__tests__/tables/comments.ts b/packages/plugin-permissions-v04/src/__tests__/tables/comments.ts similarity index 100% rename from packages/plugin-permissions/src/__tests__/tables/comments.ts rename to packages/plugin-permissions-v04/src/__tests__/tables/comments.ts diff --git a/packages/plugin-permissions/src/__tests__/tables/posts.ts b/packages/plugin-permissions-v04/src/__tests__/tables/posts.ts similarity index 100% rename from packages/plugin-permissions/src/__tests__/tables/posts.ts rename to packages/plugin-permissions-v04/src/__tests__/tables/posts.ts diff --git a/packages/plugin-permissions/src/actions/collections.roles.ts b/packages/plugin-permissions-v04/src/actions/collections.roles.ts similarity index 100% rename from packages/plugin-permissions/src/actions/collections.roles.ts rename to packages/plugin-permissions-v04/src/actions/collections.roles.ts diff --git a/packages/plugin-permissions/src/actions/roles.collections.ts b/packages/plugin-permissions-v04/src/actions/roles.collections.ts similarity index 100% rename from packages/plugin-permissions/src/actions/roles.collections.ts rename to packages/plugin-permissions-v04/src/actions/roles.collections.ts diff --git a/packages/plugin-permissions/src/collections/actions_permissions.ts b/packages/plugin-permissions-v04/src/collections/actions_permissions.ts similarity index 100% rename from packages/plugin-permissions/src/collections/actions_permissions.ts rename to packages/plugin-permissions-v04/src/collections/actions_permissions.ts diff --git a/packages/plugin-permissions/src/collections/collections.ts b/packages/plugin-permissions-v04/src/collections/collections.ts similarity index 100% rename from packages/plugin-permissions/src/collections/collections.ts rename to packages/plugin-permissions-v04/src/collections/collections.ts diff --git a/packages/plugin-permissions/src/collections/fields_permissions.ts b/packages/plugin-permissions-v04/src/collections/fields_permissions.ts similarity index 100% rename from packages/plugin-permissions/src/collections/fields_permissions.ts rename to packages/plugin-permissions-v04/src/collections/fields_permissions.ts diff --git a/packages/plugin-permissions/src/collections/permissions.ts b/packages/plugin-permissions-v04/src/collections/permissions.ts similarity index 100% rename from packages/plugin-permissions/src/collections/permissions.ts rename to packages/plugin-permissions-v04/src/collections/permissions.ts diff --git a/packages/plugin-permissions-v04/src/collections/roles.ts b/packages/plugin-permissions-v04/src/collections/roles.ts new file mode 100644 index 000000000..a88df62ba --- /dev/null +++ b/packages/plugin-permissions-v04/src/collections/roles.ts @@ -0,0 +1,194 @@ +import { TableOptions } from '@nocobase/database'; +import { ROLE_TYPE_ROOT, ROLE_TYPE_USER, ROLE_TYPE_ANONYMOUS } from '../constants'; + +export default { + name: 'roles', + title: '权限组配置', + developerMode: true, + internal: true, + fields: [ + { + interface: 'string', + title: '权限组名称', + comment: '角色名称', + type: 'string', + name: 'title', + component: { + showInTable: true, + showInForm: true, + showInDetail: true, + }, + }, + { + interface: 'select', + title: '角色类型', + type: 'integer', + name: 'type', + developerMode: true, + dataSource: [ + { value: ROLE_TYPE_ROOT, label: '系统角色' }, + { value: ROLE_TYPE_ANONYMOUS, label: '匿名角色' }, + { value: ROLE_TYPE_USER, label: '自定义角色' }, + ], + defaultValue: ROLE_TYPE_USER, + component: { + showInTable: true, + showInDetail: true, + } + }, + { + interface: 'boolean', + title: '默认权限组', + type: 'radio', + name: 'default', + component: { + showInTable: true, + showInForm: true, + showInDetail: true, + } + }, + { + interface: 'textarea', + title: '描述', + type: 'text', + name: 'description', + component: { + showInTable: true, + showInForm: true, + showInDetail: true, + }, + }, + // TODO(feature): 用户组后续考虑 + // TODO(feature): 用户表应通过插件配置关联,考虑到今后会有多账户系统的情况 + { + interface: 'linkTo', + title: '用户', + comment: '关联的用户表', + type: 'belongsToMany', + name: 'users', + target: 'users', + through: 'users_roles' + }, + { + interface: 'linkTo', + title: '数据表', + comment: '包含的以数据表分组的权限集', + type: 'belongsToMany', + name: 'collections', + through: 'permissions', + targetKey: 'name' + }, + { + interface: 'linkTo', + title: '页面', + type: 'belongsToMany', + name: 'menus', + target: 'menus', + through: 'menus_permissions', + }, + { + comment: '权限集(方便访问)', + type: 'hasMany', + name: 'permissions' + }, + ], + actions: [ + { + type: 'list', + name: 'list', + title: '查看', + }, + // { + // type: 'get', + // name: 'get', + // title: '详情', + // }, + { + type: 'create', + name: 'create', + title: '新增', + viewName: 'form', + }, + { + type: 'update', + name: 'update', + title: '编辑', + viewName: 'form', + }, + { + type: 'destroy', + name: 'destroy', + title: '删除', + filter: { + type: ROLE_TYPE_USER, + default: false + } + }, + ], + views_v2: [ + { + developerMode: true, + type: 'table', + name: 'table', + title: '全部数据', + labelField: 'title', + actions: [ + { + name: 'create', + type: 'create', + title: '新增', + viewName: 'form', + }, + { + name: 'destroy', + type: 'destroy', + title: '删除', + }, + ], + fields: ['title', 'description', 'default'], + detailsOpenMode: 'drawer', // window + details: ['descriptions', 'collections', 'pages'], + sort: ['id'], + }, + { + developerMode: true, + type: 'descriptions', + name: 'descriptions', + title: '详情', + fields: ['title', 'description', 'default'], + actions: [ + { + name: 'update', + type: 'update', + title: '编辑', + viewName: 'form', + }, + ], + }, + { + developerMode: true, + type: 'form', + name: 'form', + title: '表单', + fields: ['title', 'description', 'default'], + }, + { + developerMode: true, + type: 'table', + dataSourceType: 'association', + name: 'collections', + title: '数据操作权限', + targetViewName: 'permissions_table', + targetFieldName: 'collections', + }, + { + developerMode: true, + type: 'table', + dataSourceType: 'association', + name: 'pages', + title: '菜单和页面权限', + targetViewName: 'permissions_table', + targetFieldName: 'menus', + }, + ], +} as TableOptions; diff --git a/packages/plugin-permissions/src/collections/tabs_permissions.ts b/packages/plugin-permissions-v04/src/collections/tabs_permissions.ts similarity index 100% rename from packages/plugin-permissions/src/collections/tabs_permissions.ts rename to packages/plugin-permissions-v04/src/collections/tabs_permissions.ts diff --git a/packages/plugin-permissions/src/collections/users.ts b/packages/plugin-permissions-v04/src/collections/users.ts similarity index 100% rename from packages/plugin-permissions/src/collections/users.ts rename to packages/plugin-permissions-v04/src/collections/users.ts diff --git a/packages/plugin-permissions/src/constants.ts b/packages/plugin-permissions-v04/src/constants.ts similarity index 100% rename from packages/plugin-permissions/src/constants.ts rename to packages/plugin-permissions-v04/src/constants.ts diff --git a/packages/plugin-permissions/src/index.ts b/packages/plugin-permissions-v04/src/index.ts similarity index 100% rename from packages/plugin-permissions/src/index.ts rename to packages/plugin-permissions-v04/src/index.ts diff --git a/packages/plugin-permissions-v04/src/server.ts b/packages/plugin-permissions-v04/src/server.ts new file mode 100644 index 000000000..a7eddaaae --- /dev/null +++ b/packages/plugin-permissions-v04/src/server.ts @@ -0,0 +1,166 @@ +import path from 'path'; +import { Op } from 'sequelize'; +import { Application } from '@nocobase/server'; +import { Operator } from '@nocobase/database'; +import * as collectionsRolesActions from './actions/collections.roles'; +import * as rolesCollectionsActions from './actions/roles.collections'; +import AccessController, { PermissionParams } from './AccessController'; + +// API +// const permissions = ctx.app.getPluginInstance('permissions'); +// const result: boolean = permissions.can(key, options); + + + +export class Permissions { + readonly app: Application; + readonly options: any; + + constructor(app: Application, options) { + this.app = app; + this.options = options; + + const { database, resourcer } = app; + + database.import({ + directory: path.resolve(__dirname, 'collections'), + }); + + Object.keys(collectionsRolesActions).forEach(actionName => { + resourcer.registerActionHandler(`collections.roles:${actionName}`, collectionsRolesActions[actionName]); + }); + + Object.keys(rolesCollectionsActions).forEach(actionName => { + resourcer.registerActionHandler(`roles.collections:${actionName}`, rolesCollectionsActions[actionName]); + }); + + database.getModel('collections').addHook('afterCreate', async (model: any, options) => { + await model.updateAssociations({ + scopes: [ + { + title: '全部数据', + filter: {}, + locked: true + }, + { + title: '用户自己的数据', + filter: { + "created_by_id.$currentUser": true, + }, + locked: true + }, + ] + }, options); + }); + + database.getModel('users').addHook('afterCreate', async(model, options) => { + const { transaction = await database.sequelize.transaction() } = options; + const Role = database.getModel('roles'); + const defaultRole = await Role.findOne({ where: { default: true }, transaction }); + if (defaultRole) { + // @ts-ignore + await model.addRole(defaultRole, { transaction }); + } + if (!options.transaction) { + await transaction.commit(); + } + }); + + // 针对“自己创建的” scope 添加特殊的操作符以生成查询条件 + if (!Operator.has('$currentUser')) { + Operator.register('$currentUser', (value, { ctx }) => { + const user = ctx.state.currentUser; + return { [Op.eq]: user[user.constructor.primaryKeyAttribute] }; + }); + } + + resourcer.use(this.injection); + resourcer.use(this.middleware); + + resourcer.use(async (ctx, next) => { + const { resourceName } = ctx.action.params; + if (resourceName === 'action_logs' && !await ctx.ac.isRoot()) { + const collections = await ctx.ac.getCollections(); + ctx.action.mergeParams({ + filter: { + 'collection_name.in': collections + }, + }); + } + await next(); + }); + } + + injection = async (ctx, next) => { + ctx.ac = new AccessController(ctx); + + return next(); + }; + + middleware = async (ctx, next) => { + const { + associatedName, + resourceField, + resourceName, + actionName + } = ctx.action.params; + + let result: PermissionParams = false; + + // 关系数据的权限 + if (associatedName && resourceField) { + if (resourceField.options.id && resourceField.options.interface === 'subTable') { + if (await ctx.ac.isRoot()) { + return next(); + } + const permissions = await ctx.ac.getPermissions(); + const FieldPermission = ctx.db.getModel('fields_permissions'); + const fps = await FieldPermission.findAll({ + where: { + field_id: resourceField.options.id, + permission_id: { + [Op.in]: permissions.map(p => p.id), + } + }, + }); + if (fps.length) { + for (const fp of fps) { + if (Array.isArray(fp.actions) && fp.actions.includes(`${resourceField.options.collection_name}:${actionName}`)) { + return next(); + } + } + return this.reject(ctx); + } + } + result = await ctx.ac.can(resourceField.options.target).act(actionName).any(); + } else { + result = await ctx.ac.can(resourceName).act(actionName).any(); + } + + if (!result) { + return this.reject(ctx); + } + + if (result === true) { + return next(); + } + + ctx.action.mergeParams({ + filter: result.filter, + // TODO: 在 fields 改进之前,先注释掉 + // fields: result.fields.map(item => item.get('field').get('name')) + }); + + return next(); + }; + + reject(ctx) { + ctx.throw(404); + } +} + +export default async function (options = {}) { + const instance = new Permissions(this, options); + + return instance; +} diff --git a/packages/plugin-permissions/src/collections/action_permissions.ts b/packages/plugin-permissions/src/collections/action_permissions.ts new file mode 100644 index 000000000..4c4b52110 --- /dev/null +++ b/packages/plugin-permissions/src/collections/action_permissions.ts @@ -0,0 +1,38 @@ +import { TableOptions } from '@nocobase/database'; + +export default { + name: 'action_permissions', + fields: [ + { + type: 'string', + name: 'actionName', + }, + { + type: 'belongsTo', + name: 'scope', + }, + { + type: 'belongsTo', + name: 'collection', + }, + { + type: 'belongsTo', + name: 'role', + }, + { + type: 'belongsTo', + name: 'user', + }, + { + type: 'hasMany', + name: 'fieldPermissions', + target: 'field_permissions', + foreignKey: 'action_permission_id', + }, + { + type: 'belongsToMany', + name: 'fields', + through: 'field_permissions', + }, + ], +} as TableOptions; diff --git a/packages/plugin-permissions/src/collections/roles.ts b/packages/plugin-permissions/src/collections/roles.ts index a88df62ba..a30634fa9 100644 --- a/packages/plugin-permissions/src/collections/roles.ts +++ b/packages/plugin-permissions/src/collections/roles.ts @@ -1,194 +1,24 @@ import { TableOptions } from '@nocobase/database'; -import { ROLE_TYPE_ROOT, ROLE_TYPE_USER, ROLE_TYPE_ANONYMOUS } from '../constants'; export default { name: 'roles', - title: '权限组配置', - developerMode: true, - internal: true, + sortable: 'sort', fields: [ { - interface: 'string', - title: '权限组名称', - comment: '角色名称', + type: 'uid', + name: 'name', + primaryKey: true, + prefix: 't_', + }, + { type: 'string', name: 'title', - component: { - showInTable: true, - showInForm: true, - showInDetail: true, - }, }, { - interface: 'select', - title: '角色类型', - type: 'integer', - name: 'type', - developerMode: true, - dataSource: [ - { value: ROLE_TYPE_ROOT, label: '系统角色' }, - { value: ROLE_TYPE_ANONYMOUS, label: '匿名角色' }, - { value: ROLE_TYPE_USER, label: '自定义角色' }, - ], - defaultValue: ROLE_TYPE_USER, - component: { - showInTable: true, - showInDetail: true, - } - }, - { - interface: 'boolean', - title: '默认权限组', - type: 'radio', - name: 'default', - component: { - showInTable: true, - showInForm: true, - showInDetail: true, - } - }, - { - interface: 'textarea', - title: '描述', - type: 'text', - name: 'description', - component: { - showInTable: true, - showInForm: true, - showInDetail: true, - }, - }, - // TODO(feature): 用户组后续考虑 - // TODO(feature): 用户表应通过插件配置关联,考虑到今后会有多账户系统的情况 - { - interface: 'linkTo', - title: '用户', - comment: '关联的用户表', type: 'belongsToMany', name: 'users', target: 'users', - through: 'users_roles' - }, - { - interface: 'linkTo', - title: '数据表', - comment: '包含的以数据表分组的权限集', - type: 'belongsToMany', - name: 'collections', - through: 'permissions', - targetKey: 'name' - }, - { - interface: 'linkTo', - title: '页面', - type: 'belongsToMany', - name: 'menus', - target: 'menus', - through: 'menus_permissions', - }, - { - comment: '权限集(方便访问)', - type: 'hasMany', - name: 'permissions' - }, - ], - actions: [ - { - type: 'list', - name: 'list', - title: '查看', - }, - // { - // type: 'get', - // name: 'get', - // title: '详情', - // }, - { - type: 'create', - name: 'create', - title: '新增', - viewName: 'form', - }, - { - type: 'update', - name: 'update', - title: '编辑', - viewName: 'form', - }, - { - type: 'destroy', - name: 'destroy', - title: '删除', - filter: { - type: ROLE_TYPE_USER, - default: false - } - }, - ], - views_v2: [ - { - developerMode: true, - type: 'table', - name: 'table', - title: '全部数据', - labelField: 'title', - actions: [ - { - name: 'create', - type: 'create', - title: '新增', - viewName: 'form', - }, - { - name: 'destroy', - type: 'destroy', - title: '删除', - }, - ], - fields: ['title', 'description', 'default'], - detailsOpenMode: 'drawer', // window - details: ['descriptions', 'collections', 'pages'], - sort: ['id'], - }, - { - developerMode: true, - type: 'descriptions', - name: 'descriptions', - title: '详情', - fields: ['title', 'description', 'default'], - actions: [ - { - name: 'update', - type: 'update', - title: '编辑', - viewName: 'form', - }, - ], - }, - { - developerMode: true, - type: 'form', - name: 'form', - title: '表单', - fields: ['title', 'description', 'default'], - }, - { - developerMode: true, - type: 'table', - dataSourceType: 'association', - name: 'collections', - title: '数据操作权限', - targetViewName: 'permissions_table', - targetFieldName: 'collections', - }, - { - developerMode: true, - type: 'table', - dataSourceType: 'association', - name: 'pages', - title: '菜单和页面权限', - targetViewName: 'permissions_table', - targetFieldName: 'menus', + through: 'roles_users' }, ], } as TableOptions; diff --git a/packages/plugin-permissions/src/collections/scopes.ts b/packages/plugin-permissions/src/collections/scopes.ts new file mode 100644 index 000000000..b61514d31 --- /dev/null +++ b/packages/plugin-permissions/src/collections/scopes.ts @@ -0,0 +1,20 @@ +import { TableOptions } from '@nocobase/database'; + +export default { + name: 'scopes', + sortable: 'sort', + fields: [ + { + type: 'string', + name: 'title', + }, + { + type: 'json', + name: 'filter', + }, + { + type: 'belongsTo', + name: 'collection', + }, + ], +} as TableOptions; diff --git a/packages/plugin-permissions/src/server.ts b/packages/plugin-permissions/src/server.ts index a7eddaaae..f5270af55 100644 --- a/packages/plugin-permissions/src/server.ts +++ b/packages/plugin-permissions/src/server.ts @@ -1,166 +1,12 @@ import path from 'path'; -import { Op } from 'sequelize'; -import { Application } from '@nocobase/server'; -import { Operator } from '@nocobase/database'; -import * as collectionsRolesActions from './actions/collections.roles'; -import * as rolesCollectionsActions from './actions/roles.collections'; -import AccessController, { PermissionParams } from './AccessController'; +import Database from '@nocobase/database'; +import Resourcer from '@nocobase/resourcer'; -// API -// const permissions = ctx.app.getPluginInstance('permissions'); -// const result: boolean = permissions.can(key, options); +export default async function () { + const database: Database = this.database; + const resourcer: Resourcer = this.resourcer; - - -export class Permissions { - readonly app: Application; - readonly options: any; - - constructor(app: Application, options) { - this.app = app; - this.options = options; - - const { database, resourcer } = app; - - database.import({ - directory: path.resolve(__dirname, 'collections'), - }); - - Object.keys(collectionsRolesActions).forEach(actionName => { - resourcer.registerActionHandler(`collections.roles:${actionName}`, collectionsRolesActions[actionName]); - }); - - Object.keys(rolesCollectionsActions).forEach(actionName => { - resourcer.registerActionHandler(`roles.collections:${actionName}`, rolesCollectionsActions[actionName]); - }); - - database.getModel('collections').addHook('afterCreate', async (model: any, options) => { - await model.updateAssociations({ - scopes: [ - { - title: '全部数据', - filter: {}, - locked: true - }, - { - title: '用户自己的数据', - filter: { - "created_by_id.$currentUser": true, - }, - locked: true - }, - ] - }, options); - }); - - database.getModel('users').addHook('afterCreate', async(model, options) => { - const { transaction = await database.sequelize.transaction() } = options; - const Role = database.getModel('roles'); - const defaultRole = await Role.findOne({ where: { default: true }, transaction }); - if (defaultRole) { - // @ts-ignore - await model.addRole(defaultRole, { transaction }); - } - if (!options.transaction) { - await transaction.commit(); - } - }); - - // 针对“自己创建的” scope 添加特殊的操作符以生成查询条件 - if (!Operator.has('$currentUser')) { - Operator.register('$currentUser', (value, { ctx }) => { - const user = ctx.state.currentUser; - return { [Op.eq]: user[user.constructor.primaryKeyAttribute] }; - }); - } - - resourcer.use(this.injection); - resourcer.use(this.middleware); - - resourcer.use(async (ctx, next) => { - const { resourceName } = ctx.action.params; - if (resourceName === 'action_logs' && !await ctx.ac.isRoot()) { - const collections = await ctx.ac.getCollections(); - ctx.action.mergeParams({ - filter: { - 'collection_name.in': collections - }, - }); - } - await next(); - }); - } - - injection = async (ctx, next) => { - ctx.ac = new AccessController(ctx); - - return next(); - }; - - middleware = async (ctx, next) => { - const { - associatedName, - resourceField, - resourceName, - actionName - } = ctx.action.params; - - let result: PermissionParams = false; - - // 关系数据的权限 - if (associatedName && resourceField) { - if (resourceField.options.id && resourceField.options.interface === 'subTable') { - if (await ctx.ac.isRoot()) { - return next(); - } - const permissions = await ctx.ac.getPermissions(); - const FieldPermission = ctx.db.getModel('fields_permissions'); - const fps = await FieldPermission.findAll({ - where: { - field_id: resourceField.options.id, - permission_id: { - [Op.in]: permissions.map(p => p.id), - } - }, - }); - if (fps.length) { - for (const fp of fps) { - if (Array.isArray(fp.actions) && fp.actions.includes(`${resourceField.options.collection_name}:${actionName}`)) { - return next(); - } - } - return this.reject(ctx); - } - } - result = await ctx.ac.can(resourceField.options.target).act(actionName).any(); - } else { - result = await ctx.ac.can(resourceName).act(actionName).any(); - } - - if (!result) { - return this.reject(ctx); - } - - if (result === true) { - return next(); - } - - ctx.action.mergeParams({ - filter: result.filter, - // TODO: 在 fields 改进之前,先注释掉 - // fields: result.fields.map(item => item.get('field').get('name')) - }); - - return next(); - }; - - reject(ctx) { - ctx.throw(404); - } -} - -export default async function (options = {}) { - const instance = new Permissions(this, options); - - return instance; + database.import({ + directory: path.resolve(__dirname, 'collections'), + }); }