@nocobase/plugin-auth 2.2.0-alpha.1 → 2.2.0-alpha.11
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/client/{680.c44d0f336fd828c0.js → 680.8758971b4dd75b23.js} +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client-v2/9.c10c60a4ecc4256d.js +10 -0
- package/dist/client-v2/index.js +1 -1
- package/dist/client-v2/pages/AuthenticatorsPage.d.ts +26 -0
- package/dist/externalVersion.js +11 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- package/dist/locale/de-DE.json +2 -1
- package/dist/locale/en-US.json +4 -1
- package/dist/locale/es-ES.json +2 -1
- package/dist/locale/fr-FR.json +2 -1
- package/dist/locale/hu-HU.json +2 -1
- package/dist/locale/id-ID.json +2 -1
- package/dist/locale/it-IT.json +2 -1
- package/dist/locale/ja-JP.json +2 -1
- package/dist/locale/ko-KR.json +2 -1
- package/dist/locale/nl-NL.json +2 -1
- package/dist/locale/pt-BR.json +2 -1
- package/dist/locale/ru-RU.json +2 -1
- package/dist/locale/tr-TR.json +2 -1
- package/dist/locale/uk-UA.json +2 -1
- package/dist/locale/vi-VN.json +2 -1
- package/dist/locale/zh-CN.json +4 -1
- package/dist/locale/zh-TW.json +2 -1
- package/dist/node_modules/cron/package.json +1 -1
- package/dist/node_modules/ms/package.json +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +4 -1
- package/dist/server/locale/en-US.json +2 -1
- package/dist/server/locale/zh-CN.json +3 -2
- package/dist/server/plugin.js +3 -1
- package/dist/server/token-controller.d.ts +1 -0
- package/dist/server/token-controller.js +11 -8
- package/dist/server/utils/buildRedirectPath.js +5 -0
- package/dist/server/utils/resolveSubAppSegment.d.ts +17 -0
- package/dist/server/utils/resolveSubAppSegment.js +82 -0
- package/package.json +2 -2
- package/dist/client-v2/9.5301763a7da120fa.js +0 -10
package/dist/locale/vi-VN.json
CHANGED
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"The username or email is incorrect, please re-enter": "The username or email is incorrect, please re-enter",
|
|
69
69
|
"The username/email or password is incorrect, please re-enter": "The username/email or password is incorrect, please re-enter",
|
|
70
70
|
"The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)": "The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)",
|
|
71
|
+
"Invalid sign-in origin": "Nguồn đăng nhập không hợp lệ",
|
|
71
72
|
"Token expired": "Token expired",
|
|
72
73
|
"Token policy": "Token policy",
|
|
73
74
|
"Token validity period": "Token validity period",
|
|
@@ -81,4 +82,4 @@
|
|
|
81
82
|
"defaultResetPasswordEmailContentHTML": "<p>Hello {{$user.username}},</p>\n\n<p>We received a request to reset the password for your {{$systemSettings.title}} account.</p>\n\n<p>Please click the link below to set your new password:</p>\n\n<p>\n <a href=\"{{$resetLink}}\">Reset Your Password</a>\n</p>\n\n<p>\n If you did not request a password reset, please ignore this email. Your password will remain unchanged.\n</p>\n\n<p>\n Please note: For your security, this password reset link will expire in <strong>{{$resetLinkExpiration}} minutes</strong>.\n</p>\n\n<p>If you encounter any issues resetting your password, please contact our support team.</p>\n\n<p>\n Thanks,<br>\n The {{$systemSettings.title}} Team\n</p>",
|
|
82
83
|
"defaultResetPasswordEmailContentText": "Hello {{$user.username}},\n\nWe received a request to reset the password for your {{$systemSettings.title}} account.\n\nPlease click the link below to set your new password:\n\n{{$resetLink}}\n\nIf you did not request a password reset, please ignore this email. Your password will remain unchanged.\n\nPlease note: For your security, this password reset link will expire in {{$resetLinkExpiration}} minutes.\n\nIf you encounter any issues resetting your password, please contact our support team.\n\nThanks, The {{$systemSettings.title}} Team",
|
|
83
84
|
"defaultResetPasswordEmailSubject": "Reset your password for {{$systemSettings.title}}"
|
|
84
|
-
}
|
|
85
|
+
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"Days": "天",
|
|
14
14
|
"Email channel not found": "未找到邮件通道",
|
|
15
15
|
"Enable forget password": "启用忘记密码功能",
|
|
16
|
+
"Failed to load authenticator": "加载认证器失败",
|
|
16
17
|
"Expired token refresh limit": "过期 Token 刷新时限",
|
|
17
18
|
"Forgot password": "忘记密码",
|
|
18
19
|
"Go to login": "前往登录",
|
|
@@ -68,6 +69,8 @@
|
|
|
68
69
|
"The username or email is incorrect, please re-enter": "用户名或邮箱有误,请重新输入",
|
|
69
70
|
"The username/email or password is incorrect, please re-enter": "用户名/邮箱或密码有误,请重新输入",
|
|
70
71
|
"The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)": "每次签发的 API Token 的有效期。Token 过期后,如果处于会话有效期内,并且没有超过刷新时限,服务端将自动签发新 Token 以保持用户会话,否则要求用户重新登录。(每个 Token 只能被刷新一次)",
|
|
72
|
+
"Invalid CSRF token": "CSRF token 无效",
|
|
73
|
+
"Invalid sign-in origin": "登录来源无效",
|
|
71
74
|
"Token expired": "令牌已过期",
|
|
72
75
|
"Token policy": "Token 策略",
|
|
73
76
|
"Token validity period": "Token 有效期",
|
|
@@ -81,4 +84,4 @@
|
|
|
81
84
|
"defaultResetPasswordEmailContentHTML": "<p>您好 {{$user.username}},</p>\n\n<p>我们收到了重置您 {{$systemSettings.title}} 账户密码的请求。</p>\n\n<p>请点击下面的链接设置您的新密码:</p>\n\n<p>\n <a href=\"{{$resetLink}}\">重置您的密码</a>\n</p>\n\n<p>\n 如果您没有请求重置密码,请忽略此邮件。您的密码将保持不变。\n</p>\n\n<p>\n 请注意:为了您的安全,此密码重置链接将在 <strong>{{$resetLinkExpiration}} 分钟</strong>后过期。\n</p>\n\n<p>如果您在重置密码时遇到任何问题,请联系我们的支持团队。</p>\n\n<p>\n 谢谢,<br>\n {{$systemSettings.title}} 团队\n</p>",
|
|
82
85
|
"defaultResetPasswordEmailContentText": "您好 {{$user.username}},\n\n我们收到了重置您 {{$systemSettings.title}} 账户密码的请求。\n\n请点击下面的链接设置您的新密码:\n\n{{$resetLink}}\n\n如果您没有请求重置密码,请忽略此邮件。您的密码将保持不变。\n\n请注意:为了您的安全,此密码重置链接将在 {{$resetLinkExpiration}} 分钟后过期。\n\n如果您在重置密码时遇到任何问题,请联系我们的支持团队。\n\n谢谢,{{$systemSettings.title}} 团队",
|
|
83
86
|
"defaultResetPasswordEmailSubject": "重置您的 {{$systemSettings.title}} 密码"
|
|
84
|
-
}
|
|
87
|
+
}
|
package/dist/locale/zh-TW.json
CHANGED
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"The username or email is incorrect, please re-enter": "The username or email is incorrect, please re-enter",
|
|
69
69
|
"The username/email or password is incorrect, please re-enter": "The username/email or password is incorrect, please re-enter",
|
|
70
70
|
"The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)": "The validity period of each issued API Token. After the Token expires, if it is within the session validity period and has not exceeded the refresh limit, the server will automatically issue a new Token to maintain the user session, otherwise the user is required to log in again. (Each Token can only be refreshed once)",
|
|
71
|
+
"Invalid sign-in origin": "登入來源無效",
|
|
71
72
|
"Token expired": "Token expired",
|
|
72
73
|
"Token policy": "Token policy",
|
|
73
74
|
"Token validity period": "Token validity period",
|
|
@@ -81,4 +82,4 @@
|
|
|
81
82
|
"defaultResetPasswordEmailContentHTML": "<p>Hello {{$user.username}},</p>\n\n<p>We received a request to reset the password for your {{$systemSettings.title}} account.</p>\n\n<p>Please click the link below to set your new password:</p>\n\n<p>\n <a href=\"{{$resetLink}}\">Reset Your Password</a>\n</p>\n\n<p>\n If you did not request a password reset, please ignore this email. Your password will remain unchanged.\n</p>\n\n<p>\n Please note: For your security, this password reset link will expire in <strong>{{$resetLinkExpiration}} minutes</strong>.\n</p>\n\n<p>If you encounter any issues resetting your password, please contact our support team.</p>\n\n<p>\n Thanks,<br>\n The {{$systemSettings.title}} Team\n</p>",
|
|
82
83
|
"defaultResetPasswordEmailContentText": "Hello {{$user.username}},\n\nWe received a request to reset the password for your {{$systemSettings.title}} account.\n\nPlease click the link below to set your new password:\n\n{{$resetLink}}\n\nIf you did not request a password reset, please ignore this email. Your password will remain unchanged.\n\nPlease note: For your security, this password reset link will expire in {{$resetLinkExpiration}} minutes.\n\nIf you encounter any issues resetting your password, please contact our support team.\n\nThanks, The {{$systemSettings.title}} Team",
|
|
83
84
|
"defaultResetPasswordEmailSubject": "Reset your password for {{$systemSettings.title}}"
|
|
84
|
-
}
|
|
85
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"cron","description":"Cron jobs for your node","version":"2.4.4","author":"Nick Campbell <nicholas.j.campbell@gmail.com> (https://github.com/ncb000gt)","bugs":{"url":"https://github.com/kelektiv/node-cron/issues"},"repository":{"type":"git","url":"https://github.com/kelektiv/node-cron.git"},"main":"lib/cron","scripts":{"lint":"eslint {lib,tests}/*.js","test":"jest --coverage","test:watch":"jest --watch --coverage","test:types":"tsd","prepare":"husky install","release":"semantic-release"},"types":"types/index.d.ts","dependencies":{"@types/luxon":"~3.3.0","luxon":"~3.3.0"},"devDependencies":{"@commitlint/cli":"~17.6.6","@insurgentlab/commitlint-config":"^18.1.0","@insurgentlab/conventional-changelog-preset":"~6.0.3","@semantic-release/changelog":"~6.0.x","@semantic-release/commit-analyzer":"~9.0.x","@semantic-release/git":"~10.0.x","@semantic-release/github":"~8.1.x","@semantic-release/npm":"~10.0.x","@semantic-release/release-notes-generator":"~11.0.x","chai":"~4.2.x","eslint":"~8.36.x","eslint-config-prettier":"^8.7.x","eslint-config-standard":"~17.0.x","eslint-plugin-import":"~2.27.x","eslint-plugin-jest":"~27.2.x","eslint-plugin-n":"~15.6.x","eslint-plugin-prettier":"~4.2.x","eslint-plugin-promise":"~6.1.x","husky":"^8.0.3","jest":"~29.5.x","prettier":"~2.8.x","semantic-release":"~21.0.x","sinon":"^15.0.x","tsd":"^0.28.1"},"keywords":["cron","node cron","node-cron","schedule","scheduler","cronjob","cron job"],"license":"MIT","contributors":["Brandon der Blätter <https://interlucid.com/contact/> (https://github.com/intcreator)","Romain Beauxis <toots@rastageeks.org> (https://github.com/toots)","James Padolsey <> (https://github.com/jamespadolsey)","Finn Herpich <fh@three-heads.de> (https://github.com/ErrorProne)","Clifton Cunningham <clifton.cunningham@gmail.com> (https://github.com/cliftonc)","Eric Abouaf <eric.abouaf@gmail.com> (https://github.com/neyric)","humanchimp <morphcham@gmail.com> (https://github.com/humanchimp)","Craig Condon <craig@spiceapps.com> (https://github.com/spiceapps)","Dan Bear <daniel@hulu.com> (https://github.com/danhbear)","Vadim Baryshev <vadimbaryshev@gmail.com> (https://github.com/baryshev)","Leandro Ferrari <lfthomaz@gmail.com> (https://github.com/lfthomaz)","Gregg Zigler <greggzigler@gmail.com> (https://github.com/greggzigler)","Jordan Abderrachid <jabderrachid@gmail.com> (https://github.com/jordanabderrachid)","Masakazu Matsushita <matsukaz@gmail.com> (matsukaz)","Christopher Lunt <me@kirisu.co.uk> (https://github.com/kirisu)"],"jest":{"collectCoverage":true,"collectCoverageFrom":["lib/*.js"],"coverageThreshold":{"global":{"statements":80,"branches":80,"functions":70,"lines":80}}},"files":["lib","types","CHANGELOG.md","LICENSE","README.md"],"_lastModified":"2026-
|
|
1
|
+
{"name":"cron","description":"Cron jobs for your node","version":"2.4.4","author":"Nick Campbell <nicholas.j.campbell@gmail.com> (https://github.com/ncb000gt)","bugs":{"url":"https://github.com/kelektiv/node-cron/issues"},"repository":{"type":"git","url":"https://github.com/kelektiv/node-cron.git"},"main":"lib/cron","scripts":{"lint":"eslint {lib,tests}/*.js","test":"jest --coverage","test:watch":"jest --watch --coverage","test:types":"tsd","prepare":"husky install","release":"semantic-release"},"types":"types/index.d.ts","dependencies":{"@types/luxon":"~3.3.0","luxon":"~3.3.0"},"devDependencies":{"@commitlint/cli":"~17.6.6","@insurgentlab/commitlint-config":"^18.1.0","@insurgentlab/conventional-changelog-preset":"~6.0.3","@semantic-release/changelog":"~6.0.x","@semantic-release/commit-analyzer":"~9.0.x","@semantic-release/git":"~10.0.x","@semantic-release/github":"~8.1.x","@semantic-release/npm":"~10.0.x","@semantic-release/release-notes-generator":"~11.0.x","chai":"~4.2.x","eslint":"~8.36.x","eslint-config-prettier":"^8.7.x","eslint-config-standard":"~17.0.x","eslint-plugin-import":"~2.27.x","eslint-plugin-jest":"~27.2.x","eslint-plugin-n":"~15.6.x","eslint-plugin-prettier":"~4.2.x","eslint-plugin-promise":"~6.1.x","husky":"^8.0.3","jest":"~29.5.x","prettier":"~2.8.x","semantic-release":"~21.0.x","sinon":"^15.0.x","tsd":"^0.28.1"},"keywords":["cron","node cron","node-cron","schedule","scheduler","cronjob","cron job"],"license":"MIT","contributors":["Brandon der Blätter <https://interlucid.com/contact/> (https://github.com/intcreator)","Romain Beauxis <toots@rastageeks.org> (https://github.com/toots)","James Padolsey <> (https://github.com/jamespadolsey)","Finn Herpich <fh@three-heads.de> (https://github.com/ErrorProne)","Clifton Cunningham <clifton.cunningham@gmail.com> (https://github.com/cliftonc)","Eric Abouaf <eric.abouaf@gmail.com> (https://github.com/neyric)","humanchimp <morphcham@gmail.com> (https://github.com/humanchimp)","Craig Condon <craig@spiceapps.com> (https://github.com/spiceapps)","Dan Bear <daniel@hulu.com> (https://github.com/danhbear)","Vadim Baryshev <vadimbaryshev@gmail.com> (https://github.com/baryshev)","Leandro Ferrari <lfthomaz@gmail.com> (https://github.com/lfthomaz)","Gregg Zigler <greggzigler@gmail.com> (https://github.com/greggzigler)","Jordan Abderrachid <jabderrachid@gmail.com> (https://github.com/jordanabderrachid)","Masakazu Matsushita <matsukaz@gmail.com> (matsukaz)","Christopher Lunt <me@kirisu.co.uk> (https://github.com/kirisu)"],"jest":{"collectCoverage":true,"collectCoverageFrom":["lib/*.js"],"coverageThreshold":{"global":{"statements":80,"branches":80,"functions":70,"lines":80}}},"files":["lib","types","CHANGELOG.md","LICENSE","README.md"],"_lastModified":"2026-07-28T07:39:52.124Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"ms","version":"2.1.3","description":"Tiny millisecond conversion utility","repository":"vercel/ms","main":"./index","files":["index.js"],"scripts":{"precommit":"lint-staged","lint":"eslint lib/* bin/*","test":"mocha tests.js"},"eslintConfig":{"extends":"eslint:recommended","env":{"node":true,"es6":true}},"lint-staged":{"*.js":["npm run lint","prettier --single-quote --write","git add"]},"license":"MIT","devDependencies":{"eslint":"4.18.2","expect.js":"0.3.1","husky":"0.14.3","lint-staged":"5.0.0","mocha":"4.0.1","prettier":"2.0.5"},"_lastModified":"2026-
|
|
1
|
+
{"name":"ms","version":"2.1.3","description":"Tiny millisecond conversion utility","repository":"vercel/ms","main":"./index","files":["index.js"],"scripts":{"precommit":"lint-staged","lint":"eslint lib/* bin/*","test":"mocha tests.js"},"eslintConfig":{"extends":"eslint:recommended","env":{"node":true,"es6":true}},"lint-staged":{"*.js":["npm run lint","prettier --single-quote --write","git add"]},"license":"MIT","devDependencies":{"eslint":"4.18.2","expect.js":"0.3.1","husky":"0.14.3","lint-staged":"5.0.0","mocha":"4.0.1","prettier":"2.0.5"},"_lastModified":"2026-07-28T07:39:52.215Z"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -12,5 +12,6 @@ export { presetAuthType } from '../preset';
|
|
|
12
12
|
export { defaultTokenPolicyConfig } from '../constants';
|
|
13
13
|
export { buildRedirectPath, getModernClientPrefix, resolveSigninPrefix } from './utils/buildRedirectPath';
|
|
14
14
|
export type { BuildRedirectPathOptions, ResolveSigninPrefixOptions } from './utils/buildRedirectPath';
|
|
15
|
+
export { resolveSubAppSegment } from './utils/resolveSubAppSegment';
|
|
15
16
|
export { default } from './plugin';
|
|
16
17
|
export * from '../constants';
|
package/dist/server/index.js
CHANGED
|
@@ -44,7 +44,8 @@ __export(server_exports, {
|
|
|
44
44
|
defaultTokenPolicyConfig: () => import_constants.defaultTokenPolicyConfig,
|
|
45
45
|
getModernClientPrefix: () => import_buildRedirectPath.getModernClientPrefix,
|
|
46
46
|
presetAuthType: () => import_preset.presetAuthType,
|
|
47
|
-
resolveSigninPrefix: () => import_buildRedirectPath.resolveSigninPrefix
|
|
47
|
+
resolveSigninPrefix: () => import_buildRedirectPath.resolveSigninPrefix,
|
|
48
|
+
resolveSubAppSegment: () => import_resolveSubAppSegment.resolveSubAppSegment
|
|
48
49
|
});
|
|
49
50
|
module.exports = __toCommonJS(server_exports);
|
|
50
51
|
var import_basic_auth = require("./basic-auth");
|
|
@@ -52,6 +53,7 @@ var import_authenticator = require("./model/authenticator");
|
|
|
52
53
|
var import_preset = require("../preset");
|
|
53
54
|
var import_constants = require("../constants");
|
|
54
55
|
var import_buildRedirectPath = require("./utils/buildRedirectPath");
|
|
56
|
+
var import_resolveSubAppSegment = require("./utils/resolveSubAppSegment");
|
|
55
57
|
var import_plugin = __toESM(require("./plugin"));
|
|
56
58
|
__reExport(server_exports, require("../constants"), module.exports);
|
|
57
59
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -63,5 +65,6 @@ __reExport(server_exports, require("../constants"), module.exports);
|
|
|
63
65
|
getModernClientPrefix,
|
|
64
66
|
presetAuthType,
|
|
65
67
|
resolveSigninPrefix,
|
|
68
|
+
resolveSubAppSegment,
|
|
66
69
|
...require("../constants")
|
|
67
70
|
});
|
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
"The password is incorrect, please re-enter": "The password is incorrect, please re-enter",
|
|
5
5
|
"Not a valid cellphone number, please re-enter": "Not a valid cellphone number, please re-enter",
|
|
6
6
|
"The phone number has been registered, please login directly": "The phone number has been registered, please login directly",
|
|
7
|
-
"The phone number is not registered, please register first": "The phone number is not registered, please register first"
|
|
7
|
+
"The phone number is not registered, please register first": "The phone number is not registered, please register first",
|
|
8
|
+
"Invalid CSRF token": "Invalid CSRF token"
|
|
8
9
|
}
|
|
@@ -6,5 +6,6 @@
|
|
|
6
6
|
"The phone number is not registered, please register first": "手机号未注册,请先注册",
|
|
7
7
|
"Please keep and enable at least one authenticator": "请至少保留并启用一个认证器",
|
|
8
8
|
"Please enter your username or email": "请输入用户名或邮箱",
|
|
9
|
-
"Please enter a valid username": "请输入有效的用户名"
|
|
10
|
-
|
|
9
|
+
"Please enter a valid username": "请输入有效的用户名",
|
|
10
|
+
"Invalid CSRF token": "CSRF token 无效"
|
|
11
|
+
}
|
package/dist/server/plugin.js
CHANGED
|
@@ -136,7 +136,9 @@ class PluginAuthServer extends import_server.Plugin {
|
|
|
136
136
|
([action, handler]) => this.app.resourceManager.registerActionHandler(`authenticators:${action}`, handler)
|
|
137
137
|
);
|
|
138
138
|
["signIn", "signUp"].forEach((action) => this.app.acl.allow("auth", action));
|
|
139
|
-
["check", "signOut", "changePassword"].forEach(
|
|
139
|
+
["check", "signOut", "syncCookies", "changePassword"].forEach(
|
|
140
|
+
(action) => this.app.acl.allow("auth", action, "loggedIn")
|
|
141
|
+
);
|
|
140
142
|
["lostPassword", "resetPassword", "checkResetToken"].forEach(
|
|
141
143
|
(action) => this.app.acl.allow("auth", action, "public")
|
|
142
144
|
);
|
|
@@ -26,6 +26,7 @@ export declare class TokenController implements TokenControlService {
|
|
|
26
26
|
getConfig(): Promise<NumericTokenPolicyConfig>;
|
|
27
27
|
setConfig(config: TokenPolicyConfig): Promise<void>;
|
|
28
28
|
removeSessionExpiredTokens(userId: number): Promise<number>;
|
|
29
|
+
private cleanupSessionExpiredTokens;
|
|
29
30
|
add({ userId, authenticator }: {
|
|
30
31
|
userId: number;
|
|
31
32
|
authenticator?: string;
|
|
@@ -93,6 +93,13 @@ class TokenController {
|
|
|
93
93
|
}
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
|
+
async cleanupSessionExpiredTokens(userId) {
|
|
97
|
+
try {
|
|
98
|
+
await this.removeSessionExpiredTokens(userId);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
this.logger.error(err, { module: "auth", submodule: "token-controller", method: "removeSessionExpiredTokens" });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
96
103
|
async add({ userId, authenticator }) {
|
|
97
104
|
const jti = (0, import_crypto.randomUUID)();
|
|
98
105
|
const currTS = Date.now();
|
|
@@ -105,14 +112,10 @@ class TokenController {
|
|
|
105
112
|
authenticator
|
|
106
113
|
};
|
|
107
114
|
await this.setTokenInfo(jti, data);
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
this.removeSessionExpiredTokens(userId);
|
|
113
|
-
}
|
|
114
|
-
} catch (err) {
|
|
115
|
-
this.logger.error(err, { module: "auth", submodule: "token-controller", method: "removeSessionExpiredTokens" });
|
|
115
|
+
if (process.env.DB_DIALECT === "sqlite") {
|
|
116
|
+
await this.cleanupSessionExpiredTokens(userId);
|
|
117
|
+
} else {
|
|
118
|
+
this.cleanupSessionExpiredTokens(userId);
|
|
116
119
|
}
|
|
117
120
|
return data;
|
|
118
121
|
}
|
|
@@ -35,9 +35,14 @@ function buildRedirectPath({ appPublicPath, subAppSegment, target }) {
|
|
|
35
35
|
const normalizedAppPublicPath = (appPublicPath || "").replace(/\/+$/, "");
|
|
36
36
|
const normalizedSubAppSegment = (subAppSegment || "").replace(/\/+$/, "");
|
|
37
37
|
const resolvedTarget = target || "/admin";
|
|
38
|
+
const [resolvedPathname] = resolvedTarget.split(/[?#]/, 1);
|
|
38
39
|
if (normalizedAppPublicPath && (resolvedTarget === normalizedAppPublicPath || resolvedTarget.startsWith(normalizedAppPublicPath + "/"))) {
|
|
39
40
|
return resolvedTarget;
|
|
40
41
|
}
|
|
42
|
+
const modernSubAppSegment = `/${getModernClientPrefix()}${normalizedSubAppSegment}`;
|
|
43
|
+
if (normalizedSubAppSegment && (resolvedPathname === normalizedSubAppSegment || resolvedPathname.startsWith(`${normalizedSubAppSegment}/`) || resolvedPathname === modernSubAppSegment || resolvedPathname.startsWith(`${modernSubAppSegment}/`))) {
|
|
44
|
+
return resolvedTarget;
|
|
45
|
+
}
|
|
41
46
|
return `${normalizedAppPublicPath}${normalizedSubAppSegment}${resolvedTarget}`;
|
|
42
47
|
}
|
|
43
48
|
function getModernClientPrefix() {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
/// <reference types="node" />
|
|
10
|
+
import type { IncomingMessage } from 'http';
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the legacy sub-application URL segment for an authentication
|
|
13
|
+
* redirect. A sub-application reached through its custom domain is mounted at
|
|
14
|
+
* the root, while one reached through the supervisor domain uses
|
|
15
|
+
* `/apps/<name>`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveSubAppSegment(req: IncomingMessage, appName?: string | null): Promise<string>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var resolveSubAppSegment_exports = {};
|
|
28
|
+
__export(resolveSubAppSegment_exports, {
|
|
29
|
+
resolveSubAppSegment: () => resolveSubAppSegment
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(resolveSubAppSegment_exports);
|
|
32
|
+
var import_server = require("@nocobase/server");
|
|
33
|
+
function normalizeHostname(value) {
|
|
34
|
+
const host = value == null ? void 0 : value.split(",", 1)[0].trim();
|
|
35
|
+
if (!host) {
|
|
36
|
+
return "";
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return new URL(`http://${host}`).hostname;
|
|
40
|
+
} catch {
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function getRequestHostname(req) {
|
|
45
|
+
const hostnameHeader = req.headers["x-hostname"];
|
|
46
|
+
if (Array.isArray(hostnameHeader)) {
|
|
47
|
+
for (const value of hostnameHeader) {
|
|
48
|
+
const hostname = normalizeHostname(value);
|
|
49
|
+
if (hostname) {
|
|
50
|
+
return hostname;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
const hostname = normalizeHostname(hostnameHeader);
|
|
55
|
+
if (hostname) {
|
|
56
|
+
return hostname;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return (0, import_server.getHostname)(req);
|
|
60
|
+
}
|
|
61
|
+
async function resolveSubAppSegment(req, appName) {
|
|
62
|
+
var _a;
|
|
63
|
+
if (!appName || appName === "main") {
|
|
64
|
+
return "";
|
|
65
|
+
}
|
|
66
|
+
const appSupervisor = import_server.AppSupervisor.getInstance();
|
|
67
|
+
if (!appSupervisor || appSupervisor.runningMode === "single") {
|
|
68
|
+
return "";
|
|
69
|
+
}
|
|
70
|
+
const hostname = getRequestHostname(req);
|
|
71
|
+
if (hostname) {
|
|
72
|
+
const cnameAppName = await ((_a = appSupervisor.getAppNameByCName) == null ? void 0 : _a.call(appSupervisor, hostname));
|
|
73
|
+
if (cnameAppName === appName) {
|
|
74
|
+
return "";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return `/apps/${appName}`;
|
|
78
|
+
}
|
|
79
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
80
|
+
0 && (module.exports = {
|
|
81
|
+
resolveSubAppSegment
|
|
82
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-auth",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.11",
|
|
4
4
|
"main": "./dist/server/index.js",
|
|
5
5
|
"homepage": "https://docs.nocobase.com/handbook/auth",
|
|
6
6
|
"homepage.ru-RU": "https://docs-ru.nocobase.com/handbook/auth",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"description": "User authentication management, including password, SMS, and support for Single Sign-On (SSO) protocols, with extensibility.",
|
|
32
32
|
"description.ru-RU": "Управление аутентификацией пользователей: пароли, SMS, поддержка протоколов единого входа (SSO) и возможность расширения.",
|
|
33
33
|
"description.zh-CN": "用户认证管理,包括基础的密码认证、短信认证、SSO 协议的认证等,可扩展。",
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "c9ff1f51e5c33bc6437b64eb779212be71b78f58",
|
|
35
35
|
"keywords": [
|
|
36
36
|
"Authentication",
|
|
37
37
|
"Security"
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
"use strict";(self.webpackChunk_nocobase_plugin_auth_client_v2=self.webpackChunk_nocobase_plugin_auth_client_v2||[]).push([["9"],{648:function(e,t,n){n.r(t),n.d(t,{default:function(){return O}});var r=n(375),a=n(485),u=n(694),o=n(6),l=n(59),i=n(773),c=n(155),s=n.n(c),d=n(488),f=n(434);function p(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function m(e,t,n,r,a,u,o){try{var l=e[u](o),i=l.value}catch(e){n(e);return}l.done?t(i):Promise.resolve(i).then(r,a)}function y(e){return function(){var t=this,n=arguments;return new Promise(function(r,a){var u=e.apply(t,n);function o(e){m(u,r,a,o,l,"next",e)}function l(e){m(u,r,a,o,l,"throw",e)}o(void 0)})}}function b(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){var r;r=n[t],t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r})}return e}function h(e,t){return t=null!=t?t:{},Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):(function(e){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t.push.apply(t,n)}return t})(Object(t)).forEach(function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}),e}function v(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,a=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var u=[],o=!0,l=!1;try{for(a=a.call(e);!(o=(n=a.next()).done)&&(u.push(n.value),!t||u.length!==t);o=!0);}catch(e){l=!0,r=e}finally{try{o||null==a.return||a.return()}finally{if(l)throw r}}return u}}(e,t)||function(e,t){if(e){if("string"==typeof e)return p(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return p(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function g(e,t){var n,r,a,u={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]},o=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),l=Object.defineProperty;return l(o,"next",{value:i(0)}),l(o,"throw",{value:i(1)}),l(o,"return",{value:i(2)}),"function"==typeof Symbol&&l(o,Symbol.iterator,{value:function(){return this}}),o;function i(l){return function(i){var c=[l,i];if(n)throw TypeError("Generator is already executing.");for(;o&&(o=0,c[0]&&(u=0)),u;)try{if(n=1,r&&(a=2&c[0]?r.return:c[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,c[1])).done)return a;switch(r=0,a&&(c=[2&c[0],a.value]),c[0]){case 0:case 1:a=c;break;case 4:return u.label++,{value:c[1],done:!1};case 5:u.label++,r=c[1],c=[0];continue;case 7:c=u.ops.pop(),u.trys.pop();continue;default:if(!(a=(a=u.trys).length>0&&a[a.length-1])&&(6===c[0]||2===c[0])){u=0;continue}if(3===c[0]&&(!a||c[1]>a[0]&&c[1]<a[3])){u.label=c[1];break}if(6===c[0]&&u.label<a[1]){u.label=a[1],a=c;break}if(a&&u.label<a[2]){u.label=a[2],u.ops.push(c);break}a[2]&&u.ops.pop(),u.trys.pop();continue}c=t.call(e,u)}catch(e){c=[6,e],r=0}finally{n=a=0}if(5&c[0])throw c[1];return{value:c[0]?c[1]:void 0,done:!0}}}}function E(){return(0,u.useFlowContext)().api.resource("authenticators")}function w(e){var t=(0,d.dE)().t,n=(0,d.kj)(),r=(0,c.useMemo)(function(){return e.authTypeOptions.map(function(e){return{value:e.name,label:n(e.title||e.name)}})},[e.authTypeOptions,n]),f=E(),p=v(l.Form.useForm(),1)[0],m=v((0,c.useState)(!1),2),w=m[0],O=m[1],S=(0,c.useMemo)(function(){return"edit"===e.mode?(0,i.cloneDeep)(e.record||{}):{name:(0,u.randomId)("s_"),authType:e.authType,enabled:!1,options:{}}},[e.authType,e.mode,e.record]);(0,c.useEffect)(function(){p.setFieldsValue(S)},[p,S]);var T=l.Form.useWatch("authType",p),A=null!=T?T:e.authType,k=(0,c.useMemo)(function(){var t;return null==(t=e.plugin.authTypes.get(A))?void 0:t.adminSettingsFormLoader},[e.plugin,A]),j=(0,c.useMemo)(function(){return k?(0,c.lazy)(k):null},[k]),I=(0,o.useMemoizedFn)(function(){p.setFieldValue("options",{})}),F=(0,o.useMemoizedFn)(function(){return y(function(){var t,n,r,a;return g(this,function(u){switch(u.label){case 0:return[4,p.validateFields()];case 1:n=function e(t){return"string"==typeof t?t.trim():Array.isArray(t)?t.map(e):t&&(void 0===t?"undefined":t&&"u">typeof Symbol&&t.constructor===Symbol?"symbol":typeof t)=="object"?Object.fromEntries(Object.entries(t).map(function(t){var n=v(t,2);return[n[0],e(n[1])]})):t}((t=u.sent()).options||{}),O(!0),u.label=2;case 2:if(u.trys.push([2,,7,8]),"create"!==e.mode)return[3,4];return[4,f.create({values:h(b({},t),{options:n})})];case 3:return u.sent(),[3,6];case 4:if((null==(r=e.record)?void 0:r.id)==null)return[3,6];return a=h(b({},(0,i.cloneDeep)(e.record),t),{options:b({},e.record.options||{},n)}),[4,f.update({filterByTk:e.record.id,values:a})];case 5:u.sent(),u.label=6;case 6:return e.onSubmitted(),[3,8];case 7:return O(!1),[7];case 8:return[2]}})})()});return s().createElement(a.DrawerFormLayout,{title:t("create"===e.mode?"Add new":"Configure"),onSubmit:F,submitting:w,submitText:t("Submit"),cancelText:t("Cancel")},s().createElement(l.Form,{form:p,layout:"vertical",initialValues:S},s().createElement(l.Form.Item,{name:"name",label:t("Auth UID"),rules:[{required:!0,message:t("Please enter an Auth UID")},{pattern:/^[a-zA-Z0-9_-]+$/,message:t("a-z, A-Z, 0-9, _, -")}]},s().createElement(l.Input,{disabled:"edit"===e.mode})),s().createElement(l.Form.Item,{name:"authType",label:t("Auth Type"),rules:[{required:!0}]},s().createElement(l.Select,{options:r,onChange:I})),s().createElement(l.Form.Item,{name:"title",label:t("Title")},s().createElement(l.Input,null)),s().createElement(l.Form.Item,{name:"description",label:t("Description")},s().createElement(l.Input,null)),s().createElement(l.Form.Item,{name:"enabled",label:t("Enabled"),valuePropName:"checked"},s().createElement(l.Checkbox,null)),j?s().createElement(c.Suspense,{fallback:s().createElement(l.Spin,null)},s().createElement(j,null)):null))}function O(){var e,t=(0,d.dE)().t,n=(0,d.kj)(),i=(0,u.useFlowContext)(),p=l.theme.useToken().token,m=l.App.useApp(),b=m.modal,h=m.message,O=E(),S=i.app.pm.get(f.A),T=v((0,c.useState)(1),2),A=T[0],k=T[1],j=v((0,c.useState)(a.DEFAULT_PAGE_SIZE),2),I=j[0],F=j[1],D=v((0,c.useState)([]),2),C=D[0],P=D[1],x=(e=E(),(0,o.useRequest)(function(){return y(function(){var t,n,r,a;return g(this,function(u){switch(u.label){case 0:return[4,e.listTypes()];case 1:return[2,Array.isArray(a=null!=(t=null==(r=u.sent())||null==(n=r.data)?void 0:n.data)?t:null==r?void 0:r.data)?a:[]]}})})()},{cacheKey:"@nocobase/plugin-auth:authenticators:listTypes"})).data,M=(0,o.useRequest)(function(){return y(function(){return g(this,function(e){switch(e.label){case 0:return[4,O.list({page:A,pageSize:I,sort:["sort"],appends:[]})];case 1:var t,n,r,a,u;return[2,{records:a=Array.isArray(r=null==(n=null==(t=e.sent())?void 0:t.data)?void 0:n.data)?r:Array.isArray(null==r?void 0:r.data)?r.data:[],total:(u=(null==n?void 0:n.meta)||(null==r?void 0:r.meta)||{}).count||u.total||a.length}]}})})()},{refreshDeps:[A,I]}),_=M.data,z=M.loading,B=M.refresh,U=(0,o.useMemoizedFn)(function(e,t){if(t!==I){F(t),k(1);return}k(e)}),q=(0,c.useMemo)(function(){return x||[]},[x]),K=(0,o.useMemoizedFn)(function(e,t,n){i.viewer.drawer({width:"50%",closable:!0,content:function(){return s().createElement(w,{mode:e,authType:t,authTypeOptions:q,plugin:S,record:n,onSubmitted:function(){return B()}})}})}),L=(0,o.useMemoizedFn)(function(e){b.confirm({title:t("Delete"),content:t("Are you sure you want to delete it?"),onOk:function(){return y(function(){return g(this,function(t){switch(t.label){case 0:return[4,O.destroy({filterByTk:e})];case 1:return t.sent(),P([]),B(),[2]}})})()}})}),R=(0,o.useMemoizedFn)(function(e,n){return y(function(){var r;return g(this,function(a){switch(a.label){case 0:if(null==e.id||null==n.id)return[2];a.label=1;case 1:return a.trys.push([1,3,,4]),[4,O.move({sourceId:e.id,targetId:n.id})];case 2:return a.sent(),h.success(t("Saved successfully"),.2),B(),[3,4];case 3:return r=a.sent(),h.error((null==r?void 0:r.message)||"Move failed"),[3,4];case 4:return[2]}})})()}),V=(0,o.useMemoizedFn)(function(e){var t=q.find(function(t){return t.name===e});return n((null==t?void 0:t.title)||e||"")}),Z=(0,c.useMemo)(function(){return[{title:t("Auth UID"),dataIndex:"name"},{title:t("Auth Type"),dataIndex:"authType",render:function(e){return e?s().createElement(l.Tag,null,V(e)):null}},{title:t("Title"),dataIndex:"title"},{title:t("Description"),dataIndex:"description"},{title:t("Enabled"),dataIndex:"enabled",align:"center",width:80,render:function(e){return e?s().createElement(r.CheckOutlined,{style:{color:p.colorSuccess}}):null}},{title:t("Actions"),width:160,render:function(e,n){return s().createElement(l.Space,null,s().createElement("a",{onClick:function(){if(n.authType){if(!S.authTypes.get(n.authType))return void h.error(t("Auth type {{type}} is not registered.").replace("{{type}}",n.authType));K("edit",n.authType,n)}}},t("Configure")),s().createElement("a",{onClick:function(){return L(n.id)}},t("Delete")))}}]},[V,L,h,K,S,t]);return s().createElement(l.Card,{variant:"borderless"},s().createElement("div",{style:{display:"flex",justifyContent:"flex-end",gap:p.marginSM,marginBottom:p.margin}},s().createElement(l.Button,{icon:s().createElement(r.DeleteOutlined,null),disabled:!C.length,onClick:function(){return L(C)}},t("Delete")),s().createElement(l.Dropdown,{menu:{items:q.map(function(e){return{key:e.name,label:n(e.title||e.name)}}),onClick:function(e){K("create",e.key)}},disabled:!q.length},s().createElement(l.Button,{type:"primary",icon:s().createElement(r.PlusOutlined,null)},t("Add new")," ",s().createElement(r.DownOutlined,null)))),s().createElement(a.Table,{rowKey:"id",loading:z,columns:Z,dataSource:(null==_?void 0:_.records)||[],isDraggable:!0,onSortEnd:R,rowSelection:{selectedRowKeys:C,onChange:P},pagination:{current:A,pageSize:I,total:(null==_?void 0:_.total)||0,onChange:U}}))}}}]);
|