@tachybase/module-user 1.3.25 → 1.5.0

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.
@@ -0,0 +1,232 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var add_user_status_fields_exports = {};
19
+ __export(add_user_status_fields_exports, {
20
+ default: () => AddUserStatusFieldsMigration
21
+ });
22
+ module.exports = __toCommonJS(add_user_status_fields_exports);
23
+ var import_server = require("@tego/server");
24
+ class AddUserStatusFieldsMigration extends import_server.Migration {
25
+ constructor() {
26
+ super(...arguments);
27
+ this.appVersion = "<1.4.0";
28
+ }
29
+ async up() {
30
+ const Field = this.context.db.getRepository("fields");
31
+ const statusFieldExists = await Field.count({
32
+ filter: {
33
+ name: "status",
34
+ collectionName: "users"
35
+ }
36
+ });
37
+ if (!statusFieldExists) {
38
+ await Field.create({
39
+ values: {
40
+ name: "status",
41
+ collectionName: "users",
42
+ type: "string",
43
+ defaultValue: "active",
44
+ comment: "\u7528\u6237\u72B6\u6001\uFF1Aactive-\u6B63\u5E38, pending-\u5F85\u5BA1\u6838, locked-\u9501\u5B9A, disabled-\u505C\u7528",
45
+ uiSchema: {
46
+ type: "string",
47
+ title: '{{t("Status")}}',
48
+ "x-component": "Select",
49
+ "x-component-props": {
50
+ fieldNames: {
51
+ label: "title",
52
+ value: "key"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ });
58
+ }
59
+ const statusExpireAtFieldExists = await Field.count({
60
+ filter: {
61
+ name: "statusExpireAt",
62
+ collectionName: "users"
63
+ }
64
+ });
65
+ if (!statusExpireAtFieldExists) {
66
+ await Field.create({
67
+ values: {
68
+ name: "statusExpireAt",
69
+ collectionName: "users",
70
+ type: "date",
71
+ comment: "\u72B6\u6001\u8FC7\u671F\u65F6\u95F4\uFF0Cnull\u8868\u793A\u6C38\u4E45",
72
+ uiSchema: {
73
+ type: "string",
74
+ title: '{{t("Status Expire At")}}',
75
+ "x-component": "DatePicker",
76
+ "x-component-props": {
77
+ showTime: true
78
+ }
79
+ }
80
+ }
81
+ });
82
+ }
83
+ const previousStatusFieldExists = await Field.count({
84
+ filter: {
85
+ name: "previousStatus",
86
+ collectionName: "users"
87
+ }
88
+ });
89
+ if (!previousStatusFieldExists) {
90
+ await Field.create({
91
+ values: {
92
+ name: "previousStatus",
93
+ collectionName: "users",
94
+ type: "string",
95
+ comment: "\u539F\u72B6\u6001\uFF0C\u7528\u4E8E\u72B6\u6001\u8FC7\u671F\u540E\u81EA\u52A8\u6062\u590D",
96
+ uiSchema: {
97
+ type: "string",
98
+ title: '{{t("Previous Status")}}',
99
+ "x-component": "Select",
100
+ "x-component-props": {
101
+ fieldNames: {
102
+ label: "title",
103
+ value: "key"
104
+ }
105
+ }
106
+ }
107
+ }
108
+ });
109
+ }
110
+ const statusReasonFieldExists = await Field.count({
111
+ filter: {
112
+ name: "statusReason",
113
+ collectionName: "users"
114
+ }
115
+ });
116
+ if (!statusReasonFieldExists) {
117
+ await Field.create({
118
+ values: {
119
+ name: "statusReason",
120
+ collectionName: "users",
121
+ type: "text",
122
+ comment: "\u72B6\u6001\u53D8\u66F4\u539F\u56E0\u8BF4\u660E",
123
+ uiSchema: {
124
+ type: "string",
125
+ title: '{{t("Status Reason")}}',
126
+ "x-component": "Input.TextArea"
127
+ }
128
+ }
129
+ });
130
+ }
131
+ const statusInfoFieldExists = await Field.count({
132
+ filter: {
133
+ name: "statusInfo",
134
+ collectionName: "users"
135
+ }
136
+ });
137
+ if (!statusInfoFieldExists) {
138
+ await Field.create({
139
+ values: {
140
+ name: "statusInfo",
141
+ collectionName: "users",
142
+ type: "belongsTo",
143
+ target: "userStatuses",
144
+ foreignKey: "status",
145
+ targetKey: "key",
146
+ uiSchema: {
147
+ type: "object",
148
+ title: '{{t("Status")}}',
149
+ "x-component": "AssociationField",
150
+ "x-component-props": {
151
+ fieldNames: {
152
+ label: "title",
153
+ value: "key"
154
+ }
155
+ }
156
+ }
157
+ }
158
+ });
159
+ }
160
+ const previousStatusInfoFieldExists = await Field.count({
161
+ filter: {
162
+ name: "previousStatusInfo",
163
+ collectionName: "users"
164
+ }
165
+ });
166
+ if (!previousStatusInfoFieldExists) {
167
+ await Field.create({
168
+ values: {
169
+ name: "previousStatusInfo",
170
+ collectionName: "users",
171
+ type: "belongsTo",
172
+ target: "userStatuses",
173
+ foreignKey: "previousStatus",
174
+ targetKey: "key",
175
+ uiSchema: {
176
+ type: "object",
177
+ title: '{{t("Previous Status")}}',
178
+ "x-component": "AssociationField",
179
+ "x-component-props": {
180
+ fieldNames: {
181
+ label: "title",
182
+ value: "key"
183
+ }
184
+ }
185
+ }
186
+ }
187
+ });
188
+ }
189
+ const statusHistoriesFieldExists = await Field.count({
190
+ filter: {
191
+ name: "statusHistories",
192
+ collectionName: "users"
193
+ }
194
+ });
195
+ if (!statusHistoriesFieldExists) {
196
+ await Field.create({
197
+ values: {
198
+ name: "statusHistories",
199
+ collectionName: "users",
200
+ type: "hasMany",
201
+ target: "userStatusHistories",
202
+ foreignKey: "userId",
203
+ uiSchema: {
204
+ type: "array",
205
+ title: '{{t("Status History")}}',
206
+ "x-component": "AssociationField"
207
+ }
208
+ }
209
+ });
210
+ }
211
+ }
212
+ async down() {
213
+ const Field = this.context.db.getRepository("fields");
214
+ const fieldsToRemove = [
215
+ "status",
216
+ "statusExpireAt",
217
+ "previousStatus",
218
+ "statusReason",
219
+ "statusInfo",
220
+ "previousStatusInfo",
221
+ "statusHistories"
222
+ ];
223
+ for (const fieldName of fieldsToRemove) {
224
+ await Field.destroy({
225
+ filter: {
226
+ name: fieldName,
227
+ collectionName: "users"
228
+ }
229
+ });
230
+ }
231
+ }
232
+ }
@@ -9,4 +9,8 @@ export default class PluginUsersServer extends Plugin {
9
9
  rootUsername: any;
10
10
  };
11
11
  install(options: any): Promise<void>;
12
+ /**
13
+ * 初始化系统内置状态
14
+ */
15
+ initSystemStatuses(): Promise<void>;
12
16
  }
@@ -139,6 +139,48 @@ class PluginUsersServer extends import_server.Plugin {
139
139
  name: `pm.${this.name}.*`,
140
140
  actions: ["users:listExcludeRole", "users:list"]
141
141
  });
142
+ this.app.acl.registerSnippet({
143
+ name: `pm.users.statuses`,
144
+ actions: ["userStatuses:*", "userStatusHistories:*"]
145
+ });
146
+ this.app.acl.addFixedParams("userStatuses", "destroy", () => {
147
+ return {
148
+ filter: {
149
+ "isSystemDefined.$ne": true
150
+ }
151
+ };
152
+ });
153
+ this.app.acl.addFixedParams("userStatuses", "update", () => {
154
+ return {
155
+ filter: {
156
+ "isSystemDefined.$ne": true
157
+ }
158
+ };
159
+ });
160
+ this.app.acl.addFixedParams("userStatusHistories", "destroy", () => {
161
+ return {
162
+ filter: {
163
+ id: -1
164
+ // 永远不匹配任何记录
165
+ }
166
+ };
167
+ });
168
+ this.app.acl.addFixedParams("userStatusHistories", "update", () => {
169
+ return {
170
+ filter: {
171
+ id: -1
172
+ // 永远不匹配任何记录
173
+ }
174
+ };
175
+ });
176
+ this.app.acl.addFixedParams("userStatusHistories", "create", () => {
177
+ return {
178
+ filter: {
179
+ id: -1
180
+ // 永远不匹配任何记录
181
+ }
182
+ };
183
+ });
142
184
  }
143
185
  async load() {
144
186
  await this.importCollections((0, import_node_path.resolve)(__dirname, "collections"));
@@ -152,6 +194,9 @@ class PluginUsersServer extends import_server.Plugin {
152
194
  if (!import_node_worker_threads.isMainThread) {
153
195
  return;
154
196
  }
197
+ this.app.on("afterLoad", async () => {
198
+ await this.initSystemStatuses();
199
+ });
155
200
  this.app.resourcer.use(
156
201
  async (ctx, next) => {
157
202
  await next();
@@ -220,4 +265,67 @@ class PluginUsersServer extends import_server.Plugin {
220
265
  await repo.db2cm("users");
221
266
  }
222
267
  }
268
+ /**
269
+ * 初始化系统内置状态
270
+ */
271
+ async initSystemStatuses() {
272
+ const systemStatuses = [
273
+ {
274
+ key: "active",
275
+ title: '{{t("Active")}}',
276
+ color: "green",
277
+ allowLogin: true,
278
+ loginErrorMessage: null,
279
+ isSystemDefined: true,
280
+ packageName: "@tachybase/module-user",
281
+ description: '{{t("Normal active user")}}',
282
+ sort: 1,
283
+ config: {}
284
+ },
285
+ {
286
+ key: "pending",
287
+ title: '{{t("Pending")}}',
288
+ color: "orange",
289
+ allowLogin: false,
290
+ loginErrorMessage: '{{t("Your account is under review, please wait for administrator approval")}}',
291
+ isSystemDefined: true,
292
+ packageName: "@tachybase/module-user",
293
+ description: '{{t("User waiting for approval")}}',
294
+ sort: 2,
295
+ config: {}
296
+ },
297
+ {
298
+ key: "disabled",
299
+ title: '{{t("Disabled")}}',
300
+ color: "gray",
301
+ allowLogin: false,
302
+ loginErrorMessage: '{{t("Your account has been disabled, please contact administrator if you have any questions")}}',
303
+ isSystemDefined: true,
304
+ packageName: "@tachybase/module-user",
305
+ description: '{{t("Manually disabled by administrator")}}',
306
+ sort: 3,
307
+ config: {}
308
+ }
309
+ ];
310
+ const statusRepo = this.db.getRepository("userStatuses");
311
+ if (!statusRepo) {
312
+ this.app.logger.warn("userStatuses repository not found");
313
+ return;
314
+ }
315
+ for (const status of systemStatuses) {
316
+ try {
317
+ const existing = await statusRepo.findOne({
318
+ filter: { key: status.key }
319
+ });
320
+ if (!existing) {
321
+ await statusRepo.create({
322
+ values: status
323
+ });
324
+ this.app.logger.info(`Created system status: ${status.key}`);
325
+ }
326
+ } catch (error) {
327
+ this.app.logger.error(`Failed to create system status ${status.key}:`, error);
328
+ }
329
+ }
330
+ }
223
331
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tachybase/module-user",
3
3
  "displayName": "Users",
4
- "version": "1.3.25",
4
+ "version": "1.5.0",
5
5
  "description": "Provides basic user model, as well as created by and updated by fields.",
6
6
  "keywords": [
7
7
  "Users & permissions"
@@ -17,10 +17,10 @@
17
17
  "@types/jsonwebtoken": "^8.5.9",
18
18
  "antd": "5.22.5",
19
19
  "jsonwebtoken": "^8.5.1",
20
- "react-i18next": "15.2.0",
21
- "@tachybase/client": "1.3.25",
22
- "@tachybase/module-auth": "1.3.25",
23
- "@tachybase/module-acl": "1.3.25"
20
+ "react-i18next": "16.2.1",
21
+ "@tachybase/client": "1.5.0",
22
+ "@tachybase/module-acl": "1.5.0",
23
+ "@tachybase/module-auth": "1.5.0"
24
24
  },
25
25
  "description.zh-CN": "提供了基础的用户模型,以及创建人和最后更新人字段。",
26
26
  "displayName.zh-CN": "用户",