better-auth 1.4.9 → 1.5.0-beta.1
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/api/index.d.mts +396 -395
- package/dist/api/index.mjs +6 -4
- package/dist/api/index.mjs.map +1 -1
- package/dist/api/middlewares/origin-check.d.mts +3 -3
- package/dist/api/middlewares/origin-check.mjs +14 -4
- package/dist/api/middlewares/origin-check.mjs.map +1 -1
- package/dist/api/routes/account.d.mts +11 -11
- package/dist/api/routes/account.mjs +59 -30
- package/dist/api/routes/account.mjs.map +1 -1
- package/dist/api/routes/callback.d.mts +2 -2
- package/dist/api/routes/email-verification.d.mts +4 -4
- package/dist/api/routes/email-verification.mjs +14 -14
- package/dist/api/routes/email-verification.mjs.map +1 -1
- package/dist/api/routes/error.d.mts +2 -2
- package/dist/api/routes/ok.d.mts +2 -2
- package/dist/api/routes/reset-password.d.mts +5 -5
- package/dist/api/routes/reset-password.mjs +9 -7
- package/dist/api/routes/reset-password.mjs.map +1 -1
- package/dist/api/routes/session.d.mts +14 -14
- package/dist/api/routes/session.mjs +31 -11
- package/dist/api/routes/session.mjs.map +1 -1
- package/dist/api/routes/sign-in.d.mts +3 -3
- package/dist/api/routes/sign-in.mjs +22 -17
- package/dist/api/routes/sign-in.mjs.map +1 -1
- package/dist/api/routes/sign-out.d.mts +2 -2
- package/dist/api/routes/sign-up.d.mts +2 -2
- package/dist/api/routes/sign-up.mjs +15 -12
- package/dist/api/routes/sign-up.mjs.map +1 -1
- package/dist/api/routes/update-user.d.mts +13 -13
- package/dist/api/routes/update-user.mjs +29 -24
- package/dist/api/routes/update-user.mjs.map +1 -1
- package/dist/api/to-auth-endpoints.mjs +7 -6
- package/dist/api/to-auth-endpoints.mjs.map +1 -1
- package/dist/client/lynx/index.d.mts +15 -15
- package/dist/client/plugins/index.d.mts +12 -2
- package/dist/client/plugins/index.mjs +11 -1
- package/dist/client/react/index.d.mts +13 -13
- package/dist/client/solid/index.d.mts +13 -13
- package/dist/client/svelte/index.d.mts +15 -15
- package/dist/client/types.d.mts +4 -1
- package/dist/client/vue/index.d.mts +13 -13
- package/dist/context/create-context.mjs +2 -2
- package/dist/context/create-context.mjs.map +1 -1
- package/dist/context/helpers.mjs +2 -2
- package/dist/context/helpers.mjs.map +1 -1
- package/dist/db/field.d.mts +6 -6
- package/dist/db/schema.mjs +14 -5
- package/dist/db/schema.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/integrations/next-js.d.mts +4 -4
- package/dist/integrations/svelte-kit.d.mts +2 -2
- package/dist/integrations/tanstack-start.d.mts +4 -4
- package/dist/oauth2/link-account.mjs +3 -2
- package/dist/oauth2/link-account.mjs.map +1 -1
- package/dist/oauth2/state.mjs +3 -3
- package/dist/oauth2/state.mjs.map +1 -1
- package/dist/plugins/admin/admin.d.mts +200 -137
- package/dist/plugins/admin/admin.mjs +3 -4
- package/dist/plugins/admin/admin.mjs.map +1 -1
- package/dist/plugins/admin/client.d.mts +87 -0
- package/dist/plugins/admin/client.mjs +3 -1
- package/dist/plugins/admin/client.mjs.map +1 -1
- package/dist/plugins/admin/error-codes.d.mts +90 -0
- package/dist/plugins/admin/error-codes.mjs.map +1 -1
- package/dist/plugins/admin/routes.mjs +40 -46
- package/dist/plugins/admin/routes.mjs.map +1 -1
- package/dist/plugins/anonymous/client.d.mts +19 -0
- package/dist/plugins/anonymous/client.mjs +4 -1
- package/dist/plugins/anonymous/client.mjs.map +1 -1
- package/dist/plugins/anonymous/error-codes.d.mts +22 -0
- package/dist/plugins/anonymous/index.d.mts +21 -9
- package/dist/plugins/anonymous/index.mjs +5 -5
- package/dist/plugins/anonymous/index.mjs.map +1 -1
- package/dist/plugins/api-key/client.d.mts +103 -0
- package/dist/plugins/api-key/client.mjs +4 -1
- package/dist/plugins/api-key/client.mjs.map +1 -1
- package/dist/plugins/api-key/error-codes.d.mts +106 -0
- package/dist/plugins/api-key/error-codes.mjs +34 -0
- package/dist/plugins/api-key/error-codes.mjs.map +1 -0
- package/dist/plugins/api-key/index.d.mts +181 -112
- package/dist/plugins/api-key/index.mjs +7 -34
- package/dist/plugins/api-key/index.mjs.map +1 -1
- package/dist/plugins/api-key/rate-limit.mjs +3 -2
- package/dist/plugins/api-key/rate-limit.mjs.map +1 -1
- package/dist/plugins/api-key/routes/create-api-key.mjs +19 -17
- package/dist/plugins/api-key/routes/create-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/delete-api-key.mjs +7 -5
- package/dist/plugins/api-key/routes/delete-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/get-api-key.mjs +5 -3
- package/dist/plugins/api-key/routes/get-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/update-api-key.mjs +18 -16
- package/dist/plugins/api-key/routes/update-api-key.mjs.map +1 -1
- package/dist/plugins/api-key/routes/verify-api-key.mjs +16 -35
- package/dist/plugins/api-key/routes/verify-api-key.mjs.map +1 -1
- package/dist/plugins/bearer/index.d.mts +3 -3
- package/dist/plugins/captcha/index.d.mts +2 -2
- package/dist/plugins/captcha/index.mjs +3 -3
- package/dist/plugins/captcha/index.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/captchafox.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/captchafox.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs.map +1 -1
- package/dist/plugins/captcha/verify-handlers/h-captcha.mjs +2 -2
- package/dist/plugins/captcha/verify-handlers/h-captcha.mjs.map +1 -1
- package/dist/plugins/custom-session/index.d.mts +5 -5
- package/dist/plugins/device-authorization/index.d.mts +54 -18
- package/dist/plugins/device-authorization/routes.mjs +18 -18
- package/dist/plugins/device-authorization/routes.mjs.map +1 -1
- package/dist/plugins/email-otp/client.d.mts +15 -0
- package/dist/plugins/email-otp/client.mjs +4 -1
- package/dist/plugins/email-otp/client.mjs.map +1 -1
- package/dist/plugins/email-otp/error-codes.d.mts +18 -0
- package/dist/plugins/email-otp/error-codes.mjs +12 -0
- package/dist/plugins/email-otp/error-codes.mjs.map +1 -0
- package/dist/plugins/email-otp/index.d.mts +64 -55
- package/dist/plugins/email-otp/index.mjs +4 -3
- package/dist/plugins/email-otp/index.mjs.map +1 -1
- package/dist/plugins/email-otp/routes.mjs +30 -35
- package/dist/plugins/email-otp/routes.mjs.map +1 -1
- package/dist/plugins/generic-oauth/client.d.mts +27 -0
- package/dist/plugins/generic-oauth/client.mjs +4 -1
- package/dist/plugins/generic-oauth/client.mjs.map +1 -1
- package/dist/plugins/generic-oauth/error-codes.d.mts +30 -0
- package/dist/plugins/generic-oauth/index.d.mts +55 -37
- package/dist/plugins/generic-oauth/index.mjs +4 -4
- package/dist/plugins/generic-oauth/index.mjs.map +1 -1
- package/dist/plugins/generic-oauth/routes.mjs +11 -12
- package/dist/plugins/generic-oauth/routes.mjs.map +1 -1
- package/dist/plugins/haveibeenpwned/index.d.mts +7 -4
- package/dist/plugins/haveibeenpwned/index.mjs +5 -4
- package/dist/plugins/haveibeenpwned/index.mjs.map +1 -1
- package/dist/plugins/index.d.mts +4 -2
- package/dist/plugins/index.mjs +6 -4
- package/dist/plugins/jwt/index.d.mts +9 -9
- package/dist/plugins/jwt/index.mjs +2 -2
- package/dist/plugins/jwt/index.mjs.map +1 -1
- package/dist/plugins/last-login-method/index.d.mts +4 -4
- package/dist/plugins/magic-link/index.d.mts +4 -4
- package/dist/plugins/mcp/authorize.mjs +1 -1
- package/dist/plugins/mcp/authorize.mjs.map +1 -1
- package/dist/plugins/mcp/index.d.mts +10 -10
- package/dist/plugins/multi-session/client.d.mts +10 -14
- package/dist/plugins/multi-session/client.mjs +5 -2
- package/dist/plugins/multi-session/client.mjs.map +1 -1
- package/dist/plugins/multi-session/error-codes.d.mts +10 -0
- package/dist/plugins/multi-session/error-codes.mjs +8 -0
- package/dist/plugins/multi-session/error-codes.mjs.map +1 -0
- package/dist/plugins/multi-session/index.d.mts +18 -14
- package/dist/plugins/multi-session/index.mjs +6 -7
- package/dist/plugins/multi-session/index.mjs.map +1 -1
- package/dist/plugins/oauth-proxy/index.d.mts +8 -8
- package/dist/plugins/oidc-provider/authorize.mjs +1 -1
- package/dist/plugins/oidc-provider/authorize.mjs.map +1 -1
- package/dist/plugins/oidc-provider/error.mjs +1 -1
- package/dist/plugins/oidc-provider/error.mjs.map +1 -1
- package/dist/plugins/oidc-provider/index.d.mts +15 -15
- package/dist/plugins/one-tap/client.d.mts +2 -2
- package/dist/plugins/one-tap/index.d.mts +2 -2
- package/dist/plugins/one-time-token/index.d.mts +5 -5
- package/dist/plugins/open-api/index.d.mts +3 -3
- package/dist/plugins/organization/client.d.mts +229 -2
- package/dist/plugins/organization/client.mjs +3 -1
- package/dist/plugins/organization/client.mjs.map +1 -1
- package/dist/plugins/organization/error-codes.d.mts +224 -56
- package/dist/plugins/organization/organization.d.mts +7 -7
- package/dist/plugins/organization/organization.mjs +4 -4
- package/dist/plugins/organization/organization.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-access-control.d.mts +22 -22
- package/dist/plugins/organization/routes/crud-access-control.mjs +40 -39
- package/dist/plugins/organization/routes/crud-access-control.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-invites.d.mts +58 -58
- package/dist/plugins/organization/routes/crud-invites.mjs +42 -40
- package/dist/plugins/organization/routes/crud-invites.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-members.d.mts +67 -67
- package/dist/plugins/organization/routes/crud-members.mjs +41 -54
- package/dist/plugins/organization/routes/crud-members.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-org.d.mts +51 -51
- package/dist/plugins/organization/routes/crud-org.mjs +28 -25
- package/dist/plugins/organization/routes/crud-org.mjs.map +1 -1
- package/dist/plugins/organization/routes/crud-team.d.mts +77 -77
- package/dist/plugins/organization/routes/crud-team.mjs +41 -47
- package/dist/plugins/organization/routes/crud-team.mjs.map +1 -1
- package/dist/plugins/phone-number/client.d.mts +51 -0
- package/dist/plugins/phone-number/client.mjs +4 -1
- package/dist/plugins/phone-number/client.mjs.map +1 -1
- package/dist/plugins/phone-number/error-codes.d.mts +54 -0
- package/dist/plugins/phone-number/index.d.mts +81 -45
- package/dist/plugins/phone-number/index.mjs +2 -2
- package/dist/plugins/phone-number/index.mjs.map +1 -1
- package/dist/plugins/phone-number/routes.mjs +27 -28
- package/dist/plugins/phone-number/routes.mjs.map +1 -1
- package/dist/plugins/siwe/index.d.mts +3 -3
- package/dist/plugins/siwe/index.mjs +7 -6
- package/dist/plugins/siwe/index.mjs.map +1 -1
- package/dist/plugins/two-factor/backup-codes/index.mjs +7 -7
- package/dist/plugins/two-factor/backup-codes/index.mjs.map +1 -1
- package/dist/plugins/two-factor/client.d.mts +39 -0
- package/dist/plugins/two-factor/client.mjs +4 -1
- package/dist/plugins/two-factor/client.mjs.map +1 -1
- package/dist/plugins/two-factor/error-code.d.mts +36 -9
- package/dist/plugins/two-factor/index.d.mts +54 -27
- package/dist/plugins/two-factor/index.mjs +4 -5
- package/dist/plugins/two-factor/index.mjs.map +1 -1
- package/dist/plugins/two-factor/otp/index.mjs +8 -6
- package/dist/plugins/two-factor/otp/index.mjs.map +1 -1
- package/dist/plugins/two-factor/totp/index.mjs +16 -8
- package/dist/plugins/two-factor/totp/index.mjs.map +1 -1
- package/dist/plugins/two-factor/verify-two-factor.mjs +9 -6
- package/dist/plugins/two-factor/verify-two-factor.mjs.map +1 -1
- package/dist/plugins/username/client.d.mts +35 -0
- package/dist/plugins/username/client.mjs +4 -1
- package/dist/plugins/username/client.mjs.map +1 -1
- package/dist/plugins/username/error-codes.d.mts +32 -8
- package/dist/plugins/username/index.d.mts +41 -17
- package/dist/plugins/username/index.mjs +21 -31
- package/dist/plugins/username/index.mjs.map +1 -1
- package/dist/plugins/username/schema.d.mts +3 -3
- package/dist/test-utils/test-instance.d.mts +1349 -1198
- package/dist/utils/is-api-error.d.mts +7 -0
- package/dist/utils/is-api-error.mjs +11 -0
- package/dist/utils/is-api-error.mjs.map +1 -0
- package/dist/utils/password.mjs +3 -3
- package/dist/utils/password.mjs.map +1 -1
- package/dist/utils/plugin-helper.mjs +2 -2
- package/dist/utils/plugin-helper.mjs.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sign-in.mjs","names":[],"sources":["../../../src/api/routes/sign-in.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { SocialProviderListEnum } from \"@better-auth/core/social-providers\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport { handleOAuthUserInfo } from \"../../oauth2/link-account\";\nimport type { InferUser } from \"../../types\";\nimport { generateState } from \"../../utils\";\nimport { createEmailVerificationToken } from \"./email-verification\";\n\nconst socialSignInBodySchema = z.object({\n\t/**\n\t * Callback URL to redirect to after the user\n\t * has signed in.\n\t */\n\tcallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Callback URL to redirect to after the user has signed in\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * callback url to redirect if the user is newly registered.\n\t *\n\t * useful if you have different routes for existing users and new users\n\t */\n\tnewUserCallbackURL: z.string().optional(),\n\t/**\n\t * Callback url to redirect to if an error happens\n\t *\n\t * If it's initiated from the client sdk this defaults to\n\t * the current url.\n\t */\n\terrorCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Callback URL to redirect to if an error happens\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * OAuth2 provider to use`\n\t */\n\tprovider: SocialProviderListEnum,\n\t/**\n\t * Disable automatic redirection to the provider\n\t *\n\t * This is useful if you want to handle the redirection\n\t * yourself like in a popup or a different tab.\n\t */\n\tdisableRedirect: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Disable automatic redirection to the provider. Useful for handling the redirection yourself\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * ID token from the provider\n\t *\n\t * This is used to sign in the user\n\t * if the user is already signed in with the\n\t * provider in the frontend.\n\t *\n\t * Only applicable if the provider supports\n\t * it. Currently only `apple` and `google` is\n\t * supported out of the box.\n\t */\n\tidToken: z.optional(\n\t\tz.object({\n\t\t\t/**\n\t\t\t * ID token from the provider\n\t\t\t */\n\t\t\ttoken: z.string().meta({\n\t\t\t\tdescription: \"ID token from the provider\",\n\t\t\t}),\n\t\t\t/**\n\t\t\t * The nonce used to generate the token\n\t\t\t */\n\t\t\tnonce: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Nonce used to generate the token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Access token from the provider\n\t\t\t */\n\t\t\taccessToken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Access token from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Refresh token from the provider\n\t\t\t */\n\t\t\trefreshToken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Refresh token from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Expiry date of the token\n\t\t\t */\n\t\t\texpiresAt: z\n\t\t\t\t.number()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Expiry date of the token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t),\n\tscopes: z\n\t\t.array(z.string())\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Array of scopes to request from the provider. This will override the default scopes passed.\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Explicitly request sign-up\n\t *\n\t * Should be used to allow sign up when\n\t * disableImplicitSignUp for this provider is\n\t * true\n\t */\n\trequestSignUp: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Explicitly request sign-up. Useful when disableImplicitSignUp is true for this provider\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * The login hint to use for the authorization code request\n\t */\n\tloginHint: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The login hint to use for the authorization code request\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Additional data to be passed through the OAuth flow\n\t */\n\tadditionalData: z.record(z.string(), z.any()).optional().meta({\n\t\tdescription: \"Additional data to be passed through the OAuth flow\",\n\t}),\n});\n\nexport const signInSocial = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/social\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"socialSignIn\",\n\t\t\tbody: socialSignInBodySchema,\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as z.infer<typeof socialSignInBodySchema>,\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\tredirect: boolean;\n\t\t\t\t\t\ttoken?: string | undefined;\n\t\t\t\t\t\turl?: string | undefined;\n\t\t\t\t\t\tuser?: InferUser<O> | undefined;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Sign in with a social provider\",\n\t\t\t\t\toperationId: \"socialSignIn\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Success - Returns either session details or redirect URL\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t// todo: we need support for multiple schema\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"Session response when idToken is provided\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\turl: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [false],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"redirect\", \"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (\n\t\t\tc,\n\t\t): Promise<\n\t\t\t| { redirect: boolean; url: string }\n\t\t\t| { redirect: boolean; token: string; url: undefined; user: InferUser<O> }\n\t\t> => {\n\t\t\tconst provider = c.context.socialProviders.find(\n\t\t\t\t(p) => p.id === c.body.provider,\n\t\t\t);\n\t\t\tif (!provider) {\n\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.PROVIDER_NOT_FOUND,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (c.body.idToken) {\n\t\t\t\tif (!provider.verifyIdToken) {\n\t\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\t\"Provider does not support id token verification\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.ID_TOKEN_NOT_SUPPORTED,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst { token, nonce } = c.body.idToken;\n\t\t\t\tconst valid = await provider.verifyIdToken(token, nonce);\n\t\t\t\tif (!valid) {\n\t\t\t\t\tc.context.logger.error(\"Invalid id token\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_TOKEN,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst userInfo = await provider.getUserInfo({\n\t\t\t\t\tidToken: token,\n\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\trefreshToken: c.body.idToken.refreshToken,\n\t\t\t\t});\n\t\t\t\tif (!userInfo || !userInfo?.user) {\n\t\t\t\t\tc.context.logger.error(\"Failed to get user info\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (!userInfo.user.email) {\n\t\t\t\t\tc.context.logger.error(\"User email not found\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_EMAIL_NOT_FOUND,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst data = await handleOAuthUserInfo(c, {\n\t\t\t\t\tuserInfo: {\n\t\t\t\t\t\t...userInfo.user,\n\t\t\t\t\t\temail: userInfo.user.email,\n\t\t\t\t\t\tid: String(userInfo.user.id),\n\t\t\t\t\t\tname: userInfo.user.name || \"\",\n\t\t\t\t\t\timage: userInfo.user.image,\n\t\t\t\t\t\temailVerified: userInfo.user.emailVerified || false,\n\t\t\t\t\t},\n\t\t\t\t\taccount: {\n\t\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\t\taccountId: String(userInfo.user.id),\n\t\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\t},\n\t\t\t\t\tcallbackURL: c.body.callbackURL,\n\t\t\t\t\tdisableSignUp:\n\t\t\t\t\t\t(provider.disableImplicitSignUp && !c.body.requestSignUp) ||\n\t\t\t\t\t\tprovider.disableSignUp,\n\t\t\t\t});\n\t\t\t\tif (data.error) {\n\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: data.error,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(c, data.data!);\n\t\t\t\treturn c.json({\n\t\t\t\t\tredirect: false,\n\t\t\t\t\ttoken: data.data!.session.token,\n\t\t\t\t\turl: undefined,\n\t\t\t\t\tuser: parseUserOutput(\n\t\t\t\t\t\tc.context.options,\n\t\t\t\t\t\tdata.data!.user,\n\t\t\t\t\t) as InferUser<O>,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst { codeVerifier, state } = await generateState(\n\t\t\t\tc,\n\t\t\t\tundefined,\n\t\t\t\tc.body.additionalData,\n\t\t\t);\n\t\t\tconst url = await provider.createAuthorizationURL({\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\t\tscopes: c.body.scopes,\n\t\t\t\tloginHint: c.body.loginHint,\n\t\t\t});\n\n\t\t\treturn c.json({\n\t\t\t\turl: url.toString(),\n\t\t\t\tredirect: !c.body.disableRedirect,\n\t\t\t});\n\t\t},\n\t);\n\nexport const signInEmail = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"signInEmail\",\n\t\t\tbody: z.object({\n\t\t\t\t/**\n\t\t\t\t * Email of the user\n\t\t\t\t */\n\t\t\t\temail: z.string().meta({\n\t\t\t\t\tdescription: \"Email of the user\",\n\t\t\t\t}),\n\t\t\t\t/**\n\t\t\t\t * Password of the user\n\t\t\t\t */\n\t\t\t\tpassword: z.string().meta({\n\t\t\t\t\tdescription: \"Password of the user\",\n\t\t\t\t}),\n\t\t\t\t/**\n\t\t\t\t * Callback URL to use as a redirect for email\n\t\t\t\t * verification and for possible redirects\n\t\t\t\t */\n\t\t\t\tcallbackURL: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.meta({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Callback URL to use as a redirect for email verification\",\n\t\t\t\t\t})\n\t\t\t\t\t.optional(),\n\t\t\t\t/**\n\t\t\t\t * If this is false, the session will not be remembered\n\t\t\t\t * @default true\n\t\t\t\t */\n\t\t\t\trememberMe: z\n\t\t\t\t\t.boolean()\n\t\t\t\t\t.meta({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"If this is false, the session will not be remembered. Default is `true`.\",\n\t\t\t\t\t})\n\t\t\t\t\t.default(true)\n\t\t\t\t\t.optional(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\temail: string;\n\t\t\t\t\t\tpassword: string;\n\t\t\t\t\t\tcallbackURL?: string | undefined;\n\t\t\t\t\t\trememberMe?: boolean | undefined;\n\t\t\t\t\t},\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\tredirect: boolean;\n\t\t\t\t\t\ttoken: string;\n\t\t\t\t\t\turl?: string | undefined;\n\t\t\t\t\t\tuser: InferUser<O>;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"signInEmail\",\n\t\t\t\t\tdescription: \"Sign in with email and password\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Success - Returns either session details or redirect URL\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t// todo: we need support for multiple schema\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"Session response when idToken is provided\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [false],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Session token\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\turl: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"redirect\", \"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (\n\t\t\tctx,\n\t\t): Promise<{\n\t\t\tredirect: boolean;\n\t\t\ttoken: string;\n\t\t\turl?: string | undefined;\n\t\t\tuser: InferUser<O>;\n\t\t}> => {\n\t\t\tif (!ctx.context.options?.emailAndPassword?.enabled) {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\t\"Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!\",\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Email and password is not enabled\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst { email, password } = ctx.body;\n\t\t\tconst isValidEmail = z.email().safeParse(email);\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\t\tincludeAccounts: true,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\t// Hash password to prevent timing attacks from revealing valid email addresses\n\t\t\t\t// By hashing passwords for invalid emails, we ensure consistent response times\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"User not found\", { email });\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst credentialAccount = user.accounts.find(\n\t\t\t\t(a) => a.providerId === \"credential\",\n\t\t\t);\n\t\t\tif (!credentialAccount) {\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"Credential account not found\", { email });\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst currentPassword = credentialAccount?.password;\n\t\t\tif (!currentPassword) {\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"Password not found\", { email });\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst validPassword = await ctx.context.password.verify({\n\t\t\t\thash: currentPassword,\n\t\t\t\tpassword,\n\t\t\t});\n\t\t\tif (!validPassword) {\n\t\t\t\tctx.context.logger.error(\"Invalid password\");\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tctx.context.options?.emailAndPassword?.requireEmailVerification &&\n\t\t\t\t!user.user.emailVerified\n\t\t\t) {\n\t\t\t\tif (!ctx.context.options?.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_NOT_VERIFIED,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (ctx.context.options?.emailVerification?.sendOnSignIn) {\n\t\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tuser.user.email,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t\t);\n\t\t\t\t\tconst callbackURL = ctx.body.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(ctx.body.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tconst url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.EMAIL_NOT_VERIFIED,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\tuser.user.id,\n\t\t\t\tctx.body.rememberMe === false,\n\t\t\t);\n\n\t\t\tif (!session) {\n\t\t\t\tctx.context.logger.error(\"Failed to create session\");\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tawait setSessionCookie(\n\t\t\t\tctx,\n\t\t\t\t{\n\t\t\t\t\tsession,\n\t\t\t\t\tuser: user.user,\n\t\t\t\t},\n\t\t\t\tctx.body.rememberMe === false,\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tredirect: !!ctx.body.callbackURL,\n\t\t\t\ttoken: session.token,\n\t\t\t\turl: ctx.body.callbackURL,\n\t\t\t\tuser: parseUserOutput(ctx.context.options, user.user) as InferUser<O>,\n\t\t\t});\n\t\t},\n\t);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sign-in.mjs","names":[],"sources":["../../../src/api/routes/sign-in.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { APIError, BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { SocialProviderListEnum } from \"@better-auth/core/social-providers\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport { handleOAuthUserInfo } from \"../../oauth2/link-account\";\nimport type { InferUser } from \"../../types\";\nimport { generateState } from \"../../utils\";\nimport { createEmailVerificationToken } from \"./email-verification\";\n\nconst socialSignInBodySchema = z.object({\n\t/**\n\t * Callback URL to redirect to after the user\n\t * has signed in.\n\t */\n\tcallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Callback URL to redirect to after the user has signed in\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * callback url to redirect if the user is newly registered.\n\t *\n\t * useful if you have different routes for existing users and new users\n\t */\n\tnewUserCallbackURL: z.string().optional(),\n\t/**\n\t * Callback url to redirect to if an error happens\n\t *\n\t * If it's initiated from the client sdk this defaults to\n\t * the current url.\n\t */\n\terrorCallbackURL: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"Callback URL to redirect to if an error happens\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * OAuth2 provider to use`\n\t */\n\tprovider: SocialProviderListEnum,\n\t/**\n\t * Disable automatic redirection to the provider\n\t *\n\t * This is useful if you want to handle the redirection\n\t * yourself like in a popup or a different tab.\n\t */\n\tdisableRedirect: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Disable automatic redirection to the provider. Useful for handling the redirection yourself\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * ID token from the provider\n\t *\n\t * This is used to sign in the user\n\t * if the user is already signed in with the\n\t * provider in the frontend.\n\t *\n\t * Only applicable if the provider supports\n\t * it. Currently only `apple` and `google` is\n\t * supported out of the box.\n\t */\n\tidToken: z.optional(\n\t\tz.object({\n\t\t\t/**\n\t\t\t * ID token from the provider\n\t\t\t */\n\t\t\ttoken: z.string().meta({\n\t\t\t\tdescription: \"ID token from the provider\",\n\t\t\t}),\n\t\t\t/**\n\t\t\t * The nonce used to generate the token\n\t\t\t */\n\t\t\tnonce: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Nonce used to generate the token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Access token from the provider\n\t\t\t */\n\t\t\taccessToken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Access token from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Refresh token from the provider\n\t\t\t */\n\t\t\trefreshToken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Refresh token from the provider\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\t/**\n\t\t\t * Expiry date of the token\n\t\t\t */\n\t\t\texpiresAt: z\n\t\t\t\t.number()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"Expiry date of the token\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t),\n\tscopes: z\n\t\t.array(z.string())\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Array of scopes to request from the provider. This will override the default scopes passed.\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Explicitly request sign-up\n\t *\n\t * Should be used to allow sign up when\n\t * disableImplicitSignUp for this provider is\n\t * true\n\t */\n\trequestSignUp: z\n\t\t.boolean()\n\t\t.meta({\n\t\t\tdescription:\n\t\t\t\t\"Explicitly request sign-up. Useful when disableImplicitSignUp is true for this provider\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * The login hint to use for the authorization code request\n\t */\n\tloginHint: z\n\t\t.string()\n\t\t.meta({\n\t\t\tdescription: \"The login hint to use for the authorization code request\",\n\t\t})\n\t\t.optional(),\n\t/**\n\t * Additional data to be passed through the OAuth flow\n\t */\n\tadditionalData: z.record(z.string(), z.any()).optional().meta({\n\t\tdescription: \"Additional data to be passed through the OAuth flow\",\n\t}),\n});\n\nexport const signInSocial = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/social\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"socialSignIn\",\n\t\t\tbody: socialSignInBodySchema,\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as z.infer<typeof socialSignInBodySchema>,\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\tredirect: boolean;\n\t\t\t\t\t\ttoken?: string | undefined;\n\t\t\t\t\t\turl?: string | undefined;\n\t\t\t\t\t\tuser?: InferUser<O> | undefined;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\tdescription: \"Sign in with a social provider\",\n\t\t\t\t\toperationId: \"socialSignIn\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Success - Returns either session details or redirect URL\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t// todo: we need support for multiple schema\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"Session response when idToken is provided\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\turl: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [false],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"redirect\", \"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (\n\t\t\tc,\n\t\t): Promise<\n\t\t\t| { redirect: boolean; url: string }\n\t\t\t| { redirect: boolean; token: string; url: undefined; user: InferUser<O> }\n\t\t> => {\n\t\t\tconst provider = c.context.socialProviders.find(\n\t\t\t\t(p) => p.id === c.body.provider,\n\t\t\t);\n\t\t\tif (!provider) {\n\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t\t{\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"NOT_FOUND\", BASE_ERROR_CODES.PROVIDER_NOT_FOUND);\n\t\t\t}\n\n\t\t\tif (c.body.idToken) {\n\t\t\t\tif (!provider.verifyIdToken) {\n\t\t\t\t\tc.context.logger.error(\n\t\t\t\t\t\t\"Provider does not support id token verification\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"NOT_FOUND\",\n\t\t\t\t\t\tBASE_ERROR_CODES.ID_TOKEN_NOT_SUPPORTED,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst { token, nonce } = c.body.idToken;\n\t\t\t\tconst valid = await provider.verifyIdToken(token, nonce);\n\t\t\t\tif (!valid) {\n\t\t\t\t\tc.context.logger.error(\"Invalid id token\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow APIError.from(\"UNAUTHORIZED\", BASE_ERROR_CODES.INVALID_TOKEN);\n\t\t\t\t}\n\t\t\t\tconst userInfo = await provider.getUserInfo({\n\t\t\t\t\tidToken: token,\n\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\trefreshToken: c.body.idToken.refreshToken,\n\t\t\t\t});\n\t\t\t\tif (!userInfo || !userInfo?.user) {\n\t\t\t\t\tc.context.logger.error(\"Failed to get user info\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\t\tBASE_ERROR_CODES.FAILED_TO_GET_USER_INFO,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!userInfo.user.email) {\n\t\t\t\t\tc.context.logger.error(\"User email not found\", {\n\t\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t\t});\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\t\tBASE_ERROR_CODES.USER_EMAIL_NOT_FOUND,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst data = await handleOAuthUserInfo(c, {\n\t\t\t\t\tuserInfo: {\n\t\t\t\t\t\t...userInfo.user,\n\t\t\t\t\t\temail: userInfo.user.email,\n\t\t\t\t\t\tid: String(userInfo.user.id),\n\t\t\t\t\t\tname: userInfo.user.name || \"\",\n\t\t\t\t\t\timage: userInfo.user.image,\n\t\t\t\t\t\temailVerified: userInfo.user.emailVerified || false,\n\t\t\t\t\t},\n\t\t\t\t\taccount: {\n\t\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\t\taccountId: String(userInfo.user.id),\n\t\t\t\t\t\taccessToken: c.body.idToken.accessToken,\n\t\t\t\t\t},\n\t\t\t\t\tcallbackURL: c.body.callbackURL,\n\t\t\t\t\tdisableSignUp:\n\t\t\t\t\t\t(provider.disableImplicitSignUp && !c.body.requestSignUp) ||\n\t\t\t\t\t\tprovider.disableSignUp,\n\t\t\t\t});\n\t\t\t\tif (data.error) {\n\t\t\t\t\tthrow APIError.from(\"UNAUTHORIZED\", {\n\t\t\t\t\t\tmessage: data.error,\n\t\t\t\t\t\tcode: \"OAUTH_LINK_ERROR\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(c, data.data!);\n\t\t\t\treturn c.json({\n\t\t\t\t\tredirect: false,\n\t\t\t\t\ttoken: data.data!.session.token,\n\t\t\t\t\turl: undefined,\n\t\t\t\t\tuser: parseUserOutput(\n\t\t\t\t\t\tc.context.options,\n\t\t\t\t\t\tdata.data!.user,\n\t\t\t\t\t) as InferUser<O>,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst { codeVerifier, state } = await generateState(\n\t\t\t\tc,\n\t\t\t\tundefined,\n\t\t\t\tc.body.additionalData,\n\t\t\t);\n\t\t\tconst url = await provider.createAuthorizationURL({\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\t\tscopes: c.body.scopes,\n\t\t\t\tloginHint: c.body.loginHint,\n\t\t\t});\n\n\t\t\treturn c.json({\n\t\t\t\turl: url.toString(),\n\t\t\t\tredirect: !c.body.disableRedirect,\n\t\t\t});\n\t\t},\n\t);\n\nexport const signInEmail = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-in/email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"signInEmail\",\n\t\t\tbody: z.object({\n\t\t\t\t/**\n\t\t\t\t * Email of the user\n\t\t\t\t */\n\t\t\t\temail: z.string().meta({\n\t\t\t\t\tdescription: \"Email of the user\",\n\t\t\t\t}),\n\t\t\t\t/**\n\t\t\t\t * Password of the user\n\t\t\t\t */\n\t\t\t\tpassword: z.string().meta({\n\t\t\t\t\tdescription: \"Password of the user\",\n\t\t\t\t}),\n\t\t\t\t/**\n\t\t\t\t * Callback URL to use as a redirect for email\n\t\t\t\t * verification and for possible redirects\n\t\t\t\t */\n\t\t\t\tcallbackURL: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.meta({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Callback URL to use as a redirect for email verification\",\n\t\t\t\t\t})\n\t\t\t\t\t.optional(),\n\t\t\t\t/**\n\t\t\t\t * If this is false, the session will not be remembered\n\t\t\t\t * @default true\n\t\t\t\t */\n\t\t\t\trememberMe: z\n\t\t\t\t\t.boolean()\n\t\t\t\t\t.meta({\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"If this is false, the session will not be remembered. Default is `true`.\",\n\t\t\t\t\t})\n\t\t\t\t\t.default(true)\n\t\t\t\t\t.optional(),\n\t\t\t}),\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\temail: string;\n\t\t\t\t\t\tpassword: string;\n\t\t\t\t\t\tcallbackURL?: string | undefined;\n\t\t\t\t\t\trememberMe?: boolean | undefined;\n\t\t\t\t\t},\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\tredirect: boolean;\n\t\t\t\t\t\ttoken: string;\n\t\t\t\t\t\turl?: string | undefined;\n\t\t\t\t\t\tuser: InferUser<O>;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"signInEmail\",\n\t\t\t\t\tdescription: \"Sign in with email and password\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Success - Returns either session details or redirect URL\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t// todo: we need support for multiple schema\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"Session response when idToken is provided\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tredirect: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\tenum: [false],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Session token\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\turl: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"redirect\", \"token\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (\n\t\t\tctx,\n\t\t): Promise<{\n\t\t\tredirect: boolean;\n\t\t\ttoken: string;\n\t\t\turl?: string | undefined;\n\t\t\tuser: InferUser<O>;\n\t\t}> => {\n\t\t\tif (!ctx.context.options?.emailAndPassword?.enabled) {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\t\"Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!\",\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"EMAIL_PASSWORD_DISABLED\",\n\t\t\t\t\tmessage: \"Email and password is not enabled\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst { email, password } = ctx.body;\n\t\t\tconst isValidEmail = z.email().safeParse(email);\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_EMAIL);\n\t\t\t}\n\t\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\t\tincludeAccounts: true,\n\t\t\t});\n\n\t\t\tif (!user) {\n\t\t\t\t// Hash password to prevent timing attacks from revealing valid email addresses\n\t\t\t\t// By hashing passwords for invalid emails, we ensure consistent response times\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"User not found\", { email });\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tBASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst credentialAccount = user.accounts.find(\n\t\t\t\t(a) => a.providerId === \"credential\",\n\t\t\t);\n\t\t\tif (!credentialAccount) {\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"Credential account not found\", { email });\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tBASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst currentPassword = credentialAccount?.password;\n\t\t\tif (!currentPassword) {\n\t\t\t\tawait ctx.context.password.hash(password);\n\t\t\t\tctx.context.logger.error(\"Password not found\", { email });\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tBASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst validPassword = await ctx.context.password.verify({\n\t\t\t\thash: currentPassword,\n\t\t\t\tpassword,\n\t\t\t});\n\t\t\tif (!validPassword) {\n\t\t\t\tctx.context.logger.error(\"Invalid password\");\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tBASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tctx.context.options?.emailAndPassword?.requireEmailVerification &&\n\t\t\t\t!user.user.emailVerified\n\t\t\t) {\n\t\t\t\tif (!ctx.context.options?.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\tthrow APIError.from(\"FORBIDDEN\", BASE_ERROR_CODES.EMAIL_NOT_VERIFIED);\n\t\t\t\t}\n\n\t\t\t\tif (ctx.context.options?.emailVerification?.sendOnSignIn) {\n\t\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tuser.user.email,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t\t);\n\t\t\t\t\tconst callbackURL = ctx.body.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(ctx.body.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tconst url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tuser: user.user,\n\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthrow APIError.from(\"FORBIDDEN\", BASE_ERROR_CODES.EMAIL_NOT_VERIFIED);\n\t\t\t}\n\n\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\tuser.user.id,\n\t\t\t\tctx.body.rememberMe === false,\n\t\t\t);\n\n\t\t\tif (!session) {\n\t\t\t\tctx.context.logger.error(\"Failed to create session\");\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"UNAUTHORIZED\",\n\t\t\t\t\tBASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tawait setSessionCookie(\n\t\t\t\tctx,\n\t\t\t\t{\n\t\t\t\t\tsession,\n\t\t\t\t\tuser: user.user,\n\t\t\t\t},\n\t\t\t\tctx.body.rememberMe === false,\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tredirect: !!ctx.body.callbackURL,\n\t\t\t\ttoken: session.token,\n\t\t\t\turl: ctx.body.callbackURL,\n\t\t\t\tuser: parseUserOutput(ctx.context.options, user.user) as InferUser<O>,\n\t\t\t});\n\t\t},\n\t);\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as better_call733 from "better-call";
|
|
2
2
|
|
|
3
3
|
//#region src/api/routes/sign-out.d.ts
|
|
4
|
-
declare const signOut:
|
|
4
|
+
declare const signOut: better_call733.StrictEndpoint<"/sign-out", {
|
|
5
5
|
method: "POST";
|
|
6
6
|
operationId: string;
|
|
7
7
|
requireHeaders: true;
|
|
@@ -2,10 +2,10 @@ import { AdditionalUserFieldsInput, InferUser } from "../../types/models.mjs";
|
|
|
2
2
|
import "../../types/index.mjs";
|
|
3
3
|
import { BetterAuthOptions } from "@better-auth/core";
|
|
4
4
|
import * as z from "zod";
|
|
5
|
-
import * as
|
|
5
|
+
import * as better_call740 from "better-call";
|
|
6
6
|
|
|
7
7
|
//#region src/api/routes/sign-up.d.ts
|
|
8
|
-
declare const signUpEmail: <O extends BetterAuthOptions>() =>
|
|
8
|
+
declare const signUpEmail: <O extends BetterAuthOptions>() => better_call740.StrictEndpoint<"/sign-up/email", {
|
|
9
9
|
method: "POST";
|
|
10
10
|
operationId: string;
|
|
11
11
|
body: z.ZodIntersection<z.ZodObject<{
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { parseUserInput, parseUserOutput } from "../../db/schema.mjs";
|
|
2
2
|
import "../../db/index.mjs";
|
|
3
|
+
import { isAPIError } from "../../utils/is-api-error.mjs";
|
|
3
4
|
import { setSessionCookie } from "../../cookies/index.mjs";
|
|
4
5
|
import { createEmailVerificationToken } from "./email-verification.mjs";
|
|
5
6
|
import { runWithTransaction } from "@better-auth/core/context";
|
|
6
7
|
import { isDevelopment } from "@better-auth/core/env";
|
|
7
|
-
import { BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
8
|
+
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
8
9
|
import * as z from "zod";
|
|
9
|
-
import { APIError } from "better-call";
|
|
10
10
|
import { createAuthEndpoint } from "@better-auth/core/api";
|
|
11
11
|
|
|
12
12
|
//#region src/api/routes/sign-up.ts
|
|
@@ -137,23 +137,26 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
137
137
|
}
|
|
138
138
|
}, async (ctx) => {
|
|
139
139
|
return runWithTransaction(ctx.context.adapter, async () => {
|
|
140
|
-
if (!ctx.context.options.emailAndPassword?.enabled || ctx.context.options.emailAndPassword?.disableSignUp) throw
|
|
140
|
+
if (!ctx.context.options.emailAndPassword?.enabled || ctx.context.options.emailAndPassword?.disableSignUp) throw APIError.from("BAD_REQUEST", {
|
|
141
|
+
message: "Email and password sign up is not enabled",
|
|
142
|
+
code: "EMAIL_PASSWORD_SIGN_UP_DISABLED"
|
|
143
|
+
});
|
|
141
144
|
const body = ctx.body;
|
|
142
145
|
const { name, email, password, image, callbackURL: _callbackURL, rememberMe, ...rest } = body;
|
|
143
|
-
if (!z.email().safeParse(email).success) throw
|
|
146
|
+
if (!z.email().safeParse(email).success) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
|
|
144
147
|
const minPasswordLength = ctx.context.password.config.minPasswordLength;
|
|
145
148
|
if (password.length < minPasswordLength) {
|
|
146
149
|
ctx.context.logger.error("Password is too short");
|
|
147
|
-
throw
|
|
150
|
+
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
|
|
148
151
|
}
|
|
149
152
|
const maxPasswordLength = ctx.context.password.config.maxPasswordLength;
|
|
150
153
|
if (password.length > maxPasswordLength) {
|
|
151
154
|
ctx.context.logger.error("Password is too long");
|
|
152
|
-
throw
|
|
155
|
+
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
|
|
153
156
|
}
|
|
154
157
|
if ((await ctx.context.internalAdapter.findUserByEmail(email))?.user) {
|
|
155
158
|
ctx.context.logger.info(`Sign-up attempt for existing email: ${email}`);
|
|
156
|
-
throw
|
|
159
|
+
throw APIError.from("UNPROCESSABLE_ENTITY", BASE_ERROR_CODES.USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL);
|
|
157
160
|
}
|
|
158
161
|
/**
|
|
159
162
|
* Hash the password
|
|
@@ -174,14 +177,14 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
174
177
|
...data,
|
|
175
178
|
emailVerified: false
|
|
176
179
|
});
|
|
177
|
-
if (!createdUser) throw
|
|
180
|
+
if (!createdUser) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.FAILED_TO_CREATE_USER);
|
|
178
181
|
} catch (e) {
|
|
179
182
|
if (isDevelopment()) ctx.context.logger.error("Failed to create user", e);
|
|
180
|
-
if (e
|
|
183
|
+
if (isAPIError(e)) throw e;
|
|
181
184
|
ctx.context.logger?.error("Failed to create user", e);
|
|
182
|
-
throw
|
|
185
|
+
throw APIError.from("UNPROCESSABLE_ENTITY", BASE_ERROR_CODES.FAILED_TO_CREATE_USER);
|
|
183
186
|
}
|
|
184
|
-
if (!createdUser) throw
|
|
187
|
+
if (!createdUser) throw APIError.from("UNPROCESSABLE_ENTITY", BASE_ERROR_CODES.FAILED_TO_CREATE_USER);
|
|
185
188
|
await ctx.context.internalAdapter.linkAccount({
|
|
186
189
|
userId: createdUser.id,
|
|
187
190
|
providerId: "credential",
|
|
@@ -203,7 +206,7 @@ const signUpEmail = () => createAuthEndpoint("/sign-up/email", {
|
|
|
203
206
|
user: parseUserOutput(ctx.context.options, createdUser)
|
|
204
207
|
});
|
|
205
208
|
const session = await ctx.context.internalAdapter.createSession(createdUser.id, rememberMe === false);
|
|
206
|
-
if (!session) throw
|
|
209
|
+
if (!session) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION);
|
|
207
210
|
await setSessionCookie(ctx, {
|
|
208
211
|
session,
|
|
209
212
|
user: createdUser
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sign-up.mjs","names":["createdUser: User"],"sources":["../../../src/api/routes/sign-up.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { runWithTransaction } from \"@better-auth/core/context\";\nimport { isDevelopment } from \"@better-auth/core/env\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { parseUserInput } from \"../../db\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport type { AdditionalUserFieldsInput, InferUser, User } from \"../../types\";\nimport { createEmailVerificationToken } from \"./email-verification\";\n\nconst signUpEmailBodySchema = z\n\t.object({\n\t\tname: z.string().nonempty(),\n\t\temail: z.email(),\n\t\tpassword: z.string().nonempty(),\n\t\timage: z.string().optional(),\n\t\tcallbackURL: z.string().optional(),\n\t\trememberMe: z.boolean().optional(),\n\t})\n\t.and(z.record(z.string(), z.any()));\n\nexport const signUpEmail = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-up/email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"signUpWithEmailAndPassword\",\n\t\t\tbody: signUpEmailBodySchema,\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\tname: string;\n\t\t\t\t\t\temail: string;\n\t\t\t\t\t\tpassword: string;\n\t\t\t\t\t\timage?: string | undefined;\n\t\t\t\t\t\tcallbackURL?: string | undefined;\n\t\t\t\t\t\trememberMe?: boolean | undefined;\n\t\t\t\t\t} & AdditionalUserFieldsInput<O>,\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\ttoken: string | null;\n\t\t\t\t\t\tuser: InferUser<O>;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"signUpWithEmailAndPassword\",\n\t\t\t\t\tdescription: \"Sign up a user using email and password\",\n\t\t\t\t\trequestBody: {\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The name of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\temail: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The email of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tpassword: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The password of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\timage: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The profile image URL of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tcallbackURL: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"The URL to use for email verification callback\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trememberMe: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"If this is false, the session will not be remembered. Default is `true`.\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"name\", \"email\", \"password\"],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"Successfully created user\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Authentication token for the session\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The unique identifier of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\temail: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"email\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The email address of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The name of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\timage: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The profile image URL of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\temailVerified: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Whether the email has been verified\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tcreatedAt: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"When the user was created\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tupdatedAt: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"When the user was last updated\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"email\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"emailVerified\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"user\"], // token is optional\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"422\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Unprocessable Entity. User already exists or failed to create user.\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn runWithTransaction(ctx.context.adapter, async () => {\n\t\t\t\tif (\n\t\t\t\t\t!ctx.context.options.emailAndPassword?.enabled ||\n\t\t\t\t\tctx.context.options.emailAndPassword?.disableSignUp\n\t\t\t\t) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: \"Email and password sign up is not enabled\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst body = ctx.body as any as User & {\n\t\t\t\t\tpassword: string;\n\t\t\t\t\tcallbackURL?: string | undefined;\n\t\t\t\t\trememberMe?: boolean | undefined;\n\t\t\t\t} & {\n\t\t\t\t\t[key: string]: any;\n\t\t\t\t};\n\t\t\t\tconst {\n\t\t\t\t\tname,\n\t\t\t\t\temail,\n\t\t\t\t\tpassword,\n\t\t\t\t\timage,\n\t\t\t\t\tcallbackURL: _callbackURL,\n\t\t\t\t\trememberMe,\n\t\t\t\t\t...rest\n\t\t\t\t} = body;\n\t\t\t\tconst isValidEmail = z.email().safeParse(email);\n\n\t\t\t\tif (!isValidEmail.success) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_EMAIL,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\t\t\tif (password.length < minPasswordLength) {\n\t\t\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_SHORT,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\t\t\t\tif (password.length > maxPasswordLength) {\n\t\t\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_LONG,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst dbUser = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\t\tif (dbUser?.user) {\n\t\t\t\t\tctx.context.logger.info(\n\t\t\t\t\t\t`Sign-up attempt for existing email: ${email}`,\n\t\t\t\t\t);\n\t\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * Hash the password\n\t\t\t\t *\n\t\t\t\t * This is done prior to creating the user\n\t\t\t\t * to ensure that any plugin that\n\t\t\t\t * may break the hashing should break\n\t\t\t\t * before the user is created.\n\t\t\t\t */\n\t\t\t\tconst hash = await ctx.context.password.hash(password);\n\t\t\t\tlet createdUser: User;\n\t\t\t\ttry {\n\t\t\t\t\tconst data = parseUserInput(ctx.context.options, rest, \"create\");\n\t\t\t\t\tcreatedUser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\t\temail: email.toLowerCase(),\n\t\t\t\t\t\tname,\n\t\t\t\t\t\timage,\n\t\t\t\t\t\t...data,\n\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t});\n\t\t\t\t\tif (!createdUser) {\n\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_USER,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (isDevelopment()) {\n\t\t\t\t\t\tctx.context.logger.error(\"Failed to create user\", e);\n\t\t\t\t\t}\n\t\t\t\t\tif (e instanceof APIError) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t\tctx.context.logger?.error(\"Failed to create user\", e);\n\t\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_USER,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (!createdUser) {\n\t\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_USER,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait ctx.context.internalAdapter.linkAccount({\n\t\t\t\t\tuserId: createdUser.id,\n\t\t\t\t\tproviderId: \"credential\",\n\t\t\t\t\taccountId: createdUser.id,\n\t\t\t\t\tpassword: hash,\n\t\t\t\t});\n\t\t\t\tif (\n\t\t\t\t\tctx.context.options.emailVerification?.sendOnSignUp ||\n\t\t\t\t\tctx.context.options.emailAndPassword.requireEmailVerification\n\t\t\t\t) {\n\t\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tcreatedUser.email,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t\t);\n\t\t\t\t\tconst callbackURL = body.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(body.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tconst url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\n\t\t\t\t\tif (ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tctx.context.options.emailAndPassword.autoSignIn === false ||\n\t\t\t\t\tctx.context.options.emailAndPassword.requireEmailVerification\n\t\t\t\t) {\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\ttoken: null,\n\t\t\t\t\t\tuser: parseUserOutput(\n\t\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\t\tcreatedUser,\n\t\t\t\t\t\t) as InferUser<O>,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tcreatedUser.id,\n\t\t\t\t\trememberMe === false,\n\t\t\t\t);\n\t\t\t\tif (!session) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(\n\t\t\t\t\tctx,\n\t\t\t\t\t{\n\t\t\t\t\t\tsession,\n\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t},\n\t\t\t\t\trememberMe === false,\n\t\t\t\t);\n\t\t\t\treturn ctx.json({\n\t\t\t\t\ttoken: session.token,\n\t\t\t\t\tuser: parseUserOutput(\n\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\tcreatedUser,\n\t\t\t\t\t) as InferUser<O>,\n\t\t\t\t});\n\t\t\t});\n\t\t},\n\t);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sign-up.mjs","names":["createdUser: User"],"sources":["../../../src/api/routes/sign-up.ts"],"sourcesContent":["import type { BetterAuthOptions } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { runWithTransaction } from \"@better-auth/core/context\";\nimport { isDevelopment } from \"@better-auth/core/env\";\nimport { APIError, BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport * as z from \"zod\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { parseUserInput } from \"../../db\";\nimport { parseUserOutput } from \"../../db/schema\";\nimport type { AdditionalUserFieldsInput, InferUser, User } from \"../../types\";\nimport { isAPIError } from \"../../utils/is-api-error\";\nimport { createEmailVerificationToken } from \"./email-verification\";\n\nconst signUpEmailBodySchema = z\n\t.object({\n\t\tname: z.string().nonempty(),\n\t\temail: z.email(),\n\t\tpassword: z.string().nonempty(),\n\t\timage: z.string().optional(),\n\t\tcallbackURL: z.string().optional(),\n\t\trememberMe: z.boolean().optional(),\n\t})\n\t.and(z.record(z.string(), z.any()));\n\nexport const signUpEmail = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-up/email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\toperationId: \"signUpWithEmailAndPassword\",\n\t\t\tbody: signUpEmailBodySchema,\n\t\t\tmetadata: {\n\t\t\t\t$Infer: {\n\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\tname: string;\n\t\t\t\t\t\temail: string;\n\t\t\t\t\t\tpassword: string;\n\t\t\t\t\t\timage?: string | undefined;\n\t\t\t\t\t\tcallbackURL?: string | undefined;\n\t\t\t\t\t\trememberMe?: boolean | undefined;\n\t\t\t\t\t} & AdditionalUserFieldsInput<O>,\n\t\t\t\t\treturned: {} as {\n\t\t\t\t\t\ttoken: string | null;\n\t\t\t\t\t\tuser: InferUser<O>;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"signUpWithEmailAndPassword\",\n\t\t\t\t\tdescription: \"Sign up a user using email and password\",\n\t\t\t\t\trequestBody: {\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The name of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\temail: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The email of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tpassword: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The password of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\timage: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription: \"The profile image URL of the user\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tcallbackURL: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"The URL to use for email verification callback\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trememberMe: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"If this is false, the session will not be remembered. Default is `true`.\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"name\", \"email\", \"password\"],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"Successfully created user\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Authentication token for the session\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The unique identifier of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\temail: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"email\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The email address of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The name of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\timage: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"uri\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"The profile image URL of the user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\temailVerified: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Whether the email has been verified\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tcreatedAt: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"When the user was created\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tupdatedAt: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tformat: \"date-time\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"When the user was last updated\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"id\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"email\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"emailVerified\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"createdAt\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"updatedAt\",\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"user\"], // token is optional\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"422\": {\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\"Unprocessable Entity. User already exists or failed to create user.\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\treturn runWithTransaction(ctx.context.adapter, async () => {\n\t\t\t\tif (\n\t\t\t\t\t!ctx.context.options.emailAndPassword?.enabled ||\n\t\t\t\t\tctx.context.options.emailAndPassword?.disableSignUp\n\t\t\t\t) {\n\t\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: \"Email and password sign up is not enabled\",\n\t\t\t\t\t\tcode: \"EMAIL_PASSWORD_SIGN_UP_DISABLED\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst body = ctx.body as any as User & {\n\t\t\t\t\tpassword: string;\n\t\t\t\t\tcallbackURL?: string | undefined;\n\t\t\t\t\trememberMe?: boolean | undefined;\n\t\t\t\t} & {\n\t\t\t\t\t[key: string]: any;\n\t\t\t\t};\n\t\t\t\tconst {\n\t\t\t\t\tname,\n\t\t\t\t\temail,\n\t\t\t\t\tpassword,\n\t\t\t\t\timage,\n\t\t\t\t\tcallbackURL: _callbackURL,\n\t\t\t\t\trememberMe,\n\t\t\t\t\t...rest\n\t\t\t\t} = body;\n\t\t\t\tconst isValidEmail = z.email().safeParse(email);\n\n\t\t\t\tif (!isValidEmail.success) {\n\t\t\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_EMAIL);\n\t\t\t\t}\n\n\t\t\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\t\t\tif (password.length < minPasswordLength) {\n\t\t\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\t\tBASE_ERROR_CODES.PASSWORD_TOO_SHORT,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\t\t\t\tif (password.length > maxPasswordLength) {\n\t\t\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\t\tBASE_ERROR_CODES.PASSWORD_TOO_LONG,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst dbUser = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\t\tif (dbUser?.user) {\n\t\t\t\t\tctx.context.logger.info(\n\t\t\t\t\t\t`Sign-up attempt for existing email: ${email}`,\n\t\t\t\t\t);\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"UNPROCESSABLE_ENTITY\",\n\t\t\t\t\t\tBASE_ERROR_CODES.USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * Hash the password\n\t\t\t\t *\n\t\t\t\t * This is done prior to creating the user\n\t\t\t\t * to ensure that any plugin that\n\t\t\t\t * may break the hashing should break\n\t\t\t\t * before the user is created.\n\t\t\t\t */\n\t\t\t\tconst hash = await ctx.context.password.hash(password);\n\t\t\t\tlet createdUser: User;\n\t\t\t\ttry {\n\t\t\t\t\tconst data = parseUserInput(ctx.context.options, rest, \"create\");\n\t\t\t\t\tcreatedUser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\t\temail: email.toLowerCase(),\n\t\t\t\t\t\tname,\n\t\t\t\t\t\timage,\n\t\t\t\t\t\t...data,\n\t\t\t\t\t\temailVerified: false,\n\t\t\t\t\t});\n\t\t\t\t\tif (!createdUser) {\n\t\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\t\t\tBASE_ERROR_CODES.FAILED_TO_CREATE_USER,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tif (isDevelopment()) {\n\t\t\t\t\t\tctx.context.logger.error(\"Failed to create user\", e);\n\t\t\t\t\t}\n\t\t\t\t\tif (isAPIError(e)) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t\tctx.context.logger?.error(\"Failed to create user\", e);\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"UNPROCESSABLE_ENTITY\",\n\t\t\t\t\t\tBASE_ERROR_CODES.FAILED_TO_CREATE_USER,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!createdUser) {\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"UNPROCESSABLE_ENTITY\",\n\t\t\t\t\t\tBASE_ERROR_CODES.FAILED_TO_CREATE_USER,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait ctx.context.internalAdapter.linkAccount({\n\t\t\t\t\tuserId: createdUser.id,\n\t\t\t\t\tproviderId: \"credential\",\n\t\t\t\t\taccountId: createdUser.id,\n\t\t\t\t\tpassword: hash,\n\t\t\t\t});\n\t\t\t\tif (\n\t\t\t\t\tctx.context.options.emailVerification?.sendOnSignUp ||\n\t\t\t\t\tctx.context.options.emailAndPassword.requireEmailVerification\n\t\t\t\t) {\n\t\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\tcreatedUser.email,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\tctx.context.options.emailVerification?.expiresIn,\n\t\t\t\t\t);\n\t\t\t\t\tconst callbackURL = body.callbackURL\n\t\t\t\t\t\t? encodeURIComponent(body.callbackURL)\n\t\t\t\t\t\t: encodeURIComponent(\"/\");\n\t\t\t\t\tconst url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\n\t\t\t\t\tif (ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\t\t\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\t\t\t\t\tctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t\t\t\t\turl,\n\t\t\t\t\t\t\t\t\ttoken,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tctx.request,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tctx.context.options.emailAndPassword.autoSignIn === false ||\n\t\t\t\t\tctx.context.options.emailAndPassword.requireEmailVerification\n\t\t\t\t) {\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\ttoken: null,\n\t\t\t\t\t\tuser: parseUserOutput(\n\t\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\t\tcreatedUser,\n\t\t\t\t\t\t) as InferUser<O>,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tcreatedUser.id,\n\t\t\t\t\trememberMe === false,\n\t\t\t\t);\n\t\t\t\tif (!session) {\n\t\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\t\"BAD_REQUEST\",\n\t\t\t\t\t\tBASE_ERROR_CODES.FAILED_TO_CREATE_SESSION,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait setSessionCookie(\n\t\t\t\t\tctx,\n\t\t\t\t\t{\n\t\t\t\t\t\tsession,\n\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t},\n\t\t\t\t\trememberMe === false,\n\t\t\t\t);\n\t\t\t\treturn ctx.json({\n\t\t\t\t\ttoken: session.token,\n\t\t\t\t\tuser: parseUserOutput(\n\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\tcreatedUser,\n\t\t\t\t\t) as InferUser<O>,\n\t\t\t\t});\n\t\t\t});\n\t\t},\n\t);\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,wBAAwB,EAC5B,OAAO;CACP,MAAM,EAAE,QAAQ,CAAC,UAAU;CAC3B,OAAO,EAAE,OAAO;CAChB,UAAU,EAAE,QAAQ,CAAC,UAAU;CAC/B,OAAO,EAAE,QAAQ,CAAC,UAAU;CAC5B,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,YAAY,EAAE,SAAS,CAAC,UAAU;CAClC,CAAC,CACD,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;AAEpC,MAAa,oBACZ,mBACC,kBACA;CACC,QAAQ;CACR,aAAa;CACb,MAAM;CACN,UAAU;EACT,QAAQ;GACP,MAAM,EAAE;GAQR,UAAU,EAAE;GAIZ;EACD,SAAS;GACR,aAAa;GACb,aAAa;GACb,aAAa,EACZ,SAAS,EACR,oBAAoB,EACnB,QAAQ;IACP,MAAM;IACN,YAAY;KACX,MAAM;MACL,MAAM;MACN,aAAa;MACb;KACD,OAAO;MACN,MAAM;MACN,aAAa;MACb;KACD,UAAU;MACT,MAAM;MACN,aAAa;MACb;KACD,OAAO;MACN,MAAM;MACN,aAAa;MACb;KACD,aAAa;MACZ,MAAM;MACN,aACC;MACD;KACD,YAAY;MACX,MAAM;MACN,aACC;MACD;KACD;IACD,UAAU;KAAC;KAAQ;KAAS;KAAW;IACvC,EACD,EACD,EACD;GACD,WAAW;IACV,OAAO;KACN,aAAa;KACb,SAAS,EACR,oBAAoB,EACnB,QAAQ;MACP,MAAM;MACN,YAAY;OACX,OAAO;QACN,MAAM;QACN,UAAU;QACV,aAAa;QACb;OACD,MAAM;QACL,MAAM;QACN,YAAY;SACX,IAAI;UACH,MAAM;UACN,aAAa;UACb;SACD,OAAO;UACN,MAAM;UACN,QAAQ;UACR,aAAa;UACb;SACD,MAAM;UACL,MAAM;UACN,aAAa;UACb;SACD,OAAO;UACN,MAAM;UACN,QAAQ;UACR,UAAU;UACV,aAAa;UACb;SACD,eAAe;UACd,MAAM;UACN,aAAa;UACb;SACD,WAAW;UACV,MAAM;UACN,QAAQ;UACR,aAAa;UACb;SACD,WAAW;UACV,MAAM;UACN,QAAQ;UACR,aAAa;UACb;SACD;QACD,UAAU;SACT;SACA;SACA;SACA;SACA;SACA;SACA;QACD;OACD;MACD,UAAU,CAAC,OAAO;MAClB,EACD,EACD;KACD;IACD,OAAO;KACN,aACC;KACD,SAAS,EACR,oBAAoB,EACnB,QAAQ;MACP,MAAM;MACN,YAAY,EACX,SAAS,EACR,MAAM,UACN,EACD;MACD,EACD,EACD;KACD;IACD;GACD;EACD;CACD,EACD,OAAO,QAAQ;AACd,QAAO,mBAAmB,IAAI,QAAQ,SAAS,YAAY;AAC1D,MACC,CAAC,IAAI,QAAQ,QAAQ,kBAAkB,WACvC,IAAI,QAAQ,QAAQ,kBAAkB,cAEtC,OAAM,SAAS,KAAK,eAAe;GAClC,SAAS;GACT,MAAM;GACN,CAAC;EAEH,MAAM,OAAO,IAAI;EAOjB,MAAM,EACL,MACA,OACA,UACA,OACA,aAAa,cACb,YACA,GAAG,SACA;AAGJ,MAAI,CAFiB,EAAE,OAAO,CAAC,UAAU,MAAM,CAE7B,QACjB,OAAM,SAAS,KAAK,eAAe,iBAAiB,cAAc;EAGnE,MAAM,oBAAoB,IAAI,QAAQ,SAAS,OAAO;AACtD,MAAI,SAAS,SAAS,mBAAmB;AACxC,OAAI,QAAQ,OAAO,MAAM,wBAAwB;AACjD,SAAM,SAAS,KACd,eACA,iBAAiB,mBACjB;;EAGF,MAAM,oBAAoB,IAAI,QAAQ,SAAS,OAAO;AACtD,MAAI,SAAS,SAAS,mBAAmB;AACxC,OAAI,QAAQ,OAAO,MAAM,uBAAuB;AAChD,SAAM,SAAS,KACd,eACA,iBAAiB,kBACjB;;AAGF,OADe,MAAM,IAAI,QAAQ,gBAAgB,gBAAgB,MAAM,GAC3D,MAAM;AACjB,OAAI,QAAQ,OAAO,KAClB,uCAAuC,QACvC;AACD,SAAM,SAAS,KACd,wBACA,iBAAiB,sCACjB;;;;;;;;;;EAUF,MAAM,OAAO,MAAM,IAAI,QAAQ,SAAS,KAAK,SAAS;EACtD,IAAIA;AACJ,MAAI;GACH,MAAM,OAAO,eAAe,IAAI,QAAQ,SAAS,MAAM,SAAS;AAChE,iBAAc,MAAM,IAAI,QAAQ,gBAAgB,WAAW;IAC1D,OAAO,MAAM,aAAa;IAC1B;IACA;IACA,GAAG;IACH,eAAe;IACf,CAAC;AACF,OAAI,CAAC,YACJ,OAAM,SAAS,KACd,eACA,iBAAiB,sBACjB;WAEM,GAAG;AACX,OAAI,eAAe,CAClB,KAAI,QAAQ,OAAO,MAAM,yBAAyB,EAAE;AAErD,OAAI,WAAW,EAAE,CAChB,OAAM;AAEP,OAAI,QAAQ,QAAQ,MAAM,yBAAyB,EAAE;AACrD,SAAM,SAAS,KACd,wBACA,iBAAiB,sBACjB;;AAEF,MAAI,CAAC,YACJ,OAAM,SAAS,KACd,wBACA,iBAAiB,sBACjB;AAEF,QAAM,IAAI,QAAQ,gBAAgB,YAAY;GAC7C,QAAQ,YAAY;GACpB,YAAY;GACZ,WAAW,YAAY;GACvB,UAAU;GACV,CAAC;AACF,MACC,IAAI,QAAQ,QAAQ,mBAAmB,gBACvC,IAAI,QAAQ,QAAQ,iBAAiB,0BACpC;GACD,MAAM,QAAQ,MAAM,6BACnB,IAAI,QAAQ,QACZ,YAAY,OACZ,QACA,IAAI,QAAQ,QAAQ,mBAAmB,UACvC;GACD,MAAM,cAAc,KAAK,cACtB,mBAAmB,KAAK,YAAY,GACpC,mBAAmB,IAAI;GAC1B,MAAM,MAAM,GAAG,IAAI,QAAQ,QAAQ,sBAAsB,MAAM,eAAe;AAE9E,OAAI,IAAI,QAAQ,QAAQ,mBAAmB,sBAC1C,OAAM,IAAI,QAAQ,uBACjB,IAAI,QAAQ,QAAQ,kBAAkB,sBACrC;IACC,MAAM;IACN;IACA;IACA,EACD,IAAI,QACJ,CACD;;AAIH,MACC,IAAI,QAAQ,QAAQ,iBAAiB,eAAe,SACpD,IAAI,QAAQ,QAAQ,iBAAiB,yBAErC,QAAO,IAAI,KAAK;GACf,OAAO;GACP,MAAM,gBACL,IAAI,QAAQ,SACZ,YACA;GACD,CAAC;EAGH,MAAM,UAAU,MAAM,IAAI,QAAQ,gBAAgB,cACjD,YAAY,IACZ,eAAe,MACf;AACD,MAAI,CAAC,QACJ,OAAM,SAAS,KACd,eACA,iBAAiB,yBACjB;AAEF,QAAM,iBACL,KACA;GACC;GACA,MAAM;GACN,EACD,eAAe,MACf;AACD,SAAO,IAAI,KAAK;GACf,OAAO,QAAQ;GACf,MAAM,gBACL,IAAI,QAAQ,SACZ,YACA;GACD,CAAC;GACD;EAEH"}
|
|
@@ -2,14 +2,14 @@ import { AdditionalUserFieldsInput } from "../../types/models.mjs";
|
|
|
2
2
|
import "../../types/index.mjs";
|
|
3
3
|
import { BetterAuthOptions } from "@better-auth/core";
|
|
4
4
|
import * as z from "zod";
|
|
5
|
-
import * as
|
|
5
|
+
import * as better_call714 from "better-call";
|
|
6
6
|
|
|
7
7
|
//#region src/api/routes/update-user.d.ts
|
|
8
|
-
declare const updateUser: <O extends BetterAuthOptions>() =>
|
|
8
|
+
declare const updateUser: <O extends BetterAuthOptions>() => better_call714.StrictEndpoint<"/update-user", {
|
|
9
9
|
method: "POST";
|
|
10
10
|
operationId: string;
|
|
11
11
|
body: z.ZodRecord<z.ZodString, z.ZodAny>;
|
|
12
|
-
use: ((inputContext:
|
|
12
|
+
use: ((inputContext: better_call714.MiddlewareInputContext<better_call714.MiddlewareOptions>) => Promise<{
|
|
13
13
|
session: {
|
|
14
14
|
session: Record<string, any> & {
|
|
15
15
|
id: string;
|
|
@@ -85,7 +85,7 @@ declare const updateUser: <O extends BetterAuthOptions>() => better_call917.Stri
|
|
|
85
85
|
}, {
|
|
86
86
|
status: boolean;
|
|
87
87
|
}>;
|
|
88
|
-
declare const changePassword:
|
|
88
|
+
declare const changePassword: better_call714.StrictEndpoint<"/change-password", {
|
|
89
89
|
method: "POST";
|
|
90
90
|
operationId: string;
|
|
91
91
|
body: z.ZodObject<{
|
|
@@ -93,7 +93,7 @@ declare const changePassword: better_call917.StrictEndpoint<"/change-password",
|
|
|
93
93
|
currentPassword: z.ZodString;
|
|
94
94
|
revokeOtherSessions: z.ZodOptional<z.ZodBoolean>;
|
|
95
95
|
}, z.core.$strip>;
|
|
96
|
-
use: ((inputContext:
|
|
96
|
+
use: ((inputContext: better_call714.MiddlewareInputContext<better_call714.MiddlewareOptions>) => Promise<{
|
|
97
97
|
session: {
|
|
98
98
|
session: Record<string, any> & {
|
|
99
99
|
id: string;
|
|
@@ -193,12 +193,12 @@ declare const changePassword: better_call917.StrictEndpoint<"/change-password",
|
|
|
193
193
|
updatedAt: Date;
|
|
194
194
|
};
|
|
195
195
|
}>;
|
|
196
|
-
declare const setPassword:
|
|
196
|
+
declare const setPassword: better_call714.StrictEndpoint<string, {
|
|
197
197
|
method: "POST";
|
|
198
198
|
body: z.ZodObject<{
|
|
199
199
|
newPassword: z.ZodString;
|
|
200
200
|
}, z.core.$strip>;
|
|
201
|
-
use: ((inputContext:
|
|
201
|
+
use: ((inputContext: better_call714.MiddlewareInputContext<better_call714.MiddlewareOptions>) => Promise<{
|
|
202
202
|
session: {
|
|
203
203
|
session: Record<string, any> & {
|
|
204
204
|
id: string;
|
|
@@ -224,9 +224,9 @@ declare const setPassword: better_call917.StrictEndpoint<string, {
|
|
|
224
224
|
}, {
|
|
225
225
|
status: boolean;
|
|
226
226
|
}>;
|
|
227
|
-
declare const deleteUser:
|
|
227
|
+
declare const deleteUser: better_call714.StrictEndpoint<"/delete-user", {
|
|
228
228
|
method: "POST";
|
|
229
|
-
use: ((inputContext:
|
|
229
|
+
use: ((inputContext: better_call714.MiddlewareInputContext<better_call714.MiddlewareOptions>) => Promise<{
|
|
230
230
|
session: {
|
|
231
231
|
session: Record<string, any> & {
|
|
232
232
|
id: string;
|
|
@@ -311,13 +311,13 @@ declare const deleteUser: better_call917.StrictEndpoint<"/delete-user", {
|
|
|
311
311
|
success: boolean;
|
|
312
312
|
message: string;
|
|
313
313
|
}>;
|
|
314
|
-
declare const deleteUserCallback:
|
|
314
|
+
declare const deleteUserCallback: better_call714.StrictEndpoint<"/delete-user/callback", {
|
|
315
315
|
method: "GET";
|
|
316
316
|
query: z.ZodObject<{
|
|
317
317
|
token: z.ZodString;
|
|
318
318
|
callbackURL: z.ZodOptional<z.ZodString>;
|
|
319
319
|
}, z.core.$strip>;
|
|
320
|
-
use: ((inputContext:
|
|
320
|
+
use: ((inputContext: better_call714.MiddlewareInputContext<better_call714.MiddlewareOptions>) => Promise<void>)[];
|
|
321
321
|
metadata: {
|
|
322
322
|
openapi: {
|
|
323
323
|
description: string;
|
|
@@ -351,13 +351,13 @@ declare const deleteUserCallback: better_call917.StrictEndpoint<"/delete-user/ca
|
|
|
351
351
|
success: boolean;
|
|
352
352
|
message: string;
|
|
353
353
|
}>;
|
|
354
|
-
declare const changeEmail:
|
|
354
|
+
declare const changeEmail: better_call714.StrictEndpoint<"/change-email", {
|
|
355
355
|
method: "POST";
|
|
356
356
|
body: z.ZodObject<{
|
|
357
357
|
newEmail: z.ZodEmail;
|
|
358
358
|
callbackURL: z.ZodOptional<z.ZodString>;
|
|
359
359
|
}, z.core.$strip>;
|
|
360
|
-
use: ((inputContext:
|
|
360
|
+
use: ((inputContext: better_call714.MiddlewareInputContext<better_call714.MiddlewareOptions>) => Promise<{
|
|
361
361
|
session: {
|
|
362
362
|
session: Record<string, any> & {
|
|
363
363
|
id: string;
|
|
@@ -6,9 +6,8 @@ import "../../crypto/index.mjs";
|
|
|
6
6
|
import { deleteSessionCookie, setSessionCookie } from "../../cookies/index.mjs";
|
|
7
7
|
import { getSessionFromCtx, sensitiveSessionMiddleware, sessionMiddleware } from "./session.mjs";
|
|
8
8
|
import { createEmailVerificationToken } from "./email-verification.mjs";
|
|
9
|
-
import { BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
9
|
+
import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
|
|
10
10
|
import * as z from "zod";
|
|
11
|
-
import { APIError } from "better-call";
|
|
12
11
|
import { createAuthEndpoint } from "@better-auth/core/api";
|
|
13
12
|
|
|
14
13
|
//#region src/api/routes/update-user.ts
|
|
@@ -52,11 +51,11 @@ const updateUser = () => createAuthEndpoint("/update-user", {
|
|
|
52
51
|
}, async (ctx) => {
|
|
53
52
|
const body = ctx.body;
|
|
54
53
|
if (typeof body !== "object" || Array.isArray(body)) throw new APIError("BAD_REQUEST", { message: "Body must be an object" });
|
|
55
|
-
if (body.email) throw
|
|
54
|
+
if (body.email) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.EMAIL_CAN_NOT_BE_UPDATED);
|
|
56
55
|
const { name, image, ...rest } = body;
|
|
57
56
|
const session = ctx.context.session;
|
|
58
57
|
const additionalFields = parseUserInput(ctx.context.options, rest, "update");
|
|
59
|
-
if (image === void 0 && name === void 0 && Object.keys(additionalFields).length === 0) throw
|
|
58
|
+
if (image === void 0 && name === void 0 && Object.keys(additionalFields).length === 0) throw APIError.fromStatus("BAD_REQUEST", { message: "No fields to update" });
|
|
60
59
|
const updatedUser = await ctx.context.internalAdapter.updateUser(session.user.id, {
|
|
61
60
|
name,
|
|
62
61
|
image,
|
|
@@ -155,26 +154,26 @@ const changePassword = createAuthEndpoint("/change-password", {
|
|
|
155
154
|
const minPasswordLength = ctx.context.password.config.minPasswordLength;
|
|
156
155
|
if (newPassword.length < minPasswordLength) {
|
|
157
156
|
ctx.context.logger.error("Password is too short");
|
|
158
|
-
throw
|
|
157
|
+
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
|
|
159
158
|
}
|
|
160
159
|
const maxPasswordLength = ctx.context.password.config.maxPasswordLength;
|
|
161
160
|
if (newPassword.length > maxPasswordLength) {
|
|
162
161
|
ctx.context.logger.error("Password is too long");
|
|
163
|
-
throw
|
|
162
|
+
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
|
|
164
163
|
}
|
|
165
164
|
const account = (await ctx.context.internalAdapter.findAccounts(session.user.id)).find((account$1) => account$1.providerId === "credential" && account$1.password);
|
|
166
|
-
if (!account || !account.password) throw
|
|
165
|
+
if (!account || !account.password) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CREDENTIAL_ACCOUNT_NOT_FOUND);
|
|
167
166
|
const passwordHash = await ctx.context.password.hash(newPassword);
|
|
168
167
|
if (!await ctx.context.password.verify({
|
|
169
168
|
hash: account.password,
|
|
170
169
|
password: currentPassword
|
|
171
|
-
})) throw
|
|
170
|
+
})) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_PASSWORD);
|
|
172
171
|
await ctx.context.internalAdapter.updateAccount(account.id, { password: passwordHash });
|
|
173
172
|
let token = null;
|
|
174
173
|
if (revokeOtherSessions) {
|
|
175
174
|
await ctx.context.internalAdapter.deleteSessions(session.user.id);
|
|
176
175
|
const newSession = await ctx.context.internalAdapter.createSession(session.user.id);
|
|
177
|
-
if (!newSession) throw
|
|
176
|
+
if (!newSession) throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_GET_SESSION);
|
|
178
177
|
await setSessionCookie(ctx, {
|
|
179
178
|
session: newSession,
|
|
180
179
|
user: session.user
|
|
@@ -204,12 +203,12 @@ const setPassword = createAuthEndpoint({
|
|
|
204
203
|
const minPasswordLength = ctx.context.password.config.minPasswordLength;
|
|
205
204
|
if (newPassword.length < minPasswordLength) {
|
|
206
205
|
ctx.context.logger.error("Password is too short");
|
|
207
|
-
throw
|
|
206
|
+
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);
|
|
208
207
|
}
|
|
209
208
|
const maxPasswordLength = ctx.context.password.config.maxPasswordLength;
|
|
210
209
|
if (newPassword.length > maxPasswordLength) {
|
|
211
210
|
ctx.context.logger.error("Password is too long");
|
|
212
|
-
throw
|
|
211
|
+
throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.PASSWORD_TOO_LONG);
|
|
213
212
|
}
|
|
214
213
|
const account = (await ctx.context.internalAdapter.findAccounts(session.user.id)).find((account$1) => account$1.providerId === "credential" && account$1.password);
|
|
215
214
|
const passwordHash = await ctx.context.password.hash(newPassword);
|
|
@@ -222,7 +221,10 @@ const setPassword = createAuthEndpoint({
|
|
|
222
221
|
});
|
|
223
222
|
return ctx.json({ status: true });
|
|
224
223
|
}
|
|
225
|
-
throw
|
|
224
|
+
throw APIError.from("BAD_REQUEST", {
|
|
225
|
+
message: "user already has a password",
|
|
226
|
+
code: "USER_ALREADY_HAS_PASSWORD"
|
|
227
|
+
});
|
|
226
228
|
});
|
|
227
229
|
const deleteUser = createAuthEndpoint("/delete-user", {
|
|
228
230
|
method: "POST",
|
|
@@ -274,16 +276,16 @@ const deleteUser = createAuthEndpoint("/delete-user", {
|
|
|
274
276
|
}, async (ctx) => {
|
|
275
277
|
if (!ctx.context.options.user?.deleteUser?.enabled) {
|
|
276
278
|
ctx.context.logger.error("Delete user is disabled. Enable it in the options");
|
|
277
|
-
throw
|
|
279
|
+
throw APIError.fromStatus("NOT_FOUND");
|
|
278
280
|
}
|
|
279
281
|
const session = ctx.context.session;
|
|
280
282
|
if (ctx.body.password) {
|
|
281
283
|
const account = (await ctx.context.internalAdapter.findAccounts(session.user.id)).find((account$1) => account$1.providerId === "credential" && account$1.password);
|
|
282
|
-
if (!account || !account.password) throw
|
|
284
|
+
if (!account || !account.password) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.CREDENTIAL_ACCOUNT_NOT_FOUND);
|
|
283
285
|
if (!await ctx.context.password.verify({
|
|
284
286
|
hash: account.password,
|
|
285
287
|
password: ctx.body.password
|
|
286
|
-
})) throw
|
|
288
|
+
})) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_PASSWORD);
|
|
287
289
|
}
|
|
288
290
|
if (ctx.body.token) {
|
|
289
291
|
await deleteUserCallback({
|
|
@@ -316,7 +318,7 @@ const deleteUser = createAuthEndpoint("/delete-user", {
|
|
|
316
318
|
if (!ctx.body.password && ctx.context.sessionConfig.freshAge !== 0) {
|
|
317
319
|
const currentAge = new Date(session.session.createdAt).getTime();
|
|
318
320
|
const freshAge = ctx.context.sessionConfig.freshAge * 1e3;
|
|
319
|
-
if (Date.now() - currentAge > freshAge * 1e3) throw
|
|
321
|
+
if (Date.now() - currentAge > freshAge * 1e3) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.SESSION_EXPIRED);
|
|
320
322
|
}
|
|
321
323
|
const beforeDelete = ctx.context.options.user.deleteUser?.beforeDelete;
|
|
322
324
|
if (beforeDelete) await beforeDelete(session.user, ctx.request);
|
|
@@ -361,13 +363,16 @@ const deleteUserCallback = createAuthEndpoint("/delete-user/callback", {
|
|
|
361
363
|
}, async (ctx) => {
|
|
362
364
|
if (!ctx.context.options.user?.deleteUser?.enabled) {
|
|
363
365
|
ctx.context.logger.error("Delete user is disabled. Enable it in the options");
|
|
364
|
-
throw
|
|
366
|
+
throw APIError.from("NOT_FOUND", {
|
|
367
|
+
message: "Not found",
|
|
368
|
+
code: "NOT_FOUND"
|
|
369
|
+
});
|
|
365
370
|
}
|
|
366
371
|
const session = await getSessionFromCtx(ctx);
|
|
367
|
-
if (!session) throw
|
|
372
|
+
if (!session) throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO);
|
|
368
373
|
const token = await ctx.context.internalAdapter.findVerificationValue(`delete-account-${ctx.query.token}`);
|
|
369
|
-
if (!token || token.expiresAt < /* @__PURE__ */ new Date()) throw
|
|
370
|
-
if (token.value !== session.user.id) throw
|
|
374
|
+
if (!token || token.expiresAt < /* @__PURE__ */ new Date()) throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.INVALID_TOKEN);
|
|
375
|
+
if (token.value !== session.user.id) throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.INVALID_TOKEN);
|
|
371
376
|
const beforeDelete = ctx.context.options.user.deleteUser?.beforeDelete;
|
|
372
377
|
if (beforeDelete) await beforeDelete(session.user, ctx.request);
|
|
373
378
|
await ctx.context.internalAdapter.deleteUser(session.user.id);
|
|
@@ -428,16 +433,16 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
428
433
|
}, async (ctx) => {
|
|
429
434
|
if (!ctx.context.options.user?.changeEmail?.enabled) {
|
|
430
435
|
ctx.context.logger.error("Change email is disabled.");
|
|
431
|
-
throw
|
|
436
|
+
throw APIError.fromStatus("BAD_REQUEST", { message: "Change email is disabled" });
|
|
432
437
|
}
|
|
433
438
|
const newEmail = ctx.body.newEmail.toLowerCase();
|
|
434
439
|
if (newEmail === ctx.context.session.user.email) {
|
|
435
440
|
ctx.context.logger.error("Email is the same");
|
|
436
|
-
throw
|
|
441
|
+
throw APIError.fromStatus("BAD_REQUEST", { message: "Email is the same" });
|
|
437
442
|
}
|
|
438
443
|
if (await ctx.context.internalAdapter.findUserByEmail(newEmail)) {
|
|
439
444
|
ctx.context.logger.error("Email already exists");
|
|
440
|
-
throw
|
|
445
|
+
throw APIError.from("UNPROCESSABLE_ENTITY", BASE_ERROR_CODES.USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL);
|
|
441
446
|
}
|
|
442
447
|
/**
|
|
443
448
|
* If the email is not verified, we can update the email if the option is enabled
|
|
@@ -479,7 +484,7 @@ const changeEmail = createAuthEndpoint("/change-email", {
|
|
|
479
484
|
}
|
|
480
485
|
if (!ctx.context.options.emailVerification?.sendVerificationEmail) {
|
|
481
486
|
ctx.context.logger.error("Verification email isn't enabled.");
|
|
482
|
-
throw
|
|
487
|
+
throw APIError.fromStatus("BAD_REQUEST", { message: "Verification email isn't enabled" });
|
|
483
488
|
}
|
|
484
489
|
const token = await createEmailVerificationToken(ctx.context.secret, ctx.context.session.user.email, newEmail, ctx.context.options.emailVerification?.expiresIn, { requestType: "change-email-verification" });
|
|
485
490
|
const url = `${ctx.context.baseURL}/verify-email?token=${token}&callbackURL=${ctx.body.callbackURL || "/"}`;
|