najm-auth 4.0.1 → 4.0.2

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/README.md CHANGED
@@ -138,8 +138,9 @@ auth({
138
138
  publicRegistration?: boolean // Default: true; mounts POST /auth/register
139
139
  bcryptRounds?: number // Default: 10 (valid: 4-31)
140
140
 
141
- // Frontend
142
- frontendUrl?: string // Password reset link base URL
141
+ // Frontend
142
+ frontendUrl?: string // Password reset link base URL
143
+ appName?: string // Security email brand (default: 'Your app')
143
144
 
144
145
  // Login identifier normalization (see "Identity presets")
145
146
  identity?: {
@@ -1130,10 +1131,16 @@ consumption. Once consumed, a token stays consumed even if the later user
1130
1131
  mutation fails; restoring it would make the link replayable, so the user must
1131
1132
  request a new one.
1132
1133
 
1133
- Accepting an account invitation also marks the destination email verified and
1134
- activates the account when its status is `pending`. An ordinary password reset
1135
- changes neither verification nor lifecycle status, and an explicitly inactive
1136
- invited account remains inactive.
1134
+ Accepting an account invitation also marks the destination email verified and
1135
+ activates the account when its status is `pending`. An ordinary password reset
1136
+ changes neither verification nor lifecycle status, and an explicitly inactive
1137
+ invited account remains inactive.
1138
+
1139
+ Set `appName` on `auth()` to brand the invitation subject and email card. The
1140
+ provisioned role is presented as the account type, so a sponsor invitation can
1141
+ say “Activate your sponsor account” without application-owned HTML. The shared
1142
+ template uses inline critical styles for Gmail and keeps the raw token URL out
1143
+ of visible fallback copy.
1137
1144
 
1138
1145
  The built-in memory and Redis drivers implement the required atomic primitive.
1139
1146
  A custom cache driver may omit `compareAndDelete()` for compatibility with
package/dist/index.d.ts CHANGED
@@ -198,6 +198,8 @@ interface AuthConfig {
198
198
  defaultRole: string | null;
199
199
  /** Frontend URL for password reset links (default: 'http://localhost:3000') */
200
200
  frontendUrl: string;
201
+ /** Product name used in security email subjects and templates. */
202
+ appName: string;
201
203
  /** Registration mode: 'active' auto-activates, 'pending' requires admin approval (default: 'active') */
202
204
  registrationMode: 'active' | 'pending';
203
205
  /** Whether the unauthenticated POST /auth/register route is mounted. */
@@ -265,6 +267,8 @@ type AuthPluginConfig = {
265
267
  defaultRole?: string | null;
266
268
  /** Frontend URL for password reset links. Falls back to FRONTEND_URL env var, then 'http://localhost:3000' */
267
269
  frontendUrl?: string;
270
+ /** Product name used in account invitation emails (default: 'Your app'). */
271
+ appName?: string;
268
272
  /** Registration mode: 'active' auto-activates new users, 'pending' requires admin approval (default: 'active') */
269
273
  registrationMode?: 'active' | 'pending';
270
274
  /**
@@ -432,7 +436,7 @@ var auth = {
432
436
  subject: "Reset your password"
433
437
  },
434
438
  accountInvite: {
435
- subject: "You've been invited — set up your account"
439
+ subject: "{{appName}}: activate your {{accountLabel}}"
436
440
  }
437
441
  }
438
442
  };
package/dist/index.js CHANGED
@@ -3488,9 +3488,16 @@ var AuthService = class AuthService2 {
3488
3488
  });
3489
3489
  const { token } = await this.tokenService.generateInviteToken(user.id);
3490
3490
  const inviteLink = `${this.config.frontendUrl}/reset-password?token=${token}`;
3491
+ const accountType = body.role?.trim().toLowerCase();
3492
+ const accountLabel = accountType ? `${accountType} account` : "account";
3491
3493
  let emailSent = false;
3492
3494
  try {
3493
- await this.emailService.sendHtml(body.email, this.t("emails.accountInvite.subject"), accountInviteTemplate({
3495
+ await this.emailService.sendHtml(body.email, this.t("emails.accountInvite.subject", {
3496
+ accountLabel,
3497
+ appName: this.config.appName
3498
+ }), accountInviteTemplate({
3499
+ accountType,
3500
+ appName: this.config.appName,
3494
3501
  inviteLink,
3495
3502
  userName: user.name || body.email
3496
3503
  }));
@@ -6346,7 +6353,7 @@ var en_default = {
6346
6353
  subject: "Reset your password"
6347
6354
  },
6348
6355
  accountInvite: {
6349
- subject: "You've been invited \u2014 set up your account"
6356
+ subject: "{{appName}}: activate your {{accountLabel}}"
6350
6357
  }
6351
6358
  }
6352
6359
  },
@@ -7478,6 +7485,13 @@ var validateCallbackUrl = /* @__PURE__ */ __name((value, name) => {
7478
7485
  }
7479
7486
  return callback.toString();
7480
7487
  }, "validateCallbackUrl");
7488
+ var resolveAppName = /* @__PURE__ */ __name((value) => {
7489
+ const appName = value?.trim() || "Your app";
7490
+ if (appName.length > 80 || /[\u0000-\u001f\u007f]/.test(appName)) {
7491
+ throw new Error("auth.appName must be at most 80 characters without control characters");
7492
+ }
7493
+ return appName;
7494
+ }, "resolveAppName");
7481
7495
  var resolveGoogleConfig = /* @__PURE__ */ __name((config) => {
7482
7496
  const configuredGoogle = config?.oauth?.google;
7483
7497
  if (!configuredGoogle)
@@ -7554,6 +7568,7 @@ var resolveAuthConfig = /* @__PURE__ */ __name((config) => {
7554
7568
  blacklistPrefix: config?.blacklistPrefix ?? "auth:blacklist:",
7555
7569
  defaultRole: config?.defaultRole ?? null,
7556
7570
  frontendUrl: config?.frontendUrl ?? process.env.FRONTEND_URL ?? "http://localhost:3000",
7571
+ appName: resolveAppName(config?.appName),
7557
7572
  registrationMode: config?.registrationMode ?? "active",
7558
7573
  publicRegistration: config?.publicRegistration ?? true,
7559
7574
  requireVerifiedEmail: config?.requireVerifiedEmail ?? false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "najm-auth",
3
- "version": "4.0.1",
3
+ "version": "4.0.2",
4
4
  "description": "Authentication and authorization library for najm framework",
5
5
  "type": "module",
6
6
  "files": [
@@ -97,7 +97,7 @@
97
97
  "najm-guard": "^2.0.2",
98
98
  "najm-i18n": "^2.1.2",
99
99
  "najm-cache": "^2.2.0",
100
- "najm-email": "^2.0.3",
100
+ "najm-email": "^2.0.4",
101
101
  "najm-rate": "^2.1.1",
102
102
  "najm-validation": "^2.0.2",
103
103
  "jsonwebtoken": "^9.0.3",