authhero 0.244.0 → 0.245.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/authhero.cjs CHANGED
@@ -69,7 +69,7 @@
69
69
  <\/script>
70
70
  </body>
71
71
 
72
- </html>`}class Zi extends S{constructor(e,n){super(e,{message:JSON.stringify(n),res:new Response(JSON.stringify(n),{status:e,headers:{"Content-Type":"application/json"}})})}}const b2=["openid","profile","email","address","phone"];async function s4(t,e){var x,q;const{tenantId:n,clientId:r,audience:i,requestedScopes:o}=e,a=o.filter(U=>b2.includes(U)),u=(await t.env.data.resourceServers.list(n)).resource_servers.filter(U=>U.identifier===i);if(u.length===0)return{scopes:a,permissions:[]};const d=u[0];if(!d)return{scopes:a,permissions:[]};const p=((x=d.options)==null?void 0:x.enforce_policies)===!0,g=((q=d.options)==null?void 0:q.token_dialect)||"access_token",v=(await t.env.data.clientGrants.list(n,{q:`client_id:"${r}"`})).client_grants.find(U=>U.audience===i);if(!v)return{scopes:a,permissions:[]};const $=v.scope||[],E=(d.scopes||[]).map(U=>U.value);if(!p){let U;return o.length===0?U=$.filter(M=>E.includes(M)):U=o.filter(M=>E.includes(M)&&$.includes(M)),{scopes:[...new Set([...a,...U])],permissions:[]}}if(g==="access_token_authz"){const U=$.filter(O=>E.includes(O));return{scopes:a,permissions:U}}let N;return o.length===0?N=$.filter(U=>E.includes(U)):N=o.filter(U=>E.includes(U)&&$.includes(U)),{scopes:[...new Set([...a,...N])],permissions:[]}}async function Qa(t,e){var V,H;if(e.grantType===mn.ClientCredential)return await s4(t,{tenantId:e.tenantId,clientId:e.clientId,audience:e.audience,requestedScopes:e.requestedScopes});const{tenantId:n,userId:r,audience:i,requestedScopes:o,organizationId:a}=e;if(a&&!(await t.env.data.userOrganizations.list(n,{q:`user_id:${r}`,per_page:1e3})).userOrganizations.some(R=>R.organization_id===a))throw new Zi(403,{error:"access_denied",error_description:"User is not a member of the specified organization"});const l=o.filter(K=>b2.includes(K)),d=(await t.env.data.resourceServers.list(n)).resource_servers.filter(K=>K.identifier===i);if(d.length===0)return{scopes:l,permissions:[]};const p=d[0];if(!p)return{scopes:l,permissions:[]};const g=(p.scopes||[]).map(K=>K.value),m=((V=p.options)==null?void 0:V.enforce_policies)===!0,v=((H=p.options)==null?void 0:H.token_dialect)||"access_token";if(!m){const K=o.filter(R=>g.includes(R));return{scopes:[...new Set([...l,...K])],permissions:[]}}const $=await t.env.data.userPermissions.list(n,r,void 0,a),E=await t.env.data.userRoles.list(n,r,void 0,""),N=a?await t.env.data.userRoles.list(n,r,void 0,a):[],z=[...E,...N],x=[];for(const K of z)(await t.env.data.rolePermissions.list(n,K.id)).forEach(R=>{R.resource_server_identifier===i&&x.push(R.permission_name)});const q=new Set;$.forEach(K=>{K.resource_server_identifier===i&&q.add(K.permission_name)}),x.forEach(K=>{q.add(K)});const U=Array.from(q);if(v==="access_token_authz"){const K=U.filter(ce=>g.includes(ce));return{scopes:l,permissions:K}}const O=o.filter(K=>g.includes(K)&&U.includes(K));return{scopes:[...new Set([...l,...O])],permissions:[]}}const Y0=["sub","iss","aud","exp","nbf","iat","jti"];async function tl(t,e){var q,U;const{authParams:n,user:r,client:i,session_id:o,organization:a,permissions:l,impersonatingUser:u}=e,{signingKeys:d}=await t.env.data.keys.list({q:"type:jwt_signing"}),p=d.filter(O=>!O.revoked_at||new Date(O.revoked_at)>new Date),g=p[p.length-1];if(!(g!=null&&g.pkcs7))throw new S(500,{message:"No signing key available"});const m=zb(g.pkcs7),v=t.var.custom_domain?`https://${t.var.custom_domain}/`:t.env.ISSUER,$={aud:n.audience||"default",scope:n.scope||"",sub:(r==null?void 0:r.user_id)||n.client_id,iss:v,tenant_id:t.var.tenant_id,sid:o,act:u?{sub:u.user_id}:void 0,org_id:a?a.id:void 0,permissions:l},E=r&&((q=n.scope)!=null&&q.split(" ").includes("openid"))?{aud:n.client_id,sub:r.user_id,iss:v,sid:o,nonce:n.nonce,given_name:r.given_name,family_name:r.family_name,nickname:r.nickname,picture:r.picture,locale:r.locale,name:r.name,email:r.email,email_verified:r.email_verified,act:u?{sub:u.user_id}:void 0,organization:a?{org_id:a.id,org_name:a.name}:void 0}:void 0;(U=t.env.hooks)!=null&&U.onExecuteCredentialsExchange&&await t.env.hooks.onExecuteCredentialsExchange({ctx:t,client:i,user:r,request:{ip:t.var.ip||"",user_agent:t.var.useragent||"",method:t.req.method,url:t.req.url},scope:n.scope||"",grant_type:""},{accessToken:{setCustomClaim:(O,M)=>{if(Y0.includes(O))throw new Error(`Cannot overwrite reserved claim '${O}'`);$[O]=M}},idToken:{setCustomClaim:(O,M)=>{if(Y0.includes(O))throw new Error(`Cannot overwrite reserved claim '${O}'`);E&&(E[O]=M)}},access:{deny:O=>{throw new S(400,{message:`Access denied: ${O}`})}},token:{createServiceToken:async O=>{const{createServiceToken:M}=await Promise.resolve().then(()=>c4);return(await M(t,t.var.tenant_id,O.scope,O.expiresInSeconds)).access_token}}});const N={includeIssuedTimestamp:!0,expiresIn:u?new Ya(1,"h"):new Ya(1,"d"),headers:{kid:g.kid}},z=await V0("RS256",m,$,N),x=E?await V0("RS256",m,E,N):void 0;return{access_token:z,refresh_token:e.refresh_token,id_token:x,token_type:"Bearer",expires_in:u?3600:86400}}async function $2(t,e){return{code:(await t.env.data.codes.create(e.client.tenant.id,{code_id:Xe(),user_id:e.user.user_id,code_type:"authorization_code",login_id:e.login_id,expires_at:new Date(Date.now()+Ob*1e3).toISOString(),code_challenge:e.authParams.code_challenge,code_challenge_method:e.authParams.code_challenge_method,redirect_uri:e.authParams.redirect_uri,state:e.authParams.state,nonce:e.authParams.nonce})).code_id,state:e.authParams.state}}async function x2(t,e){const{client:n,scope:r,audience:i=n.tenant.audience,session_id:o}=e;return await t.env.data.refreshTokens.create(n.tenant.id,{id:Xe(),session_id:o,client_id:n.client_id,idle_expires_at:new Date(Date.now()+Qc*1e3).toISOString(),user_id:e.user.user_id,device:{last_ip:t.var.ip,initial_ip:t.var.ip,last_user_agent:t.var.useragent||"",initial_user_agent:t.var.useragent||"",initial_asn:"",last_asn:""},resource_servers:[{audience:i,scopes:r}],rotating:!1})}async function A2(t,{user:e,client:n,loginSession:r}){const i=await t.env.data.sessions.create(n.tenant.id,{id:Xe(),user_id:e.user_id,login_session_id:r.id,idle_expires_at:new Date(Date.now()+Qc*1e3).toISOString(),device:{last_ip:t.var.ip||"",initial_ip:t.var.ip||"",last_user_agent:t.var.useragent||"",initial_user_agent:t.var.useragent||"",initial_asn:"",last_asn:""},clients:[n.client_id]});return await t.env.data.loginSessions.update(n.tenant.id,r.id,{session_id:i.id}),i}async function Mn(t,e){var v,$;const{authParams:n,client:r,ticketAuth:i}=e;let{user:o}=e;const a=n.response_type||an.CODE,l=n.response_mode||Bn.QUERY;if(i){if(!e.loginSession)throw new S(500,{message:"Login session not found for ticket auth."});const E=Cb(),N=Xe(12),z=await t.env.data.codes.create(r.tenant.id,{code_id:Xe(),code_type:"ticket",login_id:e.loginSession.id,expires_at:new Date(Date.now()+Db).toISOString(),code_verifier:[N,E].join("|"),redirect_uri:n.redirect_uri,state:n.state,nonce:n.nonce});return t.json({login_ticket:z.code_id,co_verifier:E,co_id:N})}let u=e.refreshToken,d=e.sessionId;if(!d&&((v=e.loginSession)!=null&&v.session_id)){d=e.loginSession.session_id;const E=await t.env.data.sessions.get(r.tenant.id,d);E&&!E.clients.includes(r.client_id)&&await t.env.data.sessions.update(r.tenant.id,d,{clients:[...E.clients,r.client_id]})}else if(!d){if(!e.loginSession)throw new S(500,{message:"Login session not found for creating a new session."});d=(await A2(t,{user:o,client:r,loginSession:e.loginSession})).id}if(!u&&(($=n.scope)!=null&&$.split(" ").includes("offline_access"))&&![an.TOKEN,an.CODE].includes(a)&&!e.impersonatingUser&&(u=(await x2(t,{user:o,client:r,session_id:d,scope:n.scope,audience:n.audience})).id),l===Bn.SAML_POST){if(!d)throw new S(500,{message:"Session ID not available for SAML response"});return i4(t,e.client,e.authParams,o,d)}const p=await a4(t,{authParams:n,user:o,client:r,session_id:d,refresh_token:u,strategy:e.strategy,loginSession:e.loginSession,responseType:a,skipHooks:e.skipHooks,organization:e.organization,impersonatingUser:e.impersonatingUser});if(p instanceof Response)return p;if(l===Bn.WEB_MESSAGE){if(!n.redirect_uri)throw new S(400,{message:"Redirect URI not allowed for WEB_MESSAGE response mode."});const E=new Headers;if(d){const x=Za(r.tenant.id,d,t.var.host||"");x&&E.set("set-cookie",x)}else console.warn("Session ID not available for WEB_MESSAGE, cookie will not be set.");const N=new URL(n.redirect_uri),z=`${N.protocol}//${N.host}`;return t.html(td(z,JSON.stringify({...p,state:n.state})),{headers:E})}if(!n.redirect_uri)throw new S(400,{message:"Redirect uri not found for this response mode."});const g=new Headers;if(d){const E=Za(r.tenant.id,d,t.var.custom_domain||t.req.header("host")||"");E&&g.set("set-cookie",E)}const m=new URL(n.redirect_uri);if("code"in p)m.searchParams.set("code",p.code),p.state&&m.searchParams.set("state",p.state);else if("access_token"in p)m.hash=new URLSearchParams({access_token:p.access_token,...p.id_token&&{id_token:p.id_token},token_type:p.token_type,expires_in:p.expires_in.toString(),...n.state&&{state:n.state},...n.scope&&{scope:n.scope}}).toString();else throw new S(500,{message:"Invalid token response for implicit flow."});return g.set("location",m.toString()),new Response("Redirecting",{status:302,headers:g})}async function a4(t,e){var l,u,d,p,g,m;let{user:n}=e;const r=e.responseType||an.TOKEN;if(n&&e.organization&&!(await t.env.data.userOrganizations.list(e.client.tenant.id,{q:`user_id:${n.user_id}`,per_page:1e3})).userOrganizations.some(E=>E.organization_id===e.organization.id))throw new Zi(403,{error:"access_denied",error_description:"User is not a member of the specified organization"});let i=e.authParams.scope||"",o=[];if(e.authParams.audience)try{let v;if(e.grantType===mn.ClientCredential||!n&&!e.user)v=await Qa(t,{grantType:mn.ClientCredential,tenantId:e.client.tenant.id,clientId:e.client.client_id,audience:e.authParams.audience,requestedScopes:((l=e.authParams.scope)==null?void 0:l.split(" "))||[],organizationId:(u=e.organization)==null?void 0:u.id});else{const $=(n==null?void 0:n.user_id)||((d=e.user)==null?void 0:d.user_id);if(!$)throw new Zi(400,{error:"invalid_request",error_description:"User ID is required for user-based grants"});v=await Qa(t,{grantType:e.grantType,tenantId:e.client.tenant.id,userId:$,clientId:e.client.client_id,audience:e.authParams.audience,requestedScopes:((p=e.authParams.scope)==null?void 0:p.split(" "))||[],organizationId:(g=e.organization)==null?void 0:g.id})}i=v.scopes.join(" "),o=v.permissions}catch(v){if(v instanceof S)throw v}const a={...e.authParams,scope:i};if(e.loginSession&&n&&!e.skipHooks){e.strategy&&((m=n.app_metadata)==null?void 0:m.strategy)!==e.strategy&&(n.app_metadata={...n.app_metadata,strategy:e.strategy},await t.env.data.users.update(e.client.tenant.id,n.user_id,{app_metadata:{...n.app_metadata||{},strategy:e.strategy}}));const v=await E2(t,t.env.data,e.client.tenant.id,n,e.loginSession,{client:e.client,authParams:a,authStrategy:e.strategy?{strategy:e.strategy,strategy_type:"social"}:void 0});if(v instanceof Response)return v;n=v}if(r===an.CODE){if(!n||!e.loginSession)throw new S(500,{message:"User and loginSession is required for code flow"});return await $2(t,{user:n,client:e.client,authParams:a,login_id:e.loginSession.id})}else return tl(t,{...e,user:n,authParams:a,permissions:o})}const Z0="auth-service";async function Zp(t,e,n,r){const i=await t.env.data.tenants.get(e);if(!i)throw new Error(`Tenant not found: ${e}`);const o={client_id:Z0,tenant:i,created_at:new Date().toISOString(),updated_at:new Date().toISOString(),name:"Auth Service",global:!1,is_first_party:!0,oidc_conformant:!1,sso:!1,sso_disabled:!1,cross_origin_authentication:!1,custom_login_page_on:!1,require_pushed_authorization_requests:!1,require_proof_of_possession:!1,client_metadata:{disable_sign_ups:"false",email_validation:"disabled"},disable_sign_ups:!1,email_validation:"disabled",connections:[]},a=await tl(t,{client:o,authParams:{client_id:Z0,response_type:an.TOKEN,scope:n}});return{access_token:a.access_token,token_type:a.token_type,expires_in:r||3600}}const c4=Object.freeze(Object.defineProperty({__proto__:null,createServiceToken:Zp},Symbol.toStringTag,{value:"Module"}));async function k2(t,e,n){const r=await Zp(t,n.tenant_id,"webhook");for await(const i of e.filter(o=>"url"in o))if(!(await fetch(i.url,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`,"Content-Type":"application/json"},body:JSON.stringify(n)})).ok){const a=We(t,{type:qe.FAILED_HOOK,description:`Failed to invoke hook ${i.hook_id}`});await t.env.data.logs.create(n.tenant_id,a)}}function l4(t){return async(e,n)=>{const{hooks:r}=await t.env.data.hooks.list(e);return await k2(t,r,{tenant_id:e,user:n,trigger_id:"post-user-registration"}),n}}function u4(t){return async(e,n)=>{const{hooks:r}=await t.env.data.hooks.list(e,{q:"trigger_id:pre-user-signup",page:0,per_page:100,include_totals:!1});await k2(t,r,{tenant_id:e,email:n,trigger_id:"pre-user-signup"})}}function Q0(t){return typeof t.form_id=="string"}async function d4(t,e,n){var u;const r=t.env.data,i=t.var.tenant_id||t.req.header("tenant-id");if(!i)throw new S(400,{message:"Missing tenant_id in context"});const o=await r.forms.get(i,e);if(!o)throw new S(404,{message:"Form not found for post-user-login hook"});let a=(u=o.start)==null?void 0:u.next_node;if(!a&&o.nodes&&o.nodes.length>0){const d=o.nodes.find(p=>p.type==="STEP");a=d==null?void 0:d.id}if(!a)throw new S(400,{message:"No start node found in form"});let l=`/u/forms/${o.id}/nodes/${a}?state=${encodeURIComponent(n.id)}`;return new Response(null,{status:302,headers:{location:l}})}function eh(t){return typeof t.page_id=="string"&&typeof t.enabled=="boolean"}async function p4(t,e,n,r,i){const o=t.env.data,a=t.var.tenant_id||t.req.header("tenant-id");if(!a)throw new S(400,{message:"Missing tenant_id in context"});if(i&&!(await o.userPermissions.list(a,r.user_id)).some(p=>p.permission_name===i))return r;let l=`/u/${e}?state=${encodeURIComponent(n.id)}`;return new Response(null,{status:302,headers:{location:l}})}function Qi(t,e){return{createServiceToken:async n=>(await Zp(t,e,n.scope,n.expiresInSeconds)).access_token}}function th(t){return typeof t.url=="string"}function f4(t,e){return async(n,r)=>{var a,l,u;const i={method:t.req.method,ip:t.req.query("x-real-ip")||"",user_agent:t.req.query("user-agent"),url:((a=t.var.loginSession)==null?void 0:a.authorization_url)||t.req.url};if((l=t.env.hooks)!=null&&l.onExecutePreUserRegistration)try{await t.env.hooks.onExecutePreUserRegistration({ctx:t,user:r,request:i},{user:{setUserMetadata:async(d,p)=>{r[d]=p}},token:Qi(t,n)})}catch{const p=We(t,{type:qe.FAILED_SIGNUP,description:"Pre user registration hook failed"});await e.logs.create(n,p)}let o=await xb(e)(n,r);if((u=t.env.hooks)!=null&&u.onExecutePostUserRegistration)try{await t.env.hooks.onExecutePostUserRegistration({ctx:t,user:r,request:i},{user:{},token:Qi(t,n)})}catch{const p=We(t,{type:qe.FAILED_SIGNUP,description:"Post user registration hook failed"});await t.env.data.logs.create(n,p)}return await l4(t)(n,o),o}}function h4(t,e){return async(n,r,i)=>{var l;if(Object.keys(i).length===1&&"linked_to"in i)return e.users.update(n,r,i);const o=await e.users.get(n,r);if(!o)throw new S(404,{message:"User not found"});const a={method:t.req.method,ip:t.var.ip||t.get("ip")||"",user_agent:t.var.useragent||t.get("useragent")||"",url:t.req.url};if((l=t.env.hooks)!=null&&l.onExecutePreUserUpdate)try{await t.env.hooks.onExecutePreUserUpdate({ctx:t,tenant:{id:n},user_id:r,user:o,updates:i,request:a},{user:{setUserMetadata:async(u,d)=>{i[u]=d}},cancel:()=>{throw new S(400,{message:"User update cancelled by pre-update hook"})},token:Qi(t,n)})}catch{throw new S(400,{message:"Pre user update hook failed"})}if(await e.users.update(n,r,i),i.email||i.email_verified){const u=await e.users.get(n,r);if(u&&u.email&&u.email_verified){const{users:d}=await e.users.list(n,{page:0,per_page:10,include_totals:!1,q:`email:${u.email}`}),p=d.filter(g=>g.email_verified&&g.user_id!==r&&!g.linked_to);p.length>0&&await e.users.update(n,r,{linked_to:p[0].user_id})}}if(i.email){const u=We(t,{type:qe.SUCCESS_CHANGE_EMAIL,description:`Email updated to ${i.email}`,userId:r});await e.logs.create(n,u)}return!0}}async function g4(t,e,n,r){var i,o;if(((i=e.client_metadata)==null?void 0:i.disable_sign_ups)==="true"){const a=(o=t.var.loginSession)==null?void 0:o.authorization_url;if(!(a&&new URL(a).searchParams.get("screen_hint")==="signup")&&!await ef({userAdapter:n.users,tenant_id:e.tenant.id,email:r})){const d=We(t,{type:qe.FAILED_SIGNUP,description:"Public signup is disabled"});throw await n.logs.create(e.tenant.id,d),new S(400,{message:"Signups are disabled for this client"})}}await u4(t)(t.var.tenant_id||"",r)}function m4(t,e){return async(n,r)=>{var l,u;const i=await e.users.get(n,r);if(!i)return!1;const o={method:t.req.method,ip:t.var.ip||t.get("ip")||"",user_agent:t.var.useragent||t.get("useragent")||"",url:t.req.url};if((l=t.env.hooks)!=null&&l.onExecutePreUserDeletion)try{await t.env.hooks.onExecutePreUserDeletion({ctx:t,user:i,user_id:r,request:o,tenant:{id:n}},{cancel:()=>{throw new S(400,{message:"User deletion cancelled by pre-deletion hook"})},token:Qi(t,n)})}catch(d){if(d instanceof S)throw d;const p=We(t,{type:qe.FAILED_HOOK,description:`Pre user deletion hook failed: ${d instanceof Error?d.message:String(d)}`});throw await e.logs.create(n,p),new S(400,{message:"Pre user deletion hook failed"})}const a=await e.users.remove(n,r);if(a){const d=We(t,{type:qe.SUCCESS_USER_DELETION,description:`user_id: ${r}`,strategy:i.provider||"auth0",strategy_type:i.is_social?"social":"database"});d.connection=i.connection||"",d.connection_id="",d.details={...d.details,body:{tenant:n,connection:i.connection||""}},await e.logs.create(n,d)}if(a&&((u=t.env.hooks)!=null&&u.onExecutePostUserDeletion))try{await t.env.hooks.onExecutePostUserDeletion({ctx:t,user:i,user_id:r,request:o,tenant:{id:n}},{token:Qi(t,n)})}catch(d){const p=We(t,{type:qe.FAILED_HOOK,description:`Post user deletion hook failed: ${d instanceof Error?d.message:String(d)}`});await e.logs.create(n,p)}return a}}function ks(t,e){const n=e;return{...e,users:{...e.users,create:f4(t,n),update:h4(t,n),remove:m4(t,n)}}}async function _4(t,e,n,r,i,o){var p,g,m,v,$,E,N,z,x,q,U,O,M,V;let a=[];try{a=(await e.userRoles.list(n,r.user_id,void 0,"")).map(ce=>ce.name||ce.id)}catch(H){console.error("Error fetching user roles:",H)}let l={};if(r.connection)try{const K=(await e.connections.list(n,{page:0,per_page:100,include_totals:!1})).connections.find(ce=>ce.name===r.connection);K&&(l={id:K.id,name:K.name,strategy:K.strategy||r.provider,metadata:K.options||{}})}catch(H){console.error("Error fetching connection info:",H)}let u;try{if((p=i.authParams)!=null&&p.organization){const H=await e.organizations.get(n,i.authParams.organization);H&&(u={id:H.id,name:H.name,display_name:H.display_name||H.name,metadata:H.metadata||{}})}}catch(H){console.error("Error fetching organization info:",H)}const d=t.get("countryCode");return{ctx:t,client:o.client,user:r,request:{asn:void 0,ip:t.get("ip")||"",user_agent:t.get("useragent"),method:t.req.method,url:t.req.url,geoip:{cityName:void 0,continentCode:void 0,countryCode:d||void 0,countryName:void 0,latitude:void 0,longitude:void 0,timeZone:void 0}},transaction:{id:i.id,locale:((g=i.authParams)==null?void 0:g.ui_locales)||"en",login_hint:void 0,prompt:(m=i.authParams)==null?void 0:m.prompt,redirect_uri:(v=i.authParams)==null?void 0:v.redirect_uri,requested_scopes:((E=($=i.authParams)==null?void 0:$.scope)==null?void 0:E.split(" "))||[],response_mode:(N=i.authParams)==null?void 0:N.response_mode,response_type:(z=i.authParams)==null?void 0:z.response_type,state:(x=i.authParams)==null?void 0:x.state,ui_locales:(q=i.authParams)==null?void 0:q.ui_locales},scope:((U=o.authParams)==null?void 0:U.scope)||"",grant_type:((O=o.authParams)==null?void 0:O.grant_type)||"",audience:(M=o.authParams)==null?void 0:M.audience,authentication:{methods:[{name:r.is_social?"federated":"pwd",timestamp:new Date().toISOString()}]},authorization:{roles:a},connection:Object.keys(l).length>0?l:{id:r.connection||"Username-Password-Authentication",name:r.connection||"Username-Password-Authentication",strategy:r.provider||"auth0"},organization:u,resource_server:(V=o.authParams)!=null&&V.audience?{identifier:o.authParams.audience}:void 0,stats:{logins_count:r.login_count||0},tenant:{id:n},session:{id:i.id,created_at:i.created_at,authenticated_at:new Date().toISOString(),clients:[{client_id:o.client.client_id}],device:{initial_ip:t.get("ip"),initial_user_agent:t.get("useragent"),last_ip:r.last_ip||t.get("ip"),last_user_agent:t.get("useragent")}}}}async function E2(t,e,n,r,i,o){var g,m,v,$,E;const a=(g=o==null?void 0:o.authStrategy)!=null&&g.strategy_type?o.authStrategy.strategy_type:r.is_social?"social":"database",l=((m=o==null?void 0:o.authStrategy)==null?void 0:m.strategy)||r.connection||"",u=We(t,{type:qe.SUCCESS_LOGIN,description:`Successful login for ${r.user_id}`,userId:r.user_id,strategy_type:a,strategy:l,connection:l,audience:(v=o==null?void 0:o.authParams)==null?void 0:v.audience,scope:($=o==null?void 0:o.authParams)==null?void 0:$.scope});if(await e.logs.create(n,u),await e.users.update(n,r.user_id,{last_login:new Date().toISOString(),last_ip:t.var.ip||"",login_count:r.login_count+1}),(E=t.env.hooks)!=null&&E.onExecutePostLogin&&(o!=null&&o.client)&&(o!=null&&o.authParams)&&i){let N=null;const z=await _4(t,e,n,r,i,{client:o.client,authParams:o.authParams});if(await t.env.hooks.onExecutePostLogin(z,{prompt:{render:x=>{}},redirect:{sendUserTo:(x,q)=>{const U=new URL(x,t.req.url);U.searchParams.set("state",i.id),q!=null&&q.query&&Object.entries(q.query).forEach(([O,M])=>{U.searchParams.set(O,M)}),N=U.toString()},encodeToken:x=>JSON.stringify({payload:x.payload,exp:Date.now()+(x.expiresInSeconds||900)*1e3}),validateToken:x=>null},token:Qi(t,n)}),N)return new Response(null,{status:302,headers:{location:N}})}const{hooks:d}=await e.hooks.list(n,{q:"trigger_id:post-user-login",page:0,per_page:100,include_totals:!1});if(i){const N=d.find(x=>x.enabled&&Q0(x));if(N&&Q0(N))return d4(t,N.form_id,i);const z=d.find(x=>x.enabled&&eh(x));if(z&&eh(z))return p4(t,z.page_id,i,r,z.permission_required)}const p=d.filter(N=>N.enabled&&th(N));for(const N of p)if(th(N))try{await fetch(N.url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tenant_id:n,user:r,trigger_id:"post-user-login"})})}catch{const x=We(t,{type:qe.FAILED_HOOK,description:`Failed to invoke post-user-login webhook: ${N.url}`});await e.logs.create(n,x)}return r}function y4(t){return ks(t,t.env.data)}async function Qp(t,e,n){return(await t.list(e,{page:0,per_page:10,include_totals:!1,q:`email:${n}`})).users}async function vo({userAdapter:t,tenant_id:e,username:n,provider:r}){const i=r==="sms"?`phone_number:${n}`:`email:${n}`,{users:o}=await t.list(e,{page:0,per_page:10,include_totals:!1,q:`${i} provider:${r}`});return o.length>1&&console.error("More than one user found for same email and provider"),o[0]||null}async function ef({userAdapter:t,tenant_id:e,email:n}){var l;const{users:r}=await t.list(e,{page:0,per_page:10,include_totals:!1,q:`email:${n}`}),i=r.filter(u=>!(u.provider==="auth2"&&!u.email_verified));if(i.length===0)return;const o=i.filter(u=>!u.linked_to);if(o.length>0)return o.length>1&&console.error("More than one primary user found for same email"),o[0];const a=await t.get(e,(l=i[0])==null?void 0:l.linked_to);if(!a)throw new Error("Primary account not found");return a}async function rs({userAdapter:t,tenant_id:e,username:n,provider:r}){const i=await vo({userAdapter:t,tenant_id:e,username:n,provider:r});return i?i.linked_to?t.get(e,i.linked_to):i:null}async function nl(t,e){const{username:n,provider:r,connection:i,client:o,userId:a,isSocial:l,profileData:u={},ip:d=""}=e;let p=await rs({userAdapter:t.env.data.users,tenant_id:e.client.tenant.id,username:n,provider:r});if(!p){const g={user_id:`${r}|${a||Yc()}`,email:i!=="sms"?n:void 0,phone_number:i==="sms"?n:void 0,name:n,provider:r,connection:i,email_verified:!0,last_ip:d,is_social:l,last_login:new Date().toISOString(),profileData:JSON.stringify(u)};p=await y4(t).users.create(o.tenant.id,g),t.set("user_id",p.user_id)}return p}const ht=s.z.object({page:s.z.string().min(0).optional().default("0").transform(t=>parseInt(t,10)).openapi({description:"The page number where 0 is the first page"}),per_page:s.z.string().min(1).optional().default("10").transform(t=>parseInt(t,10)).openapi({description:"The number of items per page"}),include_totals:s.z.string().optional().default("false").transform(t=>t==="true").openapi({description:"If the total number of items should be included in the response"}),sort:s.z.string().regex(/^.+:(-1|1)$/).optional().openapi({description:"A property that should have the format 'string:-1' or 'string:1'"}),q:s.z.string().optional().openapi({description:"A lucene query string used to filter the results"})});function It(t){if(!t)return;const[e,n]=t.split(":"),r=n==="1"?"asc":"desc";if(!(!e||!r))return{sort_by:e,sort_order:r}}var w4={deno:"Deno",bun:"Bun",workerd:"Cloudflare-Workers",node:"Node.js"},S2=()=>{var n,r;const t=globalThis;if(typeof navigator<"u"&&typeof navigator.userAgent=="string"){for(const[i,o]of Object.entries(w4))if(v4(o))return i}return typeof(t==null?void 0:t.EdgeRuntime)=="string"?"edge-light":(t==null?void 0:t.fastly)!==void 0?"fastly":((r=(n=t==null?void 0:t.process)==null?void 0:n.release)==null?void 0:r.name)==="node"?"node":"other"},v4=t=>navigator.userAgent.startsWith(t);function wn(t,e){S2()==="workerd"&&t.executionCtx.waitUntil(e)}const nh=Mt.extend({users:s.z.array(Dn)}),b4=Mt.extend({sessions:s.z.array(Xc)}),$4=Mt.extend({organizations:s.z.array(Er)}),x4=new s.OpenAPIHono().openapi(s.createRoute({tags:["users"],method:"get",path:"/",request:{query:ht,headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:s.z.union([s.z.array(Dn),nh])}},description:"List of users"}}}),async t=>{const{page:e,per_page:n,include_totals:r,sort:i,q:o}=t.req.valid("query");if(o!=null&&o.includes("identities.profileData.email")){const d=o.split("=")[1],g=(await t.env.data.users.list(t.var.tenant_id,{page:e,per_page:n,include_totals:r,q:`email:${d}`})).users.filter($=>$.linked_to),[m]=g;if(!m)return t.json([]);const v=await t.env.data.users.get(t.var.tenant_id,m.linked_to);if(!v)throw new S(500,{message:"Primary account not found"});return t.json([Dn.parse(v)])}const a=["-_exists_:linked_to"];o&&a.push(o);const l=await t.env.data.users.list(t.var.tenant_id,{page:e,per_page:n,include_totals:r,sort:It(i),q:a.join(" ")}),u=l.users.filter(d=>!d.linked_to);return r?t.json(nh.parse({users:u,length:l.length,start:l.start,limit:l.limit})):t.json(s.z.array(Dn).parse(u))}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:Dn}},description:"List of users"}}}),async t=>{const{user_id:e}=t.req.valid("param"),n=await t.env.data.users.get(t.var.tenant_id,e);if(!n)throw new S(404);if(n.linked_to)throw new S(404,{message:"User is linked to another user"});return t.json(n)}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Status"}}}),async t=>{const{user_id:e}=t.req.valid("param");if(!await t.env.data.users.remove(t.var.tenant_id,e))throw new S(404);const r=We(t,{type:qe.SUCCESS_API_OPERATION,description:"Delete a User"});return r.details={...r.details,response:{statusCode:204,body:{}}},wn(t,t.env.data.logs.create(t.var.tenant_id,r)),t.text("OK")}).openapi(s.createRoute({tags:["users"],method:"post",path:"/",request:{headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({...Fa.shape})}}}},security:[{Bearer:["auth:write"]}],responses:{201:{content:{"application/json":{schema:Dn}},description:"Status"}}}),async t=>{const e=t.req.valid("json");t.set("body",e);const{email:n,phone_number:r,name:i,linked_to:o,email_verified:a,provider:l,connection:u}=e,d=`${e.provider}|${e.user_id||Yc()}`;try{const p=await t.env.data.users.create(t.var.tenant_id,{email:n,user_id:d,name:i||n||r,phone_number:r,provider:l,connection:u,linked_to:o??void 0,email_verified:a||!1,last_ip:"",is_social:!1,last_login:new Date().toISOString()});t.set("user_id",p.user_id);const g=We(t,{type:qe.SUCCESS_API_OPERATION,description:"User created"});wn(t,t.env.data.logs.create(t.var.tenant_id,g));const m={...p,identities:[{connection:p.connection,provider:p.provider,user_id:q0(p.user_id),isSocial:p.is_social}]};return t.json(Dn.parse(m),{status:201})}catch(p){throw p.message==="User already exists"?new S(409,{message:"User already exists"}):p}}).openapi(s.createRoute({tags:["users"],method:"patch",path:"/{user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({...Fa.shape,verify_email:s.z.boolean(),password:s.z.string()}).partial()}}},params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Status"}}}),async t=>{var p;const{data:e}=t.env,n=t.req.valid("json"),{user_id:r}=t.req.valid("param"),{verify_email:i,password:o,...a}=n,l=await e.users.get(t.var.tenant_id,r);if(!l)throw new S(404);if(a.email&&a.email!==l.email){const g=await Qp(t.env.data.users,t.var.tenant_id,a.email);if(g.length&&g.some(m=>m.user_id!==r))throw new S(409,{message:"Another user with the same email address already exists."})}if(l.linked_to)throw new S(404,{message:"User is linked to another user"});if(await t.env.data.users.update(t.var.tenant_id,r,a),o){const g=(p=l.identities)==null?void 0:p.find($=>$.connection==="Username-Password-Authentication");if(!g)throw new S(400,{message:"User does not have a password identity"});const m={user_id:g.user_id,password:await As.hash(o,10),algorithm:"bcrypt"};await e.passwords.get(t.var.tenant_id,g.user_id)?await e.passwords.update(t.var.tenant_id,m):await e.passwords.create(t.var.tenant_id,m)}const u=await t.env.data.users.get(t.var.tenant_id,r);if(!u)throw new S(500);const d=We(t,{type:qe.SUCCESS_API_OPERATION,description:"Update a User",body:n});return d.details={...d.details,response:{statusCode:200,body:u}},wn(t,t.env.data.logs.create(t.var.tenant_id,d)),t.json(u)}).openapi(s.createRoute({tags:["users"],method:"post",path:"/{user_id}/identities",request:{headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.union([s.z.object({link_with:s.z.string()}),s.z.object({user_id:s.z.string(),provider:s.z.string(),connection:s.z.string().optional()})])}}},params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{201:{content:{"application/json":{schema:s.z.array(s.z.object({connection:s.z.string(),provider:s.z.string(),user_id:s.z.string(),isSocial:s.z.boolean()}))}},description:"Status"}}}),async t=>{const e=t.req.valid("json"),{user_id:n}=t.req.valid("param"),r="link_with"in e?e.link_with:e.user_id,i=await t.env.data.users.get(t.var.tenant_id,n);if(!i)throw new S(400,{message:"Linking an inexistent identity is not allowed."});await t.env.data.users.update(t.var.tenant_id,r,{linked_to:n});const o=await t.env.data.users.list(t.var.tenant_id,{page:0,per_page:10,include_totals:!1,q:`linked_to:${n}`}),a=[i,...o.users].map(l=>({connection:l.connection,provider:l.provider,user_id:q0(l.user_id),isSocial:l.is_social}));return t.json(a,{status:201})}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/identities/{provider}/{linked_user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string(),provider:s.z.string(),linked_user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{content:{"application/json":{schema:s.z.array(Dn)}},description:"Status"}}}),async t=>{const{user_id:e,provider:n,linked_user_id:r}=t.req.valid("param");await t.env.data.users.unlink(t.var.tenant_id,e,n,r);const i=await t.env.data.users.get(t.var.tenant_id,e);if(!i)throw new S(404);return t.json([Dn.parse(i)])}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/sessions",request:{query:ht,headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:s.z.union([s.z.array(Xc),b4])}},description:"List of sessions"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{include_totals:n,page:r,per_page:i}=t.req.valid("query"),o=await t.env.data.sessions.list(t.var.tenant_id,{page:r,per_page:i,include_totals:n,q:`user_id:${e}`});return n?t.json(o):t.json(o.sessions)}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/permissions",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),query:ht},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:Z_}},description:"User permissions"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{page:n,per_page:r,sort:i,q:o}=t.req.valid("query");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const l=await t.env.data.userPermissions.list(t.var.tenant_id,e,{page:n,per_page:r,include_totals:!1,sort:It(i),q:o});return t.json(l)}).openapi(s.createRoute({tags:["users"],method:"post",path:"/{user_id}/permissions",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({permissions:s.z.array(s.z.object({permission_name:s.z.string(),resource_server_identifier:s.z.string()}))})}}}},security:[{Bearer:["auth:write"]}],responses:{201:{description:"Permissions assigned to user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{permissions:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userPermissions.create(t.var.tenant_id,e,{user_id:e,resource_server_identifier:i.resource_server_identifier,permission_name:i.permission_name}))throw new S(500,{message:"Failed to assign permissions to user"});return t.json({message:"Permissions assigned successfully"},{status:201})}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/permissions",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({permissions:s.z.array(s.z.object({permission_name:s.z.string(),resource_server_identifier:s.z.string()}))})}}}},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Permissions removed from user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{permissions:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userPermissions.remove(t.var.tenant_id,e,i))throw new S(500,{message:"Failed to remove permissions from user"});return t.json({message:"Permissions removed successfully"})}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/roles",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:Xa}},description:"User roles"}}}),async t=>{const{user_id:e}=t.req.valid("param");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const r=await t.env.data.userRoles.list(t.var.tenant_id,e,void 0,"");return t.json(r)}).openapi(s.createRoute({tags:["users"],method:"post",path:"/{user_id}/roles",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({roles:s.z.array(s.z.string())})}}}},security:[{Bearer:["auth:write"]}],responses:{201:{description:"Roles assigned to user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{roles:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userRoles.create(t.var.tenant_id,e,i,""))throw new S(500,{message:"Failed to assign roles to user"});return t.json({message:"Roles assigned successfully"},{status:201})}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/roles",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({roles:s.z.array(s.z.string())})}}}},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Roles removed from user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{roles:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userRoles.remove(t.var.tenant_id,e,i,""))throw new S(500,{message:"Failed to remove roles from user"});return t.json({message:"Roles removed successfully"})}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/organizations",request:{params:s.z.object({user_id:s.z.string()}),query:ht,headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:s.z.union([$4,s.z.array(Er)])}},description:"List of user organizations"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{page:n,per_page:r,include_totals:i,sort:o}=t.req.valid("query");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const l=await t.env.data.userOrganizations.listUserOrganizations(t.var.tenant_id,e,{page:n,per_page:r,sort:It(o)});return i?t.json({organizations:l.organizations,start:l.start,limit:l.limit,length:l.length}):t.json(l.organizations)}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/organizations/{organization_id}",request:{params:s.z.object({user_id:s.z.string(),organization_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{description:"User removed from organization successfully"}}}),async t=>{const{user_id:e,organization_id:n}=t.req.valid("param");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const o=(await t.env.data.userOrganizations.list(t.var.tenant_id,{q:`user_id:${e}`,per_page:100})).userOrganizations.find(a=>a.organization_id===n);if(!o)throw new S(404,{message:"User is not a member of this organization"});return await t.env.data.userOrganizations.remove(t.var.tenant_id,o.id),t.json({message:"User removed from organization successfully"})});/*! *****************************************************************************
72
+ </html>`}class Zi extends S{constructor(e,n){super(e,{message:JSON.stringify(n),res:new Response(JSON.stringify(n),{status:e,headers:{"Content-Type":"application/json"}})})}}const b2=["openid","profile","email","address","phone"];async function s4(t,e){var x,q;const{tenantId:n,clientId:r,audience:i,requestedScopes:o}=e,a=o.filter(U=>b2.includes(U)),u=(await t.env.data.resourceServers.list(n)).resource_servers.filter(U=>U.identifier===i);if(u.length===0)return{scopes:a,permissions:[]};const d=u[0];if(!d)return{scopes:a,permissions:[]};const p=((x=d.options)==null?void 0:x.enforce_policies)===!0,g=((q=d.options)==null?void 0:q.token_dialect)||"access_token",v=(await t.env.data.clientGrants.list(n,{q:`client_id:"${r}"`})).client_grants.find(U=>U.audience===i);if(!v)return{scopes:a,permissions:[]};const $=v.scope||[],E=(d.scopes||[]).map(U=>U.value);if(!p){let U;return o.length===0?U=$.filter(M=>E.includes(M)):U=o.filter(M=>E.includes(M)&&$.includes(M)),{scopes:[...new Set([...a,...U])],permissions:[]}}if(g==="access_token_authz"){const U=$.filter(O=>E.includes(O));return{scopes:a,permissions:U}}let N;return o.length===0?N=$.filter(U=>E.includes(U)):N=o.filter(U=>E.includes(U)&&$.includes(U)),{scopes:[...new Set([...a,...N])],permissions:[]}}async function Qa(t,e){var V,H;if(e.grantType===mn.ClientCredential)return await s4(t,{tenantId:e.tenantId,clientId:e.clientId,audience:e.audience,requestedScopes:e.requestedScopes});const{tenantId:n,userId:r,audience:i,requestedScopes:o,organizationId:a}=e;if(a&&!(await t.env.data.userOrganizations.list(n,{q:`user_id:${r}`,per_page:1e3})).userOrganizations.some(R=>R.organization_id===a))throw new Zi(403,{error:"access_denied",error_description:"User is not a member of the specified organization"});const l=o.filter(K=>b2.includes(K)),d=(await t.env.data.resourceServers.list(n)).resource_servers.filter(K=>K.identifier===i);if(d.length===0)return{scopes:l,permissions:[]};const p=d[0];if(!p)return{scopes:l,permissions:[]};const g=(p.scopes||[]).map(K=>K.value),m=((V=p.options)==null?void 0:V.enforce_policies)===!0,v=((H=p.options)==null?void 0:H.token_dialect)||"access_token";if(!m){const K=o.filter(R=>g.includes(R));return{scopes:[...new Set([...l,...K])],permissions:[]}}const $=await t.env.data.userPermissions.list(n,r,void 0,a),E=await t.env.data.userRoles.list(n,r,void 0,""),N=a?await t.env.data.userRoles.list(n,r,void 0,a):[],z=[...E,...N],x=[];for(const K of z)(await t.env.data.rolePermissions.list(n,K.id)).forEach(R=>{R.resource_server_identifier===i&&x.push(R.permission_name)});const q=new Set;$.forEach(K=>{K.resource_server_identifier===i&&q.add(K.permission_name)}),x.forEach(K=>{q.add(K)});const U=Array.from(q);if(v==="access_token_authz"){const K=U.filter(ce=>g.includes(ce));return{scopes:l,permissions:K}}const O=o.filter(K=>g.includes(K)&&U.includes(K));return{scopes:[...new Set([...l,...O])],permissions:[]}}const Y0=["sub","iss","aud","exp","nbf","iat","jti"];async function tl(t,e){var q,U;const{authParams:n,user:r,client:i,session_id:o,organization:a,permissions:l,impersonatingUser:u}=e,{signingKeys:d}=await t.env.data.keys.list({q:"type:jwt_signing"}),p=d.filter(O=>!O.revoked_at||new Date(O.revoked_at)>new Date),g=p[p.length-1];if(!(g!=null&&g.pkcs7))throw new S(500,{message:"No signing key available"});const m=zb(g.pkcs7),v=t.var.custom_domain?`https://${t.var.custom_domain}/`:t.env.ISSUER,$={aud:n.audience||"default",scope:n.scope||"",sub:(r==null?void 0:r.user_id)||n.client_id,iss:v,tenant_id:t.var.tenant_id,sid:o,act:u?{sub:u.user_id}:void 0,org_id:a?a.id:void 0,permissions:l},E=r&&((q=n.scope)!=null&&q.split(" ").includes("openid"))?{aud:n.client_id,sub:r.user_id,iss:v,sid:o,nonce:n.nonce,given_name:r.given_name,family_name:r.family_name,nickname:r.nickname,picture:r.picture,locale:r.locale,name:r.name,email:r.email,email_verified:r.email_verified,act:u?{sub:u.user_id}:void 0,org_id:a==null?void 0:a.id,org_name:a==null?void 0:a.name}:void 0;(U=t.env.hooks)!=null&&U.onExecuteCredentialsExchange&&await t.env.hooks.onExecuteCredentialsExchange({ctx:t,client:i,user:r,request:{ip:t.var.ip||"",user_agent:t.var.useragent||"",method:t.req.method,url:t.req.url},scope:n.scope||"",grant_type:""},{accessToken:{setCustomClaim:(O,M)=>{if(Y0.includes(O))throw new Error(`Cannot overwrite reserved claim '${O}'`);$[O]=M}},idToken:{setCustomClaim:(O,M)=>{if(Y0.includes(O))throw new Error(`Cannot overwrite reserved claim '${O}'`);E&&(E[O]=M)}},access:{deny:O=>{throw new S(400,{message:`Access denied: ${O}`})}},token:{createServiceToken:async O=>{const{createServiceToken:M}=await Promise.resolve().then(()=>c4);return(await M(t,t.var.tenant_id,O.scope,O.expiresInSeconds)).access_token}}});const N={includeIssuedTimestamp:!0,expiresIn:u?new Ya(1,"h"):new Ya(1,"d"),headers:{kid:g.kid}},z=await V0("RS256",m,$,N),x=E?await V0("RS256",m,E,N):void 0;return{access_token:z,refresh_token:e.refresh_token,id_token:x,token_type:"Bearer",expires_in:u?3600:86400}}async function $2(t,e){return{code:(await t.env.data.codes.create(e.client.tenant.id,{code_id:Xe(),user_id:e.user.user_id,code_type:"authorization_code",login_id:e.login_id,expires_at:new Date(Date.now()+Ob*1e3).toISOString(),code_challenge:e.authParams.code_challenge,code_challenge_method:e.authParams.code_challenge_method,redirect_uri:e.authParams.redirect_uri,state:e.authParams.state,nonce:e.authParams.nonce})).code_id,state:e.authParams.state}}async function x2(t,e){const{client:n,scope:r,audience:i=n.tenant.audience,session_id:o}=e;return await t.env.data.refreshTokens.create(n.tenant.id,{id:Xe(),session_id:o,client_id:n.client_id,idle_expires_at:new Date(Date.now()+Qc*1e3).toISOString(),user_id:e.user.user_id,device:{last_ip:t.var.ip,initial_ip:t.var.ip,last_user_agent:t.var.useragent||"",initial_user_agent:t.var.useragent||"",initial_asn:"",last_asn:""},resource_servers:[{audience:i,scopes:r}],rotating:!1})}async function A2(t,{user:e,client:n,loginSession:r}){const i=await t.env.data.sessions.create(n.tenant.id,{id:Xe(),user_id:e.user_id,login_session_id:r.id,idle_expires_at:new Date(Date.now()+Qc*1e3).toISOString(),device:{last_ip:t.var.ip||"",initial_ip:t.var.ip||"",last_user_agent:t.var.useragent||"",initial_user_agent:t.var.useragent||"",initial_asn:"",last_asn:""},clients:[n.client_id]});return await t.env.data.loginSessions.update(n.tenant.id,r.id,{session_id:i.id}),i}async function Mn(t,e){var v,$;const{authParams:n,client:r,ticketAuth:i}=e;let{user:o}=e;const a=n.response_type||an.CODE,l=n.response_mode||Bn.QUERY;if(i){if(!e.loginSession)throw new S(500,{message:"Login session not found for ticket auth."});const E=Cb(),N=Xe(12),z=await t.env.data.codes.create(r.tenant.id,{code_id:Xe(),code_type:"ticket",login_id:e.loginSession.id,expires_at:new Date(Date.now()+Db).toISOString(),code_verifier:[N,E].join("|"),redirect_uri:n.redirect_uri,state:n.state,nonce:n.nonce});return t.json({login_ticket:z.code_id,co_verifier:E,co_id:N})}let u=e.refreshToken,d=e.sessionId;if(!d&&((v=e.loginSession)!=null&&v.session_id)){d=e.loginSession.session_id;const E=await t.env.data.sessions.get(r.tenant.id,d);E&&!E.clients.includes(r.client_id)&&await t.env.data.sessions.update(r.tenant.id,d,{clients:[...E.clients,r.client_id]})}else if(!d){if(!e.loginSession)throw new S(500,{message:"Login session not found for creating a new session."});d=(await A2(t,{user:o,client:r,loginSession:e.loginSession})).id}if(!u&&(($=n.scope)!=null&&$.split(" ").includes("offline_access"))&&![an.TOKEN,an.CODE].includes(a)&&!e.impersonatingUser&&(u=(await x2(t,{user:o,client:r,session_id:d,scope:n.scope,audience:n.audience})).id),l===Bn.SAML_POST){if(!d)throw new S(500,{message:"Session ID not available for SAML response"});return i4(t,e.client,e.authParams,o,d)}const p=await a4(t,{authParams:n,user:o,client:r,session_id:d,refresh_token:u,strategy:e.strategy,loginSession:e.loginSession,responseType:a,skipHooks:e.skipHooks,organization:e.organization,impersonatingUser:e.impersonatingUser});if(p instanceof Response)return p;if(l===Bn.WEB_MESSAGE){if(!n.redirect_uri)throw new S(400,{message:"Redirect URI not allowed for WEB_MESSAGE response mode."});const E=new Headers;if(d){const x=Za(r.tenant.id,d,t.var.host||"");x&&E.set("set-cookie",x)}else console.warn("Session ID not available for WEB_MESSAGE, cookie will not be set.");const N=new URL(n.redirect_uri),z=`${N.protocol}//${N.host}`;return t.html(td(z,JSON.stringify({...p,state:n.state})),{headers:E})}if(!n.redirect_uri)throw new S(400,{message:"Redirect uri not found for this response mode."});const g=new Headers;if(d){const E=Za(r.tenant.id,d,t.var.custom_domain||t.req.header("host")||"");E&&g.set("set-cookie",E)}const m=new URL(n.redirect_uri);if("code"in p)m.searchParams.set("code",p.code),p.state&&m.searchParams.set("state",p.state);else if("access_token"in p)m.hash=new URLSearchParams({access_token:p.access_token,...p.id_token&&{id_token:p.id_token},token_type:p.token_type,expires_in:p.expires_in.toString(),...n.state&&{state:n.state},...n.scope&&{scope:n.scope}}).toString();else throw new S(500,{message:"Invalid token response for implicit flow."});return g.set("location",m.toString()),new Response("Redirecting",{status:302,headers:g})}async function a4(t,e){var l,u,d,p,g,m;let{user:n}=e;const r=e.responseType||an.TOKEN;if(n&&e.organization&&!(await t.env.data.userOrganizations.list(e.client.tenant.id,{q:`user_id:${n.user_id}`,per_page:1e3})).userOrganizations.some(E=>E.organization_id===e.organization.id))throw new Zi(403,{error:"access_denied",error_description:"User is not a member of the specified organization"});let i=e.authParams.scope||"",o=[];if(e.authParams.audience)try{let v;if(e.grantType===mn.ClientCredential||!n&&!e.user)v=await Qa(t,{grantType:mn.ClientCredential,tenantId:e.client.tenant.id,clientId:e.client.client_id,audience:e.authParams.audience,requestedScopes:((l=e.authParams.scope)==null?void 0:l.split(" "))||[],organizationId:(u=e.organization)==null?void 0:u.id});else{const $=(n==null?void 0:n.user_id)||((d=e.user)==null?void 0:d.user_id);if(!$)throw new Zi(400,{error:"invalid_request",error_description:"User ID is required for user-based grants"});v=await Qa(t,{grantType:e.grantType,tenantId:e.client.tenant.id,userId:$,clientId:e.client.client_id,audience:e.authParams.audience,requestedScopes:((p=e.authParams.scope)==null?void 0:p.split(" "))||[],organizationId:(g=e.organization)==null?void 0:g.id})}i=v.scopes.join(" "),o=v.permissions}catch(v){if(v instanceof S)throw v}const a={...e.authParams,scope:i};if(e.loginSession&&n&&!e.skipHooks){e.strategy&&((m=n.app_metadata)==null?void 0:m.strategy)!==e.strategy&&(n.app_metadata={...n.app_metadata,strategy:e.strategy},await t.env.data.users.update(e.client.tenant.id,n.user_id,{app_metadata:{...n.app_metadata||{},strategy:e.strategy}}));const v=await E2(t,t.env.data,e.client.tenant.id,n,e.loginSession,{client:e.client,authParams:a,authStrategy:e.strategy?{strategy:e.strategy,strategy_type:"social"}:void 0});if(v instanceof Response)return v;n=v}if(r===an.CODE){if(!n||!e.loginSession)throw new S(500,{message:"User and loginSession is required for code flow"});return await $2(t,{user:n,client:e.client,authParams:a,login_id:e.loginSession.id})}else return tl(t,{...e,user:n,authParams:a,permissions:o})}const Z0="auth-service";async function Zp(t,e,n,r){const i=await t.env.data.tenants.get(e);if(!i)throw new Error(`Tenant not found: ${e}`);const o={client_id:Z0,tenant:i,created_at:new Date().toISOString(),updated_at:new Date().toISOString(),name:"Auth Service",global:!1,is_first_party:!0,oidc_conformant:!1,sso:!1,sso_disabled:!1,cross_origin_authentication:!1,custom_login_page_on:!1,require_pushed_authorization_requests:!1,require_proof_of_possession:!1,client_metadata:{disable_sign_ups:"false",email_validation:"disabled"},disable_sign_ups:!1,email_validation:"disabled",connections:[]},a=await tl(t,{client:o,authParams:{client_id:Z0,response_type:an.TOKEN,scope:n}});return{access_token:a.access_token,token_type:a.token_type,expires_in:r||3600}}const c4=Object.freeze(Object.defineProperty({__proto__:null,createServiceToken:Zp},Symbol.toStringTag,{value:"Module"}));async function k2(t,e,n){const r=await Zp(t,n.tenant_id,"webhook");for await(const i of e.filter(o=>"url"in o))if(!(await fetch(i.url,{method:"POST",headers:{Authorization:`Bearer ${r.access_token}`,"Content-Type":"application/json"},body:JSON.stringify(n)})).ok){const a=We(t,{type:qe.FAILED_HOOK,description:`Failed to invoke hook ${i.hook_id}`});await t.env.data.logs.create(n.tenant_id,a)}}function l4(t){return async(e,n)=>{const{hooks:r}=await t.env.data.hooks.list(e);return await k2(t,r,{tenant_id:e,user:n,trigger_id:"post-user-registration"}),n}}function u4(t){return async(e,n)=>{const{hooks:r}=await t.env.data.hooks.list(e,{q:"trigger_id:pre-user-signup",page:0,per_page:100,include_totals:!1});await k2(t,r,{tenant_id:e,email:n,trigger_id:"pre-user-signup"})}}function Q0(t){return typeof t.form_id=="string"}async function d4(t,e,n){var u;const r=t.env.data,i=t.var.tenant_id||t.req.header("tenant-id");if(!i)throw new S(400,{message:"Missing tenant_id in context"});const o=await r.forms.get(i,e);if(!o)throw new S(404,{message:"Form not found for post-user-login hook"});let a=(u=o.start)==null?void 0:u.next_node;if(!a&&o.nodes&&o.nodes.length>0){const d=o.nodes.find(p=>p.type==="STEP");a=d==null?void 0:d.id}if(!a)throw new S(400,{message:"No start node found in form"});let l=`/u/forms/${o.id}/nodes/${a}?state=${encodeURIComponent(n.id)}`;return new Response(null,{status:302,headers:{location:l}})}function eh(t){return typeof t.page_id=="string"&&typeof t.enabled=="boolean"}async function p4(t,e,n,r,i){const o=t.env.data,a=t.var.tenant_id||t.req.header("tenant-id");if(!a)throw new S(400,{message:"Missing tenant_id in context"});if(i&&!(await o.userPermissions.list(a,r.user_id)).some(p=>p.permission_name===i))return r;let l=`/u/${e}?state=${encodeURIComponent(n.id)}`;return new Response(null,{status:302,headers:{location:l}})}function Qi(t,e){return{createServiceToken:async n=>(await Zp(t,e,n.scope,n.expiresInSeconds)).access_token}}function th(t){return typeof t.url=="string"}function f4(t,e){return async(n,r)=>{var a,l,u;const i={method:t.req.method,ip:t.req.query("x-real-ip")||"",user_agent:t.req.query("user-agent"),url:((a=t.var.loginSession)==null?void 0:a.authorization_url)||t.req.url};if((l=t.env.hooks)!=null&&l.onExecutePreUserRegistration)try{await t.env.hooks.onExecutePreUserRegistration({ctx:t,user:r,request:i},{user:{setUserMetadata:async(d,p)=>{r[d]=p}},token:Qi(t,n)})}catch{const p=We(t,{type:qe.FAILED_SIGNUP,description:"Pre user registration hook failed"});await e.logs.create(n,p)}let o=await xb(e)(n,r);if((u=t.env.hooks)!=null&&u.onExecutePostUserRegistration)try{await t.env.hooks.onExecutePostUserRegistration({ctx:t,user:r,request:i},{user:{},token:Qi(t,n)})}catch{const p=We(t,{type:qe.FAILED_SIGNUP,description:"Post user registration hook failed"});await t.env.data.logs.create(n,p)}return await l4(t)(n,o),o}}function h4(t,e){return async(n,r,i)=>{var l;if(Object.keys(i).length===1&&"linked_to"in i)return e.users.update(n,r,i);const o=await e.users.get(n,r);if(!o)throw new S(404,{message:"User not found"});const a={method:t.req.method,ip:t.var.ip||t.get("ip")||"",user_agent:t.var.useragent||t.get("useragent")||"",url:t.req.url};if((l=t.env.hooks)!=null&&l.onExecutePreUserUpdate)try{await t.env.hooks.onExecutePreUserUpdate({ctx:t,tenant:{id:n},user_id:r,user:o,updates:i,request:a},{user:{setUserMetadata:async(u,d)=>{i[u]=d}},cancel:()=>{throw new S(400,{message:"User update cancelled by pre-update hook"})},token:Qi(t,n)})}catch{throw new S(400,{message:"Pre user update hook failed"})}if(await e.users.update(n,r,i),i.email||i.email_verified){const u=await e.users.get(n,r);if(u&&u.email&&u.email_verified){const{users:d}=await e.users.list(n,{page:0,per_page:10,include_totals:!1,q:`email:${u.email}`}),p=d.filter(g=>g.email_verified&&g.user_id!==r&&!g.linked_to);p.length>0&&await e.users.update(n,r,{linked_to:p[0].user_id})}}if(i.email){const u=We(t,{type:qe.SUCCESS_CHANGE_EMAIL,description:`Email updated to ${i.email}`,userId:r});await e.logs.create(n,u)}return!0}}async function g4(t,e,n,r){var i,o;if(((i=e.client_metadata)==null?void 0:i.disable_sign_ups)==="true"){const a=(o=t.var.loginSession)==null?void 0:o.authorization_url;if(!(a&&new URL(a).searchParams.get("screen_hint")==="signup")&&!await ef({userAdapter:n.users,tenant_id:e.tenant.id,email:r})){const d=We(t,{type:qe.FAILED_SIGNUP,description:"Public signup is disabled"});throw await n.logs.create(e.tenant.id,d),new S(400,{message:"Signups are disabled for this client"})}}await u4(t)(t.var.tenant_id||"",r)}function m4(t,e){return async(n,r)=>{var l,u;const i=await e.users.get(n,r);if(!i)return!1;const o={method:t.req.method,ip:t.var.ip||t.get("ip")||"",user_agent:t.var.useragent||t.get("useragent")||"",url:t.req.url};if((l=t.env.hooks)!=null&&l.onExecutePreUserDeletion)try{await t.env.hooks.onExecutePreUserDeletion({ctx:t,user:i,user_id:r,request:o,tenant:{id:n}},{cancel:()=>{throw new S(400,{message:"User deletion cancelled by pre-deletion hook"})},token:Qi(t,n)})}catch(d){if(d instanceof S)throw d;const p=We(t,{type:qe.FAILED_HOOK,description:`Pre user deletion hook failed: ${d instanceof Error?d.message:String(d)}`});throw await e.logs.create(n,p),new S(400,{message:"Pre user deletion hook failed"})}const a=await e.users.remove(n,r);if(a){const d=We(t,{type:qe.SUCCESS_USER_DELETION,description:`user_id: ${r}`,strategy:i.provider||"auth0",strategy_type:i.is_social?"social":"database"});d.connection=i.connection||"",d.connection_id="",d.details={...d.details,body:{tenant:n,connection:i.connection||""}},await e.logs.create(n,d)}if(a&&((u=t.env.hooks)!=null&&u.onExecutePostUserDeletion))try{await t.env.hooks.onExecutePostUserDeletion({ctx:t,user:i,user_id:r,request:o,tenant:{id:n}},{token:Qi(t,n)})}catch(d){const p=We(t,{type:qe.FAILED_HOOK,description:`Post user deletion hook failed: ${d instanceof Error?d.message:String(d)}`});await e.logs.create(n,p)}return a}}function ks(t,e){const n=e;return{...e,users:{...e.users,create:f4(t,n),update:h4(t,n),remove:m4(t,n)}}}async function _4(t,e,n,r,i,o){var p,g,m,v,$,E,N,z,x,q,U,O,M,V;let a=[];try{a=(await e.userRoles.list(n,r.user_id,void 0,"")).map(ce=>ce.name||ce.id)}catch(H){console.error("Error fetching user roles:",H)}let l={};if(r.connection)try{const K=(await e.connections.list(n,{page:0,per_page:100,include_totals:!1})).connections.find(ce=>ce.name===r.connection);K&&(l={id:K.id,name:K.name,strategy:K.strategy||r.provider,metadata:K.options||{}})}catch(H){console.error("Error fetching connection info:",H)}let u;try{if((p=i.authParams)!=null&&p.organization){const H=await e.organizations.get(n,i.authParams.organization);H&&(u={id:H.id,name:H.name,display_name:H.display_name||H.name,metadata:H.metadata||{}})}}catch(H){console.error("Error fetching organization info:",H)}const d=t.get("countryCode");return{ctx:t,client:o.client,user:r,request:{asn:void 0,ip:t.get("ip")||"",user_agent:t.get("useragent"),method:t.req.method,url:t.req.url,geoip:{cityName:void 0,continentCode:void 0,countryCode:d||void 0,countryName:void 0,latitude:void 0,longitude:void 0,timeZone:void 0}},transaction:{id:i.id,locale:((g=i.authParams)==null?void 0:g.ui_locales)||"en",login_hint:void 0,prompt:(m=i.authParams)==null?void 0:m.prompt,redirect_uri:(v=i.authParams)==null?void 0:v.redirect_uri,requested_scopes:((E=($=i.authParams)==null?void 0:$.scope)==null?void 0:E.split(" "))||[],response_mode:(N=i.authParams)==null?void 0:N.response_mode,response_type:(z=i.authParams)==null?void 0:z.response_type,state:(x=i.authParams)==null?void 0:x.state,ui_locales:(q=i.authParams)==null?void 0:q.ui_locales},scope:((U=o.authParams)==null?void 0:U.scope)||"",grant_type:((O=o.authParams)==null?void 0:O.grant_type)||"",audience:(M=o.authParams)==null?void 0:M.audience,authentication:{methods:[{name:r.is_social?"federated":"pwd",timestamp:new Date().toISOString()}]},authorization:{roles:a},connection:Object.keys(l).length>0?l:{id:r.connection||"Username-Password-Authentication",name:r.connection||"Username-Password-Authentication",strategy:r.provider||"auth0"},organization:u,resource_server:(V=o.authParams)!=null&&V.audience?{identifier:o.authParams.audience}:void 0,stats:{logins_count:r.login_count||0},tenant:{id:n},session:{id:i.id,created_at:i.created_at,authenticated_at:new Date().toISOString(),clients:[{client_id:o.client.client_id}],device:{initial_ip:t.get("ip"),initial_user_agent:t.get("useragent"),last_ip:r.last_ip||t.get("ip"),last_user_agent:t.get("useragent")}}}}async function E2(t,e,n,r,i,o){var g,m,v,$,E;const a=(g=o==null?void 0:o.authStrategy)!=null&&g.strategy_type?o.authStrategy.strategy_type:r.is_social?"social":"database",l=((m=o==null?void 0:o.authStrategy)==null?void 0:m.strategy)||r.connection||"",u=We(t,{type:qe.SUCCESS_LOGIN,description:`Successful login for ${r.user_id}`,userId:r.user_id,strategy_type:a,strategy:l,connection:l,audience:(v=o==null?void 0:o.authParams)==null?void 0:v.audience,scope:($=o==null?void 0:o.authParams)==null?void 0:$.scope});if(await e.logs.create(n,u),await e.users.update(n,r.user_id,{last_login:new Date().toISOString(),last_ip:t.var.ip||"",login_count:r.login_count+1}),(E=t.env.hooks)!=null&&E.onExecutePostLogin&&(o!=null&&o.client)&&(o!=null&&o.authParams)&&i){let N=null;const z=await _4(t,e,n,r,i,{client:o.client,authParams:o.authParams});if(await t.env.hooks.onExecutePostLogin(z,{prompt:{render:x=>{}},redirect:{sendUserTo:(x,q)=>{const U=new URL(x,t.req.url);U.searchParams.set("state",i.id),q!=null&&q.query&&Object.entries(q.query).forEach(([O,M])=>{U.searchParams.set(O,M)}),N=U.toString()},encodeToken:x=>JSON.stringify({payload:x.payload,exp:Date.now()+(x.expiresInSeconds||900)*1e3}),validateToken:x=>null},token:Qi(t,n)}),N)return new Response(null,{status:302,headers:{location:N}})}const{hooks:d}=await e.hooks.list(n,{q:"trigger_id:post-user-login",page:0,per_page:100,include_totals:!1});if(i){const N=d.find(x=>x.enabled&&Q0(x));if(N&&Q0(N))return d4(t,N.form_id,i);const z=d.find(x=>x.enabled&&eh(x));if(z&&eh(z))return p4(t,z.page_id,i,r,z.permission_required)}const p=d.filter(N=>N.enabled&&th(N));for(const N of p)if(th(N))try{await fetch(N.url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tenant_id:n,user:r,trigger_id:"post-user-login"})})}catch{const x=We(t,{type:qe.FAILED_HOOK,description:`Failed to invoke post-user-login webhook: ${N.url}`});await e.logs.create(n,x)}return r}function y4(t){return ks(t,t.env.data)}async function Qp(t,e,n){return(await t.list(e,{page:0,per_page:10,include_totals:!1,q:`email:${n}`})).users}async function vo({userAdapter:t,tenant_id:e,username:n,provider:r}){const i=r==="sms"?`phone_number:${n}`:`email:${n}`,{users:o}=await t.list(e,{page:0,per_page:10,include_totals:!1,q:`${i} provider:${r}`});return o.length>1&&console.error("More than one user found for same email and provider"),o[0]||null}async function ef({userAdapter:t,tenant_id:e,email:n}){var l;const{users:r}=await t.list(e,{page:0,per_page:10,include_totals:!1,q:`email:${n}`}),i=r.filter(u=>!(u.provider==="auth2"&&!u.email_verified));if(i.length===0)return;const o=i.filter(u=>!u.linked_to);if(o.length>0)return o.length>1&&console.error("More than one primary user found for same email"),o[0];const a=await t.get(e,(l=i[0])==null?void 0:l.linked_to);if(!a)throw new Error("Primary account not found");return a}async function rs({userAdapter:t,tenant_id:e,username:n,provider:r}){const i=await vo({userAdapter:t,tenant_id:e,username:n,provider:r});return i?i.linked_to?t.get(e,i.linked_to):i:null}async function nl(t,e){const{username:n,provider:r,connection:i,client:o,userId:a,isSocial:l,profileData:u={},ip:d=""}=e;let p=await rs({userAdapter:t.env.data.users,tenant_id:e.client.tenant.id,username:n,provider:r});if(!p){const g={user_id:`${r}|${a||Yc()}`,email:i!=="sms"?n:void 0,phone_number:i==="sms"?n:void 0,name:n,provider:r,connection:i,email_verified:!0,last_ip:d,is_social:l,last_login:new Date().toISOString(),profileData:JSON.stringify(u)};p=await y4(t).users.create(o.tenant.id,g),t.set("user_id",p.user_id)}return p}const ht=s.z.object({page:s.z.string().min(0).optional().default("0").transform(t=>parseInt(t,10)).openapi({description:"The page number where 0 is the first page"}),per_page:s.z.string().min(1).optional().default("10").transform(t=>parseInt(t,10)).openapi({description:"The number of items per page"}),include_totals:s.z.string().optional().default("false").transform(t=>t==="true").openapi({description:"If the total number of items should be included in the response"}),sort:s.z.string().regex(/^.+:(-1|1)$/).optional().openapi({description:"A property that should have the format 'string:-1' or 'string:1'"}),q:s.z.string().optional().openapi({description:"A lucene query string used to filter the results"})});function It(t){if(!t)return;const[e,n]=t.split(":"),r=n==="1"?"asc":"desc";if(!(!e||!r))return{sort_by:e,sort_order:r}}var w4={deno:"Deno",bun:"Bun",workerd:"Cloudflare-Workers",node:"Node.js"},S2=()=>{var n,r;const t=globalThis;if(typeof navigator<"u"&&typeof navigator.userAgent=="string"){for(const[i,o]of Object.entries(w4))if(v4(o))return i}return typeof(t==null?void 0:t.EdgeRuntime)=="string"?"edge-light":(t==null?void 0:t.fastly)!==void 0?"fastly":((r=(n=t==null?void 0:t.process)==null?void 0:n.release)==null?void 0:r.name)==="node"?"node":"other"},v4=t=>navigator.userAgent.startsWith(t);function wn(t,e){S2()==="workerd"&&t.executionCtx.waitUntil(e)}const nh=Mt.extend({users:s.z.array(Dn)}),b4=Mt.extend({sessions:s.z.array(Xc)}),$4=Mt.extend({organizations:s.z.array(Er)}),x4=new s.OpenAPIHono().openapi(s.createRoute({tags:["users"],method:"get",path:"/",request:{query:ht,headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:s.z.union([s.z.array(Dn),nh])}},description:"List of users"}}}),async t=>{const{page:e,per_page:n,include_totals:r,sort:i,q:o}=t.req.valid("query");if(o!=null&&o.includes("identities.profileData.email")){const d=o.split("=")[1],g=(await t.env.data.users.list(t.var.tenant_id,{page:e,per_page:n,include_totals:r,q:`email:${d}`})).users.filter($=>$.linked_to),[m]=g;if(!m)return t.json([]);const v=await t.env.data.users.get(t.var.tenant_id,m.linked_to);if(!v)throw new S(500,{message:"Primary account not found"});return t.json([Dn.parse(v)])}const a=["-_exists_:linked_to"];o&&a.push(o);const l=await t.env.data.users.list(t.var.tenant_id,{page:e,per_page:n,include_totals:r,sort:It(i),q:a.join(" ")}),u=l.users.filter(d=>!d.linked_to);return r?t.json(nh.parse({users:u,length:l.length,start:l.start,limit:l.limit})):t.json(s.z.array(Dn).parse(u))}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:Dn}},description:"List of users"}}}),async t=>{const{user_id:e}=t.req.valid("param"),n=await t.env.data.users.get(t.var.tenant_id,e);if(!n)throw new S(404);if(n.linked_to)throw new S(404,{message:"User is linked to another user"});return t.json(n)}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Status"}}}),async t=>{const{user_id:e}=t.req.valid("param");if(!await t.env.data.users.remove(t.var.tenant_id,e))throw new S(404);const r=We(t,{type:qe.SUCCESS_API_OPERATION,description:"Delete a User"});return r.details={...r.details,response:{statusCode:204,body:{}}},wn(t,t.env.data.logs.create(t.var.tenant_id,r)),t.text("OK")}).openapi(s.createRoute({tags:["users"],method:"post",path:"/",request:{headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({...Fa.shape})}}}},security:[{Bearer:["auth:write"]}],responses:{201:{content:{"application/json":{schema:Dn}},description:"Status"}}}),async t=>{const e=t.req.valid("json");t.set("body",e);const{email:n,phone_number:r,name:i,linked_to:o,email_verified:a,provider:l,connection:u}=e,d=`${e.provider}|${e.user_id||Yc()}`;try{const p=await t.env.data.users.create(t.var.tenant_id,{email:n,user_id:d,name:i||n||r,phone_number:r,provider:l,connection:u,linked_to:o??void 0,email_verified:a||!1,last_ip:"",is_social:!1,last_login:new Date().toISOString()});t.set("user_id",p.user_id);const g=We(t,{type:qe.SUCCESS_API_OPERATION,description:"User created"});wn(t,t.env.data.logs.create(t.var.tenant_id,g));const m={...p,identities:[{connection:p.connection,provider:p.provider,user_id:q0(p.user_id),isSocial:p.is_social}]};return t.json(Dn.parse(m),{status:201})}catch(p){throw p.message==="User already exists"?new S(409,{message:"User already exists"}):p}}).openapi(s.createRoute({tags:["users"],method:"patch",path:"/{user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({...Fa.shape,verify_email:s.z.boolean(),password:s.z.string()}).partial()}}},params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Status"}}}),async t=>{var p;const{data:e}=t.env,n=t.req.valid("json"),{user_id:r}=t.req.valid("param"),{verify_email:i,password:o,...a}=n,l=await e.users.get(t.var.tenant_id,r);if(!l)throw new S(404);if(a.email&&a.email!==l.email){const g=await Qp(t.env.data.users,t.var.tenant_id,a.email);if(g.length&&g.some(m=>m.user_id!==r))throw new S(409,{message:"Another user with the same email address already exists."})}if(l.linked_to)throw new S(404,{message:"User is linked to another user"});if(await t.env.data.users.update(t.var.tenant_id,r,a),o){const g=(p=l.identities)==null?void 0:p.find($=>$.connection==="Username-Password-Authentication");if(!g)throw new S(400,{message:"User does not have a password identity"});const m={user_id:g.user_id,password:await As.hash(o,10),algorithm:"bcrypt"};await e.passwords.get(t.var.tenant_id,g.user_id)?await e.passwords.update(t.var.tenant_id,m):await e.passwords.create(t.var.tenant_id,m)}const u=await t.env.data.users.get(t.var.tenant_id,r);if(!u)throw new S(500);const d=We(t,{type:qe.SUCCESS_API_OPERATION,description:"Update a User",body:n});return d.details={...d.details,response:{statusCode:200,body:u}},wn(t,t.env.data.logs.create(t.var.tenant_id,d)),t.json(u)}).openapi(s.createRoute({tags:["users"],method:"post",path:"/{user_id}/identities",request:{headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.union([s.z.object({link_with:s.z.string()}),s.z.object({user_id:s.z.string(),provider:s.z.string(),connection:s.z.string().optional()})])}}},params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{201:{content:{"application/json":{schema:s.z.array(s.z.object({connection:s.z.string(),provider:s.z.string(),user_id:s.z.string(),isSocial:s.z.boolean()}))}},description:"Status"}}}),async t=>{const e=t.req.valid("json"),{user_id:n}=t.req.valid("param"),r="link_with"in e?e.link_with:e.user_id,i=await t.env.data.users.get(t.var.tenant_id,n);if(!i)throw new S(400,{message:"Linking an inexistent identity is not allowed."});await t.env.data.users.update(t.var.tenant_id,r,{linked_to:n});const o=await t.env.data.users.list(t.var.tenant_id,{page:0,per_page:10,include_totals:!1,q:`linked_to:${n}`}),a=[i,...o.users].map(l=>({connection:l.connection,provider:l.provider,user_id:q0(l.user_id),isSocial:l.is_social}));return t.json(a,{status:201})}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/identities/{provider}/{linked_user_id}",request:{headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string(),provider:s.z.string(),linked_user_id:s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{content:{"application/json":{schema:s.z.array(Dn)}},description:"Status"}}}),async t=>{const{user_id:e,provider:n,linked_user_id:r}=t.req.valid("param");await t.env.data.users.unlink(t.var.tenant_id,e,n,r);const i=await t.env.data.users.get(t.var.tenant_id,e);if(!i)throw new S(404);return t.json([Dn.parse(i)])}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/sessions",request:{query:ht,headers:s.z.object({"tenant-id":s.z.string()}),params:s.z.object({user_id:s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:s.z.union([s.z.array(Xc),b4])}},description:"List of sessions"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{include_totals:n,page:r,per_page:i}=t.req.valid("query"),o=await t.env.data.sessions.list(t.var.tenant_id,{page:r,per_page:i,include_totals:n,q:`user_id:${e}`});return n?t.json(o):t.json(o.sessions)}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/permissions",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),query:ht},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:Z_}},description:"User permissions"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{page:n,per_page:r,sort:i,q:o}=t.req.valid("query");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const l=await t.env.data.userPermissions.list(t.var.tenant_id,e,{page:n,per_page:r,include_totals:!1,sort:It(i),q:o});return t.json(l)}).openapi(s.createRoute({tags:["users"],method:"post",path:"/{user_id}/permissions",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({permissions:s.z.array(s.z.object({permission_name:s.z.string(),resource_server_identifier:s.z.string()}))})}}}},security:[{Bearer:["auth:write"]}],responses:{201:{description:"Permissions assigned to user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{permissions:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userPermissions.create(t.var.tenant_id,e,{user_id:e,resource_server_identifier:i.resource_server_identifier,permission_name:i.permission_name}))throw new S(500,{message:"Failed to assign permissions to user"});return t.json({message:"Permissions assigned successfully"},{status:201})}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/permissions",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({permissions:s.z.array(s.z.object({permission_name:s.z.string(),resource_server_identifier:s.z.string()}))})}}}},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Permissions removed from user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{permissions:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userPermissions.remove(t.var.tenant_id,e,i))throw new S(500,{message:"Failed to remove permissions from user"});return t.json({message:"Permissions removed successfully"})}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/roles",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:Xa}},description:"User roles"}}}),async t=>{const{user_id:e}=t.req.valid("param");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const r=await t.env.data.userRoles.list(t.var.tenant_id,e,void 0,"");return t.json(r)}).openapi(s.createRoute({tags:["users"],method:"post",path:"/{user_id}/roles",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({roles:s.z.array(s.z.string())})}}}},security:[{Bearer:["auth:write"]}],responses:{201:{description:"Roles assigned to user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{roles:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userRoles.create(t.var.tenant_id,e,i,""))throw new S(500,{message:"Failed to assign roles to user"});return t.json({message:"Roles assigned successfully"},{status:201})}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/roles",request:{params:s.z.object({user_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()}),body:{content:{"application/json":{schema:s.z.object({roles:s.z.array(s.z.string())})}}}},security:[{Bearer:["auth:write"]}],responses:{200:{description:"Roles removed from user"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{roles:n}=t.req.valid("json");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});for(const i of n)if(!await t.env.data.userRoles.remove(t.var.tenant_id,e,i,""))throw new S(500,{message:"Failed to remove roles from user"});return t.json({message:"Roles removed successfully"})}).openapi(s.createRoute({tags:["users"],method:"get",path:"/{user_id}/organizations",request:{params:s.z.object({user_id:s.z.string()}),query:ht,headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:read"]}],responses:{200:{content:{"application/json":{schema:s.z.union([$4,s.z.array(Er)])}},description:"List of user organizations"}}}),async t=>{const{user_id:e}=t.req.valid("param"),{page:n,per_page:r,include_totals:i,sort:o}=t.req.valid("query");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const l=await t.env.data.userOrganizations.listUserOrganizations(t.var.tenant_id,e,{page:n,per_page:r,sort:It(o)});return i?t.json({organizations:l.organizations,start:l.start,limit:l.limit,length:l.length}):t.json(l.organizations)}).openapi(s.createRoute({tags:["users"],method:"delete",path:"/{user_id}/organizations/{organization_id}",request:{params:s.z.object({user_id:s.z.string(),organization_id:s.z.string()}),headers:s.z.object({"tenant-id":s.z.string()})},security:[{Bearer:["auth:write"]}],responses:{200:{description:"User removed from organization successfully"}}}),async t=>{const{user_id:e,organization_id:n}=t.req.valid("param");if(!await t.env.data.users.get(t.var.tenant_id,e))throw new S(404,{message:"User not found"});const o=(await t.env.data.userOrganizations.list(t.var.tenant_id,{q:`user_id:${e}`,per_page:100})).userOrganizations.find(a=>a.organization_id===n);if(!o)throw new S(404,{message:"User is not a member of this organization"});return await t.env.data.userOrganizations.remove(t.var.tenant_id,o.id),t.json({message:"User removed from organization successfully"})});/*! *****************************************************************************
73
73
  Copyright (C) Microsoft. All rights reserved.
74
74
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
75
75
  this file except in compliance with the License. You may obtain a copy of the
package/dist/authhero.mjs CHANGED
@@ -6732,10 +6732,8 @@ async function jc(t, e) {
6732
6732
  email: r.email,
6733
6733
  email_verified: r.email_verified,
6734
6734
  act: u ? { sub: u.user_id } : void 0,
6735
- organization: a ? {
6736
- org_id: a.id,
6737
- org_name: a.name
6738
- } : void 0
6735
+ org_id: a == null ? void 0 : a.id,
6736
+ org_name: a == null ? void 0 : a.name
6739
6737
  } : void 0;
6740
6738
  (M = t.env.hooks) != null && M.onExecuteCredentialsExchange && await t.env.hooks.onExecuteCredentialsExchange(
6741
6739
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "authhero",
3
- "version": "0.244.0",
3
+ "version": "0.245.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],