@nocobase/plugin-auth 1.7.0-beta.9 → 1.8.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.
- package/dist/client/367cf457dd5bebe5.js +10 -0
- package/dist/client/662f930270b54313.js +10 -0
- package/dist/client/8a134e884eae4f4b.js +10 -0
- package/dist/client/ef57ca1a043c2bc8.js +10 -0
- package/dist/client/{43e9587ca4936ffe.js → f57512ca2e74813f.js} +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/pages/ForgotPasswordPage.d.ts +2 -0
- package/dist/client/pages/ResetPasswordPage.d.ts +2 -0
- package/dist/externalVersion.js +10 -10
- package/dist/locale/de-DE.json +35 -1
- package/dist/locale/en-US.json +34 -1
- package/dist/locale/it-IT.json +35 -1
- package/dist/locale/ja-JP.json +36 -2
- package/dist/locale/ko-KR.json +36 -1
- package/dist/locale/nl-NL.json +65 -31
- package/dist/locale/zh-CN.json +35 -1
- package/dist/node_modules/cron/package.json +1 -1
- package/dist/node_modules/ms/package.json +1 -1
- package/dist/server/actions/auth.d.ts +3 -0
- package/dist/server/actions/auth.js +13 -12
- package/dist/server/basic-auth.d.ts +7 -1
- package/dist/server/basic-auth.js +148 -29
- package/dist/server/locale/en-US.json +1 -1
- package/dist/server/plugin.js +9 -13
- package/dist/server/token-controller.d.ts +1 -1
- package/dist/server/token-controller.js +5 -4
- package/dist/swagger/index.js +0 -40
- package/package.json +2 -2
- package/dist/client/0091d4359312cb07.js +0 -10
- package/dist/client/2fde58876f8f8762.js +0 -10
- package/dist/client/9e603524b127e7b4.js +0 -10
- package/dist/client/f2122264b5758d8b.js +0 -10
package/dist/locale/nl-NL.json
CHANGED
|
@@ -1,33 +1,67 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
2
|
+
"Auth Type": "Authenticatietype",
|
|
3
|
+
"Authenticators": "Authenticators",
|
|
4
|
+
"Authentication": "Authenticatie",
|
|
5
|
+
"Sign in via email": "Inloggen via e-mail",
|
|
6
|
+
"Sign in via password": "Inloggen via wachtwoord",
|
|
7
|
+
"Not allowed to sign up": "Aanmelden is niet toegestaan",
|
|
8
|
+
"Allow to sign up": "Toestaan om je aan te melden",
|
|
9
|
+
"The username or email is incorrect, please re-enter": "De gebruikersnaam of e-mail is incorrect, probeer het opnieuw",
|
|
10
|
+
"The password is incorrect, please re-enter": "Het wachtwoord is incorrect, probeer het opnieuw",
|
|
11
|
+
"Not a valid cellphone number, please re-enter": "Geen geldig telefoonnummer, probeer opnieuw in te voeren",
|
|
12
|
+
"The phone number has been registered, please login directly": "Het telefoonnummer is al geregistreerd, log direct in",
|
|
13
|
+
"The phone number is not registered, please register first": "Het telefoonnummer is niet geregistreerd, registreer eerst",
|
|
14
|
+
"Please keep and enable at least one authenticator": "Houd minstens één authenticator ingeschakeld",
|
|
15
|
+
"Allow to sign in with": "Toestaan om in te loggen met",
|
|
16
|
+
"Please enter a valid username": "Voer een geldige gebruikersnaam in",
|
|
17
|
+
"Please enter a valid email": "Voer een geldig e-mailadres in",
|
|
18
|
+
"Please enter your username or email": "Voer je gebruikersnaam of e-mailadres in",
|
|
19
|
+
"Please enter a password": "Voer een wachtwoord in",
|
|
20
|
+
"Username/Email": "Gebruikersnaam/E-mail",
|
|
21
|
+
"Auth UID": "Auth UID",
|
|
22
|
+
"The authentication allows users to sign in via username or email.": "De authenticatie staat gebruikers toe in te loggen via gebruikersnaam of e-mail.",
|
|
23
|
+
"No authentication methods available.": "Geen authenticatiemethoden beschikbaar.",
|
|
24
|
+
"The password is inconsistent, please re-enter": "Het wachtwoord is inconsistent, probeer het opnieuw",
|
|
25
|
+
"Sign-in": "Inloggen",
|
|
26
|
+
"Password": "Wachtwoord",
|
|
27
|
+
"The username/email or password is incorrect, please re-enter": "De gebruikersnaam/e-mail of het wachtwoord is incorrect, probeer het opnieuw",
|
|
28
|
+
"Show": "Toon",
|
|
29
|
+
"Sign up settings": "Aanmeldinstellingen",
|
|
30
|
+
"Sign up form": "Aanmeldformulier",
|
|
31
|
+
"At least one of the username or email fields is required": "Ten minste één van de velden voor gebruikersnaam of e-mail is verplicht",
|
|
32
|
+
"Password is not allowed to be changed": "Wachtwoord mag niet worden gewijzigd",
|
|
33
|
+
"Email channel not found": "E-mailkanaal niet gevonden",
|
|
34
|
+
"Notification manager plugin not found": "Notificatiebeheer-plugin niet gevonden",
|
|
35
|
+
"Not allowed to reset password": "Wachtwoord resetten niet toegestaan",
|
|
36
|
+
"Token expired": "Token verlopen",
|
|
37
|
+
"User not found": "Gebruiker niet gevonden",
|
|
38
|
+
"Forgot password": "Wachtwoord vergeten",
|
|
39
|
+
"Please enter your email": "Voer je e-mailadres",
|
|
40
|
+
"Reset password": "Wachtwoord opnieuw instellen",
|
|
41
|
+
"Back to login": "Terug naar inloggen",
|
|
42
|
+
"Send reset email": "Stuur reset e-mail",
|
|
43
|
+
"Reset link has expired": "Resetlink is verlopen",
|
|
44
|
+
"Go to login": "Ga naar inloggen",
|
|
45
|
+
"Please enter new password": "Voer een nieuw wachtwoord in",
|
|
46
|
+
"Please enter the same password again": "Voer hetzelfde wachtwoord opnieuw in",
|
|
47
|
+
"The passwords entered twice are inconsistent": "De twee ingevoerde wachtwoorden zijn inconsistent",
|
|
48
|
+
"Password reset successful": "Wachtwoord opnieuw instellen succesvol",
|
|
49
|
+
"Enable forget password": "Vergeet wachtwoord functie inschakelen",
|
|
50
|
+
"Notification channel (Email)": "Notificatiekanaal (E-mail)",
|
|
51
|
+
"Subject": "Onderwerp",
|
|
52
|
+
"Content type": "Contenttype",
|
|
53
|
+
"Plain text": "Gewone tekst",
|
|
54
|
+
"defaultResetPasswordEmailSubject": "Stel uw wachtwoord opnieuw in voor {{$systemSettings.title}}",
|
|
55
|
+
"defaultResetPasswordEmailContentHTML": "<p>Hallo {{$user.username}},</p>\n\n<p>We hebben een verzoek ontvangen om het wachtwoord voor uw {{$systemSettings.title}}-account opnieuw in te stellen.</p>\n\n<p>Klik op de onderstaande link om uw nieuwe wachtwoord in te stellen:</p>\n\n<p>\n <a href=\"{{$resetLink}}\">Stel uw wachtwoord opnieuw in</a>\n</p>\n\n<p>\n Als u geen wachtwoordreset heeft aangevraagd, negeer dan deze e-mail. Uw wachtwoord blijft ongewijzigd.\n</p>\n\n<p>\n Let op: Voor uw veiligheid verloopt deze wachtwoordresetlink over <strong>{{$resetLinkExpiration}} minuten</strong>.\n</p>\n\n<p>Als u problemen ondervindt bij het opnieuw instellen van uw wachtwoord, neem dan contact op met ons ondersteuningsteam.</p>\n\n<p>\n Bedankt,<br>\n Het {{$systemSettings.title}} Team\n</p>",
|
|
56
|
+
"defaultResetPasswordEmailContentText": "Hallo {{$user.username}},\n\nWe hebben een verzoek ontvangen om het wachtwoord voor uw {{$systemSettings.title}}-account opnieuw in te stellen.\n\nKlik op de onderstaande link om uw nieuwe wachtwoord in te stellen:\n\n{{$resetLink}}\n\nAls u geen wachtwoordreset heeft aangevraagd, negeer dan deze e-mail. Uw wachtwoord blijft ongewijzigd.\n\nLet op: Voor uw veiligheid verloopt deze wachtwoordresetlink over {{$resetLinkExpiration}} minuten.\n\nAls u problemen ondervindt bij het opnieuw instellen van uw wachtwoord, neem dan contact op met ons ondersteuningsteam.\n\nBedankt, Het {{$systemSettings.title}} Team",
|
|
57
|
+
"No notification channels found. Please ": "Geen meldingskanalen gevonden. Gelieve ",
|
|
58
|
+
"add one first": "een toe te voegen",
|
|
59
|
+
"Reset password email": "Wachtwoord opnieuw instellen e-mail",
|
|
60
|
+
"1. Select notification channel": "1. Selecteer meldingskanaal",
|
|
61
|
+
"2. Configure reset email": "2. Configureer reset e-mail",
|
|
62
|
+
"The notification channel used to send the reset password email, only support email channel": "Het notificatiekanaal dat wordt gebruikt om de e-mail voor het opnieuw instellen van het wachtwoord te verzenden, ondersteunt alleen het e-mailkanaal",
|
|
63
|
+
"Reset link expiration (minutes)": "Verloop van de resetlink (minuten)",
|
|
64
|
+
"Reset password link": "Wachtwoord opnieuw instellen link",
|
|
65
|
+
"Missing X-Authenticator in request header": "Ontbrekende X-Authenticator in de aanvraagheader",
|
|
66
|
+
"Reset email sent successfully": "Reset e-mail succesvol verzonden"
|
|
33
67
|
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -45,5 +45,39 @@
|
|
|
45
45
|
"The maximum time limit allowed for refreshing a Token after it expires. After this time limit, the token cannot be automatically renewed, and the user needs to log in again.": "Token 过期后允许刷新的最大时限,超过此时限后,Token 无法自动更新,用户需重新登录。",
|
|
46
46
|
"Your session has expired. Please sign in again.": "您的会话已过期,请重新登录。",
|
|
47
47
|
"Unauthenticated. Please sign in to continue.": "未认证。请登录以继续。",
|
|
48
|
-
"User not found. Please sign in again to continue.": "用户不存在。请重新登录以继续。"
|
|
48
|
+
"User not found. Please sign in again to continue.": "用户不存在。请重新登录以继续。",
|
|
49
|
+
"Email channel not found": "未找到邮件通道",
|
|
50
|
+
"Notification manager plugin not found": "未找到通知管理插件",
|
|
51
|
+
"Not allowed to reset password": "不允许重置密码",
|
|
52
|
+
"Token expired": "令牌已过期",
|
|
53
|
+
"User not found": "未找到用户",
|
|
54
|
+
"Forgot password": "忘记密码",
|
|
55
|
+
"Please enter your email": "请输入您的邮箱",
|
|
56
|
+
"Reset password": "重置密码",
|
|
57
|
+
"Back to login": "返回登录",
|
|
58
|
+
"Send reset email": "发送重置邮件",
|
|
59
|
+
"Reset link has expired": "重置链接已过期",
|
|
60
|
+
"Go to login": "前往登录",
|
|
61
|
+
"Please enter new password": "请输入新密码",
|
|
62
|
+
"Please enter the same password again": "请再次输入相同的密码",
|
|
63
|
+
"The passwords entered twice are inconsistent": "两次输入的密码不一致",
|
|
64
|
+
"Password reset successful": "密码重置成功",
|
|
65
|
+
"Enable forget password": "启用忘记密码功能",
|
|
66
|
+
"Notification channel (Email)": "通知渠道(电子邮件)",
|
|
67
|
+
"Subject": "主题",
|
|
68
|
+
"Content type": "内容类型",
|
|
69
|
+
"Plain text": "普通文本",
|
|
70
|
+
"defaultResetPasswordEmailSubject": "重置您的 {{$systemSettings.title}} 密码",
|
|
71
|
+
"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>",
|
|
72
|
+
"defaultResetPasswordEmailContentText": "您好 {{$user.username}},\n\n我们收到了重置您 {{$systemSettings.title}} 账户密码的请求。\n\n请点击下面的链接设置您的新密码:\n\n{{$resetLink}}\n\n如果您没有请求重置密码,请忽略此邮件。您的密码将保持不变。\n\n请注意:为了您的安全,此密码重置链接将在 {{$resetLinkExpiration}} 分钟后过期。\n\n如果您在重置密码时遇到任何问题,请联系我们的支持团队。\n\n谢谢,{{$systemSettings.title}} 团队",
|
|
73
|
+
"No notification channels found. Please ": "未找到通知渠道,请",
|
|
74
|
+
"add one first": "先添加一个",
|
|
75
|
+
"Reset password email": "重置密码邮件",
|
|
76
|
+
"1. Select notification channel": "1. 选择通知渠道",
|
|
77
|
+
"2. Configure reset email": "2. 配置重置邮件",
|
|
78
|
+
"The notification channel used to send the reset password email, only support email channel": "发送重置密码邮件所使用的通知渠道,仅支持电子邮件通道",
|
|
79
|
+
"Reset link expiration (minutes)": "重置链接有效期(分钟)",
|
|
80
|
+
"Reset password link": "重置密码链接",
|
|
81
|
+
"Missing X-Authenticator in request header": "请求头中缺少了 X-Authenticator",
|
|
82
|
+
"Reset email sent successfully": "重置邮件发送成功"
|
|
49
83
|
}
|
|
@@ -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":"2025-
|
|
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":"2025-06-04T02:26:10.295Z"}
|
|
@@ -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":"2025-
|
|
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":"2025-06-04T02:26:10.373Z"}
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Context, Next } from '@nocobase/actions';
|
|
10
10
|
declare const _default: {
|
|
11
|
+
lostPassword: (ctx: Context, next: Next) => Promise<void>;
|
|
12
|
+
resetPassword: (ctx: Context, next: Next) => Promise<void>;
|
|
13
|
+
checkResetToken: (ctx: Context, next: Next) => Promise<void>;
|
|
11
14
|
changePassword: (ctx: Context, next: Next) => Promise<void>;
|
|
12
15
|
};
|
|
13
16
|
export default _default;
|
|
@@ -32,18 +32,19 @@ module.exports = __toCommonJS(auth_exports);
|
|
|
32
32
|
var import_preset = require("../../preset");
|
|
33
33
|
/* istanbul ignore file -- @preserve */
|
|
34
34
|
var auth_default = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
lostPassword: async (ctx, next) => {
|
|
36
|
+
ctx.body = await ctx.auth.lostPassword();
|
|
37
|
+
await next();
|
|
38
|
+
},
|
|
39
|
+
resetPassword: async (ctx, next) => {
|
|
40
|
+
ctx.body = await ctx.auth.resetPassword();
|
|
41
|
+
await next();
|
|
42
|
+
},
|
|
43
|
+
checkResetToken: async (ctx, next) => {
|
|
44
|
+
const { resetToken } = ctx.action.params.values;
|
|
45
|
+
ctx.body = await ctx.auth.checkResetToken(resetToken);
|
|
46
|
+
await next();
|
|
47
|
+
},
|
|
47
48
|
changePassword: async (ctx, next) => {
|
|
48
49
|
const systemSettings = ctx.db.getRepository("systemSettings");
|
|
49
50
|
const settings = await systemSettings.findOne();
|
|
@@ -8,12 +8,18 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { AuthConfig, BaseAuth } from '@nocobase/auth';
|
|
10
10
|
export declare class BasicAuth extends BaseAuth {
|
|
11
|
+
static readonly optionsKeysNotAllowedInEnv: string[];
|
|
11
12
|
constructor(config: AuthConfig);
|
|
13
|
+
private isEmail;
|
|
12
14
|
validate(): Promise<any>;
|
|
13
15
|
private getSignupFormSettings;
|
|
14
16
|
private verfiySignupParams;
|
|
15
17
|
signUp(): Promise<any>;
|
|
18
|
+
private getEmailConfig;
|
|
16
19
|
lostPassword(): Promise<any>;
|
|
17
20
|
resetPassword(): Promise<any>;
|
|
18
|
-
|
|
21
|
+
/**
|
|
22
|
+
* 检查重置密码的 Token 是否有效
|
|
23
|
+
*/
|
|
24
|
+
checkResetToken(resetToken: string): Promise<boolean>;
|
|
19
25
|
}
|
|
@@ -40,14 +40,18 @@ __export(basic_auth_exports, {
|
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(basic_auth_exports);
|
|
42
42
|
var import_auth = require("@nocobase/auth");
|
|
43
|
-
var import_crypto = __toESM(require("crypto"));
|
|
44
|
-
var import_preset = require("../preset");
|
|
45
43
|
var import_lodash = __toESM(require("lodash"));
|
|
44
|
+
var import_preset = require("../preset");
|
|
45
|
+
var import_utils = require("@nocobase/utils");
|
|
46
46
|
class BasicAuth extends import_auth.BaseAuth {
|
|
47
|
+
static optionsKeysNotAllowedInEnv = ["emailContentText", "emailContentHTML", "emailSubject"];
|
|
47
48
|
constructor(config) {
|
|
48
49
|
const userCollection = config.ctx.db.getCollection("users");
|
|
49
50
|
super({ ...config, userCollection });
|
|
50
51
|
}
|
|
52
|
+
isEmail(value) {
|
|
53
|
+
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(value);
|
|
54
|
+
}
|
|
51
55
|
async validate() {
|
|
52
56
|
const ctx = this.ctx;
|
|
53
57
|
const {
|
|
@@ -73,7 +77,7 @@ class BasicAuth extends import_auth.BaseAuth {
|
|
|
73
77
|
const valid = await field.verify(password, user.password);
|
|
74
78
|
if (!valid) {
|
|
75
79
|
ctx.throw(401, ctx.t("The username/email or password is incorrect, please re-enter", { ns: import_preset.namespace }), {
|
|
76
|
-
|
|
80
|
+
internalCode: "INCORRECT_PASSWORD",
|
|
77
81
|
user
|
|
78
82
|
});
|
|
79
83
|
}
|
|
@@ -101,7 +105,7 @@ class BasicAuth extends import_auth.BaseAuth {
|
|
|
101
105
|
}
|
|
102
106
|
const emailSetting = signupFormSettings.find((item) => item.field === "email");
|
|
103
107
|
if (emailSetting && emailSetting.show) {
|
|
104
|
-
if (email &&
|
|
108
|
+
if (email && !this.isEmail(email)) {
|
|
105
109
|
throw new Error("Please enter a valid email address");
|
|
106
110
|
}
|
|
107
111
|
if (emailSetting.required && !email) {
|
|
@@ -142,15 +146,27 @@ class BasicAuth extends import_auth.BaseAuth {
|
|
|
142
146
|
const user = await User.create({ values: { ...userValues, password } });
|
|
143
147
|
return user;
|
|
144
148
|
}
|
|
145
|
-
|
|
149
|
+
getEmailConfig() {
|
|
150
|
+
var _a, _b;
|
|
151
|
+
const options = import_lodash.default.omit(this.authenticator.options, "public") || {};
|
|
152
|
+
return { ...options, enableResetPassword: (_b = (_a = this.authenticator.options) == null ? void 0 : _a.public) == null ? void 0 : _b.enableResetPassword };
|
|
153
|
+
}
|
|
146
154
|
async lostPassword() {
|
|
155
|
+
var _a;
|
|
147
156
|
const ctx = this.ctx;
|
|
148
157
|
const {
|
|
149
|
-
values: { email }
|
|
158
|
+
values: { email, baseURL }
|
|
150
159
|
} = ctx.action.params;
|
|
160
|
+
const authenticatorName = ctx.headers["x-authenticator"];
|
|
161
|
+
if (!authenticatorName) {
|
|
162
|
+
ctx.throw(400, ctx.t("Missing X-Authenticator in request header", { ns: import_preset.namespace }));
|
|
163
|
+
}
|
|
151
164
|
if (!email) {
|
|
152
165
|
ctx.throw(400, ctx.t("Please fill in your email address", { ns: import_preset.namespace }));
|
|
153
166
|
}
|
|
167
|
+
if (!this.isEmail(email)) {
|
|
168
|
+
ctx.throw(400, ctx.t("Incorrect email format", { ns: import_preset.namespace }));
|
|
169
|
+
}
|
|
154
170
|
const user = await this.userRepository.findOne({
|
|
155
171
|
where: {
|
|
156
172
|
email
|
|
@@ -159,44 +175,147 @@ class BasicAuth extends import_auth.BaseAuth {
|
|
|
159
175
|
if (!user) {
|
|
160
176
|
ctx.throw(401, ctx.t("The email is incorrect, please re-enter", { ns: import_preset.namespace }));
|
|
161
177
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
178
|
+
const {
|
|
179
|
+
notificationChannel,
|
|
180
|
+
emailContentType,
|
|
181
|
+
emailContentHTML,
|
|
182
|
+
emailContentText,
|
|
183
|
+
emailSubject,
|
|
184
|
+
enableResetPassword,
|
|
185
|
+
resetTokenExpiresIn
|
|
186
|
+
} = this.getEmailConfig();
|
|
187
|
+
if (!enableResetPassword) {
|
|
188
|
+
ctx.throw(403, ctx.t("Not allowed to reset password", { ns: import_preset.namespace }));
|
|
189
|
+
}
|
|
190
|
+
const resetToken = await ctx.app.authManager.jwt.sign(
|
|
191
|
+
{
|
|
192
|
+
resetPasswordUserId: user.id
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
expiresIn: resetTokenExpiresIn * 60
|
|
196
|
+
// 配置的过期时间,单位分钟,需要转成秒
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
const resetLink = `${baseURL}/reset-password?resetToken=${resetToken}&name=${authenticatorName}`;
|
|
200
|
+
const systemSettings = await ((_a = ctx.db.getRepository("systemSettings")) == null ? void 0 : _a.findOne()) || {};
|
|
201
|
+
const notificationManager = ctx.app.getPlugin("notification-manager");
|
|
202
|
+
if (notificationManager) {
|
|
203
|
+
const emailer = await notificationManager.manager.findChannel(notificationChannel);
|
|
204
|
+
if (emailer) {
|
|
205
|
+
try {
|
|
206
|
+
const parsedSubject = (0, import_utils.parsedValue)(emailSubject, {
|
|
207
|
+
$user: user,
|
|
208
|
+
$resetLink: resetLink,
|
|
209
|
+
$env: ctx.app.environment.getVariables(),
|
|
210
|
+
$resetLinkExpiration: resetTokenExpiresIn,
|
|
211
|
+
$systemSettings: systemSettings
|
|
212
|
+
});
|
|
213
|
+
const parsedContent = (0, import_utils.parsedValue)(emailContentType === "html" ? emailContentHTML : emailContentText, {
|
|
214
|
+
$user: user,
|
|
215
|
+
$resetLink: resetLink,
|
|
216
|
+
$env: ctx.app.environment.getVariables(),
|
|
217
|
+
$resetLinkExpiration: resetTokenExpiresIn,
|
|
218
|
+
$systemSettings: systemSettings
|
|
219
|
+
});
|
|
220
|
+
const content = emailContentType === "html" ? { html: parsedContent } : { text: parsedContent };
|
|
221
|
+
try {
|
|
222
|
+
await notificationManager.send({
|
|
223
|
+
channelName: notificationChannel,
|
|
224
|
+
message: {
|
|
225
|
+
to: [email],
|
|
226
|
+
subject: parsedSubject,
|
|
227
|
+
contentType: emailContentType,
|
|
228
|
+
...content
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
ctx.logger.info(`Password reset email sent to ${email}`);
|
|
232
|
+
} catch (error) {
|
|
233
|
+
ctx.logger.error(`Failed to send reset password email: ${error.message}`, {
|
|
234
|
+
error,
|
|
235
|
+
email,
|
|
236
|
+
notificationChannel
|
|
237
|
+
});
|
|
238
|
+
ctx.throw(
|
|
239
|
+
500,
|
|
240
|
+
ctx.t("Failed to send email. Error: {{error}}", {
|
|
241
|
+
ns: import_preset.namespace,
|
|
242
|
+
error: error.message
|
|
243
|
+
})
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
} catch (error) {
|
|
247
|
+
ctx.logger.error(`Error parsing email template variables: ${error.message}`, {
|
|
248
|
+
error,
|
|
249
|
+
emailSubject,
|
|
250
|
+
emailContentType
|
|
251
|
+
});
|
|
252
|
+
ctx.throw(
|
|
253
|
+
500,
|
|
254
|
+
ctx.t("Error parsing email template. Error: {{error}}", {
|
|
255
|
+
ns: import_preset.namespace,
|
|
256
|
+
error: error.message
|
|
257
|
+
})
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
ctx.throw(400, ctx.t("Email channel not found", { ns: import_preset.namespace }));
|
|
262
|
+
}
|
|
263
|
+
} else {
|
|
264
|
+
ctx.throw(500, ctx.t("Notification manager plugin not found", { ns: import_preset.namespace }));
|
|
265
|
+
}
|
|
266
|
+
ctx.logger.info(`Password reset email sent to ${email}`);
|
|
267
|
+
return null;
|
|
165
268
|
}
|
|
166
|
-
/* istanbul ignore next -- @preserve */
|
|
167
269
|
async resetPassword() {
|
|
168
270
|
const ctx = this.ctx;
|
|
169
271
|
const {
|
|
170
|
-
values: {
|
|
272
|
+
values: { password, resetToken }
|
|
171
273
|
} = ctx.action.params;
|
|
274
|
+
if (!resetToken) {
|
|
275
|
+
ctx.throw(401, ctx.t("Token expired", { ns: import_preset.namespace }));
|
|
276
|
+
}
|
|
277
|
+
try {
|
|
278
|
+
await this.checkResetToken(resetToken);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
let decodedToken;
|
|
283
|
+
try {
|
|
284
|
+
decodedToken = await ctx.app.authManager.jwt.decode(resetToken);
|
|
285
|
+
} catch (error) {
|
|
286
|
+
ctx.throw(401, ctx.t("Token expired", { ns: import_preset.namespace }));
|
|
287
|
+
}
|
|
172
288
|
const user = await this.userRepository.findOne({
|
|
173
289
|
where: {
|
|
174
|
-
|
|
175
|
-
resetToken
|
|
290
|
+
id: decodedToken.resetPasswordUserId
|
|
176
291
|
}
|
|
177
292
|
});
|
|
178
293
|
if (!user) {
|
|
179
|
-
ctx.throw(404);
|
|
294
|
+
ctx.throw(404, ctx.t("User not found", { ns: import_preset.namespace }));
|
|
180
295
|
}
|
|
181
|
-
user.token = null;
|
|
182
|
-
user.resetToken = null;
|
|
183
296
|
user.password = password;
|
|
184
297
|
await user.save();
|
|
185
|
-
|
|
298
|
+
await ctx.app.authManager.jwt.block(resetToken);
|
|
299
|
+
ctx.logger.info(`Password for user ${user.id} has been reset`);
|
|
300
|
+
return null;
|
|
186
301
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
302
|
+
/**
|
|
303
|
+
* 检查重置密码的 Token 是否有效
|
|
304
|
+
*/
|
|
305
|
+
async checkResetToken(resetToken) {
|
|
306
|
+
if (!resetToken) {
|
|
307
|
+
this.ctx.throw(401, this.ctx.t("Token expired", { ns: import_preset.namespace }));
|
|
308
|
+
}
|
|
309
|
+
const blocked = await this.jwt.blacklist.has(resetToken);
|
|
310
|
+
if (blocked) {
|
|
311
|
+
this.ctx.throw(401, this.ctx.t("Token expired", { ns: import_preset.namespace }));
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
await this.ctx.app.authManager.jwt.decode(resetToken);
|
|
315
|
+
return true;
|
|
316
|
+
} catch (err) {
|
|
317
|
+
this.ctx.throw(401, this.ctx.t("Token expired", { ns: import_preset.namespace }));
|
|
198
318
|
}
|
|
199
|
-
return user;
|
|
200
319
|
}
|
|
201
320
|
}
|
|
202
321
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -5,4 +5,4 @@
|
|
|
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
7
|
"The phone number is not registered, please register first": "The phone number is not registered, please register first"
|
|
8
|
-
}
|
|
8
|
+
}
|
package/dist/server/plugin.js
CHANGED
|
@@ -135,6 +135,9 @@ class PluginAuthServer extends import_server.Plugin {
|
|
|
135
135
|
);
|
|
136
136
|
["signIn", "signUp"].forEach((action) => this.app.acl.allow("auth", action));
|
|
137
137
|
["check", "signOut", "changePassword"].forEach((action) => this.app.acl.allow("auth", action, "loggedIn"));
|
|
138
|
+
["lostPassword", "resetPassword", "checkResetToken"].forEach(
|
|
139
|
+
(action) => this.app.acl.allow("auth", action, "public")
|
|
140
|
+
);
|
|
138
141
|
this.app.acl.allow("authenticators", "publicList");
|
|
139
142
|
this.app.acl.registerSnippet({
|
|
140
143
|
name: `pm.${this.name}.authenticators`,
|
|
@@ -229,22 +232,15 @@ class PluginAuthServer extends import_server.Plugin {
|
|
|
229
232
|
filterByTk: userId
|
|
230
233
|
});
|
|
231
234
|
const roles = await (user == null ? void 0 : user.getRoles());
|
|
232
|
-
if (
|
|
235
|
+
if (roles && roles.length === 1) {
|
|
233
236
|
return {
|
|
234
|
-
userId
|
|
237
|
+
userId,
|
|
238
|
+
roleName: roles[0].name
|
|
235
239
|
};
|
|
236
|
-
} else {
|
|
237
|
-
if (roles.length === 1) {
|
|
238
|
-
return {
|
|
239
|
-
userId,
|
|
240
|
-
roleName: roles[0].name
|
|
241
|
-
};
|
|
242
|
-
} else {
|
|
243
|
-
return {
|
|
244
|
-
userId
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
240
|
}
|
|
241
|
+
return {
|
|
242
|
+
userId
|
|
243
|
+
};
|
|
248
244
|
}
|
|
249
245
|
},
|
|
250
246
|
{
|
|
@@ -25,7 +25,7 @@ export declare class TokenController implements TokenControlService {
|
|
|
25
25
|
setTokenInfo(id: string, value: TokenInfo): Promise<void>;
|
|
26
26
|
getConfig(): Promise<NumericTokenPolicyConfig>;
|
|
27
27
|
setConfig(config: TokenPolicyConfig): Promise<void>;
|
|
28
|
-
removeSessionExpiredTokens(userId: number): Promise<
|
|
28
|
+
removeSessionExpiredTokens(userId: number): Promise<number>;
|
|
29
29
|
add({ userId }: {
|
|
30
30
|
userId: number;
|
|
31
31
|
}): Promise<{
|
|
@@ -42,6 +42,7 @@ module.exports = __toCommonJS(token_controller_exports);
|
|
|
42
42
|
var import_auth = require("@nocobase/auth");
|
|
43
43
|
var import_crypto = require("crypto");
|
|
44
44
|
var import_ms = __toESM(require("ms"));
|
|
45
|
+
var import_database = require("@nocobase/database");
|
|
45
46
|
var import_constants = require("../constants");
|
|
46
47
|
const JTICACHEKEY = "token-jti";
|
|
47
48
|
class TokenController {
|
|
@@ -81,13 +82,13 @@ class TokenController {
|
|
|
81
82
|
}
|
|
82
83
|
async removeSessionExpiredTokens(userId) {
|
|
83
84
|
const config = await this.getConfig();
|
|
84
|
-
const
|
|
85
|
+
const model = this.app.db.getModel(import_constants.issuedTokensCollectionName);
|
|
85
86
|
const currTS = Date.now();
|
|
86
|
-
return
|
|
87
|
-
|
|
87
|
+
return model.destroy({
|
|
88
|
+
where: {
|
|
88
89
|
userId,
|
|
89
90
|
signInTime: {
|
|
90
|
-
|
|
91
|
+
[import_database.Op.lt]: currTS - config.sessionExpirationTime
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
});
|
package/dist/swagger/index.js
CHANGED
|
@@ -309,46 +309,6 @@ var swagger_default = {
|
|
|
309
309
|
// },
|
|
310
310
|
// },
|
|
311
311
|
// },
|
|
312
|
-
// '/auth:getUserByResetToken': {
|
|
313
|
-
// get: {
|
|
314
|
-
// description: 'Get user by reset token',
|
|
315
|
-
// tags: ['Basic auth'],
|
|
316
|
-
// security: [],
|
|
317
|
-
// parameters: [
|
|
318
|
-
// {
|
|
319
|
-
// name: 'token',
|
|
320
|
-
// in: 'query',
|
|
321
|
-
// description: '重置密码的token',
|
|
322
|
-
// required: true,
|
|
323
|
-
// schema: {
|
|
324
|
-
// type: 'string',
|
|
325
|
-
// },
|
|
326
|
-
// },
|
|
327
|
-
// ],
|
|
328
|
-
// responses: {
|
|
329
|
-
// 200: {
|
|
330
|
-
// description: 'ok',
|
|
331
|
-
// content: {
|
|
332
|
-
// 'application/json': {
|
|
333
|
-
// schema: {
|
|
334
|
-
// $ref: '#/components/schemas/user',
|
|
335
|
-
// },
|
|
336
|
-
// },
|
|
337
|
-
// },
|
|
338
|
-
// },
|
|
339
|
-
// 401: {
|
|
340
|
-
// description: 'Unauthorized',
|
|
341
|
-
// content: {
|
|
342
|
-
// 'application/json': {
|
|
343
|
-
// schema: {
|
|
344
|
-
// $ref: '#/components/schemas/error',
|
|
345
|
-
// },
|
|
346
|
-
// },
|
|
347
|
-
// },
|
|
348
|
-
// },
|
|
349
|
-
// },
|
|
350
|
-
// },
|
|
351
|
-
// },
|
|
352
312
|
"/auth:changePassword": {
|
|
353
313
|
post: {
|
|
354
314
|
description: "Change password",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0-alpha.1",
|
|
4
4
|
"main": "./dist/server/index.js",
|
|
5
5
|
"homepage": "https://docs.nocobase.com/handbook/auth",
|
|
6
6
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/auth",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"displayName.zh-CN": "用户认证",
|
|
28
28
|
"description": "User authentication management, including password, SMS, and support for Single Sign-On (SSO) protocols, with extensibility.",
|
|
29
29
|
"description.zh-CN": "用户认证管理,包括基础的密码认证、短信认证、SSO 协议的认证等,可扩展。",
|
|
30
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "bc81ea73ed91b18dfb7cfad0f353b825881b4cc7",
|
|
31
31
|
"keywords": [
|
|
32
32
|
"Authentication",
|
|
33
33
|
"Security"
|