faire-auth 1.0.3 → 1.1.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/{adapter-factory-lKIOf2OR.mjs → adapter-factory-qPVW8x9-.mjs} +34 -36
- package/dist/{adapter-factory-D1I7joki.cjs → adapter-factory-u8r3oTez.cjs} +66 -68
- package/dist/adapters/drizzle-adapter/index.cjs +34 -40
- package/dist/adapters/drizzle-adapter/index.d.cts +4 -9
- package/dist/adapters/drizzle-adapter/index.d.mts +4 -9
- package/dist/adapters/drizzle-adapter/index.mjs +20 -26
- package/dist/adapters/index.cjs +11 -16
- package/dist/adapters/index.d.cts +11 -37
- package/dist/adapters/index.d.mts +11 -37
- package/dist/adapters/index.mjs +4 -13
- package/dist/adapters/kysely-adapter/index.cjs +270 -11
- package/dist/adapters/kysely-adapter/index.d.cts +9 -19
- package/dist/adapters/kysely-adapter/index.d.mts +9 -19
- package/dist/adapters/kysely-adapter/index.mjs +267 -9
- package/dist/adapters/memory-adapter/index.cjs +146 -9
- package/dist/adapters/memory-adapter/index.d.cts +4 -10
- package/dist/adapters/memory-adapter/index.d.mts +4 -10
- package/dist/adapters/memory-adapter/index.mjs +145 -9
- package/dist/adapters/mongodb-adapter/index.cjs +13 -21
- package/dist/adapters/mongodb-adapter/index.d.cts +3 -8
- package/dist/adapters/mongodb-adapter/index.d.mts +4 -9
- package/dist/adapters/mongodb-adapter/index.mjs +12 -20
- package/dist/adapters/prisma-adapter/index.cjs +12 -20
- package/dist/adapters/prisma-adapter/index.d.cts +4 -8
- package/dist/adapters/prisma-adapter/index.d.mts +4 -8
- package/dist/adapters/prisma-adapter/index.mjs +5 -13
- package/dist/adapters/test.cjs +86 -69
- package/dist/adapters/test.d.cts +7 -11
- package/dist/adapters/test.d.mts +7 -11
- package/dist/adapters/test.mjs +83 -66
- package/dist/api/index.cjs +3 -20
- package/dist/api/index.d.cts +2 -3
- package/dist/api/index.d.mts +2 -3
- package/dist/api/index.mjs +1 -20
- package/dist/api/middleware/index.cjs +4 -11
- package/dist/api/middleware/index.d.cts +3 -9
- package/dist/api/middleware/index.d.mts +3 -9
- package/dist/api/middleware/index.mjs +3 -11
- package/dist/{api-B4RDwBty.mjs → api-0f-F-Fi2.mjs} +292 -189
- package/dist/{api-CaRC1Gio.cjs → api-LjfH6hQi.cjs} +557 -452
- package/dist/{test-utils/bun-sqlite-dialect-BZBvHchL.cjs → bun-sqlite-dialect-BHkarnxN.cjs} +5 -9
- package/dist/{test-utils/bun-sqlite-dialect-BSWhhKNs.mjs → bun-sqlite-dialect-BiZBuEF6.mjs} +6 -9
- package/dist/client/index.cjs +8 -15
- package/dist/client/index.d.cts +9 -14
- package/dist/client/index.d.mts +9 -14
- package/dist/client/index.mjs +7 -15
- package/dist/client/lynx/index.cjs +10 -18
- package/dist/client/lynx/index.d.cts +402 -71
- package/dist/client/lynx/index.d.mts +402 -71
- package/dist/client/lynx/index.mjs +5 -13
- package/dist/client/plugins/index.cjs +3 -5
- package/dist/client/plugins/index.d.cts +5 -10
- package/dist/client/plugins/index.d.mts +5 -10
- package/dist/client/plugins/index.mjs +2 -4
- package/dist/client/react/index.cjs +6 -14
- package/dist/client/react/index.d.cts +402 -71
- package/dist/client/react/index.d.mts +402 -71
- package/dist/client/react/index.mjs +5 -13
- package/dist/client/solid/index.cjs +6 -14
- package/dist/client/solid/index.d.cts +393 -57
- package/dist/client/solid/index.d.mts +393 -57
- package/dist/client/solid/index.mjs +5 -13
- package/dist/client/svelte/index.cjs +5 -10
- package/dist/client/svelte/index.d.cts +400 -67
- package/dist/client/svelte/index.d.mts +400 -67
- package/dist/client/svelte/index.mjs +4 -10
- package/dist/client/vue/index.cjs +6 -14
- package/dist/client/vue/index.d.cts +401 -68
- package/dist/client/vue/index.d.mts +401 -68
- package/dist/client/vue/index.mjs +5 -13
- package/dist/{cookies-BTs1o992.mjs → cookies-D9aY_gJh.mjs} +25 -21
- package/dist/{cookies-BTl72THv.cjs → cookies-DQ52rcOy.cjs} +119 -115
- package/dist/crypto/index.cjs +10 -8
- package/dist/crypto/index.d.cts +5 -13
- package/dist/crypto/index.d.mts +5 -13
- package/dist/crypto/index.mjs +2 -5
- package/dist/{crypto-DH2Aa7jN.mjs → crypto-BH-hD0lJ.mjs} +7 -10
- package/dist/{crypto-DpSCnrTp.cjs → crypto-BITfWVwD.cjs} +24 -27
- package/dist/db/index.cjs +1135 -29
- package/dist/db/index.d.cts +1 -2
- package/dist/db/index.d.mts +1 -2
- package/dist/db/index.mjs +1115 -16
- package/dist/defu-D2h4S3X-.mjs +87 -0
- package/dist/defu-DWS5RPWt.cjs +134 -0
- package/dist/{email-verification-DI_0H4JC.cjs → email-verification-DOPnSgbI.cjs} +65 -71
- package/dist/{email-verification-C_lBu_JY.mjs → email-verification-YSR5n5lb.mjs} +23 -29
- package/dist/{hono-CO-zsqI-.mjs → hono-BAV2wQkK.mjs} +16 -33
- package/dist/hono-SVQuc5Ru.mjs +4 -0
- package/dist/hono-pgK4H_U1.cjs +9 -0
- package/dist/{hono-DnW5crl1.cjs → hono-tyFFJFdS.cjs} +42 -60
- package/dist/index-B86Cy0dE.d.cts +2 -0
- package/dist/index-B86Cy0dE.d.mts +2 -0
- package/dist/index.cjs +115 -150
- package/dist/index.d.cts +4 -5
- package/dist/index.d.mts +4 -5
- package/dist/index.mjs +46 -81
- package/dist/integrations/next-js.cjs +5 -9
- package/dist/integrations/next-js.d.cts +6 -14
- package/dist/integrations/next-js.d.mts +6 -14
- package/dist/integrations/next-js.mjs +4 -9
- package/dist/integrations/node.cjs +16 -14
- package/dist/integrations/node.d.cts +6 -14
- package/dist/integrations/node.d.mts +6 -14
- package/dist/integrations/node.mjs +15 -13
- package/dist/integrations/react-start.cjs +7 -11
- package/dist/integrations/react-start.d.cts +5 -13
- package/dist/integrations/react-start.d.mts +5 -13
- package/dist/integrations/react-start.mjs +6 -11
- package/dist/integrations/solid-start.cjs +3 -5
- package/dist/integrations/solid-start.d.cts +2 -5
- package/dist/integrations/solid-start.d.mts +2 -5
- package/dist/integrations/solid-start.mjs +2 -4
- package/dist/integrations/svelte-kit.cjs +6 -10
- package/dist/integrations/svelte-kit.d.cts +11 -23
- package/dist/integrations/svelte-kit.d.mts +11 -23
- package/dist/integrations/svelte-kit.mjs +5 -10
- package/dist/{ip-BjNYspCH.mjs → ip-6Lv2o42m.mjs} +4 -9
- package/dist/{ip-C17Qdq-G.cjs → ip-DPydExzV.cjs} +21 -27
- package/dist/{json--tl7Grvs.cjs → json-D3aq-nH2.cjs} +9 -13
- package/dist/{json-B1v2qRTQ.mjs → json-DooGMtnJ.mjs} +2 -5
- package/dist/{logged-CyGfp8_H.mjs → logged-B83SzMnJ.mjs} +6 -10
- package/dist/{logged-Dv3st5qc.cjs → logged-BIpCpnVY.cjs} +13 -18
- package/dist/{middleware-CE6OhDkq.mjs → middleware-Cakg4e1D.mjs} +2 -4
- package/dist/{middleware-CWvRH4EW.cjs → middleware-Cd-VkNxB.cjs} +17 -20
- package/dist/{node-sqlite-dialect-w4DAg0PH.mjs → node-sqlite-dialect-BMVOjEMh.mjs} +6 -9
- package/dist/{test-utils/node-sqlite-dialect-BgJqjBOu.cjs → node-sqlite-dialect-D3QPFROH.cjs} +5 -9
- package/dist/oauth2/index.cjs +166 -22
- package/dist/oauth2/index.d.cts +5 -17
- package/dist/oauth2/index.d.mts +5 -17
- package/dist/oauth2/index.mjs +156 -16
- package/dist/{origin-check-DjLTuZQ8.cjs → origin-check-BflGhEEN.cjs} +34 -38
- package/dist/{origin-check-8Gajklvh.mjs → origin-check-CRgs1M7k.mjs} +13 -16
- package/dist/{parser-B25ylT5u.mjs → parser-CqwvpF6l.cjs} +12 -10
- package/dist/{parser-B_wxvaAr.cjs → parser-DcKDjjHO.mjs} +7 -22
- package/dist/plugins/access/index.cjs +38 -4
- package/dist/plugins/access/index.d.cts +36 -2
- package/dist/plugins/access/index.d.mts +36 -2
- package/dist/plugins/access/index.mjs +36 -3
- package/dist/plugins/bearer/index.cjs +52 -7
- package/dist/plugins/bearer/index.d.cts +27 -4
- package/dist/plugins/bearer/index.d.mts +27 -4
- package/dist/plugins/bearer/index.mjs +51 -7
- package/dist/plugins/index.cjs +1385 -842
- package/dist/plugins/index.d.cts +489 -7566
- package/dist/plugins/index.d.mts +489 -7566
- package/dist/plugins/index.mjs +1118 -576
- package/dist/plugins/passkey/index.cjs +551 -15
- package/dist/plugins/passkey/index.d.cts +123 -4
- package/dist/plugins/passkey/index.d.mts +123 -4
- package/dist/plugins/passkey/index.mjs +547 -15
- package/dist/{chunk-BFnQceUY.mjs → rolldown-runtime-BKpuH2hG.mjs} +6 -7
- package/dist/{chunk-fPmz2rbM.cjs → rolldown-runtime-C_Pgydhf.cjs} +22 -24
- package/dist/{schema-DTIwLLmf.mjs → schema-CFCpv0tK.mjs} +3 -6
- package/dist/{schema-CirKflVs.cjs → schema-b-lKhMkG.cjs} +51 -55
- package/dist/{session-CM3rmOYF.mjs → session-BGjJgihS.mjs} +51 -74
- package/dist/{session-Cwrj4GfV.cjs → session-CzZSMmQC.cjs} +197 -219
- package/dist/shared.d.cts +1581 -0
- package/dist/shared.d.mts +1581 -0
- package/dist/social-providers/index.cjs +9 -9
- package/dist/social-providers/index.d.cts +1 -1
- package/dist/social-providers/index.d.mts +1 -1
- package/dist/social-providers/index.mjs +3 -5
- package/dist/social-providers-CjPww-qf.mjs +6 -0
- package/dist/social-providers-D7w_7Ym8.cjs +10 -0
- package/dist/{state-CvSihlVT.cjs → state-2OrNjOO-.cjs} +24 -24
- package/dist/{state-CQghgH9I.mjs → state-Dooeisfq.mjs} +17 -17
- package/dist/{bun-sqlite-dialect-DPgTzc0w.cjs → test-utils/bun-sqlite-dialect-BHkarnxN.cjs} +5 -9
- package/dist/{bun-sqlite-dialect-6NqeV3px.mjs → test-utils/bun-sqlite-dialect-BiZBuEF6.mjs} +6 -9
- package/dist/test-utils/index.cjs +8831 -7941
- package/dist/test-utils/index.d.cts +310 -12440
- package/dist/test-utils/index.d.mts +313 -12440
- package/dist/test-utils/index.mjs +8591 -7701
- package/dist/test-utils/{node-sqlite-dialect-DAQXiobH.mjs → node-sqlite-dialect-BMVOjEMh.mjs} +6 -9
- package/dist/{node-sqlite-dialect-DP11CB0y.cjs → test-utils/node-sqlite-dialect-D3QPFROH.cjs} +5 -9
- package/dist/types/index.d.cts +2 -3
- package/dist/types/index.d.mts +2 -3
- package/dist/types/index.mjs +1 -1
- package/dist/{url-BoUuoIwZ.mjs → url-CJtdrrUu.mjs} +12 -13
- package/dist/{url-Ce7CVaQD.cjs → url-DjCmCUHS.cjs} +42 -44
- package/dist/utils/cookies.cjs +29 -30
- package/dist/utils/cookies.d.cts +21 -25
- package/dist/utils/cookies.d.mts +20 -24
- package/dist/utils/cookies.mjs +2 -7
- package/dist/utils-C7OHyfHa.mjs +4 -0
- package/dist/utils-iX0Vy_UL.cjs +3 -0
- package/package.json +40 -30
- package/dist/access-BZ7-AbTM.cjs +0 -51
- package/dist/access-D0DRqUKC.mjs +0 -39
- package/dist/bearer-DDzrp5M7.cjs +0 -60
- package/dist/bearer-WZcs7gxL.mjs +0 -54
- package/dist/db-4tUsQJXd.mjs +0 -1119
- package/dist/db-ChMbb_U-.cjs +0 -1180
- package/dist/defu-BmOYq4PU.cjs +0 -34
- package/dist/defu-D9ZTXqlo.mjs +0 -28
- package/dist/hono-C14rpOEa.cjs +0 -13
- package/dist/hono-CoKYWnXA.mjs +0 -7
- package/dist/hono-D0VqxVy1.d.mts +0 -18
- package/dist/hono-DOM31WQz.d.cts +0 -18
- package/dist/index-BCTFWP_o.d.mts +0 -992
- package/dist/index-BDhhaE6Y.d.cts +0 -3
- package/dist/index-BVRfQy6L.d.mts +0 -992
- package/dist/index-Baarsq5J.d.mts +0 -33
- package/dist/index-By364WbF.d.cts +0 -992
- package/dist/index-BzWwMgxr.d.cts +0 -992
- package/dist/index-CF9iq55a.d.mts +0 -3
- package/dist/index-CJD2yB-W.d.cts +0 -33
- package/dist/index-CRt_fppq.d.mts +0 -41
- package/dist/index-CdLyn7qP.d.cts +0 -41
- package/dist/index-CsWF3f7U.d.cts +0 -13350
- package/dist/index-CzidsAyA.d.mts +0 -13350
- package/dist/index-DvW-GCcI.d.cts +0 -33
- package/dist/index-f-5OJ9yV.d.cts +0 -13350
- package/dist/index-rFv8Hxld.d.mts +0 -13350
- package/dist/index-ztVZPQdV.d.mts +0 -33
- package/dist/kysely-adapter-CtIdoHa8.mjs +0 -270
- package/dist/kysely-adapter-QZTx077T.cjs +0 -288
- package/dist/memory-adapter-17RZd5df.cjs +0 -154
- package/dist/memory-adapter-Dp4XdCZK.mjs +0 -148
- package/dist/oauth2-5RL4cVNS.cjs +0 -177
- package/dist/oauth2-C56wz-n9.mjs +0 -159
- package/dist/passkey-BTT-v5c-.cjs +0 -512
- package/dist/passkey-CzY_W2us.mjs +0 -505
- package/dist/request-1NL_1lyJ.mjs +0 -58
- package/dist/request-CPNlp-DK.cjs +0 -100
- package/dist/social-providers-B8RK5yqI.mjs +0 -9
- package/dist/social-providers-BmFOIIPk.cjs +0 -13
- package/dist/utils-44aDDP8f.cjs +0 -2
- package/dist/utils-D4vZd1-9.mjs +0 -4
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { t as contextStorage } from "./hono-
|
|
2
|
-
import {
|
|
3
|
-
import { n as
|
|
4
|
-
import {
|
|
5
|
-
import { n as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { n as
|
|
11
|
-
import { n as
|
|
12
|
-
import {
|
|
13
|
-
import { r as
|
|
14
|
-
import {
|
|
1
|
+
import { t as contextStorage } from "./hono-SVQuc5Ru.mjs";
|
|
2
|
+
import { decryptOAuthToken, handleOAuthUserInfo, setTokenUtil } from "./oauth2/index.mjs";
|
|
3
|
+
import { n as parseState, t as generateState } from "./state-Dooeisfq.mjs";
|
|
4
|
+
import { n as cookies_exports, o as deleteSessionCookie, y as setSessionCookie } from "./cookies-D9aY_gJh.mjs";
|
|
5
|
+
import { _ as initContextMiddleware, a as requestOnlySessionMiddleware, c as revokeSessions, d as createAPI, f as createEndpoint, g as initHooksMiddleware, h as initErrorHandler, i as listSessions, l as sensitiveSessionMiddleware, m as setDefaultExecutionCtx, n as getSession, o as revokeOtherSessions, p as setRenderer, s as revokeSession, t as freshSessionMiddleware, u as sessionMiddleware } from "./session-BGjJgihS.mjs";
|
|
6
|
+
import { t as social_providers_exports } from "./social-providers-CjPww-qf.mjs";
|
|
7
|
+
import { n as sendVerificationEmail, r as verifyEmail, t as createEmailVerificationToken } from "./email-verification-YSR5n5lb.mjs";
|
|
8
|
+
import { t as safeJSONParse } from "./json-DooGMtnJ.mjs";
|
|
9
|
+
import { r as generateId } from "./utils-C7OHyfHa.mjs";
|
|
10
|
+
import { n as originCheck, r as wildcardMatch, t as initOriginCheckMiddleware } from "./origin-check-CRgs1M7k.mjs";
|
|
11
|
+
import { n as crypto_exports } from "./crypto-BH-hD0lJ.mjs";
|
|
12
|
+
import { c as parseUserInput } from "./schema-CFCpv0tK.mjs";
|
|
13
|
+
import { r as runWithTransaction, t as getIp } from "./ip-6Lv2o42m.mjs";
|
|
14
|
+
import { r as createMiddleware } from "./middleware-Cakg4e1D.mjs";
|
|
15
15
|
import { isDevelopment } from "@faire-auth/core/env";
|
|
16
16
|
import { BASE_ERROR_CODES } from "@faire-auth/core/error";
|
|
17
17
|
import { OpenAPIHono, callbackURLSchema, createRoute, emailSchema, nameSchema, passwordSchema, req, res } from "@faire-auth/core/factory";
|
|
@@ -19,68 +19,154 @@ import { Definitions, False, Routes, SCHEMAS, True, isPromise } from "@faire-aut
|
|
|
19
19
|
import { buildSchemas, getDate } from "@faire-auth/core/utils";
|
|
20
20
|
import { Hono } from "hono";
|
|
21
21
|
import { RegExpRouter } from "hono/router/reg-exp-router";
|
|
22
|
-
import * as z
|
|
22
|
+
import * as z from "zod";
|
|
23
23
|
import { looseUserSchema } from "@faire-auth/core/db";
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
24
|
+
// src/api/schema/account.ts
|
|
25
|
+
const socialProviderListEnum = z.enum(social_providers_exports.socialProviderList).or(z.string());
|
|
26
|
+
const linkAccountSchema = z.object({
|
|
27
|
+
/**
|
|
28
|
+
* Callback URL to redirect to after the user has signed in.
|
|
29
|
+
*/
|
|
28
30
|
callbackURL: callbackURLSchema(true).openapi({ description: "The URL to redirect to after the user has signed in" }),
|
|
31
|
+
/**
|
|
32
|
+
* OAuth2 provider to use
|
|
33
|
+
*/
|
|
29
34
|
provider: socialProviderListEnum,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
/**
|
|
36
|
+
* ID Token for direct authentication without redirect
|
|
37
|
+
*/
|
|
38
|
+
idToken: z.object({
|
|
39
|
+
token: z.string(),
|
|
40
|
+
nonce: z.string().optional(),
|
|
41
|
+
accessToken: z.string().optional(),
|
|
42
|
+
refreshToken: z.string().optional(),
|
|
43
|
+
scopes: z.array(z.string().min(1)).optional()
|
|
36
44
|
}).optional(),
|
|
37
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Additional scopes to request when linking the account.
|
|
47
|
+
* This is useful for requesting additional permissions when
|
|
48
|
+
* linking a social account compared to the initial authentication.
|
|
49
|
+
*/
|
|
50
|
+
scopes: z.array(z.string().min(1)).optional().openapi({ description: "Additional scopes to request when linking the account" }),
|
|
51
|
+
/**
|
|
52
|
+
* The URL to redirect to if there is an error during the link process.
|
|
53
|
+
*/
|
|
38
54
|
errorCallbackURL: callbackURLSchema(true).openapi({ description: "The URL to redirect to if there is an error during the link process" })
|
|
39
55
|
});
|
|
40
|
-
const unlinkAccountSchema = z
|
|
41
|
-
providerId: z
|
|
42
|
-
accountId: z
|
|
56
|
+
const unlinkAccountSchema = z.object({
|
|
57
|
+
providerId: z.string(),
|
|
58
|
+
accountId: z.string().optional()
|
|
43
59
|
});
|
|
44
|
-
const getAccessTokenSchema = z
|
|
45
|
-
providerId: z
|
|
46
|
-
accountId: z
|
|
47
|
-
userId: z
|
|
60
|
+
const getAccessTokenSchema = z.object({
|
|
61
|
+
providerId: z.string().openapi({ description: "The provider ID for the OAuth provider" }),
|
|
62
|
+
accountId: z.string().optional().openapi({ description: "The account ID associated with the refresh token" }),
|
|
63
|
+
userId: z.string().optional().openapi({ description: "The user ID associated with the account" })
|
|
48
64
|
});
|
|
49
|
-
const refreshAccessTokenSchema = z
|
|
50
|
-
providerId: z
|
|
51
|
-
accountId: z
|
|
52
|
-
userId: z
|
|
65
|
+
const refreshAccessTokenSchema = z.object({
|
|
66
|
+
providerId: z.string().openapi({ description: "The provider ID for the OAuth provider" }),
|
|
67
|
+
accountId: z.string().optional().openapi({ description: "The account ID associated with the refresh token" }),
|
|
68
|
+
userId: z.string().optional().openapi({ description: "The user ID associated with the account" })
|
|
53
69
|
});
|
|
54
|
-
const getAccountInfoSchema = z
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
const getAccountInfoSchema = z.object({ accountId: z.string().openapi({ description: "The provider given account id for which to get the account info" }) });
|
|
71
|
+
// src/api/schema/sign-in.ts
|
|
72
|
+
const signInSocialSchema = z.object({
|
|
73
|
+
/**
|
|
74
|
+
* Callback URL to redirect to after the user
|
|
75
|
+
* has signed in.
|
|
76
|
+
*/
|
|
59
77
|
callbackURL: callbackURLSchema(true).openapi({ description: "Callback URL to redirect to after the user has signed in" }),
|
|
78
|
+
/**
|
|
79
|
+
* callback url to redirect if the user is newly registered.
|
|
80
|
+
*
|
|
81
|
+
* useful if you have different routes for existing users and new users
|
|
82
|
+
*/
|
|
60
83
|
newUserCallbackURL: callbackURLSchema(true),
|
|
84
|
+
/**
|
|
85
|
+
* Callback url to redirect to if an error happens
|
|
86
|
+
*
|
|
87
|
+
* If it's initiated from the client sdk this defaults to
|
|
88
|
+
* the current url.
|
|
89
|
+
*/
|
|
61
90
|
errorCallbackURL: callbackURLSchema(true).openapi({ description: "Callback URL to redirect to if an error happens" }),
|
|
91
|
+
/**
|
|
92
|
+
* OAuth2 provider to use
|
|
93
|
+
*/
|
|
62
94
|
provider: socialProviderListEnum,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Disable automatic redirection to the provider
|
|
97
|
+
*
|
|
98
|
+
* This is useful if you want to handle the redirection
|
|
99
|
+
* yourself like in a popup or a different tab.
|
|
100
|
+
*/
|
|
101
|
+
disableRedirect: z.boolean().optional().openapi({ description: "Disable automatic redirection to the provider. Useful for handling the redirection yourself" }),
|
|
102
|
+
/**
|
|
103
|
+
* ID token from the provider
|
|
104
|
+
*
|
|
105
|
+
* This is used to sign in the user
|
|
106
|
+
* if the user is already signed in with the
|
|
107
|
+
* provider in the frontend.
|
|
108
|
+
*
|
|
109
|
+
* Only applicable if the provider supports
|
|
110
|
+
* it. Currently only `apple` and `google` is
|
|
111
|
+
* supported out of the box.
|
|
112
|
+
*/
|
|
113
|
+
idToken: z.optional(z.object({
|
|
114
|
+
/**
|
|
115
|
+
* ID token from the provider
|
|
116
|
+
*/
|
|
117
|
+
token: z.string().openapi({ description: "ID token from the provider" }),
|
|
118
|
+
/**
|
|
119
|
+
* The nonce used to generate the token
|
|
120
|
+
*/
|
|
121
|
+
nonce: z.string().optional().openapi({ description: "Nonce used to generate the token" }),
|
|
122
|
+
/**
|
|
123
|
+
* Access token from the provider
|
|
124
|
+
*/
|
|
125
|
+
accessToken: z.string().optional().openapi({ description: "Access token from the provider" }),
|
|
126
|
+
/**
|
|
127
|
+
* Refresh token from the provider
|
|
128
|
+
*/
|
|
129
|
+
refreshToken: z.string().optional().openapi({ description: "Refresh token from the provider" }),
|
|
130
|
+
/**
|
|
131
|
+
* Expiry date of the token
|
|
132
|
+
*/
|
|
133
|
+
expiresAt: z.number().optional().openapi({ description: "Expiry date of the token" })
|
|
70
134
|
})).openapi({ description: "ID token from the provider to sign in the user with id token" }),
|
|
71
|
-
scopes: z
|
|
72
|
-
|
|
73
|
-
|
|
135
|
+
scopes: z.array(z.string().min(1)).optional().openapi({ description: "Array of scopes to request from the provider. This will override the default scopes passed." }),
|
|
136
|
+
/**
|
|
137
|
+
* Explicitly request sign-up
|
|
138
|
+
*
|
|
139
|
+
* Should be used to allow sign up when
|
|
140
|
+
* disableImplicitSignUp for this provider is
|
|
141
|
+
* true
|
|
142
|
+
*/
|
|
143
|
+
requestSignUp: z.boolean().optional().openapi({ description: "Explicitly request sign-up. Useful when disableImplicitSignUp is true for this provider" }),
|
|
144
|
+
/**
|
|
145
|
+
* The login hint to use for the authorization code request
|
|
146
|
+
*/
|
|
147
|
+
loginHint: z.string().optional().openapi({ description: "The login hint to use for the authorization code request" })
|
|
74
148
|
});
|
|
75
|
-
const signInEmailSchema = z
|
|
149
|
+
const signInEmailSchema = z.object({
|
|
150
|
+
/**
|
|
151
|
+
* Email of the user
|
|
152
|
+
*/
|
|
76
153
|
email: emailSchema.openapi({ description: "Email of the user" }),
|
|
154
|
+
/**
|
|
155
|
+
* Password of the user
|
|
156
|
+
*/
|
|
77
157
|
password: passwordSchema.openapi({ description: "Password of the user" }),
|
|
158
|
+
/**
|
|
159
|
+
* Callback URL to use as a redirect for email
|
|
160
|
+
* verification and for possible redirects
|
|
161
|
+
*/
|
|
78
162
|
callbackURL: callbackURLSchema(true).openapi({ description: "Callback URL to use as a redirect for email verification" }),
|
|
79
|
-
|
|
163
|
+
/**
|
|
164
|
+
* If this is false, the session will not be remembered
|
|
165
|
+
* @default true
|
|
166
|
+
*/
|
|
167
|
+
rememberMe: z.boolean().default(true).openapi({ description: "If this is false, the session will not be remembered. Default is `true`." })
|
|
80
168
|
});
|
|
81
|
-
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/api/routes/sign-in.ts
|
|
169
|
+
// src/api/routes/sign-in.ts
|
|
84
170
|
const signInSocialRoute = createRoute({
|
|
85
171
|
operationId: Routes.SIGN_IN_SOCIAL,
|
|
86
172
|
method: "post",
|
|
@@ -279,18 +365,16 @@ const signInEmail = createEndpoint(signInEmailRoute, (options) => async (ctx) =>
|
|
|
279
365
|
user: user.user
|
|
280
366
|
}, 200);
|
|
281
367
|
});
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
state: z$1.string(),
|
|
291
|
-
user: z$1.string()
|
|
368
|
+
// src/api/schema/callback.ts
|
|
369
|
+
const callbackSchema = z.object({
|
|
370
|
+
code: z.string(),
|
|
371
|
+
error: z.string(),
|
|
372
|
+
device_id: z.string(),
|
|
373
|
+
error_description: z.string(),
|
|
374
|
+
state: z.string(),
|
|
375
|
+
user: z.string()
|
|
292
376
|
}).partial();
|
|
293
|
-
const oauthCallbackParamsSchema = z
|
|
377
|
+
const oauthCallbackParamsSchema = z.object({ id: z.string().openapi({
|
|
294
378
|
param: {
|
|
295
379
|
name: "id",
|
|
296
380
|
in: "path"
|
|
@@ -298,24 +382,22 @@ const oauthCallbackParamsSchema = z$1.object({ id: z$1.string().openapi({
|
|
|
298
382
|
description: "OAuth provider ID"
|
|
299
383
|
}) });
|
|
300
384
|
const oauthCallbackQuerySchema = callbackSchema;
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
//#region src/api/routes/callback.ts
|
|
304
|
-
const handleCallbackOAuth = async (ctx, paramsId, { code, error: error$1, device_id, error_description, state, user } = {}, options) => {
|
|
385
|
+
// src/api/routes/callback.ts
|
|
386
|
+
const handleCallbackOAuth = async (ctx, paramsId, { code, error, device_id, error_description, state, user } = {}, options) => {
|
|
305
387
|
const context = ctx.get("context");
|
|
306
388
|
const defaultErrorURL = options.onAPIError?.errorURL ?? `${context.baseURL}/error`;
|
|
307
|
-
if (error
|
|
389
|
+
if (error != null) return ctx.redirect(`${defaultErrorURL}?error=${error}&error_description=${error_description}`, 302);
|
|
308
390
|
if (state == null) {
|
|
309
|
-
context.logger.error("State not found", error
|
|
391
|
+
context.logger.error("State not found", error);
|
|
310
392
|
return ctx.redirect(`${defaultErrorURL}?error=state_not_found`, 302);
|
|
311
393
|
}
|
|
312
|
-
const res
|
|
313
|
-
if (res
|
|
314
|
-
const { codeVerifier, callbackURL, link, errorURL, newUserURL, requestSignUp } = res
|
|
315
|
-
const redirectOnError = (error
|
|
394
|
+
const res = await parseState(ctx, options);
|
|
395
|
+
if (res.type === "redirect") return res.response;
|
|
396
|
+
const { codeVerifier, callbackURL, link, errorURL, newUserURL, requestSignUp } = res.data;
|
|
397
|
+
const redirectOnError = (error) => {
|
|
316
398
|
let url = errorURL ?? defaultErrorURL;
|
|
317
|
-
if (url.includes("?")) url = `${url}&error=${error
|
|
318
|
-
else url = `${url}?error=${error
|
|
399
|
+
if (url.includes("?")) url = `${url}&error=${error}`;
|
|
400
|
+
else url = `${url}?error=${error}`;
|
|
319
401
|
return ctx.redirect(url, 302);
|
|
320
402
|
};
|
|
321
403
|
if (code == null) {
|
|
@@ -342,7 +424,7 @@ const handleCallbackOAuth = async (ctx, paramsId, { code, error: error$1, device
|
|
|
342
424
|
const userInfo = await provider.getUserInfo({
|
|
343
425
|
...tokens,
|
|
344
426
|
...user && { user: safeJSONParse(user) }
|
|
345
|
-
}).then((res
|
|
427
|
+
}).then((res) => res?.user);
|
|
346
428
|
if (!userInfo) {
|
|
347
429
|
context.logger.error("Unable to get user info");
|
|
348
430
|
return redirectOnError("unable_to_get_user_info");
|
|
@@ -377,13 +459,13 @@ const handleCallbackOAuth = async (ctx, paramsId, { code, error: error$1, device
|
|
|
377
459
|
refreshToken: await setTokenUtil(tokens.refreshToken, ctx, options),
|
|
378
460
|
...tokens.scopes && tokens.scopes.length > 0 && { scope: tokens.scopes.join(",") }
|
|
379
461
|
}) == null) return redirectOnError("unable_to_link_account");
|
|
380
|
-
let toRedirectTo
|
|
462
|
+
let toRedirectTo;
|
|
381
463
|
try {
|
|
382
|
-
toRedirectTo
|
|
464
|
+
toRedirectTo = callbackURL.toString();
|
|
383
465
|
} catch {
|
|
384
|
-
toRedirectTo
|
|
466
|
+
toRedirectTo = callbackURL;
|
|
385
467
|
}
|
|
386
|
-
return ctx.redirect(toRedirectTo
|
|
468
|
+
return ctx.redirect(toRedirectTo, 302);
|
|
387
469
|
}
|
|
388
470
|
if (userInfo.email == null) {
|
|
389
471
|
context.logger.error("Provider did not return email. This could be due to misconfiguration in the provider settings.");
|
|
@@ -452,9 +534,7 @@ const postOAuthCallback = createEndpoint(postOAuthCallbackRoute, (options) => as
|
|
|
452
534
|
const { id: paramsId } = ctx.req.valid("param");
|
|
453
535
|
return handleCallbackOAuth(ctx, paramsId, body, options);
|
|
454
536
|
});
|
|
455
|
-
|
|
456
|
-
//#endregion
|
|
457
|
-
//#region src/api/routes/sign-out.ts
|
|
537
|
+
// src/api/routes/sign-out.ts
|
|
458
538
|
const signOutRoute = createRoute({
|
|
459
539
|
operationId: Routes.SIGN_OUT,
|
|
460
540
|
method: "post",
|
|
@@ -476,35 +556,40 @@ const signOut = createEndpoint(signOutRoute, (_options) => async (ctx) => {
|
|
|
476
556
|
deleteSessionCookie(ctx);
|
|
477
557
|
return ctx.render({ success: True }, 200);
|
|
478
558
|
});
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
559
|
+
// src/api/schema/reset-password.ts
|
|
560
|
+
const requestPasswordResetSchema = z.object({
|
|
561
|
+
/**
|
|
562
|
+
* The email address of the user to send the password reset email to.
|
|
563
|
+
*/
|
|
483
564
|
email: emailSchema.openapi({ description: "The email address of the user to send the password reset email to" }),
|
|
565
|
+
/**
|
|
566
|
+
* The URL to redirect the user to reset their password.
|
|
567
|
+
* If the token isn't valid or expired, it'll be redirected with a query parameter `?
|
|
568
|
+
* error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?
|
|
569
|
+
* token=VALID_TOKEN
|
|
570
|
+
*/
|
|
484
571
|
redirectTo: callbackURLSchema(true).openapi({ description: "The URL to redirect the user to reset their password. If the token isn't valid or expired, it'll be redirected with a query parameter `?error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?token=VALID_TOKEN`" })
|
|
485
572
|
});
|
|
486
|
-
const requestPasswordResetCallbackParamsSchema = z
|
|
573
|
+
const requestPasswordResetCallbackParamsSchema = z.object({ token: z.string().openapi({ param: {
|
|
487
574
|
in: "path",
|
|
488
575
|
name: "token"
|
|
489
576
|
} }) });
|
|
490
|
-
const requestPasswordResetCallbackQuerySchema = z
|
|
577
|
+
const requestPasswordResetCallbackQuerySchema = z.object({ callbackURL: callbackURLSchema().openapi({
|
|
491
578
|
param: {
|
|
492
579
|
in: "query",
|
|
493
580
|
name: "callbackURL"
|
|
494
581
|
},
|
|
495
582
|
description: "The URL to redirect the user to reset their password"
|
|
496
583
|
}) });
|
|
497
|
-
const resetPasswordSchema = z
|
|
584
|
+
const resetPasswordSchema = z.object({
|
|
498
585
|
newPassword: passwordSchema.openapi({ description: "The new password to set" }),
|
|
499
|
-
token: z
|
|
586
|
+
token: z.string().optional().openapi({ description: "The token to reset the password" })
|
|
500
587
|
});
|
|
501
|
-
const resetPasswordQuerySchema = z
|
|
588
|
+
const resetPasswordQuerySchema = z.object({ token: z.string().optional().openapi({ param: {
|
|
502
589
|
in: "query",
|
|
503
590
|
name: "token"
|
|
504
591
|
} }) });
|
|
505
|
-
|
|
506
|
-
//#endregion
|
|
507
|
-
//#region src/api/routes/reset-password.ts
|
|
592
|
+
// src/api/routes/reset-password.ts
|
|
508
593
|
const redirectError = (ctx, callbackURL, query) => {
|
|
509
594
|
const url = callbackURL != null ? new URL(callbackURL, ctx.get("context").baseURL) : new URL(`${ctx.get("context").baseURL}/error`);
|
|
510
595
|
if (query) Object.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));
|
|
@@ -541,7 +626,7 @@ const requestPasswordReset = createEndpoint(requestPasswordResetRoute, (options)
|
|
|
541
626
|
message: "If this email exists in our system, check your email for the reset link"
|
|
542
627
|
}, 200);
|
|
543
628
|
}
|
|
544
|
-
const expiresAt = getDate(options.emailAndPassword.resetPasswordTokenExpiresIn ?? 3600
|
|
629
|
+
const expiresAt = getDate(options.emailAndPassword.resetPasswordTokenExpiresIn ?? 3600, "sec");
|
|
545
630
|
const verificationToken = generateId(24);
|
|
546
631
|
await context.internalAdapter.createVerificationValue({
|
|
547
632
|
value: user.user.id,
|
|
@@ -623,9 +708,7 @@ const resetPassword = createEndpoint(resetPasswordRoute, (options) => async (ctx
|
|
|
623
708
|
if (options.emailAndPassword?.revokeSessionsOnPasswordReset) await context.internalAdapter.deleteSessions(userId);
|
|
624
709
|
return ctx.render({ success: True }, 200);
|
|
625
710
|
});
|
|
626
|
-
|
|
627
|
-
//#endregion
|
|
628
|
-
//#region src/api/schema/update-user.ts
|
|
711
|
+
// src/api/schema/update-user.ts
|
|
629
712
|
const updateUserSchema = looseUserSchema.omit({
|
|
630
713
|
id: true,
|
|
631
714
|
createdAt: true,
|
|
@@ -633,19 +716,40 @@ const updateUserSchema = looseUserSchema.omit({
|
|
|
633
716
|
emailVerified: true,
|
|
634
717
|
email: true
|
|
635
718
|
});
|
|
636
|
-
const changePasswordSchema = z
|
|
719
|
+
const changePasswordSchema = z.object({
|
|
720
|
+
/**
|
|
721
|
+
* The new password to set
|
|
722
|
+
*/
|
|
637
723
|
newPassword: passwordSchema.openapi({ description: "The new password to set" }),
|
|
724
|
+
/**
|
|
725
|
+
* The current password of the user
|
|
726
|
+
*/
|
|
638
727
|
currentPassword: passwordSchema.openapi({ description: "The current password" }),
|
|
639
|
-
|
|
728
|
+
/**
|
|
729
|
+
* revoke all sessions that are not the
|
|
730
|
+
* current one logged in by the user
|
|
731
|
+
*/
|
|
732
|
+
revokeOtherSessions: z.boolean().optional().openapi({ description: "Revoke all other sessions" })
|
|
640
733
|
});
|
|
641
|
-
const setPasswordSchema = z
|
|
642
|
-
const deleteUserSchema = z
|
|
734
|
+
const setPasswordSchema = z.object({ newPassword: passwordSchema });
|
|
735
|
+
const deleteUserSchema = z.object({
|
|
736
|
+
/**
|
|
737
|
+
* The callback URL to redirect to after the user is deleted
|
|
738
|
+
* this is only used on delete user callback
|
|
739
|
+
*/
|
|
643
740
|
callbackURL: callbackURLSchema(true).openapi({ description: "The callback URL to redirect to after the user is deleted" }),
|
|
741
|
+
/**
|
|
742
|
+
* The password of the user. If the password isn't provided, session freshness
|
|
743
|
+
* will be checked.
|
|
744
|
+
*/
|
|
644
745
|
password: passwordSchema.optional().openapi({ description: "The password of the user. If the password isn't provided, session freshness will be checked." }),
|
|
645
|
-
|
|
746
|
+
/**
|
|
747
|
+
* The token to delete the user. If the token is provided, the user will be deleted
|
|
748
|
+
*/
|
|
749
|
+
token: z.string().optional().openapi({ description: "The token to delete the user. If the token is provided, the user will be deleted" })
|
|
646
750
|
});
|
|
647
|
-
const deleteUserCallbackQuerySchema = z
|
|
648
|
-
token: z
|
|
751
|
+
const deleteUserCallbackQuerySchema = z.object({
|
|
752
|
+
token: z.string().openapi({ param: {
|
|
649
753
|
in: "query",
|
|
650
754
|
name: "token"
|
|
651
755
|
} }),
|
|
@@ -654,13 +758,11 @@ const deleteUserCallbackQuerySchema = z$1.object({
|
|
|
654
758
|
name: "callbackURL"
|
|
655
759
|
} })
|
|
656
760
|
});
|
|
657
|
-
const changeEmailSchema = z
|
|
761
|
+
const changeEmailSchema = z.object({
|
|
658
762
|
newEmail: emailSchema.openapi({ description: "The new email to set" }),
|
|
659
763
|
callbackURL: callbackURLSchema(true).openapi({ description: "The URL to redirect to after email verification" })
|
|
660
764
|
});
|
|
661
|
-
|
|
662
|
-
//#endregion
|
|
663
|
-
//#region src/api/routes/update-user.ts
|
|
765
|
+
// src/api/routes/update-user.ts
|
|
664
766
|
const updateUserRoute = createRoute({
|
|
665
767
|
operationId: Routes.UPDATE_USER,
|
|
666
768
|
method: "post",
|
|
@@ -671,7 +773,7 @@ const updateUserRoute = createRoute({
|
|
|
671
773
|
responses: res(SCHEMAS[Definitions.SUCCESS].default).zod().err(500, "Failed to update user").bld()
|
|
672
774
|
});
|
|
673
775
|
const updateUser = createEndpoint(updateUserRoute, (options) => async (ctx) => {
|
|
674
|
-
const { name, image
|
|
776
|
+
const { name, image, ...rest } = ctx.req.valid("json");
|
|
675
777
|
if (image === void 0 && name === void 0 && Object.keys(rest).length === 0) return ctx.render({ success: True }, 200);
|
|
676
778
|
const context = ctx.get("context");
|
|
677
779
|
const session = ctx.get("session");
|
|
@@ -707,7 +809,7 @@ const changePasswordRoute = createRoute({
|
|
|
707
809
|
const changePassword = createEndpoint(changePasswordRoute, (options) => async (ctx) => {
|
|
708
810
|
const context = ctx.get("context");
|
|
709
811
|
const session = ctx.get("session");
|
|
710
|
-
const { newPassword, currentPassword, revokeOtherSessions
|
|
812
|
+
const { newPassword, currentPassword, revokeOtherSessions } = ctx.req.valid("json");
|
|
711
813
|
const { minPasswordLength } = context.password.config;
|
|
712
814
|
if (newPassword.length < minPasswordLength) {
|
|
713
815
|
context.logger.error("Password is too short");
|
|
@@ -724,7 +826,7 @@ const changePassword = createEndpoint(changePasswordRoute, (options) => async (c
|
|
|
724
826
|
message: BASE_ERROR_CODES.PASSWORD_TOO_LONG
|
|
725
827
|
}, 400);
|
|
726
828
|
}
|
|
727
|
-
const account = (await context.internalAdapter.findAccounts(session.user.id)).find((account
|
|
829
|
+
const account = (await context.internalAdapter.findAccounts(session.user.id)).find((account) => account.providerId === "credential" && account.password != null);
|
|
728
830
|
if (account?.password == null) return ctx.render({
|
|
729
831
|
success: False,
|
|
730
832
|
message: BASE_ERROR_CODES.CREDENTIAL_ACCOUNT_NOT_FOUND
|
|
@@ -739,7 +841,7 @@ const changePassword = createEndpoint(changePasswordRoute, (options) => async (c
|
|
|
739
841
|
}, 400);
|
|
740
842
|
await context.internalAdapter.updateAccount(account.id, { password: passwordHash });
|
|
741
843
|
let token = session.session.token;
|
|
742
|
-
if (revokeOtherSessions
|
|
844
|
+
if (revokeOtherSessions === true) {
|
|
743
845
|
await context.internalAdapter.deleteSessions(session.user.id);
|
|
744
846
|
const newSession = await context.internalAdapter.createSession(session.user.id);
|
|
745
847
|
if (newSession == null) return ctx.render({
|
|
@@ -789,7 +891,7 @@ const setPassword = createEndpoint(setPasswordRoute, (_options) => async (ctx) =
|
|
|
789
891
|
message: BASE_ERROR_CODES.PASSWORD_TOO_LONG
|
|
790
892
|
}, 400);
|
|
791
893
|
}
|
|
792
|
-
const account = (await context.internalAdapter.findAccounts(session.user.id)).find((account
|
|
894
|
+
const account = (await context.internalAdapter.findAccounts(session.user.id)).find((account) => account.providerId === "credential" && account.password != null);
|
|
793
895
|
const passwordHash = await context.password.hash(newPassword);
|
|
794
896
|
if (!account) {
|
|
795
897
|
await context.internalAdapter.linkAccount({
|
|
@@ -827,7 +929,7 @@ const deleteUser = createEndpoint(deleteUserRoute, (options) => async (ctx) => {
|
|
|
827
929
|
const api = ctx.get("api");
|
|
828
930
|
const { callbackURL, password, token } = ctx.req.valid("json");
|
|
829
931
|
let canDelete = false;
|
|
830
|
-
const account = (await context.internalAdapter.findAccounts(session.user.id)).find((account
|
|
932
|
+
const account = (await context.internalAdapter.findAccounts(session.user.id)).find((account) => account.providerId === "credential" && account.password != null);
|
|
831
933
|
if (password != null) {
|
|
832
934
|
if (account?.password == null) return ctx.render({
|
|
833
935
|
success: False,
|
|
@@ -842,23 +944,23 @@ const deleteUser = createEndpoint(deleteUserRoute, (options) => async (ctx) => {
|
|
|
842
944
|
}, 400);
|
|
843
945
|
canDelete = true;
|
|
844
946
|
}
|
|
845
|
-
if (token != null) return await api.deleteUserCallback({ query: { token } }, ctx).then((res
|
|
947
|
+
if (token != null) return await api.deleteUserCallback({ query: { token } }, ctx).then((res) => res instanceof Response ? res : ctx.render(res, res.success === true ? 200 : "errors" in res ? 422 : 404));
|
|
846
948
|
if (options.user?.deleteUser?.sendDeleteAccountVerification != null) {
|
|
847
949
|
if (account?.password != null && !canDelete) return ctx.render({
|
|
848
950
|
success: False,
|
|
849
951
|
message: BASE_ERROR_CODES.USER_ALREADY_HAS_PASSWORD
|
|
850
952
|
}, 400);
|
|
851
|
-
const token
|
|
953
|
+
const token = (0, crypto_exports.generateRandomString)(32, "0-9", "a-z");
|
|
852
954
|
await context.internalAdapter.createVerificationValue({
|
|
853
955
|
value: session.user.id,
|
|
854
|
-
identifier: `delete-account-${token
|
|
855
|
-
expiresAt: new Date(Date.now() + (options.user.deleteUser.deleteTokenExpiresIn ??
|
|
956
|
+
identifier: `delete-account-${token}`,
|
|
957
|
+
expiresAt: new Date(Date.now() + (options.user.deleteUser.deleteTokenExpiresIn ?? 86400) * 1e3)
|
|
856
958
|
});
|
|
857
|
-
const url = `${context.baseURL}/delete-user/callback?token=${token
|
|
959
|
+
const url = `${context.baseURL}/delete-user/callback?token=${token}${callbackURL ? `&callbackURL=${callbackURL}` : ""}`;
|
|
858
960
|
await options.user.deleteUser.sendDeleteAccountVerification({
|
|
859
961
|
user: session.user,
|
|
860
962
|
url,
|
|
861
|
-
token
|
|
963
|
+
token
|
|
862
964
|
}, ctx);
|
|
863
965
|
return ctx.render({
|
|
864
966
|
success: True,
|
|
@@ -990,12 +1092,12 @@ const changeEmail = createEndpoint(changeEmailRoute, (options) => async (ctx) =>
|
|
|
990
1092
|
}
|
|
991
1093
|
});
|
|
992
1094
|
if (options.emailVerification?.sendVerificationEmail) {
|
|
993
|
-
const token
|
|
994
|
-
const url
|
|
1095
|
+
const token = await createEmailVerificationToken(context.secret, newEmail, void 0, options.emailVerification.expiresIn);
|
|
1096
|
+
const url = `${context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL ?? "/"}`;
|
|
995
1097
|
await options.emailVerification.sendVerificationEmail({
|
|
996
1098
|
user: session.user,
|
|
997
|
-
url
|
|
998
|
-
token
|
|
1099
|
+
url,
|
|
1100
|
+
token
|
|
999
1101
|
}, ctx);
|
|
1000
1102
|
}
|
|
1001
1103
|
return ctx.render({ success: True }, 200);
|
|
@@ -1020,9 +1122,7 @@ const changeEmail = createEndpoint(changeEmailRoute, (options) => async (ctx) =>
|
|
|
1020
1122
|
}, ctx);
|
|
1021
1123
|
return ctx.render({ success: True }, 200);
|
|
1022
1124
|
});
|
|
1023
|
-
|
|
1024
|
-
//#endregion
|
|
1025
|
-
//#region src/api/routes/error.ts
|
|
1125
|
+
// src/api/routes/error.ts
|
|
1026
1126
|
const sanitize = (input) => input.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
1027
1127
|
const html = (errorCode = "Unknown", errorDescription) => `<!DOCTYPE html>
|
|
1028
1128
|
<html lang="en">
|
|
@@ -1111,9 +1211,9 @@ const html = (errorCode = "Unknown", errorDescription) => `<!DOCTYPE html>
|
|
|
1111
1211
|
</div>
|
|
1112
1212
|
</body>
|
|
1113
1213
|
</html>`;
|
|
1114
|
-
const errorQuerySchema = z
|
|
1115
|
-
error: z
|
|
1116
|
-
error_description: z
|
|
1214
|
+
const errorQuerySchema = z.object({
|
|
1215
|
+
error: z.string().optional(),
|
|
1216
|
+
error_description: z.string().optional()
|
|
1117
1217
|
});
|
|
1118
1218
|
const errorRoute = createRoute({
|
|
1119
1219
|
operationId: Routes.ERROR,
|
|
@@ -1123,15 +1223,13 @@ const errorRoute = createRoute({
|
|
|
1123
1223
|
path: "/error",
|
|
1124
1224
|
description: "Displays an error page",
|
|
1125
1225
|
request: req().qry(errorQuerySchema).bld(),
|
|
1126
|
-
responses: res(z
|
|
1226
|
+
responses: res(z.string().openapi({ description: "The HTML content of the error page" }), "A HTML error page", "text/html").zod().bld()
|
|
1127
1227
|
});
|
|
1128
1228
|
const error = createEndpoint(errorRoute, (_options) => async (ctx) => {
|
|
1129
|
-
const { error
|
|
1130
|
-
return ctx.html(html(error
|
|
1229
|
+
const { error, error_description: _error_description } = ctx.req.valid("query");
|
|
1230
|
+
return ctx.html(html(error), 200);
|
|
1131
1231
|
});
|
|
1132
|
-
|
|
1133
|
-
//#endregion
|
|
1134
|
-
//#region src/api/routes/ok.ts
|
|
1232
|
+
// src/api/routes/ok.ts
|
|
1135
1233
|
const okRoute = createRoute({
|
|
1136
1234
|
operationId: Routes.OK,
|
|
1137
1235
|
hide: true,
|
|
@@ -1142,20 +1240,36 @@ const okRoute = createRoute({
|
|
|
1142
1240
|
responses: res(SCHEMAS[Definitions.SUCCESS].default, "API is working").bld()
|
|
1143
1241
|
});
|
|
1144
1242
|
const ok = createEndpoint(okRoute, (_options) => async (ctx) => ctx.render({ success: True }, 200));
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1243
|
+
// src/api/schema/sign-up.ts
|
|
1244
|
+
const signUpEmailSchema = z.looseObject({
|
|
1245
|
+
/**
|
|
1246
|
+
* Name of the user
|
|
1247
|
+
*/
|
|
1149
1248
|
name: nameSchema,
|
|
1249
|
+
/**
|
|
1250
|
+
* Email of the user
|
|
1251
|
+
*/
|
|
1150
1252
|
email: emailSchema.openapi({ description: "The email of the user" }),
|
|
1253
|
+
/**
|
|
1254
|
+
* Password of the user
|
|
1255
|
+
*/
|
|
1151
1256
|
password: passwordSchema.openapi({ description: "The password of the user" }),
|
|
1152
|
-
|
|
1257
|
+
/**
|
|
1258
|
+
* Image url for the user
|
|
1259
|
+
*/
|
|
1260
|
+
image: z.url().nullish().openapi({ description: "The profile image URL of the user" }),
|
|
1261
|
+
/**
|
|
1262
|
+
* Callback URL to use as a redirect for email
|
|
1263
|
+
* verification and for possible redirects
|
|
1264
|
+
*/
|
|
1153
1265
|
callbackURL: callbackURLSchema(true).openapi({ description: "The URL to use for email verification callback" }),
|
|
1154
|
-
|
|
1266
|
+
/**
|
|
1267
|
+
* If this is false, the session will not be remembered
|
|
1268
|
+
* @default true
|
|
1269
|
+
*/
|
|
1270
|
+
rememberMe: z.boolean().default(true).openapi({ description: "If this is false, the session will not be remembered. Default is `true`." })
|
|
1155
1271
|
});
|
|
1156
|
-
|
|
1157
|
-
//#endregion
|
|
1158
|
-
//#region src/api/routes/sign-up.ts
|
|
1272
|
+
// src/api/routes/sign-up.ts
|
|
1159
1273
|
const signUpEmailRoute = createRoute({
|
|
1160
1274
|
operationId: Routes.SIGN_UP_EMAIL,
|
|
1161
1275
|
method: "post",
|
|
@@ -1169,7 +1283,7 @@ const signUpEmail = createEndpoint(signUpEmailRoute, (options) => async (ctx) =>
|
|
|
1169
1283
|
success: False,
|
|
1170
1284
|
message: "Email and password sign up is not enabled"
|
|
1171
1285
|
}, 400);
|
|
1172
|
-
const { name, email, password, image, callbackURL, rememberMe
|
|
1286
|
+
const { name, email, password, image, callbackURL, rememberMe, ...additionalFields } = ctx.req.valid("json");
|
|
1173
1287
|
const context = ctx.get("context");
|
|
1174
1288
|
const { minPasswordLength, maxPasswordLength } = context.password.config;
|
|
1175
1289
|
if (password.length < minPasswordLength) {
|
|
@@ -1262,9 +1376,7 @@ const signUpEmail = createEndpoint(signUpEmailRoute, (options) => async (ctx) =>
|
|
|
1262
1376
|
}, 200);
|
|
1263
1377
|
});
|
|
1264
1378
|
});
|
|
1265
|
-
|
|
1266
|
-
//#endregion
|
|
1267
|
-
//#region src/api/routes/account.ts
|
|
1379
|
+
// src/api/routes/account.ts
|
|
1268
1380
|
const listAccountsRoute = createRoute({
|
|
1269
1381
|
operationId: Routes.LIST_ACCOUNTS,
|
|
1270
1382
|
method: "get",
|
|
@@ -1574,9 +1686,7 @@ const getAccountInfo = createEndpoint(getAccountInfoRoute, (_options) => async (
|
|
|
1574
1686
|
}, 500);
|
|
1575
1687
|
return ctx.render(info, 200);
|
|
1576
1688
|
});
|
|
1577
|
-
|
|
1578
|
-
//#endregion
|
|
1579
|
-
//#region src/api/endpoints.ts
|
|
1689
|
+
// src/api/endpoints.ts
|
|
1580
1690
|
const staticRouteMap = {
|
|
1581
1691
|
[Routes.SET_PASSWORD]: setPassword,
|
|
1582
1692
|
[Routes.CHANGE_EMAIL]: changeEmail,
|
|
@@ -1642,16 +1752,14 @@ const createArgs = (endpoints, builtSchemas, context, routeHooks) => {
|
|
|
1642
1752
|
}
|
|
1643
1753
|
return groups;
|
|
1644
1754
|
};
|
|
1645
|
-
|
|
1646
|
-
//#endregion
|
|
1647
|
-
//#region src/api/middleware/intercept.ts
|
|
1755
|
+
// src/api/middleware/intercept.ts
|
|
1648
1756
|
const runIntercept = (ctx, hooks) => {
|
|
1649
1757
|
let response = void 0;
|
|
1650
1758
|
for (const hook of hooks) try {
|
|
1651
1759
|
const result = hook(ctx);
|
|
1652
1760
|
if (result instanceof Response) response = result;
|
|
1653
|
-
} catch (error
|
|
1654
|
-
ctx.error = error
|
|
1761
|
+
} catch (error) {
|
|
1762
|
+
ctx.error = error;
|
|
1655
1763
|
}
|
|
1656
1764
|
return response;
|
|
1657
1765
|
};
|
|
@@ -1683,9 +1791,7 @@ const initInterceptMiddleware = (options) => {
|
|
|
1683
1791
|
if (after instanceof Response) ctx.res = after;
|
|
1684
1792
|
});
|
|
1685
1793
|
};
|
|
1686
|
-
|
|
1687
|
-
//#endregion
|
|
1688
|
-
//#region src/api/middleware/on-disabled.ts
|
|
1794
|
+
// src/api/middleware/on-disabled.ts
|
|
1689
1795
|
/**
|
|
1690
1796
|
* Initializes the middleware to handle disabled paths.
|
|
1691
1797
|
* @param options - The FaireAuth options.
|
|
@@ -1699,9 +1805,7 @@ const initHandleDisabledMiddleware = (options) => {
|
|
|
1699
1805
|
return await next();
|
|
1700
1806
|
});
|
|
1701
1807
|
};
|
|
1702
|
-
|
|
1703
|
-
//#endregion
|
|
1704
|
-
//#region src/api/middleware/rate-limit.ts
|
|
1808
|
+
// src/api/middleware/rate-limit.ts
|
|
1705
1809
|
const shouldRateLimit = (max, window, rateLimitData) => {
|
|
1706
1810
|
const now = Date.now();
|
|
1707
1811
|
const windowInMs = window * 1e3;
|
|
@@ -1724,21 +1828,21 @@ const createDBStorage = (ctx) => {
|
|
|
1724
1828
|
const db = ctx.adapter;
|
|
1725
1829
|
return {
|
|
1726
1830
|
get: async (key) => {
|
|
1727
|
-
const res
|
|
1831
|
+
const res = db.findMany({
|
|
1728
1832
|
model,
|
|
1729
1833
|
where: [{
|
|
1730
1834
|
field: "key",
|
|
1731
1835
|
value: key
|
|
1732
1836
|
}]
|
|
1733
1837
|
});
|
|
1734
|
-
const data = isPromise(res
|
|
1838
|
+
const data = isPromise(res) ? (await res)[0] : res[0];
|
|
1735
1839
|
if (typeof data?.lastRequest === "bigint") data.lastRequest = Number(data.lastRequest);
|
|
1736
1840
|
return data;
|
|
1737
1841
|
},
|
|
1738
1842
|
set: async (key, value, _update) => {
|
|
1739
1843
|
try {
|
|
1740
1844
|
if (_update === true) {
|
|
1741
|
-
const res
|
|
1845
|
+
const res = db.updateMany({
|
|
1742
1846
|
model: "rateLimit",
|
|
1743
1847
|
where: [{
|
|
1744
1848
|
field: "key",
|
|
@@ -1749,9 +1853,9 @@ const createDBStorage = (ctx) => {
|
|
|
1749
1853
|
lastRequest: value.lastRequest
|
|
1750
1854
|
}
|
|
1751
1855
|
});
|
|
1752
|
-
if (isPromise(res
|
|
1856
|
+
if (isPromise(res)) await res;
|
|
1753
1857
|
} else {
|
|
1754
|
-
const res
|
|
1858
|
+
const res = await db.create({
|
|
1755
1859
|
model: "rateLimit",
|
|
1756
1860
|
data: {
|
|
1757
1861
|
key,
|
|
@@ -1759,7 +1863,7 @@ const createDBStorage = (ctx) => {
|
|
|
1759
1863
|
lastRequest: value.lastRequest
|
|
1760
1864
|
}
|
|
1761
1865
|
});
|
|
1762
|
-
if (isPromise(res
|
|
1866
|
+
if (isPromise(res)) await res;
|
|
1763
1867
|
}
|
|
1764
1868
|
} catch (e) {
|
|
1765
1869
|
ctx.logger.error("Error setting rate limit", e);
|
|
@@ -1778,8 +1882,8 @@ const getRateLimitStorage = (config, context, options) => {
|
|
|
1778
1882
|
if (options.rateLimit?.customStorage) return options.rateLimit.customStorage;
|
|
1779
1883
|
if (config.storage === "secondary-storage") return {
|
|
1780
1884
|
get: (key) => {
|
|
1781
|
-
const res
|
|
1782
|
-
return isPromise(res
|
|
1885
|
+
const res = options.secondaryStorage?.get(key);
|
|
1886
|
+
return isPromise(res) ? res.then((r) => r ? safeJSONParse(r) : void 0) : res ? safeJSONParse(res) : void 0;
|
|
1783
1887
|
},
|
|
1784
1888
|
set: (key, value) => options.secondaryStorage?.set(key, JSON.stringify(value))
|
|
1785
1889
|
};
|
|
@@ -1827,8 +1931,8 @@ const initRateLimitMiddleware = (options, rateLimit) => {
|
|
|
1827
1931
|
const _path = Object.keys(rateLimit.customRules).find((p) => p.includes("*") ? wildcardMatch(p)(path) : p === path);
|
|
1828
1932
|
if (_path) {
|
|
1829
1933
|
const customRule = rateLimit.customRules[_path];
|
|
1830
|
-
const res
|
|
1831
|
-
const resolved = isPromise(res
|
|
1934
|
+
const res = typeof customRule === "function" ? customRule(ctx.req) : customRule;
|
|
1935
|
+
const resolved = isPromise(res) ? await res : res;
|
|
1832
1936
|
if (resolved) {
|
|
1833
1937
|
window = resolved.window;
|
|
1834
1938
|
max = resolved.max;
|
|
@@ -1837,9 +1941,9 @@ const initRateLimitMiddleware = (options, rateLimit) => {
|
|
|
1837
1941
|
}
|
|
1838
1942
|
}
|
|
1839
1943
|
const storage = getRateLimitStorage(rateLimit, context, options);
|
|
1840
|
-
const res
|
|
1944
|
+
const res = storage.get(key);
|
|
1841
1945
|
const now = Date.now();
|
|
1842
|
-
const data = isPromise(res
|
|
1946
|
+
const data = isPromise(res) ? await res : res;
|
|
1843
1947
|
if (!data) {
|
|
1844
1948
|
const res2 = storage.set(key, {
|
|
1845
1949
|
key,
|
|
@@ -1849,7 +1953,10 @@ const initRateLimitMiddleware = (options, rateLimit) => {
|
|
|
1849
1953
|
if (isPromise(res2)) await res2;
|
|
1850
1954
|
} else {
|
|
1851
1955
|
const timeSinceLastRequest = now - data.lastRequest;
|
|
1852
|
-
if (shouldRateLimit(max, window, data))
|
|
1956
|
+
if (shouldRateLimit(max, window, data)) {
|
|
1957
|
+
const retryAfter = getRetryAfter(data.lastRequest, window);
|
|
1958
|
+
return rateLimitResponse(ctx, retryAfter);
|
|
1959
|
+
}
|
|
1853
1960
|
if (timeSinceLastRequest > window * 1e3) {
|
|
1854
1961
|
const res3 = storage.set(key, {
|
|
1855
1962
|
...data,
|
|
@@ -1869,9 +1976,7 @@ const initRateLimitMiddleware = (options, rateLimit) => {
|
|
|
1869
1976
|
return await next();
|
|
1870
1977
|
});
|
|
1871
1978
|
};
|
|
1872
|
-
|
|
1873
|
-
//#endregion
|
|
1874
|
-
//#region src/api/index.ts
|
|
1979
|
+
// src/api/index.ts
|
|
1875
1980
|
const router = (context, options) => {
|
|
1876
1981
|
const schemas = buildSchemas(SCHEMAS, options);
|
|
1877
1982
|
const { endpoints, hooks } = createEndpoints(options);
|
|
@@ -1887,6 +1992,4 @@ const router = (context, options) => {
|
|
|
1887
1992
|
}).basePath(options.basePath).use(setDefaultExecutionCtx, setRenderer, initContextMiddleware(options, context, endpoints), contextStorage(), initHandleDisabledMiddleware(options), initInterceptMiddleware(options), initRateLimitMiddleware(options, context.rateLimit), initOriginCheckMiddleware(options, context), initHooksMiddleware(options)).onError(initErrorHandler(options)).route("/", app)
|
|
1888
1993
|
};
|
|
1889
1994
|
};
|
|
1890
|
-
|
|
1891
|
-
//#endregion
|
|
1892
|
-
export { router as t };
|
|
1995
|
+
export { router as t };
|