@authhero/multi-tenancy 14.6.0 → 14.7.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/multi-tenancy.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var ae=Object.defineProperty;var re=(t,e,n)=>e in t?ae(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var D=(t,e,n)=>re(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const se=require("hono"),y=require("authhero"),S=require("@hono/zod-openapi");function B(t){const{controlPlaneTenantId:e,requireOrganizationMatch:n=!0}=t;return{async onTenantAccessValidation(a,s){if(s===e)return!0;if(n){const c=a.var.org_name,l=a.var.organization_id,r=c||l;return r?r.toLowerCase()===s.toLowerCase():!1}return!0}}}function K(t,e,n,a){if(e===n)return!0;const s=a||t;return s?s.toLowerCase()===e.toLowerCase():!1}function V(t){return{async resolveDataAdapters(e){try{return await t.getAdapters(e)}catch(n){console.error(`Failed to resolve data adapters for tenant ${e}:`,n);return}}}}function oe(t){return`urn:authhero:tenant:${t.toLowerCase()}`}function W(t){return{async beforeCreate(e,n){return!n.audience&&n.id?{...n,audience:oe(n.id)}:n},async afterCreate(e,n){const{accessControl:a,databaseIsolation:s}=t;a&&e.ctx&&await ie(e,n,a),s!=null&&s.onProvision&&await s.onProvision(n.id)},async beforeDelete(e,n){const{accessControl:a,databaseIsolation:s}=t;if(a)try{const l=(await e.adapters.organizations.list(a.controlPlaneTenantId)).organizations.find(r=>r.name===n);l&&await e.adapters.organizations.remove(a.controlPlaneTenantId,l.id)}catch(c){console.warn(`Failed to remove organization for tenant ${n}:`,c)}if(s!=null&&s.onDeprovision)try{await s.onDeprovision(n)}catch(c){console.warn(`Failed to deprovision database for tenant ${n}:`,c)}}}}async function ie(t,e,n){const{controlPlaneTenantId:a,defaultPermissions:s,defaultRoles:c,issuer:l,adminRoleName:r="Tenant Admin",adminRoleDescription:p="Full access to all tenant management operations",addCreatorToOrganization:o=!0}=n,i=await t.adapters.organizations.create(a,{name:e.id,display_name:e.friendly_name||e.id});let f;if(l&&(f=await le(t,a,r,p)),o&&t.ctx){const d=t.ctx.var.user;if(d!=null&&d.sub&&!await ce(t,a,d.sub))try{await t.adapters.userOrganizations.create(a,{user_id:d.sub,organization_id:i.id}),f&&await t.adapters.userRoles.create(a,d.sub,f,i.id)}catch(m){console.warn(`Failed to add creator ${d.sub} to organization ${i.id}:`,m)}}c&&c.length>0&&console.log(`Would assign roles ${c.join(", ")} to organization ${i.id}`),s&&s.length>0&&console.log(`Would grant permissions ${s.join(", ")} to organization ${i.id}`)}async function ce(t,e,n){const a=await t.adapters.userRoles.list(e,n,void 0,"");for(const s of a)if((await t.adapters.rolePermissions.list(e,s.id,{per_page:1e3})).some(r=>r.permission_name==="admin:organizations"))return!0;return!1}async function le(t,e,n,a){const c=(await t.adapters.roles.list(e,{})).roles.find(o=>o.name===n);if(c)return c.id;const l=await t.adapters.roles.create(e,{name:n,description:a}),r=y.MANAGEMENT_API_AUDIENCE,p=y.MANAGEMENT_API_SCOPES.map(o=>({role_id:l.id,resource_server_identifier:r,permission_name:o.value}));return await t.adapters.rolePermissions.assign(e,l.id,p),l.id}function N(t,e,n=()=>!0){const{controlPlaneTenantId:a,getChildTenantIds:s,getAdapters:c}=t,l=new Map;async function r(i,f,d){return(await e(i).list(f,{q:`name:${d}`,per_page:1}))[0]??null}async function p(i){const f=await s(),d=e(await c(a));await Promise.all(f.map(async u=>{try{const m=await c(u),g=e(m),w={...d.transform(i),is_system:!0},h=await r(m,u,i.name),_=h?g.getId(h):void 0;if(h&&_){const A=g.preserveOnUpdate?g.preserveOnUpdate(h,w):w;await g.update(u,_,A)}else await g.create(u,w)}catch(m){console.error(`Failed to sync ${d.listKey} "${i.name}" to tenant "${u}":`,m)}}))}async function o(i){const f=await s();await Promise.all(f.map(async d=>{try{const u=await c(d),m=e(u),g=await r(u,d,i),v=g?m.getId(g):void 0;g&&v&&await m.remove(d,v)}catch(u){console.error(`Failed to delete entity "${i}" from tenant "${d}":`,u)}}))}return{afterCreate:async(i,f)=>{i.tenantId===a&&n(f)&&await p(f)},afterUpdate:async(i,f,d)=>{i.tenantId===a&&n(d)&&await p(d)},beforeDelete:async(i,f)=>{if(i.tenantId!==a)return;const u=await e(i.adapters).get(i.tenantId,f);u&&n(u)&&l.set(f,u)},afterDelete:async(i,f)=>{if(i.tenantId!==a)return;const d=l.get(f);d&&(l.delete(f),await o(d.name))}}}function H(t,e,n=()=>!0){const{controlPlaneTenantId:a,getControlPlaneAdapters:s,getAdapters:c}=t;return{async afterCreate(l,r){if(r.id!==a)try{const p=await s(),o=await c(r.id),i=e(p),f=e(o),d=await y.fetchAll(u=>i.listPaginated(a,u),i.listKey,{cursorField:"id",pageSize:100});await Promise.all(d.filter(u=>n(u)).map(async u=>{try{const m=i.transform(u);await f.create(r.id,{...m,is_system:!0})}catch(m){console.error(`Failed to sync entity to new tenant "${r.id}":`,m)}}))}catch(p){console.error(`Failed to sync entities to new tenant "${r.id}":`,p)}}}}const G=t=>({list:async(e,n)=>(await t.resourceServers.list(e,n)).resource_servers,listPaginated:(e,n)=>t.resourceServers.list(e,n),get:(e,n)=>t.resourceServers.get(e,n),create:(e,n)=>t.resourceServers.create(e,n),update:(e,n,a)=>t.resourceServers.update(e,n,a),remove:(e,n)=>t.resourceServers.remove(e,n),listKey:"resource_servers",getId:e=>e.id,transform:e=>({id:e.id,name:e.name,identifier:e.identifier,scopes:e.scopes,signing_alg:e.signing_alg,token_lifetime:e.token_lifetime,token_lifetime_for_web:e.token_lifetime_for_web})}),L=t=>({list:async(e,n)=>(await t.roles.list(e,n)).roles,listPaginated:(e,n)=>t.roles.list(e,n),get:(e,n)=>t.roles.get(e,n),create:(e,n)=>t.roles.create(e,n),update:(e,n,a)=>t.roles.update(e,n,a),remove:(e,n)=>t.roles.remove(e,n),listKey:"roles",getId:e=>e.id,transform:e=>({id:e.id,name:e.name,description:e.description})});function U(t){var e;return((e=t.metadata)==null?void 0:e.sync)!==!1}function Q(t){const{sync:e={},filters:n={}}=t,a=e.resourceServers??!0,s=e.roles??!0,c=m=>U(m)?n.resourceServers?n.resourceServers(m):!0:!1,l=m=>U(m)?n.roles?n.roles(m):!0:!1,r=a?N(t,G,c):void 0,p=s?N(t,L,l):void 0,o=a?H(t,G,c):void 0,i=s?H(t,L,l):void 0,f=s?{async afterCreate(m,g){var v;if(g.id!==t.controlPlaneTenantId){await((v=i==null?void 0:i.afterCreate)==null?void 0:v.call(i,m,g));try{const w=await t.getControlPlaneAdapters(),h=await t.getAdapters(g.id),_=await y.fetchAll(b=>w.roles.list(t.controlPlaneTenantId,b),"roles",{cursorField:"id",pageSize:100}),A=new Map;for(const b of _.filter(T=>{var C;return((C=n.roles)==null?void 0:C.call(n,T))??!0})){const T=await d(h,g.id,b.name);T&&A.set(b.name,T.id)}for(const b of _.filter(T=>{var C;return((C=n.roles)==null?void 0:C.call(n,T))??!0})){const T=A.get(b.name);if(T)try{const C=await w.rolePermissions.list(t.controlPlaneTenantId,b.id,{});C.length>0&&await h.rolePermissions.assign(g.id,T,C.map(P=>({role_id:T,resource_server_identifier:P.resource_server_identifier,permission_name:P.permission_name})))}catch(C){console.error(`Failed to sync permissions for role "${b.name}" to tenant "${g.id}":`,C)}}}catch(w){console.error(`Failed to sync role permissions to tenant "${g.id}":`,w)}}}}:void 0;async function d(m,g,v){return(await m.roles.list(g,{q:`name:${v}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:r,roles:p},tenantHooks:{async afterCreate(m,g){const v=[o==null?void 0:o.afterCreate,(f==null?void 0:f.afterCreate)??(i==null?void 0:i.afterCreate)],w=[];for(const h of v)if(h)try{await h(m,g)}catch(_){w.push(_ instanceof Error?_:new Error(String(_)))}if(w.length===1)throw w[0];if(w.length>1)throw new AggregateError(w,w.map(h=>h.message).join("; "))}}}}var I=class extends Error{constructor(e=500,n){super(n==null?void 0:n.message,{cause:n==null?void 0:n.cause});D(this,"res");D(this,"status");this.res=n==null?void 0:n.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 $(t,e){const n=new S.OpenAPIHono;return n.openapi(S.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:y.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:S.z.object({tenants:S.z.array(y.tenantSchema),start:S.z.number().optional(),limit:S.z.number().optional(),length:S.z.number().optional()})}},description:"List of tenants"}}}),async a=>{var m,g,v,w,h,_;const s=a.req.valid("query"),{page:c,per_page:l,include_totals:r,q:p}=s,o=a.var.user,i=(o==null?void 0:o.permissions)||[];if(i.includes("auth:read")||i.includes("admin:organizations")){const A=await a.env.data.tenants.list({page:c,per_page:l,include_totals:r,q:p});return r?a.json({tenants:A.tenants,start:((m=A.totals)==null?void 0:m.start)??0,limit:((g=A.totals)==null?void 0:g.limit)??l,length:A.tenants.length}):a.json({tenants:A.tenants})}const d=((v=t.accessControl)==null?void 0:v.controlPlaneTenantId)??((w=a.env.data.multiTenancyConfig)==null?void 0:w.controlPlaneTenantId);if(d&&(o!=null&&o.sub)){const b=(await y.fetchAll(O=>a.env.data.userOrganizations.listUserOrganizations(d,o.sub,O),"organizations")).map(O=>O.name);if(b.length===0)return r?a.json({tenants:[],start:0,limit:l??50,length:0}):a.json({tenants:[]});const T=b.length,C=c??0,P=l??50,z=C*P,M=b.slice(z,z+P);if(M.length===0)return r?a.json({tenants:[],start:z,limit:P,length:T}):a.json({tenants:[]});const E=M.map(O=>`id:${O}`).join(" OR "),ne=p?`(${E}) AND (${p})`:E,j=await a.env.data.tenants.list({q:ne,per_page:P,include_totals:!1});return r?a.json({tenants:j.tenants,start:z,limit:P,length:T}):a.json({tenants:j.tenants})}const u=await a.env.data.tenants.list({page:c,per_page:l,include_totals:r,q:p});return r?a.json({tenants:u.tenants,start:((h=u.totals)==null?void 0:h.start)??0,limit:((_=u.totals)==null?void 0:_.limit)??l,length:u.tenants.length}):a.json({tenants:u.tenants})}),n.openapi(S.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:y.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:y.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async a=>{var p,o;const s=a.var.user;if(!(s!=null&&s.sub))throw new I(401,{message:"Authentication required to create tenants"});let c=a.req.valid("json");const l={adapters:a.env.data,ctx:a};(p=e.tenants)!=null&&p.beforeCreate&&(c=await e.tenants.beforeCreate(l,c));const r=await a.env.data.tenants.create(c);return(o=e.tenants)!=null&&o.afterCreate&&await e.tenants.afterCreate(l,r),a.json(r,201)}),n.openapi(S.createRoute({tags:["tenants"],method:"delete",path:"/{id}",request:{params:S.z.object({id:S.z.string()})},security:[{Bearer:["delete:tenants"]}],responses:{204:{description:"Tenant deleted"},403:{description:"Access denied or cannot delete the control plane"},404:{description:"Tenant not found"}}}),async a=>{var p,o,i,f;const{id:s}=a.req.valid("param"),c=((p=t.accessControl)==null?void 0:p.controlPlaneTenantId)??((o=a.env.data.multiTenancyConfig)==null?void 0:o.controlPlaneTenantId);if(c){const d=a.var.user;if(!(d!=null&&d.sub))throw new I(401,{message:"Authentication required"});if(s===c)throw new I(403,{message:"Cannot delete the control plane"});if(!(await y.fetchAll(g=>a.env.data.userOrganizations.listUserOrganizations(c,d.sub,g),"organizations")).some(g=>g.name===s))throw new I(403,{message:"Access denied to this tenant"})}if(!await a.env.data.tenants.get(s))throw new I(404,{message:"Tenant not found"});const r={adapters:a.env.data,ctx:a};return(i=e.tenants)!=null&&i.beforeDelete&&await e.tenants.beforeDelete(r,s),await a.env.data.tenants.remove(s),(f=e.tenants)!=null&&f.afterDelete&&await e.tenants.afterDelete(r,s),a.body(null,204)}),n}function de(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:n,type:a}of e){const s=t.match(n);if(s&&s[1])return{type:a,id:s[1]}}return null}async function ue(t,e,n){try{switch(n.type){case"resource_server":{const a=await t.resourceServers.get(e,n.id);return(a==null?void 0:a.is_system)===!0}case"role":{const a=await t.roles.get(e,n.id);return(a==null?void 0:a.is_system)===!0}case"connection":{const a=await t.connections.get(e,n.id);return(a==null?void 0:a.is_system)===!0}default:return!1}}catch{return!1}}function fe(t){return{resource_server:"resource server",role:"role",connection:"connection"}[t]}function J(){return async(t,e)=>{if(!["PATCH","PUT","DELETE"].includes(t.req.method))return e();const n=de(t.req.path);if(!n)return e();const a=t.var.tenant_id||t.req.header("x-tenant-id")||t.req.header("tenant-id");if(!a)return e();if(await ue(t.env.data,a,n))throw new I(403,{message:`This ${fe(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return e()}}const me=["client_secret","app_secret","twilio_token"];function q(t){if(!t)return t;const e={...t};for(const n of me)delete e[n];return e}function X(t,e){const{controlPlaneTenantId:n,controlPlaneClientId:a,excludeSensitiveFields:s=!1}=e;return{...t,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:a},legacyClients:{...t.legacyClients,get:async c=>{var d;const l=await t.legacyClients.get(c);if(!l)return null;const r=a?await t.legacyClients.get(a):void 0,p=await t.connections.list(l.tenant.id),o=n?await t.connections.list(n):{connections:[]},i=p.connections.map(u=>{var w;const m=(w=o.connections)==null?void 0:w.find(h=>h.strategy===u.strategy);if(!(m!=null&&m.options))return u;const g=y.connectionSchema.parse({...m||{},...u}),v=s?q(m.options):m.options;return g.options=y.connectionOptionsSchema.parse({...v||{},...u.options}),g}).filter(u=>u),f={...(r==null?void 0:r.tenant)||{},...l.tenant};return!l.tenant.audience&&((d=r==null?void 0:r.tenant)!=null&&d.audience)&&(f.audience=r.tenant.audience),{...l,web_origins:[...(r==null?void 0:r.web_origins)||[],...l.web_origins||[]],allowed_logout_urls:[...(r==null?void 0:r.allowed_logout_urls)||[],...l.allowed_logout_urls||[]],callbacks:[...(r==null?void 0:r.callbacks)||[],...l.callbacks||[]],connections:i,tenant:f}}},connections:{...t.connections,get:async(c,l)=>{var d;const r=await t.connections.get(c,l);if(!r||!n||c===n)return r;const o=(d=(await t.connections.list(n)).connections)==null?void 0:d.find(u=>u.strategy===r.strategy);if(!(o!=null&&o.options))return r;const i=y.connectionSchema.parse({...o,...r}),f=s?q(o.options):o.options;return i.options=y.connectionOptionsSchema.parse({...f||{},...r.options}),i},list:async(c,l)=>{const r=await t.connections.list(c,l);if(!n||c===n)return r;const p=await t.connections.list(n),o=r.connections.map(i=>{var m;const f=(m=p.connections)==null?void 0:m.find(g=>g.strategy===i.strategy);if(!(f!=null&&f.options))return i;const d=y.connectionSchema.parse({...f,...i}),u=s?q(f.options):f.options;return d.options=y.connectionOptionsSchema.parse({...u||{},...i.options}),d});return{...r,connections:o}}}}}function R(t,e){return X(t,e)}function Y(t){return async(e,n)=>{const a=e.var.user;return(a==null?void 0:a.tenant_id)===t&&a.org_name&&e.set("tenant_id",a.org_name),n()}}function Z(t){return async(e,n)=>{if(!t.accessControl)return n();const{controlPlaneTenantId:a}=t.accessControl,s=e.var.org_name,c=e.var.organization_id,l=s||c;let r=e.var.tenant_id;const p=e.var.user,i=(p!=null&&p.aud?Array.isArray(p.aud)?p.aud:[p.aud]:[]).includes(y.MANAGEMENT_API_AUDIENCE);if(!r&&l&&i&&(e.set("tenant_id",l),r=l),!r)throw new I(400,{message:"Tenant ID not found in request"});if(!K(c,r,a,s))throw new I(403,{message:`Access denied to tenant ${r}`});return n()}}function x(t){return async(e,n)=>{if(!t.subdomainRouting)return n();const{baseDomain:a,reservedSubdomains:s=[],resolveSubdomain:c}=t.subdomainRouting,l=e.req.header("host")||"";let r=null;if(l.endsWith(a)){const o=l.slice(0,-(a.length+1));o&&!o.includes(".")&&(r=o)}if(r&&s.includes(r)&&(r=null),!r)return t.accessControl&&e.set("tenant_id",t.accessControl.controlPlaneTenantId),n();let p=null;if(c)p=await c(r);else if(t.subdomainRouting.useOrganizations!==!1&&t.accessControl)try{const o=await e.env.data.organizations.get(t.accessControl.controlPlaneTenantId,r);o&&(p=o.id)}catch{}if(!p)throw new I(404,{message:`Tenant not found for subdomain: ${r}`});return e.set("tenant_id",p),n()}}function ee(t){return async(e,n)=>{if(!t.databaseIsolation)return n();const a=e.var.tenant_id;if(!a)throw new I(400,{message:"Tenant ID not found in request"});try{const s=await t.databaseIsolation.getAdapters(a);e.env.data=s}catch(s){throw console.error(`Failed to resolve database for tenant ${a}:`,s),new I(500,{message:"Failed to resolve tenant database"})}return n()}}function k(t){const e=x(t),n=Z(t),a=ee(t);return async(s,c)=>(await e(s,async()=>{}),await n(s,async()=>{}),await a(s,async()=>{}),c())}function pe(t){const{dataAdapter:e,controlPlane:n,controlPlane:{tenantId:a="control_plane",clientId:s}={},sync:c={resourceServers:!0,roles:!0},defaultPermissions:l=["tenant:admin"],requireOrganizationMatch:r=!1,managementApiExtensions:p=[],entityHooks:o,getChildTenantIds:i,getAdapters:f,...d}=t;let u=e,m=e;n&&(u=R(e,{controlPlaneTenantId:a,controlPlaneClientId:s}),m=R(e,{controlPlaneTenantId:a,controlPlaneClientId:s,excludeSensitiveFields:!0}));const g=c!==!1,v=g?{resourceServers:c.resourceServers??!0,roles:c.roles??!0}:{resourceServers:!1,roles:!1},_={controlPlaneTenantId:a,getChildTenantIds:i??(async()=>(await y.fetchAll(M=>u.tenants.list(M),"tenants",{cursorField:"id",pageSize:100})).filter(M=>M.id!==a).map(M=>M.id)),getAdapters:f??(async()=>u),getControlPlaneAdapters:async()=>u,sync:v},{entityHooks:A,tenantHooks:b}=Q(_),T={resourceServers:[A.resourceServers,...(o==null?void 0:o.resourceServers)??[]],roles:[A.roles,...(o==null?void 0:o.roles)??[]],connections:(o==null?void 0:o.connections)??[],tenants:(o==null?void 0:o.tenants)??[],rolePermissions:(o==null?void 0:o.rolePermissions)??[]},C=$({accessControl:{controlPlaneTenantId:a,requireOrganizationMatch:r,defaultPermissions:l}},{tenants:b}),{app:P}=y.init({dataAdapter:u,managementDataAdapter:m,...d,entityHooks:T,managementApiExtensions:[...p,{path:"/tenants",router:C}]});return P.use("/api/v2/*",Y(a)),g&&P.use("/api/v2/*",J()),{app:P,controlPlaneTenantId:a}}function ge(t){const e=F(t);return{name:"multi-tenancy",middleware:k(t),hooks:e,routes:[{path:"/management",handler:$(t,e)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),t.accessControl&&console.log(` - Access control enabled (control plane: ${t.accessControl.controlPlaneTenantId})`),t.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${t.subdomainRouting.baseDomain})`),t.databaseIsolation&&console.log(" - Database isolation enabled")}}}function F(t){const e=t.accessControl?B(t.accessControl):{},n=t.databaseIsolation?V(t.databaseIsolation):{},a=W(t);return{...e,...n,tenants:a}}function te(t){const e=new se.Hono,n=F(t);return e.route("/tenants",$(t,n)),e}function we(t){return{hooks:F(t),middleware:k(t),app:te(t),config:t,wrapAdapters:(e,n)=>{var a;return R(e,{controlPlaneTenantId:(a=t.accessControl)==null?void 0:a.controlPlaneTenantId,controlPlaneClientId:n==null?void 0:n.controlPlaneClientId})}}}exports.createAccessControlHooks=B;exports.createAccessControlMiddleware=Z;exports.createControlPlaneTenantMiddleware=Y;exports.createDatabaseHooks=V;exports.createDatabaseMiddleware=ee;exports.createMultiTenancy=te;exports.createMultiTenancyHooks=F;exports.createMultiTenancyMiddleware=k;exports.createMultiTenancyPlugin=ge;exports.createProtectSyncedMiddleware=J;exports.createProvisioningHooks=W;exports.createRuntimeFallbackAdapter=X;exports.createSubdomainMiddleware=x;exports.createSyncHooks=Q;exports.createTenantsOpenAPIRouter=$;exports.initMultiTenant=pe;exports.setupMultiTenancy=we;exports.validateTenantAccess=K;exports.withRuntimeFallback=R;
|
|
1
|
+
"use strict";var re=Object.defineProperty;var ae=(t,e,n)=>e in t?re(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var D=(t,e,n)=>ae(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const se=require("hono"),y=require("authhero"),I=require("@hono/zod-openapi");function B(t){const{controlPlaneTenantId:e,requireOrganizationMatch:n=!0}=t;return{async onTenantAccessValidation(r,a){if(a===e)return!0;if(n){const c=r.var.org_name,d=r.var.organization_id,s=c||d;return s?s.toLowerCase()===a.toLowerCase():!1}return!0}}}function K(t,e,n,r){if(e===n)return!0;const a=r||t;return a?a.toLowerCase()===e.toLowerCase():!1}function V(t){return{async resolveDataAdapters(e){try{return await t.getAdapters(e)}catch(n){console.error(`Failed to resolve data adapters for tenant ${e}:`,n);return}}}}function oe(t){return`urn:authhero:tenant:${t.toLowerCase()}`}function W(t){return{async beforeCreate(e,n){return!n.audience&&n.id?{...n,audience:oe(n.id)}:n},async afterCreate(e,n){const{accessControl:r,databaseIsolation:a}=t;r&&e.ctx&&await ie(e,n,r),a!=null&&a.onProvision&&await a.onProvision(n.id)},async beforeDelete(e,n){const{accessControl:r,databaseIsolation:a}=t;if(r)try{const d=(await e.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find(s=>s.name===n);d&&await e.adapters.organizations.remove(r.controlPlaneTenantId,d.id)}catch(c){console.warn(`Failed to remove organization for tenant ${n}:`,c)}if(a!=null&&a.onDeprovision)try{await a.onDeprovision(n)}catch(c){console.warn(`Failed to deprovision database for tenant ${n}:`,c)}}}}async function ie(t,e,n){const{controlPlaneTenantId:r,defaultPermissions:a,defaultRoles:c,issuer:d,adminRoleName:s="Tenant Admin",adminRoleDescription:f="Full access to all tenant management operations",addCreatorToOrganization:o=!0}=n,i=await t.adapters.organizations.create(r,{name:e.id,display_name:e.friendly_name||e.id});let u;if(d&&(u=await le(t,r,s,f)),o&&t.ctx){const l=t.ctx.var.user;if(l!=null&&l.sub&&!await ce(t,r,l.sub))try{await t.adapters.userOrganizations.create(r,{user_id:l.sub,organization_id:i.id}),u&&await t.adapters.userRoles.create(r,l.sub,u,i.id)}catch(p){console.warn(`Failed to add creator ${l.sub} to organization ${i.id}:`,p)}}c&&c.length>0&&console.log(`Would assign roles ${c.join(", ")} to organization ${i.id}`),a&&a.length>0&&console.log(`Would grant permissions ${a.join(", ")} to organization ${i.id}`)}async function ce(t,e,n){const r=await t.adapters.userRoles.list(e,n,void 0,"");for(const a of r)if((await t.adapters.rolePermissions.list(e,a.id,{per_page:1e3})).some(s=>s.permission_name==="admin:organizations"))return!0;return!1}async function le(t,e,n,r){const c=(await t.adapters.roles.list(e,{})).roles.find(o=>o.name===n);if(c)return c.id;const d=await t.adapters.roles.create(e,{name:n,description:r}),s=y.MANAGEMENT_API_AUDIENCE,f=y.MANAGEMENT_API_SCOPES.map(o=>({role_id:d.id,resource_server_identifier:s,permission_name:o.value}));return await t.adapters.rolePermissions.assign(e,d.id,f),d.id}function k(t,e,n=()=>!0){const{controlPlaneTenantId:r,getChildTenantIds:a,getAdapters:c}=t,d=new Map;async function s(i,u,l){return(await e(i).list(u,{q:`name:${l}`,per_page:1}))[0]??null}async function f(i){const u=await a(),l=e(await c(r));await Promise.all(u.map(async m=>{try{const p=await c(m),g=e(p),w={...l.transform(i),is_system:!0},h=await s(p,m,i.name),A=h?g.getId(h):void 0;if(h&&A){const P=g.preserveOnUpdate?g.preserveOnUpdate(h,w):w;await g.update(m,A,P)}else await g.create(m,w)}catch(p){console.error(`Failed to sync ${l.listKey} "${i.name}" to tenant "${m}":`,p)}}))}async function o(i){const u=await a();await Promise.all(u.map(async l=>{try{const m=await c(l),p=e(m),g=await s(m,l,i),v=g?p.getId(g):void 0;g&&v&&await p.remove(l,v)}catch(m){console.error(`Failed to delete entity "${i}" from tenant "${l}":`,m)}}))}return{afterCreate:async(i,u)=>{i.tenantId===r&&n(u)&&await f(u)},afterUpdate:async(i,u,l)=>{i.tenantId===r&&n(l)&&await f(l)},beforeDelete:async(i,u)=>{if(i.tenantId!==r)return;const m=await e(i.adapters).get(i.tenantId,u);m&&n(m)&&d.set(u,m)},afterDelete:async(i,u)=>{if(i.tenantId!==r)return;const l=d.get(u);l&&(d.delete(u),await o(l.name))}}}function N(t,e,n=()=>!0){const{controlPlaneTenantId:r,getControlPlaneAdapters:a,getAdapters:c}=t;return{async afterCreate(d,s){if(s.id!==r)try{const f=await a(),o=await c(s.id),i=e(f),u=e(o),l=await y.fetchAll(m=>i.listPaginated(r,m),i.listKey,{cursorField:"id",pageSize:100});await Promise.all(l.filter(m=>n(m)).map(async m=>{try{const p=i.transform(m);await u.create(s.id,{...p,is_system:!0})}catch(p){console.error(`Failed to sync entity to new tenant "${s.id}":`,p)}}))}catch(f){console.error(`Failed to sync entities to new tenant "${s.id}":`,f)}}}}const H=t=>({list:async(e,n)=>(await t.resourceServers.list(e,n)).resource_servers,listPaginated:(e,n)=>t.resourceServers.list(e,n),get:(e,n)=>t.resourceServers.get(e,n),create:(e,n)=>t.resourceServers.create(e,n),update:(e,n,r)=>t.resourceServers.update(e,n,r),remove:(e,n)=>t.resourceServers.remove(e,n),listKey:"resource_servers",getId:e=>e.id,transform:e=>({id:e.id,name:e.name,identifier:e.identifier,scopes:e.scopes,signing_alg:e.signing_alg,token_lifetime:e.token_lifetime,token_lifetime_for_web:e.token_lifetime_for_web})}),G=t=>({list:async(e,n)=>(await t.roles.list(e,n)).roles,listPaginated:(e,n)=>t.roles.list(e,n),get:(e,n)=>t.roles.get(e,n),create:(e,n)=>t.roles.create(e,n),update:(e,n,r)=>t.roles.update(e,n,r),remove:(e,n)=>t.roles.remove(e,n),listKey:"roles",getId:e=>e.id,transform:e=>({id:e.id,name:e.name,description:e.description})});function L(t){var e;return((e=t.metadata)==null?void 0:e.sync)!==!1}function Q(t){const{sync:e={},filters:n={}}=t,r=e.resourceServers??!0,a=e.roles??!0,c=p=>L(p)?n.resourceServers?n.resourceServers(p):!0:!1,d=p=>L(p)?n.roles?n.roles(p):!0:!1,s=r?k(t,H,c):void 0,f=a?k(t,G,d):void 0,o=r?N(t,H,c):void 0,i=a?N(t,G,d):void 0,u=a?{async afterCreate(p,g){var v;if(g.id!==t.controlPlaneTenantId){await((v=i==null?void 0:i.afterCreate)==null?void 0:v.call(i,p,g));try{const w=await t.getControlPlaneAdapters(),h=await t.getAdapters(g.id),A=await y.fetchAll(_=>w.roles.list(t.controlPlaneTenantId,_),"roles",{cursorField:"id",pageSize:100}),P=new Map;for(const _ of A.filter(T=>{var b;return((b=n.roles)==null?void 0:b.call(n,T))??!0})){const T=await l(h,g.id,_.name);T&&P.set(_.name,T.id)}for(const _ of A.filter(T=>{var b;return((b=n.roles)==null?void 0:b.call(n,T))??!0})){const T=P.get(_.name);if(T)try{const b=await w.rolePermissions.list(t.controlPlaneTenantId,_.id,{});b.length>0&&await h.rolePermissions.assign(g.id,T,b.map(C=>({role_id:T,resource_server_identifier:C.resource_server_identifier,permission_name:C.permission_name})))}catch(b){console.error(`Failed to sync permissions for role "${_.name}" to tenant "${g.id}":`,b)}}}catch(w){console.error(`Failed to sync role permissions to tenant "${g.id}":`,w)}}}}:void 0;async function l(p,g,v){return(await p.roles.list(g,{q:`name:${v}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:s,roles:f},tenantHooks:{async afterCreate(p,g){const v=[o==null?void 0:o.afterCreate,(u==null?void 0:u.afterCreate)??(i==null?void 0:i.afterCreate)],w=[];for(const h of v)if(h)try{await h(p,g)}catch(A){w.push(A instanceof Error?A:new Error(String(A)))}if(w.length===1)throw w[0];if(w.length>1)throw new AggregateError(w,w.map(h=>h.message).join("; "))}}}}var S=class extends Error{constructor(e=500,n){super(n==null?void 0:n.message,{cause:n==null?void 0:n.cause});D(this,"res");D(this,"status");this.res=n==null?void 0:n.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 $(t,e){const n=new I.OpenAPIHono;return n.openapi(I.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:y.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:I.z.object({tenants:I.z.array(y.tenantSchema),start:I.z.number().optional(),limit:I.z.number().optional(),length:I.z.number().optional()})}},description:"List of tenants"}}}),async r=>{var p,g,v,w,h,A;const a=r.req.valid("query"),{page:c,per_page:d,include_totals:s,q:f}=a,o=r.var.user,i=(o==null?void 0:o.permissions)||[];if(i.includes("auth:read")||i.includes("admin:organizations")){const P=await r.env.data.tenants.list({page:c,per_page:d,include_totals:s,q:f});return s?r.json({tenants:P.tenants,start:((p=P.totals)==null?void 0:p.start)??0,limit:((g=P.totals)==null?void 0:g.limit)??d,length:P.tenants.length}):r.json({tenants:P.tenants})}const l=((v=t.accessControl)==null?void 0:v.controlPlaneTenantId)??((w=r.env.data.multiTenancyConfig)==null?void 0:w.controlPlaneTenantId);if(l&&(o!=null&&o.sub)){const _=(await y.fetchAll(O=>r.env.data.userOrganizations.listUserOrganizations(l,o.sub,O),"organizations")).map(O=>O.name);if(_.length===0)return s?r.json({tenants:[],start:0,limit:d??50,length:0}):r.json({tenants:[]});const T=_.length,b=c??0,C=d??50,z=b*C,M=_.slice(z,z+C);if(M.length===0)return s?r.json({tenants:[],start:z,limit:C,length:T}):r.json({tenants:[]});const E=M.map(O=>`id:${O}`).join(" OR "),ne=f?`(${E}) AND (${f})`:E,j=await r.env.data.tenants.list({q:ne,per_page:C,include_totals:!1});return s?r.json({tenants:j.tenants,start:z,limit:C,length:T}):r.json({tenants:j.tenants})}const m=await r.env.data.tenants.list({page:c,per_page:d,include_totals:s,q:f});return s?r.json({tenants:m.tenants,start:((h=m.totals)==null?void 0:h.start)??0,limit:((A=m.totals)==null?void 0:A.limit)??d,length:m.tenants.length}):r.json({tenants:m.tenants})}),n.openapi(I.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:y.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:y.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async r=>{var f,o;const a=r.var.user;if(!(a!=null&&a.sub))throw new S(401,{message:"Authentication required to create tenants"});let c=r.req.valid("json");const d={adapters:r.env.data,ctx:r};(f=e.tenants)!=null&&f.beforeCreate&&(c=await e.tenants.beforeCreate(d,c));const s=await r.env.data.tenants.create(c);return(o=e.tenants)!=null&&o.afterCreate&&await e.tenants.afterCreate(d,s),r.json(s,201)}),n.openapi(I.createRoute({tags:["tenants"],method:"delete",path:"/{id}",request:{params:I.z.object({id:I.z.string()})},security:[{Bearer:["delete:tenants"]}],responses:{204:{description:"Tenant deleted"},403:{description:"Access denied or cannot delete the control plane"},404:{description:"Tenant not found"}}}),async r=>{var f,o,i,u;const{id:a}=r.req.valid("param"),c=((f=t.accessControl)==null?void 0:f.controlPlaneTenantId)??((o=r.env.data.multiTenancyConfig)==null?void 0:o.controlPlaneTenantId);if(c){const l=r.var.user;if(!(l!=null&&l.sub))throw new S(401,{message:"Authentication required"});if(a===c)throw new S(403,{message:"Cannot delete the control plane"});if(!(await y.fetchAll(g=>r.env.data.userOrganizations.listUserOrganizations(c,l.sub,g),"organizations")).some(g=>g.name===a))throw new S(403,{message:"Access denied to this tenant"})}if(!await r.env.data.tenants.get(a))throw new S(404,{message:"Tenant not found"});const s={adapters:r.env.data,ctx:r};return(i=e.tenants)!=null&&i.beforeDelete&&await e.tenants.beforeDelete(s,a),await r.env.data.tenants.remove(a),(u=e.tenants)!=null&&u.afterDelete&&await e.tenants.afterDelete(s,a),r.body(null,204)}),n}function de(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:n,type:r}of e){const a=t.match(n);if(a&&a[1])return{type:r,id:a[1]}}return null}async function ue(t,e,n){try{switch(n.type){case"resource_server":{const r=await t.resourceServers.get(e,n.id);return(r==null?void 0:r.is_system)===!0}case"role":{const r=await t.roles.get(e,n.id);return(r==null?void 0:r.is_system)===!0}case"connection":{const r=await t.connections.get(e,n.id);return(r==null?void 0:r.is_system)===!0}default:return!1}}catch{return!1}}function fe(t){return{resource_server:"resource server",role:"role",connection:"connection"}[t]}function J(){return async(t,e)=>{if(!["PATCH","PUT","DELETE"].includes(t.req.method))return e();const n=de(t.req.path);if(!n)return e();const r=t.var.tenant_id||t.req.header("x-tenant-id")||t.req.header("tenant-id");if(!r)return e();if(await ue(t.env.data,r,n))throw new S(403,{message:`This ${fe(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return e()}}const me=["client_secret","app_secret","twilio_token"];function U(t){if(!t)return t;const e={...t};for(const n of me)delete e[n];return e}function X(t,e){const{controlPlaneTenantId:n,controlPlaneClientId:r,excludeSensitiveFields:a=!1}=e;return{...t,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:r},connections:{...t.connections,get:async(c,d)=>{var l;const s=await t.connections.get(c,d);if(!s||!n||c===n)return s;const o=(l=(await t.connections.list(n)).connections)==null?void 0:l.find(m=>m.strategy===s.strategy);if(!(o!=null&&o.options))return s;const i=y.connectionSchema.parse({...o,...s}),u=a?U(o.options):o.options;return i.options=y.connectionOptionsSchema.parse({...u||{},...s.options}),i},list:async(c,d)=>{const s=await t.connections.list(c,d);if(!n||c===n)return s;const f=await t.connections.list(n),o=s.connections.map(i=>{var p;const u=(p=f.connections)==null?void 0:p.find(g=>g.strategy===i.strategy);if(!(u!=null&&u.options))return i;const l=y.connectionSchema.parse({...u,...i}),m=a?U(u.options):u.options;return l.options=y.connectionOptionsSchema.parse({...m||{},...i.options}),l});return{...s,connections:o}}}}}function R(t,e){return X(t,e)}function Y(t){return async(e,n)=>{const r=e.var.user;return(r==null?void 0:r.tenant_id)===t&&r.org_name&&e.set("tenant_id",r.org_name),n()}}function Z(t){return async(e,n)=>{if(!t.accessControl)return n();const{controlPlaneTenantId:r}=t.accessControl,a=e.var.org_name,c=e.var.organization_id,d=a||c;let s=e.var.tenant_id;const f=e.var.user,i=(f!=null&&f.aud?Array.isArray(f.aud)?f.aud:[f.aud]:[]).includes(y.MANAGEMENT_API_AUDIENCE);if(!s&&d&&i&&(e.set("tenant_id",d),s=d),!s)throw new S(400,{message:"Tenant ID not found in request"});if(!K(c,s,r,a))throw new S(403,{message:`Access denied to tenant ${s}`});return n()}}function x(t){return async(e,n)=>{if(!t.subdomainRouting)return n();const{baseDomain:r,reservedSubdomains:a=[],resolveSubdomain:c}=t.subdomainRouting,d=e.req.header("host")||"";let s=null;if(d.endsWith(r)){const o=d.slice(0,-(r.length+1));o&&!o.includes(".")&&(s=o)}if(s&&a.includes(s)&&(s=null),!s)return t.accessControl&&e.set("tenant_id",t.accessControl.controlPlaneTenantId),n();let f=null;if(c)f=await c(s);else if(t.subdomainRouting.useOrganizations!==!1&&t.accessControl)try{const o=await e.env.data.organizations.get(t.accessControl.controlPlaneTenantId,s);o&&(f=o.id)}catch{}if(!f)throw new S(404,{message:`Tenant not found for subdomain: ${s}`});return e.set("tenant_id",f),n()}}function ee(t){return async(e,n)=>{if(!t.databaseIsolation)return n();const r=e.var.tenant_id;if(!r)throw new S(400,{message:"Tenant ID not found in request"});try{const a=await t.databaseIsolation.getAdapters(r);e.env.data=a}catch(a){throw console.error(`Failed to resolve database for tenant ${r}:`,a),new S(500,{message:"Failed to resolve tenant database"})}return n()}}function q(t){const e=x(t),n=Z(t),r=ee(t);return async(a,c)=>(await e(a,async()=>{}),await n(a,async()=>{}),await r(a,async()=>{}),c())}function pe(t){const{dataAdapter:e,controlPlane:n,controlPlane:{tenantId:r="control_plane",clientId:a}={},sync:c={resourceServers:!0,roles:!0},defaultPermissions:d=["tenant:admin"],requireOrganizationMatch:s=!1,managementApiExtensions:f=[],entityHooks:o,getChildTenantIds:i,getAdapters:u,...l}=t;let m=e,p=e;n&&(m=R(e,{controlPlaneTenantId:r,controlPlaneClientId:a}),p=R(e,{controlPlaneTenantId:r,controlPlaneClientId:a,excludeSensitiveFields:!0}));const g=c!==!1,v=g?{resourceServers:c.resourceServers??!0,roles:c.roles??!0}:{resourceServers:!1,roles:!1},A={controlPlaneTenantId:r,getChildTenantIds:i??(async()=>(await y.fetchAll(M=>m.tenants.list(M),"tenants",{cursorField:"id",pageSize:100})).filter(M=>M.id!==r).map(M=>M.id)),getAdapters:u??(async()=>m),getControlPlaneAdapters:async()=>m,sync:v},{entityHooks:P,tenantHooks:_}=Q(A),T={resourceServers:[P.resourceServers,...(o==null?void 0:o.resourceServers)??[]],roles:[P.roles,...(o==null?void 0:o.roles)??[]],connections:(o==null?void 0:o.connections)??[],tenants:(o==null?void 0:o.tenants)??[],rolePermissions:(o==null?void 0:o.rolePermissions)??[]},b=$({accessControl:{controlPlaneTenantId:r,requireOrganizationMatch:s,defaultPermissions:d}},{tenants:_}),{app:C}=y.init({dataAdapter:m,managementDataAdapter:p,...l,entityHooks:T,managementApiExtensions:[...f,{path:"/tenants",router:b}]});return C.use("/api/v2/*",Y(r)),g&&C.use("/api/v2/*",J()),{app:C,controlPlaneTenantId:r}}function ge(t){const e=F(t);return{name:"multi-tenancy",middleware:q(t),hooks:e,routes:[{path:"/management",handler:$(t,e)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),t.accessControl&&console.log(` - Access control enabled (control plane: ${t.accessControl.controlPlaneTenantId})`),t.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${t.subdomainRouting.baseDomain})`),t.databaseIsolation&&console.log(" - Database isolation enabled")}}}function F(t){const e=t.accessControl?B(t.accessControl):{},n=t.databaseIsolation?V(t.databaseIsolation):{},r=W(t);return{...e,...n,tenants:r}}function te(t){const e=new se.Hono,n=F(t);return e.route("/tenants",$(t,n)),e}function we(t){return{hooks:F(t),middleware:q(t),app:te(t),config:t,wrapAdapters:(e,n)=>{var r;return R(e,{controlPlaneTenantId:(r=t.accessControl)==null?void 0:r.controlPlaneTenantId,controlPlaneClientId:n==null?void 0:n.controlPlaneClientId})}}}exports.createAccessControlHooks=B;exports.createAccessControlMiddleware=Z;exports.createControlPlaneTenantMiddleware=Y;exports.createDatabaseHooks=V;exports.createDatabaseMiddleware=ee;exports.createMultiTenancy=te;exports.createMultiTenancyHooks=F;exports.createMultiTenancyMiddleware=q;exports.createMultiTenancyPlugin=ge;exports.createProtectSyncedMiddleware=J;exports.createProvisioningHooks=W;exports.createRuntimeFallbackAdapter=X;exports.createSubdomainMiddleware=x;exports.createSyncHooks=Q;exports.createTenantsOpenAPIRouter=$;exports.initMultiTenant=pe;exports.setupMultiTenancy=we;exports.validateTenantAccess=K;exports.withRuntimeFallback=R;
|
package/dist/multi-tenancy.mjs
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
var X = Object.defineProperty;
|
|
2
2
|
var Y = (t, e, n) => e in t ? X(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n;
|
|
3
|
-
var
|
|
3
|
+
var O = (t, e, n) => Y(t, typeof e != "symbol" ? e + "" : e, n);
|
|
4
4
|
import { Hono as Z } from "hono";
|
|
5
|
-
import { MANAGEMENT_API_SCOPES as x, MANAGEMENT_API_AUDIENCE as W, fetchAll as
|
|
6
|
-
import { OpenAPIHono as re, createRoute as
|
|
7
|
-
function
|
|
5
|
+
import { MANAGEMENT_API_SCOPES as x, MANAGEMENT_API_AUDIENCE as W, fetchAll as F, auth0QuerySchema as ee, tenantSchema as N, tenantInsertSchema as te, connectionSchema as k, connectionOptionsSchema as H, init as ne } from "authhero";
|
|
6
|
+
import { OpenAPIHono as re, createRoute as R, z as S } from "@hono/zod-openapi";
|
|
7
|
+
function ae(t) {
|
|
8
8
|
const { controlPlaneTenantId: e, requireOrganizationMatch: n = !0 } = t;
|
|
9
9
|
return {
|
|
10
10
|
async onTenantAccessValidation(r, a) {
|
|
11
11
|
if (a === e)
|
|
12
12
|
return !0;
|
|
13
13
|
if (n) {
|
|
14
|
-
const c = r.var.org_name,
|
|
14
|
+
const c = r.var.org_name, d = r.var.organization_id, s = c || d;
|
|
15
15
|
return s ? s.toLowerCase() === a.toLowerCase() : !1;
|
|
16
16
|
}
|
|
17
17
|
return !0;
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function se(t, e, n, r) {
|
|
22
22
|
if (e === n)
|
|
23
23
|
return !0;
|
|
24
24
|
const a = r || t;
|
|
@@ -58,12 +58,12 @@ function ce(t) {
|
|
|
58
58
|
const { accessControl: r, databaseIsolation: a } = t;
|
|
59
59
|
if (r)
|
|
60
60
|
try {
|
|
61
|
-
const
|
|
61
|
+
const d = (await e.adapters.organizations.list(
|
|
62
62
|
r.controlPlaneTenantId
|
|
63
63
|
)).organizations.find((s) => s.name === n);
|
|
64
|
-
|
|
64
|
+
d && await e.adapters.organizations.remove(
|
|
65
65
|
r.controlPlaneTenantId,
|
|
66
|
-
|
|
66
|
+
d.id
|
|
67
67
|
);
|
|
68
68
|
} catch (c) {
|
|
69
69
|
console.warn(
|
|
@@ -88,9 +88,9 @@ async function le(t, e, n) {
|
|
|
88
88
|
controlPlaneTenantId: r,
|
|
89
89
|
defaultPermissions: a,
|
|
90
90
|
defaultRoles: c,
|
|
91
|
-
issuer:
|
|
91
|
+
issuer: d,
|
|
92
92
|
adminRoleName: s = "Tenant Admin",
|
|
93
|
-
adminRoleDescription:
|
|
93
|
+
adminRoleDescription: f = "Full access to all tenant management operations",
|
|
94
94
|
addCreatorToOrganization: o = !0
|
|
95
95
|
} = n, i = await t.adapters.organizations.create(
|
|
96
96
|
r,
|
|
@@ -99,34 +99,34 @@ async function le(t, e, n) {
|
|
|
99
99
|
display_name: e.friendly_name || e.id
|
|
100
100
|
}
|
|
101
101
|
);
|
|
102
|
-
let
|
|
103
|
-
if (
|
|
102
|
+
let u;
|
|
103
|
+
if (d && (u = await ue(
|
|
104
104
|
t,
|
|
105
105
|
r,
|
|
106
106
|
s,
|
|
107
|
-
|
|
107
|
+
f
|
|
108
108
|
)), o && t.ctx) {
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
109
|
+
const l = t.ctx.var.user;
|
|
110
|
+
if (l != null && l.sub && !await de(
|
|
111
111
|
t,
|
|
112
112
|
r,
|
|
113
|
-
|
|
113
|
+
l.sub
|
|
114
114
|
))
|
|
115
115
|
try {
|
|
116
116
|
await t.adapters.userOrganizations.create(r, {
|
|
117
|
-
user_id:
|
|
117
|
+
user_id: l.sub,
|
|
118
118
|
organization_id: i.id
|
|
119
|
-
}),
|
|
119
|
+
}), u && await t.adapters.userRoles.create(
|
|
120
120
|
r,
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
l.sub,
|
|
122
|
+
u,
|
|
123
123
|
i.id
|
|
124
124
|
// organizationId
|
|
125
125
|
);
|
|
126
|
-
} catch (
|
|
126
|
+
} catch (p) {
|
|
127
127
|
console.warn(
|
|
128
|
-
`Failed to add creator ${
|
|
129
|
-
|
|
128
|
+
`Failed to add creator ${l.sub} to organization ${i.id}:`,
|
|
129
|
+
p
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
}
|
|
@@ -159,123 +159,123 @@ async function ue(t, e, n, r) {
|
|
|
159
159
|
const c = (await t.adapters.roles.list(e, {})).roles.find((o) => o.name === n);
|
|
160
160
|
if (c)
|
|
161
161
|
return c.id;
|
|
162
|
-
const
|
|
162
|
+
const d = await t.adapters.roles.create(e, {
|
|
163
163
|
name: n,
|
|
164
164
|
description: r
|
|
165
|
-
}), s = W,
|
|
166
|
-
role_id:
|
|
165
|
+
}), s = W, f = x.map((o) => ({
|
|
166
|
+
role_id: d.id,
|
|
167
167
|
resource_server_identifier: s,
|
|
168
168
|
permission_name: o.value
|
|
169
169
|
}));
|
|
170
170
|
return await t.adapters.rolePermissions.assign(
|
|
171
171
|
e,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
),
|
|
172
|
+
d.id,
|
|
173
|
+
f
|
|
174
|
+
), d.id;
|
|
175
175
|
}
|
|
176
|
-
function
|
|
177
|
-
const { controlPlaneTenantId: r, getChildTenantIds: a, getAdapters: c } = t,
|
|
178
|
-
async function s(i,
|
|
179
|
-
return (await e(i).list(
|
|
180
|
-
q: `name:${
|
|
176
|
+
function G(t, e, n = () => !0) {
|
|
177
|
+
const { controlPlaneTenantId: r, getChildTenantIds: a, getAdapters: c } = t, d = /* @__PURE__ */ new Map();
|
|
178
|
+
async function s(i, u, l) {
|
|
179
|
+
return (await e(i).list(u, {
|
|
180
|
+
q: `name:${l}`,
|
|
181
181
|
per_page: 1
|
|
182
182
|
}))[0] ?? null;
|
|
183
183
|
}
|
|
184
|
-
async function
|
|
185
|
-
const
|
|
184
|
+
async function f(i) {
|
|
185
|
+
const u = await a(), l = e(await c(r));
|
|
186
186
|
await Promise.all(
|
|
187
|
-
|
|
187
|
+
u.map(async (m) => {
|
|
188
188
|
try {
|
|
189
|
-
const
|
|
190
|
-
...
|
|
189
|
+
const p = await c(m), g = e(p), w = {
|
|
190
|
+
...l.transform(i),
|
|
191
191
|
is_system: !0
|
|
192
|
-
}, y = await s(
|
|
193
|
-
if (y &&
|
|
194
|
-
const
|
|
195
|
-
await g.update(
|
|
192
|
+
}, y = await s(p, m, i.name), T = y ? g.getId(y) : void 0;
|
|
193
|
+
if (y && T) {
|
|
194
|
+
const A = g.preserveOnUpdate ? g.preserveOnUpdate(y, w) : w;
|
|
195
|
+
await g.update(m, T, A);
|
|
196
196
|
} else
|
|
197
|
-
await g.create(
|
|
198
|
-
} catch (
|
|
197
|
+
await g.create(m, w);
|
|
198
|
+
} catch (p) {
|
|
199
199
|
console.error(
|
|
200
|
-
`Failed to sync ${
|
|
201
|
-
|
|
200
|
+
`Failed to sync ${l.listKey} "${i.name}" to tenant "${m}":`,
|
|
201
|
+
p
|
|
202
202
|
);
|
|
203
203
|
}
|
|
204
204
|
})
|
|
205
205
|
);
|
|
206
206
|
}
|
|
207
207
|
async function o(i) {
|
|
208
|
-
const
|
|
208
|
+
const u = await a();
|
|
209
209
|
await Promise.all(
|
|
210
|
-
|
|
210
|
+
u.map(async (l) => {
|
|
211
211
|
try {
|
|
212
|
-
const
|
|
213
|
-
g && h && await
|
|
214
|
-
} catch (
|
|
212
|
+
const m = await c(l), p = e(m), g = await s(m, l, i), h = g ? p.getId(g) : void 0;
|
|
213
|
+
g && h && await p.remove(l, h);
|
|
214
|
+
} catch (m) {
|
|
215
215
|
console.error(
|
|
216
|
-
`Failed to delete entity "${i}" from tenant "${
|
|
217
|
-
|
|
216
|
+
`Failed to delete entity "${i}" from tenant "${l}":`,
|
|
217
|
+
m
|
|
218
218
|
);
|
|
219
219
|
}
|
|
220
220
|
})
|
|
221
221
|
);
|
|
222
222
|
}
|
|
223
223
|
return {
|
|
224
|
-
afterCreate: async (i,
|
|
225
|
-
i.tenantId === r && n(
|
|
224
|
+
afterCreate: async (i, u) => {
|
|
225
|
+
i.tenantId === r && n(u) && await f(u);
|
|
226
226
|
},
|
|
227
|
-
afterUpdate: async (i,
|
|
228
|
-
i.tenantId === r && n(
|
|
227
|
+
afterUpdate: async (i, u, l) => {
|
|
228
|
+
i.tenantId === r && n(l) && await f(l);
|
|
229
229
|
},
|
|
230
|
-
beforeDelete: async (i,
|
|
230
|
+
beforeDelete: async (i, u) => {
|
|
231
231
|
if (i.tenantId !== r) return;
|
|
232
|
-
const
|
|
233
|
-
|
|
232
|
+
const m = await e(i.adapters).get(i.tenantId, u);
|
|
233
|
+
m && n(m) && d.set(u, m);
|
|
234
234
|
},
|
|
235
|
-
afterDelete: async (i,
|
|
235
|
+
afterDelete: async (i, u) => {
|
|
236
236
|
if (i.tenantId !== r) return;
|
|
237
|
-
const
|
|
238
|
-
|
|
237
|
+
const l = d.get(u);
|
|
238
|
+
l && (d.delete(u), await o(l.name));
|
|
239
239
|
}
|
|
240
240
|
};
|
|
241
241
|
}
|
|
242
|
-
function
|
|
242
|
+
function L(t, e, n = () => !0) {
|
|
243
243
|
const { controlPlaneTenantId: r, getControlPlaneAdapters: a, getAdapters: c } = t;
|
|
244
244
|
return {
|
|
245
|
-
async afterCreate(
|
|
245
|
+
async afterCreate(d, s) {
|
|
246
246
|
if (s.id !== r)
|
|
247
247
|
try {
|
|
248
|
-
const
|
|
249
|
-
(
|
|
248
|
+
const f = await a(), o = await c(s.id), i = e(f), u = e(o), l = await F(
|
|
249
|
+
(m) => i.listPaginated(r, m),
|
|
250
250
|
i.listKey,
|
|
251
251
|
{ cursorField: "id", pageSize: 100 }
|
|
252
252
|
);
|
|
253
253
|
await Promise.all(
|
|
254
|
-
|
|
254
|
+
l.filter((m) => n(m)).map(async (m) => {
|
|
255
255
|
try {
|
|
256
|
-
const
|
|
257
|
-
await
|
|
258
|
-
...
|
|
256
|
+
const p = i.transform(m);
|
|
257
|
+
await u.create(s.id, {
|
|
258
|
+
...p,
|
|
259
259
|
is_system: !0
|
|
260
260
|
});
|
|
261
|
-
} catch (
|
|
261
|
+
} catch (p) {
|
|
262
262
|
console.error(
|
|
263
263
|
`Failed to sync entity to new tenant "${s.id}":`,
|
|
264
|
-
|
|
264
|
+
p
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
267
|
})
|
|
268
268
|
);
|
|
269
|
-
} catch (
|
|
269
|
+
} catch (f) {
|
|
270
270
|
console.error(
|
|
271
271
|
`Failed to sync entities to new tenant "${s.id}":`,
|
|
272
|
-
|
|
272
|
+
f
|
|
273
273
|
);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
};
|
|
277
277
|
}
|
|
278
|
-
const
|
|
278
|
+
const U = (t) => ({
|
|
279
279
|
list: async (e, n) => (await t.resourceServers.list(e, n)).resource_servers,
|
|
280
280
|
listPaginated: (e, n) => t.resourceServers.list(e, n),
|
|
281
281
|
get: (e, n) => t.resourceServers.get(e, n),
|
|
@@ -293,7 +293,7 @@ const B = (t) => ({
|
|
|
293
293
|
token_lifetime: e.token_lifetime,
|
|
294
294
|
token_lifetime_for_web: e.token_lifetime_for_web
|
|
295
295
|
})
|
|
296
|
-
}),
|
|
296
|
+
}), B = (t) => ({
|
|
297
297
|
list: async (e, n) => (await t.roles.list(e, n)).roles,
|
|
298
298
|
listPaginated: (e, n) => t.roles.list(e, n),
|
|
299
299
|
get: (e, n) => t.roles.get(e, n),
|
|
@@ -308,81 +308,81 @@ const B = (t) => ({
|
|
|
308
308
|
description: e.description
|
|
309
309
|
})
|
|
310
310
|
});
|
|
311
|
-
function
|
|
311
|
+
function K(t) {
|
|
312
312
|
var e;
|
|
313
313
|
return ((e = t.metadata) == null ? void 0 : e.sync) !== !1;
|
|
314
314
|
}
|
|
315
315
|
function fe(t) {
|
|
316
|
-
const { sync: e = {}, filters: n = {} } = t, r = e.resourceServers ?? !0, a = e.roles ?? !0, c = (
|
|
316
|
+
const { sync: e = {}, filters: n = {} } = t, r = e.resourceServers ?? !0, a = e.roles ?? !0, c = (p) => K(p) ? n.resourceServers ? n.resourceServers(p) : !0 : !1, d = (p) => K(p) ? n.roles ? n.roles(p) : !0 : !1, s = r ? G(
|
|
317
317
|
t,
|
|
318
|
-
|
|
318
|
+
U,
|
|
319
319
|
c
|
|
320
|
-
) : void 0,
|
|
321
|
-
t,
|
|
322
|
-
K,
|
|
323
|
-
l
|
|
324
|
-
) : void 0, o = r ? U(
|
|
320
|
+
) : void 0, f = a ? G(
|
|
325
321
|
t,
|
|
326
322
|
B,
|
|
323
|
+
d
|
|
324
|
+
) : void 0, o = r ? L(
|
|
325
|
+
t,
|
|
326
|
+
U,
|
|
327
327
|
c
|
|
328
|
-
) : void 0, i = a ?
|
|
328
|
+
) : void 0, i = a ? L(
|
|
329
329
|
t,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
) : void 0,
|
|
333
|
-
async afterCreate(
|
|
330
|
+
B,
|
|
331
|
+
d
|
|
332
|
+
) : void 0, u = a ? {
|
|
333
|
+
async afterCreate(p, g) {
|
|
334
334
|
var h;
|
|
335
335
|
if (g.id !== t.controlPlaneTenantId) {
|
|
336
|
-
await ((h = i == null ? void 0 : i.afterCreate) == null ? void 0 : h.call(i,
|
|
336
|
+
await ((h = i == null ? void 0 : i.afterCreate) == null ? void 0 : h.call(i, p, g));
|
|
337
337
|
try {
|
|
338
|
-
const w = await t.getControlPlaneAdapters(), y = await t.getAdapters(g.id),
|
|
339
|
-
(
|
|
338
|
+
const w = await t.getControlPlaneAdapters(), y = await t.getAdapters(g.id), T = await F(
|
|
339
|
+
(_) => w.roles.list(
|
|
340
340
|
t.controlPlaneTenantId,
|
|
341
|
-
|
|
341
|
+
_
|
|
342
342
|
),
|
|
343
343
|
"roles",
|
|
344
344
|
{ cursorField: "id", pageSize: 100 }
|
|
345
|
-
),
|
|
346
|
-
for (const
|
|
345
|
+
), A = /* @__PURE__ */ new Map();
|
|
346
|
+
for (const _ of T.filter(
|
|
347
347
|
(v) => {
|
|
348
|
-
var
|
|
349
|
-
return ((
|
|
348
|
+
var P;
|
|
349
|
+
return ((P = n.roles) == null ? void 0 : P.call(n, v)) ?? !0;
|
|
350
350
|
}
|
|
351
351
|
)) {
|
|
352
|
-
const v = await
|
|
352
|
+
const v = await l(
|
|
353
353
|
y,
|
|
354
354
|
g.id,
|
|
355
|
-
|
|
355
|
+
_.name
|
|
356
356
|
);
|
|
357
|
-
v &&
|
|
357
|
+
v && A.set(_.name, v.id);
|
|
358
358
|
}
|
|
359
|
-
for (const
|
|
359
|
+
for (const _ of T.filter(
|
|
360
360
|
(v) => {
|
|
361
|
-
var
|
|
362
|
-
return ((
|
|
361
|
+
var P;
|
|
362
|
+
return ((P = n.roles) == null ? void 0 : P.call(n, v)) ?? !0;
|
|
363
363
|
}
|
|
364
364
|
)) {
|
|
365
|
-
const v =
|
|
365
|
+
const v = A.get(_.name);
|
|
366
366
|
if (v)
|
|
367
367
|
try {
|
|
368
|
-
const
|
|
368
|
+
const P = await w.rolePermissions.list(
|
|
369
369
|
t.controlPlaneTenantId,
|
|
370
|
-
|
|
370
|
+
_.id,
|
|
371
371
|
{}
|
|
372
372
|
);
|
|
373
|
-
|
|
373
|
+
P.length > 0 && await y.rolePermissions.assign(
|
|
374
374
|
g.id,
|
|
375
375
|
v,
|
|
376
|
-
|
|
376
|
+
P.map((C) => ({
|
|
377
377
|
role_id: v,
|
|
378
378
|
resource_server_identifier: C.resource_server_identifier,
|
|
379
379
|
permission_name: C.permission_name
|
|
380
380
|
}))
|
|
381
381
|
);
|
|
382
|
-
} catch (
|
|
382
|
+
} catch (P) {
|
|
383
383
|
console.error(
|
|
384
|
-
`Failed to sync permissions for role "${
|
|
385
|
-
|
|
384
|
+
`Failed to sync permissions for role "${_.name}" to tenant "${g.id}":`,
|
|
385
|
+
P
|
|
386
386
|
);
|
|
387
387
|
}
|
|
388
388
|
}
|
|
@@ -395,8 +395,8 @@ function fe(t) {
|
|
|
395
395
|
}
|
|
396
396
|
}
|
|
397
397
|
} : void 0;
|
|
398
|
-
async function
|
|
399
|
-
return (await
|
|
398
|
+
async function l(p, g, h) {
|
|
399
|
+
return (await p.roles.list(g, {
|
|
400
400
|
q: `name:${h}`,
|
|
401
401
|
per_page: 1
|
|
402
402
|
})).roles[0] ?? null;
|
|
@@ -404,20 +404,20 @@ function fe(t) {
|
|
|
404
404
|
return {
|
|
405
405
|
entityHooks: {
|
|
406
406
|
resourceServers: s,
|
|
407
|
-
roles:
|
|
407
|
+
roles: f
|
|
408
408
|
},
|
|
409
409
|
tenantHooks: {
|
|
410
|
-
async afterCreate(
|
|
410
|
+
async afterCreate(p, g) {
|
|
411
411
|
const h = [
|
|
412
412
|
o == null ? void 0 : o.afterCreate,
|
|
413
|
-
(
|
|
413
|
+
(u == null ? void 0 : u.afterCreate) ?? (i == null ? void 0 : i.afterCreate)
|
|
414
414
|
], w = [];
|
|
415
415
|
for (const y of h)
|
|
416
416
|
if (y)
|
|
417
417
|
try {
|
|
418
|
-
await y(
|
|
419
|
-
} catch (
|
|
420
|
-
w.push(
|
|
418
|
+
await y(p, g);
|
|
419
|
+
} catch (T) {
|
|
420
|
+
w.push(T instanceof Error ? T : new Error(String(T)));
|
|
421
421
|
}
|
|
422
422
|
if (w.length === 1) throw w[0];
|
|
423
423
|
if (w.length > 1)
|
|
@@ -429,7 +429,7 @@ function fe(t) {
|
|
|
429
429
|
}
|
|
430
430
|
};
|
|
431
431
|
}
|
|
432
|
-
var
|
|
432
|
+
var b = class extends Error {
|
|
433
433
|
/**
|
|
434
434
|
* Creates an instance of `HTTPException`.
|
|
435
435
|
* @param status - HTTP status code for the exception. Defaults to 500.
|
|
@@ -437,8 +437,8 @@ var P = class extends Error {
|
|
|
437
437
|
*/
|
|
438
438
|
constructor(e = 500, n) {
|
|
439
439
|
super(n == null ? void 0 : n.message, { cause: n == null ? void 0 : n.cause });
|
|
440
|
-
|
|
441
|
-
|
|
440
|
+
O(this, "res");
|
|
441
|
+
O(this, "status");
|
|
442
442
|
this.res = n == null ? void 0 : n.res, this.status = e;
|
|
443
443
|
}
|
|
444
444
|
/**
|
|
@@ -455,10 +455,10 @@ var P = class extends Error {
|
|
|
455
455
|
});
|
|
456
456
|
}
|
|
457
457
|
};
|
|
458
|
-
function
|
|
458
|
+
function M(t, e) {
|
|
459
459
|
const n = new re();
|
|
460
460
|
return n.openapi(
|
|
461
|
-
|
|
461
|
+
R({
|
|
462
462
|
tags: ["tenants"],
|
|
463
463
|
method: "get",
|
|
464
464
|
path: "/",
|
|
@@ -475,7 +475,7 @@ function E(t, e) {
|
|
|
475
475
|
content: {
|
|
476
476
|
"application/json": {
|
|
477
477
|
schema: S.object({
|
|
478
|
-
tenants: S.array(
|
|
478
|
+
tenants: S.array(N),
|
|
479
479
|
start: S.number().optional(),
|
|
480
480
|
limit: S.number().optional(),
|
|
481
481
|
length: S.number().optional()
|
|
@@ -487,40 +487,40 @@ function E(t, e) {
|
|
|
487
487
|
}
|
|
488
488
|
}),
|
|
489
489
|
async (r) => {
|
|
490
|
-
var
|
|
491
|
-
const a = r.req.valid("query"), { page: c, per_page:
|
|
490
|
+
var p, g, h, w, y, T;
|
|
491
|
+
const a = r.req.valid("query"), { page: c, per_page: d, include_totals: s, q: f } = a, o = r.var.user, i = (o == null ? void 0 : o.permissions) || [];
|
|
492
492
|
if (i.includes("auth:read") || i.includes("admin:organizations")) {
|
|
493
|
-
const
|
|
493
|
+
const A = await r.env.data.tenants.list({
|
|
494
494
|
page: c,
|
|
495
|
-
per_page:
|
|
495
|
+
per_page: d,
|
|
496
496
|
include_totals: s,
|
|
497
|
-
q:
|
|
497
|
+
q: f
|
|
498
498
|
});
|
|
499
499
|
return s ? r.json({
|
|
500
|
-
tenants:
|
|
501
|
-
start: ((
|
|
502
|
-
limit: ((g =
|
|
503
|
-
length:
|
|
504
|
-
}) : r.json({ tenants:
|
|
500
|
+
tenants: A.tenants,
|
|
501
|
+
start: ((p = A.totals) == null ? void 0 : p.start) ?? 0,
|
|
502
|
+
limit: ((g = A.totals) == null ? void 0 : g.limit) ?? d,
|
|
503
|
+
length: A.tenants.length
|
|
504
|
+
}) : r.json({ tenants: A.tenants });
|
|
505
505
|
}
|
|
506
|
-
const
|
|
507
|
-
if (
|
|
508
|
-
const
|
|
506
|
+
const l = ((h = t.accessControl) == null ? void 0 : h.controlPlaneTenantId) ?? ((w = r.env.data.multiTenancyConfig) == null ? void 0 : w.controlPlaneTenantId);
|
|
507
|
+
if (l && (o != null && o.sub)) {
|
|
508
|
+
const _ = (await F(
|
|
509
509
|
(z) => r.env.data.userOrganizations.listUserOrganizations(
|
|
510
|
-
|
|
510
|
+
l,
|
|
511
511
|
o.sub,
|
|
512
512
|
z
|
|
513
513
|
),
|
|
514
514
|
"organizations"
|
|
515
515
|
)).map((z) => z.name);
|
|
516
|
-
if (
|
|
516
|
+
if (_.length === 0)
|
|
517
517
|
return s ? r.json({
|
|
518
518
|
tenants: [],
|
|
519
519
|
start: 0,
|
|
520
|
-
limit:
|
|
520
|
+
limit: d ?? 50,
|
|
521
521
|
length: 0
|
|
522
522
|
}) : r.json({ tenants: [] });
|
|
523
|
-
const v =
|
|
523
|
+
const v = _.length, P = c ?? 0, C = d ?? 50, $ = P * C, I = _.slice($, $ + C);
|
|
524
524
|
if (I.length === 0)
|
|
525
525
|
return s ? r.json({
|
|
526
526
|
tenants: [],
|
|
@@ -528,34 +528,34 @@ function E(t, e) {
|
|
|
528
528
|
limit: C,
|
|
529
529
|
length: v
|
|
530
530
|
}) : r.json({ tenants: [] });
|
|
531
|
-
const
|
|
531
|
+
const j = I.map((z) => `id:${z}`).join(" OR "), J = f ? `(${j}) AND (${f})` : j, E = await r.env.data.tenants.list({
|
|
532
532
|
q: J,
|
|
533
533
|
per_page: C,
|
|
534
534
|
include_totals: !1
|
|
535
535
|
// We calculate totals from accessibleTenantIds
|
|
536
536
|
});
|
|
537
537
|
return s ? r.json({
|
|
538
|
-
tenants:
|
|
538
|
+
tenants: E.tenants,
|
|
539
539
|
start: $,
|
|
540
540
|
limit: C,
|
|
541
541
|
length: v
|
|
542
|
-
}) : r.json({ tenants:
|
|
542
|
+
}) : r.json({ tenants: E.tenants });
|
|
543
543
|
}
|
|
544
|
-
const
|
|
544
|
+
const m = await r.env.data.tenants.list({
|
|
545
545
|
page: c,
|
|
546
|
-
per_page:
|
|
546
|
+
per_page: d,
|
|
547
547
|
include_totals: s,
|
|
548
|
-
q:
|
|
548
|
+
q: f
|
|
549
549
|
});
|
|
550
550
|
return s ? r.json({
|
|
551
|
-
tenants:
|
|
552
|
-
start: ((y =
|
|
553
|
-
limit: ((
|
|
554
|
-
length:
|
|
555
|
-
}) : r.json({ tenants:
|
|
551
|
+
tenants: m.tenants,
|
|
552
|
+
start: ((y = m.totals) == null ? void 0 : y.start) ?? 0,
|
|
553
|
+
limit: ((T = m.totals) == null ? void 0 : T.limit) ?? d,
|
|
554
|
+
length: m.tenants.length
|
|
555
|
+
}) : r.json({ tenants: m.tenants });
|
|
556
556
|
}
|
|
557
557
|
), n.openapi(
|
|
558
|
-
|
|
558
|
+
R({
|
|
559
559
|
tags: ["tenants"],
|
|
560
560
|
method: "post",
|
|
561
561
|
path: "/",
|
|
@@ -577,7 +577,7 @@ function E(t, e) {
|
|
|
577
577
|
201: {
|
|
578
578
|
content: {
|
|
579
579
|
"application/json": {
|
|
580
|
-
schema:
|
|
580
|
+
schema: N
|
|
581
581
|
}
|
|
582
582
|
},
|
|
583
583
|
description: "Tenant created"
|
|
@@ -591,23 +591,23 @@ function E(t, e) {
|
|
|
591
591
|
}
|
|
592
592
|
}),
|
|
593
593
|
async (r) => {
|
|
594
|
-
var
|
|
594
|
+
var f, o;
|
|
595
595
|
const a = r.var.user;
|
|
596
596
|
if (!(a != null && a.sub))
|
|
597
|
-
throw new
|
|
597
|
+
throw new b(401, {
|
|
598
598
|
message: "Authentication required to create tenants"
|
|
599
599
|
});
|
|
600
600
|
let c = r.req.valid("json");
|
|
601
|
-
const
|
|
601
|
+
const d = {
|
|
602
602
|
adapters: r.env.data,
|
|
603
603
|
ctx: r
|
|
604
604
|
};
|
|
605
|
-
(
|
|
605
|
+
(f = e.tenants) != null && f.beforeCreate && (c = await e.tenants.beforeCreate(d, c));
|
|
606
606
|
const s = await r.env.data.tenants.create(c);
|
|
607
|
-
return (o = e.tenants) != null && o.afterCreate && await e.tenants.afterCreate(
|
|
607
|
+
return (o = e.tenants) != null && o.afterCreate && await e.tenants.afterCreate(d, s), r.json(s, 201);
|
|
608
608
|
}
|
|
609
609
|
), n.openapi(
|
|
610
|
-
|
|
610
|
+
R({
|
|
611
611
|
tags: ["tenants"],
|
|
612
612
|
method: "delete",
|
|
613
613
|
path: "/{id}",
|
|
@@ -634,39 +634,39 @@ function E(t, e) {
|
|
|
634
634
|
}
|
|
635
635
|
}),
|
|
636
636
|
async (r) => {
|
|
637
|
-
var
|
|
638
|
-
const { id: a } = r.req.valid("param"), c = ((
|
|
637
|
+
var f, o, i, u;
|
|
638
|
+
const { id: a } = r.req.valid("param"), c = ((f = t.accessControl) == null ? void 0 : f.controlPlaneTenantId) ?? ((o = r.env.data.multiTenancyConfig) == null ? void 0 : o.controlPlaneTenantId);
|
|
639
639
|
if (c) {
|
|
640
|
-
const
|
|
641
|
-
if (!(
|
|
642
|
-
throw new
|
|
640
|
+
const l = r.var.user;
|
|
641
|
+
if (!(l != null && l.sub))
|
|
642
|
+
throw new b(401, {
|
|
643
643
|
message: "Authentication required"
|
|
644
644
|
});
|
|
645
645
|
if (a === c)
|
|
646
|
-
throw new
|
|
646
|
+
throw new b(403, {
|
|
647
647
|
message: "Cannot delete the control plane"
|
|
648
648
|
});
|
|
649
|
-
if (!(await
|
|
649
|
+
if (!(await F(
|
|
650
650
|
(g) => r.env.data.userOrganizations.listUserOrganizations(
|
|
651
651
|
c,
|
|
652
|
-
|
|
652
|
+
l.sub,
|
|
653
653
|
g
|
|
654
654
|
),
|
|
655
655
|
"organizations"
|
|
656
656
|
)).some((g) => g.name === a))
|
|
657
|
-
throw new
|
|
657
|
+
throw new b(403, {
|
|
658
658
|
message: "Access denied to this tenant"
|
|
659
659
|
});
|
|
660
660
|
}
|
|
661
661
|
if (!await r.env.data.tenants.get(a))
|
|
662
|
-
throw new
|
|
662
|
+
throw new b(404, {
|
|
663
663
|
message: "Tenant not found"
|
|
664
664
|
});
|
|
665
665
|
const s = {
|
|
666
666
|
adapters: r.env.data,
|
|
667
667
|
ctx: r
|
|
668
668
|
};
|
|
669
|
-
return (i = e.tenants) != null && i.beforeDelete && await e.tenants.beforeDelete(s, a), await r.env.data.tenants.remove(a), (
|
|
669
|
+
return (i = e.tenants) != null && i.beforeDelete && await e.tenants.beforeDelete(s, a), await r.env.data.tenants.remove(a), (u = e.tenants) != null && u.afterDelete && await e.tenants.afterDelete(s, a), r.body(null, 204);
|
|
670
670
|
}
|
|
671
671
|
), n;
|
|
672
672
|
}
|
|
@@ -726,7 +726,7 @@ function we() {
|
|
|
726
726
|
if (!r)
|
|
727
727
|
return e();
|
|
728
728
|
if (await pe(t.env.data, r, n))
|
|
729
|
-
throw new
|
|
729
|
+
throw new b(403, {
|
|
730
730
|
message: `This ${ge(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`
|
|
731
731
|
});
|
|
732
732
|
return e();
|
|
@@ -737,7 +737,7 @@ const ye = [
|
|
|
737
737
|
"app_secret",
|
|
738
738
|
"twilio_token"
|
|
739
739
|
];
|
|
740
|
-
function
|
|
740
|
+
function V(t) {
|
|
741
741
|
if (!t) return t;
|
|
742
742
|
const e = { ...t };
|
|
743
743
|
for (const n of ye)
|
|
@@ -757,96 +757,49 @@ function he(t, e) {
|
|
|
757
757
|
controlPlaneTenantId: n,
|
|
758
758
|
controlPlaneClientId: r
|
|
759
759
|
},
|
|
760
|
-
legacyClients: {
|
|
761
|
-
...t.legacyClients,
|
|
762
|
-
get: async (c) => {
|
|
763
|
-
var d;
|
|
764
|
-
const l = await t.legacyClients.get(c);
|
|
765
|
-
if (!l)
|
|
766
|
-
return null;
|
|
767
|
-
const s = r ? await t.legacyClients.get(r) : void 0, p = await t.connections.list(
|
|
768
|
-
l.tenant.id
|
|
769
|
-
), o = n ? await t.connections.list(n) : { connections: [] }, i = p.connections.map((u) => {
|
|
770
|
-
var w;
|
|
771
|
-
const m = (w = o.connections) == null ? void 0 : w.find(
|
|
772
|
-
(y) => y.strategy === u.strategy
|
|
773
|
-
);
|
|
774
|
-
if (!(m != null && m.options))
|
|
775
|
-
return u;
|
|
776
|
-
const g = R.parse({
|
|
777
|
-
...m || {},
|
|
778
|
-
...u
|
|
779
|
-
}), h = a ? q(m.options) : m.options;
|
|
780
|
-
return g.options = D.parse({
|
|
781
|
-
...h || {},
|
|
782
|
-
...u.options
|
|
783
|
-
}), g;
|
|
784
|
-
}).filter((u) => u), f = {
|
|
785
|
-
...(s == null ? void 0 : s.tenant) || {},
|
|
786
|
-
...l.tenant
|
|
787
|
-
};
|
|
788
|
-
return !l.tenant.audience && ((d = s == null ? void 0 : s.tenant) != null && d.audience) && (f.audience = s.tenant.audience), {
|
|
789
|
-
...l,
|
|
790
|
-
web_origins: [
|
|
791
|
-
...(s == null ? void 0 : s.web_origins) || [],
|
|
792
|
-
...l.web_origins || []
|
|
793
|
-
],
|
|
794
|
-
allowed_logout_urls: [
|
|
795
|
-
...(s == null ? void 0 : s.allowed_logout_urls) || [],
|
|
796
|
-
...l.allowed_logout_urls || []
|
|
797
|
-
],
|
|
798
|
-
callbacks: [
|
|
799
|
-
...(s == null ? void 0 : s.callbacks) || [],
|
|
800
|
-
...l.callbacks || []
|
|
801
|
-
],
|
|
802
|
-
connections: i,
|
|
803
|
-
tenant: f
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
},
|
|
807
760
|
connections: {
|
|
808
761
|
...t.connections,
|
|
809
|
-
get: async (c,
|
|
810
|
-
var
|
|
762
|
+
get: async (c, d) => {
|
|
763
|
+
var l;
|
|
811
764
|
const s = await t.connections.get(
|
|
812
765
|
c,
|
|
813
|
-
|
|
766
|
+
d
|
|
814
767
|
);
|
|
815
768
|
if (!s || !n || c === n)
|
|
816
769
|
return s;
|
|
817
|
-
const o = (
|
|
818
|
-
(
|
|
770
|
+
const o = (l = (await t.connections.list(n)).connections) == null ? void 0 : l.find(
|
|
771
|
+
(m) => m.strategy === s.strategy
|
|
819
772
|
);
|
|
820
773
|
if (!(o != null && o.options))
|
|
821
774
|
return s;
|
|
822
|
-
const i =
|
|
775
|
+
const i = k.parse({
|
|
823
776
|
...o,
|
|
824
777
|
...s
|
|
825
|
-
}),
|
|
826
|
-
return i.options =
|
|
827
|
-
...
|
|
778
|
+
}), u = a ? V(o.options) : o.options;
|
|
779
|
+
return i.options = H.parse({
|
|
780
|
+
...u || {},
|
|
828
781
|
...s.options
|
|
829
782
|
}), i;
|
|
830
783
|
},
|
|
831
|
-
list: async (c,
|
|
832
|
-
const s = await t.connections.list(c,
|
|
784
|
+
list: async (c, d) => {
|
|
785
|
+
const s = await t.connections.list(c, d);
|
|
833
786
|
if (!n || c === n)
|
|
834
787
|
return s;
|
|
835
|
-
const
|
|
836
|
-
var
|
|
837
|
-
const
|
|
788
|
+
const f = await t.connections.list(n), o = s.connections.map((i) => {
|
|
789
|
+
var p;
|
|
790
|
+
const u = (p = f.connections) == null ? void 0 : p.find(
|
|
838
791
|
(g) => g.strategy === i.strategy
|
|
839
792
|
);
|
|
840
|
-
if (!(
|
|
793
|
+
if (!(u != null && u.options))
|
|
841
794
|
return i;
|
|
842
|
-
const
|
|
843
|
-
...
|
|
795
|
+
const l = k.parse({
|
|
796
|
+
...u,
|
|
844
797
|
...i
|
|
845
|
-
}),
|
|
846
|
-
return
|
|
847
|
-
...
|
|
798
|
+
}), m = a ? V(u.options) : u.options;
|
|
799
|
+
return l.options = H.parse({
|
|
800
|
+
...m || {},
|
|
848
801
|
...i.options
|
|
849
|
-
}),
|
|
802
|
+
}), l;
|
|
850
803
|
});
|
|
851
804
|
return {
|
|
852
805
|
...s,
|
|
@@ -863,7 +816,7 @@ function he(t, e) {
|
|
|
863
816
|
// They remain part of ...baseAdapters and can be properly wrapped by caching.
|
|
864
817
|
};
|
|
865
818
|
}
|
|
866
|
-
function
|
|
819
|
+
function D(t, e) {
|
|
867
820
|
return he(t, e);
|
|
868
821
|
}
|
|
869
822
|
function ve(t) {
|
|
@@ -872,30 +825,30 @@ function ve(t) {
|
|
|
872
825
|
return (r == null ? void 0 : r.tenant_id) === t && r.org_name && e.set("tenant_id", r.org_name), n();
|
|
873
826
|
};
|
|
874
827
|
}
|
|
875
|
-
function
|
|
828
|
+
function Te(t) {
|
|
876
829
|
return async (e, n) => {
|
|
877
830
|
if (!t.accessControl)
|
|
878
831
|
return n();
|
|
879
|
-
const { controlPlaneTenantId: r } = t.accessControl, a = e.var.org_name, c = e.var.organization_id,
|
|
832
|
+
const { controlPlaneTenantId: r } = t.accessControl, a = e.var.org_name, c = e.var.organization_id, d = a || c;
|
|
880
833
|
let s = e.var.tenant_id;
|
|
881
|
-
const
|
|
882
|
-
if (!s &&
|
|
883
|
-
throw new
|
|
834
|
+
const f = e.var.user, i = (f != null && f.aud ? Array.isArray(f.aud) ? f.aud : [f.aud] : []).includes(W);
|
|
835
|
+
if (!s && d && i && (e.set("tenant_id", d), s = d), !s)
|
|
836
|
+
throw new b(400, {
|
|
884
837
|
message: "Tenant ID not found in request"
|
|
885
838
|
});
|
|
886
|
-
if (!
|
|
839
|
+
if (!se(
|
|
887
840
|
c,
|
|
888
841
|
s,
|
|
889
842
|
r,
|
|
890
843
|
a
|
|
891
844
|
))
|
|
892
|
-
throw new
|
|
845
|
+
throw new b(403, {
|
|
893
846
|
message: `Access denied to tenant ${s}`
|
|
894
847
|
});
|
|
895
848
|
return n();
|
|
896
849
|
};
|
|
897
850
|
}
|
|
898
|
-
function
|
|
851
|
+
function Ae(t) {
|
|
899
852
|
return async (e, n) => {
|
|
900
853
|
if (!t.subdomainRouting)
|
|
901
854
|
return n();
|
|
@@ -903,40 +856,40 @@ function Te(t) {
|
|
|
903
856
|
baseDomain: r,
|
|
904
857
|
reservedSubdomains: a = [],
|
|
905
858
|
resolveSubdomain: c
|
|
906
|
-
} = t.subdomainRouting,
|
|
859
|
+
} = t.subdomainRouting, d = e.req.header("host") || "";
|
|
907
860
|
let s = null;
|
|
908
|
-
if (
|
|
909
|
-
const o =
|
|
861
|
+
if (d.endsWith(r)) {
|
|
862
|
+
const o = d.slice(0, -(r.length + 1));
|
|
910
863
|
o && !o.includes(".") && (s = o);
|
|
911
864
|
}
|
|
912
865
|
if (s && a.includes(s) && (s = null), !s)
|
|
913
866
|
return t.accessControl && e.set("tenant_id", t.accessControl.controlPlaneTenantId), n();
|
|
914
|
-
let
|
|
867
|
+
let f = null;
|
|
915
868
|
if (c)
|
|
916
|
-
|
|
869
|
+
f = await c(s);
|
|
917
870
|
else if (t.subdomainRouting.useOrganizations !== !1 && t.accessControl)
|
|
918
871
|
try {
|
|
919
872
|
const o = await e.env.data.organizations.get(
|
|
920
873
|
t.accessControl.controlPlaneTenantId,
|
|
921
874
|
s
|
|
922
875
|
);
|
|
923
|
-
o && (
|
|
876
|
+
o && (f = o.id);
|
|
924
877
|
} catch {
|
|
925
878
|
}
|
|
926
|
-
if (!
|
|
927
|
-
throw new
|
|
879
|
+
if (!f)
|
|
880
|
+
throw new b(404, {
|
|
928
881
|
message: `Tenant not found for subdomain: ${s}`
|
|
929
882
|
});
|
|
930
|
-
return e.set("tenant_id",
|
|
883
|
+
return e.set("tenant_id", f), n();
|
|
931
884
|
};
|
|
932
885
|
}
|
|
933
|
-
function
|
|
886
|
+
function _e(t) {
|
|
934
887
|
return async (e, n) => {
|
|
935
888
|
if (!t.databaseIsolation)
|
|
936
889
|
return n();
|
|
937
890
|
const r = e.var.tenant_id;
|
|
938
891
|
if (!r)
|
|
939
|
-
throw new
|
|
892
|
+
throw new b(400, {
|
|
940
893
|
message: "Tenant ID not found in request"
|
|
941
894
|
});
|
|
942
895
|
try {
|
|
@@ -946,7 +899,7 @@ function Ae(t) {
|
|
|
946
899
|
throw console.error(
|
|
947
900
|
`Failed to resolve database for tenant ${r}:`,
|
|
948
901
|
a
|
|
949
|
-
), new
|
|
902
|
+
), new b(500, {
|
|
950
903
|
message: "Failed to resolve tenant database"
|
|
951
904
|
});
|
|
952
905
|
}
|
|
@@ -954,7 +907,7 @@ function Ae(t) {
|
|
|
954
907
|
};
|
|
955
908
|
}
|
|
956
909
|
function Q(t) {
|
|
957
|
-
const e =
|
|
910
|
+
const e = Ae(t), n = Te(t), r = _e(t);
|
|
958
911
|
return async (a, c) => (await e(a, async () => {
|
|
959
912
|
}), await n(a, async () => {
|
|
960
913
|
}), await r(a, async () => {
|
|
@@ -969,19 +922,19 @@ function $e(t) {
|
|
|
969
922
|
clientId: a
|
|
970
923
|
} = {},
|
|
971
924
|
sync: c = { resourceServers: !0, roles: !0 },
|
|
972
|
-
defaultPermissions:
|
|
925
|
+
defaultPermissions: d = ["tenant:admin"],
|
|
973
926
|
requireOrganizationMatch: s = !1,
|
|
974
|
-
managementApiExtensions:
|
|
927
|
+
managementApiExtensions: f = [],
|
|
975
928
|
entityHooks: o,
|
|
976
929
|
getChildTenantIds: i,
|
|
977
|
-
getAdapters:
|
|
978
|
-
...
|
|
930
|
+
getAdapters: u,
|
|
931
|
+
...l
|
|
979
932
|
} = t;
|
|
980
|
-
let
|
|
981
|
-
n && (
|
|
933
|
+
let m = e, p = e;
|
|
934
|
+
n && (m = D(e, {
|
|
982
935
|
controlPlaneTenantId: r,
|
|
983
936
|
controlPlaneClientId: a
|
|
984
|
-
}),
|
|
937
|
+
}), p = D(e, {
|
|
985
938
|
controlPlaneTenantId: r,
|
|
986
939
|
controlPlaneClientId: a,
|
|
987
940
|
excludeSensitiveFields: !0
|
|
@@ -989,48 +942,48 @@ function $e(t) {
|
|
|
989
942
|
const g = c !== !1, h = g ? {
|
|
990
943
|
resourceServers: c.resourceServers ?? !0,
|
|
991
944
|
roles: c.roles ?? !0
|
|
992
|
-
} : { resourceServers: !1, roles: !1 },
|
|
945
|
+
} : { resourceServers: !1, roles: !1 }, T = {
|
|
993
946
|
controlPlaneTenantId: r,
|
|
994
|
-
getChildTenantIds: i ?? (async () => (await
|
|
995
|
-
(I) =>
|
|
947
|
+
getChildTenantIds: i ?? (async () => (await F(
|
|
948
|
+
(I) => m.tenants.list(I),
|
|
996
949
|
"tenants",
|
|
997
950
|
{ cursorField: "id", pageSize: 100 }
|
|
998
951
|
)).filter((I) => I.id !== r).map((I) => I.id)),
|
|
999
|
-
getAdapters:
|
|
1000
|
-
getControlPlaneAdapters: async () =>
|
|
952
|
+
getAdapters: u ?? (async () => m),
|
|
953
|
+
getControlPlaneAdapters: async () => m,
|
|
1001
954
|
sync: h
|
|
1002
|
-
}, { entityHooks:
|
|
955
|
+
}, { entityHooks: A, tenantHooks: _ } = fe(T), v = {
|
|
1003
956
|
resourceServers: [
|
|
1004
|
-
|
|
957
|
+
A.resourceServers,
|
|
1005
958
|
...(o == null ? void 0 : o.resourceServers) ?? []
|
|
1006
959
|
],
|
|
1007
|
-
roles: [
|
|
960
|
+
roles: [A.roles, ...(o == null ? void 0 : o.roles) ?? []],
|
|
1008
961
|
connections: (o == null ? void 0 : o.connections) ?? [],
|
|
1009
962
|
tenants: (o == null ? void 0 : o.tenants) ?? [],
|
|
1010
963
|
rolePermissions: (o == null ? void 0 : o.rolePermissions) ?? []
|
|
1011
|
-
},
|
|
964
|
+
}, P = M(
|
|
1012
965
|
{
|
|
1013
966
|
accessControl: {
|
|
1014
967
|
controlPlaneTenantId: r,
|
|
1015
968
|
requireOrganizationMatch: s,
|
|
1016
|
-
defaultPermissions:
|
|
969
|
+
defaultPermissions: d
|
|
1017
970
|
}
|
|
1018
971
|
},
|
|
1019
|
-
{ tenants:
|
|
972
|
+
{ tenants: _ }
|
|
1020
973
|
), { app: C } = ne({
|
|
1021
|
-
dataAdapter:
|
|
1022
|
-
managementDataAdapter:
|
|
1023
|
-
...
|
|
974
|
+
dataAdapter: m,
|
|
975
|
+
managementDataAdapter: p,
|
|
976
|
+
...l,
|
|
1024
977
|
entityHooks: v,
|
|
1025
978
|
managementApiExtensions: [
|
|
1026
|
-
...
|
|
1027
|
-
{ path: "/tenants", router:
|
|
979
|
+
...f,
|
|
980
|
+
{ path: "/tenants", router: P }
|
|
1028
981
|
]
|
|
1029
982
|
});
|
|
1030
983
|
return C.use("/api/v2/*", ve(r)), g && C.use("/api/v2/*", we()), { app: C, controlPlaneTenantId: r };
|
|
1031
984
|
}
|
|
1032
985
|
function ze(t) {
|
|
1033
|
-
const e =
|
|
986
|
+
const e = q(t);
|
|
1034
987
|
return {
|
|
1035
988
|
name: "multi-tenancy",
|
|
1036
989
|
// Apply multi-tenancy middleware for subdomain routing, database resolution, etc.
|
|
@@ -1041,7 +994,7 @@ function ze(t) {
|
|
|
1041
994
|
routes: [
|
|
1042
995
|
{
|
|
1043
996
|
path: "/management",
|
|
1044
|
-
handler:
|
|
997
|
+
handler: M(t, e)
|
|
1045
998
|
}
|
|
1046
999
|
],
|
|
1047
1000
|
// Called when plugin is registered
|
|
@@ -1054,23 +1007,23 @@ function ze(t) {
|
|
|
1054
1007
|
}
|
|
1055
1008
|
};
|
|
1056
1009
|
}
|
|
1057
|
-
function
|
|
1058
|
-
const e = t.accessControl ?
|
|
1010
|
+
function q(t) {
|
|
1011
|
+
const e = t.accessControl ? ae(t.accessControl) : {}, n = t.databaseIsolation ? oe(t.databaseIsolation) : {}, r = ce(t);
|
|
1059
1012
|
return {
|
|
1060
1013
|
...e,
|
|
1061
1014
|
...n,
|
|
1062
1015
|
tenants: r
|
|
1063
1016
|
};
|
|
1064
1017
|
}
|
|
1065
|
-
function
|
|
1066
|
-
const e = new Z(), n =
|
|
1067
|
-
return e.route("/tenants",
|
|
1018
|
+
function Pe(t) {
|
|
1019
|
+
const e = new Z(), n = q(t);
|
|
1020
|
+
return e.route("/tenants", M(t, n)), e;
|
|
1068
1021
|
}
|
|
1069
|
-
function
|
|
1022
|
+
function Fe(t) {
|
|
1070
1023
|
return {
|
|
1071
|
-
hooks:
|
|
1024
|
+
hooks: q(t),
|
|
1072
1025
|
middleware: Q(t),
|
|
1073
|
-
app:
|
|
1026
|
+
app: Pe(t),
|
|
1074
1027
|
config: t,
|
|
1075
1028
|
/**
|
|
1076
1029
|
* Wraps data adapters with runtime fallback from the control plane.
|
|
@@ -1082,7 +1035,7 @@ function Oe(t) {
|
|
|
1082
1035
|
*/
|
|
1083
1036
|
wrapAdapters: (e, n) => {
|
|
1084
1037
|
var r;
|
|
1085
|
-
return
|
|
1038
|
+
return D(e, {
|
|
1086
1039
|
controlPlaneTenantId: (r = t.accessControl) == null ? void 0 : r.controlPlaneTenantId,
|
|
1087
1040
|
controlPlaneClientId: n == null ? void 0 : n.controlPlaneClientId
|
|
1088
1041
|
});
|
|
@@ -1090,23 +1043,23 @@ function Oe(t) {
|
|
|
1090
1043
|
};
|
|
1091
1044
|
}
|
|
1092
1045
|
export {
|
|
1093
|
-
|
|
1094
|
-
|
|
1046
|
+
ae as createAccessControlHooks,
|
|
1047
|
+
Te as createAccessControlMiddleware,
|
|
1095
1048
|
ve as createControlPlaneTenantMiddleware,
|
|
1096
1049
|
oe as createDatabaseHooks,
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1050
|
+
_e as createDatabaseMiddleware,
|
|
1051
|
+
Pe as createMultiTenancy,
|
|
1052
|
+
q as createMultiTenancyHooks,
|
|
1100
1053
|
Q as createMultiTenancyMiddleware,
|
|
1101
1054
|
ze as createMultiTenancyPlugin,
|
|
1102
1055
|
we as createProtectSyncedMiddleware,
|
|
1103
1056
|
ce as createProvisioningHooks,
|
|
1104
1057
|
he as createRuntimeFallbackAdapter,
|
|
1105
|
-
|
|
1058
|
+
Ae as createSubdomainMiddleware,
|
|
1106
1059
|
fe as createSyncHooks,
|
|
1107
|
-
|
|
1060
|
+
M as createTenantsOpenAPIRouter,
|
|
1108
1061
|
$e as initMultiTenant,
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1062
|
+
Fe as setupMultiTenancy,
|
|
1063
|
+
se as validateTenantAccess,
|
|
1064
|
+
D as withRuntimeFallback
|
|
1112
1065
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-inheritance.d.ts","sourceRoot":"","sources":["../../../src/middleware/settings-inheritance.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,
|
|
1
|
+
{"version":3,"file":"settings-inheritance.d.ts","sourceRoot":"","sources":["../../../src/middleware/settings-inheritance.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAIb,MAAM,UAAU,CAAC;AA+BlB;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,qBAAqB,GAC5B,YAAY,CA0Hd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,qBAAqB,GAC5B,YAAY,CAEd"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "https://github.com/markusahlstrand/authhero"
|
|
13
13
|
},
|
|
14
|
-
"version": "14.
|
|
14
|
+
"version": "14.7.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"
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"typescript": "^5.6.0",
|
|
37
37
|
"vite": "^6.0.0",
|
|
38
38
|
"vitest": "^2.1.0",
|
|
39
|
-
"authhero": "
|
|
40
|
-
"
|
|
41
|
-
"@authhero/
|
|
39
|
+
"@authhero/kysely-adapter": "10.88.0",
|
|
40
|
+
"authhero": "4.23.0",
|
|
41
|
+
"@authhero/adapter-interfaces": "0.127.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"zod": "^3.24.0"
|