better-auth 0.5.2-beta.12 → 0.5.2-beta.13
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/adapters/drizzle.d.cts +1 -1
- package/dist/adapters/drizzle.d.ts +1 -1
- package/dist/adapters/kysely.d.cts +1 -1
- package/dist/adapters/kysely.d.ts +1 -1
- package/dist/adapters/mongodb.d.cts +1 -1
- package/dist/adapters/mongodb.d.ts +1 -1
- package/dist/adapters/prisma.d.cts +1 -1
- package/dist/adapters/prisma.d.ts +1 -1
- package/dist/api.cjs +1 -1
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1 -1
- package/dist/{auth-SMzIERpz.d.ts → auth-D1kVkHCi.d.ts} +24 -24
- package/dist/{auth-kXZUEU5B.d.cts → auth-D7_h4yVD.d.cts} +24 -24
- package/dist/client/plugins.d.cts +3 -3
- package/dist/client/plugins.d.ts +3 -3
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/cookies.d.cts +1 -1
- package/dist/cookies.d.ts +1 -1
- package/dist/db.d.cts +2 -2
- package/dist/db.d.ts +2 -2
- package/dist/{index-R4tR6ojQ.d.cts → index-BFsm4pYA.d.cts} +1 -1
- package/dist/{index-DOKc35nY.d.ts → index-Ctg062Fg.d.ts} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/plugins.cjs +5 -5
- package/dist/plugins.d.cts +3 -3
- package/dist/plugins.d.ts +3 -3
- package/dist/plugins.js +5 -5
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/solid-start.d.cts +1 -1
- package/dist/solid-start.d.ts +1 -1
- package/dist/solid.d.cts +1 -1
- package/dist/solid.d.ts +1 -1
- package/dist/svelte-kit.d.cts +1 -1
- package/dist/svelte-kit.d.ts +1 -1
- package/dist/svelte.d.cts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/package.json +1 -1
package/dist/plugins.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { A as AnonymousOptions, O as OrganizationOptions, b as Passkey, P as PasskeyOptions, U as UserWithPhoneNumber, f as UserWithRole, i as admin, h as adminMiddleware, e as anonymous, j as genericOAuth, g as getPasskeyActions, m as magicLink, k as multiSession, o as organization, p as passkey, c as passkeyClient, d as phoneNumber, t as twoFactor, a as twoFactorClient, u as username } from './index-
|
|
1
|
+
export { A as AnonymousOptions, O as OrganizationOptions, b as Passkey, P as PasskeyOptions, U as UserWithPhoneNumber, f as UserWithRole, i as admin, h as adminMiddleware, e as anonymous, j as genericOAuth, g as getPasskeyActions, m as magicLink, k as multiSession, o as organization, p as passkey, c as passkeyClient, d as phoneNumber, t as twoFactor, a as twoFactorClient, u as username } from './index-Ctg062Fg.js';
|
|
2
2
|
export { i as ac } from './index-DfAHOgpj.js';
|
|
3
|
-
import { H as HookEndpointContext, P as PluginSchema } from './auth-
|
|
4
|
-
export { e as AuthEndpoint, f as AuthMiddleware, b as BetterAuthPlugin, d as createAuthEndpoint, c as createAuthMiddleware, o as optionsMiddleware } from './auth-
|
|
3
|
+
import { H as HookEndpointContext, P as PluginSchema } from './auth-D1kVkHCi.js';
|
|
4
|
+
export { e as AuthEndpoint, f as AuthMiddleware, b as BetterAuthPlugin, d as createAuthEndpoint, c as createAuthMiddleware, o as optionsMiddleware } from './auth-D1kVkHCi.js';
|
|
5
5
|
export { H as HIDE_METADATA } from './hide-metadata-DEHJp1rk.js';
|
|
6
6
|
import { U as User } from './schema-Dkt0LqYs.js';
|
|
7
7
|
import * as better_call from 'better-call';
|
package/dist/plugins.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var yr=Object.defineProperty;var br=(e,t)=>{for(var r in t)yr(e,r,{get:t[r],enumerable:!0})};import{APIError as tr}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as Ar,createMiddleware as at,createMiddlewareCreator as kr}from"better-call";var dt=at(async()=>({})),T=kr({use:[dt,at(async()=>({}))]}),u=Ar({use:[dt]});import{APIError as Z}from"better-call";import{generateCodeVerifier as Jr}from"oslo/oauth2";import{z as Q}from"zod";import{generateState as Rr}from"oslo/oauth2";import{z as Le}from"zod";import{sha256 as ct}from"oslo/crypto";function Ze(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let i=0;i<r.length;i++)n|=r[i]^o[i];return n===0}async function ut(e){let t=await ct(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ze(e,t){let r=await ct(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Ze(r,o)}import"better-call";async function De(e){let t=Rr(),r=JSON.stringify({code:t,callbackURL:e}),o=await ut(r);return{raw:r,hash:o}}function we(e){return Le.object({code:Le.string(),callbackURL:Le.string().optional(),currentURL:Le.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as gn}from"oslo";var $=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};import{env as yn,isProduction as bn}from"std-env";async function A(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function
|
|
2
|
-
`)}}),y=Ur();var S=T(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let i=new URL(t).origin;if(!n.includes(i))throw y.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new pt("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw y.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new pt("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as Tr}from"oslo/jwt";import{sha256 as vr}from"oslo/crypto";import{env as Tn}from"std-env";function mt(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Ir}from"oslo/encoding";async function ft(e){let t=await vr(new TextEncoder().encode(e));return Ir.encode(new Uint8Array(t),{includePadding:!1})}function gt(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function B({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await ft(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,g)=>(p[g]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}import{betterFetch as Er}from"@better-fetch/fetch";async function I({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let i=new URLSearchParams;i.set("grant_type","authorization_code"),i.set("code",e),t&&i.set("code_verifier",t),i.set("redirect_uri",r),i.set("client_id",o.clientId),i.set("client_secret",o.clientSecret);let{data:a,error:s}=await Er(n,{method:"POST",body:i,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(s)throw s;return gt(a)}function ye(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var ht=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${i.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>I({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Tr(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Sr}from"@better-fetch/fetch";var wt=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>I({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Sr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Pr}from"@better-fetch/fetch";var yt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await B({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>I({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Pr("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as bt}from"@better-fetch/fetch";var At=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let a=e.scope||o||["user:email"];return B({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>I({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await bt("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await bt("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as Cr}from"oslo/jwt";var kt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw y.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return B({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>I({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=Cr(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as _r}from"@better-fetch/fetch";import{parseJWT as Br}from"oslo/jwt";var Rt=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=e.scope||n.scopes||["openid","profile","email","User.Read"];return B({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return I({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=Br(n.idToken)?.payload,a=e.profilePhotoSize||48;return await _r(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){y.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as zr}from"@better-fetch/fetch";var Ot=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return B({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>I({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await zr("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var de={isAction:!1};function Lr(e){return e.toString(2).padStart(8,"0")}function Dr(e){return[...e].map(t=>Lr(t)).join("")}function Ut(e){return parseInt(Dr(e),2)}function xr(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=Ut(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Ut(o);return n}function V(e,t){let r="";for(let o=0;o<e;o++)r+=t[xr(t.length)];return r}function H(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}import{nanoid as jr}from"nanoid";var _=e=>jr(e);import{parseJWT as Nr}from"oslo/jwt";var vt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return B({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>I({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return y.error("No idToken found in token"),null;let o=Nr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Fr}from"@better-fetch/fetch";var It=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return B({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>I({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Fr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var Mr={apple:ht,discord:wt,facebook:yt,github:At,microsoft:Rt,google:kt,spotify:Ot,twitch:vt,twitter:It},Et=Object.keys(Mr);import{TimeSpan as Vr}from"oslo";import{createJWT as Hr,validateJWT as Qr}from"oslo/jwt";import{z as G}from"zod";import{APIError as be}from"better-call";import{APIError as ve}from"better-call";var J=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Tt}from"zod";var St=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return Ue(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,i=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+i*1e3<=Date.now()){let d=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:J(e.context.sessionConfig.expiresIn,"sec")});if(!d)return Ue(e),e.json(null,{status:401});let c=(d.expiresAt.valueOf()-Date.now())/1e3;return await A(e,d.id,!1,{maxAge:c}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),F=async e=>await St()({...e,_flag:"json",headers:e.headers}),w=T(async e=>{let t=await F(e);if(!t?.session)throw new ve("UNAUTHORIZED");return{session:t}});var qr=u("/user/revoke-session",{method:"POST",body:Tt.object({id:Tt.string()}),use:[w],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new ve("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new ve("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),$r=u("/user/revoke-sessions",{method:"POST",use:[w],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function oe(e,t,r){return await Hr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new Vr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Wr=u("/send-verification-email",{method:"POST",query:G.object({currentURL:G.string().optional()}).optional(),body:G.object({email:G.string().email(),callbackURL:G.string().optional()}),use:[S]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be("BAD_REQUEST",{message:"User not found"});let o=await oe(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),Kr=u("/verify-email",{method:"GET",query:G.object({token:G.string(),callbackURL:G.string().optional()}),use:[S]},async e=>{let{token:t}=e.query,r;try{r=await Qr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be("BAD_REQUEST",{message:"Invalid token"})}let n=G.object({email:G.string().email(),updateTo:G.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await F(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Gr=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:Q.object({currentURL:Q.string().optional()}).optional(),body:Q.object({callbackURL:Q.string().optional(),provider:Q.enum(Et)}),use:[S]},async e=>{let t=e.context.socialProviders.find(d=>d.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new Z("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,i=await De(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=Jr();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let s=await t.createAuthorizationURL({state:i.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:s.toString(),state:i,codeVerifier:a,redirect:!0})}),Zr=u("/sign-in/email",{method:"POST",body:Q.object({email:Q.string(),password:Q.string(),callbackURL:Q.string().optional(),dontRememberMe:Q.boolean().default(!1).optional()}),use:[S]},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.context.logger.error("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!"),new Z("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new Z("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new Z("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw y.error("Email verification is required but no email verification handler is provided"),new Z("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await oe(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new Z("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new Z("UNAUTHORIZED",{message:"Failed to create session"});return await A(e,c.id,e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as Ne}from"zod";import{z as b}from"zod";var Ds=b.object({id:b.string(),providerId:b.string(),accountId:b.string(),userId:b.string(),accessToken:b.string().nullable().optional(),refreshToken:b.string().nullable().optional(),idToken:b.string().nullable().optional(),expiresAt:b.date().nullable().optional(),password:b.string().optional().nullable()}),je=b.object({id:b.string(),email:b.string().transform(e=>e.toLowerCase()),emailVerified:b.boolean().default(!1),name:b.string(),image:b.string().optional(),createdAt:b.date().default(new Date),updatedAt:b.date().default(new Date)}),xs=b.object({id:b.string(),userId:b.string(),expiresAt:b.date(),ipAddress:b.string().optional(),userAgent:b.string().optional()}),js=b.object({id:b.string(),value:b.string(),expiresAt:b.date(),identifier:b.string()});function Yr(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Pt(e,t){let r={...e.user?.additionalFields};return Yr(t||{},{fields:r})}var Xr=u("/callback/:id",{method:"GET",query:Ne.object({state:Ne.string(),code:Ne.string().optional(),error:Ne.string().optional()}),metadata:de},async e=>{if(e.query.error||!e.query.code){let R=we(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${R}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(h=>h.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=we(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,i=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!i)throw y.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ze(e.query.state,i))throw y.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let s=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),d;try{d=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:s,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(h){throw e.context.logger.error(h),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(d).then(h=>h?.user),l=_(),p=je.safeParse({...c,id:l});if(!c||p.success===!1)throw y.error("Unable to get user info",p.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);function g(h){throw e.redirect(`${n||o||`${e.context.baseURL}/error`}?error=${h}`)}let f=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(h=>{throw y.error(`Better auth was unable to query your database.
|
|
3
|
-
Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),k=f?.user.id;if(f){if(!f.accounts.find(R=>R.providerId===t.id)){(!e.context.options.account?.accountLinking?.trustedProviders?.includes(t.id)&&!c.emailVerified||!e.context.options.account?.accountLinking?.enabled)&&g("account_not_linked");try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:f.user.id,...ye(d)})}catch(K){y.error("Unable to link account",K),g("unable_to_link_account")}}}else try{let h=c.emailVerified||!1,R=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:h},{...ye(d),providerId:t.id,accountId:c.id.toString()});if(k=R?.user.id,!h&&R&&e.context.options.emailVerification?.sendOnSignUp){let q=await oe(e.context.secret,c.email),K=`${e.context.baseURL}/verify-email?token=${q}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(R.user,K,q)}}catch(h){y.error("Unable to create user",h),g("unable_to_create_user")}k||g("unable_to_create_user");let
|
|
1
|
+
var yr=Object.defineProperty;var br=(e,t)=>{for(var r in t)yr(e,r,{get:t[r],enumerable:!0})};import{APIError as tr}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as Ar,createMiddleware as at,createMiddlewareCreator as kr}from"better-call";var dt=at(async()=>({})),T=kr({use:[dt,at(async()=>({}))]}),u=Ar({use:[dt]});import{APIError as Z}from"better-call";import{generateCodeVerifier as Jr}from"oslo/oauth2";import{z as Q}from"zod";import{generateState as Rr}from"oslo/oauth2";import{z as Le}from"zod";import{sha256 as ct}from"oslo/crypto";function Ze(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let i=0;i<r.length;i++)n|=r[i]^o[i];return n===0}async function ut(e){let t=await ct(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ze(e,t){let r=await ct(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Ze(r,o)}import"better-call";async function De(e){let t=Rr(),r=JSON.stringify({code:t,callbackURL:e}),o=await ut(r);return{raw:r,hash:o}}function we(e){return Le.object({code:Le.string(),callbackURL:Le.string().optional(),currentURL:Le.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as gn}from"oslo";var $=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};import{env as yn,isProduction as bn}from"std-env";async function A(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function ve(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function lt(e){let t=new Map;return e.split(", ").forEach(o=>{let[n,...i]=o.split("; "),[a,s]=n.split("="),d={value:s};i.forEach(c=>{let[l,p]=c.split("=");d[l.toLowerCase()]=p||!0}),t.set(a,d)}),t}function xe(e){let t=e.split("; "),r=new Map;return t.forEach(o=>{let[n,i]=o.split("=");r.set(n,i)}),r}import{APIError as pt}from"better-call";import{createConsola as Or}from"consola";var ce=Or({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),vr=e=>({log:(...t)=>{!e?.disabled&&ce.log("",...t)},error:(...t)=>{!e?.disabled&&ce.error("",...t)},warn:(...t)=>{!e?.disabled&&ce.warn("",...t)},info:(...t)=>{!e?.disabled&&ce.info("",...t)},debug:(...t)=>{!e?.disabled&&ce.debug("",...t)},box:(...t)=>{!e?.disabled&&ce.box("",...t)},success:(...t)=>{!e?.disabled&&ce.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
|
|
2
|
+
`)}}),y=vr();var S=T(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let i=new URL(t).origin;if(!n.includes(i))throw y.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new pt("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw y.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new pt("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as Tr}from"oslo/jwt";import{sha256 as Ir}from"oslo/crypto";import{env as Tn}from"std-env";function mt(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Ur}from"oslo/encoding";async function ft(e){let t=await Ir(new TextEncoder().encode(e));return Ur.encode(new Uint8Array(t),{includePadding:!1})}function gt(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function B({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await ft(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,g)=>(p[g]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}import{betterFetch as Er}from"@better-fetch/fetch";async function U({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let i=new URLSearchParams;i.set("grant_type","authorization_code"),i.set("code",e),t&&i.set("code_verifier",t),i.set("redirect_uri",r),i.set("client_id",o.clientId),i.set("client_secret",o.clientSecret);let{data:a,error:s}=await Er(n,{method:"POST",body:i,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(s)throw s;return gt(a)}function ye(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var ht=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${i.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>U({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Tr(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Sr}from"@better-fetch/fetch";var wt=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Sr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Pr}from"@better-fetch/fetch";var yt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await B({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Pr("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as bt}from"@better-fetch/fetch";var At=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let a=e.scope||o||["user:email"];return B({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>U({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await bt("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await bt("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as Cr}from"oslo/jwt";var kt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw y.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return B({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=Cr(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as _r}from"@better-fetch/fetch";import{parseJWT as Br}from"oslo/jwt";var Rt=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=e.scope||n.scopes||["openid","profile","email","User.Read"];return B({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return U({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=Br(n.idToken)?.payload,a=e.profilePhotoSize||48;return await _r(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){y.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as zr}from"@better-fetch/fetch";var Ot=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return B({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await zr("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var de={isAction:!1};function Lr(e){return e.toString(2).padStart(8,"0")}function Dr(e){return[...e].map(t=>Lr(t)).join("")}function vt(e){return parseInt(Dr(e),2)}function xr(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=vt(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=vt(o);return n}function V(e,t){let r="";for(let o=0;o<e;o++)r+=t[xr(t.length)];return r}function H(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}import{nanoid as jr}from"nanoid";var _=e=>jr(e);import{parseJWT as Nr}from"oslo/jwt";var It=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return B({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return y.error("No idToken found in token"),null;let o=Nr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Fr}from"@better-fetch/fetch";var Ut=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return B({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Fr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var Mr={apple:ht,discord:wt,facebook:yt,github:At,microsoft:Rt,google:kt,spotify:Ot,twitch:It,twitter:Ut},Et=Object.keys(Mr);import{TimeSpan as Vr}from"oslo";import{createJWT as Hr,validateJWT as Qr}from"oslo/jwt";import{z as G}from"zod";import{APIError as be}from"better-call";import{APIError as Ie}from"better-call";var J=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Tt}from"zod";var St=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return ve(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,i=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+i*1e3<=Date.now()){let d=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:J(e.context.sessionConfig.expiresIn,"sec")});if(!d)return ve(e),e.json(null,{status:401});let c=(d.expiresAt.valueOf()-Date.now())/1e3;return await A(e,d.id,!1,{maxAge:c}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),F=async e=>await St()({...e,_flag:"json",headers:e.headers}),w=T(async e=>{let t=await F(e);if(!t?.session)throw new Ie("UNAUTHORIZED");return{session:t}});var qr=u("/user/revoke-session",{method:"POST",body:Tt.object({id:Tt.string()}),use:[w],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Ie("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Ie("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),$r=u("/user/revoke-sessions",{method:"POST",use:[w],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function oe(e,t,r){return await Hr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new Vr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Wr=u("/send-verification-email",{method:"POST",query:G.object({currentURL:G.string().optional()}).optional(),body:G.object({email:G.string().email(),callbackURL:G.string().optional()}),use:[S]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be("BAD_REQUEST",{message:"User not found"});let o=await oe(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),Kr=u("/verify-email",{method:"GET",query:G.object({token:G.string(),callbackURL:G.string().optional()}),use:[S]},async e=>{let{token:t}=e.query,r;try{r=await Qr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be("BAD_REQUEST",{message:"Invalid token"})}let n=G.object({email:G.string().email(),updateTo:G.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await F(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Gr=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:Q.object({currentURL:Q.string().optional()}).optional(),body:Q.object({callbackURL:Q.string().optional(),provider:Q.enum(Et)}),use:[S]},async e=>{let t=e.context.socialProviders.find(d=>d.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new Z("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,i=await De(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=Jr();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let s=await t.createAuthorizationURL({state:i.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:s.toString(),state:i,codeVerifier:a,redirect:!0})}),Zr=u("/sign-in/email",{method:"POST",body:Q.object({email:Q.string(),password:Q.string(),callbackURL:Q.string().optional(),dontRememberMe:Q.boolean().default(!1).optional()}),use:[S]},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.context.logger.error("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!"),new Z("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new Z("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new Z("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw y.error("Email verification is required but no email verification handler is provided"),new Z("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await oe(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new Z("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new Z("UNAUTHORIZED",{message:"Failed to create session"});return await A(e,c.id,e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as Ne}from"zod";import{z as b}from"zod";var Ds=b.object({id:b.string(),providerId:b.string(),accountId:b.string(),userId:b.string(),accessToken:b.string().nullable().optional(),refreshToken:b.string().nullable().optional(),idToken:b.string().nullable().optional(),expiresAt:b.date().nullable().optional(),password:b.string().optional().nullable()}),je=b.object({id:b.string(),email:b.string().transform(e=>e.toLowerCase()),emailVerified:b.boolean().default(!1),name:b.string(),image:b.string().optional(),createdAt:b.date().default(new Date),updatedAt:b.date().default(new Date)}),xs=b.object({id:b.string(),userId:b.string(),expiresAt:b.date(),ipAddress:b.string().optional(),userAgent:b.string().optional()}),js=b.object({id:b.string(),value:b.string(),expiresAt:b.date(),identifier:b.string()});function Yr(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Pt(e,t){let r={...e.user?.additionalFields};return Yr(t||{},{fields:r})}var Xr=u("/callback/:id",{method:"GET",query:Ne.object({state:Ne.string(),code:Ne.string().optional(),error:Ne.string().optional()}),metadata:de},async e=>{if(e.query.error||!e.query.code){let R=we(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${R}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(h=>h.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=we(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,i=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!i)throw y.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ze(e.query.state,i))throw y.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let s=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),d;try{d=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:s,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(h){throw e.context.logger.error(h),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(d).then(h=>h?.user),l=_(),p=je.safeParse({...c,id:l});if(!c||p.success===!1)throw y.error("Unable to get user info",p.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);function g(h){throw e.redirect(`${n||o||`${e.context.baseURL}/error`}?error=${h}`)}let f=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(h=>{throw y.error(`Better auth was unable to query your database.
|
|
3
|
+
Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),k=f?.user.id;if(f){if(!f.accounts.find(R=>R.providerId===t.id)){(!e.context.options.account?.accountLinking?.trustedProviders?.includes(t.id)&&!c.emailVerified||!e.context.options.account?.accountLinking?.enabled)&&g("account_not_linked");try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:f.user.id,...ye(d)})}catch(K){y.error("Unable to link account",K),g("unable_to_link_account")}}}else try{let h=c.emailVerified||!1,R=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:h},{...ye(d),providerId:t.id,accountId:c.id.toString()});if(k=R?.user.id,!h&&R&&e.context.options.emailVerification?.sendOnSignUp){let q=await oe(e.context.secret,c.email),K=`${e.context.baseURL}/verify-email?token=${q}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(R.user,K,q)}}catch(h){y.error("Unable to create user",h),g("unable_to_create_user")}k||g("unable_to_create_user");let I=await e.context.internalAdapter.createSession(k,e.request);throw I||g("unable_to_create_session"),await A(e,I.id),e.redirect(o)});import"zod";import{APIError as eo}from"better-call";var to=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new eo("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),ve(e),e.json({success:!0})});import{z as X}from"zod";import{APIError as Fe}from"better-call";var ro=u("/forget-password",{method:"POST",body:X.object({email:X.string().email(),redirectTo:X.string()}),use:[S]},async e=>{if(!e.context.options.emailAndPassword?.sendResetPassword)throw e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function in your auth config!"),new Fe("BAD_REQUEST",{message:"Reset password isn't enabled"});let{email:t,redirectTo:r}=e.body,o=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!o)return e.context.logger.error("Reset Password: User not found",{email:t}),e.json({status:!1},{body:{status:!0}});let n=60*60*1,i=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),a=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${a}`,expiresAt:i});let s=`${e.context.baseURL}/reset-password/${a}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(o.user,s),e.json({status:!0})}),oo=u("/reset-password/:token",{method:"GET",query:X.object({callbackURL:X.string()}),use:[S]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),no=u("/reset-password",{query:X.optional(X.object({token:X.string()})),method:"POST",body:X.object({newPassword:X.string()})},async e=>{let t=e.query?.token;if(!t)throw new Fe("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new Fe("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let i=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(i)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:i,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(i,a))throw new Fe("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{z}from"zod";import{APIError as N}from"better-call";var io=u("/user/update",{method:"POST",body:z.object({name:z.string().optional(),image:z.string().optional()}),use:[w,S]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),so=u("/user/change-password",{method:"POST",body:z.object({newPassword:z.string(),currentPassword:z.string(),revokeOtherSessions:z.boolean().optional()}),use:[w]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,i=e.context.password.config.minPasswordLength;if(t.length<i)throw e.context.logger.error("Password is too short"),new N("BAD_REQUEST",{message:"Password is too short"});let a=e.context.password.config.maxPasswordLength;if(t.length>a)throw e.context.logger.error("Password is too long"),new N("BAD_REQUEST",{message:"Password too long"});let d=(await e.context.internalAdapter.findAccounts(n.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!d||!d.password)throw new N("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new N("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:c}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new N("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await A(e,p.id)}return e.json(n.user)}),ao=u("/user/set-password",{method:"POST",body:z.object({newPassword:z.string()}),use:[w]},async e=>{let{newPassword:t}=e.body,r=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)throw e.context.logger.error("Password is too short"),new N("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new N("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(r.user.id)).find(d=>d.providerId==="credential"&&d.password),s=await e.context.password.hash(t);if(!a)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:s}),e.json(r.user);throw new N("BAD_REQUEST",{message:"user already has a password"})}),co=u("/user/delete",{method:"POST",body:z.object({password:z.string()}),use:[w]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new N("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new N("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)}),uo=u("/user/change-email",{method:"POST",query:z.object({currentURL:z.string().optional()}).optional(),body:z.object({newEmail:z.string().email(),callbackURL:z.string().optional()}),use:[w,S]},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new N("BAD_REQUEST",{message:"Change email is disabled"});if(e.body.newEmail===e.context.session.user.email)throw e.context.logger.error("Email is the same"),new N("BAD_REQUEST",{message:"Email is the same"});if(await e.context.internalAdapter.findUserByEmail(e.body.newEmail))throw e.context.logger.error("Email already exists"),new N("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let n=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:n,status:!0})}if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new N("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await oe(e.context.secret,e.context.session.user.email,e.body.newEmail),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(e.context.session.user,o,r),e.json({user:null,status:!0})});import{xchacha20poly1305 as Ct}from"@noble/ciphers/chacha";import{bytesToHex as lo,hexToBytes as po,utf8ToBytes as mo}from"@noble/ciphers/utils";import{managedNonce as _t}from"@noble/ciphers/webcrypto";import{sha256 as Bt}from"oslo/crypto";import{decodeHex as Oa,encodeHex as va}from"oslo/encoding";import{scryptAsync as Ea}from"@noble/hashes/scrypt";async function Y(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),i=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(i)))}var Me=async({key:e,data:t})=>{let r=await Bt(new TextEncoder().encode(e)),o=mo(t),n=_t(Ct)(new Uint8Array(r));return lo(n.encrypt(o))},qe=async({key:e,data:t})=>{let r=await Bt(new TextEncoder().encode(e)),o=po(t),n=_t(Ct)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var fo=u("/csrf",{method:"GET",metadata:de},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t){let[i,a]=t.split("!")||[null,null];return e.json({csrfToken:i})}let r=V(32,H("a-z","0-9","A-Z")),o=await Y(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),e.json({csrfToken:r})});var go=(e="Unknown")=>`<!DOCTYPE html>
|
|
4
4
|
<html lang="en">
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="UTF-8">
|
|
@@ -80,5 +80,5 @@ Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)
|
|
|
80
80
|
<div class="error-code">Error Code: <span id="errorCode">${e}</span></div>
|
|
81
81
|
</div>
|
|
82
82
|
</body>
|
|
83
|
-
</html>`,ho=u("/error",{method:"GET",metadata:de},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(go(t),{headers:{"Content-Type":"text/html"}})});var wo=u("/ok",{method:"GET",metadata:de},async e=>e.json({ok:!0}));import{z as Ae}from"zod";import{APIError as ue}from"better-call";var Ye=()=>u("/sign-up/email",{method:"POST",query:Ae.object({currentURL:Ae.string().optional()}).optional(),body:Ae.record(Ae.string(),Ae.any()),use:[S]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!Ae.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let c=e.context.password.config.minPasswordLength;if(n.length<c)throw e.context.logger.error("Password is too short"),new ue("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new ue("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new ue("UNPROCESSABLE_ENTITY",{message:"Failed to create user"});let g=Pt(e.context.options,s),f=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1});if(!f)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let k=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:f.id,providerId:"credential",accountId:f.id,password:k,expiresAt:J(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let h=await oe(e.context.secret,f.email),R=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(f,R,h)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({user:f,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:null}});let v=await e.context.internalAdapter.createSession(f.id,e.request);if(!v)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await A(e,v.id),e.json({user:f,session:v},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:v}})});var zt=(e,t)=>{let r={};for(let[o,n]of Object.entries(e))r[o]=i=>n({...i,context:{...t,...i.context}}),r[o].path=n.path,r[o].method=n.method,r[o].options=n.options,r[o].headers=n.headers;return r};var Ft={};br(Ft,{AccessControl:()=>Ie,ParsingError:()=>le,Role:()=>ke,adminAc:()=>xt,createAccessControl:()=>Lt,defaultAc:()=>$e,defaultRoles:()=>Xe,defaultStatements:()=>Dt,memberAc:()=>Nt,ownerAc:()=>jt,permissionFromString:()=>yo});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},Ie=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new ke(t)}},ke=class e{statements;constructor(t){this.statements=t}authorize(t,r){for(let[o,n]of Object.entries(t)){let i=this.statements[o];if(!i)return{success:!1,error:`You are not allowed to access resource: ${o}`};let a=r==="OR"?n.some(s=>i.includes(s)):n.every(s=>i.includes(s));return a?{success:a}:{success:!1,error:`unauthorized to access resource "${o}"`}}return{success:!1,error:"Not authorized"}}static fromString(t){let r=JSON.parse(t);if(typeof r!="object")throw new le("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new le("invalid resource identifier",o);if(!Array.isArray(n))throw new le("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new le("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var Lt=e=>new Ie(e),Dt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},$e=Lt(Dt),xt=$e.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),jt=$e.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),Nt=$e.newRole({organization:[],member:[],invitation:[]}),Xe={admin:xt,owner:jt,member:Nt};var yo=e=>ke.fromString(e??"");var P=(e,t)=>({findOrganizationBySlug:async r=>await e.findOne({model:"organization",where:[{field:"slug",value:r}]}),createOrganization:async r=>{let o=await e.create({model:"organization",data:{...r.organization,metadata:r.organization.metadata?JSON.stringify(r.organization.metadata):void 0}}),n=await e.create({model:"member",data:{id:_(),organizationId:o.id,userId:r.user.id,createdAt:new Date,email:r.user.email,role:t?.creatorRole||"owner"}});return{...o,metadata:o.metadata?JSON.parse(o.metadata):void 0,members:[{...n,user:{id:r.user.id,name:r.user.name,email:r.user.email,image:r.user.image}}]}},findMemberByEmail:async r=>{let o=await e.findOne({model:"member",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberByOrgId:async r=>{let[o,n]=await Promise.all([await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{field:"organizationId",value:r.organizationId}]}),await e.findOne({model:"user",where:[{field:"id",value:r.userId}]})]);return!n||!o?null:{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}},findMemberById:async r=>{let o=await e.findOne({model:"member",where:[{field:"id",value:r}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},createMember:async r=>await e.create({model:"member",data:r}),updateMember:async(r,o)=>await e.update({model:"member",where:[{field:"id",value:r}],update:{role:o}}),deleteMember:async r=>await e.delete({model:"member",where:[{field:"id",value:r}]}),updateOrganization:async(r,o)=>await e.update({model:"organization",where:[{field:"id",value:r}],update:o}),deleteOrganization:async r=>(await e.delete({model:"member",where:[{field:"organizationId",value:r}]}),await e.delete({model:"invitation",where:[{field:"organizationId",value:r}]}),await e.delete({model:"organization",where:[{field:"id",value:r}]}),r),setActiveOrganization:async(r,o)=>await e.update({model:"session",where:[{field:"id",value:r}],update:{activeOrganizationId:o}}),findOrganizationById:async r=>await e.findOne({model:"organization",where:[{field:"id",value:r}]}),findFullOrganization:async(r,o)=>{let[n,i,a]=await Promise.all([e.findOne({model:"organization",where:[{field:"id",value:r}]}),e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),e.findMany({model:"member",where:[{field:"organizationId",value:r}]})]);if(!n)return null;let s=a.map(p=>p.userId),d=await e.findMany({model:"user",where:[{field:"id",value:s,operator:"in"}]}),c=new Map(d.map(p=>[p.id,p])),l=a.map(p=>{let g=c.get(p.userId);if(!g)throw new $("Unexpected error: User not found for member");return{...p,user:{id:g.id,name:g.name,email:g.email,image:g.image}}});return{...n,invitations:i,members:l}},listOrganizations:async r=>{let o=await e.findMany({model:"member",where:[{field:"userId",value:r}]});if(!o||o.length===0)return[];let n=o.map(a=>a.organizationId);return await e.findMany({model:"organization",where:[{field:"id",value:n,operator:"in"}]})},createInvitation:async({invitation:r,user:o})=>{let i=J(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:_(),email:r.email,role:r.role,organizationId:r.organizationId,status:"pending",expiresAt:i,inviterId:o.id}})},findInvitationById:async r=>await e.findOne({model:"invitation",where:[{field:"id",value:r}]}),findPendingInvitation:async r=>(await e.findMany({model:"invitation",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId},{field:"status",value:"pending"}]})).filter(n=>new Date(n.expiresAt)>new Date),updateInvitation:async r=>await e.update({model:"invitation",where:[{field:"id",value:r.invitationId}],update:{status:r.status}})});import"better-call";import{APIError as Gd,createRouter as Zd,statusCode as Yd}from"better-call";import{APIError as et}from"better-call";import{z as Mt}from"zod";var bo=T({body:Mt.object({csrfToken:Mt.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(e.context.trustedOrigins.includes(t.origin))return;let r=e.body?.csrfToken;if(!r)throw new et("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await Y(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{isTest as Nd}from"std-env";import{APIError as M}from"better-call";var L=T(async e=>({})),x=T({use:[w]},async e=>({session:e.context.session}));import{z as W}from"zod";import{z as U}from"zod";var Ve=U.enum(["admin","member","owner"]),Ao=U.enum(["pending","accepted","rejected","canceled"]).default("pending"),kc=U.object({id:U.string(),name:U.string(),slug:U.string(),logo:U.string().optional(),metadata:U.record(U.string()).or(U.string().transform(e=>JSON.parse(e))).optional(),createdAt:U.date()}),Rc=U.object({id:U.string(),email:U.string(),organizationId:U.string(),userId:U.string(),role:Ve,createdAt:U.date()}),Oc=U.object({id:U.string(),organizationId:U.string(),email:U.string(),role:Ve,status:Ao,inviterId:U.string(),expiresAt:U.date()});import{APIError as E}from"better-call";var qt=u("/organization/invite-member",{method:"POST",use:[L,x],body:W.object({email:W.string(),role:Ve,organizationId:W.string().optional(),resend:W.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw y.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new E("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new E("BAD_REQUEST",{message:"Organization not found"});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new E("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new E("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new E("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new E("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),$t=u("/organization/accept-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:_(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),Vt=u("/organization/reject-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),Ht=u("/organization/cancel-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new E("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),Qt=u("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:W.object({id:W.string()})},async e=>{let t=await F(e);if(!t)throw new E("UNAUTHORIZED",{message:"Not authenticated"});let r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new E("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new E("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as pe}from"zod";import{APIError as Ee}from"better-call";var Wt=u("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ee("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ee("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ee("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ee("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Ee("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Kt=u("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as C}from"zod";import{APIError as me}from"better-call";var Jt=u("/organization/create",{method:"POST",body:C.object({name:C.string(),slug:C.string(),userId:C.string().optional(),logo:C.string().optional(),metadata:C.record(C.string()).optional()}),use:[L,x]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new me("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=P(e.context.adapter,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new me("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new me("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:_(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),Gt=u("/organization/update",{method:"POST",body:C.object({data:C.object({name:C.string().optional(),slug:C.string().optional()}).partial(),orgId:C.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new me("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["update"]}).error)return e.json(null,{body:{message:"You are not allowed to update this organization"},status:403});let s=await o.updateOrganization(r,e.body.data);return e.json(s)}),Zt=u("/organization/delete",{method:"POST",body:C.object({orgId:C.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["delete"]}).error)throw new me("FORBIDDEN",{message:"You are not allowed to delete this organization"});return r===t.session.activeOrganizationId&&await o.setActiveOrganization(t.session.id,null),await o.deleteOrganization(r),e.json(r)}),Yt=u("/organization/get-full",{method:"GET",query:C.object({orgId:C.string().optional()}),requireHeaders:!0,use:[L,x]},async e=>{let t=e.context.session,r=e.query.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400});let n=await P(e.context.adapter,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new me("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Xt=u("/organization/activate",{method:"POST",body:C.object({orgId:C.string().nullable().optional()}),use:[x,L]},async e=>{let t=P(e.context.adapter,e.context.orgOptions),r=e.context.session,o=e.body.orgId;if(o===null)return r.session.activeOrganizationId&&await t.setActiveOrganization(r.session.id,null),e.json(null);if(!o){let a=r.session.activeOrganizationId;if(!a)return e.json(null);o=a}if(!await t.findMemberByOrgId({userId:r.user.id,organizationId:o}))throw await t.setActiveOrganization(r.session.id,null),new me("FORBIDDEN",{message:"You are not a member of this organization"});await t.setActiveOrganization(r.session.id,o);let i=await t.findFullOrganization(o,e.context.db||void 0);return e.json(i)}),er=u("/organization/list",{method:"GET",use:[L,x]},async e=>{let r=await P(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var iu=e=>{let t={createOrganization:Jt,updateOrganization:Gt,deleteOrganization:Zt,setActiveOrganization:Xt,getFullOrganization:Yt,listOrganization:er,createInvitation:qt,cancelInvitation:Ht,acceptInvitation:$t,getInvitation:Qt,rejectInvitation:Vt,removeMember:Wt,updateMemberRole:Kt},r={...Xe,...e?.roles};return{id:"organization",endpoints:{...zt(t,{orgOptions:e||{},roles:r,getSession:async n=>await F(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new tr("BAD_REQUEST",{message:"No active organization"});let a=await P(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new tr("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import{z as Ke}from"zod";import{z as Pe}from"zod";import{APIError as fe}from"better-call";var He="two-factor";var Qe="trust-device";import{z as rr}from"zod";var ge=T({body:rr.object({trustDevice:rr.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(He),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let i=await e.context.adapter.findMany({model:"session",where:[{field:"userId",value:o}]});if(!i.length)throw new fe("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new fe("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await Y(e.context.secret,s.id),c=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!c)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await A(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await Y(e.context.secret,`${c.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:c})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:c}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Se}from"better-call";function ko(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>V(e?.length??10,H("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function tt(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():ko(),n=await Me({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Ro(e,t){let r=await or(e.backupCodes,t);return r?r.includes(e.code):!1}async function or(e,t){let r=Buffer.from(await qe({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Pe.array(Pe.string()).safeParse(o);return n.success?n.data:null}var nr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:Pe.object({code:Pe.string(),disableSession:Pe.boolean().optional()}),use:[ge]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Ro({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Se("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await A(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",use:[w]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Se("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await tt(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",use:[w]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=or(n.backupCodes,r.context.secret);if(!i)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as We}from"better-call";import{TOTPController as Oo}from"oslo/otp";import{z as ir}from"zod";import{TimeSpan as Uo}from"oslo";var sr=(e,t)=>{let r={...e,period:new Uo(e?.period||3,"m")},o=new Oo({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[ge]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new We("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:ir.object({code:ir.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new We("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as Re}from"better-call";import{TimeSpan as vo}from"oslo";import{TOTPController as ar,createTOTPKeyURI as Io}from"oslo/otp";import{z as dr}from"zod";var cr=(e,t)=>{let r={...e,digits:6,period:new vo(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new ar(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"GET",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Io(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:dr.object({code:dr.string()}),use:[ge]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!d.enabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});let c=new ar(r),l=await qe({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await c.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function rt(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as ur}from"better-call";var $u=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t==="/two-factor/enable"||t==="/two-factor/send-otp"||t==="/two-factor/disable",signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var rl=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=cr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=nr({...e?.backupCodeOptions},t.twoFactorTable),n=sr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new ur("BAD_REQUEST",{message:"Invalid password"});let c=V(16,H("a-z","0-9","-")),l=await Me({key:i.context.secret,data:c}),p=await tt(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new ur("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:T(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[f,k]=c.split("!"),v=await Y(i.context.secret,`${s.user.id}!${k}`);if(f===v){let h=await Y(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await Y(i.context.secret,s.session.id),p=i.context.createAuthCookie(He,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.options),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as zo,generateRegistrationOptions as Lo,verifyAuthenticationResponse as Do,verifyRegistrationResponse as xo}from"@simplewebauthn/server";import{APIError as ee}from"better-call";import{z as ne}from"zod";import{env as jo}from"std-env";import{WebAuthnError as So,startAuthentication as Po,startRegistration as Co}from"@simplewebauthn/browser";import{createFetch as fl}from"@better-fetch/fetch";import"nanostores";import{betterFetch as sl}from"@better-fetch/fetch";import{atom as vl}from"nanostores";import"@better-fetch/fetch";import{atom as Eo,onMount as To}from"nanostores";var ot=(e,t,r,o)=>{let n=Eo({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():To(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as _o}from"nanostores";var Bo=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await Po(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch(s){console.log(s)}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Co(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof So?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),Vl=()=>{let e=_o();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Bo(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:ot(e,"/passkey/list-user-passkeys",t,{method:"GET",credentials:"include"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var op=e=>{let t=jo.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[w],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(V(32,H("a-z","0-9")))),p;p=await Lo({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:ne.object({email:ne.string().optional()}).optional()},async s=>{let d=await F(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await zo({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:ne.object({response:ne.any(),name:ne.string().optional()}),use:[w]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:g,userData:f}=JSON.parse(p.value);if(f.id!==s.context.session.user.id)throw new ee("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await xo({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:v,registrationInfo:h}=k;if(!v||!h)return s.json(null,{status:400});let{credentialID:R,credentialPublicKey:q,counter:K,credentialDeviceType:O,credentialBackedUp:j}=h,ae=Buffer.from(q).toString("base64"),D=_(),Be={name:s.body.name,userId:f.id,webauthnUserID:D,id:R,publicKey:ae,counter:K,deviceType:O,transports:c.response.transports.join(","),backedUp:j,createdAt:new Date},wr=await s.context.adapter.create({model:"passkey",data:Be});return s.json(wr,{status:200})}catch(k){throw console.log(k),new ee("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:ne.object({response:ne.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new ee("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:g}=JSON.parse(p.value),f=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!f)throw new ee("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await Do({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:f.id,credentialPublicKey:new Uint8Array(Buffer.from(f.publicKey,"base64")),counter:f.counter,transports:f.transports?.split(",")}}),{verified:v}=k;if(!v)throw new ee("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:f.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(f.userId,s.request);if(!h)throw new ee("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await A(s,h.id),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new ee("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[w]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:ne.object({id:ne.string()}),use:[w]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as te}from"zod";import{APIError as Je}from"better-call";var lr=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:te.object({username:te.string(),password:te.string(),dontRememberMe:te.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:"user",where:[{field:"username",value:e.body.username}]});if(!t)throw await e.context.password.hash(e.body.password),e.context.logger.error("User not found",{username:lr}),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:"account",where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.type.fieldName||"providerId",value:"credential"}]});if(!r)throw new Je("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:lr}),new Je("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:u("/sign-up/username",{method:"POST",body:te.object({username:te.string().min(3).max(20),name:te.string(),email:te.string().email(),password:te.string(),image:te.string().optional()})},async e=>{let t=await Ye()({...e,_flag:"json"}),r=await e.context.internalAdapter.updateUserByEmail(t.user?.email,{username:e.body.username});return e.json({user:r,session:t.session})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as No}from"better-call";var pp=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await No("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as Oe}from"zod";import{APIError as Fo}from"better-call";var Ap=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Oe.object({email:Oe.string().email(),callbackURL:Oe.string().optional()}),use:[S]},async t=>{let{email:r}=t.body,o=V(32,H("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new Fo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:Oe.object({token:Oe.string(),callbackURL:Oe.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await A(t,c.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as he}from"zod";import{APIError as ie}from"better-call";function Mo(e){return V(e,H("0-9"))}var Pp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw y.warn("sendOTP not implemented"),new ie("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Mo(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:J(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:he.object({phoneNumber:he.string(),code:he.string(),disableSession:he.boolean().optional(),updatePhoneNumber:he.boolean().optional()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new ie("BAD_REQUEST",{message:"OTP expired"})):new ie("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ie("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await F(r);if(!i)throw new ie("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ie("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(r,i.id),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as nt}from"zod";var xp=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=mt(t.context.baseURL)}=e||{},o=_(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await A(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:u("/user/link-anonymous",{method:"POST",body:nt.object({email:nt.string().email().optional(),password:nt.string().min(6)}),use:[w]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await A(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});import{z as m}from"zod";var re=T(async e=>{let t=await F(e);if(!t?.session)throw new M("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new M("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),$p=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/user/list-sessions"},handler:T(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:m.object({userId:m.string(),role:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:m.object({email:m.string(),password:m.string(),name:m.string(),role:m.string(),data:m.optional(m.record(m.any()))}),use:[re]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new M("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[re],query:m.object({search:m.object({field:m.enum(["email","name"]),operator:m.enum(["contains","starts_with","ends_with"]).default("contains"),value:m.string()}).optional(),limit:m.string().or(m.number()).optional(),offset:m.string().or(m.number()).optional(),sortBy:m.string().optional(),sortDirection:m.enum(["asc","desc"]).optional(),filter:m.array(m.object({field:m.string(),value:m.string().or(m.number()).or(m.boolean()),operator:m.enum(["eq","ne","lt","lte","gt","gte"]),connector:m.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[re],body:m.object({userId:m.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:m.object({userId:m.string(),banReason:m.string().optional(),banExpiresIn:m.number().optional()}),use:[re]},async t=>{if(t.body.userId===t.context.session.user.id)throw new M("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new M("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?J(e.impersonationSessionDuration,"sec"):J(60*60,"sec")});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:m.object({sessionId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});import{z as se}from"zod";import{APIError as Ce}from"better-call";import{betterFetch as it}from"@better-fetch/fetch";import{generateCodeVerifier as qo}from"oslo/oauth2";import{parseJWT as $o}from"oslo/jwt";async function Vo(e,t,r){if(t==="oidc"&&e.idToken){let n=$o(e.idToken);if(n?.payload)return n.payload}return r?(await it(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var sm=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:se.object({currentURL:se.string().optional()}).optional(),body:se.object({providerId:se.string(),callbackURL:se.string().optional()}),use:[S]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:g,prompt:f,accessType:k}=o,v=i,h=a;if(n){let D=await it(n,{onError(Be){y.error(Be.error,{discoveryUrl:n})}});D.data&&(v=D.data.authorization_endpoint,h=D.data.token_endpoint)}if(!v||!h)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let R=t.query?.currentURL?new URL(t.query?.currentURL):null,q=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${R?.origin}${t.body.callbackURL||""}`,K=await De(q||R?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,K.hash,t.context.secret,O.state.options);let j=qo();await t.setSignedCookie(O.pkCodeVerifier.name,j,t.context.secret,O.pkCodeVerifier.options);let ae=await B({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:v,state:K.raw,codeVerifier:j,scopes:c||[],disablePkce:!g,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ae.searchParams.set("response_type",p),f&&ae.searchParams.set("prompt",f),k&&ae.searchParams.set("access_type",k),{url:ae.toString(),state:K,codeVerifier:j,redirect:!0}}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:se.object({code:se.string().optional(),error:se.string().optional(),state:se.string()})},async t=>{if(t.query.error||!t.query.code){let j=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${j}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o=await t.getSignedCookie(t.context.authCookies.pkCodeVerifier.name,t.context.secret),n,i=we(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,c=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw y.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await ze(a,p))throw y.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let f=r.tokenUrl,k=r.userInfoUrl;if(r.discoveryUrl){let O=await it(r.discoveryUrl,{method:"GET"});O.data&&(f=O.data.token_endpoint,k=O.data.userinfo_endpoint)}try{if(!f)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await I({code:c,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:f})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let v=r.getUserInfo?await r.getUserInfo(n):await Vo(n,r.type||"oauth2",k),h=_(),R=v?je.safeParse({...v,id:h}):null;if(!R?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let q=await t.context.internalAdapter.findUserByEmail(R.data.email).catch(O=>{throw y.error(`Better auth was unable to query your database.
|
|
84
|
-
Error: `,O),t.redirect(`${l}?error=internal_server_error`)}),K=q?.user.id||h;if(q){let O=q.accounts.find(D=>D.providerId===r.providerId),j=t.context.options.account?.accountLinking?.trustedProviders,ae=j?j.includes(r.providerId):!0;if(!O&&(!R?.data.emailVerified||!ae)){let D;try{D=new URL(l),D.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(D.toString())}if(!O)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:R.data.id,id:`${r.providerId}:${R.data.id}`,userId:q.user.id,...ye(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(R.data,{...ye(n),id:`${r.providerId}:${R.data.id}`,providerId:r.providerId,accountId:R.data.id})}catch{let j=new URL(l);throw j.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",j.toString()),t.redirect(j.toString())}try{let O=await t.context.internalAdapter.createSession(K||h,t.request);if(!O)throw t.redirect(`${l}?error=unable_to_create_session`);await A(t,O.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var pr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},cm=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var st=e=>({getAllKeys:async()=>await e.findMany({model:"jwks"}),getLatestKey:async()=>(await e.findMany({model:"jwks",sortBy:{field:"createdAt",direction:"desc"},limit:1}))[0],createJwk:async t=>await e.create({model:"jwks",data:{...t,createdAt:new Date}})});import{exportJWK as hr,generateKeyPair as Jo,importJWK as Go,SignJWT as Zo}from"jose";import{createCipheriv as Ho,createDecipheriv as Qo,createHash as Wo,randomBytes as Ko}from"crypto";function mr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=Wo("sha256").update(e).digest(),t}function fr(e,t){let r=mr(t),o=Ko(12),n=Ho("aes-256-gcm",r,o),i=n.update(e,"utf8","base64");i+=n.final("base64");let a=n.getAuthTag();return{encryptedPrivateKey:i,iv:o.toString("base64"),authTag:a.toString("base64")}}function gr(e,t){let r=mr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=Qo("aes-256-gcm",r,a);d.setAuthTag(s);let c=d.update(o,"base64","utf8");return c+=d.final("utf8"),c}var bm=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await st(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[w]},async t=>{let r=st(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await Jo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await hr(c),g=await hr(l),f=JSON.stringify(g),k={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(fr(f,t.context.options.secret)):f,createdAt:new Date};o=await r.createJwk(k)}let i=n?gr(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await Go(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new Zo({...s,...t.context.session.session.impersonatedBy?{impersonatedBy:t.context.session.session.impersonatedBy}:{}}).setProtectedHeader({alg:e?.jwks?.keyPairConfig?.alg??"EdDSA"}).setIssuedAt().setIssuer(e?.jwt?.issuer??t.context.options.baseURL).setAudience(e?.jwt?.audience??t.context.options.baseURL).setExpirationTime(e?.jwt?.expirationTime??"15m").setSubject(t.context.session.user.id).sign(a);return t.json({token:d})})},schema:pr});import{z as Ge}from"zod";var
|
|
83
|
+
</html>`,ho=u("/error",{method:"GET",metadata:de},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(go(t),{headers:{"Content-Type":"text/html"}})});var wo=u("/ok",{method:"GET",metadata:de},async e=>e.json({ok:!0}));import{z as Ae}from"zod";import{APIError as ue}from"better-call";var Ye=()=>u("/sign-up/email",{method:"POST",query:Ae.object({currentURL:Ae.string().optional()}).optional(),body:Ae.record(Ae.string(),Ae.any()),use:[S]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!Ae.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let c=e.context.password.config.minPasswordLength;if(n.length<c)throw e.context.logger.error("Password is too short"),new ue("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new ue("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new ue("UNPROCESSABLE_ENTITY",{message:"Failed to create user"});let g=Pt(e.context.options,s),f=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1});if(!f)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let k=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:f.id,providerId:"credential",accountId:f.id,password:k,expiresAt:J(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let h=await oe(e.context.secret,f.email),R=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(f,R,h)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({user:f,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:null}});let I=await e.context.internalAdapter.createSession(f.id,e.request);if(!I)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await A(e,I.id),e.json({user:f,session:I},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:I}})});var zt=(e,t)=>{let r={};for(let[o,n]of Object.entries(e))r[o]=i=>n({...i,context:{...t,...i.context}}),r[o].path=n.path,r[o].method=n.method,r[o].options=n.options,r[o].headers=n.headers;return r};var Ft={};br(Ft,{AccessControl:()=>Ue,ParsingError:()=>le,Role:()=>ke,adminAc:()=>xt,createAccessControl:()=>Lt,defaultAc:()=>$e,defaultRoles:()=>Xe,defaultStatements:()=>Dt,memberAc:()=>Nt,ownerAc:()=>jt,permissionFromString:()=>yo});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},Ue=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new ke(t)}},ke=class e{statements;constructor(t){this.statements=t}authorize(t,r){for(let[o,n]of Object.entries(t)){let i=this.statements[o];if(!i)return{success:!1,error:`You are not allowed to access resource: ${o}`};let a=r==="OR"?n.some(s=>i.includes(s)):n.every(s=>i.includes(s));return a?{success:a}:{success:!1,error:`unauthorized to access resource "${o}"`}}return{success:!1,error:"Not authorized"}}static fromString(t){let r=JSON.parse(t);if(typeof r!="object")throw new le("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new le("invalid resource identifier",o);if(!Array.isArray(n))throw new le("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new le("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var Lt=e=>new Ue(e),Dt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},$e=Lt(Dt),xt=$e.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),jt=$e.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),Nt=$e.newRole({organization:[],member:[],invitation:[]}),Xe={admin:xt,owner:jt,member:Nt};var yo=e=>ke.fromString(e??"");var P=(e,t)=>({findOrganizationBySlug:async r=>await e.findOne({model:"organization",where:[{field:"slug",value:r}]}),createOrganization:async r=>{let o=await e.create({model:"organization",data:{...r.organization,metadata:r.organization.metadata?JSON.stringify(r.organization.metadata):void 0}}),n=await e.create({model:"member",data:{id:_(),organizationId:o.id,userId:r.user.id,createdAt:new Date,email:r.user.email,role:t?.creatorRole||"owner"}});return{...o,metadata:o.metadata?JSON.parse(o.metadata):void 0,members:[{...n,user:{id:r.user.id,name:r.user.name,email:r.user.email,image:r.user.image}}]}},findMemberByEmail:async r=>{let o=await e.findOne({model:"member",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberByOrgId:async r=>{let[o,n]=await Promise.all([await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{field:"organizationId",value:r.organizationId}]}),await e.findOne({model:"user",where:[{field:"id",value:r.userId}]})]);return!n||!o?null:{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}},findMemberById:async r=>{let o=await e.findOne({model:"member",where:[{field:"id",value:r}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},createMember:async r=>await e.create({model:"member",data:r}),updateMember:async(r,o)=>await e.update({model:"member",where:[{field:"id",value:r}],update:{role:o}}),deleteMember:async r=>await e.delete({model:"member",where:[{field:"id",value:r}]}),updateOrganization:async(r,o)=>await e.update({model:"organization",where:[{field:"id",value:r}],update:o}),deleteOrganization:async r=>(await e.delete({model:"member",where:[{field:"organizationId",value:r}]}),await e.delete({model:"invitation",where:[{field:"organizationId",value:r}]}),await e.delete({model:"organization",where:[{field:"id",value:r}]}),r),setActiveOrganization:async(r,o)=>await e.update({model:"session",where:[{field:"id",value:r}],update:{activeOrganizationId:o}}),findOrganizationById:async r=>await e.findOne({model:"organization",where:[{field:"id",value:r}]}),findFullOrganization:async(r,o)=>{let[n,i,a]=await Promise.all([e.findOne({model:"organization",where:[{field:"id",value:r}]}),e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),e.findMany({model:"member",where:[{field:"organizationId",value:r}]})]);if(!n)return null;let s=a.map(p=>p.userId),d=await e.findMany({model:"user",where:[{field:"id",value:s,operator:"in"}]}),c=new Map(d.map(p=>[p.id,p])),l=a.map(p=>{let g=c.get(p.userId);if(!g)throw new $("Unexpected error: User not found for member");return{...p,user:{id:g.id,name:g.name,email:g.email,image:g.image}}});return{...n,invitations:i,members:l}},listOrganizations:async r=>{let o=await e.findMany({model:"member",where:[{field:"userId",value:r}]});if(!o||o.length===0)return[];let n=o.map(a=>a.organizationId);return await e.findMany({model:"organization",where:[{field:"id",value:n,operator:"in"}]})},createInvitation:async({invitation:r,user:o})=>{let i=J(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:_(),email:r.email,role:r.role,organizationId:r.organizationId,status:"pending",expiresAt:i,inviterId:o.id}})},findInvitationById:async r=>await e.findOne({model:"invitation",where:[{field:"id",value:r}]}),findPendingInvitation:async r=>(await e.findMany({model:"invitation",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId},{field:"status",value:"pending"}]})).filter(n=>new Date(n.expiresAt)>new Date),updateInvitation:async r=>await e.update({model:"invitation",where:[{field:"id",value:r.invitationId}],update:{status:r.status}})});import"better-call";import{APIError as Gd,createRouter as Zd,statusCode as Yd}from"better-call";import{APIError as et}from"better-call";import{z as Mt}from"zod";var bo=T({body:Mt.object({csrfToken:Mt.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=e.headers?.get("origin")||"";if(e.context.trustedOrigins.includes(t))return;let r=e.body?.csrfToken;if(!r)throw new et("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await Y(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{isTest as Nd}from"std-env";import{APIError as M}from"better-call";var L=T(async e=>({})),x=T({use:[w]},async e=>({session:e.context.session}));import{z as W}from"zod";import{z as v}from"zod";var Ve=v.enum(["admin","member","owner"]),Ao=v.enum(["pending","accepted","rejected","canceled"]).default("pending"),kc=v.object({id:v.string(),name:v.string(),slug:v.string(),logo:v.string().optional(),metadata:v.record(v.string()).or(v.string().transform(e=>JSON.parse(e))).optional(),createdAt:v.date()}),Rc=v.object({id:v.string(),email:v.string(),organizationId:v.string(),userId:v.string(),role:Ve,createdAt:v.date()}),Oc=v.object({id:v.string(),organizationId:v.string(),email:v.string(),role:Ve,status:Ao,inviterId:v.string(),expiresAt:v.date()});import{APIError as E}from"better-call";var qt=u("/organization/invite-member",{method:"POST",use:[L,x],body:W.object({email:W.string(),role:Ve,organizationId:W.string().optional(),resend:W.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw y.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new E("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new E("BAD_REQUEST",{message:"Organization not found"});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new E("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new E("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new E("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new E("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),$t=u("/organization/accept-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:_(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),Vt=u("/organization/reject-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),Ht=u("/organization/cancel-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new E("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),Qt=u("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:W.object({id:W.string()})},async e=>{let t=await F(e);if(!t)throw new E("UNAUTHORIZED",{message:"Not authenticated"});let r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new E("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new E("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as pe}from"zod";import{APIError as Ee}from"better-call";var Wt=u("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ee("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ee("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ee("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ee("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Ee("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Kt=u("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as C}from"zod";import{APIError as me}from"better-call";var Jt=u("/organization/create",{method:"POST",body:C.object({name:C.string(),slug:C.string(),userId:C.string().optional(),logo:C.string().optional(),metadata:C.record(C.string()).optional()}),use:[L,x]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new me("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=P(e.context.adapter,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new me("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new me("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:_(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),Gt=u("/organization/update",{method:"POST",body:C.object({data:C.object({name:C.string().optional(),slug:C.string().optional()}).partial(),orgId:C.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new me("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["update"]}).error)return e.json(null,{body:{message:"You are not allowed to update this organization"},status:403});let s=await o.updateOrganization(r,e.body.data);return e.json(s)}),Zt=u("/organization/delete",{method:"POST",body:C.object({orgId:C.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["delete"]}).error)throw new me("FORBIDDEN",{message:"You are not allowed to delete this organization"});return r===t.session.activeOrganizationId&&await o.setActiveOrganization(t.session.id,null),await o.deleteOrganization(r),e.json(r)}),Yt=u("/organization/get-full",{method:"GET",query:C.object({orgId:C.string().optional()}),requireHeaders:!0,use:[L,x]},async e=>{let t=e.context.session,r=e.query.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400});let n=await P(e.context.adapter,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new me("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Xt=u("/organization/activate",{method:"POST",body:C.object({orgId:C.string().nullable().optional()}),use:[x,L]},async e=>{let t=P(e.context.adapter,e.context.orgOptions),r=e.context.session,o=e.body.orgId;if(o===null)return r.session.activeOrganizationId&&await t.setActiveOrganization(r.session.id,null),e.json(null);if(!o){let a=r.session.activeOrganizationId;if(!a)return e.json(null);o=a}if(!await t.findMemberByOrgId({userId:r.user.id,organizationId:o}))throw await t.setActiveOrganization(r.session.id,null),new me("FORBIDDEN",{message:"You are not a member of this organization"});await t.setActiveOrganization(r.session.id,o);let i=await t.findFullOrganization(o,e.context.db||void 0);return e.json(i)}),er=u("/organization/list",{method:"GET",use:[L,x]},async e=>{let r=await P(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var iu=e=>{let t={createOrganization:Jt,updateOrganization:Gt,deleteOrganization:Zt,setActiveOrganization:Xt,getFullOrganization:Yt,listOrganization:er,createInvitation:qt,cancelInvitation:Ht,acceptInvitation:$t,getInvitation:Qt,rejectInvitation:Vt,removeMember:Wt,updateMemberRole:Kt},r={...Xe,...e?.roles};return{id:"organization",endpoints:{...zt(t,{orgOptions:e||{},roles:r,getSession:async n=>await F(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new tr("BAD_REQUEST",{message:"No active organization"});let a=await P(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new tr("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import{z as Ke}from"zod";import{z as Pe}from"zod";import{APIError as fe}from"better-call";var He="two-factor";var Qe="trust-device";import{z as rr}from"zod";var ge=T({body:rr.object({trustDevice:rr.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(He),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let i=await e.context.adapter.findMany({model:"session",where:[{field:"userId",value:o}]});if(!i.length)throw new fe("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new fe("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await Y(e.context.secret,s.id),c=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!c)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await A(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await Y(e.context.secret,`${c.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:c})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:c}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Se}from"better-call";function ko(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>V(e?.length??10,H("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function tt(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():ko(),n=await Me({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Ro(e,t){let r=await or(e.backupCodes,t);return r?r.includes(e.code):!1}async function or(e,t){let r=Buffer.from(await qe({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Pe.array(Pe.string()).safeParse(o);return n.success?n.data:null}var nr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:Pe.object({code:Pe.string(),disableSession:Pe.boolean().optional()}),use:[ge]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Ro({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Se("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await A(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",use:[w]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Se("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await tt(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",use:[w]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=or(n.backupCodes,r.context.secret);if(!i)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as We}from"better-call";import{TOTPController as Oo}from"oslo/otp";import{z as ir}from"zod";import{TimeSpan as vo}from"oslo";var sr=(e,t)=>{let r={...e,period:new vo(e?.period||3,"m")},o=new Oo({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[ge]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new We("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:ir.object({code:ir.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new We("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as Re}from"better-call";import{TimeSpan as Io}from"oslo";import{TOTPController as ar,createTOTPKeyURI as Uo}from"oslo/otp";import{z as dr}from"zod";var cr=(e,t)=>{let r={...e,digits:6,period:new Io(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new ar(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"GET",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Uo(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:dr.object({code:dr.string()}),use:[ge]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!d.enabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});let c=new ar(r),l=await qe({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await c.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function rt(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as ur}from"better-call";var $u=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t==="/two-factor/enable"||t==="/two-factor/send-otp"||t==="/two-factor/disable",signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var rl=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=cr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=nr({...e?.backupCodeOptions},t.twoFactorTable),n=sr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new ur("BAD_REQUEST",{message:"Invalid password"});let c=V(16,H("a-z","0-9","-")),l=await Me({key:i.context.secret,data:c}),p=await tt(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new ur("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:T(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[f,k]=c.split("!"),I=await Y(i.context.secret,`${s.user.id}!${k}`);if(f===I){let h=await Y(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await Y(i.context.secret,s.session.id),p=i.context.createAuthCookie(He,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.options),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as zo,generateRegistrationOptions as Lo,verifyAuthenticationResponse as Do,verifyRegistrationResponse as xo}from"@simplewebauthn/server";import{APIError as ee}from"better-call";import{z as ne}from"zod";import{env as jo}from"std-env";import{WebAuthnError as So,startAuthentication as Po,startRegistration as Co}from"@simplewebauthn/browser";import{createFetch as fl}from"@better-fetch/fetch";import"nanostores";import{betterFetch as sl}from"@better-fetch/fetch";import{atom as Il}from"nanostores";import"@better-fetch/fetch";import{atom as Eo,onMount as To}from"nanostores";var ot=(e,t,r,o)=>{let n=Eo({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():To(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as _o}from"nanostores";var Bo=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await Po(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch(s){console.log(s)}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Co(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof So?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),Vl=()=>{let e=_o();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Bo(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:ot(e,"/passkey/list-user-passkeys",t,{method:"GET",credentials:"include"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var op=e=>{let t=jo.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[w],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(V(32,H("a-z","0-9")))),p;p=await Lo({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:ne.object({email:ne.string().optional()}).optional()},async s=>{let d=await F(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await zo({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:ne.object({response:ne.any(),name:ne.string().optional()}),use:[w]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:g,userData:f}=JSON.parse(p.value);if(f.id!==s.context.session.user.id)throw new ee("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await xo({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:I,registrationInfo:h}=k;if(!I||!h)return s.json(null,{status:400});let{credentialID:R,credentialPublicKey:q,counter:K,credentialDeviceType:O,credentialBackedUp:j}=h,ae=Buffer.from(q).toString("base64"),D=_(),Be={name:s.body.name,userId:f.id,webauthnUserID:D,id:R,publicKey:ae,counter:K,deviceType:O,transports:c.response.transports.join(","),backedUp:j,createdAt:new Date},wr=await s.context.adapter.create({model:"passkey",data:Be});return s.json(wr,{status:200})}catch(k){throw console.log(k),new ee("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:ne.object({response:ne.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new ee("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:g}=JSON.parse(p.value),f=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!f)throw new ee("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await Do({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:f.id,credentialPublicKey:new Uint8Array(Buffer.from(f.publicKey,"base64")),counter:f.counter,transports:f.transports?.split(",")}}),{verified:I}=k;if(!I)throw new ee("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:f.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(f.userId,s.request);if(!h)throw new ee("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await A(s,h.id),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new ee("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[w]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:ne.object({id:ne.string()}),use:[w]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as te}from"zod";import{APIError as Je}from"better-call";var lr=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:te.object({username:te.string(),password:te.string(),dontRememberMe:te.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:"user",where:[{field:"username",value:e.body.username}]});if(!t)throw await e.context.password.hash(e.body.password),e.context.logger.error("User not found",{username:lr}),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:"account",where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.type.fieldName||"providerId",value:"credential"}]});if(!r)throw new Je("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:lr}),new Je("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:u("/sign-up/username",{method:"POST",body:te.object({username:te.string().min(3).max(20),name:te.string(),email:te.string().email(),password:te.string(),image:te.string().optional()})},async e=>{let t=await Ye()({...e,_flag:"json"}),r=await e.context.internalAdapter.updateUserByEmail(t.user?.email,{username:e.body.username});return e.json({user:r,session:t.session})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as No}from"better-call";var pp=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await No("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as Oe}from"zod";import{APIError as Fo}from"better-call";var Ap=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Oe.object({email:Oe.string().email(),callbackURL:Oe.string().optional()}),use:[S]},async t=>{let{email:r}=t.body,o=V(32,H("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new Fo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:Oe.object({token:Oe.string(),callbackURL:Oe.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await A(t,c.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as he}from"zod";import{APIError as ie}from"better-call";function Mo(e){return V(e,H("0-9"))}var Pp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw y.warn("sendOTP not implemented"),new ie("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Mo(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:J(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:he.object({phoneNumber:he.string(),code:he.string(),disableSession:he.boolean().optional(),updatePhoneNumber:he.boolean().optional()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new ie("BAD_REQUEST",{message:"OTP expired"})):new ie("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ie("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await F(r);if(!i)throw new ie("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ie("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(r,i.id),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as nt}from"zod";var xp=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=mt(t.context.baseURL)}=e||{},o=_(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await A(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:u("/user/link-anonymous",{method:"POST",body:nt.object({email:nt.string().email().optional(),password:nt.string().min(6)}),use:[w]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await A(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});import{z as m}from"zod";var re=T(async e=>{let t=await F(e);if(!t?.session)throw new M("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new M("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),$p=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/user/list-sessions"},handler:T(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:m.object({userId:m.string(),role:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:m.object({email:m.string(),password:m.string(),name:m.string(),role:m.string(),data:m.optional(m.record(m.any()))}),use:[re]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new M("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[re],query:m.object({search:m.object({field:m.enum(["email","name"]),operator:m.enum(["contains","starts_with","ends_with"]).default("contains"),value:m.string()}).optional(),limit:m.string().or(m.number()).optional(),offset:m.string().or(m.number()).optional(),sortBy:m.string().optional(),sortDirection:m.enum(["asc","desc"]).optional(),filter:m.array(m.object({field:m.string(),value:m.string().or(m.number()).or(m.boolean()),operator:m.enum(["eq","ne","lt","lte","gt","gte"]),connector:m.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[re],body:m.object({userId:m.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:m.object({userId:m.string(),banReason:m.string().optional(),banExpiresIn:m.number().optional()}),use:[re]},async t=>{if(t.body.userId===t.context.session.user.id)throw new M("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new M("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?J(e.impersonationSessionDuration,"sec"):J(60*60,"sec")});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:m.object({sessionId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});import{z as se}from"zod";import{APIError as Ce}from"better-call";import{betterFetch as it}from"@better-fetch/fetch";import{generateCodeVerifier as qo}from"oslo/oauth2";import{parseJWT as $o}from"oslo/jwt";async function Vo(e,t,r){if(t==="oidc"&&e.idToken){let n=$o(e.idToken);if(n?.payload)return n.payload}return r?(await it(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var sm=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:se.object({currentURL:se.string().optional()}).optional(),body:se.object({providerId:se.string(),callbackURL:se.string().optional()}),use:[S]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:g,prompt:f,accessType:k}=o,I=i,h=a;if(n){let D=await it(n,{onError(Be){y.error(Be.error,{discoveryUrl:n})}});D.data&&(I=D.data.authorization_endpoint,h=D.data.token_endpoint)}if(!I||!h)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let R=t.query?.currentURL?new URL(t.query?.currentURL):null,q=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${R?.origin}${t.body.callbackURL||""}`,K=await De(q||R?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,K.hash,t.context.secret,O.state.options);let j=qo();await t.setSignedCookie(O.pkCodeVerifier.name,j,t.context.secret,O.pkCodeVerifier.options);let ae=await B({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:I,state:K.raw,codeVerifier:j,scopes:c||[],disablePkce:!g,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ae.searchParams.set("response_type",p),f&&ae.searchParams.set("prompt",f),k&&ae.searchParams.set("access_type",k),{url:ae.toString(),state:K,codeVerifier:j,redirect:!0}}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:se.object({code:se.string().optional(),error:se.string().optional(),state:se.string()})},async t=>{if(t.query.error||!t.query.code){let j=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${j}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o=await t.getSignedCookie(t.context.authCookies.pkCodeVerifier.name,t.context.secret),n,i=we(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,c=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw y.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await ze(a,p))throw y.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let f=r.tokenUrl,k=r.userInfoUrl;if(r.discoveryUrl){let O=await it(r.discoveryUrl,{method:"GET"});O.data&&(f=O.data.token_endpoint,k=O.data.userinfo_endpoint)}try{if(!f)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await U({code:c,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:f})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let I=r.getUserInfo?await r.getUserInfo(n):await Vo(n,r.type||"oauth2",k),h=_(),R=I?je.safeParse({...I,id:h}):null;if(!R?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let q=await t.context.internalAdapter.findUserByEmail(R.data.email).catch(O=>{throw y.error(`Better auth was unable to query your database.
|
|
84
|
+
Error: `,O),t.redirect(`${l}?error=internal_server_error`)}),K=q?.user.id||h;if(q){let O=q.accounts.find(D=>D.providerId===r.providerId),j=t.context.options.account?.accountLinking?.trustedProviders,ae=j?j.includes(r.providerId):!0;if(!O&&(!R?.data.emailVerified||!ae)){let D;try{D=new URL(l),D.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(D.toString())}if(!O)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:R.data.id,id:`${r.providerId}:${R.data.id}`,userId:q.user.id,...ye(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(R.data,{...ye(n),id:`${r.providerId}:${R.data.id}`,providerId:r.providerId,accountId:R.data.id})}catch{let j=new URL(l);throw j.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",j.toString()),t.redirect(j.toString())}try{let O=await t.context.internalAdapter.createSession(K||h,t.request);if(!O)throw t.redirect(`${l}?error=unable_to_create_session`);await A(t,O.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var pr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},cm=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var st=e=>({getAllKeys:async()=>await e.findMany({model:"jwks"}),getLatestKey:async()=>(await e.findMany({model:"jwks",sortBy:{field:"createdAt",direction:"desc"},limit:1}))[0],createJwk:async t=>await e.create({model:"jwks",data:{...t,createdAt:new Date}})});import{exportJWK as hr,generateKeyPair as Jo,importJWK as Go,SignJWT as Zo}from"jose";import{createCipheriv as Ho,createDecipheriv as Qo,createHash as Wo,randomBytes as Ko}from"crypto";function mr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=Wo("sha256").update(e).digest(),t}function fr(e,t){let r=mr(t),o=Ko(12),n=Ho("aes-256-gcm",r,o),i=n.update(e,"utf8","base64");i+=n.final("base64");let a=n.getAuthTag();return{encryptedPrivateKey:i,iv:o.toString("base64"),authTag:a.toString("base64")}}function gr(e,t){let r=mr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=Qo("aes-256-gcm",r,a);d.setAuthTag(s);let c=d.update(o,"base64","utf8");return c+=d.final("utf8"),c}var bm=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await st(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[w]},async t=>{let r=st(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await Jo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await hr(c),g=await hr(l),f=JSON.stringify(g),k={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(fr(f,t.context.options.secret)):f,createdAt:new Date};o=await r.createJwk(k)}let i=n?gr(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await Go(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new Zo({...s,...t.context.session.session.impersonatedBy?{impersonatedBy:t.context.session.session.impersonatedBy}:{}}).setProtectedHeader({alg:e?.jwks?.keyPairConfig?.alg??"EdDSA"}).setIssuedAt().setIssuer(e?.jwt?.issuer??t.context.options.baseURL).setAudience(e?.jwt?.audience??t.context.options.baseURL).setExpirationTime(e?.jwt?.expirationTime??"15m").setSubject(t.context.session.user.id).sign(a);return t.json({token:d})})},schema:pr});import{z as Ge}from"zod";var vm=e=>{let t={maximumSessions:5,...e},r=o=>o.includes("_multi-");return{id:"multi-session",endpoints:{listDeviceSessions:u("/multi-session/list-device-sessions",{method:"GET",requireHeaders:!0},async o=>{let n=o.headers?.get("cookie");if(!n)return o.json([]);let i=Object.fromEntries(xe(n)),a=(await Promise.all(Object.entries(i).filter(([c])=>r(c)).map(async([c])=>await o.getSignedCookie(c,o.context.secret)))).filter(c=>c!==void 0),d=(await o.context.internalAdapter.findSessions(a)).filter(c=>c&&c.session.expiresAt>new Date).filter((c,l,p)=>l===p.findIndex(g=>g.user.id===c.user.id));return Object.entries(i).filter(([c])=>r(c)).forEach(([c,l])=>{d.some(p=>p.session.id===l)||o.setCookie(c,"",{...o.context.authCookies.sessionToken.options,maxAge:0})}),o.json(d)}),setActiveSession:u("/multi-session/set-active",{method:"POST",body:Ge.object({sessionId:Ge.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new M("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);if(!s||s.session.expiresAt<new Date)throw o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),new M("UNAUTHORIZED",{message:"Invalid session id"});return await o.setSignedCookie(o.context.authCookies.sessionToken.name,n,o.context.secret,o.context.authCookies.sessionToken.options),o.json(s)}),DeviceSession:u("/multi-session/revoke",{method:"POST",body:Ge.object({sessionId:Ge.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new M("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);return!s||s.session.expiresAt<new Date?(o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0})):(await o.context.internalAdapter.deleteSession(n),o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0}))})},hooks:{after:[{matcher:()=>!0,handler:T(async o=>{if(!o.context.returned||!(o.context.returned instanceof Response))return;let n=o.context.returned.headers.get("set-cookie");if(!n)return;let i=lt(n),a=o.context.authCookies.sessionToken,s=i.get(a.name)?.value;if(!s)return;let d=xe(o.headers?.get("cookie")||""),c=s.split(".")[0],l=`${a.name}_multi-${c}`;if(i.get(l)||d.get(l))return;if(Object.keys(Object.fromEntries(d)).filter(r).length+(n.includes("session_token")?1:0)>t.maximumSessions)throw new M("UNAUTHORIZED",{message:"Maximum number of device sessions reached."});await o.setSignedCookie(l,c,o.context.secret,a.options);let g=o.context.returned;return g.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:g}})},{matcher:o=>o.path==="/sign-out",handler:T(async o=>{let n=o.headers?.get("cookie");if(!n)return;let i=Object.fromEntries(xe(n));await Promise.all(Object.entries(i).map(async([s,d])=>{r(s)&&(o.setCookie(s,"",{maxAge:0}),await o.context.internalAdapter.deleteSession(s.split("_multi-")[1]))}));let a=o.context.returned;return a?.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:a}})}]}}};export{de as HIDE_METADATA,Ft as ac,$p as admin,re as adminMiddleware,xp as anonymous,pp as bearer,u as createAuthEndpoint,T as createAuthMiddleware,sm as genericOAuth,Bo as getPasskeyActions,bm as jwt,Ap as magicLink,vm as multiSession,dt as optionsMiddleware,iu as organization,op as passkey,Vl as passkeyClient,Pp as phoneNumber,rl as twoFactor,$u as twoFactorClient,lr as username};
|
package/dist/react.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ import * as _better_fetch_fetch from '@better-fetch/fetch';
|
|
|
3
3
|
import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.cjs';
|
|
4
4
|
import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.cjs';
|
|
5
5
|
import { useStore } from '@nanostores/react';
|
|
6
|
-
import './auth-
|
|
6
|
+
import './auth-D7_h4yVD.cjs';
|
|
7
7
|
import 'kysely';
|
|
8
8
|
import './schema-Dkt0LqYs.cjs';
|
|
9
9
|
import 'better-call';
|