@steedos/standard-permission 2.5.0-beta.17 → 2.5.0-beta.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* @Author: sunhaolin@hotoa.com
|
|
3
3
|
* @Date: 2022-05-26 16:56:54
|
|
4
4
|
* @LastEditors: sunhaolin@hotoa.com
|
|
5
|
-
* @LastEditTime: 2023-04-
|
|
5
|
+
* @LastEditTime: 2023-04-28 14:59:28
|
|
6
6
|
* @Description: 复制已有简档来创建新简档
|
|
7
|
+
* 使用mongodb的事务处理,保证数据的一致性
|
|
8
|
+
* 复制对象包括:简档、对象权限、字段权限、选项卡权限
|
|
7
9
|
*/
|
|
8
10
|
'use strict';
|
|
9
11
|
// @ts-check
|
|
@@ -12,6 +14,8 @@ const express = require("express");
|
|
|
12
14
|
const router = express.Router();
|
|
13
15
|
const core = require('@steedos/core');
|
|
14
16
|
const objectql = require('@steedos/objectql');
|
|
17
|
+
const InternalData = require('@steedos/standard-objects').internalData;
|
|
18
|
+
const _ = require('underscore');
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* body {
|
|
@@ -38,11 +42,8 @@ router.post('/api/permission/permission_set/copy', core.requireAuthentication, a
|
|
|
38
42
|
|
|
39
43
|
const psObj = objectql.getObject('permission_set');
|
|
40
44
|
const poObj = objectql.getObject('permission_objects');
|
|
41
|
-
const pfObj = objectql.getObject('permission_fields');
|
|
42
45
|
const ptObj = objectql.getObject('permission_tabs');
|
|
43
46
|
|
|
44
|
-
// const originalPermissionSet = (await psObj.find({ filters:[ ['name', '=', originalPermissionSetId], ['space', '=', spaceId] ] }, userSession))[0]
|
|
45
|
-
|
|
46
47
|
const originalPermissionSet = await psObj.findOne(originalPermissionSetId, {}, userSession);
|
|
47
48
|
if (!originalPermissionSet) {
|
|
48
49
|
throw new Error("permission_set not found");
|
|
@@ -51,88 +52,239 @@ router.post('/api/permission/permission_set/copy', core.requireAuthentication, a
|
|
|
51
52
|
if (originalPermissionSet.type !== 'profile') {
|
|
52
53
|
throw new Error("permission_set is not profile type");
|
|
53
54
|
}
|
|
55
|
+
// API名称不能重复
|
|
56
|
+
const existPermissionSetCount = await psObj.count({
|
|
57
|
+
filters: [
|
|
58
|
+
['name', '=', name],
|
|
59
|
+
['space', '=', spaceId],
|
|
60
|
+
]
|
|
61
|
+
}, userSession);
|
|
62
|
+
if (existPermissionSetCount > 0) {
|
|
63
|
+
throw new Error("API名称不能重复");
|
|
64
|
+
}
|
|
54
65
|
|
|
55
|
-
//
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// // 创建新的字段权限
|
|
101
|
-
// delete pfDoc._id;
|
|
102
|
-
// const newPermissionField = await pfObj.insert({
|
|
103
|
-
// ...pfDoc,
|
|
104
|
-
// ...baseInfo,
|
|
105
|
-
// permission_set_id: newPermissionSetName,
|
|
106
|
-
// permission_object_id: newPermissionObjectName
|
|
107
|
-
// });
|
|
108
|
-
// }
|
|
109
|
-
// }
|
|
110
|
-
}
|
|
66
|
+
// 事务 https://www.mongodb.com/docs/v4.4/core/transactions-in-applications/#core-api
|
|
67
|
+
const config = objectql.getSteedosConfig();
|
|
68
|
+
let datasourceConfig = config.datasources['default'];
|
|
69
|
+
const driver = new objectql.SteedosMongoDriver(datasourceConfig.connection);
|
|
70
|
+
await driver.connect();
|
|
71
|
+
const client = driver._client;
|
|
72
|
+
const db = client.db();
|
|
73
|
+
|
|
74
|
+
// Start a session.
|
|
75
|
+
const session = client.startSession();
|
|
76
|
+
|
|
77
|
+
const permissionObjectsColl = db.collection('permission_objects');
|
|
78
|
+
const permissionFieldsColl = db.collection('permission_fields');
|
|
79
|
+
const permissionTabsColl = db.collection('permission_tabs');
|
|
80
|
+
const permissionSetColl = db.collection('permission_set');
|
|
81
|
+
|
|
82
|
+
// Start a transaction
|
|
83
|
+
session.startTransaction({ readConcern: { level: "local" }, writeConcern: { w: "majority" } });
|
|
84
|
+
|
|
85
|
+
let newPermissionSet = null;
|
|
86
|
+
|
|
87
|
+
// Operations inside the transaction
|
|
88
|
+
try {
|
|
89
|
+
// 基础信息
|
|
90
|
+
const baseInfo = {
|
|
91
|
+
created: new Date(),
|
|
92
|
+
created_by: userId,
|
|
93
|
+
modified: new Date(),
|
|
94
|
+
modified_by: userId,
|
|
95
|
+
space: spaceId,
|
|
96
|
+
company_id: company_id,
|
|
97
|
+
company_ids: [company_id],
|
|
98
|
+
owner: userId,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// 创建新简档
|
|
102
|
+
let newPermissionSetData = {
|
|
103
|
+
...originalPermissionSet,
|
|
104
|
+
...baseInfo,
|
|
105
|
+
is_system: false,
|
|
106
|
+
name,
|
|
107
|
+
label,
|
|
108
|
+
_id: driver._makeNewID(),
|
|
109
|
+
copy_from: originalPermissionSetId,
|
|
110
|
+
};
|
|
111
111
|
|
|
112
|
+
delete newPermissionSetData.record_permissions;
|
|
113
|
+
const insertPermissionSetResult = await permissionSetColl.insertOne(newPermissionSetData);
|
|
114
|
+
newPermissionSet = insertPermissionSetResult.ops[0];
|
|
115
|
+
console.log('newPermissionSet', newPermissionSet)
|
|
112
116
|
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
// 创建对象权限和选项卡权限
|
|
118
|
+
if (newPermissionSet) {
|
|
119
|
+
const { _id: newPermissionSetId, name: newPermissionSetName } = newPermissionSet;
|
|
120
|
+
// 对象权限数据来源于两个部分,1、内存 2、数据库
|
|
121
|
+
const internalPermissionObjects = await getInternalPermissionObjects(originalPermissionSetId);
|
|
122
|
+
const dbPermissionObjects = await poObj.directFind({ filters: [['space', '=', spaceId], ['permission_set_id', '=', originalPermissionSetId]] });
|
|
123
|
+
const originalPermissionObjects = getCombinedPermissionObjects(internalPermissionObjects, dbPermissionObjects);
|
|
124
|
+
const newPermissionObjects = []
|
|
125
|
+
const newPermissionFields = []
|
|
126
|
+
// 遍历原有的对象权限
|
|
127
|
+
for (const poDoc of originalPermissionObjects) {
|
|
128
|
+
const fromId = poDoc._id;
|
|
129
|
+
const newId = driver._makeNewID();
|
|
130
|
+
// 由于 15.permission_objects.observe.object.js 中的 _change 函数中,调用了 permission_fields.resetFieldPermissions 方法,会阻塞redis查询,需要调整15.permission_objects.observe.object.js, 避免调用 resetFieldPermissions 方法
|
|
131
|
+
const newPermissionObject = {
|
|
132
|
+
...poDoc,
|
|
133
|
+
...baseInfo,
|
|
134
|
+
permission_set_id: newPermissionSetId,
|
|
135
|
+
name: `${poDoc.object_name}.${newPermissionSetName}`,
|
|
136
|
+
_id: newId,
|
|
137
|
+
copy_from: fromId
|
|
138
|
+
};
|
|
139
|
+
newPermissionObjects.push(newPermissionObject)
|
|
140
|
+
// 获取对象所有字段
|
|
141
|
+
const fields = await objectql.getObject('object_fields').find({ filters: [['object', '=', newPermissionObject.object_name]] });
|
|
142
|
+
for (const field of fields) {
|
|
143
|
+
const apiName = `${newPermissionSetName}.${newPermissionObject.object_name}.${field.name}`
|
|
144
|
+
const fieldPermission = await getFieldPermission(apiName)
|
|
145
|
+
newPermissionFields.push({
|
|
146
|
+
...baseInfo,
|
|
147
|
+
name: apiName,
|
|
148
|
+
permission_set_id: newPermissionSetName,
|
|
149
|
+
permission_object: newPermissionObject.name,
|
|
150
|
+
object_name: newPermissionObject.object_name,
|
|
151
|
+
field: field.name,
|
|
152
|
+
editable: fieldPermission ? fieldPermission.editable : getFieldDefaultEditable(field),
|
|
153
|
+
readable: fieldPermission ? fieldPermission.readable : getFieldDefaultReadable(field),
|
|
154
|
+
_id: driver._makeNewID(),
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const originalPermissionTabs = await ptObj.find({ filters: [['space', '=', spaceId], ['permission_set', '=', originalPermissionSet.name]] }, userSession);
|
|
160
|
+
const newPermissionTabs = [];
|
|
161
|
+
// 遍历原有的选项卡权限
|
|
162
|
+
for (const ptDoc of originalPermissionTabs) {
|
|
163
|
+
const fromId = ptDoc._id;
|
|
164
|
+
const newId = driver._makeNewID();
|
|
165
|
+
delete ptDoc.record_permissions;
|
|
166
|
+
newPermissionTabs.push({
|
|
167
|
+
...ptDoc,
|
|
168
|
+
...baseInfo,
|
|
169
|
+
permission_set: newPermissionSetName,
|
|
170
|
+
_id: newId,
|
|
171
|
+
is_system: false,
|
|
172
|
+
copy_from: fromId
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 批量创建对象权限
|
|
177
|
+
await permissionObjectsColl.insertMany(newPermissionObjects, { session });
|
|
178
|
+
|
|
179
|
+
// 批量创建字段权限
|
|
180
|
+
await permissionFieldsColl.insertMany(newPermissionFields, { session });
|
|
181
|
+
|
|
182
|
+
// 批量创建选项卡权限
|
|
183
|
+
await permissionTabsColl.insertMany(newPermissionTabs, { session });
|
|
123
184
|
}
|
|
124
185
|
|
|
186
|
+
} catch (error) {
|
|
187
|
+
// Abort transaction on error
|
|
188
|
+
await session.abortTransaction();
|
|
189
|
+
throw error;
|
|
125
190
|
}
|
|
126
191
|
|
|
127
|
-
|
|
128
|
-
|
|
192
|
+
// Commit the transaction using write concern set at transaction start
|
|
193
|
+
await session.commitTransaction();
|
|
194
|
+
await session.endSession();
|
|
195
|
+
await client.close();
|
|
196
|
+
|
|
197
|
+
if (!newPermissionSet) {
|
|
198
|
+
throw new Error("create permission_set failed");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
res.status(200).send({
|
|
202
|
+
message: 'success',
|
|
129
203
|
recordId: newPermissionSet._id
|
|
130
204
|
});
|
|
131
|
-
|
|
205
|
+
|
|
132
206
|
} catch (error) {
|
|
133
207
|
console.error(error);
|
|
134
208
|
res.status(500).send({ error: error.message });
|
|
135
209
|
}
|
|
136
210
|
|
|
137
211
|
});
|
|
138
|
-
exports.default = router;
|
|
212
|
+
exports.default = router;
|
|
213
|
+
|
|
214
|
+
// 获取内存中的对象权限
|
|
215
|
+
async function getInternalPermissionObjects(permissionSetId) {
|
|
216
|
+
// 查找permissionSetId对应的permissionSet
|
|
217
|
+
const permissionSetDoc = (await objectql.getObject('permission_set').directFind({
|
|
218
|
+
filters: [
|
|
219
|
+
['_id', '=', permissionSetId],
|
|
220
|
+
]
|
|
221
|
+
})[0]);
|
|
222
|
+
// 如果库中有记录则使用库中的name作为判断条件,否则使用permissionSetId
|
|
223
|
+
const permissionSetName = permissionSetDoc ? permissionSetDoc.name : permissionSetId;
|
|
224
|
+
|
|
225
|
+
let objectsPermissions = [];
|
|
226
|
+
const datasources = objectql.getSteedosSchema().getDataSources();
|
|
227
|
+
for (const datasourceName in datasources) {
|
|
228
|
+
let datasource = datasources[datasourceName];
|
|
229
|
+
let datasourceObjects = await datasource.getObjects();
|
|
230
|
+
_.each(datasourceObjects, function (object) {
|
|
231
|
+
const objectJSON = object.metadata;
|
|
232
|
+
const objectName = objectJSON.name;
|
|
233
|
+
if (!objectJSON._id && !_.include(InternalData.hiddenObjects, objectName)) {
|
|
234
|
+
let permission_set = objectJSON.permission_set
|
|
235
|
+
_.each(permission_set, function (v, code) {
|
|
236
|
+
if (code === permissionSetName) {
|
|
237
|
+
objectsPermissions.push(Object.assign({}, v, { _id: `${code}_${objectName}`, name: `${code}_${objectName}`, permission_set_id: code, object_name: objectName }))
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return objectsPermissions;
|
|
244
|
+
}
|
|
245
|
+
// 合并内存中的对象权限和数据库中的对象权限
|
|
246
|
+
// 如果dbPermissionObjects和internalPermissionObjects中permission_set_id存在相同的值,则以dbPermissionObjects中数据为准
|
|
247
|
+
function getCombinedPermissionObjects(internalPermissionObjects, dbPermissionObjects) {
|
|
248
|
+
const dbPermissionObjectsIds = _.pluck(dbPermissionObjects, 'permission_set_id');
|
|
249
|
+
const internalPermissionObjectsIds = _.pluck(internalPermissionObjects, 'permission_set_id');
|
|
250
|
+
const sameIds = _.intersection(dbPermissionObjectsIds, internalPermissionObjectsIds);
|
|
251
|
+
if (sameIds.length > 0) {
|
|
252
|
+
for (const sameId of sameIds) {
|
|
253
|
+
const dbPermissionObject = _.findWhere(dbPermissionObjects, { permission_set_id: sameId });
|
|
254
|
+
const internalPermissionObject = _.findWhere(internalPermissionObjects, { permission_set_id: sameId });
|
|
255
|
+
if (dbPermissionObject && internalPermissionObject) {
|
|
256
|
+
const index = internalPermissionObjects.indexOf(internalPermissionObject);
|
|
257
|
+
internalPermissionObjects.splice(index, 1, dbPermissionObject);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return [...internalPermissionObjects, ...dbPermissionObjects];
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async function getFieldPermission(apiName) {
|
|
265
|
+
const schema = objectql.getSteedosSchema();
|
|
266
|
+
const config = await objectql.registerPermissionFields.get(schema.broker, apiName)
|
|
267
|
+
return config ? config.metadata : null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const systemFields = ['owner', 'created', 'created_by', 'modified', 'modified_by', 'locked', 'company_id', 'company_ids', 'instance_state'];
|
|
271
|
+
|
|
272
|
+
const getFieldDefaultEditable = (field) => {
|
|
273
|
+
if (_.includes(systemFields, field.name) && (field.omit || field.hidden || field.readonly || field.disabled)) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
if (field.omit || field.hidden || field.readonly || field.disabled) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const getFieldDefaultReadable = (field) => {
|
|
283
|
+
if (_.includes(systemFields, field.name) && !field.hidden) {
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
if (field.hidden) {
|
|
287
|
+
return false
|
|
288
|
+
}
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
@@ -99,7 +99,11 @@ module.exports = {
|
|
|
99
99
|
if (matches) {
|
|
100
100
|
const permissionSetId = matches[0];
|
|
101
101
|
// 查找permissionSetId对应的permissionSet
|
|
102
|
-
const permissionSetDoc = await objectql.getObject('permission_set').
|
|
102
|
+
const permissionSetDoc = (await objectql.getObject('permission_set').directFind({
|
|
103
|
+
filters: [
|
|
104
|
+
['_id', '=', permissionSetId],
|
|
105
|
+
]
|
|
106
|
+
})[0]);
|
|
103
107
|
if (permissionSetDoc) {
|
|
104
108
|
// 替换this.query.filters中全部的的permission_set_id为permissionSetDoc.name
|
|
105
109
|
this.query.filters = this.query.filters.replace(regex, permissionSetDoc.name).replace(`permission_set_id eq '${permissionSetDoc.name}'`, `(permission_set_id eq '${permissionSetDoc.name}') or (permission_set_id eq '${permissionSetId}')`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steedos/standard-permission",
|
|
3
|
-
"version": "2.5.0-beta.
|
|
3
|
+
"version": "2.5.0-beta.19",
|
|
4
4
|
"main": "package.service.js",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -12,5 +12,5 @@
|
|
|
12
12
|
"description": "steedos package",
|
|
13
13
|
"repository": {},
|
|
14
14
|
"license": "MIT",
|
|
15
|
-
"gitHead": "
|
|
15
|
+
"gitHead": "99f85803376a6096f0262ff47689572818bf655b"
|
|
16
16
|
}
|