better-auth 0.4.12 → 0.4.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.ts +10 -1
- package/dist/adapters/drizzle.js +1 -1
- package/dist/adapters/kysely.d.ts +10 -1
- package/dist/adapters/kysely.js +1 -2
- package/dist/adapters/mongodb.d.ts +13 -2
- package/dist/adapters/mongodb.js +1 -1
- package/dist/adapters/prisma.d.ts +12 -3
- package/dist/adapters/prisma.js +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +4 -4
- package/dist/{auth-BqAt6mrY.d.ts → auth-C6fr77co.d.ts} +46 -26
- package/dist/client/plugins.d.ts +3 -3
- package/dist/client.d.ts +1 -1
- package/dist/cookies.d.ts +1 -1
- package/dist/db.d.ts +3 -3
- package/dist/db.js +3 -3
- package/dist/{index-BN_LDD1g.d.ts → index-pILRgibH.d.ts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/node.d.ts +1 -1
- package/dist/plugins.d.ts +3 -3
- package/dist/plugins.js +5 -5
- package/dist/react.d.ts +1 -1
- package/dist/social.js +2 -2
- package/dist/solid-start.d.ts +1 -1
- package/dist/solid.d.ts +1 -1
- package/dist/svelte-kit.d.ts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/vue.d.ts +1 -1
- package/package.json +1 -1
package/dist/plugins.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var gr=Object.defineProperty;var hr=(e,t)=>{for(var r in t)gr(e,r,{get:t[r],enumerable:!0})};import{APIError as Yt}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as wr,createMiddleware as it,createMiddlewareCreator as yr}from"better-call";var st=it(async()=>({})),_=yr({use:[st,it(async()=>({}))]}),c=wr({use:[st]});import{APIError as K}from"better-call";import{generateCodeVerifier as
|
|
2
|
-
`)}}),b=kr();var C=_(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 b.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new ct("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw b.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new ct("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as vr}from"oslo/jwt";import{sha256 as Rr}from"oslo/crypto";function ut(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Or}from"oslo/encoding";async function lt(e){let t=await Rr(new TextEncoder().encode(e));return Or.encode(new Uint8Array(t),{includePadding:!1})}function pt(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 z({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let u=new URL(r);if(u.searchParams.set("response_type","code"),u.searchParams.set("client_id",t.clientId),u.searchParams.set("state",o),u.searchParams.set("scope",i.join(" ")),u.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await lt(n);u.searchParams.set("code_challenge_method","S256"),u.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,R)=>(p[R]=null,p),{});u.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return u}import{betterFetch as Ir}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 Ir(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 pt(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 mt=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=vr(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 Ur}from"@better-fetch/fetch";var ft=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 Ur("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 Tr}from"@better-fetch/fetch";var gt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await z({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 Tr("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 ht}from"@better-fetch/fetch";var wt=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 z({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 ht("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await ht("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});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 Er}from"oslo/jwt";var yt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw b.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new F("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new F("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return z({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=Er(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 Sr}from"@better-fetch/fetch";import{parseJWT as Pr}from"oslo/jwt";var bt=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 z({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=Pr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Sr(`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 u=await s.response.clone().arrayBuffer(),l=Buffer.from(u).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){b.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as _r}from"@better-fetch/fetch";var At=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return z({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 _r("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 ie={isAction:!1};function Cr(e){return e.toString(2).padStart(8,"0")}function zr(e){return[...e].map(t=>Cr(t)).join("")}function kt(e){return parseInt(zr(e),2)}function Br(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=kt(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=kt(o);return n}function j(e,t){let r="";for(let o=0;o<e;o++)r+=t[Br(t.length)];return r}function N(...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}var P=e=>j(e||21,N("a-z","0-9","A-Z"));import{parseJWT as Lr}from"oslo/jwt";var Rt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return z({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 b.error("No idToken found in token"),null;let o=Lr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as xr}from"@better-fetch/fetch";var Ot=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return z({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 xr("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 Dr={apple:mt,discord:ft,facebook:gt,github:wt,microsoft:bt,google:yt,spotify:At,twitch:Rt,twitter:Ot},It=Object.keys(Dr);import{TimeSpan as jr}from"oslo";import{createJWT as Nr,validateJWT as Fr}from"oslo/jwt";import{z as H}from"zod";import{APIError as xe}from"better-call";async function ce(e,t){return await Nr("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new jr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Mr=c("/send-verification-email",{method:"POST",query:H.object({currentURL:H.string().optional()}).optional(),body:H.object({email:H.string().email(),callbackURL:H.string().optional()}),use:[C]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new xe("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new xe("BAD_REQUEST",{message:"User not found"});let o=await ce(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})}),qr=c("/verify-email",{method:"GET",query:H.object({token:H.string(),callbackURL:H.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await Fr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new xe("BAD_REQUEST",{message:"Invalid token"})}let n=H.object({email:H.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new xe("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});var Vr=c("/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(It)}),use:[C]},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 K("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 Le(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=$r();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})}),Qr=c("/sign-in/email",{method:"POST",body:q.object({email:q.string().email(),password:q.string(),callbackURL:q.string().optional(),dontRememberMe:q.boolean().default(!1).optional()}),use:[C]},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 K("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 K("BAD_REQUEST",{message:"Invalid email"});let n=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!n)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new K("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!n.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw b.error("Email verification is required but no email verification handler is provided"),new K("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let u=await ce(e.context.secret,n.user.email),l=`${e.context.options.baseURL}/verify-email?token=${u}`;throw await e.context.options.emailVerification.sendVerificationEmail(n.user,l,u),e.context.logger.error("Email not verified",{email:t}),new K("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let i=n.accounts.find(u=>u.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new K("UNAUTHORIZED",{message:"Invalid email or password"});let a=i?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new K("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new K("UNAUTHORIZED",{message:"Invalid email or password"});let d=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!d)throw e.context.logger.error("Failed to create session"),new K("UNAUTHORIZED",{message:"Failed to create session"});return await y(e,d.id,e.body.dontRememberMe),e.json({user:n.user,session:d,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as Hr}from"better-call";import{z as je}from"zod";import{z as w}from"zod";var gs=w.object({id:w.string(),providerId:w.string(),accountId:w.string(),userId:w.string(),accessToken:w.string().nullable().optional(),refreshToken:w.string().nullable().optional(),idToken:w.string().nullable().optional(),expiresAt:w.date().nullable().optional(),password:w.string().optional().nullable()}),De=w.object({id:w.string(),email:w.string().transform(e=>e.toLowerCase()),emailVerified:w.boolean().default(!1),name:w.string(),image:w.string().optional(),createdAt:w.date().default(new Date),updatedAt:w.date().default(new Date)}),hs=w.object({id:w.string(),userId:w.string(),expiresAt:w.date(),ipAddress:w.string().optional(),userAgent:w.string().optional()}),ws=w.object({id:w.string(),value:w.string(),expiresAt:w.date(),identifier:w.string()});function Wr(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 vt(e,t){let r={...e.user?.additionalFields};return Wr(t||{},{fields:r})}var Kr=c("/callback/:id",{method:"GET",query:je.object({state:je.string(),code:je.string().optional(),error:je.string().optional()}),metadata:ie},async e=>{if(e.query.error||!e.query.code){let h=we(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${h}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(f=>f.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 b.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ze(e.query.state,i))throw b.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(f){throw e.context.logger.error(f),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let u=await t.getUserInfo(d).then(f=>f?.user),l=P(),p=De.safeParse({...u,id:l});if(!u||p.success===!1)throw b.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`);let R=await e.context.internalAdapter.findUserByEmail(u.email,{includeAccounts:!0}).catch(f=>{throw b.error(`Better auth was unable to query your database.
|
|
3
|
-
Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=R?.user.id;if(R){let f=R.accounts.find(O=>O.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,k=h?h.includes(t.id):!0;if(!f&&(!u.emailVerified||!k)){let O;try{O=new URL(n||o),O.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(O.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:u.id.toString(),id:`${t.id}:${u.id}`,userId:R.user.id,...ye(d)})}catch(O){throw console.log(O),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{let f=u.emailVerified,h=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:f},{...ye(d),id:`${t.id}:${u.id}`,providerId:t.id,accountId:u.id.toString(),userId:l});if(!f&&h&&e.context.options.emailVerification?.sendOnSignUp){let k=await ce(e.context.secret,u.email),O=`${e.context.baseURL}/verify-email?token=${k}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(h.user,O,k)}}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.redirect(h.toString())}if(!m&&!l)throw new Hr("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let f=await e.context.internalAdapter.createSession(m||l,e.request);if(!f){let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_session"),e.redirect(h.toString())}try{await y(e,f.id)}catch(h){e.context.logger.error("Unable to set session cookie",h);let k=new URL(n||o);throw k.searchParams.set("error","unable_to_create_session"),e.redirect(k.toString())}}catch{let f=new URL(n||o||"");throw f.searchParams.set("error","unable_to_create_session"),e.redirect(f.toString())}throw e.redirect(o)});import{APIError as Ie}from"better-call";var $=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Ut}from"zod";var Tt=()=>c("/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 Oe(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:$(e.context.sessionConfig.expiresIn,"sec")});if(!d)return Oe(e),e.json(null,{status:401});let u=(d.expiresAt.valueOf()-Date.now())/1e3;return await y(e,d.id,!1,{maxAge:u}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),V=async e=>await Tt()({...e,_flag:"json",headers:e.headers}),A=_(async e=>{let t=await V(e);if(!t?.session)throw new Ie("UNAUTHORIZED");return{session:t}});var Jr=c("/user/revoke-session",{method:"POST",body:Ut.object({id:Ut.string()}),use:[A],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})}),Gr=c("/user/revoke-sessions",{method:"POST",use:[A],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})});import"zod";import{APIError as Zr}from"better-call";var Yr=c("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Zr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),Oe(e),e.json({success:!0})});import{z as ee}from"zod";import{APIError as Ne}from"better-call";var Xr=c("/forget-password",{method:"POST",body:ee.object({email:ee.string().email(),redirectTo:ee.string()}),use:[C]},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 Ne("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})}),eo=c("/reset-password/:token",{method:"GET",query:ee.object({callbackURL:ee.string()}),use:[C]},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}`)}),to=c("/reset-password",{query:ee.object({token:ee.string()}).optional(),method:"POST",body:ee.object({newPassword:ee.string()})},async e=>{let t=e.query?.token;if(!t)throw new Ne("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 Ne("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 Ne("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{z as Q}from"zod";import{APIError as J}from"better-call";var ro=c("/user/update",{method:"POST",body:Q.object({name:Q.string().optional(),image:Q.string().optional()}),use:[A,C]},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})}),oo=c("/user/change-password",{method:"POST",body:Q.object({newPassword:Q.string(),currentPassword:Q.string(),revokeOtherSessions:Q.boolean().optional()}),use:[A]},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 J("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 J("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 J("BAD_REQUEST",{message:"User does not have a password"});let u=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new J("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:u}),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 J("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await y(e,p.id)}return e.json(n.user)}),no=c("/user/set-password",{method:"POST",body:Q.object({newPassword:Q.string()}),use:[A]},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 J("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 J("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 J("BAD_REQUEST",{message:"user already has a password"})}),io=c("/user/delete",{method:"POST",body:Q.object({password:Q.string()}),use:[A]},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 J("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new J("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)});import{xchacha20poly1305 as Et}from"@noble/ciphers/chacha";import{bytesToHex as so,hexToBytes as ao,utf8ToBytes as co}from"@noble/ciphers/utils";import{managedNonce as St}from"@noble/ciphers/webcrypto";import{sha256 as Pt}from"oslo/crypto";import{decodeHex as ca,encodeHex as ua}from"oslo/encoding";import{scryptAsync as ma}from"@noble/hashes/scrypt";async function W(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 Fe=async({key:e,data:t})=>{let r=await Pt(new TextEncoder().encode(e)),o=co(t),n=St(Et)(new Uint8Array(r));return so(n.encrypt(o))},Me=async({key:e,data:t})=>{let r=await Pt(new TextEncoder().encode(e)),o=ao(t),n=St(Et)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var uo=c("/csrf",{method:"GET",metadata:ie},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=j(32,N("a-z","0-9","A-Z")),o=await W(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 lo=(e="Unknown")=>`<!DOCTYPE html>
|
|
1
|
+
var gr=Object.defineProperty;var hr=(e,t)=>{for(var r in t)gr(e,r,{get:t[r],enumerable:!0})};import{APIError as Yt}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as wr,createMiddleware as it,createMiddlewareCreator as yr}from"better-call";var st=it(async()=>({})),_=yr({use:[st,it(async()=>({}))]}),c=wr({use:[st]});import{APIError as K}from"better-call";import{generateCodeVerifier as Vr}from"oslo/oauth2";import{z as q}from"zod";import{generateState as br}from"oslo/oauth2";import{z as Be}from"zod";import{sha256 as at}from"oslo/crypto";function Je(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 dt(e){let t=await at(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ze(e,t){let r=await at(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Je(r,o)}import"better-call";async function Le(e){let t=br(),r=JSON.stringify({code:t,callbackURL:e}),o=await dt(r);return{raw:r,hash:o}}function we(e){return Be.object({code:Be.string(),callbackURL:Be.string().optional(),currentURL:Be.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as ln}from"oslo";var j=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};async function y(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 Oe(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}import{APIError as ct}from"better-call";import{createConsola as Ar}from"consola";var de=Ar({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),kr=e=>({log:(...t)=>{!e?.disabled&&de.log("",...t)},error:(...t)=>{!e?.disabled&&de.error("",...t)},warn:(...t)=>{!e?.disabled&&de.warn("",...t)},info:(...t)=>{!e?.disabled&&de.info("",...t)},debug:(...t)=>{!e?.disabled&&de.debug("",...t)},box:(...t)=>{!e?.disabled&&de.box("",...t)},success:(...t)=>{!e?.disabled&&de.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
|
|
2
|
+
`)}}),b=kr();var C=_(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 b.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new ct("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw b.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new ct("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as Ir}from"oslo/jwt";import{sha256 as Rr}from"oslo/crypto";function ut(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Or}from"oslo/encoding";async function lt(e){let t=await Rr(new TextEncoder().encode(e));return Or.encode(new Uint8Array(t),{includePadding:!1})}function pt(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 z({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let u=new URL(r);if(u.searchParams.set("response_type","code"),u.searchParams.set("client_id",t.clientId),u.searchParams.set("state",o),u.searchParams.set("scope",i.join(" ")),u.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await lt(n);u.searchParams.set("code_challenge_method","S256"),u.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,R)=>(p[R]=null,p),{});u.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return u}import{betterFetch as vr}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 vr(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 pt(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 mt=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=Ir(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 Ur}from"@better-fetch/fetch";var ft=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 Ur("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 Tr}from"@better-fetch/fetch";var gt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await z({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 Tr("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 ht}from"@better-fetch/fetch";var wt=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 z({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 ht("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await ht("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});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 Er}from"oslo/jwt";var yt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw b.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new j("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new j("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return z({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=Er(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 Sr}from"@better-fetch/fetch";import{parseJWT as Pr}from"oslo/jwt";var bt=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 z({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=Pr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Sr(`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 u=await s.response.clone().arrayBuffer(),l=Buffer.from(u).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){b.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as _r}from"@better-fetch/fetch";var At=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return z({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 _r("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 ne={isAction:!1};function Cr(e){return e.toString(2).padStart(8,"0")}function zr(e){return[...e].map(t=>Cr(t)).join("")}function kt(e){return parseInt(zr(e),2)}function Br(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=kt(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=kt(o);return n}function N(e,t){let r="";for(let o=0;o<e;o++)r+=t[Br(t.length)];return r}function F(...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 Lr}from"nanoid";var P=e=>Lr(e);import{parseJWT as xr}from"oslo/jwt";var Rt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return z({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 b.error("No idToken found in token"),null;let o=xr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Dr}from"@better-fetch/fetch";var Ot=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return z({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 Dr("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 jr={apple:mt,discord:ft,facebook:gt,github:wt,microsoft:bt,google:yt,spotify:At,twitch:Rt,twitter:Ot},vt=Object.keys(jr);import{TimeSpan as Nr}from"oslo";import{createJWT as Fr,validateJWT as Mr}from"oslo/jwt";import{z as H}from"zod";import{APIError as xe}from"better-call";async function ce(e,t){return await Fr("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new Nr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var qr=c("/send-verification-email",{method:"POST",query:H.object({currentURL:H.string().optional()}).optional(),body:H.object({email:H.string().email(),callbackURL:H.string().optional()}),use:[C]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new xe("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new xe("BAD_REQUEST",{message:"User not found"});let o=await ce(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})}),$r=c("/verify-email",{method:"GET",query:H.object({token:H.string(),callbackURL:H.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await Mr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new xe("BAD_REQUEST",{message:"Invalid token"})}let n=H.object({email:H.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new xe("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});var Qr=c("/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(vt)}),use:[C]},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 K("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 Le(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=Vr();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})}),Wr=c("/sign-in/email",{method:"POST",body:q.object({email:q.string().email(),password:q.string(),callbackURL:q.string().optional(),dontRememberMe:q.boolean().default(!1).optional()}),use:[C]},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 K("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 K("BAD_REQUEST",{message:"Invalid email"});let n=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!n)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new K("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!n.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw b.error("Email verification is required but no email verification handler is provided"),new K("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let u=await ce(e.context.secret,n.user.email),l=`${e.context.options.baseURL}/verify-email?token=${u}`;throw await e.context.options.emailVerification.sendVerificationEmail(n.user,l,u),e.context.logger.error("Email not verified",{email:t}),new K("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let i=n.accounts.find(u=>u.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new K("UNAUTHORIZED",{message:"Invalid email or password"});let a=i?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new K("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new K("UNAUTHORIZED",{message:"Invalid email or password"});let d=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!d)throw e.context.logger.error("Failed to create session"),new K("UNAUTHORIZED",{message:"Failed to create session"});return await y(e,d.id,e.body.dontRememberMe),e.json({user:n.user,session:d,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as Kr}from"better-call";import{z as je}from"zod";import{z as w}from"zod";var bs=w.object({id:w.string(),providerId:w.string(),accountId:w.string(),userId:w.string(),accessToken:w.string().nullable().optional(),refreshToken:w.string().nullable().optional(),idToken:w.string().nullable().optional(),expiresAt:w.date().nullable().optional(),password:w.string().optional().nullable()}),De=w.object({id:w.string(),email:w.string().transform(e=>e.toLowerCase()),emailVerified:w.boolean().default(!1),name:w.string(),image:w.string().optional(),createdAt:w.date().default(new Date),updatedAt:w.date().default(new Date)}),As=w.object({id:w.string(),userId:w.string(),expiresAt:w.date(),ipAddress:w.string().optional(),userAgent:w.string().optional()}),ks=w.object({id:w.string(),value:w.string(),expiresAt:w.date(),identifier:w.string()});function Hr(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 It(e,t){let r={...e.user?.additionalFields};return Hr(t||{},{fields:r})}var Jr=c("/callback/:id",{method:"GET",query:je.object({state:je.string(),code:je.string().optional(),error:je.string().optional()}),metadata:ne},async e=>{if(e.query.error||!e.query.code){let h=we(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${h}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(f=>f.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 b.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ze(e.query.state,i))throw b.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(f){throw e.context.logger.error(f),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let u=await t.getUserInfo(d).then(f=>f?.user),l=P(),p=De.safeParse({...u,id:l});if(!u||p.success===!1)throw b.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`);let R=await e.context.internalAdapter.findUserByEmail(u.email,{includeAccounts:!0}).catch(f=>{throw b.error(`Better auth was unable to query your database.
|
|
3
|
+
Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=R?.user.id;if(R){let f=R.accounts.find(O=>O.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,k=h?h.includes(t.id):!0;if(!f&&(!u.emailVerified||!k)){let O;try{O=new URL(n||o),O.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(O.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:u.id.toString(),id:`${t.id}:${u.id}`,userId:R.user.id,...ye(d)})}catch(O){throw console.log(O),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{let f=u.emailVerified,h=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:f},{...ye(d),id:`${t.id}:${u.id}`,providerId:t.id,accountId:u.id.toString()});if(!f&&h&&e.context.options.emailVerification?.sendOnSignUp){let k=await ce(e.context.secret,u.email),O=`${e.context.baseURL}/verify-email?token=${k}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(h.user,O,k)}}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.redirect(h.toString())}if(!m&&!l)throw new Kr("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let f=await e.context.internalAdapter.createSession(m||l,e.request);if(!f){let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_session"),e.redirect(h.toString())}try{await y(e,f.id)}catch(h){e.context.logger.error("Unable to set session cookie",h);let k=new URL(n||o);throw k.searchParams.set("error","unable_to_create_session"),e.redirect(k.toString())}}catch{let f=new URL(n||o||"");throw f.searchParams.set("error","unable_to_create_session"),e.redirect(f.toString())}throw e.redirect(o)});import{APIError as ve}from"better-call";var $=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Ut}from"zod";var Tt=()=>c("/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 Oe(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:$(e.context.sessionConfig.expiresIn,"sec")});if(!d)return Oe(e),e.json(null,{status:401});let u=(d.expiresAt.valueOf()-Date.now())/1e3;return await y(e,d.id,!1,{maxAge:u}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),V=async e=>await Tt()({...e,_flag:"json",headers:e.headers}),A=_(async e=>{let t=await V(e);if(!t?.session)throw new ve("UNAUTHORIZED");return{session:t}});var Gr=c("/user/revoke-session",{method:"POST",body:Ut.object({id:Ut.string()}),use:[A],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})}),Zr=c("/user/revoke-sessions",{method:"POST",use:[A],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})});import"zod";import{APIError as Yr}from"better-call";var Xr=c("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Yr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),Oe(e),e.json({success:!0})});import{z as ee}from"zod";import{APIError as Ne}from"better-call";var eo=c("/forget-password",{method:"POST",body:ee.object({email:ee.string().email(),redirectTo:ee.string()}),use:[C]},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 Ne("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})}),to=c("/reset-password/:token",{method:"GET",query:ee.object({callbackURL:ee.string()}),use:[C]},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}`)}),ro=c("/reset-password",{query:ee.object({token:ee.string()}).optional(),method:"POST",body:ee.object({newPassword:ee.string()})},async e=>{let t=e.query?.token;if(!t)throw new Ne("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 Ne("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 Ne("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{z as Q}from"zod";import{APIError as J}from"better-call";var oo=c("/user/update",{method:"POST",body:Q.object({name:Q.string().optional(),image:Q.string().optional()}),use:[A,C]},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})}),no=c("/user/change-password",{method:"POST",body:Q.object({newPassword:Q.string(),currentPassword:Q.string(),revokeOtherSessions:Q.boolean().optional()}),use:[A]},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 J("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 J("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 J("BAD_REQUEST",{message:"User does not have a password"});let u=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new J("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:u}),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 J("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await y(e,p.id)}return e.json(n.user)}),io=c("/user/set-password",{method:"POST",body:Q.object({newPassword:Q.string()}),use:[A]},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 J("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 J("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 J("BAD_REQUEST",{message:"user already has a password"})}),so=c("/user/delete",{method:"POST",body:Q.object({password:Q.string()}),use:[A]},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 J("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new J("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)});import{xchacha20poly1305 as Et}from"@noble/ciphers/chacha";import{bytesToHex as ao,hexToBytes as co,utf8ToBytes as uo}from"@noble/ciphers/utils";import{managedNonce as St}from"@noble/ciphers/webcrypto";import{sha256 as Pt}from"oslo/crypto";import{decodeHex as ma,encodeHex as fa}from"oslo/encoding";import{scryptAsync as wa}from"@noble/hashes/scrypt";async function W(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 Fe=async({key:e,data:t})=>{let r=await Pt(new TextEncoder().encode(e)),o=uo(t),n=St(Et)(new Uint8Array(r));return ao(n.encrypt(o))},Me=async({key:e,data:t})=>{let r=await Pt(new TextEncoder().encode(e)),o=co(t),n=St(Et)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var lo=c("/csrf",{method:"GET",metadata:ne},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=N(32,F("a-z","0-9","A-Z")),o=await W(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 po=(e="Unknown")=>`<!DOCTYPE html>
|
|
4
4
|
<html lang="en">
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="UTF-8">
|
|
@@ -80,5 +80,5 @@ Error: `,f),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>`,po=c("/error",{method:"GET",metadata:ie},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(lo(t),{headers:{"Content-Type":"text/html"}})});var mo=c("/ok",{method:"GET",metadata:ie},async e=>e.json({ok:!0}));import{z as be}from"zod";import{APIError as ue}from"better-call";var Ge=()=>c("/sign-up/email",{method:"POST",query:be.object({currentURL:be.string().optional()}).optional(),body:be.record(be.string(),be.any()),use:[C]},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(!be.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let u=e.context.password.config.minPasswordLength;if(n.length<u)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 R=vt(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...R,emailVerified:!1});if(!m)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:$(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let k=await ce(e.context.secret,m.email),O=`${e.context.baseURL}/verify-email?token=${k}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(m,O,k)}if(!e.context.options.emailAndPassword.autoSignIn)return e.json({user:m,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:null}});let h=await e.context.internalAdapter.createSession(m.id,e.request);if(!h)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await y(e,h.id),e.json({user:m,session:h},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:h}})});var _t=(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 Dt={};hr(Dt,{AccessControl:()=>ve,ParsingError:()=>le,Role:()=>Ae,adminAc:()=>Bt,createAccessControl:()=>Ct,defaultAc:()=>qe,defaultRoles:()=>Ze,defaultStatements:()=>zt,memberAc:()=>xt,ownerAc:()=>Lt,permissionFromString:()=>fo});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},ve=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new Ae(t)}},Ae=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 Ct=e=>new ve(e),zt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},qe=Ct(zt),Bt=qe.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),Lt=qe.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),xt=qe.newRole({organization:[],member:[],invitation:[]}),Ze={admin:Bt,owner:Lt,member:xt};var fo=e=>Ae.fromString(e??"");var E=(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:P(),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=await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{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},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=await e.findOne({model:"organization",where:[{field:"id",value:r}]});if(!n)return null;let i=await e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),a=await e.findMany({model:"member",where:[{field:"organizationId",value:r}]}),s=await Promise.all(a.map(async u=>{let l=await e.findOne({model:"user",where:[{field:"id",value:u.userId}]});if(!l)throw new F("Unexpected error: User not found for member");return{...u,user:{id:l.id,name:l.name,email:l.email,image:l.image}}}));return{...n,invitations:i,members:s}},listOrganizations:async r=>{let n=(await e.findMany({model:"member",where:[{field:"userId",value:r}]}))?.map(a=>a.organizationId);if(!n)return[];let i=[];for(let a of n){let s=await e.findOne({model:"organization",where:[{field:"id",value:a}]});s&&i.push(s)}return i},createInvitation:async({invitation:r,user:o})=>{let i=$(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:P(),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 Bd,createRouter as Ld}from"better-call";import{APIError as Ye}from"better-call";import{z as jt}from"zod";var go=_({body:jt.object({csrfToken:jt.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 Ye("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||!o||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await W(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as se}from"better-call";var B=_(async e=>({})),x=_({use:[A]},async e=>({session:e.context.session}));import{z as M}from"zod";import{z as v}from"zod";var $e=v.enum(["admin","member","owner"]),ho=v.enum(["pending","accepted","rejected","canceled"]).default("pending"),nc=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()}),ic=v.object({id:v.string(),email:v.string(),organizationId:v.string(),userId:v.string(),role:$e,createdAt:v.date()}),sc=v.object({id:v.string(),organizationId:v.string(),email:v.string(),role:$e,status:ho,inviterId:v.string(),expiresAt:v.date()});import{APIError as T}from"better-call";var Nt=c("/organization/invite-member",{method:"POST",use:[B,x],body:M.object({email:M.string(),role:$e,organizationId:M.string().optional(),resend:M.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw b.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new T("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new T("BAD_REQUEST",{message:"Organization not found"});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new T("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new T("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new T("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 T("BAD_REQUEST",{message:"User is already invited to this organization"});let u=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 T("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:u.id,role:u.role,email:u.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(u)}),Ft=c("/organization/accept-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("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:P(),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!"}})}),Mt=c("/organization/reject-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("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})}),qt=c("/organization/cancel-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new T("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new T("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)}),$t=c("/organization/get-invitation",{method:"GET",use:[B],requireHeaders:!0,query:M.object({id:M.string()})},async e=>{let t=await V(e);if(!t)throw new T("UNAUTHORIZED",{message:"Not authenticated"});let r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new T("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new T("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 Ue}from"better-call";var Vt=c("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[B,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=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ue("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ue("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 Ue("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ue("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let u=null;if(e.body.memberIdOrEmail.includes("@")?u=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):u=await o.findMemberById(e.body.memberIdOrEmail),u?.organizationId!==r)throw new Ue("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(u.id),t.user.id===u.userId&&t.session.activeOrganizationId===u.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:u})}),Qt=c("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[B,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=E(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 S}from"zod";import{APIError as me}from"better-call";var Wt=c("/organization/create",{method:"POST",body:S.object({name:S.string(),slug:S.string(),userId:S.string().optional(),logo:S.string().optional(),metadata:S.record(S.string()).optional()}),use:[B,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=E(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:P(),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)}),Ht=c("/organization/update",{method:"POST",body:S.object({data:S.object({name:S.string().optional(),slug:S.string().optional()}).partial(),orgId:S.string().optional()}),requireHeaders:!0,use:[B]},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=E(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)}),Kt=c("/organization/delete",{method:"POST",body:S.object({orgId:S.string()}),requireHeaders:!0,use:[B]},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=E(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)}),Jt=c("/organization/get-full",{method:"GET",query:S.object({orgId:S.string().optional()}),requireHeaders:!0,use:[B,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 E(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)}),Gt=c("/organization/activate",{method:"POST",body:S.object({orgId:S.string().nullable().optional()}),use:[x,B]},async e=>{let t=E(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)}),Zt=c("/organization/list",{method:"GET",use:[B,x]},async e=>{let r=await E(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var qc=e=>{let t={createOrganization:Wt,updateOrganization:Ht,deleteOrganization:Kt,setActiveOrganization:Gt,getFullOrganization:Jt,listOrganization:Zt,createInvitation:Nt,cancelInvitation:qt,acceptInvitation:Ft,getInvitation:$t,rejectInvitation:Mt,removeMember:Vt,updateMemberRole:Qt},r={...Ze,...e?.roles};return{id:"organization",endpoints:{..._t(t,{orgOptions:e||{},roles:r,getSession:async n=>await V(n)}),hasPermission:c("/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 Yt("BAD_REQUEST",{message:"No active organization"});let a=await E(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Yt("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 He}from"zod";import{z as Se}from"zod";import{APIError as fe}from"better-call";var Ve="two-factor";var Qe="trust-device";import{z as Xt}from"zod";var ge=_({body:Xt.object({trustDevice:Xt.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(Ve),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 W(e.context.secret,s.id),u=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!u)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await y(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await W(e.context.secret,`${u.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:u})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:u}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Ee}from"better-call";function wo(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>j(e?.length??10,N("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function Xe(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():wo(),n=await Fe({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function yo(e,t){let r=await er(e.backupCodes,t);return r?r.includes(e.code):!1}async function er(e,t){let r=Buffer.from(await Me({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Se.array(Se.string()).safeParse(o);return n.success?n.data:null}var tr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:c("/two-factor/verify-backup-code",{method:"POST",body:Se.object({code:Se.string(),disableSession:Se.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 Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!yo({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Ee("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await y(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:c("/two-factor/generate-backup-codes",{method:"POST",use:[A]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Ee("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await Xe(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:c("/view/backup-codes",{method:"GET",use:[A]},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 Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=er(n.backupCodes,r.context.secret);if(!i)throw new Ee("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 bo}from"oslo/otp";import{z as rr}from"zod";import{TimeSpan as Ao}from"oslo";var or=(e,t)=>{let r={...e,period:new Ao(e?.period||3,"m")},o=new bo({digits:6,period:r.period}),n=c("/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 u=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,u),a.json({status:!0})}),i=c("/two-factor/verify-otp",{method:"POST",body:rr.object({code:rr.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 ke}from"better-call";import{TimeSpan as ko}from"oslo";import{TOTPController as nr,createTOTPKeyURI as Ro}from"oslo/otp";import{z as ir}from"zod";var sr=(e,t)=>{let r={...e,digits:6,period:new ko(e?.period||30,"s")},o=c("/totp/generate",{method:"POST",use:[A]},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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new nr(r).generate(Buffer.from(d.secret))}}),n=c("/two-factor/get-totp-uri",{method:"GET",use:[A]},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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Ro(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=c("/two-factor/verify-totp",{method:"POST",body:ir.object({code:ir.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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});let u=new nr(r),l=await Me({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await u.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function et(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 ar}from"better-call";var Uu=(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 Nu=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=sr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=tr({...e?.backupCodeOptions},t.twoFactorTable),n=or({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:c("/two-factor/enable",{method:"POST",body:He.object({password:He.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new ar("BAD_REQUEST",{message:"Invalid password"});let u=j(16,N("a-z","0-9","-")),l=await Fe({key:i.context.secret,data:u}),p=await Xe(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:c("/two-factor/disable",{method:"POST",body:He.object({password:He.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new ar("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:_(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}),u=await i.getSignedCookie(d.name,i.context.secret);if(u){let[m,f]=u.split("!"),h=await W(i.context.secret,`${s.user.id}!${f}`);if(m===h){let k=await W(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${k}!${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 W(i.context.secret,s.session.id),p=i.context.createAuthCookie(Ve,{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 Po,generateRegistrationOptions as _o,verifyAuthenticationResponse as Co,verifyRegistrationResponse as zo}from"@simplewebauthn/server";import{APIError as G}from"better-call";import{z as te}from"zod";import{WebAuthnError as vo,startAuthentication as Uo,startRegistration as To}from"@simplewebauthn/browser";import{createFetch as Zu}from"@better-fetch/fetch";import"nanostores";import{betterFetch as $u}from"@better-fetch/fetch";import{atom as dl}from"nanostores";import"@better-fetch/fetch";import{atom as Oo,onMount as Io}from"nanostores";var tt=(e,t,r,o)=>{let n=Oo({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 u=n.get();n.set({isPending:u.data===null,data:u.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():Io(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as Eo}from"nanostores";var So=(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 Uo(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 To(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 vo?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:{}}),Tl=()=>{let e=Eo();return{id:"passkey",$InferServerPlugin:{},getActions:t=>So(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:tt(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 Nl=e=>{let t=process.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new F("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:c("/passkey/generate-register-options",{method:"GET",use:[A],metadata:{client:!1}},async s=>{let d=s.context.session,u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(j(32,N("a-z","0-9")))),p;p=await _o({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let R=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,R,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:R,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:c("/passkey/generate-authenticate-options",{method:"POST",body:te.object({email:te.string().optional()}).optional()},async s=>{let d=await V(s),u=[];d&&(u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await Po({rpID:o.rpID,userVerification:"preferred",...u.length?{allowCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},R=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,R,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:R,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:c("/passkey/verify-registration",{method:"POST",body:te.object({response:te.any(),name:te.string().optional()}),use:[A]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:R,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new G("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let f=await zo({response:u,expectedChallenge:R,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:h,registrationInfo:k}=f;if(!h||!k)return s.json(null,{status:400});let{credentialID:O,credentialPublicKey:X,counter:oe,credentialDeviceType:I,credentialBackedUp:D}=k,ne=Buffer.from(X).toString("base64"),L=P(),Ce={name:s.body.name,userId:m.id,webauthnUserID:L,id:O,publicKey:ne,counter:oe,deviceType:I,transports:u.response.transports.join(","),backedUp:D,createdAt:new Date},fr=await s.context.adapter.create({model:"passkey",data:Ce});return s.json(fr,{status:200})}catch(f){throw console.log(f),new G("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:c("/passkey/verify-authentication",{method:"POST",body:te.object({response:te.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new G("BAD_REQUEST",{message:"origin missing"});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new G("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:R}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:u.id}]});if(!m)throw new G("UNAUTHORIZED",{message:"Passkey not found"});try{let f=await Co({response:u,expectedChallenge:R,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:m.id,credentialPublicKey:new Uint8Array(Buffer.from(m.publicKey,"base64")),counter:m.counter,transports:m.transports?.split(",")}}),{verified:h}=f;if(!h)throw new G("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:m.id}],update:{counter:f.authenticationInfo.newCounter}});let k=await s.context.internalAdapter.createSession(m.userId,s.request);if(!k)throw new G("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await y(s,k.id),s.json({session:k},{status:200})}catch(f){throw s.context.logger.error(f),new G("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:c("/passkey/list-user-passkeys",{method:"GET",use:[A]},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:c("/passkey/delete-passkey",{method:"POST",body:te.object({id:te.string()}),use:[A]},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 Z}from"zod";import{APIError as Ke}from"better-call";var dr=()=>({id:"username",endpoints:{signInUsername:c("/sign-in/username",{method:"POST",body:Z.object({username:Z.string(),password:Z.string(),dontRememberMe:Z.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:dr}),new Ke("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 Ke("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:dr}),new Ke("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Ke("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:c("/sign-up/username",{method:"POST",body:Z.object({username:Z.string().min(3).max(20),name:Z.string(),email:Z.string().email(),password:Z.string(),image:Z.string().optional()})},async e=>{let t=await Ge()({...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 Bo}from"better-call";var Kl=()=>({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 Bo("",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 Re}from"zod";import{APIError as Lo}from"better-call";var rp=e=>({id:"magic-link",endpoints:{signInMagicLink:c("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Re.object({email:Re.string().email(),callbackURL:Re.string().optional()}),use:[C]},async t=>{let{email:r}=t.body,o=j(32,N("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 Lo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:c("/magic-link/verify",{method:"GET",query:Re.object({token:Re.string(),callbackURL:Re.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,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let u=await t.context.internalAdapter.createSession(d,t.headers);if(!u)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await y(t,u.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 ae}from"better-call";function xo(e){return j(e,N("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:c("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw b.warn("sendOTP not implemented"),new ae("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=xo(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:$(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:c("/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 ae("BAD_REQUEST",{message:"OTP expired"})):new ae("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ae("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let a=await V(r);if(!a)throw new ae("UNAUTHORIZED",{message:"Session not found"});let s=await r.context.internalAdapter.updateUser(a.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:s,session:a.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(!n)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 ae("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ae("BAD_REQUEST",{message:"Phone number not found"});let i=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});if(!r.body.disableSession){let a=await r.context.internalAdapter.createSession(n.id,r.request);if(!a)throw new ae("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await y(r,a.id),r.json({user:i,session:a})}return r.json({user:i,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 rt}from"zod";var bp=e=>({id:"anonymous",endpoints:{signInAnonymous:c("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=ut(t.context.baseURL)}=e||{},o=P(),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 y(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:c("/user/link-anonymous",{method:"POST",body:rt.object({email:rt.string().email().optional(),password:rt.string().min(6)}),use:[A]},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 y(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 g}from"zod";var Y=_(async e=>{let t=await V(e);if(!t?.session)throw new se("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new se("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),vp=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:_(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:c("/admin/set-role",{method:"POST",body:g.object({userId:g.string(),role:g.string()}),use:[Y]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:c("/admin/create-user",{method:"POST",body:g.object({email:g.string(),password:g.string(),name:g.string(),role:g.string(),data:g.optional(g.record(g.any()))}),use:[Y]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new se("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 se("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:c("/admin/list-users",{method:"GET",use:[Y],query:g.object({limit:g.string().or(g.number()).optional(),offset:g.string().or(g.number()).optional(),sortBy:g.string().optional(),sortDirection:g.enum(["asc","desc"]).optional()})},async t=>{let r=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);return t.json({users:r})}),listUserSessions:c("/admin/list-user-sessions",{method:"POST",use:[Y],body:g.object({userId:g.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:c("/admin/unban-user",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:c("/admin/ban-user",{method:"POST",body:g.object({userId:g.string(),banReason:g.string().optional(),banExpiresIn:g.number().optional()}),use:[Y]},async t=>{if(t.body.userId===t.context.session.user.id)throw new se("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:c("/admin/impersonate-user",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new se("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?$(e.impersonationSessionDuration,"sec"):$(60*60,"sec")});if(!o)throw new se("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await y(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:c("/admin/revoke-user-session",{method:"POST",body:g.object({sessionId:g.string()}),use:[Y]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:c("/admin/revoke-user-sessions",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:c("/admin/remove-user",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},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,references:{model:"user",field:"id"}}}}}});import{z as re}from"zod";import{APIError as Pe}from"better-call";import{betterFetch as ot}from"@better-fetch/fetch";import{generateCodeVerifier as Do}from"oslo/oauth2";import{parseJWT as jo}from"oslo/jwt";async function No(e,t,r){if(t==="oidc"&&e.idToken){let n=jo(e.idToken);if(n?.payload)return n.payload}return r?(await ot(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var qp=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:c("/sign-in/oauth2",{method:"POST",query:re.object({currentURL:re.string().optional()}).optional(),body:re.object({providerId:re.string(),callbackURL:re.string().optional()}),use:[C]},async t=>{let{providerId:r}=t.body,o=e.config.find(L=>L.providerId===r);if(!o)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:u,redirectURI:l,responseType:p,pkce:R,prompt:m,accessType:f}=o,h=i,k=a;if(n){let L=await ot(n,{onError(Ce){b.error(Ce.error,{discoveryUrl:n})}});L.data&&(h=L.data.authorization_endpoint,k=L.data.token_endpoint)}if(!h||!k)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let O=t.query?.currentURL?new URL(t.query?.currentURL):null,X=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${O?.origin}${t.body.callbackURL||""}`,oe=await Le(X||O?.origin||t.context.options.baseURL),I=t.context.authCookies;await t.setSignedCookie(I.state.name,oe.hash,t.context.secret,I.state.options);let D=Do();await t.setSignedCookie(I.pkCodeVerifier.name,D,t.context.secret,I.pkCodeVerifier.options);let ne=await z({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:h,state:oe.raw,codeVerifier:D,scopes:u||[],disablePkce:!R,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ne.searchParams.set("response_type",p),m&&ne.searchParams.set("prompt",m),f&&ne.searchParams.set("access_type",f),{url:ne.toString(),state:oe,codeVerifier:D,redirect:!0}}),oAuth2Callback:c("/oauth2/callback/:providerId",{method:"GET",query:re.object({code:re.string().optional(),error:re.string().optional(),state:re.string()})},async t=>{if(t.query.error||!t.query.code){let D=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${D}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(I=>I.providerId===t.params.providerId);if(!r)throw new Pe("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,u=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 b.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await ze(a,p))throw b.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,f=r.userInfoUrl;if(r.discoveryUrl){let I=await ot(r.discoveryUrl,{method:"GET"});I.data&&(m=I.data.token_endpoint,f=I.data.userinfo_endpoint)}try{if(!m)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await U({code:u,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:m})}catch(I){throw t.context.logger.error(I),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let h=r.getUserInfo?await r.getUserInfo(n):await No(n,r.type||"oauth2",f),k=P(),O=h?De.safeParse({...h,id:k}):null;if(!O?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let X=await t.context.internalAdapter.findUserByEmail(O.data.email).catch(I=>{throw b.error(`Better auth was unable to query your database.
|
|
84
|
-
Error: `,
|
|
83
|
+
</html>`,mo=c("/error",{method:"GET",metadata:ne},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(po(t),{headers:{"Content-Type":"text/html"}})});var fo=c("/ok",{method:"GET",metadata:ne},async e=>e.json({ok:!0}));import{z as be}from"zod";import{APIError as ue}from"better-call";var Ge=()=>c("/sign-up/email",{method:"POST",query:be.object({currentURL:be.string().optional()}).optional(),body:be.record(be.string(),be.any()),use:[C]},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(!be.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let u=e.context.password.config.minPasswordLength;if(n.length<u)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 R=It(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...R,emailVerified:!1});if(!m)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:$(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let k=await ce(e.context.secret,m.email),O=`${e.context.baseURL}/verify-email?token=${k}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(m,O,k)}if(!e.context.options.emailAndPassword.autoSignIn)return e.json({user:m,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:null}});let h=await e.context.internalAdapter.createSession(m.id,e.request);if(!h)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await y(e,h.id),e.json({user:m,session:h},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:h}})});var _t=(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 Dt={};hr(Dt,{AccessControl:()=>Ie,ParsingError:()=>le,Role:()=>Ae,adminAc:()=>Bt,createAccessControl:()=>Ct,defaultAc:()=>qe,defaultRoles:()=>Ze,defaultStatements:()=>zt,memberAc:()=>xt,ownerAc:()=>Lt,permissionFromString:()=>go});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 Ae(t)}},Ae=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 Ct=e=>new Ie(e),zt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},qe=Ct(zt),Bt=qe.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),Lt=qe.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),xt=qe.newRole({organization:[],member:[],invitation:[]}),Ze={admin:Bt,owner:Lt,member:xt};var go=e=>Ae.fromString(e??"");var E=(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:P(),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=await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{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},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=await e.findOne({model:"organization",where:[{field:"id",value:r}]});if(!n)return null;let i=await e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),a=await e.findMany({model:"member",where:[{field:"organizationId",value:r}]}),s=await Promise.all(a.map(async u=>{let l=await e.findOne({model:"user",where:[{field:"id",value:u.userId}]});if(!l)throw new j("Unexpected error: User not found for member");return{...u,user:{id:l.id,name:l.name,email:l.email,image:l.image}}}));return{...n,invitations:i,members:s}},listOrganizations:async r=>{let n=(await e.findMany({model:"member",where:[{field:"userId",value:r}]}))?.map(a=>a.organizationId);if(!n)return[];let i=[];for(let a of n){let s=await e.findOne({model:"organization",where:[{field:"id",value:a}]});s&&i.push(s)}return i},createInvitation:async({invitation:r,user:o})=>{let i=$(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:P(),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 jd,createRouter as Nd}from"better-call";import{APIError as Ye}from"better-call";import{z as jt}from"zod";var ho=_({body:jt.object({csrfToken:jt.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 Ye("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||!o||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await W(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as ie}from"better-call";var B=_(async e=>({})),x=_({use:[A]},async e=>({session:e.context.session}));import{z as M}from"zod";import{z as I}from"zod";var $e=I.enum(["admin","member","owner"]),wo=I.enum(["pending","accepted","rejected","canceled"]).default("pending"),dc=I.object({id:I.string(),name:I.string(),slug:I.string(),logo:I.string().optional(),metadata:I.record(I.string()).or(I.string().transform(e=>JSON.parse(e))).optional(),createdAt:I.date()}),cc=I.object({id:I.string(),email:I.string(),organizationId:I.string(),userId:I.string(),role:$e,createdAt:I.date()}),uc=I.object({id:I.string(),organizationId:I.string(),email:I.string(),role:$e,status:wo,inviterId:I.string(),expiresAt:I.date()});import{APIError as T}from"better-call";var Nt=c("/organization/invite-member",{method:"POST",use:[B,x],body:M.object({email:M.string(),role:$e,organizationId:M.string().optional(),resend:M.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw b.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new T("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new T("BAD_REQUEST",{message:"Organization not found"});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new T("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new T("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new T("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 T("BAD_REQUEST",{message:"User is already invited to this organization"});let u=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 T("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:u.id,role:u.role,email:u.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(u)}),Ft=c("/organization/accept-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("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:P(),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!"}})}),Mt=c("/organization/reject-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("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})}),qt=c("/organization/cancel-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new T("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new T("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)}),$t=c("/organization/get-invitation",{method:"GET",use:[B],requireHeaders:!0,query:M.object({id:M.string()})},async e=>{let t=await V(e);if(!t)throw new T("UNAUTHORIZED",{message:"Not authenticated"});let r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new T("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new T("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 Ue}from"better-call";var Vt=c("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[B,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=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ue("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ue("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 Ue("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ue("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let u=null;if(e.body.memberIdOrEmail.includes("@")?u=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):u=await o.findMemberById(e.body.memberIdOrEmail),u?.organizationId!==r)throw new Ue("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(u.id),t.user.id===u.userId&&t.session.activeOrganizationId===u.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:u})}),Qt=c("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[B,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=E(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 S}from"zod";import{APIError as me}from"better-call";var Wt=c("/organization/create",{method:"POST",body:S.object({name:S.string(),slug:S.string(),userId:S.string().optional(),logo:S.string().optional(),metadata:S.record(S.string()).optional()}),use:[B,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=E(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:P(),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)}),Ht=c("/organization/update",{method:"POST",body:S.object({data:S.object({name:S.string().optional(),slug:S.string().optional()}).partial(),orgId:S.string().optional()}),requireHeaders:!0,use:[B]},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=E(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)}),Kt=c("/organization/delete",{method:"POST",body:S.object({orgId:S.string()}),requireHeaders:!0,use:[B]},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=E(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)}),Jt=c("/organization/get-full",{method:"GET",query:S.object({orgId:S.string().optional()}),requireHeaders:!0,use:[B,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 E(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)}),Gt=c("/organization/activate",{method:"POST",body:S.object({orgId:S.string().nullable().optional()}),use:[x,B]},async e=>{let t=E(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)}),Zt=c("/organization/list",{method:"GET",use:[B,x]},async e=>{let r=await E(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var Wc=e=>{let t={createOrganization:Wt,updateOrganization:Ht,deleteOrganization:Kt,setActiveOrganization:Gt,getFullOrganization:Jt,listOrganization:Zt,createInvitation:Nt,cancelInvitation:qt,acceptInvitation:Ft,getInvitation:$t,rejectInvitation:Mt,removeMember:Vt,updateMemberRole:Qt},r={...Ze,...e?.roles};return{id:"organization",endpoints:{..._t(t,{orgOptions:e||{},roles:r,getSession:async n=>await V(n)}),hasPermission:c("/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 Yt("BAD_REQUEST",{message:"No active organization"});let a=await E(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Yt("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 He}from"zod";import{z as Se}from"zod";import{APIError as fe}from"better-call";var Ve="two-factor";var Qe="trust-device";import{z as Xt}from"zod";var ge=_({body:Xt.object({trustDevice:Xt.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(Ve),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 W(e.context.secret,s.id),u=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!u)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await y(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await W(e.context.secret,`${u.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:u})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:u}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Ee}from"better-call";function yo(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>N(e?.length??10,F("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function Xe(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():yo(),n=await Fe({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function bo(e,t){let r=await er(e.backupCodes,t);return r?r.includes(e.code):!1}async function er(e,t){let r=Buffer.from(await Me({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Se.array(Se.string()).safeParse(o);return n.success?n.data:null}var tr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:c("/two-factor/verify-backup-code",{method:"POST",body:Se.object({code:Se.string(),disableSession:Se.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 Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!bo({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Ee("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await y(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:c("/two-factor/generate-backup-codes",{method:"POST",use:[A]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Ee("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await Xe(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:c("/view/backup-codes",{method:"GET",use:[A]},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 Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=er(n.backupCodes,r.context.secret);if(!i)throw new Ee("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 Ao}from"oslo/otp";import{z as rr}from"zod";import{TimeSpan as ko}from"oslo";var or=(e,t)=>{let r={...e,period:new ko(e?.period||3,"m")},o=new Ao({digits:6,period:r.period}),n=c("/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 u=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,u),a.json({status:!0})}),i=c("/two-factor/verify-otp",{method:"POST",body:rr.object({code:rr.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 ke}from"better-call";import{TimeSpan as Ro}from"oslo";import{TOTPController as nr,createTOTPKeyURI as Oo}from"oslo/otp";import{z as ir}from"zod";var sr=(e,t)=>{let r={...e,digits:6,period:new Ro(e?.period||30,"s")},o=c("/totp/generate",{method:"POST",use:[A]},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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new nr(r).generate(Buffer.from(d.secret))}}),n=c("/two-factor/get-totp-uri",{method:"GET",use:[A]},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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Oo(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=c("/two-factor/verify-totp",{method:"POST",body:ir.object({code:ir.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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});let u=new nr(r),l=await Me({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await u.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function et(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 ar}from"better-call";var Pu=(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 $u=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=sr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=tr({...e?.backupCodeOptions},t.twoFactorTable),n=or({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:c("/two-factor/enable",{method:"POST",body:He.object({password:He.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new ar("BAD_REQUEST",{message:"Invalid password"});let u=N(16,F("a-z","0-9","-")),l=await Fe({key:i.context.secret,data:u}),p=await Xe(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:c("/two-factor/disable",{method:"POST",body:He.object({password:He.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new ar("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:_(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}),u=await i.getSignedCookie(d.name,i.context.secret);if(u){let[m,f]=u.split("!"),h=await W(i.context.secret,`${s.user.id}!${f}`);if(m===h){let k=await W(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${k}!${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 W(i.context.secret,s.session.id),p=i.context.createAuthCookie(Ve,{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 _o,generateRegistrationOptions as Co,verifyAuthenticationResponse as zo,verifyRegistrationResponse as Bo}from"@simplewebauthn/server";import{APIError as G}from"better-call";import{z as te}from"zod";import{WebAuthnError as Uo,startAuthentication as To,startRegistration as Eo}from"@simplewebauthn/browser";import{createFetch as tl}from"@better-fetch/fetch";import"nanostores";import{betterFetch as Hu}from"@better-fetch/fetch";import{atom as pl}from"nanostores";import"@better-fetch/fetch";import{atom as vo,onMount as Io}from"nanostores";var tt=(e,t,r,o)=>{let n=vo({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 u=n.get();n.set({isPending:u.data===null,data:u.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():Io(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as So}from"nanostores";var Po=(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 To(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 Eo(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 Uo?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:{}}),_l=()=>{let e=So();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Po(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:tt(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 $l=e=>{let t=process.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new j("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:c("/passkey/generate-register-options",{method:"GET",use:[A],metadata:{client:!1}},async s=>{let d=s.context.session,u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(N(32,F("a-z","0-9")))),p;p=await Co({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let R=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,R,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:R,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:c("/passkey/generate-authenticate-options",{method:"POST",body:te.object({email:te.string().optional()}).optional()},async s=>{let d=await V(s),u=[];d&&(u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await _o({rpID:o.rpID,userVerification:"preferred",...u.length?{allowCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},R=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,R,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:R,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:c("/passkey/verify-registration",{method:"POST",body:te.object({response:te.any(),name:te.string().optional()}),use:[A]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:R,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new G("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let f=await Bo({response:u,expectedChallenge:R,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:h,registrationInfo:k}=f;if(!h||!k)return s.json(null,{status:400});let{credentialID:O,credentialPublicKey:X,counter:ae,credentialDeviceType:v,credentialBackedUp:D}=k,oe=Buffer.from(X).toString("base64"),L=P(),Ce={name:s.body.name,userId:m.id,webauthnUserID:L,id:O,publicKey:oe,counter:ae,deviceType:v,transports:u.response.transports.join(","),backedUp:D,createdAt:new Date},fr=await s.context.adapter.create({model:"passkey",data:Ce});return s.json(fr,{status:200})}catch(f){throw console.log(f),new G("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:c("/passkey/verify-authentication",{method:"POST",body:te.object({response:te.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new G("BAD_REQUEST",{message:"origin missing"});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new G("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:R}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:u.id}]});if(!m)throw new G("UNAUTHORIZED",{message:"Passkey not found"});try{let f=await zo({response:u,expectedChallenge:R,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:m.id,credentialPublicKey:new Uint8Array(Buffer.from(m.publicKey,"base64")),counter:m.counter,transports:m.transports?.split(",")}}),{verified:h}=f;if(!h)throw new G("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:m.id}],update:{counter:f.authenticationInfo.newCounter}});let k=await s.context.internalAdapter.createSession(m.userId,s.request);if(!k)throw new G("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await y(s,k.id),s.json({session:k},{status:200})}catch(f){throw s.context.logger.error(f),new G("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:c("/passkey/list-user-passkeys",{method:"GET",use:[A]},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:c("/passkey/delete-passkey",{method:"POST",body:te.object({id:te.string()}),use:[A]},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 Z}from"zod";import{APIError as Ke}from"better-call";var dr=()=>({id:"username",endpoints:{signInUsername:c("/sign-in/username",{method:"POST",body:Z.object({username:Z.string(),password:Z.string(),dontRememberMe:Z.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:dr}),new Ke("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 Ke("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:dr}),new Ke("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Ke("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:c("/sign-up/username",{method:"POST",body:Z.object({username:Z.string().min(3).max(20),name:Z.string(),email:Z.string().email(),password:Z.string(),image:Z.string().optional()})},async e=>{let t=await Ge()({...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 Lo}from"better-call";var Yl=()=>({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 Lo("",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 Re}from"zod";import{APIError as xo}from"better-call";var sp=e=>({id:"magic-link",endpoints:{signInMagicLink:c("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Re.object({email:Re.string().email(),callbackURL:Re.string().optional()}),use:[C]},async t=>{let{email:r}=t.body,o=N(32,F("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 xo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:c("/magic-link/verify",{method:"GET",query:Re.object({token:Re.string(),callbackURL:Re.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 u=await t.context.internalAdapter.createSession(d,t.headers);if(!u)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await y(t,u.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 se}from"better-call";function Do(e){return N(e,F("0-9"))}var hp=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:c("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw b.warn("sendOTP not implemented"),new se("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Do(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:$(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:c("/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 se("BAD_REQUEST",{message:"OTP expired"})):new se("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new se("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let a=await V(r);if(!a)throw new se("UNAUTHORIZED",{message:"Session not found"});let s=await r.context.internalAdapter.updateUser(a.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:s,session:a.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(!n)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 se("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new se("BAD_REQUEST",{message:"Phone number not found"});let i=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});if(!r.body.disableSession){let a=await r.context.internalAdapter.createSession(n.id,r.request);if(!a)throw new se("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await y(r,a.id),r.json({user:i,session:a})}return r.json({user:i,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 rt}from"zod";var Op=e=>({id:"anonymous",endpoints:{signInAnonymous:c("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=ut(t.context.baseURL)}=e||{},o=P(),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 y(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:c("/user/link-anonymous",{method:"POST",body:rt.object({email:rt.string().email().optional(),password:rt.string().min(6)}),use:[A]},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 y(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 g}from"zod";var Y=_(async e=>{let t=await V(e);if(!t?.session)throw new ie("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new ie("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),Sp=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:_(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:c("/admin/set-role",{method:"POST",body:g.object({userId:g.string(),role:g.string()}),use:[Y]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:c("/admin/create-user",{method:"POST",body:g.object({email:g.string(),password:g.string(),name:g.string(),role:g.string(),data:g.optional(g.record(g.any()))}),use:[Y]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new ie("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 ie("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:c("/admin/list-users",{method:"GET",use:[Y],query:g.object({limit:g.string().or(g.number()).optional(),offset:g.string().or(g.number()).optional(),sortBy:g.string().optional(),sortDirection:g.enum(["asc","desc"]).optional()})},async t=>{let r=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);return t.json({users:r})}),listUserSessions:c("/admin/list-user-sessions",{method:"POST",use:[Y],body:g.object({userId:g.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:c("/admin/unban-user",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:c("/admin/ban-user",{method:"POST",body:g.object({userId:g.string(),banReason:g.string().optional(),banExpiresIn:g.number().optional()}),use:[Y]},async t=>{if(t.body.userId===t.context.session.user.id)throw new ie("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:c("/admin/impersonate-user",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new ie("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?$(e.impersonationSessionDuration,"sec"):$(60*60,"sec")});if(!o)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await y(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:c("/admin/revoke-user-session",{method:"POST",body:g.object({sessionId:g.string()}),use:[Y]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:c("/admin/revoke-user-sessions",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:c("/admin/remove-user",{method:"POST",body:g.object({userId:g.string()}),use:[Y]},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,references:{model:"user",field:"id"}}}}}});import{z as re}from"zod";import{APIError as Pe}from"better-call";import{betterFetch as ot}from"@better-fetch/fetch";import{generateCodeVerifier as jo}from"oslo/oauth2";import{parseJWT as No}from"oslo/jwt";async function Fo(e,t,r){if(t==="oidc"&&e.idToken){let n=No(e.idToken);if(n?.payload)return n.payload}return r?(await ot(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var Wp=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:c("/sign-in/oauth2",{method:"POST",query:re.object({currentURL:re.string().optional()}).optional(),body:re.object({providerId:re.string(),callbackURL:re.string().optional()}),use:[C]},async t=>{let{providerId:r}=t.body,o=e.config.find(L=>L.providerId===r);if(!o)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:u,redirectURI:l,responseType:p,pkce:R,prompt:m,accessType:f}=o,h=i,k=a;if(n){let L=await ot(n,{onError(Ce){b.error(Ce.error,{discoveryUrl:n})}});L.data&&(h=L.data.authorization_endpoint,k=L.data.token_endpoint)}if(!h||!k)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let O=t.query?.currentURL?new URL(t.query?.currentURL):null,X=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${O?.origin}${t.body.callbackURL||""}`,ae=await Le(X||O?.origin||t.context.options.baseURL),v=t.context.authCookies;await t.setSignedCookie(v.state.name,ae.hash,t.context.secret,v.state.options);let D=jo();await t.setSignedCookie(v.pkCodeVerifier.name,D,t.context.secret,v.pkCodeVerifier.options);let oe=await z({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:h,state:ae.raw,codeVerifier:D,scopes:u||[],disablePkce:!R,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&oe.searchParams.set("response_type",p),m&&oe.searchParams.set("prompt",m),f&&oe.searchParams.set("access_type",f),{url:oe.toString(),state:ae,codeVerifier:D,redirect:!0}}),oAuth2Callback:c("/oauth2/callback/:providerId",{method:"GET",query:re.object({code:re.string().optional(),error:re.string().optional(),state:re.string()})},async t=>{if(t.query.error||!t.query.code){let D=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${D}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(v=>v.providerId===t.params.providerId);if(!r)throw new Pe("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,u=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 b.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await ze(a,p))throw b.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,f=r.userInfoUrl;if(r.discoveryUrl){let v=await ot(r.discoveryUrl,{method:"GET"});v.data&&(m=v.data.token_endpoint,f=v.data.userinfo_endpoint)}try{if(!m)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await U({code:u,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:m})}catch(v){throw t.context.logger.error(v),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let h=r.getUserInfo?await r.getUserInfo(n):await Fo(n,r.type||"oauth2",f),k=P(),O=h?De.safeParse({...h,id:k}):null;if(!O?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let X=await t.context.internalAdapter.findUserByEmail(O.data.email).catch(v=>{throw b.error(`Better auth was unable to query your database.
|
|
84
|
+
Error: `,v),t.redirect(`${l}?error=internal_server_error`)}),ae=X?.user.id||k;if(X){let v=X.accounts.find(L=>L.providerId===r.providerId),D=t.context.options.account?.accountLinking?.trustedProviders,oe=D?D.includes(r.providerId):!0;if(!v&&(!O?.data.emailVerified||!oe)){let L;try{L=new URL(l),L.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(L.toString())}if(!v)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:O.data.id,id:`${r.providerId}:${O.data.id}`,userId:X.user.id,...ye(n)})}catch(L){throw console.log(L),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(O.data,{...ye(n),id:`${r.providerId}:${O.data.id}`,providerId:r.providerId,accountId:O.data.id})}catch{let D=new URL(l);throw D.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",D.toString()),t.redirect(D.toString())}try{let v=await t.context.internalAdapter.createSession(ae||k,t.request);if(!v)throw t.redirect(`${l}?error=unable_to_create_session`);await y(t,v.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var cr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},Jp=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var nt=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 mr,generateKeyPair as Qo,importJWK as Wo,SignJWT as Ho}from"jose";import{createCipheriv as Mo,createDecipheriv as qo,createHash as $o,randomBytes as Vo}from"crypto";function ur(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=$o("sha256").update(e).digest(),t}function lr(e,t){let r=ur(t),o=Vo(12),n=Mo("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 pr(e,t){let r=ur(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 u=d.update(o,"base64","utf8");return u+=d.final("utf8"),u}var im=e=>({id:"jwt",endpoints:{getJwks:c("/jwks",{method:"GET"},async t=>{let o=await nt(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:c("/token",{method:"GET",requireHeaders:!0,use:[A]},async t=>{let r=nt(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:u,privateKey:l}=await Qo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await mr(u),R=await mr(l),m=JSON.stringify(R),f={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(lr(m,t.context.options.secret)):m,createdAt:new Date};o=await r.createJwk(f)}let i=n?pr(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await Wo(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new Ho({...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:cr});export{ne as HIDE_METADATA,Dt as ac,Sp as admin,Y as adminMiddleware,Op as anonymous,Yl as bearer,c as createAuthEndpoint,_ as createAuthMiddleware,Wp as genericOAuth,Po as getPasskeyActions,im as jwt,sp as magicLink,st as optionsMiddleware,Wc as organization,$l as passkey,_l as passkeyClient,hp as phoneNumber,$u as twoFactor,Pu as twoFactorClient,dr as username};
|
package/dist/react.d.ts
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.js';
|
|
4
4
|
import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
|
|
5
5
|
import { useStore } from '@nanostores/react';
|
|
6
|
-
import './auth-
|
|
6
|
+
import './auth-C6fr77co.js';
|
|
7
7
|
import 'kysely';
|
|
8
8
|
import './schema-Dkt0LqYs.js';
|
|
9
9
|
import 'better-call';
|