@authhero/multi-tenancy 14.10.0 → 14.11.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 se=Object.defineProperty;var oe=(e,t,n)=>t in e?se(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var D=(e,t,n)=>oe(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ie=require("hono"),T=require("authhero"),I=require("@hono/zod-openapi");function K(e){const{controlPlaneTenantId:t,requireOrganizationMatch:n=!0}=e;return{async onTenantAccessValidation(r,a){if(a===t)return!0;if(n){const s=r.var.org_name,o=r.var.organization_id,i=s||o;return i?i.toLowerCase()===a.toLowerCase():!1}return!0}}}function Q(e,t,n,r){if(t===n)return!0;const a=r||e;return a?a.toLowerCase()===t.toLowerCase():!1}function V(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(n){console.error(`Failed to resolve data adapters for tenant ${t}:`,n);return}}}}function ce(e){return`urn:authhero:tenant:${e.toLowerCase()}`}function J(e){return{async beforeCreate(t,n){return!n.audience&&n.id?{...n,audience:ce(n.id)}:n},async afterCreate(t,n){const{accessControl:r,databaseIsolation:a}=e;r&&t.ctx&&await le(t,n,r),a!=null&&a.onProvision&&await a.onProvision(n.id)},async beforeDelete(t,n){const{accessControl:r,databaseIsolation:a}=e;if(r)try{const o=(await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find(i=>i.name===n);o&&await t.adapters.organizations.remove(r.controlPlaneTenantId,o.id)}catch(s){console.warn(`Failed to remove organization for tenant ${n}:`,s)}if(a!=null&&a.onDeprovision)try{await a.onDeprovision(n)}catch(s){console.warn(`Failed to deprovision database for tenant ${n}:`,s)}}}}async function le(e,t,n){const{controlPlaneTenantId:r,defaultPermissions:a,defaultRoles:s,issuer:o,adminRoleName:i="Tenant Admin",adminRoleDescription:u="Full access to all tenant management operations",addCreatorToOrganization:c=!0}=n,l=await e.adapters.organizations.create(r,{name:t.id,display_name:t.friendly_name||t.id});let g;if(o&&(g=await de(e,r,i,u)),c&&e.ctx){const d=e.ctx.var.user;if(d!=null&&d.sub&&!await ue(e,r,d.sub))try{await e.adapters.userOrganizations.create(r,{user_id:d.sub,organization_id:l.id}),g&&await e.adapters.userRoles.create(r,d.sub,g,l.id)}catch(m){console.warn(`Failed to add creator ${d.sub} to organization ${l.id}:`,m)}}s&&s.length>0&&console.log(`Would assign roles ${s.join(", ")} to organization ${l.id}`),a&&a.length>0&&console.log(`Would grant permissions ${a.join(", ")} to organization ${l.id}`)}async function ue(e,t,n){const r=await e.adapters.userRoles.list(t,n,void 0,"");for(const a of r)if((await e.adapters.rolePermissions.list(t,a.id,{per_page:1e3})).some(i=>i.permission_name==="admin:organizations"))return!0;return!1}async function de(e,t,n,r){const s=(await e.adapters.roles.list(t,{})).roles.find(c=>c.name===n);if(s)return s.id;const o=await e.adapters.roles.create(t,{name:n,description:r}),i=T.MANAGEMENT_API_AUDIENCE,u=T.MANAGEMENT_API_SCOPES.map(c=>({role_id:o.id,resource_server_identifier:i,permission_name:c.value}));return await e.adapters.rolePermissions.assign(t,o.id,u),o.id}function H(e,t,n=()=>!0){const{controlPlaneTenantId:r,getChildTenantIds:a,getAdapters:s}=e,o=new Map;async function i(l,g,d){return(await t(l).list(g,{q:`name:${d}`,per_page:1}))[0]??null}async function u(l){const g=await a(),d=t(await s(r));await Promise.all(g.map(async f=>{try{const m=await s(f),w=t(m),p={...d.transform(l),is_system:!0},y=await i(m,f,l.name),_=y?w.getId(y):void 0;if(y&&_){const C=w.preserveOnUpdate?w.preserveOnUpdate(y,p):p;await w.update(f,_,C)}else await w.create(f,p)}catch(m){console.error(`Failed to sync ${d.listKey} "${l.name}" to tenant "${f}":`,m)}}))}async function c(l){const g=await a();await Promise.all(g.map(async d=>{try{const f=await s(d),m=t(f),w=await i(f,d,l),h=w?m.getId(w):void 0;w&&h&&await m.remove(d,h)}catch(f){console.error(`Failed to delete entity "${l}" from tenant "${d}":`,f)}}))}return{afterCreate:async(l,g)=>{l.tenantId===r&&n(g)&&await u(g)},afterUpdate:async(l,g,d)=>{l.tenantId===r&&n(d)&&await u(d)},beforeDelete:async(l,g)=>{if(l.tenantId!==r)return;const f=await t(l.adapters).get(l.tenantId,g);f&&n(f)&&o.set(g,f)},afterDelete:async(l,g)=>{if(l.tenantId!==r)return;const d=o.get(g);d&&(o.delete(g),await c(d.name))}}}function G(e,t,n=()=>!0){const{controlPlaneTenantId:r,getControlPlaneAdapters:a,getAdapters:s}=e;return{async afterCreate(o,i){if(i.id!==r)try{const u=await a(),c=await s(i.id),l=t(u),g=t(c),d=await T.fetchAll(f=>l.listPaginated(r,f),l.listKey,{cursorField:"id",pageSize:100});await Promise.all(d.filter(f=>n(f)).map(async f=>{try{const m=l.transform(f);await g.create(i.id,{...m,is_system:!0})}catch(m){console.error(`Failed to sync entity to new tenant "${i.id}":`,m)}}))}catch(u){console.error(`Failed to sync entities to new tenant "${i.id}":`,u)}}}}const B=e=>({list:async(t,n)=>(await e.resourceServers.list(t,n)).resource_servers,listPaginated:(t,n)=>e.resourceServers.list(t,n),get:(t,n)=>e.resourceServers.get(t,n),create:(t,n)=>e.resourceServers.create(t,n),update:(t,n,r)=>e.resourceServers.update(t,n,r),remove:(t,n)=>e.resourceServers.remove(t,n),listKey:"resource_servers",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,identifier:t.identifier,scopes:t.scopes,signing_alg:t.signing_alg,token_lifetime:t.token_lifetime,token_lifetime_for_web:t.token_lifetime_for_web})}),U=e=>({list:async(t,n)=>(await e.roles.list(t,n)).roles,listPaginated:(t,n)=>e.roles.list(t,n),get:(t,n)=>e.roles.get(t,n),create:(t,n)=>e.roles.create(t,n),update:(t,n,r)=>e.roles.update(t,n,r),remove:(t,n)=>e.roles.remove(t,n),listKey:"roles",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,description:t.description})});function L(e){var t;return((t=e.metadata)==null?void 0:t.sync)!==!1}function X(e){const{sync:t={},filters:n={}}=e,r=t.resourceServers??!0,a=t.roles??!0,s=m=>L(m)?n.resourceServers?n.resourceServers(m):!0:!1,o=m=>L(m)?n.roles?n.roles(m):!0:!1,i=r?H(e,B,s):void 0,u=a?H(e,U,o):void 0,c=r?G(e,B,s):void 0,l=a?G(e,U,o):void 0,g=a?{async afterCreate(m,w){var h;if(w.id!==e.controlPlaneTenantId){await((h=l==null?void 0:l.afterCreate)==null?void 0:h.call(l,m,w));try{const p=await e.getControlPlaneAdapters(),y=await e.getAdapters(w.id),_=await T.fetchAll(P=>p.roles.list(e.controlPlaneTenantId,P),"roles",{cursorField:"id",pageSize:100}),C=new Map;for(const P of _.filter(v=>{var A;return((A=n.roles)==null?void 0:A.call(n,v))??!0})){const v=await d(y,w.id,P.name);v&&C.set(P.name,v.id)}for(const P of _.filter(v=>{var A;return((A=n.roles)==null?void 0:A.call(n,v))??!0})){const v=C.get(P.name);if(v)try{const A=await p.rolePermissions.list(e.controlPlaneTenantId,P.id,{});A.length>0&&await y.rolePermissions.assign(w.id,v,A.map(b=>({role_id:v,resource_server_identifier:b.resource_server_identifier,permission_name:b.permission_name})))}catch(A){console.error(`Failed to sync permissions for role "${P.name}" to tenant "${w.id}":`,A)}}}catch(p){console.error(`Failed to sync role permissions to tenant "${w.id}":`,p)}}}}:void 0;async function d(m,w,h){return(await m.roles.list(w,{q:`name:${h}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:i,roles:u},tenantHooks:{async afterCreate(m,w){const h=[c==null?void 0:c.afterCreate,(g==null?void 0:g.afterCreate)??(l==null?void 0:l.afterCreate)],p=[];for(const y of h)if(y)try{await y(m,w)}catch(_){p.push(_ instanceof Error?_:new Error(String(_)))}if(p.length===1)throw p[0];if(p.length>1)throw new AggregateError(p,p.map(y=>y.message).join("; "))}}}}var S=class extends Error{constructor(t=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=t}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function F(e,t){const n=new I.OpenAPIHono;return n.openapi(I.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:T.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:I.z.object({tenants:I.z.array(T.tenantSchema),start:I.z.number().optional(),limit:I.z.number().optional(),length:I.z.number().optional()})}},description:"List of tenants"}}}),async r=>{var m,w,h,p,y,_;const a=r.req.valid("query"),{page:s,per_page:o,include_totals:i,q:u}=a,c=r.var.user,l=(c==null?void 0:c.permissions)||[];if(l.includes("auth:read")||l.includes("admin:organizations")){const C=await r.env.data.tenants.list({page:s,per_page:o,include_totals:i,q:u});return i?r.json({tenants:C.tenants,start:((m=C.totals)==null?void 0:m.start)??0,limit:((w=C.totals)==null?void 0:w.limit)??o,length:C.tenants.length}):r.json({tenants:C.tenants})}const d=((h=e.accessControl)==null?void 0:h.controlPlaneTenantId)??((p=r.env.data.multiTenancyConfig)==null?void 0:p.controlPlaneTenantId);if(d&&(c!=null&&c.sub)){const P=(await T.fetchAll(R=>r.env.data.userOrganizations.listUserOrganizations(d,c.sub,R),"organizations")).map(R=>R.name);if(P.length===0)return i?r.json({tenants:[],start:0,limit:o??50,length:0}):r.json({tenants:[]});const v=P.length,A=s??0,b=o??50,z=A*b,M=P.slice(z,z+b);if(M.length===0)return i?r.json({tenants:[],start:z,limit:b,length:v}):r.json({tenants:[]});const E=M.map(R=>`id:${R}`).join(" OR "),ae=u?`(${E}) AND (${u})`:E,N=await r.env.data.tenants.list({q:ae,per_page:b,include_totals:!1});return i?r.json({tenants:N.tenants,start:z,limit:b,length:v}):r.json({tenants:N.tenants})}const f=await r.env.data.tenants.list({page:s,per_page:o,include_totals:i,q:u});return i?r.json({tenants:f.tenants,start:((y=f.totals)==null?void 0:y.start)??0,limit:((_=f.totals)==null?void 0:_.limit)??o,length:f.tenants.length}):r.json({tenants:f.tenants})}),n.openapi(I.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:T.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:T.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async r=>{var u,c;const a=r.var.user;if(!(a!=null&&a.sub))throw new S(401,{message:"Authentication required to create tenants"});let s=r.req.valid("json");const o={adapters:r.env.data,ctx:r};(u=t.tenants)!=null&&u.beforeCreate&&(s=await t.tenants.beforeCreate(o,s));const i=await r.env.data.tenants.create(s);return(c=t.tenants)!=null&&c.afterCreate&&await t.tenants.afterCreate(o,i),r.json(i,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 u,c,l,g;const{id:a}=r.req.valid("param"),s=((u=e.accessControl)==null?void 0:u.controlPlaneTenantId)??((c=r.env.data.multiTenancyConfig)==null?void 0:c.controlPlaneTenantId);if(s){const d=r.var.user;if(!(d!=null&&d.sub))throw new S(401,{message:"Authentication required"});if(a===s)throw new S(403,{message:"Cannot delete the control plane"});if(!(await T.fetchAll(w=>r.env.data.userOrganizations.listUserOrganizations(s,d.sub,w),"organizations")).some(w=>w.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 i={adapters:r.env.data,ctx:r};return(l=t.tenants)!=null&&l.beforeDelete&&await t.tenants.beforeDelete(i,a),await r.env.data.tenants.remove(a),(g=t.tenants)!=null&&g.afterDelete&&await t.tenants.afterDelete(i,a),r.body(null,204)}),n}function fe(e){const t=[{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 t){const a=e.match(n);if(a&&a[1])return{type:r,id:a[1]}}return null}async function me(e,t,n){try{switch(n.type){case"resource_server":{const r=await e.resourceServers.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"role":{const r=await e.roles.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"connection":{const r=await e.connections.get(t,n.id);return(r==null?void 0:r.is_system)===!0}default:return!1}}catch{return!1}}function ge(e){return{resource_server:"resource server",role:"role",connection:"connection"}[e]}function Y(){return async(e,t)=>{if(!["PATCH","PUT","DELETE"].includes(e.req.method))return t();const n=fe(e.req.path);if(!n)return t();const r=e.var.tenant_id||e.req.header("x-tenant-id")||e.req.header("tenant-id");if(!r)return t();if(await me(e.env.data,r,n))throw new S(403,{message:`This ${ge(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}function q(e,t){const n=t.find(a=>a.strategy===e.strategy);if(!(n!=null&&n.options))return e;const r=T.connectionSchema.passthrough().parse({...n,...e});return r.options=T.connectionOptionsSchema.passthrough().parse({...n.options||{},...e.options}),r}function $(e,t){const n=[...t||[],...e||[]];return[...new Set(n)]}function W(e,t){return t?{...e,callbacks:$(e.callbacks,t.callbacks),web_origins:$(e.web_origins,t.web_origins),allowed_logout_urls:$(e.allowed_logout_urls,t.allowed_logout_urls),allowed_origins:$(e.allowed_origins,t.allowed_origins)}:e}function Z(e,t){const{controlPlaneTenantId:n,controlPlaneClientId:r}=t;return{...e,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:r},connections:{...e.connections,get:async(a,s)=>{const o=await e.connections.get(a,s);if(!o||!n||a===n)return o;const i=await e.connections.list(n);return q(o,i.connections||[])},list:async(a,s)=>{const o=await e.connections.list(a,s);if(!n||a===n)return o;const i=await e.connections.list(n),u=o.connections.map(c=>q(c,i.connections||[]));return{...o,connections:u}}},clientConnections:{...e.clientConnections,listByClient:async(a,s)=>{let o=await e.clientConnections.listByClient(a,s);if(o.length===0&&(o=(await e.connections.list(a)).connections||[]),!n||a===n)return o;const i=await e.connections.list(n);return o.map(u=>q(u,i.connections||[]))}},clients:{...e.clients,get:async(a,s)=>{const o=await e.clients.get(a,s);if(!o)return null;if(!n||!r||a===n&&s===r)return o;const i=await e.clients.get(n,r);return W(o,i)},getByClientId:async a=>{const s=await e.clients.getByClientId(a);if(!s)return null;if(!n||!r||s.tenant_id===n&&s.client_id===r)return s;const o=await e.clients.get(n,r);return{...W(s,o),tenant_id:s.tenant_id}}},emailProviders:{...e.emailProviders,get:async a=>{const s=await e.emailProviders.get(a);return s||(!n||a===n?null:e.emailProviders.get(n))}}}}function k(e,t){return Z(e,t)}function x(e){return async(t,n)=>{const r=t.var.user;return(r==null?void 0:r.tenant_id)===e&&r.org_name&&t.set("tenant_id",r.org_name),n()}}function ee(e){return async(t,n)=>{if(!e.accessControl)return n();const{controlPlaneTenantId:r}=e.accessControl,a=t.var.org_name,s=t.var.organization_id,o=a||s;let i=t.var.tenant_id;const u=t.var.user,l=(u!=null&&u.aud?Array.isArray(u.aud)?u.aud:[u.aud]:[]).includes(T.MANAGEMENT_API_AUDIENCE);if(!i&&o&&l&&(t.set("tenant_id",o),i=o),!i)throw new S(400,{message:"Tenant ID not found in request"});if(!Q(s,i,r,a))throw new S(403,{message:`Access denied to tenant ${i}`});return n()}}function te(e){return async(t,n)=>{if(!e.subdomainRouting)return n();const{baseDomain:r,reservedSubdomains:a=[],resolveSubdomain:s}=e.subdomainRouting,o=t.req.header("host")||"";let i=null;if(o.endsWith(r)){const c=o.slice(0,-(r.length+1));c&&!c.includes(".")&&(i=c)}if(i&&a.includes(i)&&(i=null),!i)return e.accessControl&&t.set("tenant_id",e.accessControl.controlPlaneTenantId),n();let u=null;if(s)u=await s(i);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{const c=await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId,i);c&&(u=c.id)}catch{}if(!u)throw new S(404,{message:`Tenant not found for subdomain: ${i}`});return t.set("tenant_id",u),n()}}function ne(e){return async(t,n)=>{if(!e.databaseIsolation)return n();const r=t.var.tenant_id;if(!r)throw new S(400,{message:"Tenant ID not found in request"});try{const a=await e.databaseIsolation.getAdapters(r);t.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 j(e){const t=te(e),n=ee(e),r=ne(e);return async(a,s)=>(await t(a,async()=>{}),await n(a,async()=>{}),await r(a,async()=>{}),s())}function we(e){const{dataAdapter:t,controlPlane:n,controlPlane:{tenantId:r="control_plane",clientId:a}={},sync:s={resourceServers:!0,roles:!0},defaultPermissions:o=["tenant:admin"],requireOrganizationMatch:i=!1,managementApiExtensions:u=[],entityHooks:c,getChildTenantIds:l,getAdapters:g,...d}=e;let f=t,m=t;n&&(f=k(t,{controlPlaneTenantId:r,controlPlaneClientId:a}),m={...t,multiTenancyConfig:{controlPlaneTenantId:r,controlPlaneClientId:a}});const w=s!==!1,h=w?{resourceServers:s.resourceServers??!0,roles:s.roles??!0}:{resourceServers:!1,roles:!1},_={controlPlaneTenantId:r,getChildTenantIds:l??(async()=>(await T.fetchAll(M=>f.tenants.list(M),"tenants",{cursorField:"id",pageSize:100})).filter(M=>M.id!==r).map(M=>M.id)),getAdapters:g??(async()=>f),getControlPlaneAdapters:async()=>f,sync:h},{entityHooks:C,tenantHooks:P}=X(_),v={resourceServers:[C.resourceServers,...(c==null?void 0:c.resourceServers)??[]],roles:[C.roles,...(c==null?void 0:c.roles)??[]],connections:(c==null?void 0:c.connections)??[],tenants:(c==null?void 0:c.tenants)??[],rolePermissions:(c==null?void 0:c.rolePermissions)??[]},A=F({accessControl:{controlPlaneTenantId:r,requireOrganizationMatch:i,defaultPermissions:o}},{tenants:P}),{app:b}=T.init({dataAdapter:f,managementDataAdapter:m,...d,entityHooks:v,managementApiExtensions:[...u,{path:"/tenants",router:A}]});return b.use("/api/v2/*",x(r)),w&&b.use("/api/v2/*",Y()),{app:b,controlPlaneTenantId:r}}function pe(e){const t=O(e);return{name:"multi-tenancy",middleware:j(e),hooks:t,routes:[{path:"/management",handler:F(e,t)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),e.accessControl&&console.log(` - Access control enabled (control plane: ${e.accessControl.controlPlaneTenantId})`),e.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${e.subdomainRouting.baseDomain})`),e.databaseIsolation&&console.log(" - Database isolation enabled")}}}function O(e){const t=e.accessControl?K(e.accessControl):{},n=e.databaseIsolation?V(e.databaseIsolation):{},r=J(e);return{...t,...n,tenants:r}}function re(e){const t=new ie.Hono,n=O(e);return t.route("/tenants",F(e,n)),t}function ye(e){return{hooks:O(e),middleware:j(e),app:re(e),config:e,wrapAdapters:(t,n)=>{var r;return k(t,{controlPlaneTenantId:(r=e.accessControl)==null?void 0:r.controlPlaneTenantId,controlPlaneClientId:n==null?void 0:n.controlPlaneClientId})}}}exports.createAccessControlHooks=K;exports.createAccessControlMiddleware=ee;exports.createControlPlaneTenantMiddleware=x;exports.createDatabaseHooks=V;exports.createDatabaseMiddleware=ne;exports.createMultiTenancy=re;exports.createMultiTenancyHooks=O;exports.createMultiTenancyMiddleware=j;exports.createMultiTenancyPlugin=pe;exports.createProtectSyncedMiddleware=Y;exports.createProvisioningHooks=J;exports.createRuntimeFallbackAdapter=Z;exports.createSubdomainMiddleware=te;exports.createSyncHooks=X;exports.createTenantsOpenAPIRouter=F;exports.initMultiTenant=we;exports.setupMultiTenancy=ye;exports.validateTenantAccess=Q;exports.withRuntimeFallback=k;
|
|
1
|
+
"use strict";var oe=Object.defineProperty;var ie=(e,t,n)=>t in e?oe(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var D=(e,t,n)=>ie(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ce=require("hono"),_=require("authhero"),I=require("@hono/zod-openapi");function Q(e){const{controlPlaneTenantId:t,requireOrganizationMatch:n=!0}=e;return{async onTenantAccessValidation(r,a){if(a===t)return!0;if(n){const s=r.var.org_name,o=r.var.organization_id,i=s||o;return i?i.toLowerCase()===a.toLowerCase():!1}return!0}}}function V(e,t,n,r){if(t===n)return!0;const a=r||e;return a?a.toLowerCase()===t.toLowerCase():!1}function J(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(n){console.error(`Failed to resolve data adapters for tenant ${t}:`,n);return}}}}function le(e){return`urn:authhero:tenant:${e.toLowerCase()}`}function X(e){return{async beforeCreate(t,n){return!n.audience&&n.id?{...n,audience:le(n.id)}:n},async afterCreate(t,n){const{accessControl:r,databaseIsolation:a}=e;r&&t.ctx&&await ue(t,n,r),a!=null&&a.onProvision&&await a.onProvision(n.id)},async beforeDelete(t,n){const{accessControl:r,databaseIsolation:a}=e;if(r)try{const o=(await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find(i=>i.name===n);o&&await t.adapters.organizations.remove(r.controlPlaneTenantId,o.id)}catch(s){console.warn(`Failed to remove organization for tenant ${n}:`,s)}if(a!=null&&a.onDeprovision)try{await a.onDeprovision(n)}catch(s){console.warn(`Failed to deprovision database for tenant ${n}:`,s)}}}}async function ue(e,t,n){const{controlPlaneTenantId:r,defaultPermissions:a,defaultRoles:s,issuer:o,adminRoleName:i="Tenant Admin",adminRoleDescription:u="Full access to all tenant management operations",addCreatorToOrganization:c=!0}=n,l=await e.adapters.organizations.create(r,{name:t.id,display_name:t.friendly_name||t.id});let g;if(o&&(g=await fe(e,r,i,u)),c&&e.ctx){const d=e.ctx.var.user;if(d!=null&&d.sub&&!await de(e,r,d.sub))try{await e.adapters.userOrganizations.create(r,{user_id:d.sub,organization_id:l.id}),g&&await e.adapters.userRoles.create(r,d.sub,g,l.id)}catch(m){console.warn(`Failed to add creator ${d.sub} to organization ${l.id}:`,m)}}s&&s.length>0&&console.log(`Would assign roles ${s.join(", ")} to organization ${l.id}`),a&&a.length>0&&console.log(`Would grant permissions ${a.join(", ")} to organization ${l.id}`)}async function de(e,t,n){const r=await e.adapters.userRoles.list(t,n,void 0,"");for(const a of r)if((await e.adapters.rolePermissions.list(t,a.id,{per_page:1e3})).some(i=>i.permission_name==="admin:organizations"))return!0;return!1}async function fe(e,t,n,r){const s=(await e.adapters.roles.list(t,{})).roles.find(c=>c.name===n);if(s)return s.id;const o=await e.adapters.roles.create(t,{name:n,description:r}),i=_.MANAGEMENT_API_AUDIENCE,u=_.MANAGEMENT_API_SCOPES.map(c=>({role_id:o.id,resource_server_identifier:i,permission_name:c.value}));return await e.adapters.rolePermissions.assign(t,o.id,u),o.id}function H(e,t,n=()=>!0){const{controlPlaneTenantId:r,getChildTenantIds:a,getAdapters:s}=e,o=new Map;async function i(l,g,d){return(await t(l).list(g,{q:`name:${d}`,per_page:1}))[0]??null}async function u(l){const g=await a(),d=t(await s(r));await Promise.all(g.map(async f=>{try{const m=await s(f),w=t(m),p={...d.transform(l),is_system:!0},y=await i(m,f,l.name),T=y?w.getId(y):void 0;if(y&&T){const C=w.preserveOnUpdate?w.preserveOnUpdate(y,p):p;await w.update(f,T,C)}else await w.create(f,p)}catch(m){console.error(`Failed to sync ${d.listKey} "${l.name}" to tenant "${f}":`,m)}}))}async function c(l){const g=await a();await Promise.all(g.map(async d=>{try{const f=await s(d),m=t(f),w=await i(f,d,l),h=w?m.getId(w):void 0;w&&h&&await m.remove(d,h)}catch(f){console.error(`Failed to delete entity "${l}" from tenant "${d}":`,f)}}))}return{afterCreate:async(l,g)=>{l.tenantId===r&&n(g)&&await u(g)},afterUpdate:async(l,g,d)=>{l.tenantId===r&&n(d)&&await u(d)},beforeDelete:async(l,g)=>{if(l.tenantId!==r)return;const f=await t(l.adapters).get(l.tenantId,g);f&&n(f)&&o.set(g,f)},afterDelete:async(l,g)=>{if(l.tenantId!==r)return;const d=o.get(g);d&&(o.delete(g),await c(d.name))}}}function B(e,t,n=()=>!0){const{controlPlaneTenantId:r,getControlPlaneAdapters:a,getAdapters:s}=e;return{async afterCreate(o,i){if(i.id!==r)try{const u=await a(),c=await s(i.id),l=t(u),g=t(c),d=await _.fetchAll(f=>l.listPaginated(r,f),l.listKey,{cursorField:"id",pageSize:100});await Promise.all(d.filter(f=>n(f)).map(async f=>{try{const m=l.transform(f);await g.create(i.id,{...m,is_system:!0})}catch(m){console.error(`Failed to sync entity to new tenant "${i.id}":`,m)}}))}catch(u){console.error(`Failed to sync entities to new tenant "${i.id}":`,u)}}}}const G=e=>({list:async(t,n)=>(await e.resourceServers.list(t,n)).resource_servers,listPaginated:(t,n)=>e.resourceServers.list(t,n),get:(t,n)=>e.resourceServers.get(t,n),create:(t,n)=>e.resourceServers.create(t,n),update:(t,n,r)=>e.resourceServers.update(t,n,r),remove:(t,n)=>e.resourceServers.remove(t,n),listKey:"resource_servers",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,identifier:t.identifier,scopes:t.scopes,signing_alg:t.signing_alg,token_lifetime:t.token_lifetime,token_lifetime_for_web:t.token_lifetime_for_web})}),U=e=>({list:async(t,n)=>(await e.roles.list(t,n)).roles,listPaginated:(t,n)=>e.roles.list(t,n),get:(t,n)=>e.roles.get(t,n),create:(t,n)=>e.roles.create(t,n),update:(t,n,r)=>e.roles.update(t,n,r),remove:(t,n)=>e.roles.remove(t,n),listKey:"roles",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,description:t.description})});function L(e){var t;return((t=e.metadata)==null?void 0:t.sync)!==!1}function Y(e){const{sync:t={},filters:n={}}=e,r=t.resourceServers??!0,a=t.roles??!0,s=m=>L(m)?n.resourceServers?n.resourceServers(m):!0:!1,o=m=>L(m)?n.roles?n.roles(m):!0:!1,i=r?H(e,G,s):void 0,u=a?H(e,U,o):void 0,c=r?B(e,G,s):void 0,l=a?B(e,U,o):void 0,g=a?{async afterCreate(m,w){var h;if(w.id!==e.controlPlaneTenantId){await((h=l==null?void 0:l.afterCreate)==null?void 0:h.call(l,m,w));try{const p=await e.getControlPlaneAdapters(),y=await e.getAdapters(w.id),T=await _.fetchAll(P=>p.roles.list(e.controlPlaneTenantId,P),"roles",{cursorField:"id",pageSize:100}),C=new Map;for(const P of T.filter(v=>{var A;return((A=n.roles)==null?void 0:A.call(n,v))??!0})){const v=await d(y,w.id,P.name);v&&C.set(P.name,v.id)}for(const P of T.filter(v=>{var A;return((A=n.roles)==null?void 0:A.call(n,v))??!0})){const v=C.get(P.name);if(v)try{const A=await p.rolePermissions.list(e.controlPlaneTenantId,P.id,{});A.length>0&&await y.rolePermissions.assign(w.id,v,A.map(b=>({role_id:v,resource_server_identifier:b.resource_server_identifier,permission_name:b.permission_name})))}catch(A){console.error(`Failed to sync permissions for role "${P.name}" to tenant "${w.id}":`,A)}}}catch(p){console.error(`Failed to sync role permissions to tenant "${w.id}":`,p)}}}}:void 0;async function d(m,w,h){return(await m.roles.list(w,{q:`name:${h}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:i,roles:u},tenantHooks:{async afterCreate(m,w){const h=[c==null?void 0:c.afterCreate,(g==null?void 0:g.afterCreate)??(l==null?void 0:l.afterCreate)],p=[];for(const y of h)if(y)try{await y(m,w)}catch(T){p.push(T instanceof Error?T:new Error(String(T)))}if(p.length===1)throw p[0];if(p.length>1)throw new AggregateError(p,p.map(y=>y.message).join("; "))}}}}var S=class extends Error{constructor(t=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=t}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function F(e,t){const n=new I.OpenAPIHono;return n.openapi(I.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:_.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:I.z.object({tenants:I.z.array(_.tenantSchema),start:I.z.number().optional(),limit:I.z.number().optional(),length:I.z.number().optional()})}},description:"List of tenants"}}}),async r=>{var m,w,h,p,y,T;const a=r.req.valid("query"),{page:s,per_page:o,include_totals:i,q:u}=a,c=r.var.user,l=(c==null?void 0:c.permissions)||[];if(l.includes("auth:read")||l.includes("admin:organizations")){const C=await r.env.data.tenants.list({page:s,per_page:o,include_totals:i,q:u});return i?r.json({tenants:C.tenants,start:((m=C.totals)==null?void 0:m.start)??0,limit:((w=C.totals)==null?void 0:w.limit)??o,length:C.tenants.length}):r.json({tenants:C.tenants})}const d=((h=e.accessControl)==null?void 0:h.controlPlaneTenantId)??((p=r.env.data.multiTenancyConfig)==null?void 0:p.controlPlaneTenantId);if(d&&(c!=null&&c.sub)){const P=(await _.fetchAll(z=>r.env.data.userOrganizations.listUserOrganizations(d,c.sub,z),"organizations")).map(z=>z.name);if(P.length===0)return i?r.json({tenants:[],start:0,limit:o??50,length:0}):r.json({tenants:[]});const v=P.length,A=s??0,b=o??50,R=A*b,M=P.slice(R,R+b);if(M.length===0)return i?r.json({tenants:[],start:R,limit:b,length:v}):r.json({tenants:[]});const E=M.map(z=>`id:${z}`).join(" OR "),se=u?`(${E}) AND (${u})`:E,N=await r.env.data.tenants.list({q:se,per_page:b,include_totals:!1});return i?r.json({tenants:N.tenants,start:R,limit:b,length:v}):r.json({tenants:N.tenants})}const f=await r.env.data.tenants.list({page:s,per_page:o,include_totals:i,q:u});return i?r.json({tenants:f.tenants,start:((y=f.totals)==null?void 0:y.start)??0,limit:((T=f.totals)==null?void 0:T.limit)??o,length:f.tenants.length}):r.json({tenants:f.tenants})}),n.openapi(I.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:_.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:_.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async r=>{var u,c;const a=r.var.user;if(!(a!=null&&a.sub))throw new S(401,{message:"Authentication required to create tenants"});let s=r.req.valid("json");const o={adapters:r.env.data,ctx:r};(u=t.tenants)!=null&&u.beforeCreate&&(s=await t.tenants.beforeCreate(o,s));const i=await r.env.data.tenants.create(s);return(c=t.tenants)!=null&&c.afterCreate&&await t.tenants.afterCreate(o,i),r.json(i,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 u,c,l,g;const{id:a}=r.req.valid("param"),s=((u=e.accessControl)==null?void 0:u.controlPlaneTenantId)??((c=r.env.data.multiTenancyConfig)==null?void 0:c.controlPlaneTenantId);if(s){const d=r.var.user;if(!(d!=null&&d.sub))throw new S(401,{message:"Authentication required"});if(a===s)throw new S(403,{message:"Cannot delete the control plane"});if(!(await _.fetchAll(w=>r.env.data.userOrganizations.listUserOrganizations(s,d.sub,w),"organizations")).some(w=>w.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 i={adapters:r.env.data,ctx:r};return(l=t.tenants)!=null&&l.beforeDelete&&await t.tenants.beforeDelete(i,a),await r.env.data.tenants.remove(a),(g=t.tenants)!=null&&g.afterDelete&&await t.tenants.afterDelete(i,a),r.body(null,204)}),n}function me(e){const t=[{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 t){const a=e.match(n);if(a&&a[1])return{type:r,id:a[1]}}return null}async function ge(e,t,n){try{switch(n.type){case"resource_server":{const r=await e.resourceServers.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"role":{const r=await e.roles.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"connection":{const r=await e.connections.get(t,n.id);return(r==null?void 0:r.is_system)===!0}default:return!1}}catch{return!1}}function we(e){return{resource_server:"resource server",role:"role",connection:"connection"}[e]}function Z(){return async(e,t)=>{if(!["PATCH","PUT","DELETE"].includes(e.req.method))return t();const n=me(e.req.path);if(!n)return t();const r=e.var.tenant_id||e.req.header("x-tenant-id")||e.req.header("tenant-id");if(!r)return t();if(await ge(e.env.data,r,n))throw new S(403,{message:`This ${we(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}function q(e,t){const n=t.find(a=>a.strategy===e.strategy);if(!(n!=null&&n.options))return e;const r=_.connectionSchema.passthrough().parse({...n,...e});return r.options=_.connectionOptionsSchema.passthrough().parse({...n.options||{},...e.options}),r}function $(e,t){const n=[...t||[],...e||[]];return[...new Set(n)]}function pe(e,t){if(!(t!=null&&t.length))return e||[];if(!(e!=null&&e.length))return t;const n=new Map;for(const r of t)n.set(r.value,r);for(const r of e)n.set(r.value,r);return Array.from(n.values())}function W(e,t){return t?{...e,scopes:pe(e.scopes,t.scopes)}:e}function K(e,t){return t?{...e,callbacks:$(e.callbacks,t.callbacks),web_origins:$(e.web_origins,t.web_origins),allowed_logout_urls:$(e.allowed_logout_urls,t.allowed_logout_urls),allowed_origins:$(e.allowed_origins,t.allowed_origins)}:e}function x(e,t){const{controlPlaneTenantId:n,controlPlaneClientId:r}=t;return{...e,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:r},connections:{...e.connections,get:async(a,s)=>{const o=await e.connections.get(a,s);if(!o||!n||a===n)return o;const i=await e.connections.list(n);return q(o,i.connections||[])},list:async(a,s)=>{const o=await e.connections.list(a,s);if(!n||a===n)return o;const i=await e.connections.list(n),u=o.connections.map(c=>q(c,i.connections||[]));return{...o,connections:u}}},clientConnections:{...e.clientConnections,listByClient:async(a,s)=>{let o=await e.clientConnections.listByClient(a,s);if(o.length===0&&(o=(await e.connections.list(a)).connections||[]),!n||a===n)return o;const i=await e.connections.list(n);return o.map(u=>q(u,i.connections||[]))}},clients:{...e.clients,get:async(a,s)=>{const o=await e.clients.get(a,s);if(!o)return null;if(!n||!r||a===n&&s===r)return o;const i=await e.clients.get(n,r);return K(o,i)},getByClientId:async a=>{const s=await e.clients.getByClientId(a);if(!s)return null;if(!n||!r||s.tenant_id===n&&s.client_id===r)return s;const o=await e.clients.get(n,r);return{...K(s,o),tenant_id:s.tenant_id}}},emailProviders:{...e.emailProviders,get:async a=>{const s=await e.emailProviders.get(a);return s||(!n||a===n?null:e.emailProviders.get(n))}},resourceServers:{...e.resourceServers,get:async(a,s)=>{const o=await e.resourceServers.get(a,s);if(!o||!n||a===n)return o;const u=(await e.resourceServers.list(n,{q:`identifier:${o.identifier}`,per_page:1})).resource_servers[0]??null;return W(o,u)},list:async(a,s)=>{const o=await e.resourceServers.list(a,s);if(!n||a===n)return o;const i=await e.resourceServers.list(n),u=new Map(i.resource_servers.map(l=>[l.identifier,l])),c=o.resource_servers.map(l=>W(l,u.get(l.identifier)??null));return{...o,resource_servers:c}}}}}function k(e,t){return x(e,t)}function ee(e){return async(t,n)=>{const r=t.var.user;return(r==null?void 0:r.tenant_id)===e&&r.org_name&&t.set("tenant_id",r.org_name),n()}}function te(e){return async(t,n)=>{if(!e.accessControl)return n();const{controlPlaneTenantId:r}=e.accessControl,a=t.var.org_name,s=t.var.organization_id,o=a||s;let i=t.var.tenant_id;const u=t.var.user,l=(u!=null&&u.aud?Array.isArray(u.aud)?u.aud:[u.aud]:[]).includes(_.MANAGEMENT_API_AUDIENCE);if(!i&&o&&l&&(t.set("tenant_id",o),i=o),!i)throw new S(400,{message:"Tenant ID not found in request"});if(!V(s,i,r,a))throw new S(403,{message:`Access denied to tenant ${i}`});return n()}}function ne(e){return async(t,n)=>{if(!e.subdomainRouting)return n();const{baseDomain:r,reservedSubdomains:a=[],resolveSubdomain:s}=e.subdomainRouting,o=t.req.header("host")||"";let i=null;if(o.endsWith(r)){const c=o.slice(0,-(r.length+1));c&&!c.includes(".")&&(i=c)}if(i&&a.includes(i)&&(i=null),!i)return e.accessControl&&t.set("tenant_id",e.accessControl.controlPlaneTenantId),n();let u=null;if(s)u=await s(i);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{const c=await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId,i);c&&(u=c.id)}catch{}if(!u)throw new S(404,{message:`Tenant not found for subdomain: ${i}`});return t.set("tenant_id",u),n()}}function re(e){return async(t,n)=>{if(!e.databaseIsolation)return n();const r=t.var.tenant_id;if(!r)throw new S(400,{message:"Tenant ID not found in request"});try{const a=await e.databaseIsolation.getAdapters(r);t.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 j(e){const t=ne(e),n=te(e),r=re(e);return async(a,s)=>(await t(a,async()=>{}),await n(a,async()=>{}),await r(a,async()=>{}),s())}function ye(e){const{dataAdapter:t,controlPlane:n,controlPlane:{tenantId:r="control_plane",clientId:a}={},sync:s={resourceServers:!0,roles:!0},defaultPermissions:o=["tenant:admin"],requireOrganizationMatch:i=!1,managementApiExtensions:u=[],entityHooks:c,getChildTenantIds:l,getAdapters:g,...d}=e;let f=t,m=t;n&&(f=k(t,{controlPlaneTenantId:r,controlPlaneClientId:a}),m={...t,multiTenancyConfig:{controlPlaneTenantId:r,controlPlaneClientId:a}});const w=s!==!1,h=w?{resourceServers:s.resourceServers??!0,roles:s.roles??!0}:{resourceServers:!1,roles:!1},T={controlPlaneTenantId:r,getChildTenantIds:l??(async()=>(await _.fetchAll(M=>f.tenants.list(M),"tenants",{cursorField:"id",pageSize:100})).filter(M=>M.id!==r).map(M=>M.id)),getAdapters:g??(async()=>f),getControlPlaneAdapters:async()=>f,sync:h},{entityHooks:C,tenantHooks:P}=Y(T),v={resourceServers:[C.resourceServers,...(c==null?void 0:c.resourceServers)??[]],roles:[C.roles,...(c==null?void 0:c.roles)??[]],connections:(c==null?void 0:c.connections)??[],tenants:(c==null?void 0:c.tenants)??[],rolePermissions:(c==null?void 0:c.rolePermissions)??[]},A=F({accessControl:{controlPlaneTenantId:r,requireOrganizationMatch:i,defaultPermissions:o}},{tenants:P}),{app:b}=_.init({dataAdapter:f,managementDataAdapter:m,...d,entityHooks:v,managementApiExtensions:[...u,{path:"/tenants",router:A}]});return b.use("/api/v2/*",ee(r)),w&&b.use("/api/v2/*",Z()),{app:b,controlPlaneTenantId:r}}function he(e){const t=O(e);return{name:"multi-tenancy",middleware:j(e),hooks:t,routes:[{path:"/management",handler:F(e,t)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),e.accessControl&&console.log(` - Access control enabled (control plane: ${e.accessControl.controlPlaneTenantId})`),e.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${e.subdomainRouting.baseDomain})`),e.databaseIsolation&&console.log(" - Database isolation enabled")}}}function O(e){const t=e.accessControl?Q(e.accessControl):{},n=e.databaseIsolation?J(e.databaseIsolation):{},r=X(e);return{...t,...n,tenants:r}}function ae(e){const t=new ce.Hono,n=O(e);return t.route("/tenants",F(e,n)),t}function ve(e){return{hooks:O(e),middleware:j(e),app:ae(e),config:e,wrapAdapters:(t,n)=>{var r;return k(t,{controlPlaneTenantId:(r=e.accessControl)==null?void 0:r.controlPlaneTenantId,controlPlaneClientId:n==null?void 0:n.controlPlaneClientId})}}}exports.createAccessControlHooks=Q;exports.createAccessControlMiddleware=te;exports.createControlPlaneTenantMiddleware=ee;exports.createDatabaseHooks=J;exports.createDatabaseMiddleware=re;exports.createMultiTenancy=ae;exports.createMultiTenancyHooks=O;exports.createMultiTenancyMiddleware=j;exports.createMultiTenancyPlugin=he;exports.createProtectSyncedMiddleware=Z;exports.createProvisioningHooks=X;exports.createRuntimeFallbackAdapter=x;exports.createSubdomainMiddleware=ne;exports.createSyncHooks=Y;exports.createTenantsOpenAPIRouter=F;exports.initMultiTenant=ye;exports.setupMultiTenancy=ve;exports.validateTenantAccess=V;exports.withRuntimeFallback=k;
|
package/dist/multi-tenancy.mjs
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { Hono as
|
|
5
|
-
import { MANAGEMENT_API_SCOPES as
|
|
6
|
-
import { OpenAPIHono as
|
|
7
|
-
function
|
|
1
|
+
var Y = Object.defineProperty;
|
|
2
|
+
var Z = (e, t, n) => t in e ? Y(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
|
|
3
|
+
var M = (e, t, n) => Z(e, typeof t != "symbol" ? t + "" : t, n);
|
|
4
|
+
import { Hono as x } from "hono";
|
|
5
|
+
import { MANAGEMENT_API_SCOPES as ee, MANAGEMENT_API_AUDIENCE as Q, fetchAll as z, auth0QuerySchema as te, tenantSchema as N, tenantInsertSchema as ne, connectionSchema as re, connectionOptionsSchema as se, init as ae } from "authhero";
|
|
6
|
+
import { OpenAPIHono as oe, createRoute as O, z as S } from "@hono/zod-openapi";
|
|
7
|
+
function ie(e) {
|
|
8
8
|
const { controlPlaneTenantId: t, requireOrganizationMatch: n = !0 } = e;
|
|
9
9
|
return {
|
|
10
|
-
async onTenantAccessValidation(r,
|
|
11
|
-
if (
|
|
10
|
+
async onTenantAccessValidation(r, s) {
|
|
11
|
+
if (s === t)
|
|
12
12
|
return !0;
|
|
13
13
|
if (n) {
|
|
14
|
-
const
|
|
15
|
-
return i ? i.toLowerCase() ===
|
|
14
|
+
const a = r.var.org_name, o = r.var.organization_id, i = a || o;
|
|
15
|
+
return i ? i.toLowerCase() === s.toLowerCase() : !1;
|
|
16
16
|
}
|
|
17
17
|
return !0;
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
function
|
|
21
|
+
function ce(e, t, n, r) {
|
|
22
22
|
if (t === n)
|
|
23
23
|
return !0;
|
|
24
|
-
const
|
|
25
|
-
return
|
|
24
|
+
const s = r || e;
|
|
25
|
+
return s ? s.toLowerCase() === t.toLowerCase() : !1;
|
|
26
26
|
}
|
|
27
|
-
function
|
|
27
|
+
function le(e) {
|
|
28
28
|
return {
|
|
29
29
|
async resolveDataAdapters(t) {
|
|
30
30
|
try {
|
|
@@ -39,23 +39,23 @@ function ce(e) {
|
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
-
function
|
|
42
|
+
function ue(e) {
|
|
43
43
|
return `urn:authhero:tenant:${e.toLowerCase()}`;
|
|
44
44
|
}
|
|
45
|
-
function
|
|
45
|
+
function de(e) {
|
|
46
46
|
return {
|
|
47
47
|
async beforeCreate(t, n) {
|
|
48
48
|
return !n.audience && n.id ? {
|
|
49
49
|
...n,
|
|
50
|
-
audience:
|
|
50
|
+
audience: ue(n.id)
|
|
51
51
|
} : n;
|
|
52
52
|
},
|
|
53
53
|
async afterCreate(t, n) {
|
|
54
|
-
const { accessControl: r, databaseIsolation:
|
|
55
|
-
r && t.ctx && await
|
|
54
|
+
const { accessControl: r, databaseIsolation: s } = e;
|
|
55
|
+
r && t.ctx && await fe(t, n, r), s != null && s.onProvision && await s.onProvision(n.id);
|
|
56
56
|
},
|
|
57
57
|
async beforeDelete(t, n) {
|
|
58
|
-
const { accessControl: r, databaseIsolation:
|
|
58
|
+
const { accessControl: r, databaseIsolation: s } = e;
|
|
59
59
|
if (r)
|
|
60
60
|
try {
|
|
61
61
|
const o = (await t.adapters.organizations.list(
|
|
@@ -65,29 +65,29 @@ function ue(e) {
|
|
|
65
65
|
r.controlPlaneTenantId,
|
|
66
66
|
o.id
|
|
67
67
|
);
|
|
68
|
-
} catch (
|
|
68
|
+
} catch (a) {
|
|
69
69
|
console.warn(
|
|
70
70
|
`Failed to remove organization for tenant ${n}:`,
|
|
71
|
-
|
|
71
|
+
a
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
|
-
if (
|
|
74
|
+
if (s != null && s.onDeprovision)
|
|
75
75
|
try {
|
|
76
|
-
await
|
|
77
|
-
} catch (
|
|
76
|
+
await s.onDeprovision(n);
|
|
77
|
+
} catch (a) {
|
|
78
78
|
console.warn(
|
|
79
79
|
`Failed to deprovision database for tenant ${n}:`,
|
|
80
|
-
|
|
80
|
+
a
|
|
81
81
|
);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
|
-
async function
|
|
86
|
+
async function fe(e, t, n) {
|
|
87
87
|
const {
|
|
88
88
|
controlPlaneTenantId: r,
|
|
89
|
-
defaultPermissions:
|
|
90
|
-
defaultRoles:
|
|
89
|
+
defaultPermissions: s,
|
|
90
|
+
defaultRoles: a,
|
|
91
91
|
issuer: o,
|
|
92
92
|
adminRoleName: i = "Tenant Admin",
|
|
93
93
|
adminRoleDescription: u = "Full access to all tenant management operations",
|
|
@@ -100,14 +100,14 @@ async function de(e, t, n) {
|
|
|
100
100
|
}
|
|
101
101
|
);
|
|
102
102
|
let g;
|
|
103
|
-
if (o && (g = await
|
|
103
|
+
if (o && (g = await ge(
|
|
104
104
|
e,
|
|
105
105
|
r,
|
|
106
106
|
i,
|
|
107
107
|
u
|
|
108
108
|
)), c && e.ctx) {
|
|
109
109
|
const d = e.ctx.var.user;
|
|
110
|
-
if (d != null && d.sub && !await
|
|
110
|
+
if (d != null && d.sub && !await me(
|
|
111
111
|
e,
|
|
112
112
|
r,
|
|
113
113
|
d.sub
|
|
@@ -130,13 +130,13 @@ async function de(e, t, n) {
|
|
|
130
130
|
);
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
|
|
134
|
-
`Would assign roles ${
|
|
135
|
-
),
|
|
136
|
-
`Would grant permissions ${
|
|
133
|
+
a && a.length > 0 && console.log(
|
|
134
|
+
`Would assign roles ${a.join(", ")} to organization ${l.id}`
|
|
135
|
+
), s && s.length > 0 && console.log(
|
|
136
|
+
`Would grant permissions ${s.join(", ")} to organization ${l.id}`
|
|
137
137
|
);
|
|
138
138
|
}
|
|
139
|
-
async function
|
|
139
|
+
async function me(e, t, n) {
|
|
140
140
|
const r = await e.adapters.userRoles.list(
|
|
141
141
|
t,
|
|
142
142
|
n,
|
|
@@ -144,10 +144,10 @@ async function fe(e, t, n) {
|
|
|
144
144
|
""
|
|
145
145
|
// Empty string for global roles
|
|
146
146
|
);
|
|
147
|
-
for (const
|
|
147
|
+
for (const s of r)
|
|
148
148
|
if ((await e.adapters.rolePermissions.list(
|
|
149
149
|
t,
|
|
150
|
-
|
|
150
|
+
s.id,
|
|
151
151
|
{ per_page: 1e3 }
|
|
152
152
|
)).some(
|
|
153
153
|
(i) => i.permission_name === "admin:organizations"
|
|
@@ -155,14 +155,14 @@ async function fe(e, t, n) {
|
|
|
155
155
|
return !0;
|
|
156
156
|
return !1;
|
|
157
157
|
}
|
|
158
|
-
async function
|
|
159
|
-
const
|
|
160
|
-
if (
|
|
161
|
-
return
|
|
158
|
+
async function ge(e, t, n, r) {
|
|
159
|
+
const a = (await e.adapters.roles.list(t, {})).roles.find((c) => c.name === n);
|
|
160
|
+
if (a)
|
|
161
|
+
return a.id;
|
|
162
162
|
const o = await e.adapters.roles.create(t, {
|
|
163
163
|
name: n,
|
|
164
164
|
description: r
|
|
165
|
-
}), i =
|
|
165
|
+
}), i = Q, u = ee.map((c) => ({
|
|
166
166
|
role_id: o.id,
|
|
167
167
|
resource_server_identifier: i,
|
|
168
168
|
permission_name: c.value
|
|
@@ -174,7 +174,7 @@ async function me(e, t, n, r) {
|
|
|
174
174
|
), o.id;
|
|
175
175
|
}
|
|
176
176
|
function H(e, t, n = () => !0) {
|
|
177
|
-
const { controlPlaneTenantId: r, getChildTenantIds:
|
|
177
|
+
const { controlPlaneTenantId: r, getChildTenantIds: s, getAdapters: a } = e, o = /* @__PURE__ */ new Map();
|
|
178
178
|
async function i(l, g, d) {
|
|
179
179
|
return (await t(l).list(g, {
|
|
180
180
|
q: `name:${d}`,
|
|
@@ -182,11 +182,11 @@ function H(e, t, n = () => !0) {
|
|
|
182
182
|
}))[0] ?? null;
|
|
183
183
|
}
|
|
184
184
|
async function u(l) {
|
|
185
|
-
const g = await
|
|
185
|
+
const g = await s(), d = t(await a(r));
|
|
186
186
|
await Promise.all(
|
|
187
187
|
g.map(async (f) => {
|
|
188
188
|
try {
|
|
189
|
-
const m = await
|
|
189
|
+
const m = await a(f), w = t(m), p = {
|
|
190
190
|
...d.transform(l),
|
|
191
191
|
is_system: !0
|
|
192
192
|
}, y = await i(m, f, l.name), _ = y ? w.getId(y) : void 0;
|
|
@@ -205,11 +205,11 @@ function H(e, t, n = () => !0) {
|
|
|
205
205
|
);
|
|
206
206
|
}
|
|
207
207
|
async function c(l) {
|
|
208
|
-
const g = await
|
|
208
|
+
const g = await s();
|
|
209
209
|
await Promise.all(
|
|
210
210
|
g.map(async (d) => {
|
|
211
211
|
try {
|
|
212
|
-
const f = await
|
|
212
|
+
const f = await a(d), m = t(f), w = await i(f, d, l), h = w ? m.getId(w) : void 0;
|
|
213
213
|
w && h && await m.remove(d, h);
|
|
214
214
|
} catch (f) {
|
|
215
215
|
console.error(
|
|
@@ -240,12 +240,12 @@ function H(e, t, n = () => !0) {
|
|
|
240
240
|
};
|
|
241
241
|
}
|
|
242
242
|
function B(e, t, n = () => !0) {
|
|
243
|
-
const { controlPlaneTenantId: r, getControlPlaneAdapters:
|
|
243
|
+
const { controlPlaneTenantId: r, getControlPlaneAdapters: s, getAdapters: a } = e;
|
|
244
244
|
return {
|
|
245
245
|
async afterCreate(o, i) {
|
|
246
246
|
if (i.id !== r)
|
|
247
247
|
try {
|
|
248
|
-
const u = await
|
|
248
|
+
const u = await s(), c = await a(i.id), l = t(u), g = t(c), d = await z(
|
|
249
249
|
(f) => l.listPaginated(r, f),
|
|
250
250
|
l.listKey,
|
|
251
251
|
{ cursorField: "id", pageSize: 100 }
|
|
@@ -312,30 +312,30 @@ function L(e) {
|
|
|
312
312
|
var t;
|
|
313
313
|
return ((t = e.metadata) == null ? void 0 : t.sync) !== !1;
|
|
314
314
|
}
|
|
315
|
-
function
|
|
316
|
-
const { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0,
|
|
315
|
+
function we(e) {
|
|
316
|
+
const { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, s = t.roles ?? !0, a = (m) => L(m) ? n.resourceServers ? n.resourceServers(m) : !0 : !1, o = (m) => L(m) ? n.roles ? n.roles(m) : !0 : !1, i = r ? H(
|
|
317
317
|
e,
|
|
318
318
|
G,
|
|
319
|
-
|
|
320
|
-
) : void 0, u =
|
|
319
|
+
a
|
|
320
|
+
) : void 0, u = s ? H(
|
|
321
321
|
e,
|
|
322
322
|
U,
|
|
323
323
|
o
|
|
324
324
|
) : void 0, c = r ? B(
|
|
325
325
|
e,
|
|
326
326
|
G,
|
|
327
|
-
|
|
328
|
-
) : void 0, l =
|
|
327
|
+
a
|
|
328
|
+
) : void 0, l = s ? B(
|
|
329
329
|
e,
|
|
330
330
|
U,
|
|
331
331
|
o
|
|
332
|
-
) : void 0, g =
|
|
332
|
+
) : void 0, g = s ? {
|
|
333
333
|
async afterCreate(m, w) {
|
|
334
334
|
var h;
|
|
335
335
|
if (w.id !== e.controlPlaneTenantId) {
|
|
336
336
|
await ((h = l == null ? void 0 : l.afterCreate) == null ? void 0 : h.call(l, m, w));
|
|
337
337
|
try {
|
|
338
|
-
const p = await e.getControlPlaneAdapters(), y = await e.getAdapters(w.id), _ = await
|
|
338
|
+
const p = await e.getControlPlaneAdapters(), y = await e.getAdapters(w.id), _ = await z(
|
|
339
339
|
(C) => p.roles.list(
|
|
340
340
|
e.controlPlaneTenantId,
|
|
341
341
|
C
|
|
@@ -437,8 +437,8 @@ var b = class extends Error {
|
|
|
437
437
|
*/
|
|
438
438
|
constructor(t = 500, n) {
|
|
439
439
|
super(n == null ? void 0 : n.message, { cause: n == null ? void 0 : n.cause });
|
|
440
|
-
|
|
441
|
-
|
|
440
|
+
M(this, "res");
|
|
441
|
+
M(this, "status");
|
|
442
442
|
this.res = n == null ? void 0 : n.res, this.status = t;
|
|
443
443
|
}
|
|
444
444
|
/**
|
|
@@ -456,14 +456,14 @@ var b = class extends Error {
|
|
|
456
456
|
}
|
|
457
457
|
};
|
|
458
458
|
function q(e, t) {
|
|
459
|
-
const n = new
|
|
459
|
+
const n = new oe();
|
|
460
460
|
return n.openapi(
|
|
461
|
-
|
|
461
|
+
O({
|
|
462
462
|
tags: ["tenants"],
|
|
463
463
|
method: "get",
|
|
464
464
|
path: "/",
|
|
465
465
|
request: {
|
|
466
|
-
query:
|
|
466
|
+
query: te
|
|
467
467
|
},
|
|
468
468
|
security: [
|
|
469
469
|
{
|
|
@@ -488,10 +488,10 @@ function q(e, t) {
|
|
|
488
488
|
}),
|
|
489
489
|
async (r) => {
|
|
490
490
|
var m, w, h, p, y, _;
|
|
491
|
-
const
|
|
491
|
+
const s = r.req.valid("query"), { page: a, per_page: o, include_totals: i, q: u } = s, c = r.var.user, l = (c == null ? void 0 : c.permissions) || [];
|
|
492
492
|
if (l.includes("auth:read") || l.includes("admin:organizations")) {
|
|
493
493
|
const T = await r.env.data.tenants.list({
|
|
494
|
-
page:
|
|
494
|
+
page: a,
|
|
495
495
|
per_page: o,
|
|
496
496
|
include_totals: i,
|
|
497
497
|
q: u
|
|
@@ -505,14 +505,14 @@ function q(e, t) {
|
|
|
505
505
|
}
|
|
506
506
|
const d = ((h = e.accessControl) == null ? void 0 : h.controlPlaneTenantId) ?? ((p = r.env.data.multiTenancyConfig) == null ? void 0 : p.controlPlaneTenantId);
|
|
507
507
|
if (d && (c != null && c.sub)) {
|
|
508
|
-
const C = (await
|
|
509
|
-
(
|
|
508
|
+
const C = (await z(
|
|
509
|
+
($) => r.env.data.userOrganizations.listUserOrganizations(
|
|
510
510
|
d,
|
|
511
511
|
c.sub,
|
|
512
|
-
|
|
512
|
+
$
|
|
513
513
|
),
|
|
514
514
|
"organizations"
|
|
515
|
-
)).map((
|
|
515
|
+
)).map(($) => $.name);
|
|
516
516
|
if (C.length === 0)
|
|
517
517
|
return i ? r.json({
|
|
518
518
|
tenants: [],
|
|
@@ -520,29 +520,29 @@ function q(e, t) {
|
|
|
520
520
|
limit: o ?? 50,
|
|
521
521
|
length: 0
|
|
522
522
|
}) : r.json({ tenants: [] });
|
|
523
|
-
const v = C.length, P =
|
|
523
|
+
const v = C.length, P = a ?? 0, A = o ?? 50, R = P * A, I = C.slice(R, R + A);
|
|
524
524
|
if (I.length === 0)
|
|
525
525
|
return i ? r.json({
|
|
526
526
|
tenants: [],
|
|
527
|
-
start:
|
|
527
|
+
start: R,
|
|
528
528
|
limit: A,
|
|
529
529
|
length: v
|
|
530
530
|
}) : r.json({ tenants: [] });
|
|
531
|
-
const k = I.map((
|
|
532
|
-
q:
|
|
531
|
+
const k = I.map(($) => `id:${$}`).join(" OR "), X = u ? `(${k}) AND (${u})` : k, E = await r.env.data.tenants.list({
|
|
532
|
+
q: X,
|
|
533
533
|
per_page: A,
|
|
534
534
|
include_totals: !1
|
|
535
535
|
// We calculate totals from accessibleTenantIds
|
|
536
536
|
});
|
|
537
537
|
return i ? r.json({
|
|
538
538
|
tenants: E.tenants,
|
|
539
|
-
start:
|
|
539
|
+
start: R,
|
|
540
540
|
limit: A,
|
|
541
541
|
length: v
|
|
542
542
|
}) : r.json({ tenants: E.tenants });
|
|
543
543
|
}
|
|
544
544
|
const f = await r.env.data.tenants.list({
|
|
545
|
-
page:
|
|
545
|
+
page: a,
|
|
546
546
|
per_page: o,
|
|
547
547
|
include_totals: i,
|
|
548
548
|
q: u
|
|
@@ -555,7 +555,7 @@ function q(e, t) {
|
|
|
555
555
|
}) : r.json({ tenants: f.tenants });
|
|
556
556
|
}
|
|
557
557
|
), n.openapi(
|
|
558
|
-
|
|
558
|
+
O({
|
|
559
559
|
tags: ["tenants"],
|
|
560
560
|
method: "post",
|
|
561
561
|
path: "/",
|
|
@@ -563,7 +563,7 @@ function q(e, t) {
|
|
|
563
563
|
body: {
|
|
564
564
|
content: {
|
|
565
565
|
"application/json": {
|
|
566
|
-
schema:
|
|
566
|
+
schema: ne
|
|
567
567
|
}
|
|
568
568
|
}
|
|
569
569
|
}
|
|
@@ -592,22 +592,22 @@ function q(e, t) {
|
|
|
592
592
|
}),
|
|
593
593
|
async (r) => {
|
|
594
594
|
var u, c;
|
|
595
|
-
const
|
|
596
|
-
if (!(
|
|
595
|
+
const s = r.var.user;
|
|
596
|
+
if (!(s != null && s.sub))
|
|
597
597
|
throw new b(401, {
|
|
598
598
|
message: "Authentication required to create tenants"
|
|
599
599
|
});
|
|
600
|
-
let
|
|
600
|
+
let a = r.req.valid("json");
|
|
601
601
|
const o = {
|
|
602
602
|
adapters: r.env.data,
|
|
603
603
|
ctx: r
|
|
604
604
|
};
|
|
605
|
-
(u = t.tenants) != null && u.beforeCreate && (
|
|
606
|
-
const i = await r.env.data.tenants.create(
|
|
605
|
+
(u = t.tenants) != null && u.beforeCreate && (a = await t.tenants.beforeCreate(o, a));
|
|
606
|
+
const i = await r.env.data.tenants.create(a);
|
|
607
607
|
return (c = t.tenants) != null && c.afterCreate && await t.tenants.afterCreate(o, i), r.json(i, 201);
|
|
608
608
|
}
|
|
609
609
|
), n.openapi(
|
|
610
|
-
|
|
610
|
+
O({
|
|
611
611
|
tags: ["tenants"],
|
|
612
612
|
method: "delete",
|
|
613
613
|
path: "/{id}",
|
|
@@ -635,30 +635,30 @@ function q(e, t) {
|
|
|
635
635
|
}),
|
|
636
636
|
async (r) => {
|
|
637
637
|
var u, c, l, g;
|
|
638
|
-
const { id:
|
|
639
|
-
if (
|
|
638
|
+
const { id: s } = r.req.valid("param"), a = ((u = e.accessControl) == null ? void 0 : u.controlPlaneTenantId) ?? ((c = r.env.data.multiTenancyConfig) == null ? void 0 : c.controlPlaneTenantId);
|
|
639
|
+
if (a) {
|
|
640
640
|
const d = r.var.user;
|
|
641
641
|
if (!(d != null && d.sub))
|
|
642
642
|
throw new b(401, {
|
|
643
643
|
message: "Authentication required"
|
|
644
644
|
});
|
|
645
|
-
if (
|
|
645
|
+
if (s === a)
|
|
646
646
|
throw new b(403, {
|
|
647
647
|
message: "Cannot delete the control plane"
|
|
648
648
|
});
|
|
649
|
-
if (!(await
|
|
649
|
+
if (!(await z(
|
|
650
650
|
(w) => r.env.data.userOrganizations.listUserOrganizations(
|
|
651
|
-
|
|
651
|
+
a,
|
|
652
652
|
d.sub,
|
|
653
653
|
w
|
|
654
654
|
),
|
|
655
655
|
"organizations"
|
|
656
|
-
)).some((w) => w.name ===
|
|
656
|
+
)).some((w) => w.name === s))
|
|
657
657
|
throw new b(403, {
|
|
658
658
|
message: "Access denied to this tenant"
|
|
659
659
|
});
|
|
660
660
|
}
|
|
661
|
-
if (!await r.env.data.tenants.get(
|
|
661
|
+
if (!await r.env.data.tenants.get(s))
|
|
662
662
|
throw new b(404, {
|
|
663
663
|
message: "Tenant not found"
|
|
664
664
|
});
|
|
@@ -666,11 +666,11 @@ function q(e, t) {
|
|
|
666
666
|
adapters: r.env.data,
|
|
667
667
|
ctx: r
|
|
668
668
|
};
|
|
669
|
-
return (l = t.tenants) != null && l.beforeDelete && await t.tenants.beforeDelete(i,
|
|
669
|
+
return (l = t.tenants) != null && l.beforeDelete && await t.tenants.beforeDelete(i, s), await r.env.data.tenants.remove(s), (g = t.tenants) != null && g.afterDelete && await t.tenants.afterDelete(i, s), r.body(null, 204);
|
|
670
670
|
}
|
|
671
671
|
), n;
|
|
672
672
|
}
|
|
673
|
-
function
|
|
673
|
+
function pe(e) {
|
|
674
674
|
const t = [
|
|
675
675
|
{
|
|
676
676
|
pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
|
|
@@ -680,13 +680,13 @@ function we(e) {
|
|
|
680
680
|
{ pattern: /\/api\/v2\/connections\/([^/]+)$/, type: "connection" }
|
|
681
681
|
];
|
|
682
682
|
for (const { pattern: n, type: r } of t) {
|
|
683
|
-
const
|
|
684
|
-
if (
|
|
685
|
-
return { type: r, id:
|
|
683
|
+
const s = e.match(n);
|
|
684
|
+
if (s && s[1])
|
|
685
|
+
return { type: r, id: s[1] };
|
|
686
686
|
}
|
|
687
687
|
return null;
|
|
688
688
|
}
|
|
689
|
-
async function
|
|
689
|
+
async function ye(e, t, n) {
|
|
690
690
|
try {
|
|
691
691
|
switch (n.type) {
|
|
692
692
|
case "resource_server": {
|
|
@@ -708,41 +708,41 @@ async function pe(e, t, n) {
|
|
|
708
708
|
return !1;
|
|
709
709
|
}
|
|
710
710
|
}
|
|
711
|
-
function
|
|
711
|
+
function he(e) {
|
|
712
712
|
return {
|
|
713
713
|
resource_server: "resource server",
|
|
714
714
|
role: "role",
|
|
715
715
|
connection: "connection"
|
|
716
716
|
}[e];
|
|
717
717
|
}
|
|
718
|
-
function
|
|
718
|
+
function ve() {
|
|
719
719
|
return async (e, t) => {
|
|
720
720
|
if (!["PATCH", "PUT", "DELETE"].includes(e.req.method))
|
|
721
721
|
return t();
|
|
722
|
-
const n =
|
|
722
|
+
const n = pe(e.req.path);
|
|
723
723
|
if (!n)
|
|
724
724
|
return t();
|
|
725
725
|
const r = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
|
|
726
726
|
if (!r)
|
|
727
727
|
return t();
|
|
728
|
-
if (await
|
|
728
|
+
if (await ye(e.env.data, r, n))
|
|
729
729
|
throw new b(403, {
|
|
730
|
-
message: `This ${
|
|
730
|
+
message: `This ${he(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`
|
|
731
731
|
});
|
|
732
732
|
return t();
|
|
733
733
|
};
|
|
734
734
|
}
|
|
735
|
-
function
|
|
735
|
+
function D(e, t) {
|
|
736
736
|
const n = t.find(
|
|
737
|
-
(
|
|
737
|
+
(s) => s.strategy === e.strategy
|
|
738
738
|
);
|
|
739
739
|
if (!(n != null && n.options))
|
|
740
740
|
return e;
|
|
741
|
-
const r =
|
|
741
|
+
const r = re.passthrough().parse({
|
|
742
742
|
...n,
|
|
743
743
|
...e
|
|
744
744
|
});
|
|
745
|
-
return r.options =
|
|
745
|
+
return r.options = se.passthrough().parse({
|
|
746
746
|
...n.options || {},
|
|
747
747
|
...e.options
|
|
748
748
|
}), r;
|
|
@@ -754,7 +754,28 @@ function F(e, t) {
|
|
|
754
754
|
];
|
|
755
755
|
return [...new Set(n)];
|
|
756
756
|
}
|
|
757
|
+
function _e(e, t) {
|
|
758
|
+
if (!(t != null && t.length))
|
|
759
|
+
return e || [];
|
|
760
|
+
if (!(e != null && e.length))
|
|
761
|
+
return t;
|
|
762
|
+
const n = /* @__PURE__ */ new Map();
|
|
763
|
+
for (const r of t)
|
|
764
|
+
n.set(r.value, r);
|
|
765
|
+
for (const r of e)
|
|
766
|
+
n.set(r.value, r);
|
|
767
|
+
return Array.from(n.values());
|
|
768
|
+
}
|
|
757
769
|
function W(e, t) {
|
|
770
|
+
return t ? {
|
|
771
|
+
...e,
|
|
772
|
+
scopes: _e(
|
|
773
|
+
e.scopes,
|
|
774
|
+
t.scopes
|
|
775
|
+
)
|
|
776
|
+
} : e;
|
|
777
|
+
}
|
|
778
|
+
function K(e, t) {
|
|
758
779
|
return t ? {
|
|
759
780
|
...e,
|
|
760
781
|
callbacks: F(e.callbacks, t.callbacks),
|
|
@@ -772,7 +793,7 @@ function W(e, t) {
|
|
|
772
793
|
)
|
|
773
794
|
} : e;
|
|
774
795
|
}
|
|
775
|
-
function
|
|
796
|
+
function Te(e, t) {
|
|
776
797
|
const { controlPlaneTenantId: n, controlPlaneClientId: r } = t;
|
|
777
798
|
return {
|
|
778
799
|
...e,
|
|
@@ -783,25 +804,25 @@ function ve(e, t) {
|
|
|
783
804
|
},
|
|
784
805
|
connections: {
|
|
785
806
|
...e.connections,
|
|
786
|
-
get: async (
|
|
807
|
+
get: async (s, a) => {
|
|
787
808
|
const o = await e.connections.get(
|
|
788
|
-
|
|
789
|
-
|
|
809
|
+
s,
|
|
810
|
+
a
|
|
790
811
|
);
|
|
791
|
-
if (!o || !n ||
|
|
812
|
+
if (!o || !n || s === n)
|
|
792
813
|
return o;
|
|
793
814
|
const i = await e.connections.list(n);
|
|
794
|
-
return
|
|
815
|
+
return D(
|
|
795
816
|
o,
|
|
796
817
|
i.connections || []
|
|
797
818
|
);
|
|
798
819
|
},
|
|
799
|
-
list: async (
|
|
800
|
-
const o = await e.connections.list(
|
|
801
|
-
if (!n ||
|
|
820
|
+
list: async (s, a) => {
|
|
821
|
+
const o = await e.connections.list(s, a);
|
|
822
|
+
if (!n || s === n)
|
|
802
823
|
return o;
|
|
803
824
|
const i = await e.connections.list(n), u = o.connections.map(
|
|
804
|
-
(c) =>
|
|
825
|
+
(c) => D(
|
|
805
826
|
c,
|
|
806
827
|
i.connections || []
|
|
807
828
|
)
|
|
@@ -814,16 +835,16 @@ function ve(e, t) {
|
|
|
814
835
|
},
|
|
815
836
|
clientConnections: {
|
|
816
837
|
...e.clientConnections,
|
|
817
|
-
listByClient: async (
|
|
838
|
+
listByClient: async (s, a) => {
|
|
818
839
|
let o = await e.clientConnections.listByClient(
|
|
819
|
-
|
|
820
|
-
|
|
840
|
+
s,
|
|
841
|
+
a
|
|
821
842
|
);
|
|
822
|
-
if (o.length === 0 && (o = (await e.connections.list(
|
|
843
|
+
if (o.length === 0 && (o = (await e.connections.list(s)).connections || []), !n || s === n)
|
|
823
844
|
return o;
|
|
824
845
|
const i = await e.connections.list(n);
|
|
825
846
|
return o.map(
|
|
826
|
-
(u) =>
|
|
847
|
+
(u) => D(
|
|
827
848
|
u,
|
|
828
849
|
i.connections || []
|
|
829
850
|
)
|
|
@@ -832,39 +853,77 @@ function ve(e, t) {
|
|
|
832
853
|
},
|
|
833
854
|
clients: {
|
|
834
855
|
...e.clients,
|
|
835
|
-
get: async (
|
|
836
|
-
const o = await e.clients.get(
|
|
856
|
+
get: async (s, a) => {
|
|
857
|
+
const o = await e.clients.get(s, a);
|
|
837
858
|
if (!o)
|
|
838
859
|
return null;
|
|
839
|
-
if (!n || !r ||
|
|
860
|
+
if (!n || !r || s === n && a === r)
|
|
840
861
|
return o;
|
|
841
862
|
const i = await e.clients.get(
|
|
842
863
|
n,
|
|
843
864
|
r
|
|
844
865
|
);
|
|
845
|
-
return
|
|
866
|
+
return K(o, i);
|
|
846
867
|
},
|
|
847
|
-
getByClientId: async (
|
|
848
|
-
const
|
|
849
|
-
if (!
|
|
868
|
+
getByClientId: async (s) => {
|
|
869
|
+
const a = await e.clients.getByClientId(s);
|
|
870
|
+
if (!a)
|
|
850
871
|
return null;
|
|
851
|
-
if (!n || !r ||
|
|
852
|
-
return
|
|
872
|
+
if (!n || !r || a.tenant_id === n && a.client_id === r)
|
|
873
|
+
return a;
|
|
853
874
|
const o = await e.clients.get(
|
|
854
875
|
n,
|
|
855
876
|
r
|
|
856
877
|
);
|
|
857
878
|
return {
|
|
858
|
-
...
|
|
859
|
-
tenant_id:
|
|
879
|
+
...K(a, o),
|
|
880
|
+
tenant_id: a.tenant_id
|
|
860
881
|
};
|
|
861
882
|
}
|
|
862
883
|
},
|
|
863
884
|
emailProviders: {
|
|
864
885
|
...e.emailProviders,
|
|
865
|
-
get: async (
|
|
866
|
-
const
|
|
867
|
-
return
|
|
886
|
+
get: async (s) => {
|
|
887
|
+
const a = await e.emailProviders.get(s);
|
|
888
|
+
return a || (!n || s === n ? null : e.emailProviders.get(n));
|
|
889
|
+
}
|
|
890
|
+
},
|
|
891
|
+
resourceServers: {
|
|
892
|
+
...e.resourceServers,
|
|
893
|
+
get: async (s, a) => {
|
|
894
|
+
const o = await e.resourceServers.get(
|
|
895
|
+
s,
|
|
896
|
+
a
|
|
897
|
+
);
|
|
898
|
+
if (!o || !n || s === n)
|
|
899
|
+
return o;
|
|
900
|
+
const u = (await e.resourceServers.list(
|
|
901
|
+
n,
|
|
902
|
+
{ q: `identifier:${o.identifier}`, per_page: 1 }
|
|
903
|
+
)).resource_servers[0] ?? null;
|
|
904
|
+
return W(
|
|
905
|
+
o,
|
|
906
|
+
u
|
|
907
|
+
);
|
|
908
|
+
},
|
|
909
|
+
list: async (s, a) => {
|
|
910
|
+
const o = await e.resourceServers.list(s, a);
|
|
911
|
+
if (!n || s === n)
|
|
912
|
+
return o;
|
|
913
|
+
const i = await e.resourceServers.list(
|
|
914
|
+
n
|
|
915
|
+
), u = new Map(
|
|
916
|
+
i.resource_servers.map((l) => [l.identifier, l])
|
|
917
|
+
), c = o.resource_servers.map(
|
|
918
|
+
(l) => W(
|
|
919
|
+
l,
|
|
920
|
+
u.get(l.identifier) ?? null
|
|
921
|
+
)
|
|
922
|
+
);
|
|
923
|
+
return {
|
|
924
|
+
...o,
|
|
925
|
+
resource_servers: c
|
|
926
|
+
};
|
|
868
927
|
}
|
|
869
928
|
}
|
|
870
929
|
// Note: Additional adapters can be extended here for runtime fallback:
|
|
@@ -872,31 +931,31 @@ function ve(e, t) {
|
|
|
872
931
|
// - branding: Fall back to control plane branding/themes
|
|
873
932
|
};
|
|
874
933
|
}
|
|
875
|
-
function
|
|
876
|
-
return
|
|
934
|
+
function V(e, t) {
|
|
935
|
+
return Te(e, t);
|
|
877
936
|
}
|
|
878
|
-
function
|
|
937
|
+
function Ce(e) {
|
|
879
938
|
return async (t, n) => {
|
|
880
939
|
const r = t.var.user;
|
|
881
940
|
return (r == null ? void 0 : r.tenant_id) === e && r.org_name && t.set("tenant_id", r.org_name), n();
|
|
882
941
|
};
|
|
883
942
|
}
|
|
884
|
-
function
|
|
943
|
+
function Pe(e) {
|
|
885
944
|
return async (t, n) => {
|
|
886
945
|
if (!e.accessControl)
|
|
887
946
|
return n();
|
|
888
|
-
const { controlPlaneTenantId: r } = e.accessControl,
|
|
947
|
+
const { controlPlaneTenantId: r } = e.accessControl, s = t.var.org_name, a = t.var.organization_id, o = s || a;
|
|
889
948
|
let i = t.var.tenant_id;
|
|
890
|
-
const u = t.var.user, l = (u != null && u.aud ? Array.isArray(u.aud) ? u.aud : [u.aud] : []).includes(
|
|
949
|
+
const u = t.var.user, l = (u != null && u.aud ? Array.isArray(u.aud) ? u.aud : [u.aud] : []).includes(Q);
|
|
891
950
|
if (!i && o && l && (t.set("tenant_id", o), i = o), !i)
|
|
892
951
|
throw new b(400, {
|
|
893
952
|
message: "Tenant ID not found in request"
|
|
894
953
|
});
|
|
895
|
-
if (!
|
|
896
|
-
|
|
954
|
+
if (!ce(
|
|
955
|
+
a,
|
|
897
956
|
i,
|
|
898
957
|
r,
|
|
899
|
-
|
|
958
|
+
s
|
|
900
959
|
))
|
|
901
960
|
throw new b(403, {
|
|
902
961
|
message: `Access denied to tenant ${i}`
|
|
@@ -904,25 +963,25 @@ function Te(e) {
|
|
|
904
963
|
return n();
|
|
905
964
|
};
|
|
906
965
|
}
|
|
907
|
-
function
|
|
966
|
+
function Ae(e) {
|
|
908
967
|
return async (t, n) => {
|
|
909
968
|
if (!e.subdomainRouting)
|
|
910
969
|
return n();
|
|
911
970
|
const {
|
|
912
971
|
baseDomain: r,
|
|
913
|
-
reservedSubdomains:
|
|
914
|
-
resolveSubdomain:
|
|
972
|
+
reservedSubdomains: s = [],
|
|
973
|
+
resolveSubdomain: a
|
|
915
974
|
} = e.subdomainRouting, o = t.req.header("host") || "";
|
|
916
975
|
let i = null;
|
|
917
976
|
if (o.endsWith(r)) {
|
|
918
977
|
const c = o.slice(0, -(r.length + 1));
|
|
919
978
|
c && !c.includes(".") && (i = c);
|
|
920
979
|
}
|
|
921
|
-
if (i &&
|
|
980
|
+
if (i && s.includes(i) && (i = null), !i)
|
|
922
981
|
return e.accessControl && t.set("tenant_id", e.accessControl.controlPlaneTenantId), n();
|
|
923
982
|
let u = null;
|
|
924
|
-
if (
|
|
925
|
-
u = await
|
|
983
|
+
if (a)
|
|
984
|
+
u = await a(i);
|
|
926
985
|
else if (e.subdomainRouting.useOrganizations !== !1 && e.accessControl)
|
|
927
986
|
try {
|
|
928
987
|
const c = await t.env.data.organizations.get(
|
|
@@ -939,7 +998,7 @@ function Ce(e) {
|
|
|
939
998
|
return t.set("tenant_id", u), n();
|
|
940
999
|
};
|
|
941
1000
|
}
|
|
942
|
-
function
|
|
1001
|
+
function be(e) {
|
|
943
1002
|
return async (t, n) => {
|
|
944
1003
|
if (!e.databaseIsolation)
|
|
945
1004
|
return n();
|
|
@@ -949,12 +1008,12 @@ function Pe(e) {
|
|
|
949
1008
|
message: "Tenant ID not found in request"
|
|
950
1009
|
});
|
|
951
1010
|
try {
|
|
952
|
-
const
|
|
953
|
-
t.env.data =
|
|
954
|
-
} catch (
|
|
1011
|
+
const s = await e.databaseIsolation.getAdapters(r);
|
|
1012
|
+
t.env.data = s;
|
|
1013
|
+
} catch (s) {
|
|
955
1014
|
throw console.error(
|
|
956
1015
|
`Failed to resolve database for tenant ${r}:`,
|
|
957
|
-
|
|
1016
|
+
s
|
|
958
1017
|
), new b(500, {
|
|
959
1018
|
message: "Failed to resolve tenant database"
|
|
960
1019
|
});
|
|
@@ -962,22 +1021,22 @@ function Pe(e) {
|
|
|
962
1021
|
return n();
|
|
963
1022
|
};
|
|
964
1023
|
}
|
|
965
|
-
function
|
|
966
|
-
const t =
|
|
967
|
-
return async (
|
|
968
|
-
}), await n(
|
|
969
|
-
}), await r(
|
|
970
|
-
}),
|
|
1024
|
+
function J(e) {
|
|
1025
|
+
const t = Ae(e), n = Pe(e), r = be(e);
|
|
1026
|
+
return async (s, a) => (await t(s, async () => {
|
|
1027
|
+
}), await n(s, async () => {
|
|
1028
|
+
}), await r(s, async () => {
|
|
1029
|
+
}), a());
|
|
971
1030
|
}
|
|
972
|
-
function
|
|
1031
|
+
function Fe(e) {
|
|
973
1032
|
const {
|
|
974
1033
|
dataAdapter: t,
|
|
975
1034
|
controlPlane: n,
|
|
976
1035
|
controlPlane: {
|
|
977
1036
|
tenantId: r = "control_plane",
|
|
978
|
-
clientId:
|
|
1037
|
+
clientId: s
|
|
979
1038
|
} = {},
|
|
980
|
-
sync:
|
|
1039
|
+
sync: a = { resourceServers: !0, roles: !0 },
|
|
981
1040
|
defaultPermissions: o = ["tenant:admin"],
|
|
982
1041
|
requireOrganizationMatch: i = !1,
|
|
983
1042
|
managementApiExtensions: u = [],
|
|
@@ -987,22 +1046,22 @@ function ze(e) {
|
|
|
987
1046
|
...d
|
|
988
1047
|
} = e;
|
|
989
1048
|
let f = t, m = t;
|
|
990
|
-
n && (f =
|
|
1049
|
+
n && (f = V(t, {
|
|
991
1050
|
controlPlaneTenantId: r,
|
|
992
|
-
controlPlaneClientId:
|
|
1051
|
+
controlPlaneClientId: s
|
|
993
1052
|
}), m = {
|
|
994
1053
|
...t,
|
|
995
1054
|
multiTenancyConfig: {
|
|
996
1055
|
controlPlaneTenantId: r,
|
|
997
|
-
controlPlaneClientId:
|
|
1056
|
+
controlPlaneClientId: s
|
|
998
1057
|
}
|
|
999
1058
|
});
|
|
1000
|
-
const w =
|
|
1001
|
-
resourceServers:
|
|
1002
|
-
roles:
|
|
1059
|
+
const w = a !== !1, h = w ? {
|
|
1060
|
+
resourceServers: a.resourceServers ?? !0,
|
|
1061
|
+
roles: a.roles ?? !0
|
|
1003
1062
|
} : { resourceServers: !1, roles: !1 }, _ = {
|
|
1004
1063
|
controlPlaneTenantId: r,
|
|
1005
|
-
getChildTenantIds: l ?? (async () => (await
|
|
1064
|
+
getChildTenantIds: l ?? (async () => (await z(
|
|
1006
1065
|
(I) => f.tenants.list(I),
|
|
1007
1066
|
"tenants",
|
|
1008
1067
|
{ cursorField: "id", pageSize: 100 }
|
|
@@ -1010,7 +1069,7 @@ function ze(e) {
|
|
|
1010
1069
|
getAdapters: g ?? (async () => f),
|
|
1011
1070
|
getControlPlaneAdapters: async () => f,
|
|
1012
1071
|
sync: h
|
|
1013
|
-
}, { entityHooks: T, tenantHooks: C } =
|
|
1072
|
+
}, { entityHooks: T, tenantHooks: C } = we(_), v = {
|
|
1014
1073
|
resourceServers: [
|
|
1015
1074
|
T.resourceServers,
|
|
1016
1075
|
...(c == null ? void 0 : c.resourceServers) ?? []
|
|
@@ -1038,14 +1097,14 @@ function ze(e) {
|
|
|
1038
1097
|
{ path: "/tenants", router: P }
|
|
1039
1098
|
]
|
|
1040
1099
|
});
|
|
1041
|
-
return A.use("/api/v2/*",
|
|
1100
|
+
return A.use("/api/v2/*", Ce(r)), w && A.use("/api/v2/*", ve()), { app: A, controlPlaneTenantId: r };
|
|
1042
1101
|
}
|
|
1043
|
-
function
|
|
1102
|
+
function Me(e) {
|
|
1044
1103
|
const t = j(e);
|
|
1045
1104
|
return {
|
|
1046
1105
|
name: "multi-tenancy",
|
|
1047
1106
|
// Apply multi-tenancy middleware for subdomain routing, database resolution, etc.
|
|
1048
|
-
middleware:
|
|
1107
|
+
middleware: J(e),
|
|
1049
1108
|
// Provide lifecycle hooks
|
|
1050
1109
|
hooks: t,
|
|
1051
1110
|
// Mount tenant management routes
|
|
@@ -1066,22 +1125,22 @@ function Re(e) {
|
|
|
1066
1125
|
};
|
|
1067
1126
|
}
|
|
1068
1127
|
function j(e) {
|
|
1069
|
-
const t = e.accessControl ?
|
|
1128
|
+
const t = e.accessControl ? ie(e.accessControl) : {}, n = e.databaseIsolation ? le(e.databaseIsolation) : {}, r = de(e);
|
|
1070
1129
|
return {
|
|
1071
1130
|
...t,
|
|
1072
1131
|
...n,
|
|
1073
1132
|
tenants: r
|
|
1074
1133
|
};
|
|
1075
1134
|
}
|
|
1076
|
-
function
|
|
1077
|
-
const t = new
|
|
1135
|
+
function Ie(e) {
|
|
1136
|
+
const t = new x(), n = j(e);
|
|
1078
1137
|
return t.route("/tenants", q(e, n)), t;
|
|
1079
1138
|
}
|
|
1080
|
-
function
|
|
1139
|
+
function Oe(e) {
|
|
1081
1140
|
return {
|
|
1082
1141
|
hooks: j(e),
|
|
1083
|
-
middleware:
|
|
1084
|
-
app:
|
|
1142
|
+
middleware: J(e),
|
|
1143
|
+
app: Ie(e),
|
|
1085
1144
|
config: e,
|
|
1086
1145
|
/**
|
|
1087
1146
|
* Wraps data adapters with runtime fallback from the control plane.
|
|
@@ -1093,7 +1152,7 @@ function Fe(e) {
|
|
|
1093
1152
|
*/
|
|
1094
1153
|
wrapAdapters: (t, n) => {
|
|
1095
1154
|
var r;
|
|
1096
|
-
return
|
|
1155
|
+
return V(t, {
|
|
1097
1156
|
controlPlaneTenantId: (r = e.accessControl) == null ? void 0 : r.controlPlaneTenantId,
|
|
1098
1157
|
controlPlaneClientId: n == null ? void 0 : n.controlPlaneClientId
|
|
1099
1158
|
});
|
|
@@ -1101,23 +1160,23 @@ function Fe(e) {
|
|
|
1101
1160
|
};
|
|
1102
1161
|
}
|
|
1103
1162
|
export {
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1163
|
+
ie as createAccessControlHooks,
|
|
1164
|
+
Pe as createAccessControlMiddleware,
|
|
1165
|
+
Ce as createControlPlaneTenantMiddleware,
|
|
1166
|
+
le as createDatabaseHooks,
|
|
1167
|
+
be as createDatabaseMiddleware,
|
|
1168
|
+
Ie as createMultiTenancy,
|
|
1110
1169
|
j as createMultiTenancyHooks,
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1170
|
+
J as createMultiTenancyMiddleware,
|
|
1171
|
+
Me as createMultiTenancyPlugin,
|
|
1172
|
+
ve as createProtectSyncedMiddleware,
|
|
1173
|
+
de as createProvisioningHooks,
|
|
1174
|
+
Te as createRuntimeFallbackAdapter,
|
|
1175
|
+
Ae as createSubdomainMiddleware,
|
|
1176
|
+
we as createSyncHooks,
|
|
1118
1177
|
q as createTenantsOpenAPIRouter,
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1178
|
+
Fe as initMultiTenant,
|
|
1179
|
+
Oe as setupMultiTenancy,
|
|
1180
|
+
ce as validateTenantAccess,
|
|
1181
|
+
V as withRuntimeFallback
|
|
1123
1182
|
};
|
|
@@ -27,6 +27,8 @@ export interface ResourceServerSyncConfig {
|
|
|
27
27
|
/**
|
|
28
28
|
* Optional: Transform the resource server before syncing to child tenants.
|
|
29
29
|
* Useful for modifying identifiers or removing sensitive data.
|
|
30
|
+
* Note: Scopes are never synced - they are inherited at runtime via the
|
|
31
|
+
* settings-inheritance middleware.
|
|
30
32
|
*/
|
|
31
33
|
transformForSync?: (resourceServer: ResourceServer, targetTenantId: string) => ResourceServerInsert;
|
|
32
34
|
}
|
|
@@ -106,6 +108,8 @@ export interface TenantResourceServerSyncConfig {
|
|
|
106
108
|
/**
|
|
107
109
|
* Optional: Transform the resource server before syncing to the new tenant.
|
|
108
110
|
* Useful for modifying identifiers or removing sensitive data.
|
|
111
|
+
* Note: Scopes are never synced - they are inherited at runtime via the
|
|
112
|
+
* settings-inheritance middleware.
|
|
109
113
|
*/
|
|
110
114
|
transformForSync?: (resourceServer: ResourceServer, targetTenantId: string) => ResourceServerInsert;
|
|
111
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-server-sync.d.ts","sourceRoot":"","sources":["../../../src/hooks/resource-server-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,cAAc,EACd,oBAAoB,EAErB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAqB,MAAM,UAAU,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE3C;;;OAGG;IACH,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAEzD;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,OAAO,CAAC;IAEzD
|
|
1
|
+
{"version":3,"file":"resource-server-sync.d.ts","sourceRoot":"","sources":["../../../src/hooks/resource-server-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,cAAc,EACd,oBAAoB,EAErB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAqB,MAAM,UAAU,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE3C;;;OAGG;IACH,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAEzD;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,OAAO,CAAC;IAEzD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CACjB,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,MAAM,KACnB,oBAAoB,CAAC;CAC3B;AAED;;GAEG;AACH,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,CACZ,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,WAAW,CAAC,EAAE,CACZ,GAAG,EAAE,iBAAiB,EACtB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,cAAc,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,wBAAwB,GAC/B,yBAAyB,CA6L3B;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;OAEG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,uBAAuB,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IAErD;;;OAGG;IACH,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAEzD;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,OAAO,CAAC;IAEzD;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,CACjB,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,MAAM,KACnB,oBAAoB,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,8BAA8B,GACrC,iBAAiB,CAoFnB"}
|
|
@@ -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,EAOb,MAAM,UAAU,CAAC;AA8HlB;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,qBAAqB,GAC5B,YAAY,CAmQd;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.11.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.95.0",
|
|
40
|
+
"authhero": "4.35.0",
|
|
41
|
+
"@authhero/adapter-interfaces": "0.132.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"zod": "^3.24.0"
|