@authhero/multi-tenancy 15.0.0 → 15.0.1
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.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Hono as e } from "hono";
|
|
2
|
-
import { MANAGEMENT_API_AUDIENCE as t, MANAGEMENT_API_SCOPES as n, auth0QuerySchema as r, brandingSchema as i, connectionInsertSchema as a, connectionOptionsSchema as o, connectionSchema as s, deepMergePatch as c, emailProviderSchema as l,
|
|
3
|
-
import { OpenAPIHono as
|
|
4
|
-
import { HTTPException as
|
|
2
|
+
import { MANAGEMENT_API_AUDIENCE as t, MANAGEMENT_API_SCOPES as n, auth0QuerySchema as r, brandingSchema as i, connectionInsertSchema as a, connectionOptionsSchema as o, connectionSchema as s, deepMergePatch as c, emailProviderSchema as l, escapeLuceneValue as u, fetchAll as d, hookInsertSchema as f, init as p, isInteractiveClient as m, listControlPlaneKeys as h, promptSettingSchema as g, provisionDefaultClients as _, resourceServerInsertSchema as v, tenantInsertSchema as y, tenantSchema as b } from "authhero";
|
|
3
|
+
import { OpenAPIHono as x, createRoute as S, z as C } from "@hono/zod-openapi";
|
|
4
|
+
import { HTTPException as w } from "hono/http-exception";
|
|
5
5
|
//#region src/hooks/access-control.ts
|
|
6
|
-
function
|
|
6
|
+
function T(e) {
|
|
7
7
|
let { controlPlaneTenantId: t, requireOrganizationMatch: n = !0 } = e;
|
|
8
8
|
return { async onTenantAccessValidation(e, r) {
|
|
9
9
|
if (r === t) return !0;
|
|
@@ -14,14 +14,14 @@ function C(e) {
|
|
|
14
14
|
return !0;
|
|
15
15
|
} };
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function E(e, t, n, r) {
|
|
18
18
|
if (t === n) return !0;
|
|
19
19
|
let i = r || e;
|
|
20
20
|
return i ? i.toLowerCase() === t.toLowerCase() : !1;
|
|
21
21
|
}
|
|
22
22
|
//#endregion
|
|
23
23
|
//#region src/hooks/database.ts
|
|
24
|
-
function
|
|
24
|
+
function D(e) {
|
|
25
25
|
return { async resolveDataAdapters(t) {
|
|
26
26
|
try {
|
|
27
27
|
return await e.getAdapters(t);
|
|
@@ -33,18 +33,18 @@ function T(e) {
|
|
|
33
33
|
}
|
|
34
34
|
//#endregion
|
|
35
35
|
//#region src/operations/instance-id.ts
|
|
36
|
-
var
|
|
37
|
-
function
|
|
36
|
+
var O = 64;
|
|
37
|
+
function k(e) {
|
|
38
38
|
return e.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
39
39
|
}
|
|
40
|
-
function
|
|
41
|
-
let t =
|
|
42
|
-
return `op-${r}-${
|
|
40
|
+
function A(e) {
|
|
41
|
+
let t = k(e.id), n = Math.max(0, O - (5 + t.length)), r = k(e.kind).slice(0, n), i = 3 + r.length + 2 + t.length, a = Math.max(0, O - i);
|
|
42
|
+
return `op-${r}-${k(e.tenant_id ?? "fleet").slice(0, a)}-${t}`.slice(0, O);
|
|
43
43
|
}
|
|
44
44
|
//#endregion
|
|
45
45
|
//#region src/operations/recorder.ts
|
|
46
|
-
var
|
|
47
|
-
function
|
|
46
|
+
var ee = 2048;
|
|
47
|
+
function j(e) {
|
|
48
48
|
let t;
|
|
49
49
|
if (e instanceof Error) t = e.message;
|
|
50
50
|
else try {
|
|
@@ -52,9 +52,9 @@ function O(e) {
|
|
|
52
52
|
} catch {
|
|
53
53
|
t = Object.prototype.toString.call(e);
|
|
54
54
|
}
|
|
55
|
-
return t.slice(0,
|
|
55
|
+
return t.slice(0, ee);
|
|
56
56
|
}
|
|
57
|
-
function
|
|
57
|
+
function M(e) {
|
|
58
58
|
let { tenantOperations: t, tenantOperationEvents: n } = e;
|
|
59
59
|
return {
|
|
60
60
|
async markRunning(e, n) {
|
|
@@ -85,24 +85,24 @@ function k(e) {
|
|
|
85
85
|
async markFailed(e, n) {
|
|
86
86
|
await t.update(e, {
|
|
87
87
|
status: "failed",
|
|
88
|
-
error:
|
|
88
|
+
error: j(n),
|
|
89
89
|
finished_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
|
-
function
|
|
94
|
+
function N(e) {
|
|
95
95
|
return e === "succeeded" || e === "failed" || e === "cancelled";
|
|
96
96
|
}
|
|
97
97
|
//#endregion
|
|
98
98
|
//#region src/operations/inline-executor.ts
|
|
99
|
-
var
|
|
99
|
+
var P = { async do(e, t, n) {
|
|
100
100
|
let r = typeof t == "function" ? t : n;
|
|
101
101
|
if (!r) throw Error("StepRunner.do called without a function");
|
|
102
102
|
return r();
|
|
103
103
|
} };
|
|
104
|
-
function
|
|
105
|
-
let t =
|
|
104
|
+
function te(e) {
|
|
105
|
+
let t = M(e.stores);
|
|
106
106
|
return {
|
|
107
107
|
engine: "inline",
|
|
108
108
|
async start(n) {
|
|
@@ -121,7 +121,7 @@ function j(e) {
|
|
|
121
121
|
try {
|
|
122
122
|
let r = await e.run({
|
|
123
123
|
operation: n,
|
|
124
|
-
step:
|
|
124
|
+
step: P
|
|
125
125
|
});
|
|
126
126
|
await t.appendEvent(n.id, {
|
|
127
127
|
step: e.name,
|
|
@@ -132,7 +132,7 @@ function j(e) {
|
|
|
132
132
|
throw await t.appendEvent(n.id, {
|
|
133
133
|
step: e.name,
|
|
134
134
|
outcome: "failed",
|
|
135
|
-
detail: { message:
|
|
135
|
+
detail: { message: j(r) }
|
|
136
136
|
}), await t.markFailed(n.id, r), r;
|
|
137
137
|
}
|
|
138
138
|
}
|
|
@@ -142,7 +142,7 @@ function j(e) {
|
|
|
142
142
|
}
|
|
143
143
|
//#endregion
|
|
144
144
|
//#region src/operations/enqueue.ts
|
|
145
|
-
async function
|
|
145
|
+
async function ne(e, t, n) {
|
|
146
146
|
let r = await e.tenantOperations.create({
|
|
147
147
|
tenant_id: t.tenant_id,
|
|
148
148
|
rollout_id: t.rollout_id,
|
|
@@ -151,12 +151,12 @@ async function M(e, t, n) {
|
|
|
151
151
|
initiated_by: t.initiated_by,
|
|
152
152
|
target_worker_version: t.target_worker_version,
|
|
153
153
|
target_database_version: t.target_database_version
|
|
154
|
-
}), i =
|
|
154
|
+
}), i = A(r);
|
|
155
155
|
try {
|
|
156
156
|
await e.tenantOperations.update(r.id, { engine_instance_id: i });
|
|
157
157
|
} catch (t) {
|
|
158
158
|
try {
|
|
159
|
-
await
|
|
159
|
+
await M(e).markFailed(r.id, t);
|
|
160
160
|
} catch {}
|
|
161
161
|
throw t;
|
|
162
162
|
}
|
|
@@ -165,14 +165,14 @@ async function M(e, t, n) {
|
|
|
165
165
|
engine_instance_id: i
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
|
-
async function
|
|
169
|
-
let r =
|
|
168
|
+
async function re(e, t, n) {
|
|
169
|
+
let r = M(e), i = await ne(e, n, t.engine);
|
|
170
170
|
try {
|
|
171
171
|
await t.start(i);
|
|
172
172
|
} catch (t) {
|
|
173
173
|
try {
|
|
174
174
|
let n = await e.tenantOperations.get(i.id);
|
|
175
|
-
n && !
|
|
175
|
+
n && !N(n.status) && await r.markFailed(i.id, t);
|
|
176
176
|
} catch (e) {
|
|
177
177
|
console.warn("Failed to record tenant operation failure:", e);
|
|
178
178
|
}
|
|
@@ -192,13 +192,13 @@ function ie(e) {
|
|
|
192
192
|
tenantOperationEvents: e.tenantOperationEvents
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
|
-
async function
|
|
195
|
+
async function ae(e, t, n) {
|
|
196
196
|
let r = ie(e);
|
|
197
197
|
if (!r) {
|
|
198
198
|
await n(void 0);
|
|
199
199
|
return;
|
|
200
200
|
}
|
|
201
|
-
let i =
|
|
201
|
+
let i = M(r), a = async (e) => {
|
|
202
202
|
try {
|
|
203
203
|
await e();
|
|
204
204
|
} catch (e) {
|
|
@@ -206,7 +206,7 @@ async function P(e, t, n) {
|
|
|
206
206
|
}
|
|
207
207
|
}, o;
|
|
208
208
|
if (await a(async () => {
|
|
209
|
-
let e = await
|
|
209
|
+
let e = await ne(r, t, "inline");
|
|
210
210
|
o = e.id, await i.markRunning(e.id);
|
|
211
211
|
}), !o) {
|
|
212
212
|
await n(void 0);
|
|
@@ -228,7 +228,7 @@ async function P(e, t, n) {
|
|
|
228
228
|
c || await i.appendEvent(s, {
|
|
229
229
|
step: t.kind,
|
|
230
230
|
outcome: "failed",
|
|
231
|
-
detail: { message:
|
|
231
|
+
detail: { message: j(e) }
|
|
232
232
|
}), await i.markFailed(s, e);
|
|
233
233
|
}), e;
|
|
234
234
|
}
|
|
@@ -241,7 +241,7 @@ async function P(e, t, n) {
|
|
|
241
241
|
}
|
|
242
242
|
//#endregion
|
|
243
243
|
//#region src/hooks/provisioning.ts
|
|
244
|
-
function
|
|
244
|
+
function oe(e) {
|
|
245
245
|
return `urn:authhero:tenant:${e.toLowerCase()}`;
|
|
246
246
|
}
|
|
247
247
|
function F(e) {
|
|
@@ -249,20 +249,20 @@ function F(e) {
|
|
|
249
249
|
async beforeCreate(e, t) {
|
|
250
250
|
return !t.audience && t.id ? {
|
|
251
251
|
...t,
|
|
252
|
-
audience:
|
|
252
|
+
audience: oe(t.id)
|
|
253
253
|
} : t;
|
|
254
254
|
},
|
|
255
255
|
async afterCreate(r, i) {
|
|
256
256
|
let { accessControl: a, databaseIsolation: o } = e;
|
|
257
|
-
if (a && r.ctx && await
|
|
257
|
+
if (a && r.ctx && await se(r, i, a), o?.onProvision) {
|
|
258
258
|
let e = o.onProvision;
|
|
259
|
-
o.recordProvisionOperations === !1 ? await e(i.id) : await
|
|
259
|
+
o.recordProvisionOperations === !1 ? await e(i.id) : await ae(r.adapters, {
|
|
260
260
|
kind: "provision",
|
|
261
261
|
tenant_id: i.id,
|
|
262
262
|
initiated_by: r.ctx?.var.user?.sub
|
|
263
263
|
}, (t) => e(i.id, t));
|
|
264
264
|
} else try {
|
|
265
|
-
await
|
|
265
|
+
await _(r.adapters, i.id, {
|
|
266
266
|
managementApiIdentifier: t,
|
|
267
267
|
managementApiScopes: n
|
|
268
268
|
});
|
|
@@ -286,14 +286,14 @@ function F(e) {
|
|
|
286
286
|
}
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
|
-
async function
|
|
289
|
+
async function se(e, t, n) {
|
|
290
290
|
let { controlPlaneTenantId: r, defaultPermissions: i, defaultRoles: a, issuer: o, adminRoleName: s = "Tenant Admin", adminRoleDescription: c = "Full access to all tenant management operations", addCreatorToOrganization: l = !0 } = n, u = await e.adapters.organizations.create(r, {
|
|
291
291
|
name: t.id,
|
|
292
292
|
display_name: t.friendly_name || t.id
|
|
293
293
|
}), d;
|
|
294
|
-
if (o && (d = await
|
|
294
|
+
if (o && (d = await le(e, r, s, c)), l && e.ctx) {
|
|
295
295
|
let t = e.ctx.var.user;
|
|
296
|
-
if (t?.sub && !await
|
|
296
|
+
if (t?.sub && !await ce(e, r, t.sub)) try {
|
|
297
297
|
await e.adapters.userOrganizations.create(r, {
|
|
298
298
|
user_id: t.sub,
|
|
299
299
|
organization_id: u.id
|
|
@@ -304,12 +304,12 @@ async function oe(e, t, n) {
|
|
|
304
304
|
}
|
|
305
305
|
a && a.length > 0 && console.log(`Would assign roles ${a.join(", ")} to organization ${u.id}`), i && i.length > 0 && console.log(`Would grant permissions ${i.join(", ")} to organization ${u.id}`);
|
|
306
306
|
}
|
|
307
|
-
async function
|
|
307
|
+
async function ce(e, n, r) {
|
|
308
308
|
let i = await e.adapters.userRoles.list(n, r, void 0, "");
|
|
309
309
|
for (let r of i) if ((await e.adapters.rolePermissions.list(n, r.id, { per_page: 1e3 })).some((e) => e.permission_name === "admin:organizations" && e.resource_server_identifier === t)) return !0;
|
|
310
310
|
return !1;
|
|
311
311
|
}
|
|
312
|
-
async function
|
|
312
|
+
async function le(e, r, i, a) {
|
|
313
313
|
let o = (await e.adapters.roles.list(r, {})).roles.find((e) => e.name === i);
|
|
314
314
|
if (o) return o.id;
|
|
315
315
|
let s = await e.adapters.roles.create(r, {
|
|
@@ -324,11 +324,11 @@ async function ce(e, r, i, a) {
|
|
|
324
324
|
}
|
|
325
325
|
//#endregion
|
|
326
326
|
//#region src/hooks/sync.ts
|
|
327
|
-
function
|
|
327
|
+
function I(e, t, n = () => !0) {
|
|
328
328
|
let { controlPlaneTenantId: r, getChildTenantIds: i, getAdapters: a } = e, o = /* @__PURE__ */ new Map();
|
|
329
329
|
async function s(e, n, r) {
|
|
330
330
|
return (await t(e).list(n, {
|
|
331
|
-
q: `name:${r}`,
|
|
331
|
+
q: `name:${u(r)}`,
|
|
332
332
|
per_page: 1
|
|
333
333
|
}))[0] ?? null;
|
|
334
334
|
}
|
|
@@ -379,15 +379,15 @@ function le(e, t, n = () => !0) {
|
|
|
379
379
|
}
|
|
380
380
|
};
|
|
381
381
|
}
|
|
382
|
-
function
|
|
382
|
+
function L(e, t, n = () => !0) {
|
|
383
383
|
let { controlPlaneTenantId: r, getControlPlaneAdapters: i, getAdapters: a } = e;
|
|
384
384
|
return { async afterCreate(e, o) {
|
|
385
385
|
if (o.id !== r) try {
|
|
386
|
-
let e = await i(), s = await a(o.id), c = t(e), l = t(s),
|
|
386
|
+
let e = await i(), s = await a(o.id), c = t(e), l = t(s), u = await d((e) => c.listPaginated(r, e), c.listKey, {
|
|
387
387
|
cursorField: "id",
|
|
388
388
|
pageSize: 100
|
|
389
389
|
});
|
|
390
|
-
await Promise.all(
|
|
390
|
+
await Promise.all(u.filter((e) => n(e)).map(async (e) => {
|
|
391
391
|
try {
|
|
392
392
|
let t = c.transform(e);
|
|
393
393
|
await l.create(o.id, {
|
|
@@ -403,7 +403,7 @@ function ue(e, t, n = () => !0) {
|
|
|
403
403
|
}
|
|
404
404
|
} };
|
|
405
405
|
}
|
|
406
|
-
var
|
|
406
|
+
var R = (e) => ({
|
|
407
407
|
list: async (t, n) => (await e.resourceServers.list(t, n)).resource_servers,
|
|
408
408
|
listPaginated: (t, n) => e.resourceServers.list(t, n),
|
|
409
409
|
get: (t, n) => e.resourceServers.get(t, n),
|
|
@@ -421,7 +421,7 @@ var de = (e) => ({
|
|
|
421
421
|
token_lifetime: e.token_lifetime,
|
|
422
422
|
token_lifetime_for_web: e.token_lifetime_for_web
|
|
423
423
|
})
|
|
424
|
-
}),
|
|
424
|
+
}), z = (e) => ({
|
|
425
425
|
list: async (t, n) => (await e.roles.list(t, n)).roles,
|
|
426
426
|
listPaginated: (t, n) => e.roles.list(t, n),
|
|
427
427
|
get: (t, n) => e.roles.get(t, n),
|
|
@@ -436,20 +436,20 @@ var de = (e) => ({
|
|
|
436
436
|
description: e.description
|
|
437
437
|
})
|
|
438
438
|
});
|
|
439
|
-
function
|
|
439
|
+
function B(e) {
|
|
440
440
|
return e.metadata?.sync !== !1;
|
|
441
441
|
}
|
|
442
|
-
function
|
|
443
|
-
let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) =>
|
|
442
|
+
function V(e) {
|
|
443
|
+
let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) => B(e) ? n.resourceServers ? n.resourceServers(e) : !0 : !1, o = (e) => B(e) ? n.roles ? n.roles(e) : !0 : !1, s = r ? I(e, R, a) : void 0, c = i ? I(e, z, o) : void 0, l = r ? L(e, R, a) : void 0, f = i ? L(e, z, o) : void 0, p = i ? { async afterCreate(t, r) {
|
|
444
444
|
if (r.id !== e.controlPlaneTenantId) {
|
|
445
|
-
await
|
|
445
|
+
await f?.afterCreate?.(t, r);
|
|
446
446
|
try {
|
|
447
|
-
let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await
|
|
447
|
+
let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await d((n) => t.roles.list(e.controlPlaneTenantId, n), "roles", {
|
|
448
448
|
cursorField: "id",
|
|
449
449
|
pageSize: 100
|
|
450
450
|
}), o = /* @__PURE__ */ new Map();
|
|
451
451
|
for (let e of a.filter((e) => n.roles?.(e) ?? !0)) {
|
|
452
|
-
let t = await
|
|
452
|
+
let t = await m(i, r.id, e.name);
|
|
453
453
|
t && o.set(e.name, t.id);
|
|
454
454
|
}
|
|
455
455
|
for (let s of a.filter((e) => n.roles?.(e) ?? !0)) {
|
|
@@ -470,9 +470,9 @@ function I(e) {
|
|
|
470
470
|
}
|
|
471
471
|
}
|
|
472
472
|
} } : void 0;
|
|
473
|
-
async function
|
|
473
|
+
async function m(e, t, n) {
|
|
474
474
|
return (await e.roles.list(t, {
|
|
475
|
-
q: `name:${n}`,
|
|
475
|
+
q: `name:${u(n)}`,
|
|
476
476
|
per_page: 1
|
|
477
477
|
})).roles[0] ?? null;
|
|
478
478
|
}
|
|
@@ -482,7 +482,7 @@ function I(e) {
|
|
|
482
482
|
roles: c
|
|
483
483
|
},
|
|
484
484
|
tenantHooks: { async afterCreate(e, t) {
|
|
485
|
-
let n = [l?.afterCreate,
|
|
485
|
+
let n = [l?.afterCreate, p?.afterCreate ?? f?.afterCreate], r = [];
|
|
486
486
|
for (let i of n) if (i) try {
|
|
487
487
|
await i(e, t);
|
|
488
488
|
} catch (e) {
|
|
@@ -495,35 +495,35 @@ function I(e) {
|
|
|
495
495
|
}
|
|
496
496
|
//#endregion
|
|
497
497
|
//#region src/routes/tenants.ts
|
|
498
|
-
var
|
|
499
|
-
sub:
|
|
500
|
-
tenant_id:
|
|
501
|
-
org_id:
|
|
502
|
-
scope:
|
|
503
|
-
permissions:
|
|
498
|
+
var ue = C.object({
|
|
499
|
+
sub: C.string(),
|
|
500
|
+
tenant_id: C.string().optional(),
|
|
501
|
+
org_id: C.string().optional(),
|
|
502
|
+
scope: C.string().optional(),
|
|
503
|
+
permissions: C.array(C.string()).optional()
|
|
504
504
|
}).passthrough();
|
|
505
|
-
function
|
|
506
|
-
let t =
|
|
505
|
+
function de(e) {
|
|
506
|
+
let t = ue.safeParse(e);
|
|
507
507
|
return t.success ? t.data : void 0;
|
|
508
508
|
}
|
|
509
|
-
function
|
|
509
|
+
function fe(e) {
|
|
510
510
|
let t = e.permissions ?? [], n = e.scope ? e.scope.split(" ").filter(Boolean) : [], r = new Set([...t, ...n]);
|
|
511
511
|
return r.has("delete:tenants") || r.has("admin:organizations");
|
|
512
512
|
}
|
|
513
|
-
function
|
|
514
|
-
let n = new
|
|
515
|
-
return n.openapi(
|
|
513
|
+
function H(e, t) {
|
|
514
|
+
let n = new x();
|
|
515
|
+
return n.openapi(S({
|
|
516
516
|
tags: ["tenants"],
|
|
517
517
|
method: "get",
|
|
518
518
|
path: "/",
|
|
519
519
|
request: { query: r },
|
|
520
520
|
security: [{ Bearer: [] }],
|
|
521
521
|
responses: { 200: {
|
|
522
|
-
content: { "application/json": { schema:
|
|
523
|
-
tenants:
|
|
524
|
-
start:
|
|
525
|
-
limit:
|
|
526
|
-
length:
|
|
522
|
+
content: { "application/json": { schema: C.object({
|
|
523
|
+
tenants: C.array(b),
|
|
524
|
+
start: C.number().optional(),
|
|
525
|
+
limit: C.number().optional(),
|
|
526
|
+
length: C.number().optional()
|
|
527
527
|
}) } },
|
|
528
528
|
description: "List of tenants"
|
|
529
529
|
} }
|
|
@@ -544,31 +544,31 @@ function L(e, t) {
|
|
|
544
544
|
}) : t.json({ tenants: e.tenants });
|
|
545
545
|
}
|
|
546
546
|
let c = e.accessControl?.controlPlaneTenantId ?? t.env.data.multiTenancyConfig?.controlPlaneTenantId;
|
|
547
|
-
if (c && !o?.sub) throw new
|
|
547
|
+
if (c && !o?.sub) throw new w(403, { message: "Access denied: token has no subject" });
|
|
548
548
|
if (c && o?.sub) {
|
|
549
|
-
let e = (await
|
|
549
|
+
let e = (await d((e) => t.env.data.userOrganizations.listUserOrganizations(c, o.sub, e), "organizations")).map((e) => e.name);
|
|
550
550
|
if (e.length === 0) return i ? t.json({
|
|
551
551
|
tenants: [],
|
|
552
552
|
start: 0,
|
|
553
553
|
limit: r ?? 50,
|
|
554
554
|
length: 0
|
|
555
555
|
}) : t.json({ tenants: [] });
|
|
556
|
-
let s = e.length, l = n ?? 0,
|
|
556
|
+
let s = e.length, l = n ?? 0, u = r ?? 50, f = l * u, p = e.slice(f, f + u);
|
|
557
557
|
if (p.length === 0) return i ? t.json({
|
|
558
558
|
tenants: [],
|
|
559
559
|
start: f,
|
|
560
|
-
limit:
|
|
560
|
+
limit: u,
|
|
561
561
|
length: s
|
|
562
562
|
}) : t.json({ tenants: [] });
|
|
563
563
|
let m = p.map((e) => `id:${e}`).join(" OR "), h = a ? `(${m}) AND (${a})` : m, g = await t.env.data.tenants.list({
|
|
564
564
|
q: h,
|
|
565
|
-
per_page:
|
|
565
|
+
per_page: u,
|
|
566
566
|
include_totals: !1
|
|
567
567
|
});
|
|
568
568
|
return i ? t.json({
|
|
569
569
|
tenants: g.tenants,
|
|
570
570
|
start: f,
|
|
571
|
-
limit:
|
|
571
|
+
limit: u,
|
|
572
572
|
length: s
|
|
573
573
|
}) : t.json({ tenants: g.tenants });
|
|
574
574
|
}
|
|
@@ -584,22 +584,22 @@ function L(e, t) {
|
|
|
584
584
|
limit: l.totals?.limit ?? r,
|
|
585
585
|
length: l.tenants.length
|
|
586
586
|
}) : t.json({ tenants: l.tenants });
|
|
587
|
-
}), n.openapi(
|
|
587
|
+
}), n.openapi(S({
|
|
588
588
|
tags: ["tenants"],
|
|
589
589
|
method: "post",
|
|
590
590
|
path: "/",
|
|
591
|
-
request: { body: { content: { "application/json": { schema:
|
|
591
|
+
request: { body: { content: { "application/json": { schema: y } } } },
|
|
592
592
|
security: [{ Bearer: [] }],
|
|
593
593
|
responses: {
|
|
594
594
|
201: {
|
|
595
|
-
content: { "application/json": { schema:
|
|
595
|
+
content: { "application/json": { schema: b } },
|
|
596
596
|
description: "Tenant created"
|
|
597
597
|
},
|
|
598
598
|
400: { description: "Validation error" },
|
|
599
599
|
409: { description: "Tenant with this ID already exists" }
|
|
600
600
|
}
|
|
601
601
|
}), async (e) => {
|
|
602
|
-
if (!e.var.user?.sub) throw new
|
|
602
|
+
if (!e.var.user?.sub) throw new w(401, { message: "Authentication required to create tenants" });
|
|
603
603
|
let n = e.req.valid("json"), r = {
|
|
604
604
|
adapters: e.env.data,
|
|
605
605
|
ctx: e
|
|
@@ -607,11 +607,11 @@ function L(e, t) {
|
|
|
607
607
|
t.tenants?.beforeCreate && (n = await t.tenants.beforeCreate(r, n));
|
|
608
608
|
let i = await e.env.data.tenants.create(n);
|
|
609
609
|
return t.tenants?.afterCreate && await t.tenants.afterCreate(r, i), e.json(i, 201);
|
|
610
|
-
}), n.openapi(
|
|
610
|
+
}), n.openapi(S({
|
|
611
611
|
tags: ["tenants"],
|
|
612
612
|
method: "delete",
|
|
613
613
|
path: "/{id}",
|
|
614
|
-
request: { params:
|
|
614
|
+
request: { params: C.object({ id: C.string() }) },
|
|
615
615
|
security: [{ Bearer: ["delete:tenants"] }],
|
|
616
616
|
responses: {
|
|
617
617
|
204: { description: "Tenant deleted" },
|
|
@@ -621,70 +621,70 @@ function L(e, t) {
|
|
|
621
621
|
}), async (n) => {
|
|
622
622
|
let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ?? n.env.data.multiTenancyConfig?.controlPlaneTenantId;
|
|
623
623
|
if (i) {
|
|
624
|
-
let e =
|
|
625
|
-
if (!e?.sub) throw new
|
|
626
|
-
if (r === i) throw new
|
|
624
|
+
let e = de(n.var.user);
|
|
625
|
+
if (!e?.sub) throw new w(401, { message: "Authentication required" });
|
|
626
|
+
if (r === i) throw new w(403, { message: "Cannot delete the control plane" });
|
|
627
627
|
let t = n.var.org_name, a = r.toLowerCase(), o = !!t && t.toLowerCase() === a;
|
|
628
628
|
if (!o) {
|
|
629
629
|
let r = !!(e.org_id ?? n.var.organization_id ?? t), a = !e.tenant_id || e.tenant_id === i;
|
|
630
|
-
!r && a &&
|
|
630
|
+
!r && a && fe(e) && (o = !0);
|
|
631
631
|
}
|
|
632
|
-
if (o ||= (await
|
|
632
|
+
if (o ||= (await d((t) => n.env.data.userOrganizations.listUserOrganizations(i, e.sub, t), "organizations")).some((e) => e.name?.toLowerCase() === a), !o) throw new w(403, { message: "Access denied to this tenant" });
|
|
633
633
|
}
|
|
634
|
-
if (!await n.env.data.tenants.get(r)) throw new
|
|
634
|
+
if (!await n.env.data.tenants.get(r)) throw new w(404, { message: "Tenant not found" });
|
|
635
635
|
let a = {
|
|
636
636
|
adapters: n.env.data,
|
|
637
637
|
ctx: n
|
|
638
638
|
};
|
|
639
639
|
return t.tenants?.beforeDelete && await t.tenants.beforeDelete(a, r), await n.env.data.tenants.remove(r), t.tenants?.afterDelete && await t.tenants.afterDelete(a, r), n.body(null, 204);
|
|
640
|
-
}), n.openapi(
|
|
640
|
+
}), n.openapi(S({
|
|
641
641
|
tags: ["tenants", "settings"],
|
|
642
642
|
method: "get",
|
|
643
643
|
path: "/settings",
|
|
644
|
-
request: { headers:
|
|
644
|
+
request: { headers: C.object({ "tenant-id": C.string().optional() }) },
|
|
645
645
|
security: [{ Bearer: ["read:tenants"] }],
|
|
646
646
|
responses: { 200: {
|
|
647
|
-
content: { "application/json": { schema:
|
|
647
|
+
content: { "application/json": { schema: b } },
|
|
648
648
|
description: "Current tenant settings"
|
|
649
649
|
} }
|
|
650
650
|
}), async (e) => {
|
|
651
651
|
let t = await e.env.data.tenants.get(e.var.tenant_id);
|
|
652
|
-
if (!t) throw new
|
|
652
|
+
if (!t) throw new w(404, { message: "Tenant not found" });
|
|
653
653
|
return e.json(t);
|
|
654
|
-
}), n.openapi(
|
|
654
|
+
}), n.openapi(S({
|
|
655
655
|
tags: ["tenants", "settings"],
|
|
656
656
|
method: "patch",
|
|
657
657
|
path: "/settings",
|
|
658
658
|
request: {
|
|
659
|
-
headers:
|
|
660
|
-
body: { content: { "application/json": { schema:
|
|
659
|
+
headers: C.object({ "tenant-id": C.string().optional() }),
|
|
660
|
+
body: { content: { "application/json": { schema: C.object(y.shape).partial() } } }
|
|
661
661
|
},
|
|
662
662
|
security: [{ Bearer: ["update:tenants"] }],
|
|
663
663
|
responses: { 200: {
|
|
664
|
-
content: { "application/json": { schema:
|
|
664
|
+
content: { "application/json": { schema: b } },
|
|
665
665
|
description: "Updated tenant settings"
|
|
666
666
|
} }
|
|
667
667
|
}), async (e) => {
|
|
668
668
|
let { id: t, ...n } = e.req.valid("json"), r = await e.env.data.tenants.get(e.var.tenant_id);
|
|
669
|
-
if (!r) throw new
|
|
669
|
+
if (!r) throw new w(404, { message: "Tenant not found" });
|
|
670
670
|
if ("default_client_id" in n) {
|
|
671
671
|
let t = n.default_client_id;
|
|
672
672
|
if (typeof t == "string" && t.length > 0) {
|
|
673
673
|
let n = await e.env.data.clients.get(e.var.tenant_id, t);
|
|
674
|
-
if (!n) throw new
|
|
675
|
-
if (!
|
|
674
|
+
if (!n) throw new w(400, { message: `Client with id '${t}' not found` });
|
|
675
|
+
if (!m(n)) throw new w(400, { message: `Client '${t}' is not an interactive client and cannot be used as the default client` });
|
|
676
676
|
}
|
|
677
677
|
}
|
|
678
678
|
let i = c(r, n);
|
|
679
679
|
await e.env.data.tenants.update(e.var.tenant_id, i);
|
|
680
680
|
let a = await e.env.data.tenants.get(e.var.tenant_id);
|
|
681
|
-
if (!a) throw new
|
|
681
|
+
if (!a) throw new w(500, { message: "Failed to retrieve updated tenant" });
|
|
682
682
|
return e.json(a);
|
|
683
683
|
}), n;
|
|
684
684
|
}
|
|
685
685
|
//#endregion
|
|
686
686
|
//#region src/middleware/protect-synced.ts
|
|
687
|
-
function
|
|
687
|
+
function pe(e) {
|
|
688
688
|
for (let { pattern: t, type: n } of [
|
|
689
689
|
{
|
|
690
690
|
pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
|
|
@@ -707,7 +707,7 @@ function _e(e) {
|
|
|
707
707
|
}
|
|
708
708
|
return null;
|
|
709
709
|
}
|
|
710
|
-
async function
|
|
710
|
+
async function me(e, t, n) {
|
|
711
711
|
try {
|
|
712
712
|
switch (n.type) {
|
|
713
713
|
case "resource_server": return (await e.resourceServers.get(t, n.id))?.is_system === !0;
|
|
@@ -719,31 +719,31 @@ async function ve(e, t, n) {
|
|
|
719
719
|
return !1;
|
|
720
720
|
}
|
|
721
721
|
}
|
|
722
|
-
function
|
|
722
|
+
function he(e) {
|
|
723
723
|
return {
|
|
724
724
|
resource_server: "resource server",
|
|
725
725
|
role: "role",
|
|
726
726
|
connection: "connection"
|
|
727
727
|
}[e];
|
|
728
728
|
}
|
|
729
|
-
function
|
|
729
|
+
function U() {
|
|
730
730
|
return async (e, t) => {
|
|
731
731
|
if (![
|
|
732
732
|
"PATCH",
|
|
733
733
|
"PUT",
|
|
734
734
|
"DELETE"
|
|
735
735
|
].includes(e.req.method)) return t();
|
|
736
|
-
let n =
|
|
736
|
+
let n = pe(e.req.path);
|
|
737
737
|
if (!n) return t();
|
|
738
738
|
let r = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
|
|
739
739
|
if (!r) return t();
|
|
740
|
-
if (await
|
|
740
|
+
if (await me(e.env.data, r, n)) throw new w(403, { message: `This ${he(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.` });
|
|
741
741
|
return t();
|
|
742
742
|
};
|
|
743
743
|
}
|
|
744
744
|
//#endregion
|
|
745
745
|
//#region src/middleware/settings-inheritance.ts
|
|
746
|
-
function
|
|
746
|
+
function W(e, t) {
|
|
747
747
|
let n = t.find((t) => t.strategy === e.strategy);
|
|
748
748
|
if (!n?.options) return e;
|
|
749
749
|
let r = s.passthrough().parse({
|
|
@@ -755,11 +755,11 @@ function z(e, t) {
|
|
|
755
755
|
...e.options
|
|
756
756
|
}), r;
|
|
757
757
|
}
|
|
758
|
-
function
|
|
758
|
+
function G(e, t) {
|
|
759
759
|
let n = [...t || [], ...e || []];
|
|
760
760
|
return [...new Set(n)];
|
|
761
761
|
}
|
|
762
|
-
function
|
|
762
|
+
function ge(e, t) {
|
|
763
763
|
if (!t?.length) return e || [];
|
|
764
764
|
if (!e?.length) return t;
|
|
765
765
|
let n = /* @__PURE__ */ new Map();
|
|
@@ -767,22 +767,22 @@ function be(e, t) {
|
|
|
767
767
|
for (let t of e) n.set(t.value, t);
|
|
768
768
|
return Array.from(n.values());
|
|
769
769
|
}
|
|
770
|
-
function
|
|
770
|
+
function _e(e, t) {
|
|
771
771
|
return t ? {
|
|
772
772
|
...e,
|
|
773
|
-
scopes:
|
|
773
|
+
scopes: ge(e.scopes, t.scopes)
|
|
774
774
|
} : e;
|
|
775
775
|
}
|
|
776
|
-
function
|
|
776
|
+
function ve(e, t) {
|
|
777
777
|
return t ? {
|
|
778
778
|
...e,
|
|
779
|
-
callbacks:
|
|
780
|
-
web_origins:
|
|
781
|
-
allowed_logout_urls:
|
|
782
|
-
allowed_origins:
|
|
779
|
+
callbacks: G(e.callbacks, t.callbacks),
|
|
780
|
+
web_origins: G(e.web_origins, t.web_origins),
|
|
781
|
+
allowed_logout_urls: G(e.allowed_logout_urls, t.allowed_logout_urls),
|
|
782
|
+
allowed_origins: G(e.allowed_origins, t.allowed_origins)
|
|
783
783
|
} : e;
|
|
784
784
|
}
|
|
785
|
-
function
|
|
785
|
+
function ye(e) {
|
|
786
786
|
let { controlPlaneTenantId: t, controlPlaneClientId: n, resolveControlPlane: r } = e;
|
|
787
787
|
if (r) return async (e) => r({ tenant_id: e });
|
|
788
788
|
if (!t) return async () => void 0;
|
|
@@ -792,14 +792,14 @@ function H(e) {
|
|
|
792
792
|
};
|
|
793
793
|
return async () => i;
|
|
794
794
|
}
|
|
795
|
-
function
|
|
795
|
+
function be(e, t) {
|
|
796
796
|
return {
|
|
797
797
|
...e.resourceServers,
|
|
798
798
|
get: async (n, r) => {
|
|
799
799
|
let i = await e.resourceServers.get(n, r);
|
|
800
800
|
if (!i) return i;
|
|
801
801
|
let a = await t(n);
|
|
802
|
-
return !a || n === a.tenantId || !i.is_system ? i :
|
|
802
|
+
return !a || n === a.tenantId || !i.is_system ? i : _e(i, await e.resourceServers.get(a.tenantId, r));
|
|
803
803
|
},
|
|
804
804
|
list: async (n, r) => {
|
|
805
805
|
let i = await e.resourceServers.list(n, r), a = await t(n);
|
|
@@ -811,7 +811,7 @@ function U(e, t) {
|
|
|
811
811
|
let n = await e.resourceServers.get(o, t);
|
|
812
812
|
n && c.set(t, n);
|
|
813
813
|
}));
|
|
814
|
-
let l = i.resource_servers.map((e) => e.is_system && e.id ?
|
|
814
|
+
let l = i.resource_servers.map((e) => e.is_system && e.id ? _e(e, c.get(e.id) ?? null) : e);
|
|
815
815
|
return {
|
|
816
816
|
...i,
|
|
817
817
|
resource_servers: l
|
|
@@ -819,18 +819,18 @@ function U(e, t) {
|
|
|
819
819
|
}
|
|
820
820
|
};
|
|
821
821
|
}
|
|
822
|
-
function
|
|
823
|
-
let n =
|
|
822
|
+
function xe(e, t) {
|
|
823
|
+
let n = ye({
|
|
824
824
|
controlPlaneTenantId: t.controlPlaneTenantId,
|
|
825
825
|
resolveControlPlane: t.resolveControlPlane
|
|
826
826
|
});
|
|
827
827
|
return {
|
|
828
828
|
...e,
|
|
829
|
-
resourceServers:
|
|
829
|
+
resourceServers: be(e, n)
|
|
830
830
|
};
|
|
831
831
|
}
|
|
832
|
-
function
|
|
833
|
-
let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i } = t, a =
|
|
832
|
+
function Se(e, t) {
|
|
833
|
+
let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i } = t, a = ye({
|
|
834
834
|
controlPlaneTenantId: n,
|
|
835
835
|
controlPlaneClientId: r,
|
|
836
836
|
resolveControlPlane: i
|
|
@@ -848,12 +848,12 @@ function G(e, t) {
|
|
|
848
848
|
let r = await e.connections.get(t, n);
|
|
849
849
|
if (!r) return r;
|
|
850
850
|
let i = await a(t);
|
|
851
|
-
return !i || t === i.tenantId ? r :
|
|
851
|
+
return !i || t === i.tenantId ? r : W(r, (await e.connections.list(i.tenantId)).connections || []);
|
|
852
852
|
},
|
|
853
853
|
list: async (t, n) => {
|
|
854
854
|
let r = await e.connections.list(t, n), i = await a(t);
|
|
855
855
|
if (!i || t === i.tenantId) return r;
|
|
856
|
-
let o = await e.connections.list(i.tenantId), s = r.connections.map((e) =>
|
|
856
|
+
let o = await e.connections.list(i.tenantId), s = r.connections.map((e) => W(e, o.connections || []));
|
|
857
857
|
return {
|
|
858
858
|
...r,
|
|
859
859
|
connections: s
|
|
@@ -868,7 +868,7 @@ function G(e, t) {
|
|
|
868
868
|
let i = await a(t);
|
|
869
869
|
if (!i || t === i.tenantId) return r;
|
|
870
870
|
let o = await e.connections.list(i.tenantId);
|
|
871
|
-
return r.map((e) =>
|
|
871
|
+
return r.map((e) => W(e, o.connections || []));
|
|
872
872
|
}
|
|
873
873
|
},
|
|
874
874
|
emailProviders: {
|
|
@@ -880,22 +880,22 @@ function G(e, t) {
|
|
|
880
880
|
return !r || t === r.tenantId ? null : e.emailProviders.get(r.tenantId);
|
|
881
881
|
}
|
|
882
882
|
},
|
|
883
|
-
resourceServers:
|
|
884
|
-
hooks:
|
|
883
|
+
resourceServers: be(e, a),
|
|
884
|
+
hooks: we(e, a)
|
|
885
885
|
};
|
|
886
886
|
}
|
|
887
|
-
function
|
|
887
|
+
function Ce(e) {
|
|
888
888
|
if (!e || typeof e != "object") return !1;
|
|
889
889
|
let t = e.metadata;
|
|
890
890
|
return !t || typeof t != "object" ? !1 : t.inheritable === !0;
|
|
891
891
|
}
|
|
892
|
-
function
|
|
892
|
+
function we(e, t) {
|
|
893
893
|
return {
|
|
894
894
|
...e.hooks,
|
|
895
895
|
list: async (n, r) => {
|
|
896
896
|
let i = await e.hooks.list(n, r), a = await t(n);
|
|
897
897
|
if (!a || n === a.tenantId) return i;
|
|
898
|
-
let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(
|
|
898
|
+
let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(Ce);
|
|
899
899
|
if (o.length === 0) return i;
|
|
900
900
|
let s = new Set((i.hooks || []).map((e) => e.hook_id)), c = o.filter((e) => !s.has(e.hook_id));
|
|
901
901
|
return {
|
|
@@ -910,31 +910,31 @@ function Se(e, t) {
|
|
|
910
910
|
let a = await t(n);
|
|
911
911
|
if (!a || n === a.tenantId) return i;
|
|
912
912
|
let o = await e.hooks.get(a.tenantId, r);
|
|
913
|
-
return o &&
|
|
913
|
+
return o && Ce(o) ? o : null;
|
|
914
914
|
}
|
|
915
915
|
};
|
|
916
916
|
}
|
|
917
|
-
function
|
|
918
|
-
return
|
|
917
|
+
function K(e, t) {
|
|
918
|
+
return Se(e, t);
|
|
919
919
|
}
|
|
920
920
|
//#endregion
|
|
921
921
|
//#region src/middleware/index.ts
|
|
922
|
-
function
|
|
922
|
+
function Te(e) {
|
|
923
923
|
return async (t, n) => {
|
|
924
924
|
let r = t.var.user;
|
|
925
925
|
return r?.tenant_id === e && r.org_name && t.set("tenant_id", r.org_name), n();
|
|
926
926
|
};
|
|
927
927
|
}
|
|
928
|
-
function
|
|
928
|
+
function Ee(e) {
|
|
929
929
|
return async (n, r) => {
|
|
930
930
|
if (!e.accessControl) return r();
|
|
931
931
|
let { controlPlaneTenantId: i } = e.accessControl, a = n.var.org_name, o = n.var.organization_id, s = a || o, c = n.var.tenant_id, l = n.var.user, u = (l?.aud ? Array.isArray(l.aud) ? l.aud : [l.aud] : []).includes(t);
|
|
932
|
-
if (!c && s && u && (n.set("tenant_id", s), c = s), !c) throw new
|
|
933
|
-
if (!
|
|
932
|
+
if (!c && s && u && (n.set("tenant_id", s), c = s), !c) throw new w(400, { message: "Tenant ID not found in request" });
|
|
933
|
+
if (!E(o, c, i, a)) throw new w(403, { message: `Access denied to tenant ${c}` });
|
|
934
934
|
return r();
|
|
935
935
|
};
|
|
936
936
|
}
|
|
937
|
-
function
|
|
937
|
+
function De(e) {
|
|
938
938
|
return async (t, n) => {
|
|
939
939
|
if (!e.subdomainRouting) return n();
|
|
940
940
|
let { baseDomain: r, reservedSubdomains: i = [], resolveSubdomain: a } = e.subdomainRouting, o = t.req.header("x-forwarded-host") || t.req.header("host") || "", s = null;
|
|
@@ -949,43 +949,43 @@ function Te(e) {
|
|
|
949
949
|
let n = await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId, s);
|
|
950
950
|
n && (c = n.id);
|
|
951
951
|
} catch {}
|
|
952
|
-
if (!c) throw new
|
|
952
|
+
if (!c) throw new w(404, { message: `Tenant not found for subdomain: ${s}` });
|
|
953
953
|
return t.set("tenant_id", c), n();
|
|
954
954
|
};
|
|
955
955
|
}
|
|
956
|
-
function
|
|
956
|
+
function Oe(e) {
|
|
957
957
|
return async (t, n) => {
|
|
958
958
|
if (!e.databaseIsolation) return n();
|
|
959
959
|
let r = t.var.tenant_id;
|
|
960
|
-
if (!r) throw new
|
|
960
|
+
if (!r) throw new w(400, { message: "Tenant ID not found in request" });
|
|
961
961
|
try {
|
|
962
962
|
let n = await e.databaseIsolation.getAdapters(r);
|
|
963
963
|
t.env.data = n;
|
|
964
964
|
} catch (e) {
|
|
965
|
-
throw console.error(`Failed to resolve database for tenant ${r}:`, e), new
|
|
965
|
+
throw console.error(`Failed to resolve database for tenant ${r}:`, e), new w(500, { message: "Failed to resolve tenant database" });
|
|
966
966
|
}
|
|
967
967
|
return n();
|
|
968
968
|
};
|
|
969
969
|
}
|
|
970
|
-
function
|
|
971
|
-
let t =
|
|
970
|
+
function q(e) {
|
|
971
|
+
let t = De(e), n = Ee(e), r = Oe(e);
|
|
972
972
|
return async (e, i) => (await t(e, async () => {}), await n(e, async () => {}), await r(e, async () => {}), i());
|
|
973
973
|
}
|
|
974
974
|
//#endregion
|
|
975
975
|
//#region src/init.ts
|
|
976
|
-
function
|
|
976
|
+
function ke(e) {
|
|
977
977
|
let { dataAdapter: t, controlPlane: n, controlPlane: { tenantId: r = "control_plane", clientId: i } = {}, resolveControlPlane: a, sync: o = {
|
|
978
978
|
resourceServers: !0,
|
|
979
979
|
roles: !0
|
|
980
|
-
}, defaultPermissions: s = ["tenant:admin"], requireOrganizationMatch: c = !1, managementApiExtensions: l = [], entityHooks:
|
|
980
|
+
}, defaultPermissions: s = ["tenant:admin"], requireOrganizationMatch: c = !1, managementApiExtensions: l = [], entityHooks: u, getChildTenantIds: f, getAdapters: m, ...h } = e;
|
|
981
981
|
if (a && !n) throw Error("initMultiTenant: `resolveControlPlane` requires `controlPlane` to be set. The static `controlPlane.tenantId` is used for access control, sync direction, and tenant management routing; the resolver only overrides per-tenant runtime inheritance lookups on top of it.");
|
|
982
982
|
let g = t, _ = t;
|
|
983
|
-
n && (g =
|
|
983
|
+
n && (g = K(t, {
|
|
984
984
|
controlPlaneTenantId: r,
|
|
985
985
|
controlPlaneClientId: i,
|
|
986
986
|
resolveControlPlane: a
|
|
987
987
|
}), _ = {
|
|
988
|
-
...
|
|
988
|
+
...xe(t, {
|
|
989
989
|
controlPlaneTenantId: r,
|
|
990
990
|
resolveControlPlane: a
|
|
991
991
|
}),
|
|
@@ -1000,7 +1000,7 @@ function De(e) {
|
|
|
1000
1000
|
let e = {
|
|
1001
1001
|
tenantOperations: t.tenantOperations,
|
|
1002
1002
|
tenantOperationEvents: t.tenantOperationEvents
|
|
1003
|
-
}, n = h.tenantUpgrade, r =
|
|
1003
|
+
}, n = h.tenantUpgrade, r = te({
|
|
1004
1004
|
stores: e,
|
|
1005
1005
|
definitions: { upgrade: (e) => [{
|
|
1006
1006
|
name: "upgrade",
|
|
@@ -1012,70 +1012,70 @@ function De(e) {
|
|
|
1012
1012
|
});
|
|
1013
1013
|
v = {
|
|
1014
1014
|
engine: r.engine,
|
|
1015
|
-
enqueue: (t) =>
|
|
1015
|
+
enqueue: (t) => re(e, r, {
|
|
1016
1016
|
...t,
|
|
1017
1017
|
tenant_id: t.tenant_id
|
|
1018
1018
|
})
|
|
1019
1019
|
};
|
|
1020
1020
|
}
|
|
1021
|
-
let y = o !== !1,
|
|
1021
|
+
let y = o !== !1, b = y ? {
|
|
1022
1022
|
resourceServers: o.resourceServers ?? !0,
|
|
1023
1023
|
roles: o.roles ?? !0
|
|
1024
1024
|
} : {
|
|
1025
1025
|
resourceServers: !1,
|
|
1026
1026
|
roles: !1
|
|
1027
|
-
}, { entityHooks:
|
|
1027
|
+
}, { entityHooks: x, tenantHooks: S } = V({
|
|
1028
1028
|
controlPlaneTenantId: r,
|
|
1029
|
-
getChildTenantIds:
|
|
1029
|
+
getChildTenantIds: f ?? (async () => (await d((e) => g.tenants.list(e), "tenants", {
|
|
1030
1030
|
cursorField: "id",
|
|
1031
1031
|
pageSize: 100
|
|
1032
1032
|
})).filter((e) => e.id !== r).map((e) => e.id)),
|
|
1033
1033
|
getAdapters: m ?? (async () => g),
|
|
1034
1034
|
getControlPlaneAdapters: async () => g,
|
|
1035
|
-
sync:
|
|
1036
|
-
}),
|
|
1037
|
-
resourceServers: [
|
|
1038
|
-
roles: [
|
|
1039
|
-
connections:
|
|
1040
|
-
tenants:
|
|
1041
|
-
rolePermissions:
|
|
1042
|
-
},
|
|
1035
|
+
sync: b
|
|
1036
|
+
}), C = {
|
|
1037
|
+
resourceServers: [x.resourceServers, ...u?.resourceServers ?? []],
|
|
1038
|
+
roles: [x.roles, ...u?.roles ?? []],
|
|
1039
|
+
connections: u?.connections ?? [],
|
|
1040
|
+
tenants: u?.tenants ?? [],
|
|
1041
|
+
rolePermissions: u?.rolePermissions ?? []
|
|
1042
|
+
}, w = F({ accessControl: {
|
|
1043
1043
|
controlPlaneTenantId: r,
|
|
1044
1044
|
requireOrganizationMatch: c,
|
|
1045
1045
|
defaultPermissions: s
|
|
1046
|
-
} }),
|
|
1046
|
+
} }), T = H({ accessControl: {
|
|
1047
1047
|
controlPlaneTenantId: r,
|
|
1048
1048
|
requireOrganizationMatch: c,
|
|
1049
1049
|
defaultPermissions: s
|
|
1050
1050
|
} }, { tenants: {
|
|
1051
1051
|
async beforeCreate(e, t) {
|
|
1052
|
-
return
|
|
1052
|
+
return w.beforeCreate && (t = await w.beforeCreate(e, t)), S.beforeCreate && (t = await S.beforeCreate(e, t)), t;
|
|
1053
1053
|
},
|
|
1054
1054
|
async afterCreate(e, t) {
|
|
1055
|
-
await
|
|
1055
|
+
await w.afterCreate?.(e, t), await S.afterCreate?.(e, t);
|
|
1056
1056
|
},
|
|
1057
1057
|
async beforeDelete(e, t) {
|
|
1058
|
-
await
|
|
1058
|
+
await w.beforeDelete?.(e, t), await S.beforeDelete?.(e, t);
|
|
1059
1059
|
}
|
|
1060
|
-
} }), { app:
|
|
1060
|
+
} }), { app: E } = p({
|
|
1061
1061
|
dataAdapter: g,
|
|
1062
1062
|
managementDataAdapter: _,
|
|
1063
1063
|
...h,
|
|
1064
1064
|
tenantOperationExecutor: v,
|
|
1065
|
-
entityHooks:
|
|
1065
|
+
entityHooks: C,
|
|
1066
1066
|
managementApiExtensions: [...l, {
|
|
1067
1067
|
path: "/tenants",
|
|
1068
|
-
router:
|
|
1068
|
+
router: T
|
|
1069
1069
|
}]
|
|
1070
1070
|
});
|
|
1071
|
-
return
|
|
1072
|
-
app:
|
|
1071
|
+
return E.use("/api/v2/*", Te(r)), y && E.use("/api/v2/*", U()), {
|
|
1072
|
+
app: E,
|
|
1073
1073
|
controlPlaneTenantId: r
|
|
1074
1074
|
};
|
|
1075
1075
|
}
|
|
1076
1076
|
//#endregion
|
|
1077
1077
|
//#region src/rollout/defaults-projection.ts
|
|
1078
|
-
function
|
|
1078
|
+
function J(e = {}) {
|
|
1079
1079
|
return {
|
|
1080
1080
|
connections: e.connections ?? !0,
|
|
1081
1081
|
resourceServers: e.resourceServers ?? !0,
|
|
@@ -1085,28 +1085,28 @@ function Y(e = {}) {
|
|
|
1085
1085
|
promptSettings: e.promptSettings ?? !0
|
|
1086
1086
|
};
|
|
1087
1087
|
}
|
|
1088
|
-
function
|
|
1088
|
+
function Y() {
|
|
1089
1089
|
return {
|
|
1090
1090
|
upserted: 0,
|
|
1091
1091
|
errors: []
|
|
1092
1092
|
};
|
|
1093
1093
|
}
|
|
1094
|
-
function
|
|
1094
|
+
function Ae(e) {
|
|
1095
1095
|
return {
|
|
1096
1096
|
tenantId: e,
|
|
1097
|
-
connections:
|
|
1098
|
-
resourceServers:
|
|
1099
|
-
hooks:
|
|
1100
|
-
emailProvider:
|
|
1101
|
-
branding:
|
|
1102
|
-
promptSettings:
|
|
1097
|
+
connections: Y(),
|
|
1098
|
+
resourceServers: Y(),
|
|
1099
|
+
hooks: Y(),
|
|
1100
|
+
emailProvider: Y(),
|
|
1101
|
+
branding: Y(),
|
|
1102
|
+
promptSettings: Y()
|
|
1103
1103
|
};
|
|
1104
1104
|
}
|
|
1105
|
-
function
|
|
1105
|
+
function je(e) {
|
|
1106
1106
|
let t = e.metadata;
|
|
1107
1107
|
return !!(t && t.inheritable === !0);
|
|
1108
1108
|
}
|
|
1109
|
-
async function
|
|
1109
|
+
async function X(e, t, n, r) {
|
|
1110
1110
|
try {
|
|
1111
1111
|
await r();
|
|
1112
1112
|
} catch (r) {
|
|
@@ -1115,17 +1115,17 @@ async function Z(e, t, n, r) {
|
|
|
1115
1115
|
e.errors.push(i);
|
|
1116
1116
|
}
|
|
1117
1117
|
}
|
|
1118
|
-
async function
|
|
1118
|
+
async function Me(e, t, n) {
|
|
1119
1119
|
return {
|
|
1120
|
-
connections: n.connections ? await
|
|
1120
|
+
connections: n.connections ? await d((n) => e.connections.list(t, n), "connections", {
|
|
1121
1121
|
cursorField: "id",
|
|
1122
1122
|
pageSize: 100
|
|
1123
1123
|
}) : [],
|
|
1124
|
-
resourceServers: n.resourceServers ? await
|
|
1124
|
+
resourceServers: n.resourceServers ? await d((n) => e.resourceServers.list(t, n), "resource_servers", {
|
|
1125
1125
|
cursorField: "id",
|
|
1126
1126
|
pageSize: 100
|
|
1127
1127
|
}) : [],
|
|
1128
|
-
hooks: n.hooks ? await
|
|
1128
|
+
hooks: n.hooks ? await d((n) => e.hooks.list(t, n), "hooks", {
|
|
1129
1129
|
cursorField: "hook_id",
|
|
1130
1130
|
pageSize: 100
|
|
1131
1131
|
}) : [],
|
|
@@ -1134,47 +1134,47 @@ async function Ae(e, t, n) {
|
|
|
1134
1134
|
promptSettings: n.promptSettings ? await e.promptSettings.get(t) ?? null : null
|
|
1135
1135
|
};
|
|
1136
1136
|
}
|
|
1137
|
-
async function
|
|
1137
|
+
async function Ne(e, t, n, r, i, o) {
|
|
1138
1138
|
if (r.connections) for (let r of e.connections) {
|
|
1139
1139
|
let e = r.id;
|
|
1140
|
-
e && await
|
|
1140
|
+
e && await X(o.connections, `connection ${e}`, i, async () => {
|
|
1141
1141
|
let i = a.parse(r);
|
|
1142
1142
|
await t.connections.get(n, e) ? await t.connections.update(n, e, i) : await t.connections.create(n, i), o.connections.upserted += 1;
|
|
1143
1143
|
});
|
|
1144
1144
|
}
|
|
1145
|
-
if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await
|
|
1146
|
-
let e =
|
|
1145
|
+
if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await X(o.resourceServers, `resource_server ${r.id}`, i, async () => {
|
|
1146
|
+
let e = v.parse(r);
|
|
1147
1147
|
await t.resourceServers.get(n, r.id) ? await t.resourceServers.update(n, r.id, e) : await t.resourceServers.create(n, e), o.resourceServers.upserted += 1;
|
|
1148
1148
|
});
|
|
1149
|
-
if (r.hooks) for (let r of e.hooks) !
|
|
1150
|
-
let e =
|
|
1149
|
+
if (r.hooks) for (let r of e.hooks) !je(r) || !r.hook_id || await X(o.hooks, `hook ${r.hook_id}`, i, async () => {
|
|
1150
|
+
let e = f.parse(r);
|
|
1151
1151
|
await t.hooks.get(n, r.hook_id) ? await t.hooks.update(n, r.hook_id, e) : await t.hooks.create(n, e), o.hooks.upserted += 1;
|
|
1152
1152
|
});
|
|
1153
|
-
r.emailProvider && e.emailProvider && await
|
|
1153
|
+
r.emailProvider && e.emailProvider && await X(o.emailProvider, "email_provider", i, async () => {
|
|
1154
1154
|
let r = e.emailProvider;
|
|
1155
1155
|
await t.emailProviders.get(n) ? await t.emailProviders.update(n, r) : await t.emailProviders.create(n, r), o.emailProvider.upserted += 1;
|
|
1156
|
-
}), r.branding && e.branding && await
|
|
1156
|
+
}), r.branding && e.branding && await X(o.branding, "branding", i, async () => {
|
|
1157
1157
|
await t.branding.set(n, e.branding), o.branding.upserted += 1;
|
|
1158
|
-
}), r.promptSettings && e.promptSettings && await
|
|
1158
|
+
}), r.promptSettings && e.promptSettings && await X(o.promptSettings, "prompt_settings", i, async () => {
|
|
1159
1159
|
await t.promptSettings.set(n, e.promptSettings), o.promptSettings.upserted += 1;
|
|
1160
1160
|
});
|
|
1161
1161
|
}
|
|
1162
|
-
async function
|
|
1163
|
-
let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s =
|
|
1164
|
-
return await
|
|
1162
|
+
async function Z(e, t) {
|
|
1163
|
+
let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s = J(a), c = await Me(await r(), n, s), l = await i(t), u = Ae(t);
|
|
1164
|
+
return await Ne(c, l, n, s, o, u), u;
|
|
1165
1165
|
}
|
|
1166
1166
|
//#endregion
|
|
1167
1167
|
//#region src/rollout/payload.ts
|
|
1168
|
-
function
|
|
1168
|
+
function Pe(e) {
|
|
1169
1169
|
let { pkcs7: t, tenant_id: n, ...r } = e;
|
|
1170
1170
|
return r;
|
|
1171
1171
|
}
|
|
1172
|
-
async function
|
|
1173
|
-
let i =
|
|
1172
|
+
async function Fe(e, t, n = {}, r) {
|
|
1173
|
+
let i = J(n), a = n.signingKeys ?? !0, o = n.tenants ?? !0, s = await Me(e, t, i), c = a ? (await h(e.keys)).map(Pe) : [], l = o ? await Ie(e, t, r) : [];
|
|
1174
1174
|
return {
|
|
1175
1175
|
connections: s.connections,
|
|
1176
1176
|
resourceServers: s.resourceServers.filter((e) => e.is_system),
|
|
1177
|
-
hooks: s.hooks.filter(
|
|
1177
|
+
hooks: s.hooks.filter(je),
|
|
1178
1178
|
emailProvider: s.emailProvider,
|
|
1179
1179
|
branding: s.branding,
|
|
1180
1180
|
promptSettings: s.promptSettings,
|
|
@@ -1182,7 +1182,7 @@ async function Ne(e, t, n = {}, r) {
|
|
|
1182
1182
|
tenants: l
|
|
1183
1183
|
};
|
|
1184
1184
|
}
|
|
1185
|
-
async function
|
|
1185
|
+
async function Ie(e, t, n) {
|
|
1186
1186
|
let r = n && n !== t ? [t, n] : [t], i = [];
|
|
1187
1187
|
for (let t of r) {
|
|
1188
1188
|
let n = await e.tenants.get(t);
|
|
@@ -1193,19 +1193,19 @@ async function Pe(e, t, n) {
|
|
|
1193
1193
|
}
|
|
1194
1194
|
return i;
|
|
1195
1195
|
}
|
|
1196
|
-
async function
|
|
1197
|
-
let r =
|
|
1196
|
+
async function Le(e, t, n) {
|
|
1197
|
+
let r = Y();
|
|
1198
1198
|
if (e.length === 0) return r;
|
|
1199
|
-
let i = await
|
|
1200
|
-
for (let i of e) await
|
|
1201
|
-
let e =
|
|
1199
|
+
let i = await h(t.keys), a = new Set(i.map((e) => e.kid));
|
|
1200
|
+
for (let i of e) await X(r, `signing_key ${i.kid}`, n, async () => {
|
|
1201
|
+
let e = Pe(i);
|
|
1202
1202
|
a.has(e.kid) || (await t.keys.create(e), a.add(e.kid), r.upserted += 1);
|
|
1203
1203
|
});
|
|
1204
1204
|
return r;
|
|
1205
1205
|
}
|
|
1206
|
-
async function
|
|
1207
|
-
let r =
|
|
1208
|
-
for (let i of e) await
|
|
1206
|
+
async function Re(e, t, n) {
|
|
1207
|
+
let r = Y();
|
|
1208
|
+
for (let i of e) await X(r, `tenant ${i.id}`, n, async () => {
|
|
1209
1209
|
await t.tenants.get(i.id) || (await t.tenants.create({
|
|
1210
1210
|
id: i.id,
|
|
1211
1211
|
friendly_name: i.friendly_name
|
|
@@ -1213,17 +1213,17 @@ async function Ie(e, t, n) {
|
|
|
1213
1213
|
});
|
|
1214
1214
|
return r;
|
|
1215
1215
|
}
|
|
1216
|
-
async function
|
|
1217
|
-
let a = r.continueOnError ?? !1, o =
|
|
1216
|
+
async function ze(e, t, n, r = {}) {
|
|
1217
|
+
let a = r.continueOnError ?? !1, o = J(r.entities), s = r.entities?.signingKeys ?? !0, c = r.entities?.tenants ?? !0, u = {
|
|
1218
1218
|
connections: e.connections,
|
|
1219
1219
|
resourceServers: e.resourceServers,
|
|
1220
1220
|
hooks: e.hooks,
|
|
1221
1221
|
emailProvider: e.emailProvider ? l.parse(e.emailProvider) : null,
|
|
1222
1222
|
branding: e.branding ? i.parse(e.branding) : null,
|
|
1223
|
-
promptSettings: e.promptSettings ?
|
|
1224
|
-
}, d = c ? await
|
|
1225
|
-
await
|
|
1226
|
-
let p = s ? await
|
|
1223
|
+
promptSettings: e.promptSettings ? g.parse(e.promptSettings) : null
|
|
1224
|
+
}, d = c ? await Re(e.tenants ?? [], t, a) : Y(), f = Ae(n);
|
|
1225
|
+
await Ne(u, t, n, o, a, f);
|
|
1226
|
+
let p = s ? await Le(e.signingKeys, t, a) : Y();
|
|
1227
1227
|
return {
|
|
1228
1228
|
...f,
|
|
1229
1229
|
signingKeys: p,
|
|
@@ -1232,27 +1232,27 @@ async function Le(e, t, n, r = {}) {
|
|
|
1232
1232
|
}
|
|
1233
1233
|
//#endregion
|
|
1234
1234
|
//#region src/rollout/index.ts
|
|
1235
|
-
function
|
|
1235
|
+
function Be(e) {
|
|
1236
1236
|
return {
|
|
1237
|
-
syncDefaults: (t) =>
|
|
1237
|
+
syncDefaults: (t) => Z(e, t),
|
|
1238
1238
|
syncDefaultsToTenants: async (t) => {
|
|
1239
1239
|
let n = [];
|
|
1240
|
-
for (let r of t) n.push(await
|
|
1240
|
+
for (let r of t) n.push(await Z(e, r));
|
|
1241
1241
|
return n;
|
|
1242
1242
|
}
|
|
1243
1243
|
};
|
|
1244
1244
|
}
|
|
1245
1245
|
//#endregion
|
|
1246
1246
|
//#region src/plugin.ts
|
|
1247
|
-
function
|
|
1248
|
-
let t =
|
|
1247
|
+
function Ve(e) {
|
|
1248
|
+
let t = Q(e);
|
|
1249
1249
|
return {
|
|
1250
1250
|
name: "multi-tenancy",
|
|
1251
|
-
middleware:
|
|
1251
|
+
middleware: q(e),
|
|
1252
1252
|
hooks: t,
|
|
1253
1253
|
routes: [{
|
|
1254
1254
|
path: "/management",
|
|
1255
|
-
handler:
|
|
1255
|
+
handler: H(e, t)
|
|
1256
1256
|
}],
|
|
1257
1257
|
onRegister: async () => {
|
|
1258
1258
|
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");
|
|
@@ -1261,29 +1261,29 @@ function ze(e) {
|
|
|
1261
1261
|
}
|
|
1262
1262
|
//#endregion
|
|
1263
1263
|
//#region src/index.ts
|
|
1264
|
-
function
|
|
1265
|
-
let t = e.accessControl ?
|
|
1264
|
+
function Q(e) {
|
|
1265
|
+
let t = e.accessControl ? T(e.accessControl) : {}, n = e.databaseIsolation ? D(e.databaseIsolation) : {}, r = F(e);
|
|
1266
1266
|
return {
|
|
1267
1267
|
...t,
|
|
1268
1268
|
...n,
|
|
1269
1269
|
tenants: r
|
|
1270
1270
|
};
|
|
1271
1271
|
}
|
|
1272
|
-
function
|
|
1273
|
-
let n = new e(), r =
|
|
1274
|
-
return n.route("/tenants",
|
|
1272
|
+
function $(t) {
|
|
1273
|
+
let n = new e(), r = Q(t);
|
|
1274
|
+
return n.route("/tenants", H(t, r)), n;
|
|
1275
1275
|
}
|
|
1276
|
-
function
|
|
1276
|
+
function He(e) {
|
|
1277
1277
|
return {
|
|
1278
|
-
hooks:
|
|
1279
|
-
middleware:
|
|
1280
|
-
app:
|
|
1278
|
+
hooks: Q(e),
|
|
1279
|
+
middleware: q(e),
|
|
1280
|
+
app: $(e),
|
|
1281
1281
|
config: e,
|
|
1282
|
-
wrapAdapters: (t, n) =>
|
|
1282
|
+
wrapAdapters: (t, n) => K(t, {
|
|
1283
1283
|
controlPlaneTenantId: e.accessControl?.controlPlaneTenantId,
|
|
1284
1284
|
controlPlaneClientId: n?.controlPlaneClientId
|
|
1285
1285
|
})
|
|
1286
1286
|
};
|
|
1287
1287
|
}
|
|
1288
1288
|
//#endregion
|
|
1289
|
-
export {
|
|
1289
|
+
export { ze as applyControlPlaneDefaultsPayload, Fe as buildControlPlaneDefaultsPayload, A as buildEngineInstanceId, T as createAccessControlHooks, Ee as createAccessControlMiddleware, Te as createControlPlaneTenantMiddleware, D as createDatabaseHooks, Oe as createDatabaseMiddleware, Be as createDirectRolloutAdapter, te as createInlineExecutor, $ as createMultiTenancy, Q as createMultiTenancyHooks, q as createMultiTenancyMiddleware, Ve as createMultiTenancyPlugin, M as createOperationRecorder, U as createProtectSyncedMiddleware, F as createProvisioningHooks, Se as createRuntimeFallbackAdapter, De as createSubdomainMiddleware, V as createSyncHooks, H as createTenantsOpenAPIRouter, re as enqueueTenantOperation, j as errorToMessage, ke as initMultiTenant, P as inlineStepRunner, N as isTerminalStatus, ve as mergeClientWithFallback, Z as projectControlPlaneDefaults, ae as runRecordedTenantOperation, He as setupMultiTenancy, E as validateTenantAccess, K as withRuntimeFallback, xe as withSystemResourceServerInheritance };
|