@authhero/multi-tenancy 13.5.0 → 13.6.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.
@@ -1 +1 @@
1
- "use strict";var W=Object.defineProperty;var G=(t,e,s)=>e in t?W(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var M=(t,e,s)=>G(t,typeof e!="symbol"?e+"":e,s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("hono"),C=require("authhero"),Q=require("zod"),$=require("@authhero/adapter-interfaces");function q(t){const{mainTenantId:e,requireOrganizationMatch:s=!0}=t;return{async onTenantAccessValidation(n,a){if(a===e)return!0;if(s){const c=n.var.organization_id;return c?c===a:!1}return!0}}}function D(t,e,s){return e===s?!0:t?t===e:!1}function z(t){return{async resolveDataAdapters(e){try{return await t.getAdapters(e)}catch(s){console.error(`Failed to resolve data adapters for tenant ${e}:`,s);return}}}}function F(t){return{async afterCreate(e,s){const{accessControl:n,databaseIsolation:a,settingsInheritance:c}=t;n&&e.ctx&&await L(e,s,n),a!=null&&a.onProvision&&await a.onProvision(s.id),(c==null?void 0:c.inheritFromMain)!==!1&&e.ctx&&await B(e,s,t)},async beforeDelete(e,s){const{accessControl:n,databaseIsolation:a}=t;if(n)try{const d=(await e.adapters.organizations.list(n.mainTenantId)).organizations.find(o=>o.name===s);d&&await e.adapters.organizations.remove(n.mainTenantId,d.id)}catch(c){console.warn(`Failed to remove organization for tenant ${s}:`,c)}if(a!=null&&a.onDeprovision)try{await a.onDeprovision(s)}catch(c){console.warn(`Failed to deprovision database for tenant ${s}:`,c)}}}}async function L(t,e,s){const{mainTenantId:n,defaultPermissions:a,defaultRoles:c,issuer:d,adminRoleName:o="Tenant Admin",adminRoleDescription:i="Full access to all tenant management operations",addCreatorToOrganization:r=!0}=s;await t.adapters.organizations.create(n,{id:e.id,name:e.id,display_name:e.friendly_name||e.id});let l=null;if(d&&(l=await Y(t,n,d,o,i)),r&&t.ctx){const f=t.ctx.var.user;if(f!=null&&f.sub)try{await t.adapters.userOrganizations.create(n,{user_id:f.sub,organization_id:e.id}),l&&await t.adapters.userRoles.create(n,f.sub,l,e.id)}catch(u){console.warn(`Failed to add creator ${f.sub} to organization ${e.id}:`,u)}}c&&c.length>0&&console.log(`Would assign roles ${c.join(", ")} to organization ${e.id}`),a&&a.length>0&&console.log(`Would grant permissions ${a.join(", ")} to organization ${e.id}`)}async function Y(t,e,s,n,a){const d=(await t.adapters.roles.list(e,{})).roles.find(l=>l.name===n);if(d)return d.id;const o=await t.adapters.roles.create(e,{name:n,description:a}),i=`${s}api/v2/`,r=C.MANAGEMENT_API_SCOPES.map(l=>({role_id:o.id,resource_server_identifier:i,permission_name:l.value}));return await t.adapters.rolePermissions.assign(e,o.id,r),o.id}async function B(t,e,s){const{accessControl:n,settingsInheritance:a}=s;if(!n)return;const c=await t.adapters.tenants.get(n.mainTenantId);if(!c)return;let d={...c};const o=["id","created_at","updated_at","friendly_name","audience","sender_email","sender_name"];for(const i of o)delete d[i];if(a!=null&&a.inheritedKeys){const i={};for(const r of a.inheritedKeys)r in c&&!o.includes(r)&&(i[r]=c[r]);d=i}if(a!=null&&a.excludedKeys)for(const i of a.excludedKeys)delete d[i];a!=null&&a.transformSettings&&(d=a.transformSettings(d,e.id)),Object.keys(d).length>0&&await t.adapters.tenants.update(e.id,d)}async function P(t,e,s={}){const{cursorField:n="id",sortOrder:a="asc",pageSize:c=100,maxItems:d=1e4,q:o}=s,i=[];let r,l=!0;for(;l;){let f=o||"";if(r){const w=`${n}:${a==="asc"?">":"<"}${r}`;f=f?`(${f}) AND ${w}`:w}const u={per_page:c,page:0,sort:{sort_by:n,sort_order:a},...f&&{q:f}},h=(await t(u))[e]||[];if(h.length===0)l=!1;else{i.push(...h);const _=h[h.length-1];if(_&&typeof _=="object"){const w=_[n];w!=null&&(r=String(w))}h.length<c&&(l=!1),d!==-1&&i.length>=d&&(console.warn(`fetchAll: Reached maxItems limit (${d}). There may be more items.`),l=!1)}}return i}function j(t){const{mainTenantId:e,getChildTenantIds:s,getAdapters:n,shouldSync:a=()=>!0,transformForSync:c}=t;async function d(r,l,f){return(await r.resourceServers.list(l,{q:`identifier:${f}`,per_page:1})).resource_servers[0]??null}async function o(r,l){const f=await s();await Promise.all(f.map(async u=>{try{const m=await n(u),_={...c?c(r,u):{name:r.name,identifier:r.identifier,scopes:r.scopes,signing_alg:r.signing_alg,signing_secret:r.signing_secret,token_lifetime:r.token_lifetime,token_lifetime_for_web:r.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:r.skip_consent_for_verifiable_first_party_clients,allow_offline_access:r.allow_offline_access,verificationKey:r.verificationKey,options:r.options},is_system:!0};if(l==="create"){const w=await d(m,u,r.identifier);w&&w.id?await m.resourceServers.update(u,w.id,_):await m.resourceServers.create(u,_)}else{const w=await d(m,u,r.identifier);w&&w.id&&await m.resourceServers.update(u,w.id,_)}}catch(m){console.error(`Failed to sync resource server "${r.identifier}" to tenant "${u}":`,m)}}))}async function i(r){const l=await s();await Promise.all(l.map(async f=>{try{const u=await n(f),m=await d(u,f,r);m&&m.id&&await u.resourceServers.remove(f,m.id)}catch(u){console.error(`Failed to delete resource server "${r}" from tenant "${f}":`,u)}}))}return{afterCreate:async(r,l)=>{r.tenantId===e&&a(l)&&await o(l,"create")},afterUpdate:async(r,l,f)=>{r.tenantId===e&&a(f)&&await o(f,"update")},afterDelete:async(r,l)=>{r.tenantId===e&&await i(l)}}}function O(t){const{mainTenantId:e,getMainTenantAdapters:s,getAdapters:n,shouldSync:a=()=>!0,transformForSync:c}=t;return{async afterCreate(d,o){if(o.id!==e)try{const i=await s(),r=await n(o.id),l=await P(f=>i.resourceServers.list(e,f),"resource_servers",{cursorField:"id",pageSize:100});await Promise.all(l.filter(f=>a(f)).map(async f=>{const u=f;try{const m=c?c(u,o.id):{name:u.name,identifier:u.identifier,scopes:u.scopes,signing_alg:u.signing_alg,signing_secret:u.signing_secret,token_lifetime:u.token_lifetime,token_lifetime_for_web:u.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:u.skip_consent_for_verifiable_first_party_clients,allow_offline_access:u.allow_offline_access,verificationKey:u.verificationKey,options:u.options};await r.resourceServers.create(o.id,{...m,is_system:!0})}catch(m){console.error(`Failed to sync resource server "${u.identifier}" to new tenant "${o.id}":`,m)}}))}catch(i){console.error(`Failed to sync resource servers to new tenant "${o.id}":`,i)}}}}var p=class extends Error{constructor(e=500,s){super(s==null?void 0:s.message,{cause:s==null?void 0:s.cause});M(this,"res");M(this,"status");this.res=s==null?void 0:s.res,this.status=e}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function S(t,e){const s=new R.Hono;return s.get("/",async n=>{var l;if(t.accessControl&&await((l=e.onTenantAccessValidation)==null?void 0:l.call(e,n,t.accessControl.mainTenantId))===!1)throw new p(403,{message:"Access denied to tenant management"});const a=$.auth0QuerySchema.parse(n.req.query()),{page:c,per_page:d,include_totals:o,q:i}=a,r=await n.env.data.tenants.list({page:c,per_page:d,include_totals:o,q:i});return o?n.json(r):n.json(r.tenants)}),s.get("/:id",async n=>{var o;const a=n.req.param("id");if(await((o=e.onTenantAccessValidation)==null?void 0:o.call(e,n,a))===!1)throw new p(403,{message:"Access denied to this tenant"});const d=await n.env.data.tenants.get(a);if(!d)throw new p(404,{message:"Tenant not found"});return n.json(d)}),s.post("/",async n=>{var a,c,d,o;try{if(t.accessControl&&await((a=e.onTenantAccessValidation)==null?void 0:a.call(e,n,t.accessControl.mainTenantId))===!1)throw new p(403,{message:"Access denied to create tenants"});let i=$.tenantInsertSchema.parse(await n.req.json());const r={adapters:n.env.data,ctx:n};(c=e.tenants)!=null&&c.beforeCreate&&(i=await e.tenants.beforeCreate(r,i));const l=await n.env.data.tenants.create(i);return(d=e.tenants)!=null&&d.afterCreate&&await e.tenants.afterCreate(r,l),n.json(l,201)}catch(i){throw i instanceof Q.z.ZodError?new p(400,{message:"Validation error",cause:i}):i instanceof Error&&("code"in i&&i.code==="SQLITE_CONSTRAINT_PRIMARYKEY"||(o=i.message)!=null&&o.includes("UNIQUE constraint failed"))?new p(409,{message:"Tenant with this ID already exists"}):i}}),s.patch("/:id",async n=>{var m,h,_;const a=n.req.param("id");if(await((m=e.onTenantAccessValidation)==null?void 0:m.call(e,n,a))===!1)throw new p(403,{message:"Access denied to update this tenant"});const d=$.tenantInsertSchema.partial().parse(await n.req.json()),{id:o,...i}=d;if(!await n.env.data.tenants.get(a))throw new p(404,{message:"Tenant not found"});const l={adapters:n.env.data,ctx:n};let f=i;(h=e.tenants)!=null&&h.beforeUpdate&&(f=await e.tenants.beforeUpdate(l,a,i)),await n.env.data.tenants.update(a,f);const u=await n.env.data.tenants.get(a);if(!u)throw new p(404,{message:"Tenant not found after update"});return(_=e.tenants)!=null&&_.afterUpdate&&await e.tenants.afterUpdate(l,u),n.json(u)}),s.delete("/:id",async n=>{var o,i,r;const a=n.req.param("id");if(t.accessControl&&a===t.accessControl.mainTenantId)throw new p(400,{message:"Cannot delete the main tenant"});if(t.accessControl&&await((o=e.onTenantAccessValidation)==null?void 0:o.call(e,n,t.accessControl.mainTenantId))===!1)throw new p(403,{message:"Access denied to delete tenants"});if(!await n.env.data.tenants.get(a))throw new p(404,{message:"Tenant not found"});const d={adapters:n.env.data,ctx:n};return(i=e.tenants)!=null&&i.beforeDelete&&await e.tenants.beforeDelete(d,a),await n.env.data.tenants.remove(a),(r=e.tenants)!=null&&r.afterDelete&&await e.tenants.afterDelete(d,a),n.body(null,204)}),s}function Z(t){const e=[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:"resource_server"},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:"role"},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:"connection"}];for(const{pattern:s,type:n}of e){const a=t.match(s);if(a&&a[1])return{type:n,id:a[1]}}return null}async function J(t,e,s){try{switch(s.type){case"resource_server":{const n=await t.resourceServers.get(e,s.id);return(n==null?void 0:n.is_system)===!0}case"role":{const n=await t.roles.get(e,s.id);return(n==null?void 0:n.is_system)===!0}case"connection":{const n=await t.connections.get(e,s.id);return(n==null?void 0:n.is_system)===!0}default:return!1}}catch{return!1}}function X(t){return{resource_server:"resource server",role:"role",connection:"connection"}[t]}function E(){return async(t,e)=>{if(!["PATCH","PUT","DELETE"].includes(t.req.method))return e();const s=Z(t.req.path);if(!s)return e();const n=t.var.tenant_id||t.req.header("x-tenant-id")||t.req.header("tenant-id");if(!n)return e();if(await J(t.env.data,n,s))throw new p(403,{message:`This ${X(s.type)} is a system resource and cannot be modified. Make changes in the main tenant instead.`});return e()}}function U(t){return async(e,s)=>{if(!t.accessControl)return s();const n=e.var.tenant_id,a=e.var.organization_id;if(!n)throw new p(400,{message:"Tenant ID not found in request"});if(!D(a,n,t.accessControl.mainTenantId))throw new p(403,{message:`Access denied to tenant ${n}`});return s()}}function N(t){return async(e,s)=>{if(!t.subdomainRouting)return s();const{baseDomain:n,reservedSubdomains:a=[],resolveSubdomain:c}=t.subdomainRouting,d=e.req.header("host")||"";let o=null;if(d.endsWith(n)){const r=d.slice(0,-(n.length+1));r&&!r.includes(".")&&(o=r)}if(o&&a.includes(o)&&(o=null),!o)return t.accessControl&&e.set("tenant_id",t.accessControl.mainTenantId),s();let i=null;if(c)i=await c(o);else if(t.subdomainRouting.useOrganizations!==!1&&t.accessControl)try{const r=await e.env.data.organizations.get(t.accessControl.mainTenantId,o);r&&(i=r.id)}catch{}if(!i)throw new p(404,{message:`Tenant not found for subdomain: ${o}`});return e.set("tenant_id",i),s()}}function K(t){return async(e,s)=>{if(!t.databaseIsolation)return s();const n=e.var.tenant_id;if(!n)throw new p(400,{message:"Tenant ID not found in request"});try{const a=await t.databaseIsolation.getAdapters(n);e.env.data=a}catch(a){throw console.error(`Failed to resolve database for tenant ${n}:`,a),new p(500,{message:"Failed to resolve tenant database"})}return s()}}function I(t){const e=N(t),s=U(t),n=K(t);return async(a,c)=>(await e(a,async()=>{}),await s(a,async()=>{}),await n(a,async()=>{}),c())}function k(t){const e=b(t);return{name:"multi-tenancy",middleware:I(t),hooks:e,routes:[{path:"/management",handler:S(t,e)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),t.accessControl&&console.log(` - Access control enabled (main tenant: ${t.accessControl.mainTenantId})`),t.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${t.subdomainRouting.baseDomain})`),t.databaseIsolation&&console.log(" - Database isolation enabled")}}}function b(t){const e=t.accessControl?q(t.accessControl):{},s=t.databaseIsolation?z(t.databaseIsolation):{},n=F(t);return{...e,...s,tenants:n}}function V(t){const e=new R.Hono,s=b(t);return e.route("/tenants",S(t,s)),e}function x(t){return{hooks:b(t),middleware:I(t),app:V(t),config:t}}function ee(t){const{mainTenantId:e="main",syncResourceServers:s=!0,multiTenancy:n,entityHooks:a,...c}=t,d={...n,accessControl:{mainTenantId:e,requireOrganizationMatch:!1,defaultPermissions:["tenant:admin"],...n==null?void 0:n.accessControl}},o=b(d);let i,r;s&&(i=j({mainTenantId:e,getChildTenantIds:async()=>(await P(y=>t.dataAdapter.tenants.list(y),"tenants",{cursorField:"id",pageSize:100})).filter(y=>y.id!==e).map(y=>y.id),getAdapters:async g=>t.dataAdapter}),r=O({mainTenantId:e,getMainTenantAdapters:async()=>t.dataAdapter,getAdapters:async g=>t.dataAdapter}));const l=async(g,y,...T)=>{const v=[];if(g)try{await g(...T)}catch(A){v.push(A instanceof Error?A:new Error(String(A)))}if(y)try{await y(...T)}catch(A){v.push(A instanceof Error?A:new Error(String(A)))}if(v.length===1)throw v[0];if(v.length>1)throw new AggregateError(v,`Multiple hook errors: ${v.map(A=>A.message).join("; ")}`)},f={...a,resourceServers:i?{...a==null?void 0:a.resourceServers,afterCreate:async(g,y)=>{var T;await l((T=a==null?void 0:a.resourceServers)==null?void 0:T.afterCreate,i==null?void 0:i.afterCreate,g,y)},afterUpdate:async(g,y,T)=>{var v;await l((v=a==null?void 0:a.resourceServers)==null?void 0:v.afterUpdate,i==null?void 0:i.afterUpdate,g,y,T)},afterDelete:async(g,y)=>{var T;await l((T=a==null?void 0:a.resourceServers)==null?void 0:T.afterDelete,i==null?void 0:i.afterDelete,g,y)}}:a==null?void 0:a.resourceServers,tenants:r?{...a==null?void 0:a.tenants,afterCreate:async(g,y)=>{var T;await l((T=a==null?void 0:a.tenants)==null?void 0:T.afterCreate,r==null?void 0:r.afterCreate,g,y)}}:a==null?void 0:a.tenants},u=C.init({...c,entityHooks:f}),{app:m,managementApp:h,..._}=u,w=new R.Hono;w.use("/api/v2/*",E()),w.route("/",m);const H=S(d,o);return w.route("/api/v2/tenants",H),{app:w,managementApp:h,..._,multiTenancyConfig:d,multiTenancyHooks:o}}Object.defineProperty(exports,"MANAGEMENT_API_SCOPES",{enumerable:!0,get:()=>C.MANAGEMENT_API_SCOPES});Object.defineProperty(exports,"seed",{enumerable:!0,get:()=>C.seed});exports.createAccessControlHooks=q;exports.createAccessControlMiddleware=U;exports.createDatabaseHooks=z;exports.createDatabaseMiddleware=K;exports.createMultiTenancy=V;exports.createMultiTenancyHooks=b;exports.createMultiTenancyMiddleware=I;exports.createMultiTenancyPlugin=k;exports.createProtectSyncedMiddleware=E;exports.createProvisioningHooks=F;exports.createResourceServerSyncHooks=j;exports.createSubdomainMiddleware=N;exports.createTenantResourceServerSyncHooks=O;exports.createTenantsRouter=S;exports.fetchAll=P;exports.init=ee;exports.setupMultiTenancy=x;exports.validateTenantAccess=D;
1
+ "use strict";var W=Object.defineProperty;var G=(e,n,s)=>n in e?W(e,n,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[n]=s;var z=(e,n,s)=>G(e,typeof n!="symbol"?n+"":n,s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("hono"),S=require("authhero"),Q=require("zod"),$=require("@authhero/adapter-interfaces");function q(e){const{mainTenantId:n,requireOrganizationMatch:s=!0}=e;return{async onTenantAccessValidation(t,a){if(a===n)return!0;if(s){const o=t.var.organization_id;return o?o===a:!1}return!0}}}function P(e,n,s){return n===s?!0:e?e===n:!1}function D(e){return{async resolveDataAdapters(n){try{return await e.getAdapters(n)}catch(s){console.error(`Failed to resolve data adapters for tenant ${n}:`,s);return}}}}function F(e){return{async afterCreate(n,s){const{accessControl:t,databaseIsolation:a,settingsInheritance:o}=e;t&&n.ctx&&await V(n,s,t),a!=null&&a.onProvision&&await a.onProvision(s.id),(o==null?void 0:o.inheritFromMain)!==!1&&n.ctx&&await Y(n,s,e)},async beforeDelete(n,s){const{accessControl:t,databaseIsolation:a}=e;if(t)try{const d=(await n.adapters.organizations.list(t.mainTenantId)).organizations.find(i=>i.name===s);d&&await n.adapters.organizations.remove(t.mainTenantId,d.id)}catch(o){console.warn(`Failed to remove organization for tenant ${s}:`,o)}if(a!=null&&a.onDeprovision)try{await a.onDeprovision(s)}catch(o){console.warn(`Failed to deprovision database for tenant ${s}:`,o)}}}}async function V(e,n,s){const{mainTenantId:t,defaultPermissions:a,defaultRoles:o,issuer:d,adminRoleName:i="Tenant Admin",adminRoleDescription:c="Full access to all tenant management operations",addCreatorToOrganization:r=!0}=s;await e.adapters.organizations.create(t,{id:n.id,name:n.id,display_name:n.friendly_name||n.id});let l=null;if(d&&(l=await L(e,t,d,i,c)),r&&e.ctx){const f=e.ctx.var.user;if(f!=null&&f.sub)try{await e.adapters.userOrganizations.create(t,{user_id:f.sub,organization_id:n.id}),l&&await e.adapters.userRoles.create(t,f.sub,l,n.id)}catch(u){console.warn(`Failed to add creator ${f.sub} to organization ${n.id}:`,u)}}o&&o.length>0&&console.log(`Would assign roles ${o.join(", ")} to organization ${n.id}`),a&&a.length>0&&console.log(`Would grant permissions ${a.join(", ")} to organization ${n.id}`)}async function L(e,n,s,t,a){const d=(await e.adapters.roles.list(n,{})).roles.find(l=>l.name===t);if(d)return d.id;const i=await e.adapters.roles.create(n,{name:t,description:a}),c=`${s}api/v2/`,r=S.MANAGEMENT_API_SCOPES.map(l=>({role_id:i.id,resource_server_identifier:c,permission_name:l.value}));return await e.adapters.rolePermissions.assign(n,i.id,r),i.id}async function Y(e,n,s){const{accessControl:t,settingsInheritance:a}=s;if(!t)return;const o=await e.adapters.tenants.get(t.mainTenantId);if(!o)return;let d={...o};const i=["id","created_at","updated_at","friendly_name","audience","sender_email","sender_name"];for(const c of i)delete d[c];if(a!=null&&a.inheritedKeys){const c={};for(const r of a.inheritedKeys)r in o&&!i.includes(r)&&(c[r]=o[r]);d=c}if(a!=null&&a.excludedKeys)for(const c of a.excludedKeys)delete d[c];a!=null&&a.transformSettings&&(d=a.transformSettings(d,n.id)),Object.keys(d).length>0&&await e.adapters.tenants.update(n.id,d)}async function R(e,n,s={}){const{cursorField:t="id",sortOrder:a="asc",pageSize:o=100,maxItems:d=1e4,q:i}=s,c=[];let r,l=!0;for(;l;){let f=i||"";if(r){const w=`${t}:${a==="asc"?">":"<"}${r}`;f=f?`(${f}) AND ${w}`:w}const u={per_page:o,page:0,sort:{sort_by:t,sort_order:a},...f&&{q:f}},_=(await e(u))[n]||[];if(_.length===0)l=!1;else{c.push(..._);const g=_[_.length-1];if(g&&typeof g=="object"){const w=g[t];w!=null&&(r=String(w))}_.length<o&&(l=!1),d!==-1&&c.length>=d&&(console.warn(`fetchAll: Reached maxItems limit (${d}). There may be more items.`),l=!1)}}return c}function j(e){const{mainTenantId:n,getChildTenantIds:s,getAdapters:t,shouldSync:a=()=>!0,transformForSync:o}=e;async function d(r,l,f){return(await r.resourceServers.list(l,{q:`identifier:${f}`,per_page:1})).resource_servers[0]??null}async function i(r,l){const f=await s();await Promise.all(f.map(async u=>{try{const m=await t(u),g={...o?o(r,u):{name:r.name,identifier:r.identifier,scopes:r.scopes,signing_alg:r.signing_alg,signing_secret:r.signing_secret,token_lifetime:r.token_lifetime,token_lifetime_for_web:r.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:r.skip_consent_for_verifiable_first_party_clients,allow_offline_access:r.allow_offline_access,verificationKey:r.verificationKey,options:r.options},is_system:!0};if(l==="create"){const w=await d(m,u,r.identifier);w&&w.id?await m.resourceServers.update(u,w.id,g):await m.resourceServers.create(u,g)}else{const w=await d(m,u,r.identifier);w&&w.id&&await m.resourceServers.update(u,w.id,g)}}catch(m){console.error(`Failed to sync resource server "${r.identifier}" to tenant "${u}":`,m)}}))}async function c(r){const l=await s();await Promise.all(l.map(async f=>{try{const u=await t(f),m=await d(u,f,r);m&&m.id&&await u.resourceServers.remove(f,m.id)}catch(u){console.error(`Failed to delete resource server "${r}" from tenant "${f}":`,u)}}))}return{afterCreate:async(r,l)=>{r.tenantId===n&&a(l)&&await i(l,"create")},afterUpdate:async(r,l,f)=>{r.tenantId===n&&a(f)&&await i(f,"update")},afterDelete:async(r,l)=>{r.tenantId===n&&await c(l)}}}function U(e){const{mainTenantId:n,getMainTenantAdapters:s,getAdapters:t,shouldSync:a=()=>!0,transformForSync:o}=e;return{async afterCreate(d,i){if(i.id!==n)try{const c=await s(),r=await t(i.id),l=await R(f=>c.resourceServers.list(n,f),"resource_servers",{cursorField:"id",pageSize:100});await Promise.all(l.filter(f=>a(f)).map(async f=>{const u=f;try{const m=o?o(u,i.id):{name:u.name,identifier:u.identifier,scopes:u.scopes,signing_alg:u.signing_alg,signing_secret:u.signing_secret,token_lifetime:u.token_lifetime,token_lifetime_for_web:u.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:u.skip_consent_for_verifiable_first_party_clients,allow_offline_access:u.allow_offline_access,verificationKey:u.verificationKey,options:u.options};await r.resourceServers.create(i.id,{...m,is_system:!0})}catch(m){console.error(`Failed to sync resource server "${u.identifier}" to new tenant "${i.id}":`,m)}}))}catch(c){console.error(`Failed to sync resource servers to new tenant "${i.id}":`,c)}}}}var p=class extends Error{constructor(n=500,s){super(s==null?void 0:s.message,{cause:s==null?void 0:s.cause});z(this,"res");z(this,"status");this.res=s==null?void 0:s.res,this.status=n}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function M(e,n){const s=new I.Hono;return s.get("/",async t=>{var f,u;const a=$.auth0QuerySchema.parse(t.req.query()),{page:o,per_page:d,include_totals:i,q:c}=a,r=t.var.user;if(e.accessControl&&(r!=null&&r.sub)){const m=e.accessControl.mainTenantId,g=(await t.env.data.userOrganizations.listUserOrganizations(m,r.sub,{})).organizations.map(y=>y.id);g.includes(m)||g.push(m);const w=await t.env.data.tenants.list({page:o,per_page:d,include_totals:i,q:c}),A=w.tenants.filter(y=>g.includes(y.id));return i?t.json({tenants:A,start:((f=w.totals)==null?void 0:f.start)??0,limit:((u=w.totals)==null?void 0:u.limit)??d,length:A.length}):t.json(A)}const l=await t.env.data.tenants.list({page:o,per_page:d,include_totals:i,q:c});return i?t.json(l):t.json(l.tenants)}),s.get("/:id",async t=>{const a=t.req.param("id");if(e.accessControl){const d=t.var.user,i=e.accessControl.mainTenantId;if(a!==i){if(!(d!=null&&d.sub))throw new p(401,{message:"Authentication required"});if(!(await t.env.data.userOrganizations.listUserOrganizations(i,d.sub,{})).organizations.some(l=>l.id===a))throw new p(403,{message:"Access denied to this tenant"})}}const o=await t.env.data.tenants.get(a);if(!o)throw new p(404,{message:"Tenant not found"});return t.json(o)}),s.post("/",async t=>{var a,o,d;try{const i=t.var.user;if(!(i!=null&&i.sub))throw new p(401,{message:"Authentication required to create tenants"});let c=$.tenantInsertSchema.parse(await t.req.json());const r={adapters:t.env.data,ctx:t};(a=n.tenants)!=null&&a.beforeCreate&&(c=await n.tenants.beforeCreate(r,c));const l=await t.env.data.tenants.create(c);return(o=n.tenants)!=null&&o.afterCreate&&await n.tenants.afterCreate(r,l),t.json(l,201)}catch(i){throw i instanceof Q.z.ZodError?new p(400,{message:"Validation error",cause:i}):i instanceof Error&&("code"in i&&i.code==="SQLITE_CONSTRAINT_PRIMARYKEY"||(d=i.message)!=null&&d.includes("UNIQUE constraint failed"))?new p(409,{message:"Tenant with this ID already exists"}):i}}),s.patch("/:id",async t=>{var u,m;const a=t.req.param("id");if(e.accessControl){const _=t.var.user;if(!(_!=null&&_.sub))throw new p(401,{message:"Authentication required to update tenants"});const g=e.accessControl.mainTenantId;if(a!==g&&!(await t.env.data.userOrganizations.listUserOrganizations(g,_.sub,{})).organizations.some(y=>y.id===a))throw new p(403,{message:"Access denied to update this tenant"})}const o=$.tenantInsertSchema.partial().parse(await t.req.json()),{id:d,...i}=o;if(!await t.env.data.tenants.get(a))throw new p(404,{message:"Tenant not found"});const r={adapters:t.env.data,ctx:t};let l=i;(u=n.tenants)!=null&&u.beforeUpdate&&(l=await n.tenants.beforeUpdate(r,a,i)),await t.env.data.tenants.update(a,l);const f=await t.env.data.tenants.get(a);if(!f)throw new p(404,{message:"Tenant not found after update"});return(m=n.tenants)!=null&&m.afterUpdate&&await n.tenants.afterUpdate(r,f),t.json(f)}),s.delete("/:id",async t=>{var i,c;const a=t.req.param("id");if(e.accessControl&&a===e.accessControl.mainTenantId)throw new p(400,{message:"Cannot delete the main tenant"});if(e.accessControl){const r=t.var.user;if(!(r!=null&&r.sub))throw new p(401,{message:"Authentication required to delete tenants"});const l=e.accessControl.mainTenantId;if(!(await t.env.data.userOrganizations.listUserOrganizations(l,r.sub,{})).organizations.some(m=>m.id===a))throw new p(403,{message:"Access denied to delete this tenant"})}if(!await t.env.data.tenants.get(a))throw new p(404,{message:"Tenant not found"});const d={adapters:t.env.data,ctx:t};return(i=n.tenants)!=null&&i.beforeDelete&&await n.tenants.beforeDelete(d,a),await t.env.data.tenants.remove(a),(c=n.tenants)!=null&&c.afterDelete&&await n.tenants.afterDelete(d,a),t.body(null,204)}),s}function B(e){const n=[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:"resource_server"},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:"role"},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:"connection"}];for(const{pattern:s,type:t}of n){const a=e.match(s);if(a&&a[1])return{type:t,id:a[1]}}return null}async function Z(e,n,s){try{switch(s.type){case"resource_server":{const t=await e.resourceServers.get(n,s.id);return(t==null?void 0:t.is_system)===!0}case"role":{const t=await e.roles.get(n,s.id);return(t==null?void 0:t.is_system)===!0}case"connection":{const t=await e.connections.get(n,s.id);return(t==null?void 0:t.is_system)===!0}default:return!1}}catch{return!1}}function J(e){return{resource_server:"resource server",role:"role",connection:"connection"}[e]}function E(){return async(e,n)=>{if(!["PATCH","PUT","DELETE"].includes(e.req.method))return n();const s=B(e.req.path);if(!s)return n();const t=e.var.tenant_id||e.req.header("x-tenant-id")||e.req.header("tenant-id");if(!t)return n();if(await Z(e.env.data,t,s))throw new p(403,{message:`This ${J(s.type)} is a system resource and cannot be modified. Make changes in the main tenant instead.`});return n()}}function N(e){return async(n,s)=>{if(!e.accessControl)return s();const t=n.var.tenant_id,a=n.var.organization_id;if(!t)throw new p(400,{message:"Tenant ID not found in request"});if(!P(a,t,e.accessControl.mainTenantId))throw new p(403,{message:`Access denied to tenant ${t}`});return s()}}function k(e){return async(n,s)=>{if(!e.subdomainRouting)return s();const{baseDomain:t,reservedSubdomains:a=[],resolveSubdomain:o}=e.subdomainRouting,d=n.req.header("host")||"";let i=null;if(d.endsWith(t)){const r=d.slice(0,-(t.length+1));r&&!r.includes(".")&&(i=r)}if(i&&a.includes(i)&&(i=null),!i)return e.accessControl&&n.set("tenant_id",e.accessControl.mainTenantId),s();let c=null;if(o)c=await o(i);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{const r=await n.env.data.organizations.get(e.accessControl.mainTenantId,i);r&&(c=r.id)}catch{}if(!c)throw new p(404,{message:`Tenant not found for subdomain: ${i}`});return n.set("tenant_id",c),s()}}function K(e){return async(n,s)=>{if(!e.databaseIsolation)return s();const t=n.var.tenant_id;if(!t)throw new p(400,{message:"Tenant ID not found in request"});try{const a=await e.databaseIsolation.getAdapters(t);n.env.data=a}catch(a){throw console.error(`Failed to resolve database for tenant ${t}:`,a),new p(500,{message:"Failed to resolve tenant database"})}return s()}}function O(e){const n=k(e),s=N(e),t=K(e);return async(a,o)=>(await n(a,async()=>{}),await s(a,async()=>{}),await t(a,async()=>{}),o())}function X(e){const n=C(e);return{name:"multi-tenancy",middleware:O(e),hooks:n,routes:[{path:"/management",handler:M(e,n)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),e.accessControl&&console.log(` - Access control enabled (main tenant: ${e.accessControl.mainTenantId})`),e.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${e.subdomainRouting.baseDomain})`),e.databaseIsolation&&console.log(" - Database isolation enabled")}}}function C(e){const n=e.accessControl?q(e.accessControl):{},s=e.databaseIsolation?D(e.databaseIsolation):{},t=F(e);return{...n,...s,tenants:t}}function H(e){const n=new I.Hono,s=C(e);return n.route("/tenants",M(e,s)),n}function x(e){return{hooks:C(e),middleware:O(e),app:H(e),config:e}}function ee(e){const{mainTenantId:n="main",syncResourceServers:s=!0,multiTenancy:t,entityHooks:a,...o}=e,d={...t,accessControl:{mainTenantId:n,requireOrganizationMatch:!1,defaultPermissions:["tenant:admin"],...t==null?void 0:t.accessControl}},i=C(d);let c,r;s&&(c=j({mainTenantId:n,getChildTenantIds:async()=>(await R(h=>e.dataAdapter.tenants.list(h),"tenants",{cursorField:"id",pageSize:100})).filter(h=>h.id!==n).map(h=>h.id),getAdapters:async y=>e.dataAdapter}),r=U({mainTenantId:n,getMainTenantAdapters:async()=>e.dataAdapter,getAdapters:async y=>e.dataAdapter}));const l=async(y,h,...T)=>{const v=[];if(y)try{await y(...T)}catch(b){v.push(b instanceof Error?b:new Error(String(b)))}if(h)try{await h(...T)}catch(b){v.push(b instanceof Error?b:new Error(String(b)))}if(v.length===1)throw v[0];if(v.length>1)throw new AggregateError(v,`Multiple hook errors: ${v.map(b=>b.message).join("; ")}`)},f={...a,resourceServers:c?{...a==null?void 0:a.resourceServers,afterCreate:async(y,h)=>{var T;await l((T=a==null?void 0:a.resourceServers)==null?void 0:T.afterCreate,c==null?void 0:c.afterCreate,y,h)},afterUpdate:async(y,h,T)=>{var v;await l((v=a==null?void 0:a.resourceServers)==null?void 0:v.afterUpdate,c==null?void 0:c.afterUpdate,y,h,T)},afterDelete:async(y,h)=>{var T;await l((T=a==null?void 0:a.resourceServers)==null?void 0:T.afterDelete,c==null?void 0:c.afterDelete,y,h)}}:a==null?void 0:a.resourceServers,tenants:r?{...a==null?void 0:a.tenants,afterCreate:async(y,h)=>{var T;await l((T=a==null?void 0:a.tenants)==null?void 0:T.afterCreate,r==null?void 0:r.afterCreate,y,h)}}:a==null?void 0:a.tenants},u=S.init({...o,entityHooks:f}),{app:m,managementApp:_,...g}=u,w=new I.Hono;w.use("/api/v2/*",E()),w.route("/",m);const A=M(d,i);return w.route("/api/v2/tenants",A),{app:w,managementApp:_,...g,multiTenancyConfig:d,multiTenancyHooks:i}}Object.defineProperty(exports,"MANAGEMENT_API_SCOPES",{enumerable:!0,get:()=>S.MANAGEMENT_API_SCOPES});Object.defineProperty(exports,"seed",{enumerable:!0,get:()=>S.seed});exports.createAccessControlHooks=q;exports.createAccessControlMiddleware=N;exports.createDatabaseHooks=D;exports.createDatabaseMiddleware=K;exports.createMultiTenancy=H;exports.createMultiTenancyHooks=C;exports.createMultiTenancyMiddleware=O;exports.createMultiTenancyPlugin=X;exports.createProtectSyncedMiddleware=E;exports.createProvisioningHooks=F;exports.createResourceServerSyncHooks=j;exports.createSubdomainMiddleware=k;exports.createTenantResourceServerSyncHooks=U;exports.createTenantsRouter=M;exports.fetchAll=R;exports.init=ee;exports.setupMultiTenancy=x;exports.validateTenantAccess=P;
@@ -9713,6 +9713,7 @@ export interface SeedResult {
9713
9713
  userId: string;
9714
9714
  email: string;
9715
9715
  clientId: string;
9716
+ clientSecret: string;
9716
9717
  }
9717
9718
  /**
9718
9719
  * Seed the AuthHero database with initial data.
@@ -1,36 +1,36 @@
1
- var D = Object.defineProperty;
2
- var q = (t, e, s) => e in t ? D(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
3
- var C = (t, e, s) => q(t, typeof e != "symbol" ? e + "" : e, s);
1
+ var O = Object.defineProperty;
2
+ var q = (e, n, s) => n in e ? O(e, n, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[n] = s;
3
+ var z = (e, n, s) => q(e, typeof n != "symbol" ? n + "" : n, s);
4
4
  import { Hono as $ } from "hono";
5
- import { MANAGEMENT_API_SCOPES as F, init as P } from "authhero";
5
+ import { MANAGEMENT_API_SCOPES as D, init as F } from "authhero";
6
6
  import { MANAGEMENT_API_SCOPES as le, seed as ue } from "authhero";
7
- import { z as j } from "zod";
8
- import { auth0QuerySchema as U, tenantInsertSchema as R } from "@authhero/adapter-interfaces";
9
- function O(t) {
10
- const { mainTenantId: e, requireOrganizationMatch: s = !0 } = t;
7
+ import { z as P } from "zod";
8
+ import { auth0QuerySchema as U, tenantInsertSchema as I } from "@authhero/adapter-interfaces";
9
+ function j(e) {
10
+ const { mainTenantId: n, requireOrganizationMatch: s = !0 } = e;
11
11
  return {
12
- async onTenantAccessValidation(n, a) {
13
- if (a === e)
12
+ async onTenantAccessValidation(t, a) {
13
+ if (a === n)
14
14
  return !0;
15
15
  if (s) {
16
- const c = n.var.organization_id;
17
- return c ? c === a : !1;
16
+ const o = t.var.organization_id;
17
+ return o ? o === a : !1;
18
18
  }
19
19
  return !0;
20
20
  }
21
21
  };
22
22
  }
23
- function E(t, e, s) {
24
- return e === s ? !0 : t ? t === e : !1;
23
+ function E(e, n, s) {
24
+ return n === s ? !0 : e ? e === n : !1;
25
25
  }
26
- function K(t) {
26
+ function K(e) {
27
27
  return {
28
- async resolveDataAdapters(e) {
28
+ async resolveDataAdapters(n) {
29
29
  try {
30
- return await t.getAdapters(e);
30
+ return await e.getAdapters(n);
31
31
  } catch (s) {
32
32
  console.error(
33
- `Failed to resolve data adapters for tenant ${e}:`,
33
+ `Failed to resolve data adapters for tenant ${n}:`,
34
34
  s
35
35
  );
36
36
  return;
@@ -38,113 +38,113 @@ function K(t) {
38
38
  }
39
39
  };
40
40
  }
41
- function N(t) {
41
+ function N(e) {
42
42
  return {
43
- async afterCreate(e, s) {
44
- const { accessControl: n, databaseIsolation: a, settingsInheritance: c } = t;
45
- n && e.ctx && await V(e, s, n), a != null && a.onProvision && await a.onProvision(s.id), (c == null ? void 0 : c.inheritFromMain) !== !1 && e.ctx && await Q(e, s, t);
43
+ async afterCreate(n, s) {
44
+ const { accessControl: t, databaseIsolation: a, settingsInheritance: o } = e;
45
+ t && n.ctx && await W(n, s, t), a != null && a.onProvision && await a.onProvision(s.id), (o == null ? void 0 : o.inheritFromMain) !== !1 && n.ctx && await Q(n, s, e);
46
46
  },
47
- async beforeDelete(e, s) {
48
- const { accessControl: n, databaseIsolation: a } = t;
49
- if (n)
47
+ async beforeDelete(n, s) {
48
+ const { accessControl: t, databaseIsolation: a } = e;
49
+ if (t)
50
50
  try {
51
- const d = (await e.adapters.organizations.list(
52
- n.mainTenantId
53
- )).organizations.find((o) => o.name === s);
54
- d && await e.adapters.organizations.remove(
55
- n.mainTenantId,
51
+ const d = (await n.adapters.organizations.list(
52
+ t.mainTenantId
53
+ )).organizations.find((i) => i.name === s);
54
+ d && await n.adapters.organizations.remove(
55
+ t.mainTenantId,
56
56
  d.id
57
57
  );
58
- } catch (c) {
58
+ } catch (o) {
59
59
  console.warn(
60
60
  `Failed to remove organization for tenant ${s}:`,
61
- c
61
+ o
62
62
  );
63
63
  }
64
64
  if (a != null && a.onDeprovision)
65
65
  try {
66
66
  await a.onDeprovision(s);
67
- } catch (c) {
67
+ } catch (o) {
68
68
  console.warn(
69
69
  `Failed to deprovision database for tenant ${s}:`,
70
- c
70
+ o
71
71
  );
72
72
  }
73
73
  }
74
74
  };
75
75
  }
76
- async function V(t, e, s) {
76
+ async function W(e, n, s) {
77
77
  const {
78
- mainTenantId: n,
78
+ mainTenantId: t,
79
79
  defaultPermissions: a,
80
- defaultRoles: c,
80
+ defaultRoles: o,
81
81
  issuer: d,
82
- adminRoleName: o = "Tenant Admin",
83
- adminRoleDescription: i = "Full access to all tenant management operations",
82
+ adminRoleName: i = "Tenant Admin",
83
+ adminRoleDescription: c = "Full access to all tenant management operations",
84
84
  addCreatorToOrganization: r = !0
85
85
  } = s;
86
- await t.adapters.organizations.create(n, {
87
- id: e.id,
88
- name: e.id,
89
- display_name: e.friendly_name || e.id
86
+ await e.adapters.organizations.create(t, {
87
+ id: n.id,
88
+ name: n.id,
89
+ display_name: n.friendly_name || n.id
90
90
  });
91
91
  let l = null;
92
- if (d && (l = await W(
92
+ if (d && (l = await k(
93
+ e,
93
94
  t,
94
- n,
95
95
  d,
96
- o,
97
- i
98
- )), r && t.ctx) {
99
- const f = t.ctx.var.user;
96
+ i,
97
+ c
98
+ )), r && e.ctx) {
99
+ const f = e.ctx.var.user;
100
100
  if (f != null && f.sub)
101
101
  try {
102
- await t.adapters.userOrganizations.create(n, {
102
+ await e.adapters.userOrganizations.create(t, {
103
103
  user_id: f.sub,
104
- organization_id: e.id
105
- }), l && await t.adapters.userRoles.create(
106
- n,
104
+ organization_id: n.id
105
+ }), l && await e.adapters.userRoles.create(
106
+ t,
107
107
  f.sub,
108
108
  l,
109
- e.id
109
+ n.id
110
110
  // organizationId
111
111
  );
112
112
  } catch (u) {
113
113
  console.warn(
114
- `Failed to add creator ${f.sub} to organization ${e.id}:`,
114
+ `Failed to add creator ${f.sub} to organization ${n.id}:`,
115
115
  u
116
116
  );
117
117
  }
118
118
  }
119
- c && c.length > 0 && console.log(
120
- `Would assign roles ${c.join(", ")} to organization ${e.id}`
119
+ o && o.length > 0 && console.log(
120
+ `Would assign roles ${o.join(", ")} to organization ${n.id}`
121
121
  ), a && a.length > 0 && console.log(
122
- `Would grant permissions ${a.join(", ")} to organization ${e.id}`
122
+ `Would grant permissions ${a.join(", ")} to organization ${n.id}`
123
123
  );
124
124
  }
125
- async function W(t, e, s, n, a) {
126
- const d = (await t.adapters.roles.list(e, {})).roles.find((l) => l.name === n);
125
+ async function k(e, n, s, t, a) {
126
+ const d = (await e.adapters.roles.list(n, {})).roles.find((l) => l.name === t);
127
127
  if (d)
128
128
  return d.id;
129
- const o = await t.adapters.roles.create(e, {
130
- name: n,
129
+ const i = await e.adapters.roles.create(n, {
130
+ name: t,
131
131
  description: a
132
- }), i = `${s}api/v2/`, r = F.map((l) => ({
133
- role_id: o.id,
134
- resource_server_identifier: i,
132
+ }), c = `${s}api/v2/`, r = D.map((l) => ({
133
+ role_id: i.id,
134
+ resource_server_identifier: c,
135
135
  permission_name: l.value
136
136
  }));
137
- return await t.adapters.rolePermissions.assign(e, o.id, r), o.id;
137
+ return await e.adapters.rolePermissions.assign(n, i.id, r), i.id;
138
138
  }
139
- async function Q(t, e, s) {
140
- const { accessControl: n, settingsInheritance: a } = s;
141
- if (!n)
139
+ async function Q(e, n, s) {
140
+ const { accessControl: t, settingsInheritance: a } = s;
141
+ if (!t)
142
142
  return;
143
- const c = await t.adapters.tenants.get(n.mainTenantId);
144
- if (!c)
143
+ const o = await e.adapters.tenants.get(t.mainTenantId);
144
+ if (!o)
145
145
  return;
146
- let d = { ...c };
147
- const o = [
146
+ let d = { ...o };
147
+ const i = [
148
148
  "id",
149
149
  "created_at",
150
150
  "updated_at",
@@ -154,83 +154,83 @@ async function Q(t, e, s) {
154
154
  "sender_email",
155
155
  "sender_name"
156
156
  ];
157
- for (const i of o)
158
- delete d[i];
157
+ for (const c of i)
158
+ delete d[c];
159
159
  if (a != null && a.inheritedKeys) {
160
- const i = {};
160
+ const c = {};
161
161
  for (const r of a.inheritedKeys)
162
- r in c && !o.includes(r) && (i[r] = c[r]);
163
- d = i;
162
+ r in o && !i.includes(r) && (c[r] = o[r]);
163
+ d = c;
164
164
  }
165
165
  if (a != null && a.excludedKeys)
166
- for (const i of a.excludedKeys)
167
- delete d[i];
166
+ for (const c of a.excludedKeys)
167
+ delete d[c];
168
168
  a != null && a.transformSettings && (d = a.transformSettings(
169
169
  d,
170
- e.id
171
- )), Object.keys(d).length > 0 && await t.adapters.tenants.update(e.id, d);
170
+ n.id
171
+ )), Object.keys(d).length > 0 && await e.adapters.tenants.update(n.id, d);
172
172
  }
173
- async function M(t, e, s = {}) {
173
+ async function R(e, n, s = {}) {
174
174
  const {
175
- cursorField: n = "id",
175
+ cursorField: t = "id",
176
176
  sortOrder: a = "asc",
177
- pageSize: c = 100,
177
+ pageSize: o = 100,
178
178
  maxItems: d = 1e4,
179
- q: o
180
- } = s, i = [];
179
+ q: i
180
+ } = s, c = [];
181
181
  let r, l = !0;
182
182
  for (; l; ) {
183
- let f = o || "";
183
+ let f = i || "";
184
184
  if (r) {
185
- const w = `${n}:${a === "asc" ? ">" : "<"}${r}`;
185
+ const w = `${t}:${a === "asc" ? ">" : "<"}${r}`;
186
186
  f = f ? `(${f}) AND ${w}` : w;
187
187
  }
188
188
  const u = {
189
- per_page: c,
189
+ per_page: o,
190
190
  page: 0,
191
191
  // Always use page 0 since we're doing cursor-based pagination
192
192
  sort: {
193
- sort_by: n,
193
+ sort_by: t,
194
194
  sort_order: a
195
195
  },
196
196
  ...f && { q: f }
197
- }, T = (await t(u))[e] || [];
198
- if (T.length === 0)
197
+ }, _ = (await e(u))[n] || [];
198
+ if (_.length === 0)
199
199
  l = !1;
200
200
  else {
201
- i.push(...T);
202
- const _ = T[T.length - 1];
203
- if (_ && typeof _ == "object") {
204
- const w = _[n];
201
+ c.push(..._);
202
+ const g = _[_.length - 1];
203
+ if (g && typeof g == "object") {
204
+ const w = g[t];
205
205
  w != null && (r = String(w));
206
206
  }
207
- T.length < c && (l = !1), d !== -1 && i.length >= d && (console.warn(
207
+ _.length < o && (l = !1), d !== -1 && c.length >= d && (console.warn(
208
208
  `fetchAll: Reached maxItems limit (${d}). There may be more items.`
209
209
  ), l = !1);
210
210
  }
211
211
  }
212
- return i;
212
+ return c;
213
213
  }
214
- function G(t) {
214
+ function V(e) {
215
215
  const {
216
- mainTenantId: e,
216
+ mainTenantId: n,
217
217
  getChildTenantIds: s,
218
- getAdapters: n,
218
+ getAdapters: t,
219
219
  shouldSync: a = () => !0,
220
- transformForSync: c
221
- } = t;
220
+ transformForSync: o
221
+ } = e;
222
222
  async function d(r, l, f) {
223
223
  return (await r.resourceServers.list(l, {
224
224
  q: `identifier:${f}`,
225
225
  per_page: 1
226
226
  })).resource_servers[0] ?? null;
227
227
  }
228
- async function o(r, l) {
228
+ async function i(r, l) {
229
229
  const f = await s();
230
230
  await Promise.all(
231
231
  f.map(async (u) => {
232
232
  try {
233
- const m = await n(u), _ = { ...c ? c(r, u) : {
233
+ const m = await t(u), g = { ...o ? o(r, u) : {
234
234
  name: r.name,
235
235
  identifier: r.identifier,
236
236
  scopes: r.scopes,
@@ -252,8 +252,8 @@ function G(t) {
252
252
  w && w.id ? await m.resourceServers.update(
253
253
  u,
254
254
  w.id,
255
- _
256
- ) : await m.resourceServers.create(u, _);
255
+ g
256
+ ) : await m.resourceServers.create(u, g);
257
257
  } else {
258
258
  const w = await d(
259
259
  m,
@@ -263,7 +263,7 @@ function G(t) {
263
263
  w && w.id && await m.resourceServers.update(
264
264
  u,
265
265
  w.id,
266
- _
266
+ g
267
267
  );
268
268
  }
269
269
  } catch (m) {
@@ -275,12 +275,12 @@ function G(t) {
275
275
  })
276
276
  );
277
277
  }
278
- async function i(r) {
278
+ async function c(r) {
279
279
  const l = await s();
280
280
  await Promise.all(
281
281
  l.map(async (f) => {
282
282
  try {
283
- const u = await n(f), m = await d(
283
+ const u = await t(f), m = await d(
284
284
  u,
285
285
  f,
286
286
  r
@@ -297,30 +297,30 @@ function G(t) {
297
297
  }
298
298
  return {
299
299
  afterCreate: async (r, l) => {
300
- r.tenantId === e && a(l) && await o(l, "create");
300
+ r.tenantId === n && a(l) && await i(l, "create");
301
301
  },
302
302
  afterUpdate: async (r, l, f) => {
303
- r.tenantId === e && a(f) && await o(f, "update");
303
+ r.tenantId === n && a(f) && await i(f, "update");
304
304
  },
305
305
  afterDelete: async (r, l) => {
306
- r.tenantId === e && await i(l);
306
+ r.tenantId === n && await c(l);
307
307
  }
308
308
  };
309
309
  }
310
- function L(t) {
310
+ function G(e) {
311
311
  const {
312
- mainTenantId: e,
312
+ mainTenantId: n,
313
313
  getMainTenantAdapters: s,
314
- getAdapters: n,
314
+ getAdapters: t,
315
315
  shouldSync: a = () => !0,
316
- transformForSync: c
317
- } = t;
316
+ transformForSync: o
317
+ } = e;
318
318
  return {
319
- async afterCreate(d, o) {
320
- if (o.id !== e)
319
+ async afterCreate(d, i) {
320
+ if (i.id !== n)
321
321
  try {
322
- const i = await s(), r = await n(o.id), l = await M(
323
- (f) => i.resourceServers.list(e, f),
322
+ const c = await s(), r = await t(i.id), l = await R(
323
+ (f) => c.resourceServers.list(n, f),
324
324
  "resource_servers",
325
325
  { cursorField: "id", pageSize: 100 }
326
326
  );
@@ -328,7 +328,7 @@ function L(t) {
328
328
  l.filter((f) => a(f)).map(async (f) => {
329
329
  const u = f;
330
330
  try {
331
- const m = c ? c(u, o.id) : {
331
+ const m = o ? o(u, i.id) : {
332
332
  name: u.name,
333
333
  identifier: u.identifier,
334
334
  scopes: u.scopes,
@@ -341,22 +341,22 @@ function L(t) {
341
341
  verificationKey: u.verificationKey,
342
342
  options: u.options
343
343
  };
344
- await r.resourceServers.create(o.id, {
344
+ await r.resourceServers.create(i.id, {
345
345
  ...m,
346
346
  is_system: !0
347
347
  });
348
348
  } catch (m) {
349
349
  console.error(
350
- `Failed to sync resource server "${u.identifier}" to new tenant "${o.id}":`,
350
+ `Failed to sync resource server "${u.identifier}" to new tenant "${i.id}":`,
351
351
  m
352
352
  );
353
353
  }
354
354
  })
355
355
  );
356
- } catch (i) {
356
+ } catch (c) {
357
357
  console.error(
358
- `Failed to sync resource servers to new tenant "${o.id}":`,
359
- i
358
+ `Failed to sync resource servers to new tenant "${i.id}":`,
359
+ c
360
360
  );
361
361
  }
362
362
  }
@@ -368,11 +368,11 @@ var p = class extends Error {
368
368
  * @param status - HTTP status code for the exception. Defaults to 500.
369
369
  * @param options - Additional options for the exception.
370
370
  */
371
- constructor(e = 500, s) {
371
+ constructor(n = 500, s) {
372
372
  super(s == null ? void 0 : s.message, { cause: s == null ? void 0 : s.cause });
373
- C(this, "res");
374
- C(this, "status");
375
- this.res = s == null ? void 0 : s.res, this.status = e;
373
+ z(this, "res");
374
+ z(this, "status");
375
+ this.res = s == null ? void 0 : s.res, this.status = n;
376
376
  }
377
377
  /**
378
378
  * Returns the response object associated with the exception.
@@ -388,119 +388,163 @@ var p = class extends Error {
388
388
  });
389
389
  }
390
390
  };
391
- function S(t, e) {
391
+ function S(e, n) {
392
392
  const s = new $();
393
- return s.get("/", async (n) => {
394
- var l;
395
- if (t.accessControl && await ((l = e.onTenantAccessValidation) == null ? void 0 : l.call(
396
- e,
397
- n,
398
- t.accessControl.mainTenantId
399
- )) === !1)
400
- throw new p(403, {
401
- message: "Access denied to tenant management"
402
- });
403
- const a = U.parse(n.req.query()), { page: c, per_page: d, include_totals: o, q: i } = a, r = await n.env.data.tenants.list({
404
- page: c,
393
+ return s.get("/", async (t) => {
394
+ var f, u;
395
+ const a = U.parse(t.req.query()), { page: o, per_page: d, include_totals: i, q: c } = a, r = t.var.user;
396
+ if (e.accessControl && (r != null && r.sub)) {
397
+ const m = e.accessControl.mainTenantId, g = (await t.env.data.userOrganizations.listUserOrganizations(
398
+ m,
399
+ r.sub,
400
+ {}
401
+ )).organizations.map((y) => y.id);
402
+ g.includes(m) || g.push(m);
403
+ const w = await t.env.data.tenants.list({
404
+ page: o,
405
+ per_page: d,
406
+ include_totals: i,
407
+ q: c
408
+ }), C = w.tenants.filter(
409
+ (y) => g.includes(y.id)
410
+ );
411
+ return i ? t.json({
412
+ tenants: C,
413
+ start: ((f = w.totals) == null ? void 0 : f.start) ?? 0,
414
+ limit: ((u = w.totals) == null ? void 0 : u.limit) ?? d,
415
+ length: C.length
416
+ }) : t.json(C);
417
+ }
418
+ const l = await t.env.data.tenants.list({
419
+ page: o,
405
420
  per_page: d,
406
- include_totals: o,
407
- q: i
421
+ include_totals: i,
422
+ q: c
408
423
  });
409
- return o ? n.json(r) : n.json(r.tenants);
410
- }), s.get("/:id", async (n) => {
411
- var o;
412
- const a = n.req.param("id");
413
- if (await ((o = e.onTenantAccessValidation) == null ? void 0 : o.call(e, n, a)) === !1)
414
- throw new p(403, {
415
- message: "Access denied to this tenant"
416
- });
417
- const d = await n.env.data.tenants.get(a);
418
- if (!d)
424
+ return i ? t.json(l) : t.json(l.tenants);
425
+ }), s.get("/:id", async (t) => {
426
+ const a = t.req.param("id");
427
+ if (e.accessControl) {
428
+ const d = t.var.user, i = e.accessControl.mainTenantId;
429
+ if (a !== i) {
430
+ if (!(d != null && d.sub))
431
+ throw new p(401, {
432
+ message: "Authentication required"
433
+ });
434
+ if (!(await t.env.data.userOrganizations.listUserOrganizations(
435
+ i,
436
+ d.sub,
437
+ {}
438
+ )).organizations.some((l) => l.id === a))
439
+ throw new p(403, {
440
+ message: "Access denied to this tenant"
441
+ });
442
+ }
443
+ }
444
+ const o = await t.env.data.tenants.get(a);
445
+ if (!o)
419
446
  throw new p(404, {
420
447
  message: "Tenant not found"
421
448
  });
422
- return n.json(d);
423
- }), s.post("/", async (n) => {
424
- var a, c, d, o;
449
+ return t.json(o);
450
+ }), s.post("/", async (t) => {
451
+ var a, o, d;
425
452
  try {
426
- if (t.accessControl && await ((a = e.onTenantAccessValidation) == null ? void 0 : a.call(
427
- e,
428
- n,
429
- t.accessControl.mainTenantId
430
- )) === !1)
431
- throw new p(403, {
432
- message: "Access denied to create tenants"
453
+ const i = t.var.user;
454
+ if (!(i != null && i.sub))
455
+ throw new p(401, {
456
+ message: "Authentication required to create tenants"
433
457
  });
434
- let i = R.parse(
435
- await n.req.json()
458
+ let c = I.parse(
459
+ await t.req.json()
436
460
  );
437
461
  const r = {
438
- adapters: n.env.data,
439
- ctx: n
462
+ adapters: t.env.data,
463
+ ctx: t
440
464
  };
441
- (c = e.tenants) != null && c.beforeCreate && (i = await e.tenants.beforeCreate(r, i));
442
- const l = await n.env.data.tenants.create(i);
443
- return (d = e.tenants) != null && d.afterCreate && await e.tenants.afterCreate(r, l), n.json(l, 201);
465
+ (a = n.tenants) != null && a.beforeCreate && (c = await n.tenants.beforeCreate(r, c));
466
+ const l = await t.env.data.tenants.create(c);
467
+ return (o = n.tenants) != null && o.afterCreate && await n.tenants.afterCreate(r, l), t.json(l, 201);
444
468
  } catch (i) {
445
- throw i instanceof j.ZodError ? new p(400, {
469
+ throw i instanceof P.ZodError ? new p(400, {
446
470
  message: "Validation error",
447
471
  cause: i
448
- }) : i instanceof Error && ("code" in i && i.code === "SQLITE_CONSTRAINT_PRIMARYKEY" || (o = i.message) != null && o.includes("UNIQUE constraint failed")) ? new p(409, {
472
+ }) : i instanceof Error && ("code" in i && i.code === "SQLITE_CONSTRAINT_PRIMARYKEY" || (d = i.message) != null && d.includes("UNIQUE constraint failed")) ? new p(409, {
449
473
  message: "Tenant with this ID already exists"
450
474
  }) : i;
451
475
  }
452
- }), s.patch("/:id", async (n) => {
453
- var m, T, _;
454
- const a = n.req.param("id");
455
- if (await ((m = e.onTenantAccessValidation) == null ? void 0 : m.call(e, n, a)) === !1)
456
- throw new p(403, {
457
- message: "Access denied to update this tenant"
458
- });
459
- const d = R.partial().parse(await n.req.json()), { id: o, ...i } = d;
460
- if (!await n.env.data.tenants.get(a))
476
+ }), s.patch("/:id", async (t) => {
477
+ var u, m;
478
+ const a = t.req.param("id");
479
+ if (e.accessControl) {
480
+ const _ = t.var.user;
481
+ if (!(_ != null && _.sub))
482
+ throw new p(401, {
483
+ message: "Authentication required to update tenants"
484
+ });
485
+ const g = e.accessControl.mainTenantId;
486
+ if (a !== g && !(await t.env.data.userOrganizations.listUserOrganizations(
487
+ g,
488
+ _.sub,
489
+ {}
490
+ )).organizations.some((y) => y.id === a))
491
+ throw new p(403, {
492
+ message: "Access denied to update this tenant"
493
+ });
494
+ }
495
+ const o = I.partial().parse(await t.req.json()), { id: d, ...i } = o;
496
+ if (!await t.env.data.tenants.get(a))
461
497
  throw new p(404, {
462
498
  message: "Tenant not found"
463
499
  });
464
- const l = {
465
- adapters: n.env.data,
466
- ctx: n
500
+ const r = {
501
+ adapters: t.env.data,
502
+ ctx: t
467
503
  };
468
- let f = i;
469
- (T = e.tenants) != null && T.beforeUpdate && (f = await e.tenants.beforeUpdate(l, a, i)), await n.env.data.tenants.update(a, f);
470
- const u = await n.env.data.tenants.get(a);
471
- if (!u)
504
+ let l = i;
505
+ (u = n.tenants) != null && u.beforeUpdate && (l = await n.tenants.beforeUpdate(r, a, i)), await t.env.data.tenants.update(a, l);
506
+ const f = await t.env.data.tenants.get(a);
507
+ if (!f)
472
508
  throw new p(404, {
473
509
  message: "Tenant not found after update"
474
510
  });
475
- return (_ = e.tenants) != null && _.afterUpdate && await e.tenants.afterUpdate(l, u), n.json(u);
476
- }), s.delete("/:id", async (n) => {
477
- var o, i, r;
478
- const a = n.req.param("id");
479
- if (t.accessControl && a === t.accessControl.mainTenantId)
511
+ return (m = n.tenants) != null && m.afterUpdate && await n.tenants.afterUpdate(r, f), t.json(f);
512
+ }), s.delete("/:id", async (t) => {
513
+ var i, c;
514
+ const a = t.req.param("id");
515
+ if (e.accessControl && a === e.accessControl.mainTenantId)
480
516
  throw new p(400, {
481
517
  message: "Cannot delete the main tenant"
482
518
  });
483
- if (t.accessControl && await ((o = e.onTenantAccessValidation) == null ? void 0 : o.call(
484
- e,
485
- n,
486
- t.accessControl.mainTenantId
487
- )) === !1)
488
- throw new p(403, {
489
- message: "Access denied to delete tenants"
490
- });
491
- if (!await n.env.data.tenants.get(a))
519
+ if (e.accessControl) {
520
+ const r = t.var.user;
521
+ if (!(r != null && r.sub))
522
+ throw new p(401, {
523
+ message: "Authentication required to delete tenants"
524
+ });
525
+ const l = e.accessControl.mainTenantId;
526
+ if (!(await t.env.data.userOrganizations.listUserOrganizations(
527
+ l,
528
+ r.sub,
529
+ {}
530
+ )).organizations.some((m) => m.id === a))
531
+ throw new p(403, {
532
+ message: "Access denied to delete this tenant"
533
+ });
534
+ }
535
+ if (!await t.env.data.tenants.get(a))
492
536
  throw new p(404, {
493
537
  message: "Tenant not found"
494
538
  });
495
539
  const d = {
496
- adapters: n.env.data,
497
- ctx: n
540
+ adapters: t.env.data,
541
+ ctx: t
498
542
  };
499
- return (i = e.tenants) != null && i.beforeDelete && await e.tenants.beforeDelete(d, a), await n.env.data.tenants.remove(a), (r = e.tenants) != null && r.afterDelete && await e.tenants.afterDelete(d, a), n.body(null, 204);
543
+ return (i = n.tenants) != null && i.beforeDelete && await n.tenants.beforeDelete(d, a), await t.env.data.tenants.remove(a), (c = n.tenants) != null && c.afterDelete && await n.tenants.afterDelete(d, a), t.body(null, 204);
500
544
  }), s;
501
545
  }
502
- function Y(t) {
503
- const e = [
546
+ function L(e) {
547
+ const n = [
504
548
  {
505
549
  pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
506
550
  type: "resource_server"
@@ -508,27 +552,27 @@ function Y(t) {
508
552
  { pattern: /\/api\/v2\/roles\/([^/]+)$/, type: "role" },
509
553
  { pattern: /\/api\/v2\/connections\/([^/]+)$/, type: "connection" }
510
554
  ];
511
- for (const { pattern: s, type: n } of e) {
512
- const a = t.match(s);
555
+ for (const { pattern: s, type: t } of n) {
556
+ const a = e.match(s);
513
557
  if (a && a[1])
514
- return { type: n, id: a[1] };
558
+ return { type: t, id: a[1] };
515
559
  }
516
560
  return null;
517
561
  }
518
- async function B(t, e, s) {
562
+ async function Y(e, n, s) {
519
563
  try {
520
564
  switch (s.type) {
521
565
  case "resource_server": {
522
- const n = await t.resourceServers.get(e, s.id);
523
- return (n == null ? void 0 : n.is_system) === !0;
566
+ const t = await e.resourceServers.get(n, s.id);
567
+ return (t == null ? void 0 : t.is_system) === !0;
524
568
  }
525
569
  case "role": {
526
- const n = await t.roles.get(e, s.id);
527
- return (n == null ? void 0 : n.is_system) === !0;
570
+ const t = await e.roles.get(n, s.id);
571
+ return (t == null ? void 0 : t.is_system) === !0;
528
572
  }
529
573
  case "connection": {
530
- const n = await t.connections.get(e, s.id);
531
- return (n == null ? void 0 : n.is_system) === !0;
574
+ const t = await e.connections.get(n, s.id);
575
+ return (t == null ? void 0 : t.is_system) === !0;
532
576
  }
533
577
  default:
534
578
  return !1;
@@ -537,100 +581,100 @@ async function B(t, e, s) {
537
581
  return !1;
538
582
  }
539
583
  }
540
- function Z(t) {
584
+ function B(e) {
541
585
  return {
542
586
  resource_server: "resource server",
543
587
  role: "role",
544
588
  connection: "connection"
545
- }[t];
589
+ }[e];
546
590
  }
547
- function J() {
548
- return async (t, e) => {
549
- if (!["PATCH", "PUT", "DELETE"].includes(t.req.method))
550
- return e();
551
- const s = Y(t.req.path);
591
+ function Z() {
592
+ return async (e, n) => {
593
+ if (!["PATCH", "PUT", "DELETE"].includes(e.req.method))
594
+ return n();
595
+ const s = L(e.req.path);
552
596
  if (!s)
553
- return e();
554
- const n = t.var.tenant_id || t.req.header("x-tenant-id") || t.req.header("tenant-id");
555
- if (!n)
556
- return e();
557
- if (await B(t.env.data, n, s))
597
+ return n();
598
+ const t = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
599
+ if (!t)
600
+ return n();
601
+ if (await Y(e.env.data, t, s))
558
602
  throw new p(403, {
559
- message: `This ${Z(s.type)} is a system resource and cannot be modified. Make changes in the main tenant instead.`
603
+ message: `This ${B(s.type)} is a system resource and cannot be modified. Make changes in the main tenant instead.`
560
604
  });
561
- return e();
605
+ return n();
562
606
  };
563
607
  }
564
- function X(t) {
565
- return async (e, s) => {
566
- if (!t.accessControl)
608
+ function J(e) {
609
+ return async (n, s) => {
610
+ if (!e.accessControl)
567
611
  return s();
568
- const n = e.var.tenant_id, a = e.var.organization_id;
569
- if (!n)
612
+ const t = n.var.tenant_id, a = n.var.organization_id;
613
+ if (!t)
570
614
  throw new p(400, {
571
615
  message: "Tenant ID not found in request"
572
616
  });
573
617
  if (!E(
574
618
  a,
575
- n,
576
- t.accessControl.mainTenantId
619
+ t,
620
+ e.accessControl.mainTenantId
577
621
  ))
578
622
  throw new p(403, {
579
- message: `Access denied to tenant ${n}`
623
+ message: `Access denied to tenant ${t}`
580
624
  });
581
625
  return s();
582
626
  };
583
627
  }
584
- function H(t) {
585
- return async (e, s) => {
586
- if (!t.subdomainRouting)
628
+ function X(e) {
629
+ return async (n, s) => {
630
+ if (!e.subdomainRouting)
587
631
  return s();
588
632
  const {
589
- baseDomain: n,
633
+ baseDomain: t,
590
634
  reservedSubdomains: a = [],
591
- resolveSubdomain: c
592
- } = t.subdomainRouting, d = e.req.header("host") || "";
593
- let o = null;
594
- if (d.endsWith(n)) {
595
- const r = d.slice(0, -(n.length + 1));
596
- r && !r.includes(".") && (o = r);
597
- }
598
- if (o && a.includes(o) && (o = null), !o)
599
- return t.accessControl && e.set("tenant_id", t.accessControl.mainTenantId), s();
635
+ resolveSubdomain: o
636
+ } = e.subdomainRouting, d = n.req.header("host") || "";
600
637
  let i = null;
601
- if (c)
602
- i = await c(o);
603
- else if (t.subdomainRouting.useOrganizations !== !1 && t.accessControl)
638
+ if (d.endsWith(t)) {
639
+ const r = d.slice(0, -(t.length + 1));
640
+ r && !r.includes(".") && (i = r);
641
+ }
642
+ if (i && a.includes(i) && (i = null), !i)
643
+ return e.accessControl && n.set("tenant_id", e.accessControl.mainTenantId), s();
644
+ let c = null;
645
+ if (o)
646
+ c = await o(i);
647
+ else if (e.subdomainRouting.useOrganizations !== !1 && e.accessControl)
604
648
  try {
605
- const r = await e.env.data.organizations.get(
606
- t.accessControl.mainTenantId,
607
- o
649
+ const r = await n.env.data.organizations.get(
650
+ e.accessControl.mainTenantId,
651
+ i
608
652
  );
609
- r && (i = r.id);
653
+ r && (c = r.id);
610
654
  } catch {
611
655
  }
612
- if (!i)
656
+ if (!c)
613
657
  throw new p(404, {
614
- message: `Tenant not found for subdomain: ${o}`
658
+ message: `Tenant not found for subdomain: ${i}`
615
659
  });
616
- return e.set("tenant_id", i), s();
660
+ return n.set("tenant_id", c), s();
617
661
  };
618
662
  }
619
- function k(t) {
620
- return async (e, s) => {
621
- if (!t.databaseIsolation)
663
+ function H(e) {
664
+ return async (n, s) => {
665
+ if (!e.databaseIsolation)
622
666
  return s();
623
- const n = e.var.tenant_id;
624
- if (!n)
667
+ const t = n.var.tenant_id;
668
+ if (!t)
625
669
  throw new p(400, {
626
670
  message: "Tenant ID not found in request"
627
671
  });
628
672
  try {
629
- const a = await t.databaseIsolation.getAdapters(n);
630
- e.env.data = a;
673
+ const a = await e.databaseIsolation.getAdapters(t);
674
+ n.env.data = a;
631
675
  } catch (a) {
632
676
  throw console.error(
633
- `Failed to resolve database for tenant ${n}:`,
677
+ `Failed to resolve database for tenant ${t}:`,
634
678
  a
635
679
  ), new p(500, {
636
680
  message: "Failed to resolve tenant database"
@@ -639,188 +683,188 @@ function k(t) {
639
683
  return s();
640
684
  };
641
685
  }
642
- function I(t) {
643
- const e = H(t), s = X(t), n = k(t);
644
- return async (a, c) => (await e(a, async () => {
686
+ function M(e) {
687
+ const n = X(e), s = J(e), t = H(e);
688
+ return async (a, o) => (await n(a, async () => {
645
689
  }), await s(a, async () => {
646
- }), await n(a, async () => {
647
- }), c());
690
+ }), await t(a, async () => {
691
+ }), o());
648
692
  }
649
- function re(t) {
650
- const e = b(t);
693
+ function re(e) {
694
+ const n = A(e);
651
695
  return {
652
696
  name: "multi-tenancy",
653
697
  // Apply multi-tenancy middleware for subdomain routing, database resolution, etc.
654
- middleware: I(t),
698
+ middleware: M(e),
655
699
  // Provide lifecycle hooks
656
- hooks: e,
700
+ hooks: n,
657
701
  // Mount tenant management routes
658
702
  routes: [
659
703
  {
660
704
  path: "/management",
661
- handler: S(t, e)
705
+ handler: S(e, n)
662
706
  }
663
707
  ],
664
708
  // Called when plugin is registered
665
709
  onRegister: async () => {
666
- console.log("Multi-tenancy plugin registered"), t.accessControl && console.log(
667
- ` - Access control enabled (main tenant: ${t.accessControl.mainTenantId})`
668
- ), t.subdomainRouting && console.log(
669
- ` - Subdomain routing enabled (base domain: ${t.subdomainRouting.baseDomain})`
670
- ), t.databaseIsolation && console.log(" - Database isolation enabled");
710
+ console.log("Multi-tenancy plugin registered"), e.accessControl && console.log(
711
+ ` - Access control enabled (main tenant: ${e.accessControl.mainTenantId})`
712
+ ), e.subdomainRouting && console.log(
713
+ ` - Subdomain routing enabled (base domain: ${e.subdomainRouting.baseDomain})`
714
+ ), e.databaseIsolation && console.log(" - Database isolation enabled");
671
715
  }
672
716
  };
673
717
  }
674
- function b(t) {
675
- const e = t.accessControl ? O(t.accessControl) : {}, s = t.databaseIsolation ? K(t.databaseIsolation) : {}, n = N(t);
718
+ function A(e) {
719
+ const n = e.accessControl ? j(e.accessControl) : {}, s = e.databaseIsolation ? K(e.databaseIsolation) : {}, t = N(e);
676
720
  return {
677
- ...e,
721
+ ...n,
678
722
  ...s,
679
- tenants: n
723
+ tenants: t
680
724
  };
681
725
  }
682
- function x(t) {
683
- const e = new $(), s = b(t);
684
- return e.route("/tenants", S(t, s)), e;
726
+ function x(e) {
727
+ const n = new $(), s = A(e);
728
+ return n.route("/tenants", S(e, s)), n;
685
729
  }
686
- function ie(t) {
730
+ function ie(e) {
687
731
  return {
688
- hooks: b(t),
689
- middleware: I(t),
690
- app: x(t),
691
- config: t
732
+ hooks: A(e),
733
+ middleware: M(e),
734
+ app: x(e),
735
+ config: e
692
736
  };
693
737
  }
694
- function oe(t) {
738
+ function oe(e) {
695
739
  const {
696
- mainTenantId: e = "main",
740
+ mainTenantId: n = "main",
697
741
  syncResourceServers: s = !0,
698
- multiTenancy: n,
742
+ multiTenancy: t,
699
743
  entityHooks: a,
700
- ...c
701
- } = t, d = {
702
- ...n,
744
+ ...o
745
+ } = e, d = {
746
+ ...t,
703
747
  accessControl: {
704
- mainTenantId: e,
748
+ mainTenantId: n,
705
749
  requireOrganizationMatch: !1,
706
750
  defaultPermissions: ["tenant:admin"],
707
- ...n == null ? void 0 : n.accessControl
751
+ ...t == null ? void 0 : t.accessControl
708
752
  }
709
- }, o = b(d);
710
- let i, r;
711
- s && (i = G({
712
- mainTenantId: e,
713
- getChildTenantIds: async () => (await M(
714
- (y) => t.dataAdapter.tenants.list(y),
753
+ }, i = A(d);
754
+ let c, r;
755
+ s && (c = V({
756
+ mainTenantId: n,
757
+ getChildTenantIds: async () => (await R(
758
+ (h) => e.dataAdapter.tenants.list(h),
715
759
  "tenants",
716
760
  { cursorField: "id", pageSize: 100 }
717
- )).filter((y) => y.id !== e).map((y) => y.id),
718
- getAdapters: async (g) => t.dataAdapter
719
- }), r = L({
720
- mainTenantId: e,
721
- getMainTenantAdapters: async () => t.dataAdapter,
722
- getAdapters: async (g) => t.dataAdapter
761
+ )).filter((h) => h.id !== n).map((h) => h.id),
762
+ getAdapters: async (y) => e.dataAdapter
763
+ }), r = G({
764
+ mainTenantId: n,
765
+ getMainTenantAdapters: async () => e.dataAdapter,
766
+ getAdapters: async (y) => e.dataAdapter
723
767
  }));
724
- const l = async (g, y, ...h) => {
725
- const v = [];
726
- if (g)
768
+ const l = async (y, h, ...v) => {
769
+ const T = [];
770
+ if (y)
727
771
  try {
728
- await g(...h);
729
- } catch (A) {
730
- v.push(A instanceof Error ? A : new Error(String(A)));
772
+ await y(...v);
773
+ } catch (b) {
774
+ T.push(b instanceof Error ? b : new Error(String(b)));
731
775
  }
732
- if (y)
776
+ if (h)
733
777
  try {
734
- await y(...h);
735
- } catch (A) {
736
- v.push(A instanceof Error ? A : new Error(String(A)));
778
+ await h(...v);
779
+ } catch (b) {
780
+ T.push(b instanceof Error ? b : new Error(String(b)));
737
781
  }
738
- if (v.length === 1)
739
- throw v[0];
740
- if (v.length > 1)
782
+ if (T.length === 1)
783
+ throw T[0];
784
+ if (T.length > 1)
741
785
  throw new AggregateError(
742
- v,
743
- `Multiple hook errors: ${v.map((A) => A.message).join("; ")}`
786
+ T,
787
+ `Multiple hook errors: ${T.map((b) => b.message).join("; ")}`
744
788
  );
745
789
  }, f = {
746
790
  ...a,
747
- resourceServers: i ? {
791
+ resourceServers: c ? {
748
792
  ...a == null ? void 0 : a.resourceServers,
749
- afterCreate: async (g, y) => {
750
- var h;
793
+ afterCreate: async (y, h) => {
794
+ var v;
751
795
  await l(
752
- (h = a == null ? void 0 : a.resourceServers) == null ? void 0 : h.afterCreate,
753
- i == null ? void 0 : i.afterCreate,
754
- g,
755
- y
796
+ (v = a == null ? void 0 : a.resourceServers) == null ? void 0 : v.afterCreate,
797
+ c == null ? void 0 : c.afterCreate,
798
+ y,
799
+ h
756
800
  );
757
801
  },
758
- afterUpdate: async (g, y, h) => {
759
- var v;
802
+ afterUpdate: async (y, h, v) => {
803
+ var T;
760
804
  await l(
761
- (v = a == null ? void 0 : a.resourceServers) == null ? void 0 : v.afterUpdate,
762
- i == null ? void 0 : i.afterUpdate,
763
- g,
805
+ (T = a == null ? void 0 : a.resourceServers) == null ? void 0 : T.afterUpdate,
806
+ c == null ? void 0 : c.afterUpdate,
764
807
  y,
765
- h
808
+ h,
809
+ v
766
810
  );
767
811
  },
768
- afterDelete: async (g, y) => {
769
- var h;
812
+ afterDelete: async (y, h) => {
813
+ var v;
770
814
  await l(
771
- (h = a == null ? void 0 : a.resourceServers) == null ? void 0 : h.afterDelete,
772
- i == null ? void 0 : i.afterDelete,
773
- g,
774
- y
815
+ (v = a == null ? void 0 : a.resourceServers) == null ? void 0 : v.afterDelete,
816
+ c == null ? void 0 : c.afterDelete,
817
+ y,
818
+ h
775
819
  );
776
820
  }
777
821
  } : a == null ? void 0 : a.resourceServers,
778
822
  tenants: r ? {
779
823
  ...a == null ? void 0 : a.tenants,
780
- afterCreate: async (g, y) => {
781
- var h;
824
+ afterCreate: async (y, h) => {
825
+ var v;
782
826
  await l(
783
- (h = a == null ? void 0 : a.tenants) == null ? void 0 : h.afterCreate,
827
+ (v = a == null ? void 0 : a.tenants) == null ? void 0 : v.afterCreate,
784
828
  r == null ? void 0 : r.afterCreate,
785
- g,
786
- y
829
+ y,
830
+ h
787
831
  );
788
832
  }
789
833
  } : a == null ? void 0 : a.tenants
790
- }, u = P({
791
- ...c,
834
+ }, u = F({
835
+ ...o,
792
836
  entityHooks: f
793
- }), { app: m, managementApp: T, ..._ } = u, w = new $();
794
- w.use("/api/v2/*", J()), w.route("/", m);
795
- const z = S(
837
+ }), { app: m, managementApp: _, ...g } = u, w = new $();
838
+ w.use("/api/v2/*", Z()), w.route("/", m);
839
+ const C = S(
796
840
  d,
797
- o
841
+ i
798
842
  );
799
- return w.route("/api/v2/tenants", z), {
843
+ return w.route("/api/v2/tenants", C), {
800
844
  app: w,
801
- managementApp: T,
802
- ..._,
845
+ managementApp: _,
846
+ ...g,
803
847
  multiTenancyConfig: d,
804
- multiTenancyHooks: o
848
+ multiTenancyHooks: i
805
849
  };
806
850
  }
807
851
  export {
808
852
  le as MANAGEMENT_API_SCOPES,
809
- O as createAccessControlHooks,
810
- X as createAccessControlMiddleware,
853
+ j as createAccessControlHooks,
854
+ J as createAccessControlMiddleware,
811
855
  K as createDatabaseHooks,
812
- k as createDatabaseMiddleware,
856
+ H as createDatabaseMiddleware,
813
857
  x as createMultiTenancy,
814
- b as createMultiTenancyHooks,
815
- I as createMultiTenancyMiddleware,
858
+ A as createMultiTenancyHooks,
859
+ M as createMultiTenancyMiddleware,
816
860
  re as createMultiTenancyPlugin,
817
- J as createProtectSyncedMiddleware,
861
+ Z as createProtectSyncedMiddleware,
818
862
  N as createProvisioningHooks,
819
- G as createResourceServerSyncHooks,
820
- H as createSubdomainMiddleware,
821
- L as createTenantResourceServerSyncHooks,
863
+ V as createResourceServerSyncHooks,
864
+ X as createSubdomainMiddleware,
865
+ G as createTenantResourceServerSyncHooks,
822
866
  S as createTenantsRouter,
823
- M as fetchAll,
867
+ R as fetchAll,
824
868
  oe as init,
825
869
  ue as seed,
826
870
  ie as setupMultiTenancy,
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "type": "git",
12
12
  "url": "https://github.com/markusahlstrand/authhero"
13
13
  },
14
- "version": "13.5.0",
14
+ "version": "13.6.0",
15
15
  "description": "Multi-tenancy support for AuthHero with organization-based access control and per-tenant database isolation",
16
16
  "files": [
17
17
  "dist"
@@ -37,12 +37,12 @@
37
37
  "typescript": "^5.6.0",
38
38
  "vite": "^6.0.0",
39
39
  "vitest": "^2.1.0",
40
- "@authhero/kysely-adapter": "10.71.0"
40
+ "@authhero/kysely-adapter": "10.72.0"
41
41
  },
42
42
  "dependencies": {
43
43
  "zod": "^3.24.0",
44
44
  "@authhero/adapter-interfaces": "0.112.0",
45
- "authhero": "0.303.0"
45
+ "authhero": "0.304.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@hono/zod-openapi": "^0.19.10",