@syncello/auth 3.3.1 → 3.4.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 +71 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -81
- package/dist/index.d.ts +100 -81
- package/dist/index.js +71 -64
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -949,11 +949,12 @@ import { eq as eq4, and as and2, gt as gt2 } from "drizzle-orm";
|
|
|
949
949
|
|
|
950
950
|
// src/factory.ts
|
|
951
951
|
function createAuth(config) {
|
|
952
|
-
const { db, schema, getEnv } = config;
|
|
952
|
+
const { db, schema, getEnv, emailBranding } = config;
|
|
953
953
|
const getContext = (c) => ({
|
|
954
954
|
db,
|
|
955
955
|
schema,
|
|
956
|
-
env: getEnv(c)
|
|
956
|
+
env: getEnv(c),
|
|
957
|
+
emailBranding
|
|
957
958
|
});
|
|
958
959
|
return {
|
|
959
960
|
db,
|
|
@@ -1535,11 +1536,15 @@ function generateEmailTemplate(options) {
|
|
|
1535
1536
|
appName = "App",
|
|
1536
1537
|
buttonBgColor = "#00fe9a",
|
|
1537
1538
|
buttonTextColor = "#000004",
|
|
1538
|
-
buttonFontWeight = 500
|
|
1539
|
+
buttonFontWeight = 500,
|
|
1540
|
+
buttonRadius = "6px",
|
|
1541
|
+
logoUrl,
|
|
1542
|
+
footerColor = "#1e1b4b"
|
|
1539
1543
|
} = options;
|
|
1540
1544
|
const safeButtonUrl = buttonUrl ? sanitizeEmailUrl(buttonUrl, appUrl) : "";
|
|
1541
1545
|
const safeAppUrl = appUrl ? sanitizeEmailUrl(appUrl, appUrl) : "";
|
|
1542
1546
|
const safeMarketingUrl = marketingUrl ? sanitizeEmailUrl(marketingUrl, appUrl) : "";
|
|
1547
|
+
const safeLogoUrl = logoUrl ? sanitizeEmailUrl(logoUrl, appUrl) : `${safeAppUrl.replace(/\/$/, "")}/email-header-image.png`;
|
|
1543
1548
|
return `
|
|
1544
1549
|
<!DOCTYPE html>
|
|
1545
1550
|
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" lang="en">
|
|
@@ -1679,7 +1684,7 @@ function generateEmailTemplate(options) {
|
|
|
1679
1684
|
<td class="pad" style="padding-left:40px;padding-right:40px;width:100%;">
|
|
1680
1685
|
<div class="alignment" align="center">
|
|
1681
1686
|
<div class="fullWidth" style="max-width: 50%;">
|
|
1682
|
-
<img src="${
|
|
1687
|
+
<img src="${safeLogoUrl}" style="display: block; height: auto; border: 0; width: 100%;" alt="${appName}" title="${appName}" height="auto">
|
|
1683
1688
|
</div>
|
|
1684
1689
|
</div>
|
|
1685
1690
|
</td>
|
|
@@ -1736,7 +1741,7 @@ function generateEmailTemplate(options) {
|
|
|
1736
1741
|
<v:textbox inset="0px,0px,0px,0px">
|
|
1737
1742
|
<center dir="false" style="color:${buttonTextColor};font-family:'Montserrat',Arial,sans-serif;font-size:16px;font-weight:${buttonFontWeight};">
|
|
1738
1743
|
<![endif]-->
|
|
1739
|
-
<a href="${safeButtonUrl}" style="background-color: ${buttonBgColor}; border: 0px solid transparent; border-radius:
|
|
1744
|
+
<a href="${safeButtonUrl}" style="background-color: ${buttonBgColor}; border: 0px solid transparent; border-radius: ${buttonRadius}; color: ${buttonTextColor}; display: inline-block; font-family: 'Montserrat', Arial, sans-serif; font-size: 16px; font-weight: ${buttonFontWeight}; mso-border-alt: none; padding: 10px 20px; text-align: center; text-decoration: none; text-transform: capitalize; word-break: keep-all;">
|
|
1740
1745
|
${buttonText}
|
|
1741
1746
|
</a>
|
|
1742
1747
|
<!--[if mso]>
|
|
@@ -1827,7 +1832,7 @@ function generateEmailTemplate(options) {
|
|
|
1827
1832
|
<tbody>
|
|
1828
1833
|
<tr>
|
|
1829
1834
|
<td>
|
|
1830
|
-
<table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color:
|
|
1835
|
+
<table class="row-content stack" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; background-color: ${footerColor}; color: #000000; max-width: 640px; width: 100%; margin: 0 auto;">
|
|
1831
1836
|
<tbody>
|
|
1832
1837
|
<tr>
|
|
1833
1838
|
<td class="column column-1" width="100%" style="mso-table-lspace: 0pt; mso-table-rspace: 0pt; font-weight: 400; text-align: left; vertical-align: top; padding: 20px;">
|
|
@@ -1886,7 +1891,7 @@ function extractAppUrl(url) {
|
|
|
1886
1891
|
return "https://your-domain.com";
|
|
1887
1892
|
}
|
|
1888
1893
|
}
|
|
1889
|
-
function generateVerificationEmail(data, appName = "Your App", configuredAppUrl = "") {
|
|
1894
|
+
function generateVerificationEmail(data, appName = "Your App", configuredAppUrl = "", branding) {
|
|
1890
1895
|
const { email, verificationUrl, firstName } = data;
|
|
1891
1896
|
const appUrl = configuredAppUrl;
|
|
1892
1897
|
const safeUrl = sanitizeEmailUrl(verificationUrl, appUrl);
|
|
@@ -1896,12 +1901,10 @@ function generateVerificationEmail(data, appName = "Your App", configuredAppUrl
|
|
|
1896
1901
|
body: `Please verify that your email address is <strong>${escapeHtml(email)}</strong>, and that you entered it when signing up for ${escapeHtml(appName)}.`,
|
|
1897
1902
|
buttonText: "Verify Email",
|
|
1898
1903
|
buttonUrl: safeUrl,
|
|
1899
|
-
buttonBgColor: "#00fe9a",
|
|
1900
|
-
buttonTextColor: "#000004",
|
|
1901
|
-
buttonFontWeight: 500,
|
|
1902
1904
|
welcomeMessage: safeFirstName ? `Hi ${safeFirstName}, Welcome to ${escapeHtml(appName)}!` : void 0,
|
|
1903
1905
|
footerNote: "",
|
|
1904
|
-
appUrl
|
|
1906
|
+
appUrl,
|
|
1907
|
+
...branding
|
|
1905
1908
|
});
|
|
1906
1909
|
return {
|
|
1907
1910
|
to: email,
|
|
@@ -1921,7 +1924,7 @@ If you didn't create an account with ${appName}, you can safely ignore this emai
|
|
|
1921
1924
|
}
|
|
1922
1925
|
};
|
|
1923
1926
|
}
|
|
1924
|
-
function generatePasswordResetEmail(data, appName = "Your App", configuredAppUrl = "") {
|
|
1927
|
+
function generatePasswordResetEmail(data, appName = "Your App", configuredAppUrl = "", branding) {
|
|
1925
1928
|
const { email, resetUrl } = data;
|
|
1926
1929
|
const appUrl = configuredAppUrl;
|
|
1927
1930
|
const safeUrl = sanitizeEmailUrl(resetUrl, appUrl);
|
|
@@ -1930,15 +1933,13 @@ function generatePasswordResetEmail(data, appName = "Your App", configuredAppUrl
|
|
|
1930
1933
|
body: "We received a request to reset your password. Click the button below to create a new password.",
|
|
1931
1934
|
buttonText: "Reset Password",
|
|
1932
1935
|
buttonUrl: safeUrl,
|
|
1933
|
-
buttonBgColor: "#00fe9a",
|
|
1934
|
-
buttonTextColor: "#000004",
|
|
1935
|
-
buttonFontWeight: 500,
|
|
1936
1936
|
securityWarning: `
|
|
1937
1937
|
<strong>Link expires in 1 hour.</strong><br>
|
|
1938
1938
|
For security, this link can only be used once.
|
|
1939
1939
|
`,
|
|
1940
1940
|
footerNote: "If you didn't request this change, no action is needed. Your password will remain unchanged.",
|
|
1941
|
-
appUrl
|
|
1941
|
+
appUrl,
|
|
1942
|
+
...branding
|
|
1942
1943
|
});
|
|
1943
1944
|
return {
|
|
1944
1945
|
to: email,
|
|
@@ -1958,7 +1959,7 @@ If you didn't request a password reset, you can safely ignore this email.`,
|
|
|
1958
1959
|
}
|
|
1959
1960
|
};
|
|
1960
1961
|
}
|
|
1961
|
-
function generateEmailChangeConfirmation(data, appName = "Your App", configuredAppUrl = "") {
|
|
1962
|
+
function generateEmailChangeConfirmation(data, appName = "Your App", configuredAppUrl = "", branding) {
|
|
1962
1963
|
const { newEmail, confirmUrl } = data;
|
|
1963
1964
|
const appUrl = configuredAppUrl;
|
|
1964
1965
|
const safeUrl = sanitizeEmailUrl(confirmUrl, appUrl);
|
|
@@ -1967,15 +1968,13 @@ function generateEmailChangeConfirmation(data, appName = "Your App", configuredA
|
|
|
1967
1968
|
body: `We received a request to change your ${escapeHtml(appName)} account email to this address. Click the button below to confirm this change.`,
|
|
1968
1969
|
buttonText: "Confirm Email Change",
|
|
1969
1970
|
buttonUrl: safeUrl,
|
|
1970
|
-
buttonBgColor: "#00fe9a",
|
|
1971
|
-
buttonTextColor: "#000004",
|
|
1972
|
-
buttonFontWeight: 500,
|
|
1973
1971
|
securityWarning: `
|
|
1974
1972
|
<strong>This link expires in 24 hours.</strong><br>
|
|
1975
1973
|
For security, this link can only be used once.
|
|
1976
1974
|
`,
|
|
1977
1975
|
footerNote: "If you didn't request this change, you can safely ignore this email.",
|
|
1978
|
-
appUrl
|
|
1976
|
+
appUrl,
|
|
1977
|
+
...branding
|
|
1979
1978
|
});
|
|
1980
1979
|
return {
|
|
1981
1980
|
to: newEmail,
|
|
@@ -1997,7 +1996,7 @@ If you didn't request this change, you can safely ignore this email.`,
|
|
|
1997
1996
|
}
|
|
1998
1997
|
};
|
|
1999
1998
|
}
|
|
2000
|
-
function generateEmailChangeNotification(data, appName = "Your App", configuredAppUrl = "") {
|
|
1999
|
+
function generateEmailChangeNotification(data, appName = "Your App", configuredAppUrl = "", branding) {
|
|
2001
2000
|
const { oldEmail, newEmail, cancelUrl } = data;
|
|
2002
2001
|
const appUrl = configuredAppUrl;
|
|
2003
2002
|
const safeUrl = sanitizeEmailUrl(cancelUrl, appUrl);
|
|
@@ -2007,15 +2006,13 @@ function generateEmailChangeNotification(data, appName = "Your App", configuredA
|
|
|
2007
2006
|
body: `Someone requested to change your ${escapeHtml(appName)} account email to <strong>${safeNewEmail}</strong>.`,
|
|
2008
2007
|
buttonText: "This Wasn't Me - Cancel Change",
|
|
2009
2008
|
buttonUrl: safeUrl,
|
|
2010
|
-
buttonBgColor: "#00fe9a",
|
|
2011
|
-
buttonTextColor: "#000004",
|
|
2012
|
-
buttonFontWeight: 500,
|
|
2013
2009
|
securityWarning: `
|
|
2014
2010
|
If you made this request, no action is needed.<br>
|
|
2015
2011
|
Complete the change by clicking the link sent to your new email address.
|
|
2016
2012
|
`,
|
|
2017
2013
|
footerNote: "If you didn't request this change, click the button above to cancel it.",
|
|
2018
|
-
appUrl
|
|
2014
|
+
appUrl,
|
|
2015
|
+
...branding
|
|
2019
2016
|
});
|
|
2020
2017
|
return {
|
|
2021
2018
|
to: oldEmail,
|
|
@@ -2035,7 +2032,7 @@ ${safeUrl}`,
|
|
|
2035
2032
|
}
|
|
2036
2033
|
};
|
|
2037
2034
|
}
|
|
2038
|
-
function generate2faCodeEmail(data, appName = "Your App", appUrl = "") {
|
|
2035
|
+
function generate2faCodeEmail(data, appName = "Your App", appUrl = "", branding) {
|
|
2039
2036
|
const { email, firstName, code } = data;
|
|
2040
2037
|
const safeFirstName = firstName ? escapeHtml(firstName) : "there";
|
|
2041
2038
|
const html = generateEmailTemplate({
|
|
@@ -2050,7 +2047,8 @@ function generate2faCodeEmail(data, appName = "Your App", appUrl = "") {
|
|
|
2050
2047
|
buttonText: "",
|
|
2051
2048
|
buttonUrl: "",
|
|
2052
2049
|
footerNote: "",
|
|
2053
|
-
appUrl
|
|
2050
|
+
appUrl,
|
|
2051
|
+
...branding
|
|
2054
2052
|
});
|
|
2055
2053
|
return {
|
|
2056
2054
|
to: email,
|
|
@@ -2070,7 +2068,7 @@ If you didn't request this code, you can safely ignore this email.
|
|
|
2070
2068
|
tags: { type: "2fa_code" }
|
|
2071
2069
|
};
|
|
2072
2070
|
}
|
|
2073
|
-
function generate2faEnabledEmail(data, appName = "Your App", appUrl = "") {
|
|
2071
|
+
function generate2faEnabledEmail(data, appName = "Your App", appUrl = "", branding) {
|
|
2074
2072
|
const { email, firstName, method } = data;
|
|
2075
2073
|
const safeFirstName = firstName ? escapeHtml(firstName) : "there";
|
|
2076
2074
|
const methodName = method === "totp" ? "an authenticator app" : "email codes";
|
|
@@ -2084,7 +2082,8 @@ function generate2faEnabledEmail(data, appName = "Your App", appUrl = "") {
|
|
|
2084
2082
|
buttonText: "",
|
|
2085
2083
|
buttonUrl: "",
|
|
2086
2084
|
footerNote: "",
|
|
2087
|
-
appUrl
|
|
2085
|
+
appUrl,
|
|
2086
|
+
...branding
|
|
2088
2087
|
});
|
|
2089
2088
|
return {
|
|
2090
2089
|
to: email,
|
|
@@ -2100,7 +2099,7 @@ If you didn't make this change, please contact support immediately and reset you
|
|
|
2100
2099
|
tags: { type: "2fa_enabled" }
|
|
2101
2100
|
};
|
|
2102
2101
|
}
|
|
2103
|
-
function generate2faDisabledEmail(data, appName = "Your App", appUrl = "") {
|
|
2102
|
+
function generate2faDisabledEmail(data, appName = "Your App", appUrl = "", branding) {
|
|
2104
2103
|
const { email, firstName } = data;
|
|
2105
2104
|
const safeFirstName = firstName ? escapeHtml(firstName) : "there";
|
|
2106
2105
|
const html = generateEmailTemplate({
|
|
@@ -2112,10 +2111,9 @@ function generate2faDisabledEmail(data, appName = "Your App", appUrl = "") {
|
|
|
2112
2111
|
`,
|
|
2113
2112
|
buttonText: "Reset Password",
|
|
2114
2113
|
buttonUrl: appUrl ? `${appUrl}/forgot-password` : "",
|
|
2115
|
-
buttonBgColor: "#ef4444",
|
|
2116
|
-
buttonTextColor: "#ffffff",
|
|
2117
2114
|
footerNote: "",
|
|
2118
|
-
appUrl
|
|
2115
|
+
appUrl,
|
|
2116
|
+
...branding
|
|
2119
2117
|
});
|
|
2120
2118
|
return {
|
|
2121
2119
|
to: email,
|
|
@@ -2305,6 +2303,7 @@ function createEmailAdapter(env) {
|
|
|
2305
2303
|
var EmailService = class {
|
|
2306
2304
|
adapter;
|
|
2307
2305
|
env;
|
|
2306
|
+
branding;
|
|
2308
2307
|
get fromAddress() {
|
|
2309
2308
|
if (this.env.EMAIL_FROM) {
|
|
2310
2309
|
return this.env.EMAIL_FROM;
|
|
@@ -2318,9 +2317,10 @@ var EmailService = class {
|
|
|
2318
2317
|
}
|
|
2319
2318
|
return `${appName} <hello@${domain}>`;
|
|
2320
2319
|
}
|
|
2321
|
-
constructor(env, adapter) {
|
|
2320
|
+
constructor(env, adapter, branding) {
|
|
2322
2321
|
this.env = env;
|
|
2323
2322
|
this.adapter = adapter ?? createEmailAdapter(env);
|
|
2323
|
+
this.branding = branding;
|
|
2324
2324
|
}
|
|
2325
2325
|
/**
|
|
2326
2326
|
* Check if email address has bounced or complained
|
|
@@ -2372,7 +2372,8 @@ var EmailService = class {
|
|
|
2372
2372
|
const template = generateVerificationEmail(
|
|
2373
2373
|
data,
|
|
2374
2374
|
this.env.APP_NAME ?? "Your App",
|
|
2375
|
-
this.env.APP_URL ?? ""
|
|
2375
|
+
this.env.APP_URL ?? "",
|
|
2376
|
+
this.branding
|
|
2376
2377
|
);
|
|
2377
2378
|
const recipient = this.getRecipientEmail(data.email, "verification");
|
|
2378
2379
|
logger_default.info("Sending verification email", {
|
|
@@ -2432,7 +2433,8 @@ var EmailService = class {
|
|
|
2432
2433
|
const template = generatePasswordResetEmail(
|
|
2433
2434
|
data,
|
|
2434
2435
|
this.env.APP_NAME ?? "Your App",
|
|
2435
|
-
this.env.APP_URL ?? ""
|
|
2436
|
+
this.env.APP_URL ?? "",
|
|
2437
|
+
this.branding
|
|
2436
2438
|
);
|
|
2437
2439
|
const recipient = this.getRecipientEmail(data.email, "password_reset");
|
|
2438
2440
|
logger_default.info("Sending password reset email", {
|
|
@@ -2492,7 +2494,8 @@ var EmailService = class {
|
|
|
2492
2494
|
const template = generateEmailChangeConfirmation(
|
|
2493
2495
|
data,
|
|
2494
2496
|
this.env.APP_NAME ?? "Your App",
|
|
2495
|
-
this.env.APP_URL ?? ""
|
|
2497
|
+
this.env.APP_URL ?? "",
|
|
2498
|
+
this.branding
|
|
2496
2499
|
);
|
|
2497
2500
|
const recipient = this.getRecipientEmail(data.newEmail, "email_change_confirmation");
|
|
2498
2501
|
logger_default.info("Sending email change confirmation", {
|
|
@@ -2552,7 +2555,8 @@ var EmailService = class {
|
|
|
2552
2555
|
const template = generateEmailChangeNotification(
|
|
2553
2556
|
data,
|
|
2554
2557
|
this.env.APP_NAME ?? "Your App",
|
|
2555
|
-
this.env.APP_URL ?? ""
|
|
2558
|
+
this.env.APP_URL ?? "",
|
|
2559
|
+
this.branding
|
|
2556
2560
|
);
|
|
2557
2561
|
const recipient = this.getRecipientEmail(data.oldEmail, "email_change_notification");
|
|
2558
2562
|
logger_default.info("Sending email change notification", {
|
|
@@ -2609,7 +2613,8 @@ var EmailService = class {
|
|
|
2609
2613
|
const template = generate2faCodeEmail(
|
|
2610
2614
|
data,
|
|
2611
2615
|
this.env.APP_NAME ?? "Your App",
|
|
2612
|
-
this.env.APP_URL ?? ""
|
|
2616
|
+
this.env.APP_URL ?? "",
|
|
2617
|
+
this.branding
|
|
2613
2618
|
);
|
|
2614
2619
|
const recipient = this.getRecipientEmail(data.email, "2fa_code");
|
|
2615
2620
|
logger_default.info("Sending 2FA code email", {
|
|
@@ -2666,7 +2671,8 @@ var EmailService = class {
|
|
|
2666
2671
|
const template = generate2faEnabledEmail(
|
|
2667
2672
|
data,
|
|
2668
2673
|
this.env.APP_NAME ?? "Your App",
|
|
2669
|
-
this.env.APP_URL ?? ""
|
|
2674
|
+
this.env.APP_URL ?? "",
|
|
2675
|
+
this.branding
|
|
2670
2676
|
);
|
|
2671
2677
|
const recipient = this.getRecipientEmail(data.email, "2fa_enabled");
|
|
2672
2678
|
logger_default.info("Sending 2FA enabled email", {
|
|
@@ -2724,7 +2730,8 @@ var EmailService = class {
|
|
|
2724
2730
|
const template = generate2faDisabledEmail(
|
|
2725
2731
|
data,
|
|
2726
2732
|
this.env.APP_NAME ?? "Your App",
|
|
2727
|
-
this.env.APP_URL ?? ""
|
|
2733
|
+
this.env.APP_URL ?? "",
|
|
2734
|
+
this.branding
|
|
2728
2735
|
);
|
|
2729
2736
|
const recipient = this.getRecipientEmail(data.email, "2fa_disabled");
|
|
2730
2737
|
logger_default.info("Sending 2FA disabled email", {
|
|
@@ -3056,7 +3063,7 @@ var signupRoute = createRoute({
|
|
|
3056
3063
|
});
|
|
3057
3064
|
var signupHandler = async (c) => {
|
|
3058
3065
|
const { email, password, name, turnstileToken, oauthToken } = c.req.valid("json");
|
|
3059
|
-
const { db: database, schema } = getAuthContext(c);
|
|
3066
|
+
const { db: database, schema, emailBranding } = getAuthContext(c);
|
|
3060
3067
|
const env = c.env;
|
|
3061
3068
|
if (oauthToken) {
|
|
3062
3069
|
const stored = await env.OAUTH_STATES.get(`oauth:signup:${oauthToken}`);
|
|
@@ -3156,7 +3163,7 @@ var signupHandler = async (c) => {
|
|
|
3156
3163
|
expiresAt,
|
|
3157
3164
|
createdAt: Date.now()
|
|
3158
3165
|
});
|
|
3159
|
-
const emailService = new EmailService(env);
|
|
3166
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
3160
3167
|
const verificationUrl = `${env.APP_URL}/verify-email?token=${emailToken}`;
|
|
3161
3168
|
await emailService.sendVerificationEmail(
|
|
3162
3169
|
{
|
|
@@ -3640,7 +3647,7 @@ var forgotPasswordRoute = createRoute6({
|
|
|
3640
3647
|
});
|
|
3641
3648
|
var forgotPasswordHandler = async (c) => {
|
|
3642
3649
|
const { email, turnstileToken } = c.req.valid("json");
|
|
3643
|
-
const { db: database, schema } = getAuthContext(c);
|
|
3650
|
+
const { db: database, schema, emailBranding } = getAuthContext(c);
|
|
3644
3651
|
const env = c.env;
|
|
3645
3652
|
const turnstileValid = await verifyTurnstileToken(
|
|
3646
3653
|
turnstileToken,
|
|
@@ -3659,7 +3666,7 @@ var forgotPasswordHandler = async (c) => {
|
|
|
3659
3666
|
if (!resetResult) {
|
|
3660
3667
|
return c.json({ success: true });
|
|
3661
3668
|
}
|
|
3662
|
-
const emailService = new EmailService(env);
|
|
3669
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
3663
3670
|
const resetUrl = `${env.APP_URL}/reset-password?token=${resetResult.token}`;
|
|
3664
3671
|
await emailService.sendPasswordResetEmail(
|
|
3665
3672
|
{
|
|
@@ -3907,7 +3914,7 @@ var changeEmailHandler = async (c) => {
|
|
|
3907
3914
|
const userId = c.get("userId");
|
|
3908
3915
|
if (!userId) return problems.unauthorized(c, "Not authenticated");
|
|
3909
3916
|
const { password, newEmail } = c.req.valid("json");
|
|
3910
|
-
const { db: database, schema } = getAuthContext(c);
|
|
3917
|
+
const { db: database, schema, emailBranding } = getAuthContext(c);
|
|
3911
3918
|
const env = c.env;
|
|
3912
3919
|
const appUrl = env.APP_URL || "http://localhost:5173";
|
|
3913
3920
|
const result = await requestEmailChange({
|
|
@@ -3924,7 +3931,7 @@ var changeEmailHandler = async (c) => {
|
|
|
3924
3931
|
}
|
|
3925
3932
|
return problems.badRequest(c, result.error || "Failed to request email change");
|
|
3926
3933
|
}
|
|
3927
|
-
const emailService = new EmailService(env);
|
|
3934
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
3928
3935
|
const confirmUrl = `${appUrl}/confirm-email-change?token=${result.confirmToken}`;
|
|
3929
3936
|
const confirmResult = await emailService.sendEmailChangeConfirmation(
|
|
3930
3937
|
{ newEmail, confirmUrl },
|
|
@@ -4229,7 +4236,7 @@ var resendVerificationRoute = createRoute15({
|
|
|
4229
4236
|
});
|
|
4230
4237
|
var resendVerificationHandler = async (c) => {
|
|
4231
4238
|
const userId = c.get("userId");
|
|
4232
|
-
const { db, schema } = getAuthContext(c);
|
|
4239
|
+
const { db, schema, emailBranding } = getAuthContext(c);
|
|
4233
4240
|
const env = c.env;
|
|
4234
4241
|
const [user] = await db.select({
|
|
4235
4242
|
id: schema.users.id,
|
|
@@ -4254,7 +4261,7 @@ var resendVerificationHandler = async (c) => {
|
|
|
4254
4261
|
expiresAt,
|
|
4255
4262
|
createdAt: Date.now()
|
|
4256
4263
|
});
|
|
4257
|
-
const emailService = new EmailService(env);
|
|
4264
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
4258
4265
|
const verificationUrl = `${env.APP_URL}/verify-email?token=${emailToken}`;
|
|
4259
4266
|
await emailService.sendVerificationEmail(
|
|
4260
4267
|
{
|
|
@@ -4542,7 +4549,7 @@ var totpVerifyHandler = async (c) => {
|
|
|
4542
4549
|
const userId = c.get("userId");
|
|
4543
4550
|
if (!userId) return problems.unauthorized(c);
|
|
4544
4551
|
const { code } = c.req.valid("json");
|
|
4545
|
-
const { db, schema, env } = getAuthContext(c);
|
|
4552
|
+
const { db, schema, env, emailBranding } = getAuthContext(c);
|
|
4546
4553
|
const secret = await env.OAUTH_STATES.get(`totp_setup:${userId}`);
|
|
4547
4554
|
if (!secret) {
|
|
4548
4555
|
return problems.badRequest(c, "Setup expired. Please start again.");
|
|
@@ -4586,7 +4593,7 @@ var totpVerifyHandler = async (c) => {
|
|
|
4586
4593
|
backupCodes = codes.map(formatBackupCode);
|
|
4587
4594
|
}
|
|
4588
4595
|
if (user) {
|
|
4589
|
-
const emailService = new EmailService(env);
|
|
4596
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
4590
4597
|
const firstName = user.name?.split(" ")[0] || null;
|
|
4591
4598
|
await emailService.send2faEnabledEmail(
|
|
4592
4599
|
{ email: user.email, firstName, method: "totp" },
|
|
@@ -4634,7 +4641,7 @@ var totpDisableHandler = async (c) => {
|
|
|
4634
4641
|
return problems.unauthorized(c);
|
|
4635
4642
|
}
|
|
4636
4643
|
const { code, method } = c.req.valid("json");
|
|
4637
|
-
const { db, schema, env } = getAuthContext(c);
|
|
4644
|
+
const { db, schema, env, emailBranding } = getAuthContext(c);
|
|
4638
4645
|
const verification = await verifyAny2faCode(db, env, userId, code, method, {
|
|
4639
4646
|
user2faMethods: schema.user2faMethods,
|
|
4640
4647
|
userBackupCodes: schema.userBackupCodes
|
|
@@ -4651,7 +4658,7 @@ var totpDisableHandler = async (c) => {
|
|
|
4651
4658
|
await invalidateAllUserSessions(db, { sessions: schema.sessions, users: schema.users }, userId);
|
|
4652
4659
|
const [user] = await db.select({ email: schema.users.email, name: schema.users.name }).from(schema.users).where(eq22(schema.users.id, userId)).limit(1);
|
|
4653
4660
|
if (user) {
|
|
4654
|
-
const emailService = new EmailService(env);
|
|
4661
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
4655
4662
|
const firstName = user.name?.split(" ")[0] || null;
|
|
4656
4663
|
await emailService.send2faDisabledEmail({ email: user.email, firstName }, db, schema.users);
|
|
4657
4664
|
}
|
|
@@ -4697,7 +4704,7 @@ var emailSetupRoute = createRoute20({
|
|
|
4697
4704
|
var emailSetupHandler = async (c) => {
|
|
4698
4705
|
const userId = c.get("userId");
|
|
4699
4706
|
if (!userId) return problems.unauthorized(c);
|
|
4700
|
-
const { db, schema, env } = getAuthContext(c);
|
|
4707
|
+
const { db, schema, env, emailBranding } = getAuthContext(c);
|
|
4701
4708
|
const existing = await db.select({ id: schema.user2faMethods.id }).from(schema.user2faMethods).where(and10(eq23(schema.user2faMethods.userId, userId), eq23(schema.user2faMethods.method, "email"))).limit(1);
|
|
4702
4709
|
if (existing.length > 0) {
|
|
4703
4710
|
return problems.badRequest(c, "Email 2FA already enabled");
|
|
@@ -4707,7 +4714,7 @@ var emailSetupHandler = async (c) => {
|
|
|
4707
4714
|
const code = generateEmailOtp();
|
|
4708
4715
|
const codeHash = await hashToken(code);
|
|
4709
4716
|
await env.OAUTH_STATES.put(`email_2fa_setup:${userId}`, codeHash, { expirationTtl: 300 });
|
|
4710
|
-
const emailService = new EmailService(env);
|
|
4717
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
4711
4718
|
const firstName = user.name?.split(" ")[0] || null;
|
|
4712
4719
|
await emailService.send2faCodeEmail({ email: user.email, firstName, code }, db, schema.users);
|
|
4713
4720
|
logSecurityEvent("2fa_email_setup_initiated", "low", { userId });
|
|
@@ -4748,7 +4755,7 @@ var emailVerifyHandler = async (c) => {
|
|
|
4748
4755
|
const userId = c.get("userId");
|
|
4749
4756
|
if (!userId) return problems.unauthorized(c);
|
|
4750
4757
|
const { code } = c.req.valid("json");
|
|
4751
|
-
const { db, schema, env } = getAuthContext(c);
|
|
4758
|
+
const { db, schema, env, emailBranding } = getAuthContext(c);
|
|
4752
4759
|
const storedHash = await env.OAUTH_STATES.get(`email_2fa_setup:${userId}`);
|
|
4753
4760
|
if (!storedHash) {
|
|
4754
4761
|
return problems.badRequest(c, "Code expired. Please request a new one.");
|
|
@@ -4786,7 +4793,7 @@ var emailVerifyHandler = async (c) => {
|
|
|
4786
4793
|
backupCodes = codes.map(formatBackupCode);
|
|
4787
4794
|
}
|
|
4788
4795
|
if (user) {
|
|
4789
|
-
const emailService = new EmailService(env);
|
|
4796
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
4790
4797
|
const firstName = user.name?.split(" ")[0] || null;
|
|
4791
4798
|
await emailService.send2faEnabledEmail(
|
|
4792
4799
|
{ email: user.email, firstName, method: "email" },
|
|
@@ -4829,7 +4836,7 @@ var emailSendCodeRoute = createRoute22({
|
|
|
4829
4836
|
var emailSendCodeHandler = async (c) => {
|
|
4830
4837
|
const userId = c.get("userId");
|
|
4831
4838
|
if (!userId) return problems.unauthorized(c);
|
|
4832
|
-
const { db, schema, env } = getAuthContext(c);
|
|
4839
|
+
const { db, schema, env, emailBranding } = getAuthContext(c);
|
|
4833
4840
|
const [emailMethod] = await db.select().from(schema.user2faMethods).where(and11(eq25(schema.user2faMethods.userId, userId), eq25(schema.user2faMethods.method, "email"))).limit(1);
|
|
4834
4841
|
if (!emailMethod) {
|
|
4835
4842
|
return problems.badRequest(c, "Email 2FA not enabled");
|
|
@@ -4841,7 +4848,7 @@ var emailSendCodeHandler = async (c) => {
|
|
|
4841
4848
|
await env.OAUTH_STATES.put(`email_2fa_challenge:${userId}`, codeHash, {
|
|
4842
4849
|
expirationTtl: 300
|
|
4843
4850
|
});
|
|
4844
|
-
const emailService = new EmailService(env);
|
|
4851
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
4845
4852
|
const firstName = user.name?.split(" ")[0] || null;
|
|
4846
4853
|
const emailResult = await emailService.send2faCodeEmail(
|
|
4847
4854
|
{ email: user.email, firstName, code },
|
|
@@ -4894,7 +4901,7 @@ var emailDisableHandler = async (c) => {
|
|
|
4894
4901
|
return problems.unauthorized(c);
|
|
4895
4902
|
}
|
|
4896
4903
|
const { code, method } = c.req.valid("json");
|
|
4897
|
-
const { db, schema, env } = getAuthContext(c);
|
|
4904
|
+
const { db, schema, env, emailBranding } = getAuthContext(c);
|
|
4898
4905
|
const verification = await verifyAny2faCode(db, env, userId, code, method, {
|
|
4899
4906
|
user2faMethods: schema.user2faMethods,
|
|
4900
4907
|
userBackupCodes: schema.userBackupCodes
|
|
@@ -4911,7 +4918,7 @@ var emailDisableHandler = async (c) => {
|
|
|
4911
4918
|
await invalidateAllUserSessions(db, { sessions: schema.sessions, users: schema.users }, userId);
|
|
4912
4919
|
const [user] = await db.select({ email: schema.users.email, name: schema.users.name }).from(schema.users).where(eq26(schema.users.id, userId)).limit(1);
|
|
4913
4920
|
if (user) {
|
|
4914
|
-
const emailService = new EmailService(env);
|
|
4921
|
+
const emailService = new EmailService(env, void 0, emailBranding);
|
|
4915
4922
|
const firstName = user.name?.split(" ")[0] || null;
|
|
4916
4923
|
await emailService.send2faDisabledEmail({ email: user.email, firstName }, db, schema.users);
|
|
4917
4924
|
}
|
|
@@ -5208,7 +5215,7 @@ var challengeResendRoute = createRoute27({
|
|
|
5208
5215
|
}
|
|
5209
5216
|
});
|
|
5210
5217
|
var challengeResendHandler = async (c) => {
|
|
5211
|
-
const { db, schema } = getAuthContext(c);
|
|
5218
|
+
const { db, schema, emailBranding } = getAuthContext(c);
|
|
5212
5219
|
const cookieName = getChallengeCookieName(c.env);
|
|
5213
5220
|
const challengeToken = getCookie3(c, cookieName);
|
|
5214
5221
|
if (!challengeToken) {
|
|
@@ -5232,7 +5239,7 @@ var challengeResendHandler = async (c) => {
|
|
|
5232
5239
|
await c.env.OAUTH_STATES.put(`email_2fa_challenge:${payload.userId}`, codeHash, {
|
|
5233
5240
|
expirationTtl: 300
|
|
5234
5241
|
});
|
|
5235
|
-
const emailService = new EmailService(c.env);
|
|
5242
|
+
const emailService = new EmailService(c.env, void 0, emailBranding);
|
|
5236
5243
|
const firstName = user.name?.split(" ")[0] || null;
|
|
5237
5244
|
await emailService.send2faCodeEmail({ email: user.email, firstName, code }, db, schema.users);
|
|
5238
5245
|
logger_default.info("Email 2FA code resent", { userId: payload.userId });
|