@nocobase/plugin-acl 2.2.0-beta.8 → 2.3.0-alpha.1

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.
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  module.exports = {
11
- "@nocobase/client": "2.2.0-beta.8",
11
+ "@nocobase/client": "2.3.0-alpha.1",
12
12
  "antd": "5.24.2",
13
13
  "react": "18.2.0",
14
14
  "react-i18next": "11.18.6",
@@ -17,15 +17,15 @@ module.exports = {
17
17
  "@formily/react": "2.3.7",
18
18
  "@ant-design/icons": "5.6.1",
19
19
  "lodash": "4.18.1",
20
- "@nocobase/utils": "2.2.0-beta.8",
21
- "@nocobase/flow-engine": "2.2.0-beta.8",
22
- "@nocobase/client-v2": "2.2.0-beta.8",
23
- "@nocobase/actions": "2.2.0-beta.8",
24
- "@nocobase/cache": "2.2.0-beta.8",
25
- "@nocobase/database": "2.2.0-beta.8",
26
- "@nocobase/server": "2.2.0-beta.8",
27
- "@nocobase/acl": "2.2.0-beta.8",
28
- "@nocobase/test": "2.2.0-beta.8",
20
+ "@nocobase/utils": "2.3.0-alpha.1",
21
+ "@nocobase/flow-engine": "2.3.0-alpha.1",
22
+ "@nocobase/client-v2": "2.3.0-alpha.1",
23
+ "@nocobase/actions": "2.3.0-alpha.1",
24
+ "@nocobase/cache": "2.3.0-alpha.1",
25
+ "@nocobase/database": "2.3.0-alpha.1",
26
+ "@nocobase/server": "2.3.0-alpha.1",
27
+ "@nocobase/acl": "2.3.0-alpha.1",
28
+ "@nocobase/test": "2.3.0-alpha.1",
29
29
  "@formily/core": "2.3.7",
30
30
  "@formily/antd-v5": "1.2.3",
31
31
  "antd-style": "3.7.1"
@@ -12,3 +12,4 @@ export declare const SystemRoleMode: {
12
12
  readonly onlyUseUnion: "only-use-union";
13
13
  readonly validate: (value: string) => boolean;
14
14
  };
15
+ export type SystemRoleMode = (typeof SystemRoleMode)[Exclude<keyof typeof SystemRoleMode, 'validate'>];
@@ -39,12 +39,58 @@ __export(setCurrentRole_exports, {
39
39
  setCurrentRole: () => setCurrentRole
40
40
  });
41
41
  module.exports = __toCommonJS(setCurrentRole_exports);
42
+ var import_utils = require("@nocobase/utils");
42
43
  var import_constants = require("../constants");
43
44
  var import_enum = require("../enum");
44
45
  var import_lodash = __toESM(require("lodash"));
46
+ function getCurrentUserId(currentUser) {
47
+ var _a;
48
+ return (currentUser == null ? void 0 : currentUser.id) ?? ((_a = currentUser == null ? void 0 : currentUser.get) == null ? void 0 : _a.call(currentUser, "id"));
49
+ }
50
+ async function loadCurrentUserRoles(options) {
51
+ const { cache, currentUser, mainDb } = options;
52
+ const userId = getCurrentUserId(currentUser);
53
+ if (typeof userId !== "string" && typeof userId !== "number") {
54
+ return [];
55
+ }
56
+ return cache.wrap(`roles:${userId}`, async () => {
57
+ var _a, _b, _c, _d, _e;
58
+ const repository = (_a = mainDb == null ? void 0 : mainDb.getRepository) == null ? void 0 : _a.call(mainDb, "users.roles", userId);
59
+ if (repository) {
60
+ return repository.find({
61
+ raw: true
62
+ });
63
+ }
64
+ const roleUsers = await ((_c = (_b = mainDb == null ? void 0 : mainDb.getRepository) == null ? void 0 : _b.call(mainDb, "rolesUsers")) == null ? void 0 : _c.find({
65
+ filter: {
66
+ userId
67
+ },
68
+ raw: true
69
+ }));
70
+ if (roleUsers == null ? void 0 : roleUsers.length) {
71
+ return roleUsers.map((roleUser) => ({ name: roleUser.roleName })).filter((role) => role.name);
72
+ }
73
+ if (typeof currentUser.getRoles === "function") {
74
+ return currentUser.getRoles({ raw: true });
75
+ }
76
+ const user = await ((_e = (_d = mainDb == null ? void 0 : mainDb.getRepository) == null ? void 0 : _d.call(mainDb, "users")) == null ? void 0 : _e.findOne({
77
+ filter: {
78
+ id: userId
79
+ }
80
+ }));
81
+ if (typeof (user == null ? void 0 : user.getRoles) === "function") {
82
+ return user.getRoles({ raw: true });
83
+ }
84
+ return [];
85
+ });
86
+ }
45
87
  async function setCurrentRole(ctx, next) {
46
- var _a, _b;
47
- let currentRole = ctx.get("X-Role");
88
+ var _a, _b, _c, _d, _e, _f, _g;
89
+ const headerRole = ctx.get("X-Role");
90
+ const roleCookieName = (0, import_utils.getAuthCookieName)("role", (_a = ctx.app) == null ? void 0 : _a.name);
91
+ const cookieRole = headerRole ? null : (_b = ctx.cookies) == null ? void 0 : _b.get(roleCookieName);
92
+ let currentRole = headerRole || cookieRole;
93
+ const currentRoleFromCookie = !!cookieRole && !headerRole;
48
94
  if (currentRole === "anonymous") {
49
95
  ctx.state.currentRole = currentRole;
50
96
  return next();
@@ -54,13 +100,12 @@ async function setCurrentRole(ctx, next) {
54
100
  }
55
101
  const attachRoles = ctx.state.attachRoles || [];
56
102
  const cache = ctx.cache;
57
- const repository = ctx.db.getRepository("users.roles", ctx.state.currentUser.id);
58
- const roles = await cache.wrap(
59
- `roles:${ctx.state.currentUser.id}`,
60
- () => repository.find({
61
- raw: true
62
- })
63
- );
103
+ const mainDb = ((_c = ctx.app) == null ? void 0 : _c.db) || ctx.db;
104
+ const roles = await loadCurrentUserRoles({
105
+ cache,
106
+ mainDb,
107
+ currentUser: ctx.state.currentUser
108
+ });
64
109
  if (!roles.length && !attachRoles.length) {
65
110
  ctx.state.currentRole = void 0;
66
111
  return ctx.throw(401, {
@@ -73,10 +118,11 @@ async function setCurrentRole(ctx, next) {
73
118
  roles.forEach((role2) => rolesMap.set(role2.name, role2));
74
119
  const userRoles = Array.from(rolesMap.values());
75
120
  ctx.state.currentUser.roles = userRoles;
76
- const systemSettings = await cache.wrap(
121
+ const systemSettingsRepository = mainDb == null ? void 0 : mainDb.getRepository("systemSettings");
122
+ const systemSettings = systemSettingsRepository ? await cache.wrap(
77
123
  `app:systemSettings`,
78
- () => ctx.db.getRepository("systemSettings").findOne({ raw: true })
79
- );
124
+ () => systemSettingsRepository.findOne({ raw: true })
125
+ ) : void 0;
80
126
  const roleMode = (systemSettings == null ? void 0 : systemSettings.roleMode) || import_enum.SystemRoleMode.default;
81
127
  if ([currentRole, ctx.state.currentRole].includes(import_constants.UNION_ROLE_KEY) && roleMode === import_enum.SystemRoleMode.default) {
82
128
  currentRole = userRoles[0].name;
@@ -95,26 +141,34 @@ async function setCurrentRole(ctx, next) {
95
141
  }
96
142
  let role;
97
143
  if (currentRole) {
98
- role = (_a = userRoles.find((role2) => role2.name === currentRole)) == null ? void 0 : _a.name;
144
+ role = (_d = userRoles.find((role2) => role2.name === currentRole)) == null ? void 0 : _d.name;
99
145
  if (!role) {
100
- return ctx.throw(401, {
101
- code: "ROLE_NOT_FOUND_FOR_USER",
102
- message: ctx.t("The role does not belong to the user", { ns: "acl" })
103
- });
146
+ if (currentRoleFromCookie) {
147
+ (_e = ctx.cookies) == null ? void 0 : _e.set(roleCookieName, null, (0, import_utils.getAuthCookieOptions)(ctx, false));
148
+ currentRole = void 0;
149
+ } else {
150
+ return ctx.throw(401, {
151
+ code: "ROLE_NOT_FOUND_FOR_USER",
152
+ message: ctx.t("The role does not belong to the user", { ns: "acl" })
153
+ });
154
+ }
104
155
  }
105
156
  }
106
157
  if (!role) {
107
158
  const defaultRoleModel = await cache.wrapWithCondition(
108
159
  `roles:${ctx.state.currentUser.id}:defaultRole`,
109
- () => ctx.db.getRepository("rolesUsers").findOne({ where: { userId: ctx.state.currentUser.id, default: true } }),
160
+ () => mainDb.getRepository("rolesUsers").findOne({ where: { userId: ctx.state.currentUser.id, default: true } }),
110
161
  {
111
162
  isCacheable: (x) => !import_lodash.default.isEmpty(x)
112
163
  }
113
164
  );
114
- role = (defaultRoleModel == null ? void 0 : defaultRoleModel.roleName) || ((_b = userRoles[0]) == null ? void 0 : _b.name);
165
+ role = (defaultRoleModel == null ? void 0 : defaultRoleModel.roleName) || ((_f = userRoles[0]) == null ? void 0 : _f.name);
115
166
  }
116
167
  ctx.state.currentRole = role;
117
168
  ctx.state.currentRoles = role === import_constants.UNION_ROLE_KEY ? userRoles.map((role2) => role2.name) : [role];
169
+ if (currentRoleFromCookie && role) {
170
+ (_g = ctx.cookies) == null ? void 0 : _g.set(roleCookieName, role, (0, import_utils.getAuthCookieOptions)(ctx, false));
171
+ }
118
172
  if (!ctx.state.currentRoles.length) {
119
173
  return ctx.throw(401, {
120
174
  code: "ROLE_NOT_FOUND_ERR",
@@ -450,7 +450,7 @@ class PluginACLServer extends import_server.Plugin {
450
450
  this.app.on("cache:del:roles", ({ userId }) => {
451
451
  this.app.cache.del(`roles:${userId}`);
452
452
  });
453
- this.app.resourcer.use(import_setCurrentRole.setCurrentRole, { tag: "setCurrentRole", before: "acl", after: "auth" });
453
+ this.app.resourceManager.use(import_setCurrentRole.setCurrentRole, { tag: "setCurrentRole", before: "acl", after: "auth" });
454
454
  this.app.acl.allow("users", "setDefaultRole", "loggedIn");
455
455
  this.app.acl.allow("roles", "check", "loggedIn");
456
456
  this.app.acl.allow("*", "*", (ctx) => {
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Based on roles, resources, and actions, access control can precisely manage interface configuration permissions, data operation permissions, menu access permissions, and plugin permissions.",
7
7
  "description.ru-RU": "На основе ролей, ресурсов и действий система контроля доступа может точно управлять разрешениями на изменение интерфейса, работу с данными, доступ к меню и разрешениями для подключаемых модулей.",
8
8
  "description.zh-CN": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。",
9
- "version": "2.2.0-beta.8",
9
+ "version": "2.3.0-alpha.1",
10
10
  "license": "Apache-2.0",
11
11
  "main": "./dist/server/index.js",
12
12
  "homepage": "https://docs.nocobase.com/handbook/acl",
@@ -46,5 +46,5 @@
46
46
  "url": "git+https://github.com/nocobase/nocobase.git",
47
47
  "directory": "packages/plugins/acl"
48
48
  },
49
- "gitHead": "fa2502c1e9faf6d74b3f51b42dbc6546638d46af"
49
+ "gitHead": "2377df8ceb12549149017f7f14a61207bf6e49a2"
50
50
  }