@syncello/auth 3.5.0 → 3.6.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/dist/index.cjs +66 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +66 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1341,12 +1341,13 @@ var import_drizzle_orm4 = require("drizzle-orm");
|
|
|
1341
1341
|
|
|
1342
1342
|
// src/factory.ts
|
|
1343
1343
|
function createAuth(config) {
|
|
1344
|
-
const { db, schema, getEnv, emailBranding } = config;
|
|
1344
|
+
const { db, schema, getEnv, emailBranding, invitations } = config;
|
|
1345
1345
|
const getContext = (c) => ({
|
|
1346
1346
|
db,
|
|
1347
1347
|
schema,
|
|
1348
1348
|
env: getEnv(c),
|
|
1349
|
-
emailBranding
|
|
1349
|
+
emailBranding,
|
|
1350
|
+
invitations
|
|
1350
1351
|
});
|
|
1351
1352
|
return {
|
|
1352
1353
|
db,
|
|
@@ -3324,7 +3325,10 @@ var signupRequestSchema = import_zod_openapi.z.object({
|
|
|
3324
3325
|
name: import_zod_openapi.z.string().min(1).optional().openapi({ example: "John Doe" }),
|
|
3325
3326
|
turnstileToken: import_zod_openapi.z.string().optional().openapi({ example: "XXXX.DUMMY.TOKEN.XXXX" }),
|
|
3326
3327
|
// OAuth signup completion token (from /signup?oauth_token=...)
|
|
3327
|
-
oauthToken: import_zod_openapi.z.string().optional().openapi({ example: "a1b2c3d4-..." })
|
|
3328
|
+
oauthToken: import_zod_openapi.z.string().optional().openapi({ example: "a1b2c3d4-..." }),
|
|
3329
|
+
// App invitation token (from /signup?token=...). When it validates for this
|
|
3330
|
+
// email, the account is created already-verified with no verification email.
|
|
3331
|
+
invitationToken: import_zod_openapi.z.string().optional().openapi({ example: "iIB8tDJJ..." })
|
|
3328
3332
|
}).openapi("SignupRequest");
|
|
3329
3333
|
var loginRequestSchema = import_zod_openapi.z.object({
|
|
3330
3334
|
email: import_zod_openapi.z.string().email().openapi({ example: "user@example.com" }),
|
|
@@ -3454,8 +3458,8 @@ var signupRoute = (0, import_zod_openapi2.createRoute)({
|
|
|
3454
3458
|
}
|
|
3455
3459
|
});
|
|
3456
3460
|
var signupHandler = async (c) => {
|
|
3457
|
-
const { email, password, name, turnstileToken, oauthToken } = c.req.valid("json");
|
|
3458
|
-
const { db: database, schema, emailBranding } = getAuthContext(c);
|
|
3461
|
+
const { email, password, name, turnstileToken, oauthToken, invitationToken } = c.req.valid("json");
|
|
3462
|
+
const { db: database, schema, emailBranding, invitations } = getAuthContext(c);
|
|
3459
3463
|
const env = c.env;
|
|
3460
3464
|
if (oauthToken) {
|
|
3461
3465
|
const stored = await env.OAUTH_STATES.get(`oauth:signup:${oauthToken}`);
|
|
@@ -3537,40 +3541,74 @@ var signupHandler = async (c) => {
|
|
|
3537
3541
|
return problems.badRequest(c, passwordValidation.error || "Invalid password");
|
|
3538
3542
|
}
|
|
3539
3543
|
const hashedPassword = await hashPassword(password, env.PASSWORD_PEPPER_V1);
|
|
3544
|
+
let invitedVerified = false;
|
|
3545
|
+
if (invitationToken && invitations) {
|
|
3546
|
+
const match = await invitations.verify({
|
|
3547
|
+
token: invitationToken,
|
|
3548
|
+
email: email.toLowerCase(),
|
|
3549
|
+
db: database,
|
|
3550
|
+
env
|
|
3551
|
+
});
|
|
3552
|
+
if (!match || match.email.toLowerCase() !== email.toLowerCase()) {
|
|
3553
|
+
return problems.badRequest(
|
|
3554
|
+
c,
|
|
3555
|
+
"This invitation is invalid, expired, or for a different email address"
|
|
3556
|
+
);
|
|
3557
|
+
}
|
|
3558
|
+
invitedVerified = true;
|
|
3559
|
+
}
|
|
3540
3560
|
const [newUser] = await database.insert(schema.users).values({
|
|
3541
3561
|
email: email.toLowerCase(),
|
|
3542
3562
|
name: name || null,
|
|
3543
3563
|
hashedPassword,
|
|
3544
3564
|
pepperKid: "v1",
|
|
3545
|
-
emailVerified:
|
|
3565
|
+
emailVerified: invitedVerified,
|
|
3546
3566
|
activatedAt: /* @__PURE__ */ new Date()
|
|
3547
3567
|
}).returning();
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
expiresAt,
|
|
3556
|
-
createdAt: Date.now()
|
|
3557
|
-
});
|
|
3558
|
-
const emailService = new EmailService(env, void 0, emailBranding);
|
|
3559
|
-
const verificationUrl = `${env.APP_URL}/verify-email?token=${emailToken}`;
|
|
3560
|
-
await emailService.sendVerificationEmail(
|
|
3561
|
-
{
|
|
3568
|
+
if (!invitedVerified) {
|
|
3569
|
+
const emailToken = generateSecureToken(32);
|
|
3570
|
+
const tokenHash = await hashToken(emailToken);
|
|
3571
|
+
const expiresAt = Date.now() + 24 * 60 * 60 * 1e3;
|
|
3572
|
+
await database.insert(schema.emailVerificationTokens).values({
|
|
3573
|
+
tokenHash,
|
|
3574
|
+
userId: newUser.id,
|
|
3562
3575
|
email: newUser.email,
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3576
|
+
expiresAt,
|
|
3577
|
+
createdAt: Date.now()
|
|
3578
|
+
});
|
|
3579
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
3580
|
+
const verificationUrl = `${env.APP_URL}/verify-email?token=${emailToken}`;
|
|
3581
|
+
await emailService.sendVerificationEmail(
|
|
3582
|
+
{
|
|
3583
|
+
email: newUser.email,
|
|
3584
|
+
token: emailToken,
|
|
3585
|
+
verificationUrl,
|
|
3586
|
+
firstName: newUser.name || void 0
|
|
3587
|
+
},
|
|
3588
|
+
database,
|
|
3589
|
+
schema.users
|
|
3590
|
+
);
|
|
3591
|
+
}
|
|
3592
|
+
if (invitedVerified && invitationToken && invitations?.onAccepted) {
|
|
3593
|
+
try {
|
|
3594
|
+
await invitations.onAccepted({
|
|
3595
|
+
token: invitationToken,
|
|
3596
|
+
user: { id: newUser.id, email: newUser.email, name: newUser.name },
|
|
3597
|
+
db: database,
|
|
3598
|
+
env
|
|
3599
|
+
});
|
|
3600
|
+
} catch (err) {
|
|
3601
|
+
logError(err, { context: "signup_invitation_onAccepted_failed", userId: newUser.id });
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3570
3604
|
const fingerprint = await generateFingerprint(c.req.raw);
|
|
3571
3605
|
const ipAddress = getClientIp(c.req.raw);
|
|
3572
3606
|
const sessionId = await createSession(database, { sessions: schema.sessions }, newUser.id, fingerprint, ipAddress);
|
|
3573
|
-
logSecurityEvent("user_signup", "low", {
|
|
3607
|
+
logSecurityEvent("user_signup", "low", {
|
|
3608
|
+
userId: newUser.id,
|
|
3609
|
+
email: newUser.email,
|
|
3610
|
+
invited: invitedVerified
|
|
3611
|
+
});
|
|
3574
3612
|
c.header("Set-Cookie", setSessionCookie(sessionId, c.env), { append: true });
|
|
3575
3613
|
return c.json({
|
|
3576
3614
|
user: {
|