@lenne.tech/nest-server 11.38.0 → 11.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/rules/configurable-features.md +23 -1
- package/.claude/rules/package-management.md +66 -0
- package/.claude/rules/testing.md +59 -5
- package/FRAMEWORK-API.md +1 -1
- package/dist/config.env.js +4 -2
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/config.helper.d.ts +2 -0
- package/dist/core/common/helpers/config.helper.js +18 -0
- package/dist/core/common/helpers/config.helper.js.map +1 -1
- package/dist/core/common/helpers/cookies.helper.d.ts +3 -0
- package/dist/core/common/helpers/cookies.helper.js +9 -0
- package/dist/core/common/helpers/cookies.helper.js.map +1 -1
- package/dist/core/common/helpers/input.helper.d.ts +1 -0
- package/dist/core/common/helpers/input.helper.js +4 -0
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/helpers/service.helper.js +6 -1
- package/dist/core/common/helpers/service.helper.js.map +1 -1
- package/dist/core/common/interceptors/check-security.interceptor.js +1 -0
- package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +1 -0
- package/dist/core/common/services/email.service.d.ts +4 -1
- package/dist/core/common/services/email.service.js +25 -2
- package/dist/core/common/services/email.service.js.map +1 -1
- package/dist/core/common/services/module.service.js +1 -0
- package/dist/core/common/services/module.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js +7 -0
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +3 -1
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-email-verification.service.d.ts +3 -1
- package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js +30 -5
- package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-error-codes.helper.d.ts +2 -0
- package/dist/core/modules/better-auth/core-better-auth-error-codes.helper.js +54 -0
- package/dist/core/modules/better-auth/core-better-auth-error-codes.helper.js.map +1 -0
- package/dist/core/modules/better-auth/index.d.ts +1 -0
- package/dist/core/modules/better-auth/index.js +1 -0
- package/dist/core/modules/better-auth/index.js.map +1 -1
- package/dist/core/modules/error-code/error-codes.d.ts +27 -0
- package/dist/core/modules/error-code/error-codes.js +24 -0
- package/dist/core/modules/error-code/error-codes.js.map +1 -1
- package/dist/core/modules/hub/core-hub.service.js +1 -0
- package/dist/core/modules/hub/core-hub.service.js.map +1 -1
- package/dist/core/modules/user/core-user.model.d.ts +1 -0
- package/dist/core/modules/user/core-user.model.js +11 -1
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core/modules/user/core-user.service.d.ts +9 -0
- package/dist/core/modules/user/core-user.service.js +96 -4
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/server/modules/error-code/error-codes.d.ts +3 -0
- package/dist/server/modules/user/user.model.d.ts +5 -0
- package/dist/server/modules/user/user.service.js +12 -6
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/templates/password-reset-de.ejs +12 -0
- package/dist/templates/password-reset-en.ejs +12 -0
- package/dist/templates/password-reset.ejs +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +14 -0
- package/migration-guides/11.37.x-to-11.38.x.md +18 -1
- package/migration-guides/11.38.x-to-11.39.x.md +456 -0
- package/package.json +1 -1
- package/src/config.env.ts +19 -3
- package/src/core/common/helpers/config.helper.ts +79 -0
- package/src/core/common/helpers/cookies.helper.ts +38 -0
- package/src/core/common/helpers/input.helper.ts +37 -0
- package/src/core/common/helpers/service.helper.ts +9 -1
- package/src/core/common/interceptors/check-security.interceptor.ts +1 -0
- package/src/core/common/interfaces/server-options.interface.ts +103 -3
- package/src/core/common/services/email.service.ts +46 -1
- package/src/core/common/services/module.service.ts +1 -0
- package/src/core/modules/better-auth/better-auth.config.ts +25 -0
- package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +8 -1
- package/src/core/modules/better-auth/core-better-auth-email-verification.service.ts +101 -6
- package/src/core/modules/better-auth/core-better-auth-error-codes.helper.ts +146 -0
- package/src/core/modules/better-auth/index.ts +1 -0
- package/src/core/modules/error-code/error-codes.ts +55 -0
- package/src/core/modules/hub/core-hub.service.ts +1 -0
- package/src/core/modules/user/core-user.model.ts +28 -1
- package/src/core/modules/user/core-user.service.ts +267 -5
- package/src/server/modules/user/user.service.ts +26 -7
- package/src/templates/password-reset-de.ejs +12 -0
- package/src/templates/password-reset-en.ejs +12 -0
- package/src/templates/password-reset.ejs +1 -0
|
@@ -91,21 +91,40 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
|
|
|
91
91
|
* Better-Auth makes on the IAM path.
|
|
92
92
|
*/
|
|
93
93
|
async sendPasswordResetMail(email: string, serviceOptions?: ServiceOptions): Promise<null | User> {
|
|
94
|
-
//
|
|
95
|
-
|
|
94
|
+
// `createPasswordResetToken`, not `setPasswordResetTokenForEmail`: the latter returns the user
|
|
95
|
+
// through `process()`, where the security interceptor strips `passwordResetToken`. Reading the
|
|
96
|
+
// token off that object is what mailed the word `undefined` to a real recipient.
|
|
97
|
+
const created = await this.createPasswordResetToken(email, serviceOptions);
|
|
96
98
|
|
|
97
|
-
if (!
|
|
99
|
+
if (!created) {
|
|
98
100
|
// Unknown address, enumeration protection on. Answer exactly as for a known one.
|
|
99
101
|
return null;
|
|
100
102
|
}
|
|
101
103
|
|
|
104
|
+
// `buildPasswordResetLink`, not string concatenation: `email.passwordResetLink` has no default,
|
|
105
|
+
// and this config file does not set one, so concatenating produced `undefined/<token>`.
|
|
106
|
+
const link = this.buildPasswordResetLink(created.token);
|
|
107
|
+
if (!link) {
|
|
108
|
+
// Sending a mail whose link cannot work is worse than sending none. The recipient has no
|
|
109
|
+
// second way in, and a dead link gives them nothing to act on — while no mail at least reads
|
|
110
|
+
// as "try again". The address is still answered exactly as a known one.
|
|
111
|
+
this.userServiceLogger.error(
|
|
112
|
+
'Password reset mail not sent: no reset link could be built. Set `email.passwordResetLink` or `appUrl`.',
|
|
113
|
+
);
|
|
114
|
+
return created.user;
|
|
115
|
+
}
|
|
116
|
+
|
|
102
117
|
// Deliberately NOT awaited — see the note above.
|
|
103
118
|
void this.emailService
|
|
104
|
-
.sendMail(user.email, 'Password reset', {
|
|
119
|
+
.sendMail(created.user.email, 'Password reset', {
|
|
105
120
|
htmlTemplate: 'password-reset',
|
|
106
121
|
templateData: {
|
|
107
|
-
link
|
|
108
|
-
|
|
122
|
+
link,
|
|
123
|
+
// The mail is the only place the recipient can learn there IS a deadline. Without it an
|
|
124
|
+
// expired link is indistinguishable from a broken one — the same experience this whole
|
|
125
|
+
// area was repaired for.
|
|
126
|
+
linkExpiresInMinutes: this.passwordResetTokenExpiryMinutes(),
|
|
127
|
+
name: created.user.username,
|
|
109
128
|
},
|
|
110
129
|
})
|
|
111
130
|
.catch((error: unknown) => {
|
|
@@ -115,7 +134,7 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
|
|
|
115
134
|
});
|
|
116
135
|
|
|
117
136
|
// Return user
|
|
118
|
-
return user;
|
|
137
|
+
return created.user;
|
|
119
138
|
}
|
|
120
139
|
|
|
121
140
|
/**
|
|
@@ -50,6 +50,18 @@
|
|
|
50
50
|
Falls die Schaltfläche nicht funktioniert, kopiere diesen Link in deinen Browser:<br>
|
|
51
51
|
<a href="<%= link %>" style="color:#1d4ed8; word-break:break-all; overflow-wrap:break-word;"><%= link %></a>
|
|
52
52
|
</p>
|
|
53
|
+
<%
|
|
54
|
+
/* Optional, like `appName`: a caller that omits it must not turn a password-reset
|
|
55
|
+
mail into a 500. Rendered only for a real, positive value — a deployment that
|
|
56
|
+
switched the expiry off (`0`) has no deadline to announce. */
|
|
57
|
+
const expiryMinutes = (typeof linkExpiresInMinutes !== 'undefined' && Number(linkExpiresInMinutes) > 0)
|
|
58
|
+
? Number(linkExpiresInMinutes) : 0;
|
|
59
|
+
-%>
|
|
60
|
+
<% if (expiryMinutes) { %>
|
|
61
|
+
<p style="margin:16px 0 0 0; font-size:13px; line-height:20px; color:#737373;">
|
|
62
|
+
Der Link ist <%= expiryMinutes %> Minuten lang gültig. Danach kannst du einfach einen neuen anfordern.
|
|
63
|
+
</p>
|
|
64
|
+
<% } %>
|
|
53
65
|
</td>
|
|
54
66
|
</tr>
|
|
55
67
|
<tr>
|
|
@@ -50,6 +50,18 @@
|
|
|
50
50
|
If the button doesn't work, copy and paste this link into your browser:<br>
|
|
51
51
|
<a href="<%= link %>" style="color:#1d4ed8; word-break:break-all; overflow-wrap:break-word;"><%= link %></a>
|
|
52
52
|
</p>
|
|
53
|
+
<%
|
|
54
|
+
/* Optional, like `appName`: a caller that omits it must not turn a password-reset
|
|
55
|
+
mail into a 500. Rendered only for a real, positive value — a deployment that
|
|
56
|
+
switched the expiry off (`0`) has no deadline to announce. */
|
|
57
|
+
const expiryMinutes = (typeof linkExpiresInMinutes !== 'undefined' && Number(linkExpiresInMinutes) > 0)
|
|
58
|
+
? Number(linkExpiresInMinutes) : 0;
|
|
59
|
+
-%>
|
|
60
|
+
<% if (expiryMinutes) { %>
|
|
61
|
+
<p style="margin:16px 0 0 0; font-size:13px; line-height:20px; color:#737373;">
|
|
62
|
+
This link is valid for <%= expiryMinutes %> minutes. After that, just request a new one.
|
|
63
|
+
</p>
|
|
64
|
+
<% } %>
|
|
53
65
|
</td>
|
|
54
66
|
</tr>
|
|
55
67
|
<tr>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
<h1>Hello <%= name %>,</h1>
|
|
2
2
|
<p>you requested a link for setting a new password. Here it is.</p><br />
|
|
3
3
|
<a href="<%= link %>">Reset password</a>
|
|
4
|
+
<% if (typeof linkExpiresInMinutes !== 'undefined' && Number(linkExpiresInMinutes) > 0) { %><br /><p>This link is valid for <%= Number(linkExpiresInMinutes) %> minutes. After that, just request a new one.</p><% } %>
|