tachybase_todo/packages/plugin-permissions/src/actions/roles.collections.ts
chenos 301229ef88
feat: route permissions (#58)
* feat: routes permissions

* fix: try to fix roles.pages action

* 多态关联

* bugfix

* fix: auto generate when option value is undefined or null

* feat: add pages' permissions saving/listing

* feat: add permission filter for getRoutes

* roles description

* feat: get root permissions all true and create user with default role

* feat: roles.collections list output with permission

* add permissions description

* fix: add context to parseApiJson

* fix: typo

* 小细节补充

Co-authored-by: mytharcher <mytharcher@gmail.com>
2021-01-22 10:18:02 +08:00

168 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Op } from 'sequelize';
import { actions } from '@nocobase/actions';
import _ from 'lodash';
export async function list(ctx: actions.Context, next: actions.Next) {
const { associated } = ctx.action.params;
// TODO: 暂时 action 中间件就这么写了
ctx.action.mergeParams({
associated: null
});
await actions.common.list(ctx, async () => {
const permissions = await associated.getPermissions();
ctx.body.rows.forEach(item => {
const permission = permissions.find(p => p.collection_name === item.get('name'));
if (permission) {
// item.permissions = [permission]; // 不输出
item.set('permissions', [permission]); // 输出
}
});
});
await next();
}
export async function get(ctx: actions.Context, next: actions.Next) {
const {
resourceKey,
associated
} = ctx.action.params;
const permissions = await ctx.ac.as(associated).can(resourceKey).permissions();
const permission = await associated.getPermissions({
where: {
collection_name: resourceKey,
},
plain: true,
limit: 1,
});
console.log(permission);
ctx.body = {
...permissions,
description: _.get(permission, 'description'),
};
await next();
}
export async function update(ctx: actions.Context, next: actions.Next) {
const {
resourceKey,
associated,
values
} = ctx.action.params;
const transaction = await ctx.db.sequelize.transaction();
// role.getPermissions
let [permission] = await associated.getPermissions({
where: {
collection_name: resourceKey
},
transaction
});
if (!permission) {
// 不存在则创建
permission = await associated.createPermission({
collection_name: resourceKey,
description: values.description
}, { transaction });
} else {
// 存在则更新描述
await permission.update({ description: values.description }, { transaction });
}
// 查找对应 collection 下所有“可用”的 actions
const ActionModel = ctx.db.getModel('actions');
const availableActions = await ActionModel.findAll({
where: {
// null 代表全局 action
collection_name: {
[Op.or]: [resourceKey, null]
},
...(ctx.state.developerMode ? {} : { developerMode: false })
},
transaction
});
// 需要移除的 = 所有可用的 - 要添加的
const toRemoveActionNames = new Set<string>();
availableActions.forEach(action => {
const name = `${action.collection_name || resourceKey}:${action.name}`;
if (!values.actions.find(item => item.name === name)) {
toRemoveActionNames.add(name);
}
});
// 移除没有设置的
// 因为只知道 name不知道 id所以只能从 Model 上调用移除
const ActionPermission = ctx.db.getModel('actions_permissions');
await ActionPermission.destroy({
where: {
permission_id: permission.id,
name: Array.from(toRemoveActionNames)
},
transaction
});
// 更新或创建
const existedActions = await permission.getActions({ transaction });
for (const actionItem of values.actions) {
const action = existedActions.find(item => item.name === actionItem.name);
if (action) {
await action.update(actionItem, { transaction });
} else {
await permission.createAction(actionItem, { transaction });
}
};
const fieldsValue = values.fields.filter(field => field.actions && field.actions.length);
const existedFields = await permission.getFields_permissions({
include: [
{ association: 'field' }
],
transaction
});
const toRemoveFields = [];
const fieldsLeft = [];
existedFields.forEach(field => {
if (
!fieldsValue.find(({ field_id }) => field_id === field.field_id)
&& !(field.field.developerMode ^ ctx.state.developerMode)
) {
toRemoveFields.push(field.field);
} else {
fieldsLeft.push(field);
}
});
if (toRemoveFields.length) {
await permission.removeFields(toRemoveFields, { transaction });
}
for (const fieldItem of fieldsValue) {
const field = fieldsLeft.find(item => item.field_id === fieldItem.field_id);
if (field) {
await field.update(fieldItem, { transaction });
} else {
await permission.createFields_permission(fieldItem, { transaction });
}
}
const TabModel = ctx.db.getModel('tabs');
const existedTabs = await permission.getTabs({ transaction });
const toRemoveTabs = existedTabs.filter(tab => (
// 如果没找到
!values.tabs.find(id => tab[TabModel.primaryKeyAttribute] === id)
// 且开发者模式匹配
&& !(tab.developerMode ^ ctx.state.developerMode)));
await permission.removeTabs(toRemoveTabs, { transaction });
await permission.addTabs(values.tabs, { transaction });
await transaction.commit();
ctx.body = permission;
await next();
}