better-auth 0.5.2-beta.15 → 0.5.2-beta.16
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/plugins.cjs +4 -4
- package/dist/plugins.js +4 -4
- package/package.json +1 -1
package/dist/plugins.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";var ct=Object.defineProperty;var oo=Object.getOwnPropertyDescriptor;var no=Object.getOwnPropertyNames;var io=Object.prototype.hasOwnProperty;var zt=(e,t)=>{for(var r in t)ct(e,r,{get:t[r],enumerable:!0})},so=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of no(t))!io.call(e,n)&&n!==r&&ct(e,n,{get:()=>t[n],enumerable:!(o=oo(t,n))||o.enumerable});return e};var ao=e=>so(ct({},"__esModule",{value:!0}),e);var cn={};zt(cn,{HIDE_METADATA:()=>se,ac:()=>At,admin:()=>on,adminMiddleware:()=>re,anonymous:()=>rn,bearer:()=>Yo,createAuthEndpoint:()=>u,createAuthMiddleware:()=>E,genericOAuth:()=>sn,getPasskeyActions:()=>Qr,jwt:()=>an,magicLink:()=>Xo,multiSession:()=>dn,optionsMiddleware:()=>ut,organization:()=>qo,passkey:()=>Zo,passkeyClient:()=>Go,phoneNumber:()=>tn,twoFactor:()=>Qo,twoFactorClient:()=>Ho,username:()=>Ct});module.exports=ao(cn);var Ot=require("better-call"),Ce=require("zod");var we=require("better-call"),ut=(0,we.createMiddleware)(async()=>({})),E=(0,we.createMiddlewareCreator)({use:[ut,(0,we.createMiddleware)(async()=>({}))]}),u=(0,we.createEndpointCreator)({use:[ut]});var J=require("better-call"),gr=require("oslo/oauth2"),q=require("zod");var Lt=require("oslo/oauth2"),xe=require("zod");var pt=require("oslo/crypto");function lt(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 Bt(e){let t=await(0,pt.sha256)(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function Ke(e,t){let r=await(0,pt.sha256)(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return lt(r,o)}var wn=require("better-call");async function Je(e){let t=(0,Lt.generateState)(),r=JSON.stringify({code:t,callbackURL:e}),o=await Bt(r);return{raw:r,hash:o}}function Ie(e){return xe.z.object({code:xe.z.string(),callbackURL:xe.z.string().optional(),currentURL:xe.z.string().optional()}).safeParse(JSON.parse(e))}var co=require("oslo");var H=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};var Dt=require("std-env");async function A(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function je(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function xt(e){let t=new Map;return e.split(", ").forEach(o=>{let[n,...i]=o.split("; "),[a,s]=n.split("="),d={value:s};i.forEach(c=>{let[l,p]=c.split("=");d[l.toLowerCase()]=p||!0}),t.set(a,d)}),t}function Ge(e){let t=e.split("; "),r=new Map;return t.forEach(o=>{let[n,i]=o.split("=");r.set(n,i)}),r}var Nt=require("better-call");var jt=require("consola"),ye=(0,jt.createConsola)({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),uo=e=>({log:(...t)=>{!e?.disabled&&ye.log("",...t)},error:(...t)=>{!e?.disabled&&ye.error("",...t)},warn:(...t)=>{!e?.disabled&&ye.warn("",...t)},info:(...t)=>{!e?.disabled&&ye.info("",...t)},debug:(...t)=>{!e?.disabled&&ye.debug("",...t)},box:(...t)=>{!e?.disabled&&ye.box("",...t)},success:(...t)=>{!e?.disabled&&ye.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
|
|
2
|
-
`)}}),b=uo();var P=E(async e=>{let{body:t,query:r,headers:o,context:n}=e,i=t?.callbackURL||r?.callbackURL||r?.redirectTo||t?.redirectTo,a=r?.currentURL||o?.get("referer")||n.baseURL,s=n.trustedOrigins,d=(c,l)=>{if(c?.startsWith("http")&&!s.some(g=>c.startsWith(g)))throw b.error(`Invalid ${l}`,{[l]:c,trustedOrigins:s}),new Nt.APIError("FORBIDDEN",{message:`Invalid ${l}`})};d(i,"callbackURL"),d(a,"currentURL")});var Qt=require("oslo/jwt");var Mt=require("oslo/crypto");var lo=require("std-env");function Ft(e){return new URL(e).origin.replace("http://","").replace("https://","")}var qt=require("oslo/encoding");async function $t(e){let t=await(0,Mt.sha256)(new TextEncoder().encode(e));return qt.base64url.encode(new Uint8Array(t),{includePadding:!1})}function Vt(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function B({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await $t(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,g)=>(p[g]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}var Ht=require("@better-fetch/fetch");async function T({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(0,Ht.betterFetch)(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 Vt(a)}function Ue(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var Wt=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})=>T({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=(0,Qt.parseJWT)(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};var Kt=require("@better-fetch/fetch");var Jt=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})=>T({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await(0,Kt.betterFetch)("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}}});var Gt=require("@better-fetch/fetch");var Zt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await B({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>T({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(0,Gt.betterFetch)("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}}});var mt=require("@better-fetch/fetch");var Yt=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let a=e.scope||o||["user:email"];return B({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>T({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await(0,mt.betterFetch)("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await(0,mt.betterFetch)("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};var Xt=require("oslo/jwt");var er=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 H("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new H("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return B({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>T({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=(0,Xt.parseJWT)(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});var tr=require("@better-fetch/fetch"),rr=require("oslo/jwt");var or=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=e.scope||n.scopes||["openid","profile","email","User.Read"];return B({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return T({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=(0,rr.parseJWT)(n.idToken)?.payload,a=e.profilePhotoSize||48;return await(0,tr.betterFetch)(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){b.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};var nr=require("@better-fetch/fetch");var ir=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return B({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>T({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(0,nr.betterFetch)("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}}});var ki=require("@better-fetch/fetch");var se={isAction:!1};function po(e){return e.toString(2).padStart(8,"0")}function mo(e){return[...e].map(t=>po(t)).join("")}function sr(e){return parseInt(mo(e),2)}function fo(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=sr(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=sr(o);return n}function Q(e,t){let r="";for(let o=0;o<e;o++)r+=t[fo(t.length)];return r}function W(...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 ar=require("nanoid"),_=e=>(0,ar.nanoid)(e);var dr=require("oslo/jwt");var cr=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return B({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>T({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=(0,dr.parseJWT)(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});var ur=require("@better-fetch/fetch");var lr=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return B({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>T({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(0,ur.betterFetch)("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 go={apple:Wt,discord:Jt,facebook:Zt,github:Yt,microsoft:or,google:er,spotify:ir,twitch:cr,twitter:lr},pr=Object.keys(go);var fr=require("oslo"),Ze=require("oslo/jwt"),K=require("zod");var be=require("better-call");var Ee=require("better-call");var Z=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));var ft=require("zod"),mr=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return je(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:Z(e.context.sessionConfig.expiresIn,"sec")});if(!d)return je(e),e.json(null,{status:401});let c=(d.expiresAt.valueOf()-Date.now())/1e3;return await A(e,d.id,!1,{maxAge:c}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),M=async e=>await mr()({...e,_flag:"json",headers:e.headers}),w=E(async e=>{let t=await M(e);if(!t?.session)throw new Ee.APIError("UNAUTHORIZED");return{session:t}});var ho=u("/user/revoke-session",{method:"POST",body:ft.z.object({id:ft.z.string()}),use:[w],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Ee.APIError("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Ee.APIError("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Ee.APIError("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),wo=u("/user/revoke-sessions",{method:"POST",use:[w],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Ee.APIError("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function ae(e,t,r){return await(0,Ze.createJWT)("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new fr.TimeSpan(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var yo=u("/send-verification-email",{method:"POST",query:K.z.object({currentURL:K.z.string().optional()}).optional(),body:K.z.object({email:K.z.string().email(),callbackURL:K.z.string().optional()}),use:[P]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be.APIError("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be.APIError("BAD_REQUEST",{message:"User not found"});let o=await ae(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})}),bo=u("/verify-email",{method:"GET",query:K.z.object({token:K.z.string(),callbackURL:K.z.string().optional()}),use:[P]},async e=>{let{token:t}=e.query,r;try{r=await(0,Ze.validateJWT)("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be.APIError("BAD_REQUEST",{message:"Invalid token"})}let n=K.z.object({email:K.z.string().email(),updateTo:K.z.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be.APIError("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await M(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be.APIError("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be.APIError("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Ao=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:q.z.object({currentURL:q.z.string().optional()}).optional(),body:q.z.object({callbackURL:q.z.string().optional(),provider:q.z.enum(pr)}),use:[P]},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 J.APIError("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 Je(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=(0,gr.generateCodeVerifier)();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})}),ko=u("/sign-in/email",{method:"POST",body:q.z.object({email:q.z.string(),password:q.z.string(),callbackURL:q.z.string().optional(),dontRememberMe:q.z.boolean().default(!1).optional()}),use:[P]},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 J.APIError("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!q.z.string().email().safeParse(t).success)throw new J.APIError("BAD_REQUEST",{message:"Invalid email"});if(!q.z.string().email().safeParse(t).success)throw new J.APIError("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new J.APIError("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new J.APIError("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new J.APIError("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new J.APIError("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw b.error("Email verification is required but no email verification handler is provided"),new J.APIError("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await ae(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new J.APIError("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new J.APIError("UNAUTHORIZED",{message:"Failed to create session"});return await A(e,c.id,e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});var Ne=require("zod");var y=require("zod"),us=y.z.object({id:y.z.string(),providerId:y.z.string(),accountId:y.z.string(),userId:y.z.string(),accessToken:y.z.string().nullable().optional(),refreshToken:y.z.string().nullable().optional(),idToken:y.z.string().nullable().optional(),expiresAt:y.z.date().nullable().optional(),password:y.z.string().optional().nullable()}),Ye=y.z.object({id:y.z.string(),email:y.z.string().transform(e=>e.toLowerCase()),emailVerified:y.z.boolean().default(!1),name:y.z.string(),image:y.z.string().optional(),createdAt:y.z.date().default(new Date),updatedAt:y.z.date().default(new Date)}),ls=y.z.object({id:y.z.string(),userId:y.z.string(),expiresAt:y.z.date(),ipAddress:y.z.string().optional(),userAgent:y.z.string().optional()}),ps=y.z.object({id:y.z.string(),value:y.z.string(),expiresAt:y.z.date(),identifier:y.z.string()});function Ro(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 hr(e,t){let r={...e.user?.additionalFields};return Ro(t||{},{fields:r})}var Oo=u("/callback/:id",{method:"GET",query:Ne.z.object({state:Ne.z.string(),code:Ne.z.string().optional(),error:Ne.z.string().optional()}),metadata:se},async e=>{if(e.query.error||!e.query.code){let R=Ie(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${R}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(h=>h.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=Ie(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 Ke(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(h){throw e.context.logger.error(h),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(d).then(h=>h?.user),l=_(),p=Ye.safeParse({...c,id:l});if(!c||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`);function g(h){throw e.redirect(`${n||o||`${e.context.baseURL}/error`}?error=${h}`)}let f=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(h=>{throw b.error(`Better auth was unable to query your database.
|
|
3
|
-
Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),k=f?.user.id;if(f){if(!f.accounts.find(R=>R.providerId===t.id)){(!e.context.options.account?.accountLinking?.trustedProviders?.includes(t.id)&&!c.emailVerified||!e.context.options.account?.accountLinking?.enabled)&&g("account_not_linked");try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:f.user.id,...Ue(d)})}catch(G){b.error("Unable to link account",G),g("unable_to_link_account")}}}else try{let h=c.emailVerified||!1,R=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:h},{...Ue(d),providerId:t.id,accountId:c.id.toString()});if(k=R?.user.id,!h&&R&&e.context.options.emailVerification?.sendOnSignUp){let V=await ae(e.context.secret,c.email),G=`${e.context.baseURL}/verify-email?token=${V}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(R.user,G,V)}}catch(h){b.error("Unable to create user",h),g("unable_to_create_user")}k||g("unable_to_create_user");let U=await e.context.internalAdapter.createSession(k,e.request);throw U||g("unable_to_create_session"),await A(e,U.id),e.redirect(o)});var Is=require("zod");var wr=require("better-call");var vo=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new wr.APIError("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),je(e),e.json({success:!0})});var Y=require("zod");var Fe=require("better-call");var Io=u("/forget-password",{method:"POST",body:Y.z.object({email:Y.z.string().email(),redirectTo:Y.z.string()}),use:[P]},async e=>{if(!e.context.options.emailAndPassword?.sendResetPassword)throw e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function in your auth config!"),new Fe.APIError("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})}),Uo=u("/reset-password/:token",{method:"GET",query:Y.z.object({callbackURL:Y.z.string()}),use:[P]},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}`)}),Eo=u("/reset-password",{query:Y.z.optional(Y.z.object({token:Y.z.string()})),method:"POST",body:Y.z.object({newPassword:Y.z.string()})},async e=>{let t=e.query?.token;if(!t)throw new Fe.APIError("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new Fe.APIError("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let i=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(i)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:i,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(i,a))throw new Fe.APIError("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});var z=require("zod");var x=require("better-call");var To=u("/user/update",{method:"POST",body:z.z.object({name:z.z.string().optional(),image:z.z.string().optional()}),use:[w,P]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),So=u("/user/change-password",{method:"POST",body:z.z.object({newPassword:z.z.string(),currentPassword:z.z.string(),revokeOtherSessions:z.z.boolean().optional()}),use:[w]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,i=e.context.password.config.minPasswordLength;if(t.length<i)throw e.context.logger.error("Password is too short"),new x.APIError("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 x.APIError("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 x.APIError("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new x.APIError("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:c}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new x.APIError("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await A(e,p.id)}return e.json(n.user)}),Po=u("/user/set-password",{method:"POST",body:z.z.object({newPassword:z.z.string()}),use:[w]},async e=>{let{newPassword:t}=e.body,r=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)throw e.context.logger.error("Password is too short"),new x.APIError("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 x.APIError("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 x.APIError("BAD_REQUEST",{message:"user already has a password"})}),Co=u("/user/delete",{method:"POST",body:z.z.object({password:z.z.string()}),use:[w]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new x.APIError("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new x.APIError("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)}),_o=u("/user/change-email",{method:"POST",query:z.z.object({currentURL:z.z.string().optional()}).optional(),body:z.z.object({newEmail:z.z.string().email(),callbackURL:z.z.string().optional()}),use:[w,P]},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new x.APIError("BAD_REQUEST",{message:"Change email is disabled"});if(e.body.newEmail===e.context.session.user.email)throw e.context.logger.error("Email is the same"),new x.APIError("BAD_REQUEST",{message:"Email is the same"});if(await e.context.internalAdapter.findUserByEmail(e.body.newEmail))throw e.context.logger.error("Email already exists"),new x.APIError("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let n=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:n,status:!0})}if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new x.APIError("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await ae(e.context.secret,e.context.session.user.email,e.body.newEmail),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(e.context.session.user,o,r),e.json({user:null,status:!0})});var gt=require("@noble/ciphers/chacha"),Te=require("@noble/ciphers/utils"),ht=require("@noble/ciphers/webcrypto"),wt=require("oslo/crypto");var yr=require("oslo/encoding");var zo=require("@noble/hashes/scrypt");async function X(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 Xe=async({key:e,data:t})=>{let r=await(0,wt.sha256)(new TextEncoder().encode(e)),o=(0,Te.utf8ToBytes)(t),n=(0,ht.managedNonce)(gt.xchacha20poly1305)(new Uint8Array(r));return(0,Te.bytesToHex)(n.encrypt(o))},et=async({key:e,data:t})=>{let r=await(0,wt.sha256)(new TextEncoder().encode(e)),o=(0,Te.hexToBytes)(t),n=(0,ht.managedNonce)(gt.xchacha20poly1305)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var Bo=u("/csrf",{method:"GET",metadata:se},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=Q(32,W("a-z","0-9","A-Z")),o=await X(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>
|
|
2
|
+
`)}}),b=uo();var P=E(async e=>{let{body:t,query:r,headers:o,context:n}=e,i=t?.callbackURL||r?.callbackURL||r?.redirectTo||t?.redirectTo,a=r?.currentURL||o?.get("referer")||n.baseURL,s=n.trustedOrigins,d=(c,l)=>{if(c?.startsWith("http")&&!s.some(g=>c.startsWith(g)))throw b.error(`Invalid ${l}`,{[l]:c,trustedOrigins:s}),new Nt.APIError("FORBIDDEN",{message:`Invalid ${l}`})};d(i,"callbackURL"),d(a,"currentURL")});var Qt=require("oslo/jwt");var Mt=require("oslo/crypto");var lo=require("std-env");function Ft(e){return new URL(e).origin.replace("http://","").replace("https://","")}var qt=require("oslo/encoding");async function $t(e){let t=await(0,Mt.sha256)(new TextEncoder().encode(e));return qt.base64url.encode(new Uint8Array(t),{includePadding:!1})}function Vt(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function B({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await $t(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,g)=>(p[g]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}var Ht=require("@better-fetch/fetch");async function T({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(0,Ht.betterFetch)(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 Vt(a)}function Ue(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var Wt=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})=>T({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=(0,Qt.parseJWT)(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};var Kt=require("@better-fetch/fetch");var Jt=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})=>T({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await(0,Kt.betterFetch)("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}}});var Gt=require("@better-fetch/fetch");var Zt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await B({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>T({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(0,Gt.betterFetch)("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}}});var mt=require("@better-fetch/fetch");var Yt=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let a=e.scope||o||["user:email"];return B({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>T({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await(0,mt.betterFetch)("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await(0,mt.betterFetch)("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};var Xt=require("oslo/jwt");var er=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 H("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new H("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return B({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>T({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=(0,Xt.parseJWT)(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});var tr=require("@better-fetch/fetch"),rr=require("oslo/jwt");var or=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=e.scope||n.scopes||["openid","profile","email","User.Read"];return B({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return T({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=(0,rr.parseJWT)(n.idToken)?.payload,a=e.profilePhotoSize||48;return await(0,tr.betterFetch)(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){b.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};var nr=require("@better-fetch/fetch");var ir=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return B({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>T({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(0,nr.betterFetch)("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}}});var ki=require("@better-fetch/fetch");var se={isAction:!1};function po(e){return e.toString(2).padStart(8,"0")}function mo(e){return[...e].map(t=>po(t)).join("")}function sr(e){return parseInt(mo(e),2)}function fo(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=sr(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=sr(o);return n}function Q(e,t){let r="";for(let o=0;o<e;o++)r+=t[fo(t.length)];return r}function W(...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 ar=require("nanoid"),_=e=>(0,ar.nanoid)(e);var dr=require("oslo/jwt");var cr=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return B({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>T({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=(0,dr.parseJWT)(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});var ur=require("@better-fetch/fetch");var lr=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return B({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>T({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(0,ur.betterFetch)("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 go={apple:Wt,discord:Jt,facebook:Zt,github:Yt,microsoft:or,google:er,spotify:ir,twitch:cr,twitter:lr},pr=Object.keys(go);var fr=require("oslo"),Ze=require("oslo/jwt"),K=require("zod");var be=require("better-call");var Ee=require("better-call");var Z=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));var ft=require("zod"),mr=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return je(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:Z(e.context.sessionConfig.expiresIn,"sec")});if(!d)return je(e),e.json(null,{status:401});let c=(d.expiresAt.valueOf()-Date.now())/1e3;return await A(e,d.id,!1,{maxAge:c}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),M=async e=>await mr()({...e,_flag:"json",headers:e.headers}),w=E(async e=>{let t=await M(e);if(!t?.session)throw new Ee.APIError("UNAUTHORIZED");return{session:t}});var ho=u("/user/revoke-session",{method:"POST",body:ft.z.object({id:ft.z.string()}),use:[w],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Ee.APIError("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Ee.APIError("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Ee.APIError("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),wo=u("/user/revoke-sessions",{method:"POST",use:[w],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Ee.APIError("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function ae(e,t,r){return await(0,Ze.createJWT)("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new fr.TimeSpan(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var yo=u("/send-verification-email",{method:"POST",query:K.z.object({currentURL:K.z.string().optional()}).optional(),body:K.z.object({email:K.z.string().email(),callbackURL:K.z.string().optional()}),use:[P]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be.APIError("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be.APIError("BAD_REQUEST",{message:"User not found"});let o=await ae(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})}),bo=u("/verify-email",{method:"GET",query:K.z.object({token:K.z.string(),callbackURL:K.z.string().optional()}),use:[P]},async e=>{let{token:t}=e.query,r;try{r=await(0,Ze.validateJWT)("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be.APIError("BAD_REQUEST",{message:"Invalid token"})}let n=K.z.object({email:K.z.string().email(),updateTo:K.z.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be.APIError("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await M(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be.APIError("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be.APIError("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Ao=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:q.z.object({currentURL:q.z.string().optional()}).optional(),body:q.z.object({callbackURL:q.z.string().optional(),provider:q.z.enum(pr)}),use:[P]},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 J.APIError("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 Je(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=(0,gr.generateCodeVerifier)();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})}),ko=u("/sign-in/email",{method:"POST",body:q.z.object({email:q.z.string(),password:q.z.string(),callbackURL:q.z.string().optional(),dontRememberMe:q.z.boolean().default(!1).optional()}),use:[P]},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 J.APIError("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!q.z.string().email().safeParse(t).success)throw new J.APIError("BAD_REQUEST",{message:"Invalid email"});if(!q.z.string().email().safeParse(t).success)throw new J.APIError("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new J.APIError("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new J.APIError("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new J.APIError("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new J.APIError("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw b.error("Email verification is required but no email verification handler is provided"),new J.APIError("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await ae(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new J.APIError("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new J.APIError("UNAUTHORIZED",{message:"Failed to create session"});return await A(e,c.id,e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});var Ne=require("zod");var y=require("zod"),us=y.z.object({id:y.z.string(),providerId:y.z.string(),accountId:y.z.string(),userId:y.z.string(),accessToken:y.z.string().nullable().optional(),refreshToken:y.z.string().nullable().optional(),idToken:y.z.string().nullable().optional(),expiresAt:y.z.date().nullable().optional(),password:y.z.string().optional().nullable()}),Ye=y.z.object({id:y.z.string(),email:y.z.string().transform(e=>e.toLowerCase()),emailVerified:y.z.boolean().default(!1),name:y.z.string(),image:y.z.string().optional(),createdAt:y.z.date().default(new Date),updatedAt:y.z.date().default(new Date)}),ls=y.z.object({id:y.z.string(),userId:y.z.string(),expiresAt:y.z.date(),ipAddress:y.z.string().optional(),userAgent:y.z.string().optional()}),ps=y.z.object({id:y.z.string(),value:y.z.string(),expiresAt:y.z.date(),identifier:y.z.string()});function Ro(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 hr(e,t){let r={...e.user?.additionalFields};return Ro(t||{},{fields:r})}var Oo=u("/callback/:id",{method:"GET",query:Ne.z.object({state:Ne.z.string(),code:Ne.z.string().optional(),error:Ne.z.string().optional()}),metadata:se},async e=>{if(e.query.error||!e.query.code){let R=Ie(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${R}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(h=>h.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=Ie(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 Ke(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(h){throw e.context.logger.error(h),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(d).then(h=>h?.user),l=_(),p=Ye.safeParse({...c,id:l});if(!c||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`);function g(h){throw e.redirect(`${n||o||`${e.context.baseURL}/error`}?error=${h}`)}let m=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(h=>{throw b.error(`Better auth was unable to query your database.
|
|
3
|
+
Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),k=m?.user.id;if(m){if(!m.accounts.find(R=>R.providerId===t.id)){(!e.context.options.account?.accountLinking?.trustedProviders?.includes(t.id)&&!c.emailVerified||!e.context.options.account?.accountLinking?.enabled)&&g("account_not_linked");try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:m.user.id,...Ue(d)})}catch(G){b.error("Unable to link account",G),g("unable_to_link_account")}}}else try{let h=c.emailVerified||!1,R=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:h},{...Ue(d),providerId:t.id,accountId:c.id.toString()});if(k=R?.user.id,!h&&R&&e.context.options.emailVerification?.sendOnSignUp){let V=await ae(e.context.secret,c.email),G=`${e.context.baseURL}/verify-email?token=${V}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(R.user,G,V)}}catch(h){b.error("Unable to create user",h),g("unable_to_create_user")}k||g("unable_to_create_user");let U=await e.context.internalAdapter.createSession(k,e.request);throw U||g("unable_to_create_session"),await A(e,U.id),e.redirect(o)});var Is=require("zod");var wr=require("better-call");var vo=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new wr.APIError("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),je(e),e.json({success:!0})});var Y=require("zod");var Fe=require("better-call");var Io=u("/forget-password",{method:"POST",body:Y.z.object({email:Y.z.string().email(),redirectTo:Y.z.string()}),use:[P]},async e=>{if(!e.context.options.emailAndPassword?.sendResetPassword)throw e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function in your auth config!"),new Fe.APIError("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})}),Uo=u("/reset-password/:token",{method:"GET",query:Y.z.object({callbackURL:Y.z.string()}),use:[P]},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}`)}),Eo=u("/reset-password",{query:Y.z.optional(Y.z.object({token:Y.z.string()})),method:"POST",body:Y.z.object({newPassword:Y.z.string()})},async e=>{let t=e.query?.token;if(!t)throw new Fe.APIError("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new Fe.APIError("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let i=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(i)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:i,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(i,a))throw new Fe.APIError("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});var z=require("zod");var x=require("better-call");var To=u("/user/update",{method:"POST",body:z.z.object({name:z.z.string().optional(),image:z.z.string().optional()}),use:[w,P]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),So=u("/user/change-password",{method:"POST",body:z.z.object({newPassword:z.z.string(),currentPassword:z.z.string(),revokeOtherSessions:z.z.boolean().optional()}),use:[w]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,i=e.context.password.config.minPasswordLength;if(t.length<i)throw e.context.logger.error("Password is too short"),new x.APIError("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 x.APIError("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 x.APIError("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new x.APIError("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:c}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new x.APIError("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await A(e,p.id)}return e.json(n.user)}),Po=u("/user/set-password",{method:"POST",body:z.z.object({newPassword:z.z.string()}),use:[w]},async e=>{let{newPassword:t}=e.body,r=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)throw e.context.logger.error("Password is too short"),new x.APIError("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 x.APIError("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 x.APIError("BAD_REQUEST",{message:"user already has a password"})}),Co=u("/user/delete",{method:"POST",body:z.z.object({password:z.z.string()}),use:[w]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new x.APIError("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new x.APIError("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)}),_o=u("/user/change-email",{method:"POST",query:z.z.object({currentURL:z.z.string().optional()}).optional(),body:z.z.object({newEmail:z.z.string().email(),callbackURL:z.z.string().optional()}),use:[w,P]},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new x.APIError("BAD_REQUEST",{message:"Change email is disabled"});if(e.body.newEmail===e.context.session.user.email)throw e.context.logger.error("Email is the same"),new x.APIError("BAD_REQUEST",{message:"Email is the same"});if(await e.context.internalAdapter.findUserByEmail(e.body.newEmail))throw e.context.logger.error("Email already exists"),new x.APIError("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let n=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:n,status:!0})}if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new x.APIError("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await ae(e.context.secret,e.context.session.user.email,e.body.newEmail),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(e.context.session.user,o,r),e.json({user:null,status:!0})});var gt=require("@noble/ciphers/chacha"),Te=require("@noble/ciphers/utils"),ht=require("@noble/ciphers/webcrypto"),wt=require("oslo/crypto");var yr=require("oslo/encoding");var zo=require("@noble/hashes/scrypt");async function X(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 Xe=async({key:e,data:t})=>{let r=await(0,wt.sha256)(new TextEncoder().encode(e)),o=(0,Te.utf8ToBytes)(t),n=(0,ht.managedNonce)(gt.xchacha20poly1305)(new Uint8Array(r));return(0,Te.bytesToHex)(n.encrypt(o))},et=async({key:e,data:t})=>{let r=await(0,wt.sha256)(new TextEncoder().encode(e)),o=(0,Te.hexToBytes)(t),n=(0,ht.managedNonce)(gt.xchacha20poly1305)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var Bo=u("/csrf",{method:"GET",metadata:se},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=Q(32,W("a-z","0-9","A-Z")),o=await X(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>
|
|
4
4
|
<html lang="en">
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="UTF-8">
|
|
@@ -80,5 +80,5 @@ Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)
|
|
|
80
80
|
<div class="error-code">Error Code: <span id="errorCode">${e}</span></div>
|
|
81
81
|
</div>
|
|
82
82
|
</body>
|
|
83
|
-
</html>`,Do=u("/error",{method:"GET",metadata:se},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(Lo(t),{headers:{"Content-Type":"text/html"}})});var xo=u("/ok",{method:"GET",metadata:se},async e=>e.json({ok:!0}));var Ae=require("zod");var ue=require("better-call");var yt=()=>u("/sign-up/email",{method:"POST",query:Ae.z.object({currentURL:Ae.z.string().optional()}).optional(),body:Ae.z.record(Ae.z.string(),Ae.z.any()),use:[P]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue.APIError("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!Ae.z.string().email().safeParse(o).success)throw new ue.APIError("BAD_REQUEST",{message:"Invalid email"});let c=e.context.password.config.minPasswordLength;if(n.length<c)throw e.context.logger.error("Password is too short"),new ue.APIError("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.APIError("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.APIError("UNPROCESSABLE_ENTITY",{message:"Failed to create user"});let g=hr(e.context.options,s),f=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1});if(!f)throw new ue.APIError("BAD_REQUEST",{message:"Failed to create user"});let k=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:f.id,providerId:"credential",accountId:f.id,password:k,expiresAt:Z(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let h=await ae(e.context.secret,f.email),R=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(f,R,h)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({user:f,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:null}});let U=await e.context.internalAdapter.createSession(f.id,e.request);if(!U)throw new ue.APIError("BAD_REQUEST",{message:"Failed to create session"});return await A(e,U.id),e.json({user:f,session:U},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:U}})});var br=(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 At={};zt(At,{AccessControl:()=>Me,ParsingError:()=>ke,Role:()=>Se,adminAc:()=>Rr,createAccessControl:()=>Ar,defaultAc:()=>tt,defaultRoles:()=>bt,defaultStatements:()=>kr,memberAc:()=>vr,ownerAc:()=>Or,permissionFromString:()=>jo});var ke=class extends Error{path;constructor(t,r){super(t),this.path=r}},Me=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new Se(t)}},Se=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 ke("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new ke("invalid resource identifier",o);if(!Array.isArray(n))throw new ke("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new ke("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var Ar=e=>new Me(e),kr={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},tt=Ar(kr),Rr=tt.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),Or=tt.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),vr=tt.newRole({organization:[],member:[],invitation:[]}),bt={admin:Rr,owner:Or,member:vr};var jo=e=>Se.fromString(e??"");var C=(e,t)=>({findOrganizationBySlug:async r=>await e.findOne({model:"organization",where:[{field:"slug",value:r}]}),createOrganization:async r=>{let o=await e.create({model:"organization",data:{...r.organization,metadata:r.organization.metadata?JSON.stringify(r.organization.metadata):void 0}}),n=await e.create({model:"member",data:{id:_(),organizationId:o.id,userId:r.user.id,createdAt:new Date,email:r.user.email,role:t?.creatorRole||"owner"}});return{...o,metadata:o.metadata?JSON.parse(o.metadata):void 0,members:[{...n,user:{id:r.user.id,name:r.user.name,email:r.user.email,image:r.user.image}}]}},findMemberByEmail:async r=>{let o=await e.findOne({model:"member",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberByOrgId:async r=>{let[o,n]=await Promise.all([await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{field:"organizationId",value:r.organizationId}]}),await e.findOne({model:"user",where:[{field:"id",value:r.userId}]})]);return!n||!o?null:{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}},findMemberById:async r=>{let o=await e.findOne({model:"member",where:[{field:"id",value:r}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},createMember:async r=>await e.create({model:"member",data:r}),updateMember:async(r,o)=>await e.update({model:"member",where:[{field:"id",value:r}],update:{role:o}}),deleteMember:async r=>await e.delete({model:"member",where:[{field:"id",value:r}]}),updateOrganization:async(r,o)=>await e.update({model:"organization",where:[{field:"id",value:r}],update:o}),deleteOrganization:async r=>(await e.delete({model:"member",where:[{field:"organizationId",value:r}]}),await e.delete({model:"invitation",where:[{field:"organizationId",value:r}]}),await e.delete({model:"organization",where:[{field:"id",value:r}]}),r),setActiveOrganization:async(r,o)=>await e.update({model:"session",where:[{field:"id",value:r}],update:{activeOrganizationId:o}}),findOrganizationById:async r=>await e.findOne({model:"organization",where:[{field:"id",value:r}]}),findFullOrganization:async(r,o)=>{let[n,i,a]=await Promise.all([e.findOne({model:"organization",where:[{field:"id",value:r}]}),e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),e.findMany({model:"member",where:[{field:"organizationId",value:r}]})]);if(!n)return null;let s=a.map(p=>p.userId),d=await e.findMany({model:"user",where:[{field:"id",value:s,operator:"in"}]}),c=new Map(d.map(p=>[p.id,p])),l=a.map(p=>{let g=c.get(p.userId);if(!g)throw new H("Unexpected error: User not found for member");return{...p,user:{id:g.id,name:g.name,email:g.email,image:g.image}}});return{...n,invitations:i,members:l}},listOrganizations:async r=>{let o=await e.findMany({model:"member",where:[{field:"userId",value:r}]});if(!o||o.length===0)return[];let n=o.map(a=>a.organizationId);return await e.findMany({model:"organization",where:[{field:"id",value:n,operator:"in"}]})},createInvitation:async({invitation:r,user:o})=>{let i=Z(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:_(),email:r.email,role:r.role,organizationId:r.organizationId,status:"pending",expiresAt:i,inviterId:o.id}})},findInvitationById:async r=>await e.findOne({model:"invitation",where:[{field:"id",value:r}]}),findPendingInvitation:async r=>(await e.findMany({model:"invitation",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId},{field:"status",value:"pending"}]})).filter(n=>new Date(n.expiresAt)>new Date),updateInvitation:async r=>await e.update({model:"invitation",where:[{field:"id",value:r.invitationId}],update:{status:r.status}})});var gd=require("better-call");var Rt=require("better-call");var rt=require("better-call"),kt=require("zod");var No=E({body:kt.z.object({csrfToken:kt.z.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=e.headers?.get("origin")||"";if(t){let s=new URL(t).origin;if(e.context.trustedOrigins.includes(s))return}let r=e.body?.csrfToken;if(!r)throw new rt.APIError("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new rt.APIError("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await X(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new rt.APIError("UNAUTHORIZED",{message:"Invalid CSRF Token"})});var Fo=require("std-env");var F=require("better-call");var L=E(async e=>({})),j=E({use:[w]},async e=>({session:e.context.session}));var $=require("zod");var v=require("zod"),ot=v.z.enum(["admin","member","owner"]),Mo=v.z.enum(["pending","accepted","rejected","canceled"]).default("pending"),Rd=v.z.object({id:v.z.string(),name:v.z.string(),slug:v.z.string(),logo:v.z.string().optional(),metadata:v.z.record(v.z.string()).or(v.z.string().transform(e=>JSON.parse(e))).optional(),createdAt:v.z.date()}),Od=v.z.object({id:v.z.string(),email:v.z.string(),organizationId:v.z.string(),userId:v.z.string(),role:ot,createdAt:v.z.date()}),vd=v.z.object({id:v.z.string(),organizationId:v.z.string(),email:v.z.string(),role:ot,status:Mo,inviterId:v.z.string(),expiresAt:v.z.date()});var I=require("better-call"),Ir=u("/organization/invite-member",{method:"POST",use:[L,j],body:$.z.object({email:$.z.string(),role:ot,organizationId:$.z.string().optional(),resend:$.z.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 I.APIError("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new I.APIError("BAD_REQUEST",{message:"Organization not found"});let o=C(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new I.APIError("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new I.APIError("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new I.APIError("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new I.APIError("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 I.APIError("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new I.APIError("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),Ur=u("/organization/accept-invitation",{method:"POST",body:$.z.object({invitationId:$.z.string()}),use:[L,j]},async e=>{let t=e.context.session,r=C(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I.APIError("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:_(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),Er=u("/organization/reject-invitation",{method:"POST",body:$.z.object({invitationId:$.z.string()}),use:[L,j]},async e=>{let t=e.context.session,r=C(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I.APIError("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})}),Tr=u("/organization/cancel-invitation",{method:"POST",body:$.z.object({invitationId:$.z.string()}),use:[L,j]},async e=>{let t=e.context.session,r=C(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new I.APIError("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new I.APIError("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)}),Sr=u("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:$.z.object({id:$.z.string()})},async e=>{let t=await M(e);if(!t)throw new I.APIError("UNAUTHORIZED",{message:"Not authenticated"});let r=C(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I.APIError("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new I.APIError("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new I.APIError("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})});var le=require("zod");var Pe=require("better-call"),Pr=u("/organization/remove-member",{method:"POST",body:le.z.object({memberIdOrEmail:le.z.string(),organizationId:le.z.string().optional()}),use:[L,j]},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=C(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Pe.APIError("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Pe.APIError("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 Pe.APIError("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Pe.APIError("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Pe.APIError("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Cr=u("/organization/update-member-role",{method:"POST",body:le.z.object({role:le.z.enum(["admin","member","owner"]),memberId:le.z.string(),organizationId:le.z.string().optional()}),use:[L,j]},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=C(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!"}})});var S=require("zod");var pe=require("better-call"),_r=u("/organization/create",{method:"POST",body:S.z.object({name:S.z.string(),slug:S.z.string(),userId:S.z.string().optional(),logo:S.z.string().optional(),metadata:S.z.record(S.z.string()).optional()}),use:[L,j]},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 pe.APIError("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=C(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 pe.APIError("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new pe.APIError("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:_(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),zr=u("/organization/update",{method:"POST",body:S.z.object({data:S.z.object({name:S.z.string().optional(),slug:S.z.string().optional()}).partial(),orgId:S.z.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new pe.APIError("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=C(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)}),Br=u("/organization/delete",{method:"POST",body:S.z.object({orgId:S.z.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=C(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 pe.APIError("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)}),Lr=u("/organization/get-full",{method:"GET",query:S.z.object({orgId:S.z.string().optional()}),requireHeaders:!0,use:[L,j]},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 C(e.context.adapter,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new pe.APIError("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Dr=u("/organization/activate",{method:"POST",body:S.z.object({orgId:S.z.string().nullable().optional()}),use:[j,L]},async e=>{let t=C(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 pe.APIError("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)}),xr=u("/organization/list",{method:"GET",use:[L,j]},async e=>{let r=await C(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var qo=e=>{let t={createOrganization:_r,updateOrganization:zr,deleteOrganization:Br,setActiveOrganization:Dr,getFullOrganization:Lr,listOrganization:xr,createInvitation:Ir,cancelInvitation:Tr,acceptInvitation:Ur,getInvitation:Sr,rejectInvitation:Er,removeMember:Pr,updateMemberRole:Cr},r={...bt,...e?.roles};return{id:"organization",endpoints:{...br(t,{orgOptions:e||{},roles:r,getSession:async n=>await M(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Ce.z.object({permission:Ce.z.record(Ce.z.string(),Ce.z.array(Ce.z.string()))}),use:[j]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new Ot.APIError("BAD_REQUEST",{message:"No active organization"});let a=await C(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Ot.APIError("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:{}}}};var Ve=require("zod");var ze=require("zod");var me=require("better-call");var nt="two-factor";var it="trust-device";var vt=require("zod"),Re=E({body:vt.z.object({trustDevice:vt.z.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(nt),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new me.APIError("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new me.APIError("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 me.APIError("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new me.APIError("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await X(e.context.secret,s.id),c=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!c)throw new me.APIError("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await A(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(it,{maxAge:2592e3}),p=await X(e.context.secret,`${c.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:c})},invalid:async()=>{throw new me.APIError("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:c}}}throw new me.APIError("UNAUTHORIZED",{message:"invalid two factor authentication"})});var _e=require("better-call");function $o(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>Q(e?.length??10,W("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function It(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():$o(),n=await Xe({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Vo(e,t){let r=await jr(e.backupCodes,t);return r?r.includes(e.code):!1}async function jr(e,t){let r=Buffer.from(await et({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=ze.z.array(ze.z.string()).safeParse(o);return n.success?n.data:null}var Nr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:ze.z.object({code:ze.z.string(),disableSession:ze.z.boolean().optional()}),use:[Re]},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 _e.APIError("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Vo({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new _e.APIError("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await A(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",use:[w]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new _e.APIError("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await It(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",use:[w]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new _e.APIError("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=jr(n.backupCodes,r.context.secret);if(!i)throw new _e.APIError("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});var qe=require("better-call"),Fr=require("oslo/otp"),Ut=require("zod");var Mr=require("oslo"),qr=(e,t)=>{let r={...e,period:new Mr.TimeSpan(e?.period||3,"m")},o=new Fr.TOTPController({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[Re]},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 qe.APIError("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 qe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:Ut.z.object({code:Ut.z.string()}),use:[Re]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new qe.APIError("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 qe.APIError("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}}};var Oe=require("better-call"),$r=require("oslo"),$e=require("oslo/otp"),Et=require("zod");var Vr=(e,t)=>{let r={...e,digits:6,period:new $r.TimeSpan(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Oe.APIError("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 Oe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new $e.TOTPController(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"GET",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Oe.APIError("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 Oe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:(0,$e.createTOTPKeyURI)(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:Et.z.object({code:Et.z.string()}),use:[Re]},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 Oe.APIError("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 Oe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});let c=new $e.TOTPController(r),l=await et({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await c.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function Tt(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)}var St=require("better-call");var Ho=(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 Qo=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=Vr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=Nr({...e?.backupCodeOptions},t.twoFactorTable),n=qr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ve.z.object({password:Ve.z.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await Tt(i,{password:s,userId:a.id}))throw new St.APIError("BAD_REQUEST",{message:"Invalid password"});let c=Q(16,W("a-z","0-9","-")),l=await Xe({key:i.context.secret,data:c}),p=await It(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ve.z.object({password:Ve.z.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await Tt(i,{password:s,userId:a.id}))throw new St.APIError("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:E(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(it,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[f,k]=c.split("!"),U=await X(i.context.secret,`${s.user.id}!${k}`);if(f===U){let h=await X(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await X(i.context.secret,s.session.id),p=i.context.createAuthCookie(nt,{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}]}};var fe=require("@simplewebauthn/server"),ee=require("better-call");var oe=require("zod");var Wr=require("std-env");var Be=require("@simplewebauthn/browser");var Ko=require("@better-fetch/fetch");var qc=require("nanostores");var Wo=require("@better-fetch/fetch");var Jo=require("nanostores");var Qc=require("@better-fetch/fetch"),st=require("nanostores"),Pt=(e,t,r,o)=>{let n=(0,st.atom)({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():(0,st.onMount)(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};var Hr=require("nanostores"),Qr=(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(0,Be.startAuthentication)(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(0,Be.startRegistration)(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 Be.WebAuthnError?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:{}}),Go=()=>{let e=(0,Hr.atom)();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Qr(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:Pt(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 Zo=e=>{let t=Wr.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new H("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[w],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(Q(32,W("a-z","0-9")))),p;p=await(0,fe.generateRegistrationOptions)({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:oe.z.object({email:oe.z.string().optional()}).optional()},async s=>{let d=await M(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await(0,fe.generateAuthenticationOptions)({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:oe.z.object({response:oe.z.any(),name:oe.z.string().optional()}),use:[w]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee.APIError("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:g,userData:f}=JSON.parse(p.value);if(f.id!==s.context.session.user.id)throw new ee.APIError("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await(0,fe.verifyRegistrationResponse)({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:U,registrationInfo:h}=k;if(!U||!h)return s.json(null,{status:400});let{credentialID:R,credentialPublicKey:V,counter:G,credentialDeviceType:O,credentialBackedUp:N}=h,ce=Buffer.from(V).toString("base64"),D=_(),We={name:s.body.name,userId:f.id,webauthnUserID:D,id:R,publicKey:ce,counter:G,deviceType:O,transports:c.response.transports.join(","),backedUp:N,createdAt:new Date},ro=await s.context.adapter.create({model:"passkey",data:We});return s.json(ro,{status:200})}catch(k){throw console.log(k),new ee.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:oe.z.object({response:oe.z.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new ee.APIError("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee.APIError("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new ee.APIError("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:g}=JSON.parse(p.value),f=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!f)throw new ee.APIError("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await(0,fe.verifyAuthenticationResponse)({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:f.id,credentialPublicKey:new Uint8Array(Buffer.from(f.publicKey,"base64")),counter:f.counter,transports:f.transports?.split(",")}}),{verified:U}=k;if(!U)throw new ee.APIError("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:f.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(f.userId,s.request);if(!h)throw new ee.APIError("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await A(s,h.id),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new ee.APIError("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[w]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:oe.z.object({id:oe.z.string()}),use:[w]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};var te=require("zod");var He=require("better-call");var Ct=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:te.z.object({username:te.z.string(),password:te.z.string(),dontRememberMe:te.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:Ct}),new He.APIError("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 He.APIError("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:Ct}),new He.APIError("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new He.APIError("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:u("/sign-up/username",{method:"POST",body:te.z.object({username:te.z.string().min(3).max(20),name:te.z.string(),email:te.z.string().email(),password:te.z.string(),image:te.z.string().optional()})},async e=>{let t=await yt()({...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}}}}});var Kr=require("better-call"),Yo=()=>({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(0,Kr.serializeSigned)("",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}}}]}});var ve=require("zod");var Jr=require("better-call");var Xo=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:ve.z.object({email:ve.z.string().email(),callbackURL:ve.z.string().optional()}),use:[P]},async t=>{let{email:r}=t.body,o=Q(32,W("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 Jr.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:ve.z.object({token:ve.z.string(),callbackURL:ve.z.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await A(t,c.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});var ge=require("zod");var ne=require("better-call");function en(e){return Q(e,W("0-9"))}var tn=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:ge.z.object({phoneNumber:ge.z.string()})},async r=>{if(!e?.sendOTP)throw b.warn("sendOTP not implemented"),new ne.APIError("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=en(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:Z(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:ge.z.object({phoneNumber:ge.z.string(),code:ge.z.string(),disableSession:ge.z.boolean().optional(),updatePhoneNumber:ge.z.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 ne.APIError("BAD_REQUEST",{message:"OTP expired"})):new ne.APIError("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ne.APIError("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await M(r);if(!i)throw new ne.APIError("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ne.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ne.APIError("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new ne.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new ne.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(r,i.id),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};var at=require("zod");var rn=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=Ft(t.context.baseURL)}=e||{},o=_(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await A(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:u("/user/link-anonymous",{method:"POST",body:at.z.object({email:at.z.string().email().optional(),password:at.z.string().min(6)}),use:[w]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await A(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});var m=require("zod");var re=E(async e=>{let t=await M(e);if(!t?.session)throw new F.APIError("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new F.APIError("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),on=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:E(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:m.z.object({userId:m.z.string(),role:m.z.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:m.z.object({email:m.z.string(),password:m.z.string(),name:m.z.string(),role:m.z.string(),data:m.z.optional(m.z.record(m.z.any()))}),use:[re]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new F.APIError("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 F.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[re],query:m.z.object({search:m.z.object({field:m.z.enum(["email","name"]),operator:m.z.enum(["contains","starts_with","ends_with"]).default("contains"),value:m.z.string()}).optional(),limit:m.z.string().or(m.z.number()).optional(),offset:m.z.string().or(m.z.number()).optional(),sortBy:m.z.string().optional(),sortDirection:m.z.enum(["asc","desc"]).optional(),filter:m.z.array(m.z.object({field:m.z.string(),value:m.z.string().or(m.z.number()).or(m.z.boolean()),operator:m.z.enum(["eq","ne","lt","lte","gt","gte"]),connector:m.z.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[re],body:m.z.object({userId:m.z.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:m.z.object({userId:m.z.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:m.z.object({userId:m.z.string(),banReason:m.z.string().optional(),banExpiresIn:m.z.number().optional()}),use:[re]},async t=>{if(t.body.userId===t.context.session.user.id)throw new F.APIError("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:m.z.object({userId:m.z.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new F.APIError("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?Z(e.impersonationSessionDuration,"sec"):Z(60*60,"sec")});if(!o)throw new F.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:m.z.object({sessionId:m.z.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:m.z.object({userId:m.z.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:m.z.object({userId:m.z.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});var ie=require("zod"),Le=require("better-call");var dt=require("@better-fetch/fetch");var Gr=require("oslo/oauth2");var Zr=require("oslo/jwt");async function nn(e,t,r){if(t==="oidc"&&e.idToken){let n=(0,Zr.parseJWT)(e.idToken);if(n?.payload)return n.payload}return r?(await(0,dt.betterFetch)(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var sn=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:ie.z.object({currentURL:ie.z.string().optional()}).optional(),body:ie.z.object({providerId:ie.z.string(),callbackURL:ie.z.string().optional()}),use:[P]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Le.APIError("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:g,prompt:f,accessType:k}=o,U=i,h=a;if(n){let D=await(0,dt.betterFetch)(n,{onError(We){b.error(We.error,{discoveryUrl:n})}});D.data&&(U=D.data.authorization_endpoint,h=D.data.token_endpoint)}if(!U||!h)throw new Le.APIError("BAD_REQUEST",{message:"Invalid OAuth configuration."});let R=t.query?.currentURL?new URL(t.query?.currentURL):null,V=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${R?.origin}${t.body.callbackURL||""}`,G=await Je(V||R?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,G.hash,t.context.secret,O.state.options);let N=(0,Gr.generateCodeVerifier)();await t.setSignedCookie(O.pkCodeVerifier.name,N,t.context.secret,O.pkCodeVerifier.options);let ce=await B({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:U,state:G.raw,codeVerifier:N,scopes:c||[],disablePkce:!g,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ce.searchParams.set("response_type",p),f&&ce.searchParams.set("prompt",f),k&&ce.searchParams.set("access_type",k),{url:ce.toString(),state:G,codeVerifier:N,redirect:!0}}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:ie.z.object({code:ie.z.string().optional(),error:ie.z.string().optional(),state:ie.z.string()})},async t=>{if(t.query.error||!t.query.code){let N=Ie(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${N}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Le.APIError("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=Ie(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,c=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw b.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await Ke(a,p))throw b.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let f=r.tokenUrl,k=r.userInfoUrl;if(r.discoveryUrl){let O=await(0,dt.betterFetch)(r.discoveryUrl,{method:"GET"});O.data&&(f=O.data.token_endpoint,k=O.data.userinfo_endpoint)}try{if(!f)throw new Le.APIError("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await T({code:c,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:f})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Le.APIError("BAD_REQUEST",{message:"Invalid OAuth configuration."});let U=r.getUserInfo?await r.getUserInfo(n):await nn(n,r.type||"oauth2",k),h=_(),R=U?Ye.safeParse({...U,id:h}):null;if(!R?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let V=await t.context.internalAdapter.findUserByEmail(R.data.email).catch(O=>{throw b.error(`Better auth was unable to query your database.
|
|
84
|
-
Error: `,O),t.redirect(`${l}?error=internal_server_error`)}),G=V?.user.id||h;if(V){let O=V.accounts.find(D=>D.providerId===r.providerId),N=t.context.options.account?.accountLinking?.trustedProviders,ce=N?N.includes(r.providerId):!0;if(!O&&(!R?.data.emailVerified||!ce)){let D;try{D=new URL(l),D.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(D.toString())}if(!O)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:R.data.id,id:`${r.providerId}:${R.data.id}`,userId:V.user.id,...Ue(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(R.data,{...Ue(n),id:`${r.providerId}:${R.data.id}`,providerId:r.providerId,accountId:R.data.id})}catch{let N=new URL(l);throw N.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",N.toString()),t.redirect(N.toString())}try{let O=await t.context.internalAdapter.createSession(G||h,t.request);if(!O)throw t.redirect(`${l}?error=unable_to_create_session`);await A(t,O.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});var De=require("zod"),Yr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},ol=De.z.object({id:De.z.string(),publicKey:De.z.string(),privateKey:De.z.string(),createdAt:De.z.date()});var _t=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}})});var de=require("jose");var he=require("crypto");function Xr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=(0,he.createHash)("sha256").update(e).digest(),t}function eo(e,t){let r=Xr(t),o=(0,he.randomBytes)(12),n=(0,he.createCipheriv)("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 to(e,t){let r=Xr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=(0,he.createDecipheriv)("aes-256-gcm",r,a);d.setAuthTag(s);let c=d.update(o,"base64","utf8");return c+=d.final("utf8"),c}var an=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await _t(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[w]},async t=>{let r=_t(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await(0,de.generateKeyPair)(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await(0,de.exportJWK)(c),g=await(0,de.exportJWK)(l),
|
|
83
|
+
</html>`,Do=u("/error",{method:"GET",metadata:se},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(Lo(t),{headers:{"Content-Type":"text/html"}})});var xo=u("/ok",{method:"GET",metadata:se},async e=>e.json({ok:!0}));var Ae=require("zod");var ue=require("better-call");var yt=()=>u("/sign-up/email",{method:"POST",query:Ae.z.object({currentURL:Ae.z.string().optional()}).optional(),body:Ae.z.record(Ae.z.string(),Ae.z.any()),use:[P]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue.APIError("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!Ae.z.string().email().safeParse(o).success)throw new ue.APIError("BAD_REQUEST",{message:"Invalid email"});let c=e.context.password.config.minPasswordLength;if(n.length<c)throw e.context.logger.error("Password is too short"),new ue.APIError("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.APIError("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.APIError("UNPROCESSABLE_ENTITY",{message:"Failed to create user"});let g=hr(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1});if(!m)throw new ue.APIError("BAD_REQUEST",{message:"Failed to create user"});let k=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:k,expiresAt:Z(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let h=await ae(e.context.secret,m.email),R=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(m,R,h)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({user:m,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:null}});let U=await e.context.internalAdapter.createSession(m.id,e.request);if(!U)throw new ue.APIError("BAD_REQUEST",{message:"Failed to create session"});return await A(e,U.id),e.json({user:m,session:U},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:U}})});var br=(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 At={};zt(At,{AccessControl:()=>Me,ParsingError:()=>ke,Role:()=>Se,adminAc:()=>Rr,createAccessControl:()=>Ar,defaultAc:()=>tt,defaultRoles:()=>bt,defaultStatements:()=>kr,memberAc:()=>vr,ownerAc:()=>Or,permissionFromString:()=>jo});var ke=class extends Error{path;constructor(t,r){super(t),this.path=r}},Me=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new Se(t)}},Se=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 ke("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new ke("invalid resource identifier",o);if(!Array.isArray(n))throw new ke("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new ke("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var Ar=e=>new Me(e),kr={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},tt=Ar(kr),Rr=tt.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),Or=tt.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),vr=tt.newRole({organization:[],member:[],invitation:[]}),bt={admin:Rr,owner:Or,member:vr};var jo=e=>Se.fromString(e??"");var C=(e,t)=>{let r=e.adapter;return{findOrganizationBySlug:async o=>await r.findOne({model:"organization",where:[{field:"slug",value:o}]}),createOrganization:async o=>{let n=await r.create({model:"organization",data:{...o.organization,metadata:o.organization.metadata?JSON.stringify(o.organization.metadata):void 0}}),i=await r.create({model:"member",data:{id:_(),organizationId:n.id,userId:o.user.id,createdAt:new Date,email:o.user.email,role:t?.creatorRole||"owner"}});return{...n,metadata:n.metadata?JSON.parse(n.metadata):void 0,members:[{...i,user:{id:o.user.id,name:o.user.name,email:o.user.email,image:o.user.image}}]}},findMemberByEmail:async o=>{let n=await r.findOne({model:"member",where:[{field:"email",value:o.email},{field:"organizationId",value:o.organizationId}]});if(!n)return null;let i=await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:n.userId}]});return i?{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}:null},findMemberByOrgId:async o=>{let[n,i]=await Promise.all([await r.findOne({model:"member",where:[{field:"userId",value:o.userId},{field:"organizationId",value:o.organizationId}]}),await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:o.userId}]})]);return!i||!n?null:{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}},findMemberById:async o=>{let n=await r.findOne({model:"member",where:[{field:"id",value:o}]});if(!n)return null;let i=await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:n.userId}]});return i?{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}:null},createMember:async o=>await r.create({model:"member",data:o}),updateMember:async(o,n)=>await r.update({model:"member",where:[{field:"id",value:o}],update:{role:n}}),deleteMember:async o=>await r.delete({model:"member",where:[{field:"id",value:o}]}),updateOrganization:async(o,n)=>await r.update({model:"organization",where:[{field:"id",value:o}],update:n}),deleteOrganization:async o=>(await r.delete({model:"member",where:[{field:"organizationId",value:o}]}),await r.delete({model:"invitation",where:[{field:"organizationId",value:o}]}),await r.delete({model:"organization",where:[{field:"id",value:o}]}),o),setActiveOrganization:async(o,n)=>await r.update({model:e.tables.session.tableName,where:[{field:"id",value:o}],update:{activeOrganizationId:n}}),findOrganizationById:async o=>await r.findOne({model:"organization",where:[{field:"id",value:o}]}),findFullOrganization:async(o,n)=>{let[i,a,s]=await Promise.all([r.findOne({model:"organization",where:[{field:"id",value:o}]}),r.findMany({model:"invitation",where:[{field:"organizationId",value:o}]}),r.findMany({model:"member",where:[{field:"organizationId",value:o}]})]);if(!i)return null;let d=s.map(g=>g.userId),c=await r.findMany({model:e.tables.user.tableName,where:[{field:"id",value:d,operator:"in"}]}),l=new Map(c.map(g=>[g.id,g])),p=s.map(g=>{let m=l.get(g.userId);if(!m)throw new H("Unexpected error: User not found for member");return{...g,user:{id:m.id,name:m.name,email:m.email,image:m.image}}});return{...i,invitations:a,members:p}},listOrganizations:async o=>{let n=await r.findMany({model:"member",where:[{field:"userId",value:o}]});if(!n||n.length===0)return[];let i=n.map(s=>s.organizationId);return await r.findMany({model:"organization",where:[{field:"id",value:i,operator:"in"}]})},createInvitation:async({invitation:o,user:n})=>{let a=Z(t?.invitationExpiresIn||1728e5);return await r.create({model:"invitation",data:{id:_(),email:o.email,role:o.role,organizationId:o.organizationId,status:"pending",expiresAt:a,inviterId:n.id}})},findInvitationById:async o=>await r.findOne({model:"invitation",where:[{field:"id",value:o}]}),findPendingInvitation:async o=>(await r.findMany({model:"invitation",where:[{field:"email",value:o.email},{field:"organizationId",value:o.organizationId},{field:"status",value:"pending"}]})).filter(i=>new Date(i.expiresAt)>new Date),updateInvitation:async o=>await r.update({model:"invitation",where:[{field:"id",value:o.invitationId}],update:{status:o.status}})}};var gd=require("better-call");var Rt=require("better-call");var rt=require("better-call"),kt=require("zod");var No=E({body:kt.z.object({csrfToken:kt.z.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=e.headers?.get("origin")||"";if(t){let s=new URL(t).origin;if(e.context.trustedOrigins.includes(s))return}let r=e.body?.csrfToken;if(!r)throw new rt.APIError("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new rt.APIError("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await X(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new rt.APIError("UNAUTHORIZED",{message:"Invalid CSRF Token"})});var Fo=require("std-env");var F=require("better-call");var L=E(async e=>({})),j=E({use:[w]},async e=>({session:e.context.session}));var $=require("zod");var v=require("zod"),ot=v.z.enum(["admin","member","owner"]),Mo=v.z.enum(["pending","accepted","rejected","canceled"]).default("pending"),Rd=v.z.object({id:v.z.string(),name:v.z.string(),slug:v.z.string(),logo:v.z.string().optional(),metadata:v.z.record(v.z.string()).or(v.z.string().transform(e=>JSON.parse(e))).optional(),createdAt:v.z.date()}),Od=v.z.object({id:v.z.string(),email:v.z.string(),organizationId:v.z.string(),userId:v.z.string(),role:ot,createdAt:v.z.date()}),vd=v.z.object({id:v.z.string(),organizationId:v.z.string(),email:v.z.string(),role:ot,status:Mo,inviterId:v.z.string(),expiresAt:v.z.date()});var I=require("better-call"),Ir=u("/organization/invite-member",{method:"POST",use:[L,j],body:$.z.object({email:$.z.string(),role:ot,organizationId:$.z.string().optional(),resend:$.z.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 I.APIError("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new I.APIError("BAD_REQUEST",{message:"Organization not found"});let o=C(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new I.APIError("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new I.APIError("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new I.APIError("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new I.APIError("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 I.APIError("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new I.APIError("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),Ur=u("/organization/accept-invitation",{method:"POST",body:$.z.object({invitationId:$.z.string()}),use:[L,j]},async e=>{let t=e.context.session,r=C(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I.APIError("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:_(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),Er=u("/organization/reject-invitation",{method:"POST",body:$.z.object({invitationId:$.z.string()}),use:[L,j]},async e=>{let t=e.context.session,r=C(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I.APIError("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})}),Tr=u("/organization/cancel-invitation",{method:"POST",body:$.z.object({invitationId:$.z.string()}),use:[L,j]},async e=>{let t=e.context.session,r=C(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new I.APIError("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new I.APIError("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)}),Sr=u("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:$.z.object({id:$.z.string()})},async e=>{let t=await M(e);if(!t)throw new I.APIError("UNAUTHORIZED",{message:"Not authenticated"});let r=C(e.context,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new I.APIError("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new I.APIError("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new I.APIError("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new I.APIError("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})});var le=require("zod");var Pe=require("better-call"),Pr=u("/organization/remove-member",{method:"POST",body:le.z.object({memberIdOrEmail:le.z.string(),organizationId:le.z.string().optional()}),use:[L,j]},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=C(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Pe.APIError("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Pe.APIError("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 Pe.APIError("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Pe.APIError("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Pe.APIError("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Cr=u("/organization/update-member-role",{method:"POST",body:le.z.object({role:le.z.enum(["admin","member","owner"]),memberId:le.z.string(),organizationId:le.z.string().optional()}),use:[L,j]},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=C(e.context,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!"}})});var S=require("zod");var pe=require("better-call"),_r=u("/organization/create",{method:"POST",body:S.z.object({name:S.z.string(),slug:S.z.string(),userId:S.z.string().optional(),logo:S.z.string().optional(),metadata:S.z.record(S.z.string()).optional()}),use:[L,j]},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 pe.APIError("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=C(e.context,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 pe.APIError("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new pe.APIError("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:_(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),zr=u("/organization/update",{method:"POST",body:S.z.object({data:S.z.object({name:S.z.string().optional(),slug:S.z.string().optional()}).partial(),orgId:S.z.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new pe.APIError("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=C(e.context,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)}),Br=u("/organization/delete",{method:"POST",body:S.z.object({orgId:S.z.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=C(e.context,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 pe.APIError("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)}),Lr=u("/organization/get-full",{method:"GET",query:S.z.object({orgId:S.z.string().optional()}),requireHeaders:!0,use:[L,j]},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 C(e.context,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new pe.APIError("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Dr=u("/organization/activate",{method:"POST",body:S.z.object({orgId:S.z.string().nullable().optional()}),use:[j,L]},async e=>{let t=C(e.context,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 pe.APIError("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)}),xr=u("/organization/list",{method:"GET",use:[L,j]},async e=>{let r=await C(e.context,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var qo=e=>{let t={createOrganization:_r,updateOrganization:zr,deleteOrganization:Br,setActiveOrganization:Dr,getFullOrganization:Lr,listOrganization:xr,createInvitation:Ir,cancelInvitation:Tr,acceptInvitation:Ur,getInvitation:Sr,rejectInvitation:Er,removeMember:Pr,updateMemberRole:Cr},r={...bt,...e?.roles};return{id:"organization",endpoints:{...br(t,{orgOptions:e||{},roles:r,getSession:async n=>await M(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Ce.z.object({permission:Ce.z.record(Ce.z.string(),Ce.z.array(Ce.z.string()))}),use:[j]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new Ot.APIError("BAD_REQUEST",{message:"No active organization"});let a=await C(n.context).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Ot.APIError("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:{}}}};var Ve=require("zod");var ze=require("zod");var me=require("better-call");var nt="two-factor";var it="trust-device";var vt=require("zod"),Re=E({body:vt.z.object({trustDevice:vt.z.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(nt),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new me.APIError("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new me.APIError("UNAUTHORIZED",{message:"invalid two factor cookie"});let i=await e.context.adapter.findMany({model:e.context.tables.session.tableName,where:[{field:"userId",value:o}]});if(!i.length)throw new me.APIError("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new me.APIError("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await X(e.context.secret,s.id),c=await e.context.adapter.findOne({model:e.context.tables.user.tableName,where:[{field:"id",value:s.userId}]});if(!c)throw new me.APIError("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await A(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(it,{maxAge:2592e3}),p=await X(e.context.secret,`${c.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:c})},invalid:async()=>{throw new me.APIError("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:c}}}throw new me.APIError("UNAUTHORIZED",{message:"invalid two factor authentication"})});var _e=require("better-call");function $o(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>Q(e?.length??10,W("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function It(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():$o(),n=await Xe({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Vo(e,t){let r=await jr(e.backupCodes,t);return r?r.includes(e.code):!1}async function jr(e,t){let r=Buffer.from(await et({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=ze.z.array(ze.z.string()).safeParse(o);return n.success?n.data:null}var Nr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:ze.z.object({code:ze.z.string(),disableSession:ze.z.boolean().optional()}),use:[Re]},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 _e.APIError("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Vo({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new _e.APIError("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await A(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",use:[w]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new _e.APIError("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await It(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",use:[w]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new _e.APIError("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=jr(n.backupCodes,r.context.secret);if(!i)throw new _e.APIError("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});var qe=require("better-call"),Fr=require("oslo/otp"),Ut=require("zod");var Mr=require("oslo"),qr=(e,t)=>{let r={...e,period:new Mr.TimeSpan(e?.period||3,"m")},o=new Fr.TOTPController({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[Re]},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 qe.APIError("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 qe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:Ut.z.object({code:Ut.z.string()}),use:[Re]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new qe.APIError("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 qe.APIError("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}}};var Oe=require("better-call"),$r=require("oslo"),$e=require("oslo/otp"),Et=require("zod");var Vr=(e,t)=>{let r={...e,digits:6,period:new $r.TimeSpan(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Oe.APIError("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 Oe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new $e.TOTPController(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"GET",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Oe.APIError("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 Oe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:(0,$e.createTOTPKeyURI)(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:Et.z.object({code:Et.z.string()}),use:[Re]},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 Oe.APIError("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 Oe.APIError("BAD_REQUEST",{message:"totp isn't enabled"});let c=new $e.TOTPController(r),l=await et({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await c.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function Tt(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)}var St=require("better-call");var Ho=(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 Qo=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=Vr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=Nr({...e?.backupCodeOptions},t.twoFactorTable),n=qr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ve.z.object({password:Ve.z.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await Tt(i,{password:s,userId:a.id}))throw new St.APIError("BAD_REQUEST",{message:"Invalid password"});let c=Q(16,W("a-z","0-9","-")),l=await Xe({key:i.context.secret,data:c}),p=await It(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ve.z.object({password:Ve.z.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await Tt(i,{password:s,userId:a.id}))throw new St.APIError("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:E(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(it,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[m,k]=c.split("!"),U=await X(i.context.secret,`${s.user.id}!${k}`);if(m===U){let h=await X(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await X(i.context.secret,s.session.id),p=i.context.createAuthCookie(nt,{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}]}};var fe=require("@simplewebauthn/server"),ee=require("better-call");var oe=require("zod");var Wr=require("std-env");var Be=require("@simplewebauthn/browser");var Ko=require("@better-fetch/fetch");var qc=require("nanostores");var Wo=require("@better-fetch/fetch");var Jo=require("nanostores");var Qc=require("@better-fetch/fetch"),st=require("nanostores"),Pt=(e,t,r,o)=>{let n=(0,st.atom)({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():(0,st.onMount)(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};var Hr=require("nanostores"),Qr=(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(0,Be.startAuthentication)(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(0,Be.startRegistration)(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 Be.WebAuthnError?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:{}}),Go=()=>{let e=(0,Hr.atom)();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Qr(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:Pt(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 Zo=e=>{let t=Wr.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new H("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[w],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(Q(32,W("a-z","0-9")))),p;p=await(0,fe.generateRegistrationOptions)({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(m=>({id:m.id,transports:m.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:oe.z.object({email:oe.z.string().optional()}).optional()},async s=>{let d=await M(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await(0,fe.generateAuthenticationOptions)({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(m=>({id:m.id,transports:m.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:oe.z.object({response:oe.z.any(),name:oe.z.string().optional()}),use:[w]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee.APIError("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:g,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new ee.APIError("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await(0,fe.verifyRegistrationResponse)({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:U,registrationInfo:h}=k;if(!U||!h)return s.json(null,{status:400});let{credentialID:R,credentialPublicKey:V,counter:G,credentialDeviceType:O,credentialBackedUp:N}=h,ce=Buffer.from(V).toString("base64"),D=_(),We={name:s.body.name,userId:m.id,webauthnUserID:D,id:R,publicKey:ce,counter:G,deviceType:O,transports:c.response.transports.join(","),backedUp:N,createdAt:new Date},ro=await s.context.adapter.create({model:"passkey",data:We});return s.json(ro,{status:200})}catch(k){throw console.log(k),new ee.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:oe.z.object({response:oe.z.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new ee.APIError("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee.APIError("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new ee.APIError("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:g}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!m)throw new ee.APIError("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await(0,fe.verifyAuthenticationResponse)({response:c,expectedChallenge:g,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:U}=k;if(!U)throw new ee.APIError("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:m.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(m.userId,s.request);if(!h)throw new ee.APIError("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await A(s,h.id),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new ee.APIError("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[w]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:oe.z.object({id:oe.z.string()}),use:[w]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};var te=require("zod");var He=require("better-call");var Ct=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:te.z.object({username:te.z.string(),password:te.z.string(),dontRememberMe:te.z.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:e.context.tables.user.tableName,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:Ct}),new He.APIError("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:e.context.tables.account.tableName,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 He.APIError("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:Ct}),new He.APIError("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new He.APIError("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:u("/sign-up/username",{method:"POST",body:te.z.object({username:te.z.string().min(3).max(20),name:te.z.string(),email:te.z.string().email(),password:te.z.string(),image:te.z.string().optional()})},async e=>{let t=await yt()({...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}}}}});var Kr=require("better-call"),Yo=()=>({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(0,Kr.serializeSigned)("",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}}}]}});var ve=require("zod");var Jr=require("better-call");var Xo=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:ve.z.object({email:ve.z.string().email(),callbackURL:ve.z.string().optional()}),use:[P]},async t=>{let{email:r}=t.body,o=Q(32,W("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 Jr.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:ve.z.object({token:ve.z.string(),callbackURL:ve.z.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await A(t,c.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});var ge=require("zod");var ne=require("better-call");function en(e){return Q(e,W("0-9"))}var tn=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:ge.z.object({phoneNumber:ge.z.string()})},async r=>{if(!e?.sendOTP)throw b.warn("sendOTP not implemented"),new ne.APIError("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=en(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:Z(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:ge.z.object({phoneNumber:ge.z.string(),code:ge.z.string(),disableSession:ge.z.boolean().optional(),updatePhoneNumber:ge.z.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 ne.APIError("BAD_REQUEST",{message:"OTP expired"})):new ne.APIError("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ne.APIError("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await M(r);if(!i)throw new ne.APIError("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ne.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ne.APIError("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new ne.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new ne.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(r,i.id),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};var at=require("zod");var rn=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=Ft(t.context.baseURL)}=e||{},o=_(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await A(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:u("/user/link-anonymous",{method:"POST",body:at.z.object({email:at.z.string().email().optional(),password:at.z.string().min(6)}),use:[w]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await A(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});var f=require("zod");var re=E(async e=>{let t=await M(e);if(!t?.session)throw new F.APIError("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new F.APIError("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),on=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:E(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:f.z.object({userId:f.z.string(),role:f.z.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:f.z.object({email:f.z.string(),password:f.z.string(),name:f.z.string(),role:f.z.string(),data:f.z.optional(f.z.record(f.z.any()))}),use:[re]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new F.APIError("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 F.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[re],query:f.z.object({search:f.z.object({field:f.z.enum(["email","name"]),operator:f.z.enum(["contains","starts_with","ends_with"]).default("contains"),value:f.z.string()}).optional(),limit:f.z.string().or(f.z.number()).optional(),offset:f.z.string().or(f.z.number()).optional(),sortBy:f.z.string().optional(),sortDirection:f.z.enum(["asc","desc"]).optional(),filter:f.z.array(f.z.object({field:f.z.string(),value:f.z.string().or(f.z.number()).or(f.z.boolean()),operator:f.z.enum(["eq","ne","lt","lte","gt","gte"]),connector:f.z.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[re],body:f.z.object({userId:f.z.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:f.z.object({userId:f.z.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:f.z.object({userId:f.z.string(),banReason:f.z.string().optional(),banExpiresIn:f.z.number().optional()}),use:[re]},async t=>{if(t.body.userId===t.context.session.user.id)throw new F.APIError("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:f.z.object({userId:f.z.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new F.APIError("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?Z(e.impersonationSessionDuration,"sec"):Z(60*60,"sec")});if(!o)throw new F.APIError("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:f.z.object({sessionId:f.z.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:f.z.object({userId:f.z.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:f.z.object({userId:f.z.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});var ie=require("zod"),Le=require("better-call");var dt=require("@better-fetch/fetch");var Gr=require("oslo/oauth2");var Zr=require("oslo/jwt");async function nn(e,t,r){if(t==="oidc"&&e.idToken){let n=(0,Zr.parseJWT)(e.idToken);if(n?.payload)return n.payload}return r?(await(0,dt.betterFetch)(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var sn=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:ie.z.object({currentURL:ie.z.string().optional()}).optional(),body:ie.z.object({providerId:ie.z.string(),callbackURL:ie.z.string().optional()}),use:[P]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Le.APIError("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:g,prompt:m,accessType:k}=o,U=i,h=a;if(n){let D=await(0,dt.betterFetch)(n,{onError(We){b.error(We.error,{discoveryUrl:n})}});D.data&&(U=D.data.authorization_endpoint,h=D.data.token_endpoint)}if(!U||!h)throw new Le.APIError("BAD_REQUEST",{message:"Invalid OAuth configuration."});let R=t.query?.currentURL?new URL(t.query?.currentURL):null,V=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${R?.origin}${t.body.callbackURL||""}`,G=await Je(V||R?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,G.hash,t.context.secret,O.state.options);let N=(0,Gr.generateCodeVerifier)();await t.setSignedCookie(O.pkCodeVerifier.name,N,t.context.secret,O.pkCodeVerifier.options);let ce=await B({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:U,state:G.raw,codeVerifier:N,scopes:c||[],disablePkce:!g,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ce.searchParams.set("response_type",p),m&&ce.searchParams.set("prompt",m),k&&ce.searchParams.set("access_type",k),{url:ce.toString(),state:G,codeVerifier:N,redirect:!0}}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:ie.z.object({code:ie.z.string().optional(),error:ie.z.string().optional(),state:ie.z.string()})},async t=>{if(t.query.error||!t.query.code){let N=Ie(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${N}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Le.APIError("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=Ie(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,c=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw b.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await Ke(a,p))throw b.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,k=r.userInfoUrl;if(r.discoveryUrl){let O=await(0,dt.betterFetch)(r.discoveryUrl,{method:"GET"});O.data&&(m=O.data.token_endpoint,k=O.data.userinfo_endpoint)}try{if(!m)throw new Le.APIError("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await T({code:c,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:m})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Le.APIError("BAD_REQUEST",{message:"Invalid OAuth configuration."});let U=r.getUserInfo?await r.getUserInfo(n):await nn(n,r.type||"oauth2",k),h=_(),R=U?Ye.safeParse({...U,id:h}):null;if(!R?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let V=await t.context.internalAdapter.findUserByEmail(R.data.email).catch(O=>{throw b.error(`Better auth was unable to query your database.
|
|
84
|
+
Error: `,O),t.redirect(`${l}?error=internal_server_error`)}),G=V?.user.id||h;if(V){let O=V.accounts.find(D=>D.providerId===r.providerId),N=t.context.options.account?.accountLinking?.trustedProviders,ce=N?N.includes(r.providerId):!0;if(!O&&(!R?.data.emailVerified||!ce)){let D;try{D=new URL(l),D.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(D.toString())}if(!O)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:R.data.id,id:`${r.providerId}:${R.data.id}`,userId:V.user.id,...Ue(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(R.data,{...Ue(n),id:`${r.providerId}:${R.data.id}`,providerId:r.providerId,accountId:R.data.id})}catch{let N=new URL(l);throw N.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",N.toString()),t.redirect(N.toString())}try{let O=await t.context.internalAdapter.createSession(G||h,t.request);if(!O)throw t.redirect(`${l}?error=unable_to_create_session`);await A(t,O.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});var De=require("zod"),Yr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},ol=De.z.object({id:De.z.string(),publicKey:De.z.string(),privateKey:De.z.string(),createdAt:De.z.date()});var _t=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}})});var de=require("jose");var he=require("crypto");function Xr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=(0,he.createHash)("sha256").update(e).digest(),t}function eo(e,t){let r=Xr(t),o=(0,he.randomBytes)(12),n=(0,he.createCipheriv)("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 to(e,t){let r=Xr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=(0,he.createDecipheriv)("aes-256-gcm",r,a);d.setAuthTag(s);let c=d.update(o,"base64","utf8");return c+=d.final("utf8"),c}var an=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await _t(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[w]},async t=>{let r=_t(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await(0,de.generateKeyPair)(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await(0,de.exportJWK)(c),g=await(0,de.exportJWK)(l),m=JSON.stringify(g),k={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(eo(m,t.context.options.secret)):m,createdAt:new Date};o=await r.createJwk(k)}let i=n?to(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await(0,de.importJWK)(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new de.SignJWT({...s,...t.context.session.session.impersonatedBy?{impersonatedBy:t.context.session.session.impersonatedBy}:{}}).setProtectedHeader({alg:e?.jwks?.keyPairConfig?.alg??"EdDSA",kid:o.id}).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:Yr});var Qe=require("zod");var dn=e=>{let t={maximumSessions:5,...e},r=o=>o.includes("_multi-");return{id:"multi-session",endpoints:{listDeviceSessions:u("/multi-session/list-device-sessions",{method:"GET",requireHeaders:!0},async o=>{let n=o.headers?.get("cookie");if(!n)return o.json([]);let i=Object.fromEntries(Ge(n)),a=(await Promise.all(Object.entries(i).filter(([c])=>r(c)).map(async([c])=>await o.getSignedCookie(c,o.context.secret)))).filter(c=>c!==void 0),d=(await o.context.internalAdapter.findSessions(a)).filter(c=>c&&c.session.expiresAt>new Date).filter((c,l,p)=>l===p.findIndex(g=>g.user.id===c.user.id));return Object.entries(i).filter(([c])=>r(c)).forEach(([c,l])=>{d.some(p=>p.session.id===l)||o.setCookie(c,"",{...o.context.authCookies.sessionToken.options,maxAge:0})}),o.json(d)}),setActiveSession:u("/multi-session/set-active",{method:"POST",body:Qe.z.object({sessionId:Qe.z.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new F.APIError("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);if(!s||s.session.expiresAt<new Date)throw o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),new F.APIError("UNAUTHORIZED",{message:"Invalid session id"});return await o.setSignedCookie(o.context.authCookies.sessionToken.name,n,o.context.secret,o.context.authCookies.sessionToken.options),o.json(s)}),DeviceSession:u("/multi-session/revoke",{method:"POST",body:Qe.z.object({sessionId:Qe.z.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new F.APIError("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);return!s||s.session.expiresAt<new Date?(o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0})):(await o.context.internalAdapter.deleteSession(n),o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0}))})},hooks:{after:[{matcher:()=>!0,handler:E(async o=>{if(!o.context.returned||!(o.context.returned instanceof Response))return;let n=o.context.returned.headers.get("set-cookie");if(!n)return;let i=xt(n),a=o.context.authCookies.sessionToken,s=i.get(a.name)?.value;if(!s)return;let d=Ge(o.headers?.get("cookie")||""),c=s.split(".")[0],l=`${a.name}_multi-${c}`;if(i.get(l)||d.get(l))return;if(Object.keys(Object.fromEntries(d)).filter(r).length+(n.includes("session_token")?1:0)>t.maximumSessions)throw new F.APIError("UNAUTHORIZED",{message:"Maximum number of device sessions reached."});await o.setSignedCookie(l,c,o.context.secret,a.options);let g=o.context.returned;return g.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:g}})},{matcher:o=>o.path==="/sign-out",handler:E(async o=>{let n=o.headers?.get("cookie");if(!n)return;let i=Object.fromEntries(Ge(n));await Promise.all(Object.entries(i).map(async([s,d])=>{r(s)&&(o.setCookie(s,"",{maxAge:0}),await o.context.internalAdapter.deleteSession(s.split("_multi-")[1]))}));let a=o.context.returned;return a?.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:a}})}]}}};0&&(module.exports={HIDE_METADATA,ac,admin,adminMiddleware,anonymous,bearer,createAuthEndpoint,createAuthMiddleware,genericOAuth,getPasskeyActions,jwt,magicLink,multiSession,optionsMiddleware,organization,passkey,passkeyClient,phoneNumber,twoFactor,twoFactorClient,username});
|
package/dist/plugins.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var wr=Object.defineProperty;var yr=(e,t)=>{for(var r in t)wr(e,r,{get:t[r],enumerable:!0})};import{APIError as er}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as br,createMiddleware as at,createMiddlewareCreator as Ar}from"better-call";var dt=at(async()=>({})),T=Ar({use:[dt,at(async()=>({}))]}),u=br({use:[dt]});import{APIError as Z}from"better-call";import{generateCodeVerifier as Jr}from"oslo/oauth2";import{z as Q}from"zod";import{generateState as kr}from"oslo/oauth2";import{z as Le}from"zod";import{sha256 as ct}from"oslo/crypto";function Ze(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let i=0;i<r.length;i++)n|=r[i]^o[i];return n===0}async function ut(e){let t=await ct(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function Be(e,t){let r=await ct(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Ze(r,o)}import"better-call";async function De(e){let t=kr(),r=JSON.stringify({code:t,callbackURL:e}),o=await ut(r);return{raw:r,hash:o}}function we(e){return Le.object({code:Le.string(),callbackURL:Le.string().optional(),currentURL:Le.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as gn}from"oslo";var $=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};import{env as yn,isProduction as bn}from"std-env";async function A(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function ve(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function lt(e){let t=new Map;return e.split(", ").forEach(o=>{let[n,...i]=o.split("; "),[a,s]=n.split("="),d={value:s};i.forEach(c=>{let[l,p]=c.split("=");d[l.toLowerCase()]=p||!0}),t.set(a,d)}),t}function xe(e){let t=e.split("; "),r=new Map;return t.forEach(o=>{let[n,i]=o.split("=");r.set(n,i)}),r}import{APIError as vr}from"better-call";import{createConsola as Rr}from"consola";var ce=Rr({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),Or=e=>({log:(...t)=>{!e?.disabled&&ce.log("",...t)},error:(...t)=>{!e?.disabled&&ce.error("",...t)},warn:(...t)=>{!e?.disabled&&ce.warn("",...t)},info:(...t)=>{!e?.disabled&&ce.info("",...t)},debug:(...t)=>{!e?.disabled&&ce.debug("",...t)},box:(...t)=>{!e?.disabled&&ce.box("",...t)},success:(...t)=>{!e?.disabled&&ce.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
|
|
2
|
-
`)}}),b=Or();var S=T(async e=>{let{body:t,query:r,headers:o,context:n}=e,i=t?.callbackURL||r?.callbackURL||r?.redirectTo||t?.redirectTo,a=r?.currentURL||o?.get("referer")||n.baseURL,s=n.trustedOrigins,d=(c,l)=>{if(c?.startsWith("http")&&!s.some(g=>c.startsWith(g)))throw b.error(`Invalid ${l}`,{[l]:c,trustedOrigins:s}),new vr("FORBIDDEN",{message:`Invalid ${l}`})};d(i,"callbackURL"),d(a,"currentURL")});import{parseJWT as Tr}from"oslo/jwt";import{sha256 as Ir}from"oslo/crypto";import{env as Tn}from"std-env";function pt(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Ur}from"oslo/encoding";async function mt(e){let t=await Ir(new TextEncoder().encode(e));return Ur.encode(new Uint8Array(t),{includePadding:!1})}function ft(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 c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await mt(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,g)=>(p[g]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}import{betterFetch as Er}from"@better-fetch/fetch";async function U({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let i=new URLSearchParams;i.set("grant_type","authorization_code"),i.set("code",e),t&&i.set("code_verifier",t),i.set("redirect_uri",r),i.set("client_id",o.clientId),i.set("client_secret",o.clientSecret);let{data:a,error:s}=await Er(n,{method:"POST",body:i,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(s)throw s;return ft(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 gt=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${i.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>U({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Tr(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Sr}from"@better-fetch/fetch";var ht=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Sr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Pr}from"@better-fetch/fetch";var wt=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 Pr("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as yt}from"@better-fetch/fetch";var bt=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 yt("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await yt("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as Cr}from"oslo/jwt";var At=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 $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("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=Cr(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as _r}from"@better-fetch/fetch";import{parseJWT as zr}from"oslo/jwt";var kt=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=zr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await _r(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){b.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as Br}from"@better-fetch/fetch";var Rt=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 Br("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var de={isAction:!1};function Lr(e){return e.toString(2).padStart(8,"0")}function Dr(e){return[...e].map(t=>Lr(t)).join("")}function Ot(e){return parseInt(Dr(e),2)}function xr(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=Ot(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Ot(o);return n}function V(e,t){let r="";for(let o=0;o<e;o++)r+=t[xr(t.length)];return r}function H(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}import{nanoid as jr}from"nanoid";var _=e=>jr(e);import{parseJWT as Nr}from"oslo/jwt";var vt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return 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=Nr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Fr}from"@better-fetch/fetch";var It=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return 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 Fr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var Mr={apple:gt,discord:ht,facebook:wt,github:bt,microsoft:kt,google:At,spotify:Rt,twitch:vt,twitter:It},Ut=Object.keys(Mr);import{TimeSpan as Vr}from"oslo";import{createJWT as Hr,validateJWT as Qr}from"oslo/jwt";import{z as G}from"zod";import{APIError as be}from"better-call";import{APIError as Ie}from"better-call";var J=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Et}from"zod";var Tt=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return ve(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,i=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+i*1e3<=Date.now()){let d=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:J(e.context.sessionConfig.expiresIn,"sec")});if(!d)return ve(e),e.json(null,{status:401});let c=(d.expiresAt.valueOf()-Date.now())/1e3;return await A(e,d.id,!1,{maxAge:c}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),F=async e=>await Tt()({...e,_flag:"json",headers:e.headers}),w=T(async e=>{let t=await F(e);if(!t?.session)throw new Ie("UNAUTHORIZED");return{session:t}});var qr=u("/user/revoke-session",{method:"POST",body:Et.object({id:Et.string()}),use:[w],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Ie("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Ie("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),$r=u("/user/revoke-sessions",{method:"POST",use:[w],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function oe(e,t,r){return await Hr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new Vr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Wr=u("/send-verification-email",{method:"POST",query:G.object({currentURL:G.string().optional()}).optional(),body:G.object({email:G.string().email(),callbackURL:G.string().optional()}),use:[S]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be("BAD_REQUEST",{message:"User not found"});let o=await oe(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),Kr=u("/verify-email",{method:"GET",query:G.object({token:G.string(),callbackURL:G.string().optional()}),use:[S]},async e=>{let{token:t}=e.query,r;try{r=await Qr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be("BAD_REQUEST",{message:"Invalid token"})}let n=G.object({email:G.string().email(),updateTo:G.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await F(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Gr=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:Q.object({currentURL:Q.string().optional()}).optional(),body:Q.object({callbackURL:Q.string().optional(),provider:Q.enum(Ut)}),use:[S]},async e=>{let t=e.context.socialProviders.find(d=>d.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new Z("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,i=await De(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=Jr();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let s=await t.createAuthorizationURL({state:i.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:s.toString(),state:i,codeVerifier:a,redirect:!0})}),Zr=u("/sign-in/email",{method:"POST",body:Q.object({email:Q.string(),password:Q.string(),callbackURL:Q.string().optional(),dontRememberMe:Q.boolean().default(!1).optional()}),use:[S]},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.context.logger.error("Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!"),new Z("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new Z("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new Z("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw b.error("Email verification is required but no email verification handler is provided"),new Z("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await oe(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new Z("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new Z("UNAUTHORIZED",{message:"Failed to create session"});return await A(e,c.id,e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as Ne}from"zod";import{z as y}from"zod";var Ds=y.object({id:y.string(),providerId:y.string(),accountId:y.string(),userId:y.string(),accessToken:y.string().nullable().optional(),refreshToken:y.string().nullable().optional(),idToken:y.string().nullable().optional(),expiresAt:y.date().nullable().optional(),password:y.string().optional().nullable()}),je=y.object({id:y.string(),email:y.string().transform(e=>e.toLowerCase()),emailVerified:y.boolean().default(!1),name:y.string(),image:y.string().optional(),createdAt:y.date().default(new Date),updatedAt:y.date().default(new Date)}),xs=y.object({id:y.string(),userId:y.string(),expiresAt:y.date(),ipAddress:y.string().optional(),userAgent:y.string().optional()}),js=y.object({id:y.string(),value:y.string(),expiresAt:y.date(),identifier:y.string()});function Yr(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function St(e,t){let r={...e.user?.additionalFields};return Yr(t||{},{fields:r})}var Xr=u("/callback/:id",{method:"GET",query:Ne.object({state:Ne.string(),code:Ne.string().optional(),error:Ne.string().optional()}),metadata:de},async e=>{if(e.query.error||!e.query.code){let R=we(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${R}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(h=>h.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=we(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,i=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!i)throw b.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await Be(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(h){throw e.context.logger.error(h),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(d).then(h=>h?.user),l=_(),p=je.safeParse({...c,id:l});if(!c||p.success===!1)throw 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`);function g(h){throw e.redirect(`${n||o||`${e.context.baseURL}/error`}?error=${h}`)}let f=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(h=>{throw b.error(`Better auth was unable to query your database.
|
|
3
|
-
Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),k=
|
|
2
|
+
`)}}),b=Or();var S=T(async e=>{let{body:t,query:r,headers:o,context:n}=e,i=t?.callbackURL||r?.callbackURL||r?.redirectTo||t?.redirectTo,a=r?.currentURL||o?.get("referer")||n.baseURL,s=n.trustedOrigins,d=(c,l)=>{if(c?.startsWith("http")&&!s.some(g=>c.startsWith(g)))throw b.error(`Invalid ${l}`,{[l]:c,trustedOrigins:s}),new vr("FORBIDDEN",{message:`Invalid ${l}`})};d(i,"callbackURL"),d(a,"currentURL")});import{parseJWT as Tr}from"oslo/jwt";import{sha256 as Ir}from"oslo/crypto";import{env as Tn}from"std-env";function pt(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Ur}from"oslo/encoding";async function mt(e){let t=await Ir(new TextEncoder().encode(e));return Ur.encode(new Uint8Array(t),{includePadding:!1})}function ft(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 c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await mt(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,g)=>(p[g]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}import{betterFetch as Er}from"@better-fetch/fetch";async function U({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let i=new URLSearchParams;i.set("grant_type","authorization_code"),i.set("code",e),t&&i.set("code_verifier",t),i.set("redirect_uri",r),i.set("client_id",o.clientId),i.set("client_secret",o.clientSecret);let{data:a,error:s}=await Er(n,{method:"POST",body:i,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(s)throw s;return ft(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 gt=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${i.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>U({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Tr(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Sr}from"@better-fetch/fetch";var ht=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Sr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Pr}from"@better-fetch/fetch";var wt=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 Pr("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as yt}from"@better-fetch/fetch";var bt=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 yt("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await yt("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as Cr}from"oslo/jwt";var At=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 $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("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=Cr(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as _r}from"@better-fetch/fetch";import{parseJWT as zr}from"oslo/jwt";var kt=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=zr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await _r(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){b.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as Br}from"@better-fetch/fetch";var Rt=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 Br("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var de={isAction:!1};function Lr(e){return e.toString(2).padStart(8,"0")}function Dr(e){return[...e].map(t=>Lr(t)).join("")}function Ot(e){return parseInt(Dr(e),2)}function xr(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=Ot(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Ot(o);return n}function V(e,t){let r="";for(let o=0;o<e;o++)r+=t[xr(t.length)];return r}function H(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}import{nanoid as jr}from"nanoid";var _=e=>jr(e);import{parseJWT as Nr}from"oslo/jwt";var vt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return 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=Nr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Fr}from"@better-fetch/fetch";var It=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return 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 Fr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var Mr={apple:gt,discord:ht,facebook:wt,github:bt,microsoft:kt,google:At,spotify:Rt,twitch:vt,twitter:It},Ut=Object.keys(Mr);import{TimeSpan as Vr}from"oslo";import{createJWT as Hr,validateJWT as Qr}from"oslo/jwt";import{z as G}from"zod";import{APIError as be}from"better-call";import{APIError as Ie}from"better-call";var J=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Et}from"zod";var Tt=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return ve(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,i=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+i*1e3<=Date.now()){let d=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:J(e.context.sessionConfig.expiresIn,"sec")});if(!d)return ve(e),e.json(null,{status:401});let c=(d.expiresAt.valueOf()-Date.now())/1e3;return await A(e,d.id,!1,{maxAge:c}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),F=async e=>await Tt()({...e,_flag:"json",headers:e.headers}),w=T(async e=>{let t=await F(e);if(!t?.session)throw new Ie("UNAUTHORIZED");return{session:t}});var qr=u("/user/revoke-session",{method:"POST",body:Et.object({id:Et.string()}),use:[w],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Ie("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Ie("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),$r=u("/user/revoke-sessions",{method:"POST",use:[w],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function oe(e,t,r){return await Hr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new Vr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Wr=u("/send-verification-email",{method:"POST",query:G.object({currentURL:G.string().optional()}).optional(),body:G.object({email:G.string().email(),callbackURL:G.string().optional()}),use:[S]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be("BAD_REQUEST",{message:"User not found"});let o=await oe(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),Kr=u("/verify-email",{method:"GET",query:G.object({token:G.string(),callbackURL:G.string().optional()}),use:[S]},async e=>{let{token:t}=e.query,r;try{r=await Qr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be("BAD_REQUEST",{message:"Invalid token"})}let n=G.object({email:G.string().email(),updateTo:G.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await F(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(s,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var Gr=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:Q.object({currentURL:Q.string().optional()}).optional(),body:Q.object({callbackURL:Q.string().optional(),provider:Q.enum(Ut)}),use:[S]},async e=>{let t=e.context.socialProviders.find(d=>d.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new Z("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,i=await De(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=Jr();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let s=await t.createAuthorizationURL({state:i.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:s.toString(),state:i,codeVerifier:a,redirect:!0})}),Zr=u("/sign-in/email",{method:"POST",body:Q.object({email:Q.string(),password:Q.string(),callbackURL:Q.string().optional(),dontRememberMe:Q.boolean().default(!1).optional()}),use:[S]},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.context.logger.error("Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!"),new Z("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});if(!Q.string().email().safeParse(t).success)throw new Z("BAD_REQUEST",{message:"Invalid email"});let i=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!i)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let a=i.accounts.find(l=>l.providerId==="credential");if(!a)throw e.context.logger.error("Credential account not found",{email:t}),new Z("UNAUTHORIZED",{message:"Invalid email or password"});let s=a?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new Z("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(s,r))throw e.context.logger.error("Invalid password"),new Z("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!i.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw b.error("Email verification is required but no email verification handler is provided"),new Z("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let l=await oe(e.context.secret,i.user.email),p=`${e.context.options.baseURL}/verify-email?token=${l}`;throw await e.context.options.emailVerification.sendVerificationEmail(i.user,p,l),e.context.logger.error("Email not verified",{email:t}),new Z("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let c=await e.context.internalAdapter.createSession(i.user.id,e.headers,e.body.dontRememberMe);if(!c)throw e.context.logger.error("Failed to create session"),new Z("UNAUTHORIZED",{message:"Failed to create session"});return await A(e,c.id,e.body.dontRememberMe),e.json({user:i.user,session:c,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as Ne}from"zod";import{z as y}from"zod";var Ds=y.object({id:y.string(),providerId:y.string(),accountId:y.string(),userId:y.string(),accessToken:y.string().nullable().optional(),refreshToken:y.string().nullable().optional(),idToken:y.string().nullable().optional(),expiresAt:y.date().nullable().optional(),password:y.string().optional().nullable()}),je=y.object({id:y.string(),email:y.string().transform(e=>e.toLowerCase()),emailVerified:y.boolean().default(!1),name:y.string(),image:y.string().optional(),createdAt:y.date().default(new Date),updatedAt:y.date().default(new Date)}),xs=y.object({id:y.string(),userId:y.string(),expiresAt:y.date(),ipAddress:y.string().optional(),userAgent:y.string().optional()}),js=y.object({id:y.string(),value:y.string(),expiresAt:y.date(),identifier:y.string()});function Yr(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function St(e,t){let r={...e.user?.additionalFields};return Yr(t||{},{fields:r})}var Xr=u("/callback/:id",{method:"GET",query:Ne.object({state:Ne.string(),code:Ne.string().optional(),error:Ne.string().optional()}),metadata:de},async e=>{if(e.query.error||!e.query.code){let R=we(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${R}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(h=>h.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=we(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,i=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!i)throw b.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await Be(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(h){throw e.context.logger.error(h),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(d).then(h=>h?.user),l=_(),p=je.safeParse({...c,id:l});if(!c||p.success===!1)throw 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`);function g(h){throw e.redirect(`${n||o||`${e.context.baseURL}/error`}?error=${h}`)}let m=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(h=>{throw b.error(`Better auth was unable to query your database.
|
|
3
|
+
Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),k=m?.user.id;if(m){if(!m.accounts.find(R=>R.providerId===t.id)){(!e.context.options.account?.accountLinking?.trustedProviders?.includes(t.id)&&!c.emailVerified||!e.context.options.account?.accountLinking?.enabled)&&g("account_not_linked");try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:m.user.id,...ye(d)})}catch(K){b.error("Unable to link account",K),g("unable_to_link_account")}}}else try{let h=c.emailVerified||!1,R=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:h},{...ye(d),providerId:t.id,accountId:c.id.toString()});if(k=R?.user.id,!h&&R&&e.context.options.emailVerification?.sendOnSignUp){let q=await oe(e.context.secret,c.email),K=`${e.context.baseURL}/verify-email?token=${q}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(R.user,K,q)}}catch(h){b.error("Unable to create user",h),g("unable_to_create_user")}k||g("unable_to_create_user");let I=await e.context.internalAdapter.createSession(k,e.request);throw I||g("unable_to_create_session"),await A(e,I.id),e.redirect(o)});import"zod";import{APIError as eo}from"better-call";var to=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new eo("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),ve(e),e.json({success:!0})});import{z as X}from"zod";import{APIError as Fe}from"better-call";var ro=u("/forget-password",{method:"POST",body:X.object({email:X.string().email(),redirectTo:X.string()}),use:[S]},async e=>{if(!e.context.options.emailAndPassword?.sendResetPassword)throw e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function in your auth config!"),new Fe("BAD_REQUEST",{message:"Reset password isn't enabled"});let{email:t,redirectTo:r}=e.body,o=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!o)return e.context.logger.error("Reset Password: User not found",{email:t}),e.json({status:!1},{body:{status:!0}});let n=60*60*1,i=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),a=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${a}`,expiresAt:i});let s=`${e.context.baseURL}/reset-password/${a}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(o.user,s),e.json({status:!0})}),oo=u("/reset-password/:token",{method:"GET",query:X.object({callbackURL:X.string()}),use:[S]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),no=u("/reset-password",{query:X.optional(X.object({token:X.string()})),method:"POST",body:X.object({newPassword:X.string()})},async e=>{let t=e.query?.token;if(!t)throw new Fe("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new Fe("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let i=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(i)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:i,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(i,a))throw new Fe("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{z as B}from"zod";import{APIError as N}from"better-call";var io=u("/user/update",{method:"POST",body:B.object({name:B.string().optional(),image:B.string().optional()}),use:[w,S]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),so=u("/user/change-password",{method:"POST",body:B.object({newPassword:B.string(),currentPassword:B.string(),revokeOtherSessions:B.boolean().optional()}),use:[w]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,i=e.context.password.config.minPasswordLength;if(t.length<i)throw e.context.logger.error("Password is too short"),new N("BAD_REQUEST",{message:"Password is too short"});let a=e.context.password.config.maxPasswordLength;if(t.length>a)throw e.context.logger.error("Password is too long"),new N("BAD_REQUEST",{message:"Password too long"});let d=(await e.context.internalAdapter.findAccounts(n.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!d||!d.password)throw new N("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new N("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:c}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new N("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await A(e,p.id)}return e.json(n.user)}),ao=u("/user/set-password",{method:"POST",body:B.object({newPassword:B.string()}),use:[w]},async e=>{let{newPassword:t}=e.body,r=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)throw e.context.logger.error("Password is too short"),new N("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new N("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(r.user.id)).find(d=>d.providerId==="credential"&&d.password),s=await e.context.password.hash(t);if(!a)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:s}),e.json(r.user);throw new N("BAD_REQUEST",{message:"user already has a password"})}),co=u("/user/delete",{method:"POST",body:B.object({password:B.string()}),use:[w]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new N("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new N("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)}),uo=u("/user/change-email",{method:"POST",query:B.object({currentURL:B.string().optional()}).optional(),body:B.object({newEmail:B.string().email(),callbackURL:B.string().optional()}),use:[w,S]},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new N("BAD_REQUEST",{message:"Change email is disabled"});if(e.body.newEmail===e.context.session.user.email)throw e.context.logger.error("Email is the same"),new N("BAD_REQUEST",{message:"Email is the same"});if(await e.context.internalAdapter.findUserByEmail(e.body.newEmail))throw e.context.logger.error("Email already exists"),new N("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let n=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:n,status:!0})}if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new N("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await oe(e.context.secret,e.context.session.user.email,e.body.newEmail),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(e.context.session.user,o,r),e.json({user:null,status:!0})});import{xchacha20poly1305 as Pt}from"@noble/ciphers/chacha";import{bytesToHex as lo,hexToBytes as po,utf8ToBytes as mo}from"@noble/ciphers/utils";import{managedNonce as Ct}from"@noble/ciphers/webcrypto";import{sha256 as _t}from"oslo/crypto";import{decodeHex as Oa,encodeHex as va}from"oslo/encoding";import{scryptAsync as Ea}from"@noble/hashes/scrypt";async function Y(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),i=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(i)))}var Me=async({key:e,data:t})=>{let r=await _t(new TextEncoder().encode(e)),o=mo(t),n=Ct(Pt)(new Uint8Array(r));return lo(n.encrypt(o))},qe=async({key:e,data:t})=>{let r=await _t(new TextEncoder().encode(e)),o=po(t),n=Ct(Pt)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var fo=u("/csrf",{method:"GET",metadata:de},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t){let[i,a]=t.split("!")||[null,null];return e.json({csrfToken:i})}let r=V(32,H("a-z","0-9","A-Z")),o=await Y(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),e.json({csrfToken:r})});var go=(e="Unknown")=>`<!DOCTYPE html>
|
|
4
4
|
<html lang="en">
|
|
5
5
|
<head>
|
|
6
6
|
<meta charset="UTF-8">
|
|
@@ -80,5 +80,5 @@ Error: `,h),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)
|
|
|
80
80
|
<div class="error-code">Error Code: <span id="errorCode">${e}</span></div>
|
|
81
81
|
</div>
|
|
82
82
|
</body>
|
|
83
|
-
</html>`,ho=u("/error",{method:"GET",metadata:de},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(go(t),{headers:{"Content-Type":"text/html"}})});var wo=u("/ok",{method:"GET",metadata:de},async e=>e.json({ok:!0}));import{z as Ae}from"zod";import{APIError as ue}from"better-call";var Ye=()=>u("/sign-up/email",{method:"POST",query:Ae.object({currentURL:Ae.string().optional()}).optional(),body:Ae.record(Ae.string(),Ae.any()),use:[S]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!Ae.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let c=e.context.password.config.minPasswordLength;if(n.length<c)throw e.context.logger.error("Password is too short"),new ue("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new ue("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new ue("UNPROCESSABLE_ENTITY",{message:"Failed to create user"});let g=St(e.context.options,s),f=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1});if(!f)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let k=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:f.id,providerId:"credential",accountId:f.id,password:k,expiresAt:J(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let h=await oe(e.context.secret,f.email),R=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(f,R,h)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({user:f,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:null}});let I=await e.context.internalAdapter.createSession(f.id,e.request);if(!I)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await A(e,I.id),e.json({user:f,session:I},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:f,session:I}})});var zt=(e,t)=>{let r={};for(let[o,n]of Object.entries(e))r[o]=i=>n({...i,context:{...t,...i.context}}),r[o].path=n.path,r[o].method=n.method,r[o].options=n.options,r[o].headers=n.headers;return r};var Nt={};yr(Nt,{AccessControl:()=>Ue,ParsingError:()=>le,Role:()=>ke,adminAc:()=>Dt,createAccessControl:()=>Bt,defaultAc:()=>$e,defaultRoles:()=>Xe,defaultStatements:()=>Lt,memberAc:()=>jt,ownerAc:()=>xt,permissionFromString:()=>yo});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},Ue=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new ke(t)}},ke=class e{statements;constructor(t){this.statements=t}authorize(t,r){for(let[o,n]of Object.entries(t)){let i=this.statements[o];if(!i)return{success:!1,error:`You are not allowed to access resource: ${o}`};let a=r==="OR"?n.some(s=>i.includes(s)):n.every(s=>i.includes(s));return a?{success:a}:{success:!1,error:`unauthorized to access resource "${o}"`}}return{success:!1,error:"Not authorized"}}static fromString(t){let r=JSON.parse(t);if(typeof r!="object")throw new le("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new le("invalid resource identifier",o);if(!Array.isArray(n))throw new le("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new le("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var Bt=e=>new Ue(e),Lt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},$e=Bt(Lt),Dt=$e.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),xt=$e.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),jt=$e.newRole({organization:[],member:[],invitation:[]}),Xe={admin:Dt,owner:xt,member:jt};var yo=e=>ke.fromString(e??"");var P=(e,t)=>({findOrganizationBySlug:async r=>await e.findOne({model:"organization",where:[{field:"slug",value:r}]}),createOrganization:async r=>{let o=await e.create({model:"organization",data:{...r.organization,metadata:r.organization.metadata?JSON.stringify(r.organization.metadata):void 0}}),n=await e.create({model:"member",data:{id:_(),organizationId:o.id,userId:r.user.id,createdAt:new Date,email:r.user.email,role:t?.creatorRole||"owner"}});return{...o,metadata:o.metadata?JSON.parse(o.metadata):void 0,members:[{...n,user:{id:r.user.id,name:r.user.name,email:r.user.email,image:r.user.image}}]}},findMemberByEmail:async r=>{let o=await e.findOne({model:"member",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberByOrgId:async r=>{let[o,n]=await Promise.all([await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{field:"organizationId",value:r.organizationId}]}),await e.findOne({model:"user",where:[{field:"id",value:r.userId}]})]);return!n||!o?null:{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}},findMemberById:async r=>{let o=await e.findOne({model:"member",where:[{field:"id",value:r}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},createMember:async r=>await e.create({model:"member",data:r}),updateMember:async(r,o)=>await e.update({model:"member",where:[{field:"id",value:r}],update:{role:o}}),deleteMember:async r=>await e.delete({model:"member",where:[{field:"id",value:r}]}),updateOrganization:async(r,o)=>await e.update({model:"organization",where:[{field:"id",value:r}],update:o}),deleteOrganization:async r=>(await e.delete({model:"member",where:[{field:"organizationId",value:r}]}),await e.delete({model:"invitation",where:[{field:"organizationId",value:r}]}),await e.delete({model:"organization",where:[{field:"id",value:r}]}),r),setActiveOrganization:async(r,o)=>await e.update({model:"session",where:[{field:"id",value:r}],update:{activeOrganizationId:o}}),findOrganizationById:async r=>await e.findOne({model:"organization",where:[{field:"id",value:r}]}),findFullOrganization:async(r,o)=>{let[n,i,a]=await Promise.all([e.findOne({model:"organization",where:[{field:"id",value:r}]}),e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),e.findMany({model:"member",where:[{field:"organizationId",value:r}]})]);if(!n)return null;let s=a.map(p=>p.userId),d=await e.findMany({model:"user",where:[{field:"id",value:s,operator:"in"}]}),c=new Map(d.map(p=>[p.id,p])),l=a.map(p=>{let g=c.get(p.userId);if(!g)throw new $("Unexpected error: User not found for member");return{...p,user:{id:g.id,name:g.name,email:g.email,image:g.image}}});return{...n,invitations:i,members:l}},listOrganizations:async r=>{let o=await e.findMany({model:"member",where:[{field:"userId",value:r}]});if(!o||o.length===0)return[];let n=o.map(a=>a.organizationId);return await e.findMany({model:"organization",where:[{field:"id",value:n,operator:"in"}]})},createInvitation:async({invitation:r,user:o})=>{let i=J(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:_(),email:r.email,role:r.role,organizationId:r.organizationId,status:"pending",expiresAt:i,inviterId:o.id}})},findInvitationById:async r=>await e.findOne({model:"invitation",where:[{field:"id",value:r}]}),findPendingInvitation:async r=>(await e.findMany({model:"invitation",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId},{field:"status",value:"pending"}]})).filter(n=>new Date(n.expiresAt)>new Date),updateInvitation:async r=>await e.update({model:"invitation",where:[{field:"id",value:r.invitationId}],update:{status:r.status}})});import"better-call";import{APIError as Gd,createRouter as Zd,statusCode as Yd}from"better-call";import{APIError as et}from"better-call";import{z as Ft}from"zod";var bo=T({body:Ft.object({csrfToken:Ft.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=e.headers?.get("origin")||"";if(t){let s=new URL(t).origin;if(e.context.trustedOrigins.includes(s))return}let r=e.body?.csrfToken;if(!r)throw new et("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await Y(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{isTest as Nd}from"std-env";import{APIError as M}from"better-call";var L=T(async e=>({})),x=T({use:[w]},async e=>({session:e.context.session}));import{z as W}from"zod";import{z as v}from"zod";var Ve=v.enum(["admin","member","owner"]),Ao=v.enum(["pending","accepted","rejected","canceled"]).default("pending"),kc=v.object({id:v.string(),name:v.string(),slug:v.string(),logo:v.string().optional(),metadata:v.record(v.string()).or(v.string().transform(e=>JSON.parse(e))).optional(),createdAt:v.date()}),Rc=v.object({id:v.string(),email:v.string(),organizationId:v.string(),userId:v.string(),role:Ve,createdAt:v.date()}),Oc=v.object({id:v.string(),organizationId:v.string(),email:v.string(),role:Ve,status:Ao,inviterId:v.string(),expiresAt:v.date()});import{APIError as E}from"better-call";var Mt=u("/organization/invite-member",{method:"POST",use:[L,x],body:W.object({email:W.string(),role:Ve,organizationId:W.string().optional(),resend:W.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw b.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new E("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new E("BAD_REQUEST",{message:"Organization not found"});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new E("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new E("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new E("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new E("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),qt=u("/organization/accept-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:_(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),$t=u("/organization/reject-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),Vt=u("/organization/cancel-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new E("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),Ht=u("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:W.object({id:W.string()})},async e=>{let t=await F(e);if(!t)throw new E("UNAUTHORIZED",{message:"Not authenticated"});let r=P(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new E("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new E("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as pe}from"zod";import{APIError as Ee}from"better-call";var Qt=u("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ee("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ee("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ee("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ee("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Ee("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Wt=u("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as C}from"zod";import{APIError as me}from"better-call";var Kt=u("/organization/create",{method:"POST",body:C.object({name:C.string(),slug:C.string(),userId:C.string().optional(),logo:C.string().optional(),metadata:C.record(C.string()).optional()}),use:[L,x]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new me("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=P(e.context.adapter,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new me("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new me("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:_(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),Jt=u("/organization/update",{method:"POST",body:C.object({data:C.object({name:C.string().optional(),slug:C.string().optional()}).partial(),orgId:C.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new me("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["update"]}).error)return e.json(null,{body:{message:"You are not allowed to update this organization"},status:403});let s=await o.updateOrganization(r,e.body.data);return e.json(s)}),Gt=u("/organization/delete",{method:"POST",body:C.object({orgId:C.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["delete"]}).error)throw new me("FORBIDDEN",{message:"You are not allowed to delete this organization"});return r===t.session.activeOrganizationId&&await o.setActiveOrganization(t.session.id,null),await o.deleteOrganization(r),e.json(r)}),Zt=u("/organization/get-full",{method:"GET",query:C.object({orgId:C.string().optional()}),requireHeaders:!0,use:[L,x]},async e=>{let t=e.context.session,r=e.query.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400});let n=await P(e.context.adapter,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new me("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Yt=u("/organization/activate",{method:"POST",body:C.object({orgId:C.string().nullable().optional()}),use:[x,L]},async e=>{let t=P(e.context.adapter,e.context.orgOptions),r=e.context.session,o=e.body.orgId;if(o===null)return r.session.activeOrganizationId&&await t.setActiveOrganization(r.session.id,null),e.json(null);if(!o){let a=r.session.activeOrganizationId;if(!a)return e.json(null);o=a}if(!await t.findMemberByOrgId({userId:r.user.id,organizationId:o}))throw await t.setActiveOrganization(r.session.id,null),new me("FORBIDDEN",{message:"You are not a member of this organization"});await t.setActiveOrganization(r.session.id,o);let i=await t.findFullOrganization(o,e.context.db||void 0);return e.json(i)}),Xt=u("/organization/list",{method:"GET",use:[L,x]},async e=>{let r=await P(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var iu=e=>{let t={createOrganization:Kt,updateOrganization:Jt,deleteOrganization:Gt,setActiveOrganization:Yt,getFullOrganization:Zt,listOrganization:Xt,createInvitation:Mt,cancelInvitation:Vt,acceptInvitation:qt,getInvitation:Ht,rejectInvitation:$t,removeMember:Qt,updateMemberRole:Wt},r={...Xe,...e?.roles};return{id:"organization",endpoints:{...zt(t,{orgOptions:e||{},roles:r,getSession:async n=>await F(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new er("BAD_REQUEST",{message:"No active organization"});let a=await P(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new er("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import{z as Ke}from"zod";import{z as Pe}from"zod";import{APIError as fe}from"better-call";var He="two-factor";var Qe="trust-device";import{z as tr}from"zod";var ge=T({body:tr.object({trustDevice:tr.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(He),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let i=await e.context.adapter.findMany({model:"session",where:[{field:"userId",value:o}]});if(!i.length)throw new fe("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new fe("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await Y(e.context.secret,s.id),c=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!c)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await A(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await Y(e.context.secret,`${c.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:c})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:c}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Se}from"better-call";function ko(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>V(e?.length??10,H("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function tt(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():ko(),n=await Me({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Ro(e,t){let r=await rr(e.backupCodes,t);return r?r.includes(e.code):!1}async function rr(e,t){let r=Buffer.from(await qe({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Pe.array(Pe.string()).safeParse(o);return n.success?n.data:null}var or=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:Pe.object({code:Pe.string(),disableSession:Pe.boolean().optional()}),use:[ge]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Ro({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Se("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await A(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",use:[w]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Se("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await tt(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",use:[w]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=rr(n.backupCodes,r.context.secret);if(!i)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as We}from"better-call";import{TOTPController as Oo}from"oslo/otp";import{z as nr}from"zod";import{TimeSpan as vo}from"oslo";var ir=(e,t)=>{let r={...e,period:new vo(e?.period||3,"m")},o=new Oo({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[ge]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new We("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:nr.object({code:nr.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new We("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as Re}from"better-call";import{TimeSpan as Io}from"oslo";import{TOTPController as sr,createTOTPKeyURI as Uo}from"oslo/otp";import{z as ar}from"zod";var dr=(e,t)=>{let r={...e,digits:6,period:new Io(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new sr(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"GET",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Uo(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:ar.object({code:ar.string()}),use:[ge]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!d.enabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});let c=new sr(r),l=await qe({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await c.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function rt(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as cr}from"better-call";var $u=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t==="/two-factor/enable"||t==="/two-factor/send-otp"||t==="/two-factor/disable",signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var rl=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=dr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=or({...e?.backupCodeOptions},t.twoFactorTable),n=ir({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new cr("BAD_REQUEST",{message:"Invalid password"});let c=V(16,H("a-z","0-9","-")),l=await Me({key:i.context.secret,data:c}),p=await tt(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new cr("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:T(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[f,k]=c.split("!"),I=await Y(i.context.secret,`${s.user.id}!${k}`);if(f===I){let h=await Y(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await Y(i.context.secret,s.session.id),p=i.context.createAuthCookie(He,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.options),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as Bo,generateRegistrationOptions as Lo,verifyAuthenticationResponse as Do,verifyRegistrationResponse as xo}from"@simplewebauthn/server";import{APIError as ee}from"better-call";import{z as ne}from"zod";import{env as jo}from"std-env";import{WebAuthnError as So,startAuthentication as Po,startRegistration as Co}from"@simplewebauthn/browser";import{createFetch as fl}from"@better-fetch/fetch";import"nanostores";import{betterFetch as sl}from"@better-fetch/fetch";import{atom as Il}from"nanostores";import"@better-fetch/fetch";import{atom as Eo,onMount as To}from"nanostores";var ot=(e,t,r,o)=>{let n=Eo({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():To(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as _o}from"nanostores";var zo=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await Po(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch(s){console.log(s)}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Co(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof So?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),Vl=()=>{let e=_o();return{id:"passkey",$InferServerPlugin:{},getActions:t=>zo(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:ot(e,"/passkey/list-user-passkeys",t,{method:"GET",credentials:"include"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var op=e=>{let t=jo.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[w],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(V(32,H("a-z","0-9")))),p;p=await Lo({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:ne.object({email:ne.string().optional()}).optional()},async s=>{let d=await F(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await Bo({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(f=>({id:f.id,transports:f.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:ne.object({response:ne.any(),name:ne.string().optional()}),use:[w]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:g,userData:f}=JSON.parse(p.value);if(f.id!==s.context.session.user.id)throw new ee("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await xo({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:I,registrationInfo:h}=k;if(!I||!h)return s.json(null,{status:400});let{credentialID:R,credentialPublicKey:q,counter:K,credentialDeviceType:O,credentialBackedUp:j}=h,ae=Buffer.from(q).toString("base64"),D=_(),ze={name:s.body.name,userId:f.id,webauthnUserID:D,id:R,publicKey:ae,counter:K,deviceType:O,transports:c.response.transports.join(","),backedUp:j,createdAt:new Date},hr=await s.context.adapter.create({model:"passkey",data:ze});return s.json(hr,{status:200})}catch(k){throw console.log(k),new ee("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:ne.object({response:ne.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new ee("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:g}=JSON.parse(p.value),f=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!f)throw new ee("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await Do({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:f.id,credentialPublicKey:new Uint8Array(Buffer.from(f.publicKey,"base64")),counter:f.counter,transports:f.transports?.split(",")}}),{verified:I}=k;if(!I)throw new ee("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:f.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(f.userId,s.request);if(!h)throw new ee("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await A(s,h.id),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new ee("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[w]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:ne.object({id:ne.string()}),use:[w]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as te}from"zod";import{APIError as Je}from"better-call";var ur=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:te.object({username:te.string(),password:te.string(),dontRememberMe:te.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:"user",where:[{field:"username",value:e.body.username}]});if(!t)throw await e.context.password.hash(e.body.password),e.context.logger.error("User not found",{username:ur}),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:"account",where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.type.fieldName||"providerId",value:"credential"}]});if(!r)throw new Je("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:ur}),new Je("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:u("/sign-up/username",{method:"POST",body:te.object({username:te.string().min(3).max(20),name:te.string(),email:te.string().email(),password:te.string(),image:te.string().optional()})},async e=>{let t=await Ye()({...e,_flag:"json"}),r=await e.context.internalAdapter.updateUserByEmail(t.user?.email,{username:e.body.username});return e.json({user:r,session:t.session})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as No}from"better-call";var pp=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await No("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as Oe}from"zod";import{APIError as Fo}from"better-call";var Ap=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Oe.object({email:Oe.string().email(),callbackURL:Oe.string().optional()}),use:[S]},async t=>{let{email:r}=t.body,o=V(32,H("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new Fo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:Oe.object({token:Oe.string(),callbackURL:Oe.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await A(t,c.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as he}from"zod";import{APIError as ie}from"better-call";function Mo(e){return V(e,H("0-9"))}var Pp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw b.warn("sendOTP not implemented"),new ie("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Mo(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:J(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:he.object({phoneNumber:he.string(),code:he.string(),disableSession:he.boolean().optional(),updatePhoneNumber:he.boolean().optional()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new ie("BAD_REQUEST",{message:"OTP expired"})):new ie("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ie("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await F(r);if(!i)throw new ie("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ie("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(r,i.id),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as nt}from"zod";var xp=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=pt(t.context.baseURL)}=e||{},o=_(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await A(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:u("/user/link-anonymous",{method:"POST",body:nt.object({email:nt.string().email().optional(),password:nt.string().min(6)}),use:[w]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await A(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});import{z as m}from"zod";var re=T(async e=>{let t=await F(e);if(!t?.session)throw new M("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new M("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),$p=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/user/list-sessions"},handler:T(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:m.object({userId:m.string(),role:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:m.object({email:m.string(),password:m.string(),name:m.string(),role:m.string(),data:m.optional(m.record(m.any()))}),use:[re]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new M("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[re],query:m.object({search:m.object({field:m.enum(["email","name"]),operator:m.enum(["contains","starts_with","ends_with"]).default("contains"),value:m.string()}).optional(),limit:m.string().or(m.number()).optional(),offset:m.string().or(m.number()).optional(),sortBy:m.string().optional(),sortDirection:m.enum(["asc","desc"]).optional(),filter:m.array(m.object({field:m.string(),value:m.string().or(m.number()).or(m.boolean()),operator:m.enum(["eq","ne","lt","lte","gt","gte"]),connector:m.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[re],body:m.object({userId:m.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:m.object({userId:m.string(),banReason:m.string().optional(),banExpiresIn:m.number().optional()}),use:[re]},async t=>{if(t.body.userId===t.context.session.user.id)throw new M("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new M("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?J(e.impersonationSessionDuration,"sec"):J(60*60,"sec")});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:m.object({sessionId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:m.object({userId:m.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});import{z as se}from"zod";import{APIError as Ce}from"better-call";import{betterFetch as it}from"@better-fetch/fetch";import{generateCodeVerifier as qo}from"oslo/oauth2";import{parseJWT as $o}from"oslo/jwt";async function Vo(e,t,r){if(t==="oidc"&&e.idToken){let n=$o(e.idToken);if(n?.payload)return n.payload}return r?(await it(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var sm=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:se.object({currentURL:se.string().optional()}).optional(),body:se.object({providerId:se.string(),callbackURL:se.string().optional()}),use:[S]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:g,prompt:f,accessType:k}=o,I=i,h=a;if(n){let D=await it(n,{onError(ze){b.error(ze.error,{discoveryUrl:n})}});D.data&&(I=D.data.authorization_endpoint,h=D.data.token_endpoint)}if(!I||!h)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let R=t.query?.currentURL?new URL(t.query?.currentURL):null,q=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${R?.origin}${t.body.callbackURL||""}`,K=await De(q||R?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,K.hash,t.context.secret,O.state.options);let j=qo();await t.setSignedCookie(O.pkCodeVerifier.name,j,t.context.secret,O.pkCodeVerifier.options);let ae=await z({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:I,state:K.raw,codeVerifier:j,scopes:c||[],disablePkce:!g,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ae.searchParams.set("response_type",p),f&&ae.searchParams.set("prompt",f),k&&ae.searchParams.set("access_type",k),{url:ae.toString(),state:K,codeVerifier:j,redirect:!0}}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:se.object({code:se.string().optional(),error:se.string().optional(),state:se.string()})},async t=>{if(t.query.error||!t.query.code){let j=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${j}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o=await t.getSignedCookie(t.context.authCookies.pkCodeVerifier.name,t.context.secret),n,i=we(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,c=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw b.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await Be(a,p))throw b.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let f=r.tokenUrl,k=r.userInfoUrl;if(r.discoveryUrl){let O=await it(r.discoveryUrl,{method:"GET"});O.data&&(f=O.data.token_endpoint,k=O.data.userinfo_endpoint)}try{if(!f)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await U({code:c,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:f})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let I=r.getUserInfo?await r.getUserInfo(n):await Vo(n,r.type||"oauth2",k),h=_(),R=I?je.safeParse({...I,id:h}):null;if(!R?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let q=await t.context.internalAdapter.findUserByEmail(R.data.email).catch(O=>{throw b.error(`Better auth was unable to query your database.
|
|
84
|
-
Error: `,O),t.redirect(`${l}?error=internal_server_error`)}),K=q?.user.id||h;if(q){let O=q.accounts.find(D=>D.providerId===r.providerId),j=t.context.options.account?.accountLinking?.trustedProviders,ae=j?j.includes(r.providerId):!0;if(!O&&(!R?.data.emailVerified||!ae)){let D;try{D=new URL(l),D.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(D.toString())}if(!O)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:R.data.id,id:`${r.providerId}:${R.data.id}`,userId:q.user.id,...ye(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(R.data,{...ye(n),id:`${r.providerId}:${R.data.id}`,providerId:r.providerId,accountId:R.data.id})}catch{let j=new URL(l);throw j.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",j.toString()),t.redirect(j.toString())}try{let O=await t.context.internalAdapter.createSession(K||h,t.request);if(!O)throw t.redirect(`${l}?error=unable_to_create_session`);await A(t,O.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var lr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},cm=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var st=e=>({getAllKeys:async()=>await e.findMany({model:"jwks"}),getLatestKey:async()=>(await e.findMany({model:"jwks",sortBy:{field:"createdAt",direction:"desc"},limit:1}))[0],createJwk:async t=>await e.create({model:"jwks",data:{...t,createdAt:new Date}})});import{exportJWK as gr,generateKeyPair as Jo,importJWK as Go,SignJWT as Zo}from"jose";import{createCipheriv as Ho,createDecipheriv as Qo,createHash as Wo,randomBytes as Ko}from"crypto";function pr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=Wo("sha256").update(e).digest(),t}function mr(e,t){let r=pr(t),o=Ko(12),n=Ho("aes-256-gcm",r,o),i=n.update(e,"utf8","base64");i+=n.final("base64");let a=n.getAuthTag();return{encryptedPrivateKey:i,iv:o.toString("base64"),authTag:a.toString("base64")}}function fr(e,t){let r=pr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=Qo("aes-256-gcm",r,a);d.setAuthTag(s);let c=d.update(o,"base64","utf8");return c+=d.final("utf8"),c}var bm=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await st(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[w]},async t=>{let r=st(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await Jo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await gr(c),g=await gr(l),
|
|
83
|
+
</html>`,ho=u("/error",{method:"GET",metadata:de},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(go(t),{headers:{"Content-Type":"text/html"}})});var wo=u("/ok",{method:"GET",metadata:de},async e=>e.json({ok:!0}));import{z as Ae}from"zod";import{APIError as ue}from"better-call";var Ye=()=>u("/sign-up/email",{method:"POST",query:Ae.object({currentURL:Ae.string().optional()}).optional(),body:Ae.record(Ae.string(),Ae.any()),use:[S]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!Ae.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let c=e.context.password.config.minPasswordLength;if(n.length<c)throw e.context.logger.error("Password is too short"),new ue("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new ue("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new ue("UNPROCESSABLE_ENTITY",{message:"Failed to create user"});let g=St(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1});if(!m)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let k=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:k,expiresAt:J(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let h=await oe(e.context.secret,m.email),R=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(m,R,h)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({user:m,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:null}});let I=await e.context.internalAdapter.createSession(m.id,e.request);if(!I)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await A(e,I.id),e.json({user:m,session:I},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:I}})});var zt=(e,t)=>{let r={};for(let[o,n]of Object.entries(e))r[o]=i=>n({...i,context:{...t,...i.context}}),r[o].path=n.path,r[o].method=n.method,r[o].options=n.options,r[o].headers=n.headers;return r};var Nt={};yr(Nt,{AccessControl:()=>Ue,ParsingError:()=>le,Role:()=>ke,adminAc:()=>Dt,createAccessControl:()=>Bt,defaultAc:()=>$e,defaultRoles:()=>Xe,defaultStatements:()=>Lt,memberAc:()=>jt,ownerAc:()=>xt,permissionFromString:()=>yo});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},Ue=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new ke(t)}},ke=class e{statements;constructor(t){this.statements=t}authorize(t,r){for(let[o,n]of Object.entries(t)){let i=this.statements[o];if(!i)return{success:!1,error:`You are not allowed to access resource: ${o}`};let a=r==="OR"?n.some(s=>i.includes(s)):n.every(s=>i.includes(s));return a?{success:a}:{success:!1,error:`unauthorized to access resource "${o}"`}}return{success:!1,error:"Not authorized"}}static fromString(t){let r=JSON.parse(t);if(typeof r!="object")throw new le("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new le("invalid resource identifier",o);if(!Array.isArray(n))throw new le("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new le("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var Bt=e=>new Ue(e),Lt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},$e=Bt(Lt),Dt=$e.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),xt=$e.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),jt=$e.newRole({organization:[],member:[],invitation:[]}),Xe={admin:Dt,owner:xt,member:jt};var yo=e=>ke.fromString(e??"");var P=(e,t)=>{let r=e.adapter;return{findOrganizationBySlug:async o=>await r.findOne({model:"organization",where:[{field:"slug",value:o}]}),createOrganization:async o=>{let n=await r.create({model:"organization",data:{...o.organization,metadata:o.organization.metadata?JSON.stringify(o.organization.metadata):void 0}}),i=await r.create({model:"member",data:{id:_(),organizationId:n.id,userId:o.user.id,createdAt:new Date,email:o.user.email,role:t?.creatorRole||"owner"}});return{...n,metadata:n.metadata?JSON.parse(n.metadata):void 0,members:[{...i,user:{id:o.user.id,name:o.user.name,email:o.user.email,image:o.user.image}}]}},findMemberByEmail:async o=>{let n=await r.findOne({model:"member",where:[{field:"email",value:o.email},{field:"organizationId",value:o.organizationId}]});if(!n)return null;let i=await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:n.userId}]});return i?{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}:null},findMemberByOrgId:async o=>{let[n,i]=await Promise.all([await r.findOne({model:"member",where:[{field:"userId",value:o.userId},{field:"organizationId",value:o.organizationId}]}),await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:o.userId}]})]);return!i||!n?null:{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}},findMemberById:async o=>{let n=await r.findOne({model:"member",where:[{field:"id",value:o}]});if(!n)return null;let i=await r.findOne({model:e.tables.user.tableName,where:[{field:"id",value:n.userId}]});return i?{...n,user:{id:i.id,name:i.name,email:i.email,image:i.image}}:null},createMember:async o=>await r.create({model:"member",data:o}),updateMember:async(o,n)=>await r.update({model:"member",where:[{field:"id",value:o}],update:{role:n}}),deleteMember:async o=>await r.delete({model:"member",where:[{field:"id",value:o}]}),updateOrganization:async(o,n)=>await r.update({model:"organization",where:[{field:"id",value:o}],update:n}),deleteOrganization:async o=>(await r.delete({model:"member",where:[{field:"organizationId",value:o}]}),await r.delete({model:"invitation",where:[{field:"organizationId",value:o}]}),await r.delete({model:"organization",where:[{field:"id",value:o}]}),o),setActiveOrganization:async(o,n)=>await r.update({model:e.tables.session.tableName,where:[{field:"id",value:o}],update:{activeOrganizationId:n}}),findOrganizationById:async o=>await r.findOne({model:"organization",where:[{field:"id",value:o}]}),findFullOrganization:async(o,n)=>{let[i,a,s]=await Promise.all([r.findOne({model:"organization",where:[{field:"id",value:o}]}),r.findMany({model:"invitation",where:[{field:"organizationId",value:o}]}),r.findMany({model:"member",where:[{field:"organizationId",value:o}]})]);if(!i)return null;let d=s.map(g=>g.userId),c=await r.findMany({model:e.tables.user.tableName,where:[{field:"id",value:d,operator:"in"}]}),l=new Map(c.map(g=>[g.id,g])),p=s.map(g=>{let m=l.get(g.userId);if(!m)throw new $("Unexpected error: User not found for member");return{...g,user:{id:m.id,name:m.name,email:m.email,image:m.image}}});return{...i,invitations:a,members:p}},listOrganizations:async o=>{let n=await r.findMany({model:"member",where:[{field:"userId",value:o}]});if(!n||n.length===0)return[];let i=n.map(s=>s.organizationId);return await r.findMany({model:"organization",where:[{field:"id",value:i,operator:"in"}]})},createInvitation:async({invitation:o,user:n})=>{let a=J(t?.invitationExpiresIn||1728e5);return await r.create({model:"invitation",data:{id:_(),email:o.email,role:o.role,organizationId:o.organizationId,status:"pending",expiresAt:a,inviterId:n.id}})},findInvitationById:async o=>await r.findOne({model:"invitation",where:[{field:"id",value:o}]}),findPendingInvitation:async o=>(await r.findMany({model:"invitation",where:[{field:"email",value:o.email},{field:"organizationId",value:o.organizationId},{field:"status",value:"pending"}]})).filter(i=>new Date(i.expiresAt)>new Date),updateInvitation:async o=>await r.update({model:"invitation",where:[{field:"id",value:o.invitationId}],update:{status:o.status}})}};import"better-call";import{APIError as Gd,createRouter as Zd,statusCode as Yd}from"better-call";import{APIError as et}from"better-call";import{z as Ft}from"zod";var bo=T({body:Ft.object({csrfToken:Ft.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=e.headers?.get("origin")||"";if(t){let s=new URL(t).origin;if(e.context.trustedOrigins.includes(s))return}let r=e.body?.csrfToken;if(!r)throw new et("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await Y(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{isTest as Nd}from"std-env";import{APIError as M}from"better-call";var L=T(async e=>({})),x=T({use:[w]},async e=>({session:e.context.session}));import{z as W}from"zod";import{z as v}from"zod";var Ve=v.enum(["admin","member","owner"]),Ao=v.enum(["pending","accepted","rejected","canceled"]).default("pending"),kc=v.object({id:v.string(),name:v.string(),slug:v.string(),logo:v.string().optional(),metadata:v.record(v.string()).or(v.string().transform(e=>JSON.parse(e))).optional(),createdAt:v.date()}),Rc=v.object({id:v.string(),email:v.string(),organizationId:v.string(),userId:v.string(),role:Ve,createdAt:v.date()}),Oc=v.object({id:v.string(),organizationId:v.string(),email:v.string(),role:Ve,status:Ao,inviterId:v.string(),expiresAt:v.date()});import{APIError as E}from"better-call";var Mt=u("/organization/invite-member",{method:"POST",use:[L,x],body:W.object({email:W.string(),role:Ve,organizationId:W.string().optional(),resend:W.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw b.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new E("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new E("BAD_REQUEST",{message:"Organization not found"});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new E("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new E("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new E("BAD_REQUEST",{message:"User is already invited to this organization"});let c=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new E("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),qt=u("/organization/accept-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:_(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),$t=u("/organization/reject-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),Vt=u("/organization/cancel-invitation",{method:"POST",body:W.object({invitationId:W.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new E("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new E("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new E("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),Ht=u("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:W.object({id:W.string()})},async e=>{let t=await F(e);if(!t)throw new E("UNAUTHORIZED",{message:"Not authenticated"});let r=P(e.context,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new E("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new E("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new E("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new E("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as pe}from"zod";import{APIError as Ee}from"better-call";var Qt=u("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ee("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ee("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ee("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ee("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Ee("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Wt=u("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=P(e.context,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as C}from"zod";import{APIError as me}from"better-call";var Kt=u("/organization/create",{method:"POST",body:C.object({name:C.string(),slug:C.string(),userId:C.string().optional(),logo:C.string().optional(),metadata:C.record(C.string()).optional()}),use:[L,x]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new me("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=P(e.context,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new me("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new me("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:_(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),Jt=u("/organization/update",{method:"POST",body:C.object({data:C.object({name:C.string().optional(),slug:C.string().optional()}).partial(),orgId:C.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new me("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context,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)}),Gt=u("/organization/delete",{method:"POST",body:C.object({orgId:C.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=P(e.context,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)}),Zt=u("/organization/get-full",{method:"GET",query:C.object({orgId:C.string().optional()}),requireHeaders:!0,use:[L,x]},async e=>{let t=e.context.session,r=e.query.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400});let n=await P(e.context,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)}),Yt=u("/organization/activate",{method:"POST",body:C.object({orgId:C.string().nullable().optional()}),use:[x,L]},async e=>{let t=P(e.context,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)}),Xt=u("/organization/list",{method:"GET",use:[L,x]},async e=>{let r=await P(e.context,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var iu=e=>{let t={createOrganization:Kt,updateOrganization:Jt,deleteOrganization:Gt,setActiveOrganization:Yt,getFullOrganization:Zt,listOrganization:Xt,createInvitation:Mt,cancelInvitation:Vt,acceptInvitation:qt,getInvitation:Ht,rejectInvitation:$t,removeMember:Qt,updateMemberRole:Wt},r={...Xe,...e?.roles};return{id:"organization",endpoints:{...zt(t,{orgOptions:e||{},roles:r,getSession:async n=>await F(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new er("BAD_REQUEST",{message:"No active organization"});let a=await P(n.context).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new er("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import{z as Ke}from"zod";import{z as Pe}from"zod";import{APIError as fe}from"better-call";var He="two-factor";var Qe="trust-device";import{z as tr}from"zod";var ge=T({body:tr.object({trustDevice:tr.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(He),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let i=await e.context.adapter.findMany({model:e.context.tables.session.tableName,where:[{field:"userId",value:o}]});if(!i.length)throw new fe("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new fe("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await Y(e.context.secret,s.id),c=await e.context.adapter.findOne({model:e.context.tables.user.tableName,where:[{field:"id",value:s.userId}]});if(!c)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await A(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await Y(e.context.secret,`${c.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:c})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:c}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Se}from"better-call";function ko(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>V(e?.length??10,H("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function tt(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():ko(),n=await Me({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Ro(e,t){let r=await rr(e.backupCodes,t);return r?r.includes(e.code):!1}async function rr(e,t){let r=Buffer.from(await qe({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Pe.array(Pe.string()).safeParse(o);return n.success?n.data:null}var or=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:Pe.object({code:Pe.string(),disableSession:Pe.boolean().optional()}),use:[ge]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Ro({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Se("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await A(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",use:[w]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Se("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await tt(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:u("/view/backup-codes",{method:"GET",use:[w]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=rr(n.backupCodes,r.context.secret);if(!i)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as We}from"better-call";import{TOTPController as Oo}from"oslo/otp";import{z as nr}from"zod";import{TimeSpan as vo}from"oslo";var ir=(e,t)=>{let r={...e,period:new vo(e?.period||3,"m")},o=new Oo({digits:6,period:r.period}),n=u("/two-factor/send-otp",{method:"POST",use:[ge]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new We("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:nr.object({code:nr.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new We("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new We("BAD_REQUEST",{message:"totp isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as Re}from"better-call";import{TimeSpan as Io}from"oslo";import{TOTPController as sr,createTOTPKeyURI as Uo}from"oslo/otp";import{z as ar}from"zod";var dr=(e,t)=>{let r={...e,digits:6,period:new Io(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new sr(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"GET",use:[w]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Uo(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:ar.object({code:ar.string()}),use:[ge]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Re("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!d.enabled)throw new Re("BAD_REQUEST",{message:"totp isn't enabled"});let c=new sr(r),l=await qe({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await c.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function rt(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as cr}from"better-call";var $u=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t==="/two-factor/enable"||t==="/two-factor/send-otp"||t==="/two-factor/disable",signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var rl=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=dr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=or({...e?.backupCodeOptions},t.twoFactorTable),n=ir({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new cr("BAD_REQUEST",{message:"Invalid password"});let c=V(16,H("a-z","0-9","-")),l=await Me({key:i.context.secret,data:c}),p=await tt(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:u("/two-factor/disable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new cr("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:T(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[m,k]=c.split("!"),I=await Y(i.context.secret,`${s.user.id}!${k}`);if(m===I){let h=await Y(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${h}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await Y(i.context.secret,s.session.id),p=i.context.createAuthCookie(He,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.options),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as Bo,generateRegistrationOptions as Lo,verifyAuthenticationResponse as Do,verifyRegistrationResponse as xo}from"@simplewebauthn/server";import{APIError as ee}from"better-call";import{z as ne}from"zod";import{env as jo}from"std-env";import{WebAuthnError as So,startAuthentication as Po,startRegistration as Co}from"@simplewebauthn/browser";import{createFetch as fl}from"@better-fetch/fetch";import"nanostores";import{betterFetch as sl}from"@better-fetch/fetch";import{atom as Il}from"nanostores";import"@better-fetch/fetch";import{atom as Eo,onMount as To}from"nanostores";var ot=(e,t,r,o)=>{let n=Eo({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let c=n.get();n.set({isPending:c.data===null,data:c.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():To(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as _o}from"nanostores";var zo=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await Po(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch(s){console.log(s)}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Co(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof So?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),Vl=()=>{let e=_o();return{id:"passkey",$InferServerPlugin:{},getActions:t=>zo(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:ot(e,"/passkey/list-user-passkeys",t,{method:"GET",credentials:"include"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var op=e=>{let t=jo.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:u("/passkey/generate-register-options",{method:"GET",use:[w],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(V(32,H("a-z","0-9")))),p;p=await Lo({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(m=>({id:m.id,transports:m.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:ne.object({email:ne.string().optional()}).optional()},async s=>{let d=await F(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await Bo({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(m=>({id:m.id,transports:m.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},g=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,g,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:g,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:ne.object({response:ne.any(),name:ne.string().optional()}),use:[w]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:g,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new ee("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let k=await xo({response:c,expectedChallenge:g,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:I,registrationInfo:h}=k;if(!I||!h)return s.json(null,{status:400});let{credentialID:R,credentialPublicKey:q,counter:K,credentialDeviceType:O,credentialBackedUp:j}=h,ae=Buffer.from(q).toString("base64"),D=_(),ze={name:s.body.name,userId:m.id,webauthnUserID:D,id:R,publicKey:ae,counter:K,deviceType:O,transports:c.response.transports.join(","),backedUp:j,createdAt:new Date},hr=await s.context.adapter.create({model:"passkey",data:ze});return s.json(hr,{status:200})}catch(k){throw console.log(k),new ee("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:ne.object({response:ne.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new ee("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new ee("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:g}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!m)throw new ee("UNAUTHORIZED",{message:"Passkey not found"});try{let k=await Do({response:c,expectedChallenge:g,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:I}=k;if(!I)throw new ee("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:m.id}],update:{counter:k.authenticationInfo.newCounter}});let h=await s.context.internalAdapter.createSession(m.userId,s.request);if(!h)throw new ee("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await A(s,h.id),s.json({session:h},{status:200})}catch(k){throw s.context.logger.error(k),new ee("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[w]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:u("/passkey/delete-passkey",{method:"POST",body:ne.object({id:ne.string()}),use:[w]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as te}from"zod";import{APIError as Je}from"better-call";var ur=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:te.object({username:te.string(),password:te.string(),dontRememberMe:te.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:e.context.tables.user.tableName,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:ur}),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:e.context.tables.account.tableName,where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.type.fieldName||"providerId",value:"credential"}]});if(!r)throw new Je("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:ur}),new Je("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Je("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:u("/sign-up/username",{method:"POST",body:te.object({username:te.string().min(3).max(20),name:te.string(),email:te.string().email(),password:te.string(),image:te.string().optional()})},async e=>{let t=await Ye()({...e,_flag:"json"}),r=await e.context.internalAdapter.updateUserByEmail(t.user?.email,{username:e.body.username});return e.json({user:r,session:t.session})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as No}from"better-call";var pp=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await No("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as Oe}from"zod";import{APIError as Fo}from"better-call";var Ap=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Oe.object({email:Oe.string().email(),callbackURL:Oe.string().optional()}),use:[S]},async t=>{let{email:r}=t.body,o=V(32,H("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new Fo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:Oe.object({token:Oe.string(),callbackURL:Oe.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await A(t,c.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as he}from"zod";import{APIError as ie}from"better-call";function Mo(e){return V(e,H("0-9"))}var Pp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw b.warn("sendOTP not implemented"),new ie("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Mo(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:J(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:he.object({phoneNumber:he.string(),code:he.string(),disableSession:he.boolean().optional(),updatePhoneNumber:he.boolean().optional()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new ie("BAD_REQUEST",{message:"OTP expired"})):new ie("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ie("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let i=await F(r);if(!i)throw new ie("UNAUTHORIZED",{message:"Session not found"});let a=await r.context.internalAdapter.updateUser(i.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:a,session:i.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(n)n=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});else if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ie("BAD_REQUEST",{message:"Phone number not found"});if(!n)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to update user"});if(!r.body.disableSession){let i=await r.context.internalAdapter.createSession(n.id,r.request);if(!i)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(r,i.id),r.json({user:n,session:i})}return r.json({user:n,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as nt}from"zod";var xp=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=pt(t.context.baseURL)}=e||{},o=_(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await A(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:u("/user/link-anonymous",{method:"POST",body:nt.object({email:nt.string().email().optional(),password:nt.string().min(6)}),use:[w]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await A(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});import{z as f}from"zod";var re=T(async e=>{let t=await F(e);if(!t?.session)throw new M("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new M("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),$p=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/user/list-sessions"},handler:T(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:u("/admin/set-role",{method:"POST",body:f.object({userId:f.string(),role:f.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/admin/create-user",{method:"POST",body:f.object({email:f.string(),password:f.string(),name:f.string(),role:f.string(),data:f.optional(f.record(f.any()))}),use:[re]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new M("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:u("/admin/list-users",{method:"GET",use:[re],query:f.object({search:f.object({field:f.enum(["email","name"]),operator:f.enum(["contains","starts_with","ends_with"]).default("contains"),value:f.string()}).optional(),limit:f.string().or(f.number()).optional(),offset:f.string().or(f.number()).optional(),sortBy:f.string().optional(),sortDirection:f.enum(["asc","desc"]).optional(),filter:f.array(f.object({field:f.string(),value:f.string().or(f.number()).or(f.boolean()),operator:f.enum(["eq","ne","lt","lte","gt","gte"]),connector:f.enum(["AND","OR"]).optional()})).optional()})},async t=>{let r=[];t.query?.search&&r.push({field:t.query.search.field,operator:t.query.search.operator,value:t.query.search.value}),t.query?.filter&&r.push(...t.query.filter||[]);let o=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0,r.length?r:void 0);return t.json({users:o})}),listUserSessions:u("/admin/list-user-sessions",{method:"POST",use:[re],body:f.object({userId:f.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:f.object({userId:f.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:f.object({userId:f.string(),banReason:f.string().optional(),banExpiresIn:f.number().optional()}),use:[re]},async t=>{if(t.body.userId===t.context.session.user.id)throw new M("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:u("/admin/impersonate-user",{method:"POST",body:f.object({userId:f.string()}),use:[re]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new M("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?J(e.impersonationSessionDuration,"sec"):J(60*60,"sec")});if(!o)throw new M("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:f.object({sessionId:f.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:f.object({userId:f.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:f.object({userId:f.string()}),use:[re]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1}}}}});import{z as se}from"zod";import{APIError as Ce}from"better-call";import{betterFetch as it}from"@better-fetch/fetch";import{generateCodeVerifier as qo}from"oslo/oauth2";import{parseJWT as $o}from"oslo/jwt";async function Vo(e,t,r){if(t==="oidc"&&e.idToken){let n=$o(e.idToken);if(n?.payload)return n.payload}return r?(await it(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var sm=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:se.object({currentURL:se.string().optional()}).optional(),body:se.object({providerId:se.string(),callbackURL:se.string().optional()}),use:[S]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:g,prompt:m,accessType:k}=o,I=i,h=a;if(n){let D=await it(n,{onError(ze){b.error(ze.error,{discoveryUrl:n})}});D.data&&(I=D.data.authorization_endpoint,h=D.data.token_endpoint)}if(!I||!h)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let R=t.query?.currentURL?new URL(t.query?.currentURL):null,q=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${R?.origin}${t.body.callbackURL||""}`,K=await De(q||R?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,K.hash,t.context.secret,O.state.options);let j=qo();await t.setSignedCookie(O.pkCodeVerifier.name,j,t.context.secret,O.pkCodeVerifier.options);let ae=await z({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:I,state:K.raw,codeVerifier:j,scopes:c||[],disablePkce:!g,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ae.searchParams.set("response_type",p),m&&ae.searchParams.set("prompt",m),k&&ae.searchParams.set("access_type",k),{url:ae.toString(),state:K,codeVerifier:j,redirect:!0}}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:se.object({code:se.string().optional(),error:se.string().optional(),state:se.string()})},async t=>{if(t.query.error||!t.query.code){let j=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${j}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o=await t.getSignedCookie(t.context.authCookies.pkCodeVerifier.name,t.context.secret),n,i=we(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,c=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw b.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await Be(a,p))throw b.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,k=r.userInfoUrl;if(r.discoveryUrl){let O=await it(r.discoveryUrl,{method:"GET"});O.data&&(m=O.data.token_endpoint,k=O.data.userinfo_endpoint)}try{if(!m)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await U({code:c,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:m})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let I=r.getUserInfo?await r.getUserInfo(n):await Vo(n,r.type||"oauth2",k),h=_(),R=I?je.safeParse({...I,id:h}):null;if(!R?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let q=await t.context.internalAdapter.findUserByEmail(R.data.email).catch(O=>{throw b.error(`Better auth was unable to query your database.
|
|
84
|
+
Error: `,O),t.redirect(`${l}?error=internal_server_error`)}),K=q?.user.id||h;if(q){let O=q.accounts.find(D=>D.providerId===r.providerId),j=t.context.options.account?.accountLinking?.trustedProviders,ae=j?j.includes(r.providerId):!0;if(!O&&(!R?.data.emailVerified||!ae)){let D;try{D=new URL(l),D.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(D.toString())}if(!O)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:R.data.id,id:`${r.providerId}:${R.data.id}`,userId:q.user.id,...ye(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(R.data,{...ye(n),id:`${r.providerId}:${R.data.id}`,providerId:r.providerId,accountId:R.data.id})}catch{let j=new URL(l);throw j.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",j.toString()),t.redirect(j.toString())}try{let O=await t.context.internalAdapter.createSession(K||h,t.request);if(!O)throw t.redirect(`${l}?error=unable_to_create_session`);await A(t,O.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var lr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},cm=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var st=e=>({getAllKeys:async()=>await e.findMany({model:"jwks"}),getLatestKey:async()=>(await e.findMany({model:"jwks",sortBy:{field:"createdAt",direction:"desc"},limit:1}))[0],createJwk:async t=>await e.create({model:"jwks",data:{...t,createdAt:new Date}})});import{exportJWK as gr,generateKeyPair as Jo,importJWK as Go,SignJWT as Zo}from"jose";import{createCipheriv as Ho,createDecipheriv as Qo,createHash as Wo,randomBytes as Ko}from"crypto";function pr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=Wo("sha256").update(e).digest(),t}function mr(e,t){let r=pr(t),o=Ko(12),n=Ho("aes-256-gcm",r,o),i=n.update(e,"utf8","base64");i+=n.final("base64");let a=n.getAuthTag();return{encryptedPrivateKey:i,iv:o.toString("base64"),authTag:a.toString("base64")}}function fr(e,t){let r=pr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=Qo("aes-256-gcm",r,a);d.setAuthTag(s);let c=d.update(o,"base64","utf8");return c+=d.final("utf8"),c}var bm=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await st(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[w]},async t=>{let r=st(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await Jo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await gr(c),g=await gr(l),m=JSON.stringify(g),k={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(mr(m,t.context.options.secret)):m,createdAt:new Date};o=await r.createJwk(k)}let i=n?fr(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await Go(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new Zo({...s,...t.context.session.session.impersonatedBy?{impersonatedBy:t.context.session.session.impersonatedBy}:{}}).setProtectedHeader({alg:e?.jwks?.keyPairConfig?.alg??"EdDSA",kid:o.id}).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:lr});import{z as Ge}from"zod";var vm=e=>{let t={maximumSessions:5,...e},r=o=>o.includes("_multi-");return{id:"multi-session",endpoints:{listDeviceSessions:u("/multi-session/list-device-sessions",{method:"GET",requireHeaders:!0},async o=>{let n=o.headers?.get("cookie");if(!n)return o.json([]);let i=Object.fromEntries(xe(n)),a=(await Promise.all(Object.entries(i).filter(([c])=>r(c)).map(async([c])=>await o.getSignedCookie(c,o.context.secret)))).filter(c=>c!==void 0),d=(await o.context.internalAdapter.findSessions(a)).filter(c=>c&&c.session.expiresAt>new Date).filter((c,l,p)=>l===p.findIndex(g=>g.user.id===c.user.id));return Object.entries(i).filter(([c])=>r(c)).forEach(([c,l])=>{d.some(p=>p.session.id===l)||o.setCookie(c,"",{...o.context.authCookies.sessionToken.options,maxAge:0})}),o.json(d)}),setActiveSession:u("/multi-session/set-active",{method:"POST",body:Ge.object({sessionId:Ge.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new M("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);if(!s||s.session.expiresAt<new Date)throw o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),new M("UNAUTHORIZED",{message:"Invalid session id"});return await o.setSignedCookie(o.context.authCookies.sessionToken.name,n,o.context.secret,o.context.authCookies.sessionToken.options),o.json(s)}),DeviceSession:u("/multi-session/revoke",{method:"POST",body:Ge.object({sessionId:Ge.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new M("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);return!s||s.session.expiresAt<new Date?(o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0})):(await o.context.internalAdapter.deleteSession(n),o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0}))})},hooks:{after:[{matcher:()=>!0,handler:T(async o=>{if(!o.context.returned||!(o.context.returned instanceof Response))return;let n=o.context.returned.headers.get("set-cookie");if(!n)return;let i=lt(n),a=o.context.authCookies.sessionToken,s=i.get(a.name)?.value;if(!s)return;let d=xe(o.headers?.get("cookie")||""),c=s.split(".")[0],l=`${a.name}_multi-${c}`;if(i.get(l)||d.get(l))return;if(Object.keys(Object.fromEntries(d)).filter(r).length+(n.includes("session_token")?1:0)>t.maximumSessions)throw new M("UNAUTHORIZED",{message:"Maximum number of device sessions reached."});await o.setSignedCookie(l,c,o.context.secret,a.options);let g=o.context.returned;return g.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:g}})},{matcher:o=>o.path==="/sign-out",handler:T(async o=>{let n=o.headers?.get("cookie");if(!n)return;let i=Object.fromEntries(xe(n));await Promise.all(Object.entries(i).map(async([s,d])=>{r(s)&&(o.setCookie(s,"",{maxAge:0}),await o.context.internalAdapter.deleteSession(s.split("_multi-")[1]))}));let a=o.context.returned;return a?.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:a}})}]}}};export{de as HIDE_METADATA,Nt as ac,$p as admin,re as adminMiddleware,xp as anonymous,pp as bearer,u as createAuthEndpoint,T as createAuthMiddleware,sm as genericOAuth,zo as getPasskeyActions,bm as jwt,Ap as magicLink,vm as multiSession,dt as optionsMiddleware,iu as organization,op as passkey,Vl as passkeyClient,Pp as phoneNumber,rl as twoFactor,$u as twoFactorClient,ur as username};
|