@tachybase/module-acl 1.6.21 → 1.6.22
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.
package/dist/externalVersion.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
"react": "18.3.1",
|
|
3
|
-
"@tachybase/client": "1.6.
|
|
4
|
-
"@tachybase/schema": "1.6.
|
|
3
|
+
"@tachybase/client": "1.6.22",
|
|
4
|
+
"@tachybase/schema": "1.6.13",
|
|
5
5
|
"antd": "5.22.5",
|
|
6
6
|
"@ant-design/icons": "6.1.0",
|
|
7
7
|
"react-i18next": "16.2.1",
|
|
8
|
-
"@tego/client": "1.6.
|
|
9
|
-
"@tego/server": "1.6.
|
|
8
|
+
"@tego/client": "1.6.13",
|
|
9
|
+
"@tego/server": "1.6.13",
|
|
10
10
|
"async-mutex": "0.5.0",
|
|
11
11
|
"lodash": "4.17.21",
|
|
12
|
-
"@tachybase/test": "1.6.
|
|
12
|
+
"@tachybase/test": "1.6.13",
|
|
13
13
|
"ahooks": "3.9.0"
|
|
14
14
|
};
|
|
@@ -33,12 +33,32 @@ async function setCurrentRole(ctx, next) {
|
|
|
33
33
|
const attachRoles = ctx.state.attachRoles || [];
|
|
34
34
|
const cache = ctx.cache;
|
|
35
35
|
const repository = ctx.db.getRepository("users.roles", ctx.state.currentUser.id);
|
|
36
|
-
const roles = await cache.wrap(
|
|
37
|
-
|
|
38
|
-
() => repository.find({
|
|
36
|
+
const roles = await cache.wrap(`roles:${ctx.state.currentUser.id}`, async () => {
|
|
37
|
+
const userRoles2 = await repository.find({
|
|
39
38
|
raw: true
|
|
40
|
-
})
|
|
41
|
-
|
|
39
|
+
});
|
|
40
|
+
const rolesUsers = await ctx.db.getRepository("rolesUsers").find({
|
|
41
|
+
filter: {
|
|
42
|
+
userId: ctx.state.currentUser.id
|
|
43
|
+
},
|
|
44
|
+
raw: true
|
|
45
|
+
});
|
|
46
|
+
const rolesUsersMap = new Map(
|
|
47
|
+
rolesUsers.map((roleUser) => {
|
|
48
|
+
var _a2;
|
|
49
|
+
const item = ((_a2 = roleUser == null ? void 0 : roleUser.toJSON) == null ? void 0 : _a2.call(roleUser)) || roleUser;
|
|
50
|
+
return [item.roleName, item];
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
return userRoles2.map((role) => {
|
|
54
|
+
var _a2;
|
|
55
|
+
const item = ((_a2 = role == null ? void 0 : role.toJSON) == null ? void 0 : _a2.call(role)) || role;
|
|
56
|
+
return {
|
|
57
|
+
...item,
|
|
58
|
+
rolesUsers: rolesUsersMap.get(item.name)
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
});
|
|
42
62
|
if (!roles.length && !attachRoles.length) {
|
|
43
63
|
ctx.state.currentRole = void 0;
|
|
44
64
|
return ctx.throw(401, {
|
|
@@ -32,9 +32,21 @@ __export(with_acl_meta_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(with_acl_meta_exports);
|
|
33
33
|
var import_server = require("@tego/server");
|
|
34
34
|
var import_lodash = __toESM(require("lodash"));
|
|
35
|
+
function escapeRegExp(value) {
|
|
36
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
37
|
+
}
|
|
38
|
+
function createAssociationMatcher(association) {
|
|
39
|
+
const parts = association.split(".").filter(Boolean);
|
|
40
|
+
if (!parts.length) {
|
|
41
|
+
return () => false;
|
|
42
|
+
}
|
|
43
|
+
const quotedAssociation = parts.map((part) => `"?${escapeRegExp(part)}"?`).join(String.raw`\s*(?:\.|->)\s*"?`);
|
|
44
|
+
const associationPattern = new RegExp(`(^|[^A-Za-z0-9_])${quotedAssociation}(?=\\s*(?:\\.|->)|[^A-Za-z0-9_]|$)`);
|
|
45
|
+
return (whereCase) => associationPattern.test(whereCase);
|
|
46
|
+
}
|
|
35
47
|
function createWithACLMetaMiddleware() {
|
|
36
48
|
return async (ctx, next) => {
|
|
37
|
-
var _a, _b, _c;
|
|
49
|
+
var _a, _b, _c, _d, _e;
|
|
38
50
|
await next();
|
|
39
51
|
const dataSourceKey = ctx.get("x-data-source");
|
|
40
52
|
const dataSource = ctx.tego.dataSourceManager.dataSources.get(dataSourceKey);
|
|
@@ -81,7 +93,12 @@ function createWithACLMetaMiddleware() {
|
|
|
81
93
|
params: {},
|
|
82
94
|
resourceName: ctx.action.resourceName,
|
|
83
95
|
resourceOf: ctx.action.resourceOf,
|
|
84
|
-
mergeParams() {
|
|
96
|
+
mergeParams(params) {
|
|
97
|
+
this.params = import_lodash.default.mergeWith({}, this.params, params, (value, srcValue) => {
|
|
98
|
+
if (Array.isArray(value) && Array.isArray(srcValue)) {
|
|
99
|
+
return srcValue;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
85
102
|
}
|
|
86
103
|
},
|
|
87
104
|
state: {
|
|
@@ -141,7 +158,7 @@ function createWithACLMetaMiddleware() {
|
|
|
141
158
|
...params,
|
|
142
159
|
context: actionCtx
|
|
143
160
|
});
|
|
144
|
-
const actionSql =
|
|
161
|
+
const actionSql = db.sequelize.queryInterface.queryGenerator.selectQuery(
|
|
145
162
|
Model.getTableName(),
|
|
146
163
|
{
|
|
147
164
|
where: (() => {
|
|
@@ -193,7 +210,10 @@ function createWithACLMetaMiddleware() {
|
|
|
193
210
|
},
|
|
194
211
|
Model
|
|
195
212
|
);
|
|
196
|
-
const whereCase = actionSql.match(
|
|
213
|
+
const whereCase = (_e = (_d = actionSql.match(/\bWHERE\s+([\s\S]*)$/i)) == null ? void 0 : _d[1]) == null ? void 0 : _e.replace(/;\s*$/, "");
|
|
214
|
+
if (!whereCase) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
197
217
|
conditions.push({
|
|
198
218
|
whereCase,
|
|
199
219
|
action,
|
|
@@ -203,18 +223,21 @@ function createWithACLMetaMiddleware() {
|
|
|
203
223
|
let include = conditions.map((condition) => condition.include).flat();
|
|
204
224
|
const whereCases = conditions.map((condition) => condition.whereCase);
|
|
205
225
|
include = include.filter((inc) => {
|
|
206
|
-
|
|
207
|
-
return
|
|
208
|
-
}
|
|
226
|
+
if (!(inc == null ? void 0 : inc.association)) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
const matchesAssociation = createAssociationMatcher(inc.association);
|
|
230
|
+
return whereCases.some((whereCase) => matchesAssociation(whereCase));
|
|
209
231
|
});
|
|
210
232
|
const results = await collection.model.findAll({
|
|
211
233
|
where: {
|
|
212
234
|
[primaryKeyField]: ids
|
|
213
235
|
},
|
|
236
|
+
raw: true,
|
|
214
237
|
attributes: [
|
|
215
238
|
primaryKeyField,
|
|
216
239
|
...conditions.map((condition) => {
|
|
217
|
-
return [
|
|
240
|
+
return [db.sequelize.literal(`CASE WHEN ${condition.whereCase} THEN 1 ELSE 0 END`), condition.action];
|
|
218
241
|
})
|
|
219
242
|
],
|
|
220
243
|
include
|
|
@@ -223,7 +246,10 @@ function createWithACLMetaMiddleware() {
|
|
|
223
246
|
if (allAllowed.includes(action)) {
|
|
224
247
|
return [action, ids];
|
|
225
248
|
}
|
|
226
|
-
return [
|
|
249
|
+
return [
|
|
250
|
+
action,
|
|
251
|
+
Array.from(new Set(results.filter((item) => Boolean(item[action])).map((item) => item[primaryKeyField])))
|
|
252
|
+
];
|
|
227
253
|
}).reduce((acc, [action, ids2]) => {
|
|
228
254
|
acc[action] = ids2;
|
|
229
255
|
return acc;
|
package/dist/server/server.js
CHANGED
|
@@ -211,7 +211,8 @@ class PluginACL extends import_server.Plugin {
|
|
|
211
211
|
await this.app.db.getRepository("dataSourcesRoles").updateOrCreate({
|
|
212
212
|
values: {
|
|
213
213
|
roleName: model.get("name"),
|
|
214
|
-
dataSourceKey: "main"
|
|
214
|
+
dataSourceKey: "main",
|
|
215
|
+
strategy: model.get("strategy")
|
|
215
216
|
},
|
|
216
217
|
filterKeys: ["roleName", "dataSourceKey"],
|
|
217
218
|
transaction
|
|
@@ -248,14 +249,26 @@ class PluginACL extends import_server.Plugin {
|
|
|
248
249
|
await this.writeResourceToACL(resource, transaction);
|
|
249
250
|
});
|
|
250
251
|
this.app.db.on("collections.afterDestroy", async (model, options) => {
|
|
252
|
+
var _a;
|
|
251
253
|
const { transaction } = options;
|
|
254
|
+
const resourceName = model.get("name");
|
|
252
255
|
await this.app.db.getRepository("dataSourcesRolesResources").destroy({
|
|
253
256
|
filter: {
|
|
254
|
-
name:
|
|
257
|
+
name: resourceName,
|
|
255
258
|
dataSourceKey: "main"
|
|
256
259
|
},
|
|
257
260
|
transaction
|
|
258
261
|
});
|
|
262
|
+
const aclRoles = (_a = this.acl) == null ? void 0 : _a.roles;
|
|
263
|
+
if (!aclRoles || typeof aclRoles.values !== "function") {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
for (const role of aclRoles.values()) {
|
|
267
|
+
if (!role || typeof role.revokeResource !== "function") {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
role.revokeResource(resourceName);
|
|
271
|
+
}
|
|
259
272
|
});
|
|
260
273
|
this.app.db.on("fields.afterCreate", async (model, options) => {
|
|
261
274
|
const { transaction } = options;
|
|
@@ -330,7 +343,7 @@ class PluginACL extends import_server.Plugin {
|
|
|
330
343
|
});
|
|
331
344
|
}
|
|
332
345
|
this.app.on("afterInstallPlugin", async (plugin) => {
|
|
333
|
-
if (plugin.getName()
|
|
346
|
+
if (!["user", "users"].includes(plugin.getName())) {
|
|
334
347
|
return;
|
|
335
348
|
}
|
|
336
349
|
const User = this.db.getCollection("users");
|
|
@@ -355,7 +368,7 @@ class PluginACL extends import_server.Plugin {
|
|
|
355
368
|
});
|
|
356
369
|
});
|
|
357
370
|
this.app.on("beforeInstallPlugin", async (plugin) => {
|
|
358
|
-
if (plugin.getName()
|
|
371
|
+
if (!["user", "users"].includes(plugin.getName())) {
|
|
359
372
|
return;
|
|
360
373
|
}
|
|
361
374
|
const roles = this.app.db.getRepository("roles");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tachybase/module-acl",
|
|
3
3
|
"displayName": "Access control",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.22",
|
|
5
5
|
"description": "Based on roles, resources, and actions, access control can precisely manage interface configuration permissions, data operation permissions, menu access permissions, and plugin permissions.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"Users & permissions"
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"dependencies": {},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@ant-design/icons": "^6.1.0",
|
|
23
|
-
"@tachybase/schema": "1.6.
|
|
24
|
-
"@tachybase/test": "1.6.
|
|
25
|
-
"@tego/client": "1.6.
|
|
26
|
-
"@tego/server": "1.6.
|
|
23
|
+
"@tachybase/schema": "1.6.13",
|
|
24
|
+
"@tachybase/test": "1.6.13",
|
|
25
|
+
"@tego/client": "1.6.13",
|
|
26
|
+
"@tego/server": "1.6.13",
|
|
27
27
|
"@types/jsonwebtoken": "^8.5.9",
|
|
28
28
|
"ahooks": "^3.9.0",
|
|
29
29
|
"antd": "5.22.5",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"react": "18.3.1",
|
|
34
34
|
"react-dom": "18.3.1",
|
|
35
35
|
"react-i18next": "16.2.1",
|
|
36
|
-
"@tachybase/client": "1.6.
|
|
36
|
+
"@tachybase/client": "1.6.22"
|
|
37
37
|
},
|
|
38
38
|
"description.zh-CN": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。",
|
|
39
39
|
"displayName.zh-CN": "权限控制",
|