@tachybase/module-auth 0.23.48 → 1.0.6

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.
Files changed (35) hide show
  1. package/dist/client/index.js +5 -5
  2. package/dist/client/interceptors.d.ts +5 -0
  3. package/dist/client/locale/index.d.ts +1 -0
  4. package/dist/client/settings/token-policy/components.d.ts +7 -0
  5. package/dist/client/settings/token-policy/hooks.d.ts +16 -0
  6. package/dist/client/settings/token-policy/index.d.ts +1 -0
  7. package/dist/constants.d.ts +5 -0
  8. package/dist/constants.js +39 -0
  9. package/dist/externalVersion.js +12 -9
  10. package/dist/locale/en-US.json +23 -1
  11. package/dist/locale/zh-CN.json +22 -1
  12. package/dist/node_modules/cron/package.json +1 -1
  13. package/dist/node_modules/ms/index.js +1 -0
  14. package/dist/node_modules/ms/package.json +1 -0
  15. package/dist/server/basic-auth.js +3 -3
  16. package/dist/server/collections/authenticators.js +0 -8
  17. package/dist/server/collections/issued-tokens.d.ts +2 -0
  18. package/dist/server/collections/issued-tokens.js +60 -0
  19. package/dist/server/collections/token-poilcy-config.d.ts +2 -0
  20. package/dist/server/collections/token-poilcy-config.js +47 -0
  21. package/dist/server/collections/users-authenticators.js +10 -1
  22. package/dist/server/locale/en-US.d.ts +1 -0
  23. package/dist/server/locale/en-US.js +2 -1
  24. package/dist/server/locale/zh-CN.d.ts +1 -0
  25. package/dist/server/locale/zh-CN.js +2 -1
  26. package/dist/server/migrations/20250318163707-create-token-policy.d.ts +6 -0
  27. package/dist/server/migrations/20250318163707-create-token-policy.js +52 -0
  28. package/dist/server/plugin.js +136 -27
  29. package/dist/server/storer.d.ts +8 -2
  30. package/dist/server/storer.js +26 -3
  31. package/dist/server/token-controller.d.ts +32 -0
  32. package/dist/server/token-controller.js +139 -0
  33. package/dist/types.d.ts +1 -0
  34. package/dist/types.js +15 -0
  35. package/package.json +15 -11
@@ -36,7 +36,6 @@ var users_authenticators_default = (0, import_database.defineCollection)({
36
36
  name: "id",
37
37
  type: "bigInt",
38
38
  autoIncrement: true,
39
- primaryKey: true,
40
39
  allowNull: false
41
40
  },
42
41
  /**
@@ -87,6 +86,16 @@ var users_authenticators_default = (0, import_database.defineCollection)({
87
86
  type: "json",
88
87
  name: "meta",
89
88
  defaultValue: {}
89
+ },
90
+ {
91
+ type: "bigInt",
92
+ name: "userId",
93
+ primaryKey: true
94
+ },
95
+ {
96
+ type: "string",
97
+ name: "authenticator",
98
+ primaryKey: true
90
99
  }
91
100
  ]
92
101
  });
@@ -5,5 +5,6 @@ declare const _default: {
5
5
  'Not a valid cellphone number, please re-enter': string;
6
6
  'The phone number has been registered, please login directly': string;
7
7
  'The phone number is not registered, please register first': string;
8
+ 'The username, email or password is incorrect, please re-enter': string;
8
9
  };
9
10
  export default _default;
@@ -26,5 +26,6 @@ var en_US_default = {
26
26
  "The password is incorrect, please re-enter": "The password is incorrect, please re-enter",
27
27
  "Not a valid cellphone number, please re-enter": "Not a valid cellphone number, please re-enter",
28
28
  "The phone number has been registered, please login directly": "The phone number has been registered, please login directly",
29
- "The phone number is not registered, please register first": "The phone number is not registered, please register first"
29
+ "The phone number is not registered, please register first": "The phone number is not registered, please register first",
30
+ "The username, email or password is incorrect, please re-enter": "The username, email or password is incorrect, please re-enter"
30
31
  };
@@ -7,5 +7,6 @@ declare const _default: {
7
7
  'Please keep and enable at least one authenticator': string;
8
8
  'Please enter your username or email': string;
9
9
  'Please enter a valid username': string;
10
+ 'The username, email or password is incorrect, please re-enter': string;
10
11
  };
11
12
  export default _default;
@@ -28,5 +28,6 @@ var zh_CN_default = {
28
28
  "The phone number is not registered, please register first": "\u624B\u673A\u53F7\u672A\u6CE8\u518C\uFF0C\u8BF7\u5148\u6CE8\u518C",
29
29
  "Please keep and enable at least one authenticator": "\u8BF7\u81F3\u5C11\u4FDD\u7559\u5E76\u542F\u7528\u4E00\u4E2A\u8BA4\u8BC1\u5668",
30
30
  "Please enter your username or email": "\u8BF7\u8F93\u5165\u7528\u6237\u540D\u6216\u90AE\u7BB1",
31
- "Please enter a valid username": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7528\u6237\u540D"
31
+ "Please enter a valid username": "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7528\u6237\u540D",
32
+ "The username, email or password is incorrect, please re-enter": "\u7528\u6237\u540D\u90AE\u7BB1\u6216\u8005\u5BC6\u7801\u6709\u8BEF,\u8BF7\u91CD\u65B0\u8F93\u5165"
32
33
  };
@@ -0,0 +1,6 @@
1
+ import { Migration } from '@tachybase/server';
2
+ export default class extends Migration {
3
+ on: string;
4
+ appVersion: string;
5
+ up(): Promise<void>;
6
+ }
@@ -0,0 +1,52 @@
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 create_token_policy_exports = {};
19
+ __export(create_token_policy_exports, {
20
+ default: () => create_token_policy_default
21
+ });
22
+ module.exports = __toCommonJS(create_token_policy_exports);
23
+ var import_server = require("@tachybase/server");
24
+ var import_constants = require("../../constants");
25
+ class create_token_policy_default extends import_server.Migration {
26
+ constructor() {
27
+ super(...arguments);
28
+ this.on = "afterLoad";
29
+ // 'beforeLoad' or 'afterLoad'
30
+ this.appVersion = "<0.23.65";
31
+ }
32
+ async up() {
33
+ const tokenPolicyRepo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
34
+ const tokenPolicy = await tokenPolicyRepo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
35
+ if (tokenPolicy) {
36
+ this.app.authManager.tokenController.setConfig(tokenPolicy.config);
37
+ } else {
38
+ const config = {
39
+ tokenExpirationTime: "1d",
40
+ sessionExpirationTime: "7d",
41
+ expiredTokenRenewLimit: "1d"
42
+ };
43
+ await tokenPolicyRepo.create({
44
+ values: {
45
+ key: import_constants.tokenPolicyRecordKey,
46
+ config
47
+ }
48
+ });
49
+ this.app.authManager.tokenController.setConfig(config);
50
+ }
51
+ }
52
+ }
@@ -31,8 +31,8 @@ __export(plugin_exports, {
31
31
  default: () => plugin_default
32
32
  });
33
33
  module.exports = __toCommonJS(plugin_exports);
34
- var import_path = require("path");
35
34
  var import_server = require("@tachybase/server");
35
+ var import_constants = require("../constants");
36
36
  var import_preset = require("../preset");
37
37
  var import_auth = __toESM(require("./actions/auth"));
38
38
  var import_authenticators = __toESM(require("./actions/authenticators"));
@@ -41,8 +41,29 @@ var import_locale = require("./locale");
41
41
  var import_authenticator = require("./model/authenticator");
42
42
  var import_storer = require("./storer");
43
43
  var import_token_blacklist = require("./token-blacklist");
44
+ var import_token_controller = require("./token-controller");
44
45
  class PluginAuthServer extends import_server.Plugin {
45
46
  afterAdd() {
47
+ this.app.on("afterLoad", async () => {
48
+ if (this.app.authManager.tokenController) {
49
+ return;
50
+ }
51
+ const cache = await this.app.cacheManager.createCache({
52
+ name: "auth-token-controller",
53
+ prefix: "auth-token-controller"
54
+ });
55
+ const tokenController = new import_token_controller.TokenController({ cache, app: this.app, logger: this.app.log });
56
+ this.app.authManager.setTokenControlService(tokenController);
57
+ const tokenPolicyRepo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
58
+ try {
59
+ const res = await tokenPolicyRepo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
60
+ if (res) {
61
+ this.app.authManager.tokenController.setConfig(res.config);
62
+ }
63
+ } catch (error) {
64
+ this.app.logger.warn("access control config not exist, use default value");
65
+ }
66
+ });
46
67
  }
47
68
  async beforeLoad() {
48
69
  this.app.i18n.addResources("zh-CN", import_preset.namespace, import_locale.zhCN);
@@ -50,22 +71,16 @@ class PluginAuthServer extends import_server.Plugin {
50
71
  this.app.db.registerModels({ AuthModel: import_authenticator.AuthModel });
51
72
  }
52
73
  async load() {
53
- await this.importCollections((0, import_path.resolve)(__dirname, "collections"));
54
- this.db.addMigrations({
55
- namespace: "auth",
56
- directory: (0, import_path.resolve)(__dirname, "migrations"),
57
- context: {
58
- plugin: this
59
- }
60
- });
61
74
  this.cache = await this.app.cacheManager.createCache({
62
75
  name: "auth",
63
76
  prefix: "auth",
64
77
  store: "memory"
65
78
  });
66
79
  const storer = new import_storer.Storer({
80
+ app: this.app,
67
81
  db: this.db,
68
- cache: this.cache
82
+ cache: this.cache,
83
+ authManager: this.app.authManager
69
84
  });
70
85
  this.app.authManager.setStorer(storer);
71
86
  if (!this.app.authManager.jwt.blacklist) {
@@ -73,7 +88,33 @@ class PluginAuthServer extends import_server.Plugin {
73
88
  }
74
89
  this.app.authManager.registerTypes(import_preset.presetAuthType, {
75
90
  auth: import_basic_auth.BasicAuth,
76
- title: "Password"
91
+ title: "Password",
92
+ getPublicOptions: (options) => {
93
+ var _a;
94
+ const usersCollection = this.db.getCollection("users");
95
+ let signupForm = ((_a = options == null ? void 0 : options.public) == null ? void 0 : _a.signupForm) || [];
96
+ signupForm = signupForm.filter((item) => item.show);
97
+ if (!(signupForm.length && signupForm.some(
98
+ (item) => ["username", "email"].includes(item.field) && item.show && item.required
99
+ ))) {
100
+ signupForm.unshift({ field: "username", show: true, required: true });
101
+ }
102
+ signupForm = signupForm.filter((field) => field.show).map((item) => {
103
+ var _a2;
104
+ const field = usersCollection.getField(item.field);
105
+ return {
106
+ ...item,
107
+ uiSchema: {
108
+ ...(_a2 = field.options) == null ? void 0 : _a2.uiSchema,
109
+ required: item.required
110
+ }
111
+ };
112
+ });
113
+ return {
114
+ ...options == null ? void 0 : options.public,
115
+ signupForm
116
+ };
117
+ }
77
118
  });
78
119
  Object.entries(import_auth.default).forEach(
79
120
  ([action, handler]) => {
@@ -84,10 +125,9 @@ class PluginAuthServer extends import_server.Plugin {
84
125
  Object.entries(import_authenticators.default).forEach(
85
126
  ([action, handler]) => this.app.resourcer.registerAction(`authenticators:${action}`, handler)
86
127
  );
87
- ["check", "signIn", "signUp"].forEach((action) => this.app.acl.allow("auth", action));
88
- ["signOut", "changePassword"].forEach((action) => this.app.acl.allow("auth", action, "loggedIn"));
128
+ ["signIn", "signUp"].forEach((action) => this.app.acl.allow("auth", action));
129
+ ["check", "signOut", "changePassword"].forEach((action) => this.app.acl.allow("auth", action, "loggedIn"));
89
130
  this.app.acl.allow("authenticators", "publicList");
90
- this.app.acl.allow("authenticators", "bindTypes", "loggedIn");
91
131
  this.app.acl.registerSnippet({
92
132
  name: `pm.${this.name}.authenticators`,
93
133
  actions: ["authenticators:*"]
@@ -100,24 +140,93 @@ class PluginAuthServer extends import_server.Plugin {
100
140
  const cache = this.app.cache;
101
141
  await cache.del(`auth:${user.id}`);
102
142
  });
143
+ this.app.on("cache:del:auth", async ({ userId }) => {
144
+ await this.cache.del(`auth:${userId}`);
145
+ });
146
+ this.app.on("ws:message:auth:token", async ({ clientId, payload }) => {
147
+ if (!payload || !payload.token || !payload.authenticator) {
148
+ this.app.emit(`ws:removeTag`, {
149
+ clientId,
150
+ tagKey: "userId"
151
+ });
152
+ return;
153
+ }
154
+ const auth = await this.app.authManager.get(payload.authenticator, {
155
+ getBearerToken: () => payload.token,
156
+ app: this.app,
157
+ db: this.app.db,
158
+ cache: this.app.cache,
159
+ logger: this.app.logger,
160
+ log: this.app.log,
161
+ throw: (...args) => {
162
+ throw new Error(...args);
163
+ },
164
+ t: this.app.i18n.t
165
+ });
166
+ let user;
167
+ try {
168
+ user = (await auth.checkToken()).user;
169
+ } catch (error) {
170
+ if (!user) {
171
+ this.app.logger.error(error);
172
+ this.app.emit(`ws:removeTag`, {
173
+ clientId,
174
+ tagKey: "userId"
175
+ });
176
+ return;
177
+ }
178
+ }
179
+ this.app.emit(`ws:setTag`, {
180
+ clientId,
181
+ tagKey: "userId",
182
+ tagValue: user.id
183
+ });
184
+ this.app.emit(`ws:authorized`, {
185
+ clientId,
186
+ userId: user.id
187
+ });
188
+ });
189
+ this.app.acl.registerSnippet({
190
+ name: `pm.security.token-policy`,
191
+ actions: [`${import_constants.tokenPolicyCollectionName}:*`]
192
+ });
193
+ this.app.db.on(`${import_constants.tokenPolicyCollectionName}.afterSave`, async (model) => {
194
+ var _a;
195
+ (_a = this.app.authManager.tokenController) == null ? void 0 : _a.setConfig(model.config);
196
+ });
103
197
  }
104
198
  async install(options) {
105
- const repository = this.db.getRepository("authenticators");
106
- const exist = await repository.findOne({ filter: { name: import_preset.presetAuthenticator } });
107
- if (exist) {
199
+ const authRepository = this.db.getRepository("authenticators");
200
+ const exist = await authRepository.findOne({ filter: { name: import_preset.presetAuthenticator } });
201
+ if (!exist) {
202
+ await authRepository.create({
203
+ values: {
204
+ name: import_preset.presetAuthenticator,
205
+ authType: import_preset.presetAuthType,
206
+ description: "Sign in with username/email.",
207
+ enabled: true,
208
+ options: {
209
+ public: {
210
+ allowSignUp: true
211
+ }
212
+ }
213
+ }
214
+ });
215
+ }
216
+ const tokenPolicyRepo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
217
+ const res = await tokenPolicyRepo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
218
+ if (res) {
108
219
  return;
109
220
  }
110
- await repository.create({
221
+ const config = {
222
+ tokenExpirationTime: "1d",
223
+ sessionExpirationTime: "7d",
224
+ expiredTokenRenewLimit: "1d"
225
+ };
226
+ await tokenPolicyRepo.create({
111
227
  values: {
112
- name: import_preset.presetAuthenticator,
113
- authType: import_preset.presetAuthType,
114
- description: "Sign in with username/email.",
115
- enabled: true,
116
- options: {
117
- public: {
118
- allowSignUp: true
119
- }
120
- }
228
+ key: import_constants.tokenPolicyRecordKey,
229
+ config
121
230
  }
122
231
  });
123
232
  }
@@ -1,15 +1,21 @@
1
- import { Storer as IStorer } from '@tachybase/auth';
1
+ import { AuthManager, Storer as IStorer } from '@tachybase/auth';
2
2
  import { Cache } from '@tachybase/cache';
3
3
  import { Database } from '@tachybase/database';
4
+ import { Application } from '@tachybase/server';
4
5
  import { AuthModel } from './model/authenticator';
5
6
  export declare class Storer implements IStorer {
6
7
  db: Database;
7
8
  cache: Cache;
9
+ app: Application;
10
+ authManager: AuthManager;
8
11
  key: string;
9
- constructor({ db, cache }: {
12
+ constructor({ app, db, cache, authManager, }: {
13
+ app?: Application;
10
14
  db: Database;
11
15
  cache: Cache;
16
+ authManager: AuthManager;
12
17
  });
18
+ renderJsonTemplate(authenticator: any): any;
13
19
  getCache(): Promise<AuthModel[]>;
14
20
  setCache(authenticators: AuthModel[]): Promise<void>;
15
21
  get(name: string): Promise<AuthModel>;
@@ -21,21 +21,43 @@ __export(storer_exports, {
21
21
  });
22
22
  module.exports = __toCommonJS(storer_exports);
23
23
  class Storer {
24
- constructor({ db, cache }) {
24
+ constructor({
25
+ app,
26
+ db,
27
+ cache,
28
+ authManager
29
+ }) {
25
30
  this.key = "authenticators";
31
+ this.app = app;
26
32
  this.db = db;
27
33
  this.cache = cache;
34
+ this.authManager = authManager;
28
35
  this.db.on("authenticators.afterSave", async (model) => {
29
36
  if (!model.enabled) {
30
37
  await this.cache.delValueInObject(this.key, model.name);
31
38
  return;
32
39
  }
33
- await this.cache.setValueInObject(this.key, model.name, model);
40
+ await this.cache.setValueInObject(this.key, model.name, this.renderJsonTemplate(model));
34
41
  });
35
42
  this.db.on("authenticators.afterDestroy", async (model) => {
36
43
  await this.cache.delValueInObject(this.key, model.name);
37
44
  });
38
45
  }
46
+ renderJsonTemplate(authenticator) {
47
+ var _a, _b;
48
+ if (!authenticator) {
49
+ return authenticator;
50
+ }
51
+ const $env = (_a = this.app) == null ? void 0 : _a.environment;
52
+ if (!$env) {
53
+ return authenticator;
54
+ }
55
+ const config = this.authManager.getAuthConfig(authenticator.authType);
56
+ authenticator.dataValues.options = $env.renderJsonTemplate(authenticator.dataValues.options, {
57
+ omit: (_b = config == null ? void 0 : config.auth) == null ? void 0 : _b["optionsKeysNotAllowedInEnv"]
58
+ });
59
+ return authenticator;
60
+ }
39
61
  async getCache() {
40
62
  const authenticators = await this.cache.get(this.key);
41
63
  if (!authenticators) {
@@ -45,7 +67,7 @@ class Storer {
45
67
  }
46
68
  async setCache(authenticators) {
47
69
  const obj = authenticators.reduce((obj2, authenticator) => {
48
- obj2[authenticator.name] = authenticator;
70
+ obj2[authenticator.name] = this.renderJsonTemplate(authenticator);
49
71
  return obj2;
50
72
  }, {});
51
73
  await this.cache.set(this.key, obj);
@@ -56,6 +78,7 @@ class Storer {
56
78
  const repo = this.db.getRepository("authenticators");
57
79
  authenticators = await repo.find({ filter: { enabled: true } });
58
80
  await this.setCache(authenticators);
81
+ authenticators = await this.getCache();
59
82
  }
60
83
  const authenticator = authenticators.find((authenticator2) => authenticator2.name === name);
61
84
  return authenticator || authenticators[0];
@@ -0,0 +1,32 @@
1
+ import { ITokenControlService, NumericTokenPolicyConfig, TokenInfo, TokenPolicyConfig } from '@tachybase/auth';
2
+ import { Cache } from '@tachybase/cache';
3
+ import Database from '@tachybase/database';
4
+ import type { SystemLogger } from '@tachybase/logger';
5
+ import Application from '@tachybase/server';
6
+ type TokenControlService = ITokenControlService;
7
+ export declare class TokenController implements TokenControlService {
8
+ cache: Cache;
9
+ app: Application;
10
+ db: Database;
11
+ logger: SystemLogger;
12
+ constructor({ cache, app, logger }: {
13
+ cache: Cache;
14
+ app: Application;
15
+ logger: SystemLogger;
16
+ });
17
+ setTokenInfo(id: string, value: TokenInfo): Promise<void>;
18
+ getConfig(): Promise<NumericTokenPolicyConfig>;
19
+ setConfig(config: TokenPolicyConfig): Promise<void>;
20
+ removeSessionExpiredTokens(userId: number): Promise<any>;
21
+ add({ userId }: {
22
+ userId: number;
23
+ }): Promise<{
24
+ jti: `${string}-${string}-${string}-${string}-${string}`;
25
+ issuedTime: number;
26
+ signInTime: number;
27
+ renewed: boolean;
28
+ userId: number;
29
+ }>;
30
+ renew: TokenControlService['renew'];
31
+ }
32
+ export {};
@@ -0,0 +1,139 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var token_controller_exports = {};
29
+ __export(token_controller_exports, {
30
+ TokenController: () => TokenController
31
+ });
32
+ module.exports = __toCommonJS(token_controller_exports);
33
+ var import_crypto = require("crypto");
34
+ var import_auth = require("@tachybase/auth");
35
+ var import_ms = __toESM(require("ms"));
36
+ var import_constants = require("../constants");
37
+ const JTICACHEKEY = "token-jti";
38
+ class TokenController {
39
+ constructor({ cache, app, logger }) {
40
+ this.renew = async (jti) => {
41
+ const repo = this.app.db.getRepository(import_constants.issuedTokensCollectionName);
42
+ const model = this.app.db.getModel(import_constants.issuedTokensCollectionName);
43
+ const newId = (0, import_crypto.randomUUID)();
44
+ const issuedTime = Date.now();
45
+ const [count] = await model.update(
46
+ { jti: newId, issuedTime },
47
+ { where: { jti } }
48
+ );
49
+ if (count === 1) {
50
+ await this.cache.set(`jti-renewed-cahce:${jti}`, { jti: newId, issuedTime }, import_constants.RENEWED_JTI_CACHE_MS);
51
+ this.logger.info("jti renewed", { oldJti: jti, newJti: newId, issuedTime });
52
+ return { jti: newId, issuedTime };
53
+ } else {
54
+ const cachedJtiData = await this.cache.get(`jti-renewed-cahce:${jti}`);
55
+ if (cachedJtiData) {
56
+ return cachedJtiData;
57
+ }
58
+ this.logger.error("jti renew failed", {
59
+ module: "auth",
60
+ submodule: "token-controller",
61
+ method: "renew",
62
+ jti,
63
+ code: import_auth.AuthErrorCode.TOKEN_RENEW_FAILED
64
+ });
65
+ throw new import_auth.AuthError({
66
+ message: "Your session has expired. Please sign in again.",
67
+ code: import_auth.AuthErrorCode.TOKEN_RENEW_FAILED
68
+ });
69
+ }
70
+ };
71
+ this.cache = cache;
72
+ this.app = app;
73
+ this.logger = logger;
74
+ }
75
+ async setTokenInfo(id, value) {
76
+ const repo = this.app.db.getRepository(import_constants.issuedTokensCollectionName);
77
+ await repo.updateOrCreate({ filterKeys: ["id"], values: value });
78
+ return;
79
+ }
80
+ getConfig() {
81
+ return this.cache.wrap("config", async () => {
82
+ const repo = this.app.db.getRepository(import_constants.tokenPolicyCollectionName);
83
+ const configRecord = await repo.findOne({ filterByTk: import_constants.tokenPolicyRecordKey });
84
+ if (!configRecord) return null;
85
+ const config = configRecord.config;
86
+ return {
87
+ tokenExpirationTime: (0, import_ms.default)(config.tokenExpirationTime),
88
+ sessionExpirationTime: (0, import_ms.default)(config.sessionExpirationTime),
89
+ expiredTokenRenewLimit: (0, import_ms.default)(config.expiredTokenRenewLimit)
90
+ };
91
+ });
92
+ }
93
+ setConfig(config) {
94
+ return this.cache.set("config", {
95
+ tokenExpirationTime: (0, import_ms.default)(config.tokenExpirationTime),
96
+ sessionExpirationTime: (0, import_ms.default)(config.sessionExpirationTime),
97
+ expiredTokenRenewLimit: (0, import_ms.default)(config.expiredTokenRenewLimit)
98
+ });
99
+ }
100
+ async removeSessionExpiredTokens(userId) {
101
+ const config = await this.getConfig();
102
+ const issuedTokenRepo = this.app.db.getRepository(import_constants.issuedTokensCollectionName);
103
+ const currTS = Date.now();
104
+ return issuedTokenRepo.destroy({
105
+ filter: {
106
+ userId,
107
+ signInTime: {
108
+ $lt: currTS - config.sessionExpirationTime
109
+ }
110
+ }
111
+ });
112
+ }
113
+ async add({ userId }) {
114
+ const jti = (0, import_crypto.randomUUID)();
115
+ const currTS = Date.now();
116
+ const data = {
117
+ jti,
118
+ issuedTime: currTS,
119
+ signInTime: currTS,
120
+ renewed: false,
121
+ userId
122
+ };
123
+ await this.setTokenInfo(jti, data);
124
+ try {
125
+ if (process.env.DB_DIALECT === "sqlite") {
126
+ await this.removeSessionExpiredTokens(userId);
127
+ } else {
128
+ this.removeSessionExpiredTokens(userId);
129
+ }
130
+ } catch (err) {
131
+ this.logger.error(err, { module: "auth", submodule: "token-controller", method: "removeSessionExpiredTokens" });
132
+ }
133
+ return data;
134
+ }
135
+ }
136
+ // Annotate the CommonJS export names for ESM import in node:
137
+ 0 && (module.exports = {
138
+ TokenController
139
+ });
@@ -0,0 +1 @@
1
+ export type { TokenPolicyConfig as TokenPolicyConfig } from '@tachybase/auth';
package/dist/types.js ADDED
@@ -0,0 +1,15 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __copyProps = (to, from, except, desc) => {
6
+ if (from && typeof from === "object" || typeof from === "function") {
7
+ for (let key of __getOwnPropNames(from))
8
+ if (!__hasOwnProp.call(to, key) && key !== except)
9
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
+ }
11
+ return to;
12
+ };
13
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
14
+ var types_exports = {};
15
+ module.exports = __toCommonJS(types_exports);
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@tachybase/module-auth",
3
3
  "displayName": "Authentication",
4
- "version": "0.23.48",
4
+ "version": "1.0.6",
5
5
  "description": "User authentication management, including password, SMS, and support for Single Sign-On (SSO) protocols, with extensibility.",
6
6
  "keywords": [
7
- "Authentication"
7
+ "Authentication",
8
+ "Security"
8
9
  ],
9
10
  "main": "./dist/server/index.js",
10
11
  "dependencies": {},
@@ -12,20 +13,23 @@
12
13
  "@ant-design/icons": "~5.3.7",
13
14
  "antd": "5.22.5",
14
15
  "cron": "^3.3.1",
16
+ "lodash": "^4.17.21",
17
+ "ms": "^2.1.3",
15
18
  "react": "^18.3.1",
16
19
  "react-i18next": "^15.2.0",
17
20
  "react-router-dom": "6.28.1",
18
- "@tachybase/schema": "0.23.48"
21
+ "@tachybase/schema": "1.0.6"
19
22
  },
20
23
  "peerDependencies": {
21
- "@tachybase/actions": "0.23.48",
22
- "@tachybase/auth": "0.23.48",
23
- "@tachybase/client": "0.23.48",
24
- "@tachybase/cache": "0.23.48",
25
- "@tachybase/database": "0.23.48",
26
- "@tachybase/utils": "0.23.48",
27
- "@tachybase/test": "0.23.48",
28
- "@tachybase/server": "0.23.48"
24
+ "@tachybase/actions": "1.0.6",
25
+ "@tachybase/auth": "1.0.6",
26
+ "@tachybase/client": "1.0.6",
27
+ "@tachybase/server": "1.0.6",
28
+ "@tachybase/cache": "1.0.6",
29
+ "@tachybase/logger": "1.0.6",
30
+ "@tachybase/database": "1.0.6",
31
+ "@tachybase/test": "1.0.6",
32
+ "@tachybase/utils": "1.0.6"
29
33
  },
30
34
  "description.zh-CN": "用户认证管理,包括基础的密码认证、短信认证、SSO 协议的认证等,可扩展。",
31
35
  "displayName.zh-CN": "用户认证",