@authhero/multi-tenancy 14.25.1 → 14.27.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 +1 -1
- package/dist/multi-tenancy.mjs +435 -181
- package/dist/types/hooks/provisioning.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/init.d.ts.map +1 -1
- package/dist/types/operations/enqueue.d.ts +17 -0
- package/dist/types/operations/enqueue.d.ts.map +1 -0
- package/dist/types/operations/index.d.ts +9 -0
- package/dist/types/operations/index.d.ts.map +1 -0
- package/dist/types/operations/inline-executor.d.ts +40 -0
- package/dist/types/operations/inline-executor.d.ts.map +1 -0
- package/dist/types/operations/instance-id.d.ts +6 -0
- package/dist/types/operations/instance-id.d.ts.map +1 -0
- package/dist/types/operations/record-provision.d.ts +20 -0
- package/dist/types/operations/record-provision.d.ts.map +1 -0
- package/dist/types/operations/recorder.d.ts +29 -0
- package/dist/types/operations/recorder.d.ts.map +1 -0
- package/dist/types/operations/types.d.ts +59 -0
- package/dist/types/operations/types.d.ts.map +1 -0
- package/dist/types/routes/tenants.d.ts.map +1 -1
- package/dist/types/types.d.ts +17 -1
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +4 -4
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, fetchAll as u, hookInsertSchema as d, init as f,
|
|
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, fetchAll as u, hookInsertSchema as d, init as f, isInteractiveClient as p, listControlPlaneKeys as m, promptSettingSchema as h, provisionDefaultClients as g, resourceServerInsertSchema as _, tenantInsertSchema as v, tenantSchema as y } from "authhero";
|
|
3
|
+
import { OpenAPIHono as ee, createRoute as b, z as x } from "@hono/zod-openapi";
|
|
4
|
+
import { HTTPException as S } from "hono/http-exception";
|
|
5
5
|
//#region src/hooks/access-control.ts
|
|
6
|
-
function
|
|
6
|
+
function C(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 S(e) {
|
|
|
14
14
|
return !0;
|
|
15
15
|
} };
|
|
16
16
|
}
|
|
17
|
-
function
|
|
17
|
+
function w(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 T(e) {
|
|
25
25
|
return { async resolveDataAdapters(t) {
|
|
26
26
|
try {
|
|
27
27
|
return await e.getAdapters(t);
|
|
@@ -32,21 +32,243 @@ function w(e) {
|
|
|
32
32
|
} };
|
|
33
33
|
}
|
|
34
34
|
//#endregion
|
|
35
|
+
//#region src/operations/instance-id.ts
|
|
36
|
+
var E = 64;
|
|
37
|
+
function D(e) {
|
|
38
|
+
return e.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
39
|
+
}
|
|
40
|
+
function te(e) {
|
|
41
|
+
let t = D(e.id), n = Math.max(0, E - (5 + t.length)), r = D(e.kind).slice(0, n), i = 3 + r.length + 2 + t.length, a = Math.max(0, E - i);
|
|
42
|
+
return `op-${r}-${D(e.tenant_id ?? "fleet").slice(0, a)}-${t}`.slice(0, E);
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/operations/recorder.ts
|
|
46
|
+
var ne = 2048;
|
|
47
|
+
function O(e) {
|
|
48
|
+
let t;
|
|
49
|
+
if (e instanceof Error) t = e.message;
|
|
50
|
+
else try {
|
|
51
|
+
t = String(e ?? "unknown error");
|
|
52
|
+
} catch {
|
|
53
|
+
t = Object.prototype.toString.call(e);
|
|
54
|
+
}
|
|
55
|
+
return t.slice(0, ne);
|
|
56
|
+
}
|
|
57
|
+
function k(e) {
|
|
58
|
+
let { tenantOperations: t, tenantOperationEvents: n } = e;
|
|
59
|
+
return {
|
|
60
|
+
async markRunning(e, n) {
|
|
61
|
+
await t.update(e, {
|
|
62
|
+
status: "running",
|
|
63
|
+
...n === void 0 ? {} : { current_step: n }
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
async setCurrentStep(e, n) {
|
|
67
|
+
await t.update(e, { current_step: n });
|
|
68
|
+
},
|
|
69
|
+
async appendEvent(e, t) {
|
|
70
|
+
await n.create({
|
|
71
|
+
operation_id: e,
|
|
72
|
+
step: t.step,
|
|
73
|
+
outcome: t.outcome,
|
|
74
|
+
detail: t.detail,
|
|
75
|
+
attempt: t.attempt ?? 1
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
async markSucceeded(e) {
|
|
79
|
+
await t.update(e, {
|
|
80
|
+
status: "succeeded",
|
|
81
|
+
error: null,
|
|
82
|
+
finished_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
83
|
+
});
|
|
84
|
+
},
|
|
85
|
+
async markFailed(e, n) {
|
|
86
|
+
await t.update(e, {
|
|
87
|
+
status: "failed",
|
|
88
|
+
error: O(n),
|
|
89
|
+
finished_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function re(e) {
|
|
95
|
+
return e === "succeeded" || e === "failed" || e === "cancelled";
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/operations/inline-executor.ts
|
|
99
|
+
var A = { async do(e, t, n) {
|
|
100
|
+
let r = typeof t == "function" ? t : n;
|
|
101
|
+
if (!r) throw Error("StepRunner.do called without a function");
|
|
102
|
+
return r();
|
|
103
|
+
} };
|
|
104
|
+
function j(e) {
|
|
105
|
+
let t = k(e.stores);
|
|
106
|
+
return {
|
|
107
|
+
engine: "inline",
|
|
108
|
+
async start(n) {
|
|
109
|
+
let r = e.definitions[n.kind];
|
|
110
|
+
if (!r) {
|
|
111
|
+
let e = /* @__PURE__ */ Error(`No inline operation definition for kind "${n.kind}"`);
|
|
112
|
+
throw await t.markFailed(n.id, e), e;
|
|
113
|
+
}
|
|
114
|
+
let i = r(n);
|
|
115
|
+
await t.markRunning(n.id, i[0]?.name);
|
|
116
|
+
for (let e of i) {
|
|
117
|
+
await t.setCurrentStep(n.id, e.name), await t.appendEvent(n.id, {
|
|
118
|
+
step: e.name,
|
|
119
|
+
outcome: "started"
|
|
120
|
+
});
|
|
121
|
+
try {
|
|
122
|
+
let r = await e.run({
|
|
123
|
+
operation: n,
|
|
124
|
+
step: A
|
|
125
|
+
});
|
|
126
|
+
await t.appendEvent(n.id, {
|
|
127
|
+
step: e.name,
|
|
128
|
+
outcome: "succeeded",
|
|
129
|
+
detail: r ?? void 0
|
|
130
|
+
});
|
|
131
|
+
} catch (r) {
|
|
132
|
+
throw await t.appendEvent(n.id, {
|
|
133
|
+
step: e.name,
|
|
134
|
+
outcome: "failed",
|
|
135
|
+
detail: { message: O(r) }
|
|
136
|
+
}), await t.markFailed(n.id, r), r;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
await t.markSucceeded(n.id);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/operations/enqueue.ts
|
|
145
|
+
async function M(e, t, n) {
|
|
146
|
+
let r = await e.tenantOperations.create({
|
|
147
|
+
tenant_id: t.tenant_id,
|
|
148
|
+
rollout_id: t.rollout_id,
|
|
149
|
+
kind: t.kind,
|
|
150
|
+
engine: n,
|
|
151
|
+
initiated_by: t.initiated_by,
|
|
152
|
+
target_worker_version: t.target_worker_version,
|
|
153
|
+
target_database_version: t.target_database_version
|
|
154
|
+
}), i = te(r);
|
|
155
|
+
try {
|
|
156
|
+
await e.tenantOperations.update(r.id, { engine_instance_id: i });
|
|
157
|
+
} catch (t) {
|
|
158
|
+
try {
|
|
159
|
+
await k(e).markFailed(r.id, t);
|
|
160
|
+
} catch {}
|
|
161
|
+
throw t;
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
...r,
|
|
165
|
+
engine_instance_id: i
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async function N(e, t, n) {
|
|
169
|
+
let r = k(e), i = await M(e, n, t.engine);
|
|
170
|
+
try {
|
|
171
|
+
await t.start(i);
|
|
172
|
+
} catch (t) {
|
|
173
|
+
try {
|
|
174
|
+
let n = await e.tenantOperations.get(i.id);
|
|
175
|
+
n && !re(n.status) && await r.markFailed(i.id, t);
|
|
176
|
+
} catch (e) {
|
|
177
|
+
console.warn("Failed to record tenant operation failure:", e);
|
|
178
|
+
}
|
|
179
|
+
throw t;
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
return await e.tenantOperations.get(i.id) ?? i;
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return console.warn("Failed to re-fetch tenant operation after start:", e), i;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/operations/record-provision.ts
|
|
189
|
+
function ie(e) {
|
|
190
|
+
if (e.tenantOperations && e.tenantOperationEvents) return {
|
|
191
|
+
tenantOperations: e.tenantOperations,
|
|
192
|
+
tenantOperationEvents: e.tenantOperationEvents
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async function P(e, t, n) {
|
|
196
|
+
let r = ie(e);
|
|
197
|
+
if (!r) {
|
|
198
|
+
await n(void 0);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
let i = k(r), a = async (e) => {
|
|
202
|
+
try {
|
|
203
|
+
await e();
|
|
204
|
+
} catch (e) {
|
|
205
|
+
console.warn("Failed to record tenant operation progress:", e);
|
|
206
|
+
}
|
|
207
|
+
}, o;
|
|
208
|
+
if (await a(async () => {
|
|
209
|
+
let e = await M(r, t, "inline");
|
|
210
|
+
o = e.id, await i.markRunning(e.id);
|
|
211
|
+
}), !o) {
|
|
212
|
+
await n(void 0);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
let s = o, c = !1, l = async (e, t, n) => {
|
|
216
|
+
c = !0, await a(async () => {
|
|
217
|
+
t === "started" && await i.setCurrentStep(s, e), await i.appendEvent(s, {
|
|
218
|
+
step: e,
|
|
219
|
+
outcome: t,
|
|
220
|
+
detail: n
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
try {
|
|
225
|
+
await n(l);
|
|
226
|
+
} catch (e) {
|
|
227
|
+
throw await a(async () => {
|
|
228
|
+
c || await i.appendEvent(s, {
|
|
229
|
+
step: t.kind,
|
|
230
|
+
outcome: "failed",
|
|
231
|
+
detail: { message: O(e) }
|
|
232
|
+
}), await i.markFailed(s, e);
|
|
233
|
+
}), e;
|
|
234
|
+
}
|
|
235
|
+
await a(async () => {
|
|
236
|
+
c || await i.appendEvent(s, {
|
|
237
|
+
step: t.kind,
|
|
238
|
+
outcome: "succeeded"
|
|
239
|
+
}), await i.markSucceeded(s);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
//#endregion
|
|
35
243
|
//#region src/hooks/provisioning.ts
|
|
36
|
-
function
|
|
244
|
+
function ae(e) {
|
|
37
245
|
return `urn:authhero:tenant:${e.toLowerCase()}`;
|
|
38
246
|
}
|
|
39
|
-
function
|
|
247
|
+
function F(e) {
|
|
40
248
|
return {
|
|
41
249
|
async beforeCreate(e, t) {
|
|
42
250
|
return !t.audience && t.id ? {
|
|
43
251
|
...t,
|
|
44
|
-
audience:
|
|
252
|
+
audience: ae(t.id)
|
|
45
253
|
} : t;
|
|
46
254
|
},
|
|
47
|
-
async afterCreate(
|
|
48
|
-
let { accessControl:
|
|
49
|
-
|
|
255
|
+
async afterCreate(r, i) {
|
|
256
|
+
let { accessControl: a, databaseIsolation: o } = e;
|
|
257
|
+
if (a && r.ctx && await oe(r, i, a), o?.onProvision) {
|
|
258
|
+
let e = o.onProvision;
|
|
259
|
+
o.recordProvisionOperations === !1 ? await e(i.id) : await P(r.adapters, {
|
|
260
|
+
kind: "provision",
|
|
261
|
+
tenant_id: i.id,
|
|
262
|
+
initiated_by: r.ctx?.var.user?.sub
|
|
263
|
+
}, (t) => e(i.id, t));
|
|
264
|
+
} else try {
|
|
265
|
+
await g(r.adapters, i.id, {
|
|
266
|
+
managementApiIdentifier: t,
|
|
267
|
+
managementApiScopes: n
|
|
268
|
+
});
|
|
269
|
+
} catch (e) {
|
|
270
|
+
throw console.warn(`Failed to provision default clients for tenant ${i.id}:`, e), e;
|
|
271
|
+
}
|
|
50
272
|
},
|
|
51
273
|
async beforeDelete(t, n) {
|
|
52
274
|
let { accessControl: r, databaseIsolation: i } = e;
|
|
@@ -64,14 +286,14 @@ function E(e) {
|
|
|
64
286
|
}
|
|
65
287
|
};
|
|
66
288
|
}
|
|
67
|
-
async function
|
|
289
|
+
async function oe(e, t, n) {
|
|
68
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, {
|
|
69
291
|
name: t.id,
|
|
70
292
|
display_name: t.friendly_name || t.id
|
|
71
293
|
}), d;
|
|
72
|
-
if (o && (d = await
|
|
294
|
+
if (o && (d = await ce(e, r, s, c)), l && e.ctx) {
|
|
73
295
|
let t = e.ctx.var.user;
|
|
74
|
-
if (t?.sub && !await
|
|
296
|
+
if (t?.sub && !await se(e, r, t.sub)) try {
|
|
75
297
|
await e.adapters.userOrganizations.create(r, {
|
|
76
298
|
user_id: t.sub,
|
|
77
299
|
organization_id: u.id
|
|
@@ -82,12 +304,12 @@ async function ee(e, t, n) {
|
|
|
82
304
|
}
|
|
83
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}`);
|
|
84
306
|
}
|
|
85
|
-
async function
|
|
307
|
+
async function se(e, t, n) {
|
|
86
308
|
let r = await e.adapters.userRoles.list(t, n, void 0, "");
|
|
87
309
|
for (let n of r) if ((await e.adapters.rolePermissions.list(t, n.id, { per_page: 1e3 })).some((e) => e.permission_name === "admin:organizations")) return !0;
|
|
88
310
|
return !1;
|
|
89
311
|
}
|
|
90
|
-
async function
|
|
312
|
+
async function ce(e, r, i, a) {
|
|
91
313
|
let o = (await e.adapters.roles.list(r, {})).roles.find((e) => e.name === i);
|
|
92
314
|
if (o) return o.id;
|
|
93
315
|
let s = await e.adapters.roles.create(r, {
|
|
@@ -102,7 +324,7 @@ async function ne(e, r, i, a) {
|
|
|
102
324
|
}
|
|
103
325
|
//#endregion
|
|
104
326
|
//#region src/hooks/sync.ts
|
|
105
|
-
function
|
|
327
|
+
function le(e, t, n = () => !0) {
|
|
106
328
|
let { controlPlaneTenantId: r, getChildTenantIds: i, getAdapters: a } = e, o = /* @__PURE__ */ new Map();
|
|
107
329
|
async function s(e, n, r) {
|
|
108
330
|
return (await t(e).list(n, {
|
|
@@ -157,7 +379,7 @@ function D(e, t, n = () => !0) {
|
|
|
157
379
|
}
|
|
158
380
|
};
|
|
159
381
|
}
|
|
160
|
-
function
|
|
382
|
+
function ue(e, t, n = () => !0) {
|
|
161
383
|
let { controlPlaneTenantId: r, getControlPlaneAdapters: i, getAdapters: a } = e;
|
|
162
384
|
return { async afterCreate(e, o) {
|
|
163
385
|
if (o.id !== r) try {
|
|
@@ -181,7 +403,7 @@ function O(e, t, n = () => !0) {
|
|
|
181
403
|
}
|
|
182
404
|
} };
|
|
183
405
|
}
|
|
184
|
-
var
|
|
406
|
+
var de = (e) => ({
|
|
185
407
|
list: async (t, n) => (await e.resourceServers.list(t, n)).resource_servers,
|
|
186
408
|
listPaginated: (t, n) => e.resourceServers.list(t, n),
|
|
187
409
|
get: (t, n) => e.resourceServers.get(t, n),
|
|
@@ -199,7 +421,7 @@ var k = (e) => ({
|
|
|
199
421
|
token_lifetime: e.token_lifetime,
|
|
200
422
|
token_lifetime_for_web: e.token_lifetime_for_web
|
|
201
423
|
})
|
|
202
|
-
}),
|
|
424
|
+
}), fe = (e) => ({
|
|
203
425
|
list: async (t, n) => (await e.roles.list(t, n)).roles,
|
|
204
426
|
listPaginated: (t, n) => e.roles.list(t, n),
|
|
205
427
|
get: (t, n) => e.roles.get(t, n),
|
|
@@ -214,11 +436,11 @@ var k = (e) => ({
|
|
|
214
436
|
description: e.description
|
|
215
437
|
})
|
|
216
438
|
});
|
|
217
|
-
function
|
|
439
|
+
function pe(e) {
|
|
218
440
|
return e.metadata?.sync !== !1;
|
|
219
441
|
}
|
|
220
|
-
function
|
|
221
|
-
let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) =>
|
|
442
|
+
function I(e) {
|
|
443
|
+
let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) => pe(e) ? !n.resourceServers || n.resourceServers(e) : !1, o = (e) => pe(e) ? !n.roles || n.roles(e) : !1, s = r ? le(e, de, a) : void 0, c = i ? le(e, fe, o) : void 0, l = r ? ue(e, de, a) : void 0, d = i ? ue(e, fe, o) : void 0, f = i ? { async afterCreate(t, r) {
|
|
222
444
|
if (r.id !== e.controlPlaneTenantId) {
|
|
223
445
|
await d?.afterCreate?.(t, r);
|
|
224
446
|
try {
|
|
@@ -273,35 +495,35 @@ function re(e) {
|
|
|
273
495
|
}
|
|
274
496
|
//#endregion
|
|
275
497
|
//#region src/routes/tenants.ts
|
|
276
|
-
var
|
|
277
|
-
sub:
|
|
278
|
-
tenant_id:
|
|
279
|
-
org_id:
|
|
280
|
-
scope:
|
|
281
|
-
permissions:
|
|
498
|
+
var me = x.object({
|
|
499
|
+
sub: x.string(),
|
|
500
|
+
tenant_id: x.string().optional(),
|
|
501
|
+
org_id: x.string().optional(),
|
|
502
|
+
scope: x.string().optional(),
|
|
503
|
+
permissions: x.array(x.string()).optional()
|
|
282
504
|
}).passthrough();
|
|
283
|
-
function
|
|
284
|
-
let t =
|
|
505
|
+
function he(e) {
|
|
506
|
+
let t = me.safeParse(e);
|
|
285
507
|
return t.success ? t.data : void 0;
|
|
286
508
|
}
|
|
287
|
-
function
|
|
288
|
-
let t = e.permissions ?? [], n = e.scope ? e.scope.split(" ").filter(Boolean) : [], r = new Set([...t, ...n]);
|
|
509
|
+
function ge(e) {
|
|
510
|
+
let t = e.permissions ?? [], n = e.scope ? e.scope.split(" ").filter(Boolean) : [], r = /* @__PURE__ */ new Set([...t, ...n]);
|
|
289
511
|
return r.has("delete:tenants") || r.has("admin:organizations");
|
|
290
512
|
}
|
|
291
|
-
function
|
|
292
|
-
let n = new
|
|
293
|
-
return n.openapi(
|
|
513
|
+
function L(e, t) {
|
|
514
|
+
let n = new ee();
|
|
515
|
+
return n.openapi(b({
|
|
294
516
|
tags: ["tenants"],
|
|
295
517
|
method: "get",
|
|
296
518
|
path: "/",
|
|
297
519
|
request: { query: r },
|
|
298
520
|
security: [{ Bearer: [] }],
|
|
299
521
|
responses: { 200: {
|
|
300
|
-
content: { "application/json": { schema:
|
|
301
|
-
tenants:
|
|
302
|
-
start:
|
|
303
|
-
limit:
|
|
304
|
-
length:
|
|
522
|
+
content: { "application/json": { schema: x.object({
|
|
523
|
+
tenants: x.array(y),
|
|
524
|
+
start: x.number().optional(),
|
|
525
|
+
limit: x.number().optional(),
|
|
526
|
+
length: x.number().optional()
|
|
305
527
|
}) } },
|
|
306
528
|
description: "List of tenants"
|
|
307
529
|
} }
|
|
@@ -322,7 +544,7 @@ function M(e, t) {
|
|
|
322
544
|
}) : t.json({ tenants: e.tenants });
|
|
323
545
|
}
|
|
324
546
|
let c = e.accessControl?.controlPlaneTenantId ?? t.env.data.multiTenancyConfig?.controlPlaneTenantId;
|
|
325
|
-
if (c && !o?.sub) throw new
|
|
547
|
+
if (c && !o?.sub) throw new S(403, { message: "Access denied: token has no subject" });
|
|
326
548
|
if (c && o?.sub) {
|
|
327
549
|
let e = (await u((e) => t.env.data.userOrganizations.listUserOrganizations(c, o.sub, e), "organizations")).map((e) => e.name);
|
|
328
550
|
if (e.length === 0) return i ? t.json({
|
|
@@ -362,22 +584,22 @@ function M(e, t) {
|
|
|
362
584
|
limit: l.totals?.limit ?? r,
|
|
363
585
|
length: l.tenants.length
|
|
364
586
|
}) : t.json({ tenants: l.tenants });
|
|
365
|
-
}), n.openapi(
|
|
587
|
+
}), n.openapi(b({
|
|
366
588
|
tags: ["tenants"],
|
|
367
589
|
method: "post",
|
|
368
590
|
path: "/",
|
|
369
|
-
request: { body: { content: { "application/json": { schema:
|
|
591
|
+
request: { body: { content: { "application/json": { schema: v } } } },
|
|
370
592
|
security: [{ Bearer: [] }],
|
|
371
593
|
responses: {
|
|
372
594
|
201: {
|
|
373
|
-
content: { "application/json": { schema:
|
|
595
|
+
content: { "application/json": { schema: y } },
|
|
374
596
|
description: "Tenant created"
|
|
375
597
|
},
|
|
376
598
|
400: { description: "Validation error" },
|
|
377
599
|
409: { description: "Tenant with this ID already exists" }
|
|
378
600
|
}
|
|
379
601
|
}), async (e) => {
|
|
380
|
-
if (!e.var.user?.sub) throw new
|
|
602
|
+
if (!e.var.user?.sub) throw new S(401, { message: "Authentication required to create tenants" });
|
|
381
603
|
let n = e.req.valid("json"), r = {
|
|
382
604
|
adapters: e.env.data,
|
|
383
605
|
ctx: e
|
|
@@ -385,11 +607,11 @@ function M(e, t) {
|
|
|
385
607
|
t.tenants?.beforeCreate && (n = await t.tenants.beforeCreate(r, n));
|
|
386
608
|
let i = await e.env.data.tenants.create(n);
|
|
387
609
|
return t.tenants?.afterCreate && await t.tenants.afterCreate(r, i), e.json(i, 201);
|
|
388
|
-
}), n.openapi(
|
|
610
|
+
}), n.openapi(b({
|
|
389
611
|
tags: ["tenants"],
|
|
390
612
|
method: "delete",
|
|
391
613
|
path: "/{id}",
|
|
392
|
-
request: { params:
|
|
614
|
+
request: { params: x.object({ id: x.string() }) },
|
|
393
615
|
security: [{ Bearer: ["delete:tenants"] }],
|
|
394
616
|
responses: {
|
|
395
617
|
204: { description: "Tenant deleted" },
|
|
@@ -399,62 +621,70 @@ function M(e, t) {
|
|
|
399
621
|
}), async (n) => {
|
|
400
622
|
let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ?? n.env.data.multiTenancyConfig?.controlPlaneTenantId;
|
|
401
623
|
if (i) {
|
|
402
|
-
let e =
|
|
403
|
-
if (!e?.sub) throw new
|
|
404
|
-
if (r === i) throw new
|
|
624
|
+
let e = he(n.var.user);
|
|
625
|
+
if (!e?.sub) throw new S(401, { message: "Authentication required" });
|
|
626
|
+
if (r === i) throw new S(403, { message: "Cannot delete the control plane" });
|
|
405
627
|
let t = n.var.org_name, a = r.toLowerCase(), o = !!t && t.toLowerCase() === a;
|
|
406
628
|
if (!o) {
|
|
407
629
|
let r = !!(e.org_id ?? n.var.organization_id ?? t), a = !e.tenant_id || e.tenant_id === i;
|
|
408
|
-
!r && a &&
|
|
630
|
+
!r && a && ge(e) && (o = !0);
|
|
409
631
|
}
|
|
410
|
-
if (o ||= (await u((t) => n.env.data.userOrganizations.listUserOrganizations(i, e.sub, t), "organizations")).some((e) => e.name?.toLowerCase() === a), !o) throw new
|
|
632
|
+
if (o ||= (await u((t) => n.env.data.userOrganizations.listUserOrganizations(i, e.sub, t), "organizations")).some((e) => e.name?.toLowerCase() === a), !o) throw new S(403, { message: "Access denied to this tenant" });
|
|
411
633
|
}
|
|
412
|
-
if (!await n.env.data.tenants.get(r)) throw new
|
|
634
|
+
if (!await n.env.data.tenants.get(r)) throw new S(404, { message: "Tenant not found" });
|
|
413
635
|
let a = {
|
|
414
636
|
adapters: n.env.data,
|
|
415
637
|
ctx: n
|
|
416
638
|
};
|
|
417
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);
|
|
418
|
-
}), n.openapi(
|
|
640
|
+
}), n.openapi(b({
|
|
419
641
|
tags: ["tenants", "settings"],
|
|
420
642
|
method: "get",
|
|
421
643
|
path: "/settings",
|
|
422
|
-
request: { headers:
|
|
644
|
+
request: { headers: x.object({ "tenant-id": x.string().optional() }) },
|
|
423
645
|
security: [{ Bearer: ["read:tenants"] }],
|
|
424
646
|
responses: { 200: {
|
|
425
|
-
content: { "application/json": { schema:
|
|
647
|
+
content: { "application/json": { schema: y } },
|
|
426
648
|
description: "Current tenant settings"
|
|
427
649
|
} }
|
|
428
650
|
}), async (e) => {
|
|
429
651
|
let t = await e.env.data.tenants.get(e.var.tenant_id);
|
|
430
|
-
if (!t) throw new
|
|
652
|
+
if (!t) throw new S(404, { message: "Tenant not found" });
|
|
431
653
|
return e.json(t);
|
|
432
|
-
}), n.openapi(
|
|
654
|
+
}), n.openapi(b({
|
|
433
655
|
tags: ["tenants", "settings"],
|
|
434
656
|
method: "patch",
|
|
435
657
|
path: "/settings",
|
|
436
658
|
request: {
|
|
437
|
-
headers:
|
|
438
|
-
body: { content: { "application/json": { schema:
|
|
659
|
+
headers: x.object({ "tenant-id": x.string().optional() }),
|
|
660
|
+
body: { content: { "application/json": { schema: x.object(v.shape).partial() } } }
|
|
439
661
|
},
|
|
440
662
|
security: [{ Bearer: ["update:tenants"] }],
|
|
441
663
|
responses: { 200: {
|
|
442
|
-
content: { "application/json": { schema:
|
|
664
|
+
content: { "application/json": { schema: y } },
|
|
443
665
|
description: "Updated tenant settings"
|
|
444
666
|
} }
|
|
445
667
|
}), async (e) => {
|
|
446
668
|
let { id: t, ...n } = e.req.valid("json"), r = await e.env.data.tenants.get(e.var.tenant_id);
|
|
447
|
-
if (!r) throw new
|
|
669
|
+
if (!r) throw new S(404, { message: "Tenant not found" });
|
|
670
|
+
if ("default_client_id" in n) {
|
|
671
|
+
let t = n.default_client_id;
|
|
672
|
+
if (typeof t == "string" && t.length > 0) {
|
|
673
|
+
let n = await e.env.data.clients.get(e.var.tenant_id, t);
|
|
674
|
+
if (!n) throw new S(400, { message: `Client with id '${t}' not found` });
|
|
675
|
+
if (!p(n)) throw new S(400, { message: `Client '${t}' is not an interactive client and cannot be used as the default client` });
|
|
676
|
+
}
|
|
677
|
+
}
|
|
448
678
|
let i = c(r, n);
|
|
449
679
|
await e.env.data.tenants.update(e.var.tenant_id, i);
|
|
450
680
|
let a = await e.env.data.tenants.get(e.var.tenant_id);
|
|
451
|
-
if (!a) throw new
|
|
681
|
+
if (!a) throw new S(500, { message: "Failed to retrieve updated tenant" });
|
|
452
682
|
return e.json(a);
|
|
453
683
|
}), n;
|
|
454
684
|
}
|
|
455
685
|
//#endregion
|
|
456
686
|
//#region src/middleware/protect-synced.ts
|
|
457
|
-
function
|
|
687
|
+
function _e(e) {
|
|
458
688
|
for (let { pattern: t, type: n } of [
|
|
459
689
|
{
|
|
460
690
|
pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
|
|
@@ -477,7 +707,7 @@ function se(e) {
|
|
|
477
707
|
}
|
|
478
708
|
return null;
|
|
479
709
|
}
|
|
480
|
-
async function
|
|
710
|
+
async function ve(e, t, n) {
|
|
481
711
|
try {
|
|
482
712
|
switch (n.type) {
|
|
483
713
|
case "resource_server": return (await e.resourceServers.get(t, n.id))?.is_system === !0;
|
|
@@ -489,31 +719,31 @@ async function ce(e, t, n) {
|
|
|
489
719
|
return !1;
|
|
490
720
|
}
|
|
491
721
|
}
|
|
492
|
-
function
|
|
722
|
+
function ye(e) {
|
|
493
723
|
return {
|
|
494
724
|
resource_server: "resource server",
|
|
495
725
|
role: "role",
|
|
496
726
|
connection: "connection"
|
|
497
727
|
}[e];
|
|
498
728
|
}
|
|
499
|
-
function
|
|
729
|
+
function R() {
|
|
500
730
|
return async (e, t) => {
|
|
501
731
|
if (![
|
|
502
732
|
"PATCH",
|
|
503
733
|
"PUT",
|
|
504
734
|
"DELETE"
|
|
505
735
|
].includes(e.req.method)) return t();
|
|
506
|
-
let n =
|
|
736
|
+
let n = _e(e.req.path);
|
|
507
737
|
if (!n) return t();
|
|
508
738
|
let r = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
|
|
509
739
|
if (!r) return t();
|
|
510
|
-
if (await
|
|
740
|
+
if (await ve(e.env.data, r, n)) throw new S(403, { message: `This ${ye(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.` });
|
|
511
741
|
return t();
|
|
512
742
|
};
|
|
513
743
|
}
|
|
514
744
|
//#endregion
|
|
515
745
|
//#region src/middleware/settings-inheritance.ts
|
|
516
|
-
function
|
|
746
|
+
function z(e, t) {
|
|
517
747
|
let n = t.find((t) => t.strategy === e.strategy);
|
|
518
748
|
if (!n?.options) return e;
|
|
519
749
|
let r = s.passthrough().parse({
|
|
@@ -525,11 +755,11 @@ function P(e, t) {
|
|
|
525
755
|
...e.options
|
|
526
756
|
}), r;
|
|
527
757
|
}
|
|
528
|
-
function
|
|
758
|
+
function B(e, t) {
|
|
529
759
|
let n = [...t || [], ...e || []];
|
|
530
760
|
return [...new Set(n)];
|
|
531
761
|
}
|
|
532
|
-
function
|
|
762
|
+
function be(e, t) {
|
|
533
763
|
if (!t?.length) return e || [];
|
|
534
764
|
if (!e?.length) return t;
|
|
535
765
|
let n = /* @__PURE__ */ new Map();
|
|
@@ -537,22 +767,22 @@ function ue(e, t) {
|
|
|
537
767
|
for (let t of e) n.set(t.value, t);
|
|
538
768
|
return Array.from(n.values());
|
|
539
769
|
}
|
|
540
|
-
function
|
|
770
|
+
function V(e, t) {
|
|
541
771
|
return t ? {
|
|
542
772
|
...e,
|
|
543
|
-
scopes:
|
|
773
|
+
scopes: be(e.scopes, t.scopes)
|
|
544
774
|
} : e;
|
|
545
775
|
}
|
|
546
|
-
function
|
|
776
|
+
function xe(e, t) {
|
|
547
777
|
return t ? {
|
|
548
778
|
...e,
|
|
549
|
-
callbacks:
|
|
550
|
-
web_origins:
|
|
551
|
-
allowed_logout_urls:
|
|
552
|
-
allowed_origins:
|
|
779
|
+
callbacks: B(e.callbacks, t.callbacks),
|
|
780
|
+
web_origins: B(e.web_origins, t.web_origins),
|
|
781
|
+
allowed_logout_urls: B(e.allowed_logout_urls, t.allowed_logout_urls),
|
|
782
|
+
allowed_origins: B(e.allowed_origins, t.allowed_origins)
|
|
553
783
|
} : e;
|
|
554
784
|
}
|
|
555
|
-
function
|
|
785
|
+
function H(e) {
|
|
556
786
|
let { controlPlaneTenantId: t, controlPlaneClientId: n, resolveControlPlane: r } = e;
|
|
557
787
|
if (r) return async (e) => r({ tenant_id: e });
|
|
558
788
|
if (!t) return async () => void 0;
|
|
@@ -562,14 +792,14 @@ function L(e) {
|
|
|
562
792
|
};
|
|
563
793
|
return async () => i;
|
|
564
794
|
}
|
|
565
|
-
function
|
|
795
|
+
function U(e, t) {
|
|
566
796
|
return {
|
|
567
797
|
...e.resourceServers,
|
|
568
798
|
get: async (n, r) => {
|
|
569
799
|
let i = await e.resourceServers.get(n, r);
|
|
570
800
|
if (!i) return i;
|
|
571
801
|
let a = await t(n);
|
|
572
|
-
return !a || n === a.tenantId || !i.is_system ? i :
|
|
802
|
+
return !a || n === a.tenantId || !i.is_system ? i : V(i, await e.resourceServers.get(a.tenantId, r));
|
|
573
803
|
},
|
|
574
804
|
list: async (n, r) => {
|
|
575
805
|
let i = await e.resourceServers.list(n, r), a = await t(n);
|
|
@@ -581,7 +811,7 @@ function R(e, t) {
|
|
|
581
811
|
let n = await e.resourceServers.get(o, t);
|
|
582
812
|
n && c.set(t, n);
|
|
583
813
|
}));
|
|
584
|
-
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 ? V(e, c.get(e.id) ?? null) : e);
|
|
585
815
|
return {
|
|
586
816
|
...i,
|
|
587
817
|
resource_servers: l
|
|
@@ -589,18 +819,18 @@ function R(e, t) {
|
|
|
589
819
|
}
|
|
590
820
|
};
|
|
591
821
|
}
|
|
592
|
-
function
|
|
593
|
-
let n =
|
|
822
|
+
function W(e, t) {
|
|
823
|
+
let n = H({
|
|
594
824
|
controlPlaneTenantId: t.controlPlaneTenantId,
|
|
595
825
|
resolveControlPlane: t.resolveControlPlane
|
|
596
826
|
});
|
|
597
827
|
return {
|
|
598
828
|
...e,
|
|
599
|
-
resourceServers:
|
|
829
|
+
resourceServers: U(e, n)
|
|
600
830
|
};
|
|
601
831
|
}
|
|
602
|
-
function
|
|
603
|
-
let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i } = t, a =
|
|
832
|
+
function G(e, t) {
|
|
833
|
+
let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i } = t, a = H({
|
|
604
834
|
controlPlaneTenantId: n,
|
|
605
835
|
controlPlaneClientId: r,
|
|
606
836
|
resolveControlPlane: i
|
|
@@ -618,12 +848,12 @@ function B(e, t) {
|
|
|
618
848
|
let r = await e.connections.get(t, n);
|
|
619
849
|
if (!r) return r;
|
|
620
850
|
let i = await a(t);
|
|
621
|
-
return !i || t === i.tenantId ? r :
|
|
851
|
+
return !i || t === i.tenantId ? r : z(r, (await e.connections.list(i.tenantId)).connections || []);
|
|
622
852
|
},
|
|
623
853
|
list: async (t, n) => {
|
|
624
854
|
let r = await e.connections.list(t, n), i = await a(t);
|
|
625
855
|
if (!i || t === i.tenantId) return r;
|
|
626
|
-
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) => z(e, o.connections || []));
|
|
627
857
|
return {
|
|
628
858
|
...r,
|
|
629
859
|
connections: s
|
|
@@ -638,7 +868,7 @@ function B(e, t) {
|
|
|
638
868
|
let i = await a(t);
|
|
639
869
|
if (!i || t === i.tenantId) return r;
|
|
640
870
|
let o = await e.connections.list(i.tenantId);
|
|
641
|
-
return r.map((e) =>
|
|
871
|
+
return r.map((e) => z(e, o.connections || []));
|
|
642
872
|
}
|
|
643
873
|
},
|
|
644
874
|
emailProviders: {
|
|
@@ -650,22 +880,22 @@ function B(e, t) {
|
|
|
650
880
|
return !r || t === r.tenantId ? null : e.emailProviders.get(r.tenantId);
|
|
651
881
|
}
|
|
652
882
|
},
|
|
653
|
-
resourceServers:
|
|
654
|
-
hooks:
|
|
883
|
+
resourceServers: U(e, a),
|
|
884
|
+
hooks: Se(e, a)
|
|
655
885
|
};
|
|
656
886
|
}
|
|
657
|
-
function
|
|
887
|
+
function K(e) {
|
|
658
888
|
if (!e || typeof e != "object") return !1;
|
|
659
889
|
let t = e.metadata;
|
|
660
890
|
return !t || typeof t != "object" ? !1 : t.inheritable === !0;
|
|
661
891
|
}
|
|
662
|
-
function
|
|
892
|
+
function Se(e, t) {
|
|
663
893
|
return {
|
|
664
894
|
...e.hooks,
|
|
665
895
|
list: async (n, r) => {
|
|
666
896
|
let i = await e.hooks.list(n, r), a = await t(n);
|
|
667
897
|
if (!a || n === a.tenantId) return i;
|
|
668
|
-
let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(
|
|
898
|
+
let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(K);
|
|
669
899
|
if (o.length === 0) return i;
|
|
670
900
|
let s = new Set((i.hooks || []).map((e) => e.hook_id)), c = o.filter((e) => !s.has(e.hook_id));
|
|
671
901
|
return {
|
|
@@ -680,31 +910,31 @@ function fe(e, t) {
|
|
|
680
910
|
let a = await t(n);
|
|
681
911
|
if (!a || n === a.tenantId) return i;
|
|
682
912
|
let o = await e.hooks.get(a.tenantId, r);
|
|
683
|
-
return o &&
|
|
913
|
+
return o && K(o) ? o : null;
|
|
684
914
|
}
|
|
685
915
|
};
|
|
686
916
|
}
|
|
687
|
-
function
|
|
688
|
-
return
|
|
917
|
+
function q(e, t) {
|
|
918
|
+
return G(e, t);
|
|
689
919
|
}
|
|
690
920
|
//#endregion
|
|
691
921
|
//#region src/middleware/index.ts
|
|
692
|
-
function
|
|
922
|
+
function Ce(e) {
|
|
693
923
|
return async (t, n) => {
|
|
694
924
|
let r = t.var.user;
|
|
695
925
|
return r?.tenant_id === e && r.org_name && t.set("tenant_id", r.org_name), n();
|
|
696
926
|
};
|
|
697
927
|
}
|
|
698
|
-
function
|
|
928
|
+
function we(e) {
|
|
699
929
|
return async (n, r) => {
|
|
700
930
|
if (!e.accessControl) return r();
|
|
701
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);
|
|
702
|
-
if (!c && s && u && (n.set("tenant_id", s), c = s), !c) throw new
|
|
703
|
-
if (!
|
|
932
|
+
if (!c && s && u && (n.set("tenant_id", s), c = s), !c) throw new S(400, { message: "Tenant ID not found in request" });
|
|
933
|
+
if (!w(o, c, i, a)) throw new S(403, { message: `Access denied to tenant ${c}` });
|
|
704
934
|
return r();
|
|
705
935
|
};
|
|
706
936
|
}
|
|
707
|
-
function
|
|
937
|
+
function Te(e) {
|
|
708
938
|
return async (t, n) => {
|
|
709
939
|
if (!e.subdomainRouting) return n();
|
|
710
940
|
let { baseDomain: r, reservedSubdomains: i = [], resolveSubdomain: a } = e.subdomainRouting, o = t.req.header("x-forwarded-host") || t.req.header("host") || "", s = null;
|
|
@@ -719,43 +949,43 @@ function G(e) {
|
|
|
719
949
|
let n = await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId, s);
|
|
720
950
|
n && (c = n.id);
|
|
721
951
|
} catch {}
|
|
722
|
-
if (!c) throw new
|
|
952
|
+
if (!c) throw new S(404, { message: `Tenant not found for subdomain: ${s}` });
|
|
723
953
|
return t.set("tenant_id", c), n();
|
|
724
954
|
};
|
|
725
955
|
}
|
|
726
|
-
function
|
|
956
|
+
function Ee(e) {
|
|
727
957
|
return async (t, n) => {
|
|
728
958
|
if (!e.databaseIsolation) return n();
|
|
729
959
|
let r = t.var.tenant_id;
|
|
730
|
-
if (!r) throw new
|
|
960
|
+
if (!r) throw new S(400, { message: "Tenant ID not found in request" });
|
|
731
961
|
try {
|
|
732
962
|
let n = await e.databaseIsolation.getAdapters(r);
|
|
733
963
|
t.env.data = n;
|
|
734
964
|
} catch (e) {
|
|
735
|
-
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 S(500, { message: "Failed to resolve tenant database" });
|
|
736
966
|
}
|
|
737
967
|
return n();
|
|
738
968
|
};
|
|
739
969
|
}
|
|
740
|
-
function
|
|
741
|
-
let t =
|
|
970
|
+
function J(e) {
|
|
971
|
+
let t = Te(e), n = we(e), r = Ee(e);
|
|
742
972
|
return async (e, i) => (await t(e, async () => {}), await n(e, async () => {}), await r(e, async () => {}), i());
|
|
743
973
|
}
|
|
744
974
|
//#endregion
|
|
745
975
|
//#region src/init.ts
|
|
746
|
-
function
|
|
976
|
+
function De(e) {
|
|
747
977
|
let { dataAdapter: t, controlPlane: n, controlPlane: { tenantId: r = "control_plane", clientId: i } = {}, resolveControlPlane: a, sync: o = {
|
|
748
978
|
resourceServers: !0,
|
|
749
979
|
roles: !0
|
|
750
980
|
}, defaultPermissions: s = ["tenant:admin"], requireOrganizationMatch: c = !1, managementApiExtensions: l = [], entityHooks: d, getChildTenantIds: p, getAdapters: m, ...h } = e;
|
|
751
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.");
|
|
752
982
|
let g = t, _ = t;
|
|
753
|
-
n && (g =
|
|
983
|
+
n && (g = q(t, {
|
|
754
984
|
controlPlaneTenantId: r,
|
|
755
985
|
controlPlaneClientId: i,
|
|
756
986
|
resolveControlPlane: a
|
|
757
987
|
}), _ = {
|
|
758
|
-
...
|
|
988
|
+
...W(t, {
|
|
759
989
|
controlPlaneTenantId: r,
|
|
760
990
|
resolveControlPlane: a
|
|
761
991
|
}),
|
|
@@ -765,13 +995,36 @@ function pe(e) {
|
|
|
765
995
|
resolveControlPlane: a
|
|
766
996
|
}
|
|
767
997
|
});
|
|
768
|
-
let v =
|
|
998
|
+
let v = h.tenantOperationExecutor;
|
|
999
|
+
if (!v && t.tenantOperations && t.tenantOperationEvents && h.tenantUpgrade) {
|
|
1000
|
+
let e = {
|
|
1001
|
+
tenantOperations: t.tenantOperations,
|
|
1002
|
+
tenantOperationEvents: t.tenantOperationEvents
|
|
1003
|
+
}, n = h.tenantUpgrade, r = j({
|
|
1004
|
+
stores: e,
|
|
1005
|
+
definitions: { upgrade: (e) => [{
|
|
1006
|
+
name: "upgrade",
|
|
1007
|
+
async run() {
|
|
1008
|
+
if (!e.tenant_id) throw Error("upgrade operations require a tenant_id");
|
|
1009
|
+
await n(e.tenant_id);
|
|
1010
|
+
}
|
|
1011
|
+
}] }
|
|
1012
|
+
});
|
|
1013
|
+
v = {
|
|
1014
|
+
engine: r.engine,
|
|
1015
|
+
enqueue: (t) => N(e, r, {
|
|
1016
|
+
...t,
|
|
1017
|
+
tenant_id: t.tenant_id
|
|
1018
|
+
})
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
let y = o !== !1, ee = y ? {
|
|
769
1022
|
resourceServers: o.resourceServers ?? !0,
|
|
770
1023
|
roles: o.roles ?? !0
|
|
771
1024
|
} : {
|
|
772
1025
|
resourceServers: !1,
|
|
773
1026
|
roles: !1
|
|
774
|
-
}, { entityHooks: b, tenantHooks: x } =
|
|
1027
|
+
}, { entityHooks: b, tenantHooks: x } = I({
|
|
775
1028
|
controlPlaneTenantId: r,
|
|
776
1029
|
getChildTenantIds: p ?? (async () => (await u((e) => g.tenants.list(e), "tenants", {
|
|
777
1030
|
cursorField: "id",
|
|
@@ -779,18 +1032,18 @@ function pe(e) {
|
|
|
779
1032
|
})).filter((e) => e.id !== r).map((e) => e.id)),
|
|
780
1033
|
getAdapters: m ?? (async () => g),
|
|
781
1034
|
getControlPlaneAdapters: async () => g,
|
|
782
|
-
sync:
|
|
1035
|
+
sync: ee
|
|
783
1036
|
}), S = {
|
|
784
1037
|
resourceServers: [b.resourceServers, ...d?.resourceServers ?? []],
|
|
785
1038
|
roles: [b.roles, ...d?.roles ?? []],
|
|
786
1039
|
connections: d?.connections ?? [],
|
|
787
1040
|
tenants: d?.tenants ?? [],
|
|
788
1041
|
rolePermissions: d?.rolePermissions ?? []
|
|
789
|
-
}, C =
|
|
1042
|
+
}, C = F({ accessControl: {
|
|
790
1043
|
controlPlaneTenantId: r,
|
|
791
1044
|
requireOrganizationMatch: c,
|
|
792
1045
|
defaultPermissions: s
|
|
793
|
-
} }), w =
|
|
1046
|
+
} }), w = L({ accessControl: {
|
|
794
1047
|
controlPlaneTenantId: r,
|
|
795
1048
|
requireOrganizationMatch: c,
|
|
796
1049
|
defaultPermissions: s
|
|
@@ -808,20 +1061,21 @@ function pe(e) {
|
|
|
808
1061
|
dataAdapter: g,
|
|
809
1062
|
managementDataAdapter: _,
|
|
810
1063
|
...h,
|
|
1064
|
+
tenantOperationExecutor: v,
|
|
811
1065
|
entityHooks: S,
|
|
812
1066
|
managementApiExtensions: [...l, {
|
|
813
1067
|
path: "/tenants",
|
|
814
1068
|
router: w
|
|
815
1069
|
}]
|
|
816
1070
|
});
|
|
817
|
-
return T.use("/api/v2/*",
|
|
1071
|
+
return T.use("/api/v2/*", Ce(r)), y && T.use("/api/v2/*", R()), {
|
|
818
1072
|
app: T,
|
|
819
1073
|
controlPlaneTenantId: r
|
|
820
1074
|
};
|
|
821
1075
|
}
|
|
822
1076
|
//#endregion
|
|
823
1077
|
//#region src/rollout/defaults-projection.ts
|
|
824
|
-
function
|
|
1078
|
+
function Y(e = {}) {
|
|
825
1079
|
return {
|
|
826
1080
|
connections: e.connections ?? !0,
|
|
827
1081
|
resourceServers: e.resourceServers ?? !0,
|
|
@@ -831,28 +1085,28 @@ function J(e = {}) {
|
|
|
831
1085
|
promptSettings: e.promptSettings ?? !0
|
|
832
1086
|
};
|
|
833
1087
|
}
|
|
834
|
-
function
|
|
1088
|
+
function X() {
|
|
835
1089
|
return {
|
|
836
1090
|
upserted: 0,
|
|
837
1091
|
errors: []
|
|
838
1092
|
};
|
|
839
1093
|
}
|
|
840
|
-
function
|
|
1094
|
+
function Oe(e) {
|
|
841
1095
|
return {
|
|
842
1096
|
tenantId: e,
|
|
843
|
-
connections:
|
|
844
|
-
resourceServers:
|
|
845
|
-
hooks:
|
|
846
|
-
emailProvider:
|
|
847
|
-
branding:
|
|
848
|
-
promptSettings:
|
|
1097
|
+
connections: X(),
|
|
1098
|
+
resourceServers: X(),
|
|
1099
|
+
hooks: X(),
|
|
1100
|
+
emailProvider: X(),
|
|
1101
|
+
branding: X(),
|
|
1102
|
+
promptSettings: X()
|
|
849
1103
|
};
|
|
850
1104
|
}
|
|
851
|
-
function
|
|
1105
|
+
function ke(e) {
|
|
852
1106
|
let t = e.metadata;
|
|
853
1107
|
return !!(t && t.inheritable === !0);
|
|
854
1108
|
}
|
|
855
|
-
async function
|
|
1109
|
+
async function Z(e, t, n, r) {
|
|
856
1110
|
try {
|
|
857
1111
|
await r();
|
|
858
1112
|
} catch (r) {
|
|
@@ -861,7 +1115,7 @@ async function X(e, t, n, r) {
|
|
|
861
1115
|
e.errors.push(i);
|
|
862
1116
|
}
|
|
863
1117
|
}
|
|
864
|
-
async function
|
|
1118
|
+
async function Ae(e, t, n) {
|
|
865
1119
|
return {
|
|
866
1120
|
connections: n.connections ? await u((n) => e.connections.list(t, n), "connections", {
|
|
867
1121
|
cursorField: "id",
|
|
@@ -880,47 +1134,47 @@ async function ge(e, t, n) {
|
|
|
880
1134
|
promptSettings: n.promptSettings ? await e.promptSettings.get(t) ?? null : null
|
|
881
1135
|
};
|
|
882
1136
|
}
|
|
883
|
-
async function
|
|
1137
|
+
async function je(e, t, n, r, i, o) {
|
|
884
1138
|
if (r.connections) for (let r of e.connections) {
|
|
885
1139
|
let e = r.id;
|
|
886
|
-
e && await
|
|
1140
|
+
e && await Z(o.connections, `connection ${e}`, i, async () => {
|
|
887
1141
|
let i = a.parse(r);
|
|
888
1142
|
await t.connections.get(n, e) ? await t.connections.update(n, e, i) : await t.connections.create(n, i), o.connections.upserted += 1;
|
|
889
1143
|
});
|
|
890
1144
|
}
|
|
891
|
-
if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await
|
|
892
|
-
let e =
|
|
1145
|
+
if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await Z(o.resourceServers, `resource_server ${r.id}`, i, async () => {
|
|
1146
|
+
let e = _.parse(r);
|
|
893
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;
|
|
894
1148
|
});
|
|
895
|
-
if (r.hooks) for (let r of e.hooks) !
|
|
1149
|
+
if (r.hooks) for (let r of e.hooks) !ke(r) || !r.hook_id || await Z(o.hooks, `hook ${r.hook_id}`, i, async () => {
|
|
896
1150
|
let e = d.parse(r);
|
|
897
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;
|
|
898
1152
|
});
|
|
899
|
-
r.emailProvider && e.emailProvider && await
|
|
1153
|
+
r.emailProvider && e.emailProvider && await Z(o.emailProvider, "email_provider", i, async () => {
|
|
900
1154
|
let r = e.emailProvider;
|
|
901
1155
|
await t.emailProviders.get(n) ? await t.emailProviders.update(n, r) : await t.emailProviders.create(n, r), o.emailProvider.upserted += 1;
|
|
902
|
-
}), r.branding && e.branding && await
|
|
1156
|
+
}), r.branding && e.branding && await Z(o.branding, "branding", i, async () => {
|
|
903
1157
|
await t.branding.set(n, e.branding), o.branding.upserted += 1;
|
|
904
|
-
}), r.promptSettings && e.promptSettings && await
|
|
1158
|
+
}), r.promptSettings && e.promptSettings && await Z(o.promptSettings, "prompt_settings", i, async () => {
|
|
905
1159
|
await t.promptSettings.set(n, e.promptSettings), o.promptSettings.upserted += 1;
|
|
906
1160
|
});
|
|
907
1161
|
}
|
|
908
|
-
async function
|
|
909
|
-
let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s =
|
|
910
|
-
return await
|
|
1162
|
+
async function Q(e, t) {
|
|
1163
|
+
let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s = Y(a), c = await Ae(await r(), n, s), l = await i(t), u = Oe(t);
|
|
1164
|
+
return await je(c, l, n, s, o, u), u;
|
|
911
1165
|
}
|
|
912
1166
|
//#endregion
|
|
913
1167
|
//#region src/rollout/payload.ts
|
|
914
|
-
function
|
|
1168
|
+
function Me(e) {
|
|
915
1169
|
let { pkcs7: t, tenant_id: n, ...r } = e;
|
|
916
1170
|
return r;
|
|
917
1171
|
}
|
|
918
|
-
async function
|
|
919
|
-
let i =
|
|
1172
|
+
async function Ne(e, t, n = {}, r) {
|
|
1173
|
+
let i = Y(n), a = n.signingKeys ?? !0, o = n.tenants ?? !0, s = await Ae(e, t, i), c = a ? (await m(e.keys)).map(Me) : [], l = o ? await Pe(e, t, r) : [];
|
|
920
1174
|
return {
|
|
921
1175
|
connections: s.connections,
|
|
922
1176
|
resourceServers: s.resourceServers.filter((e) => e.is_system),
|
|
923
|
-
hooks: s.hooks.filter(
|
|
1177
|
+
hooks: s.hooks.filter(ke),
|
|
924
1178
|
emailProvider: s.emailProvider,
|
|
925
1179
|
branding: s.branding,
|
|
926
1180
|
promptSettings: s.promptSettings,
|
|
@@ -928,7 +1182,7 @@ async function ye(e, t, n = {}, r) {
|
|
|
928
1182
|
tenants: l
|
|
929
1183
|
};
|
|
930
1184
|
}
|
|
931
|
-
async function
|
|
1185
|
+
async function Pe(e, t, n) {
|
|
932
1186
|
let r = n && n !== t ? [t, n] : [t], i = [];
|
|
933
1187
|
for (let t of r) {
|
|
934
1188
|
let n = await e.tenants.get(t);
|
|
@@ -939,19 +1193,19 @@ async function be(e, t, n) {
|
|
|
939
1193
|
}
|
|
940
1194
|
return i;
|
|
941
1195
|
}
|
|
942
|
-
async function
|
|
943
|
-
let r =
|
|
1196
|
+
async function Fe(e, t, n) {
|
|
1197
|
+
let r = X();
|
|
944
1198
|
if (e.length === 0) return r;
|
|
945
|
-
let i = await
|
|
946
|
-
for (let i of e) await
|
|
947
|
-
let e =
|
|
1199
|
+
let i = await m(t.keys), a = new Set(i.map((e) => e.kid));
|
|
1200
|
+
for (let i of e) await Z(r, `signing_key ${i.kid}`, n, async () => {
|
|
1201
|
+
let e = Me(i);
|
|
948
1202
|
a.has(e.kid) || (await t.keys.create(e), a.add(e.kid), r.upserted += 1);
|
|
949
1203
|
});
|
|
950
1204
|
return r;
|
|
951
1205
|
}
|
|
952
|
-
async function
|
|
953
|
-
let r =
|
|
954
|
-
for (let i of e) await
|
|
1206
|
+
async function Ie(e, t, n) {
|
|
1207
|
+
let r = X();
|
|
1208
|
+
for (let i of e) await Z(r, `tenant ${i.id}`, n, async () => {
|
|
955
1209
|
await t.tenants.get(i.id) || (await t.tenants.create({
|
|
956
1210
|
id: i.id,
|
|
957
1211
|
friendly_name: i.friendly_name
|
|
@@ -959,17 +1213,17 @@ async function Se(e, t, n) {
|
|
|
959
1213
|
});
|
|
960
1214
|
return r;
|
|
961
1215
|
}
|
|
962
|
-
async function
|
|
963
|
-
let a = r.continueOnError ?? !1, o =
|
|
1216
|
+
async function Le(e, t, n, r = {}) {
|
|
1217
|
+
let a = r.continueOnError ?? !1, o = Y(r.entities), s = r.entities?.signingKeys ?? !0, c = r.entities?.tenants ?? !0, u = {
|
|
964
1218
|
connections: e.connections,
|
|
965
1219
|
resourceServers: e.resourceServers,
|
|
966
1220
|
hooks: e.hooks,
|
|
967
1221
|
emailProvider: e.emailProvider ? l.parse(e.emailProvider) : null,
|
|
968
1222
|
branding: e.branding ? i.parse(e.branding) : null,
|
|
969
|
-
promptSettings: e.promptSettings ?
|
|
970
|
-
}, d = c ? await
|
|
971
|
-
await
|
|
972
|
-
let p = s ? await
|
|
1223
|
+
promptSettings: e.promptSettings ? h.parse(e.promptSettings) : null
|
|
1224
|
+
}, d = c ? await Ie(e.tenants ?? [], t, a) : X(), f = Oe(n);
|
|
1225
|
+
await je(u, t, n, o, a, f);
|
|
1226
|
+
let p = s ? await Fe(e.signingKeys, t, a) : X();
|
|
973
1227
|
return {
|
|
974
1228
|
...f,
|
|
975
1229
|
signingKeys: p,
|
|
@@ -978,27 +1232,27 @@ async function Ce(e, t, n, r = {}) {
|
|
|
978
1232
|
}
|
|
979
1233
|
//#endregion
|
|
980
1234
|
//#region src/rollout/index.ts
|
|
981
|
-
function
|
|
1235
|
+
function Re(e) {
|
|
982
1236
|
return {
|
|
983
|
-
syncDefaults: (t) =>
|
|
1237
|
+
syncDefaults: (t) => Q(e, t),
|
|
984
1238
|
syncDefaultsToTenants: async (t) => {
|
|
985
1239
|
let n = [];
|
|
986
|
-
for (let r of t) n.push(await
|
|
1240
|
+
for (let r of t) n.push(await Q(e, r));
|
|
987
1241
|
return n;
|
|
988
1242
|
}
|
|
989
1243
|
};
|
|
990
1244
|
}
|
|
991
1245
|
//#endregion
|
|
992
1246
|
//#region src/plugin.ts
|
|
993
|
-
function
|
|
994
|
-
let t =
|
|
1247
|
+
function ze(e) {
|
|
1248
|
+
let t = $(e);
|
|
995
1249
|
return {
|
|
996
1250
|
name: "multi-tenancy",
|
|
997
|
-
middleware:
|
|
1251
|
+
middleware: J(e),
|
|
998
1252
|
hooks: t,
|
|
999
1253
|
routes: [{
|
|
1000
1254
|
path: "/management",
|
|
1001
|
-
handler:
|
|
1255
|
+
handler: L(e, t)
|
|
1002
1256
|
}],
|
|
1003
1257
|
onRegister: async () => {
|
|
1004
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");
|
|
@@ -1007,29 +1261,29 @@ function Te(e) {
|
|
|
1007
1261
|
}
|
|
1008
1262
|
//#endregion
|
|
1009
1263
|
//#region src/index.ts
|
|
1010
|
-
function
|
|
1011
|
-
let t = e.accessControl ?
|
|
1264
|
+
function $(e) {
|
|
1265
|
+
let t = e.accessControl ? C(e.accessControl) : {}, n = e.databaseIsolation ? T(e.databaseIsolation) : {}, r = F(e);
|
|
1012
1266
|
return {
|
|
1013
1267
|
...t,
|
|
1014
1268
|
...n,
|
|
1015
1269
|
tenants: r
|
|
1016
1270
|
};
|
|
1017
1271
|
}
|
|
1018
|
-
function
|
|
1019
|
-
let n = new e(), r =
|
|
1020
|
-
return n.route("/tenants",
|
|
1272
|
+
function Be(t) {
|
|
1273
|
+
let n = new e(), r = $(t);
|
|
1274
|
+
return n.route("/tenants", L(t, r)), n;
|
|
1021
1275
|
}
|
|
1022
|
-
function
|
|
1276
|
+
function Ve(e) {
|
|
1023
1277
|
return {
|
|
1024
|
-
hooks:
|
|
1025
|
-
middleware:
|
|
1026
|
-
app:
|
|
1278
|
+
hooks: $(e),
|
|
1279
|
+
middleware: J(e),
|
|
1280
|
+
app: Be(e),
|
|
1027
1281
|
config: e,
|
|
1028
|
-
wrapAdapters: (t, n) =>
|
|
1282
|
+
wrapAdapters: (t, n) => q(t, {
|
|
1029
1283
|
controlPlaneTenantId: e.accessControl?.controlPlaneTenantId,
|
|
1030
1284
|
controlPlaneClientId: n?.controlPlaneClientId
|
|
1031
1285
|
})
|
|
1032
1286
|
};
|
|
1033
1287
|
}
|
|
1034
1288
|
//#endregion
|
|
1035
|
-
export {
|
|
1289
|
+
export { Le as applyControlPlaneDefaultsPayload, Ne as buildControlPlaneDefaultsPayload, te as buildEngineInstanceId, C as createAccessControlHooks, we as createAccessControlMiddleware, Ce as createControlPlaneTenantMiddleware, T as createDatabaseHooks, Ee as createDatabaseMiddleware, Re as createDirectRolloutAdapter, j as createInlineExecutor, Be as createMultiTenancy, $ as createMultiTenancyHooks, J as createMultiTenancyMiddleware, ze as createMultiTenancyPlugin, k as createOperationRecorder, R as createProtectSyncedMiddleware, F as createProvisioningHooks, G as createRuntimeFallbackAdapter, Te as createSubdomainMiddleware, I as createSyncHooks, L as createTenantsOpenAPIRouter, N as enqueueTenantOperation, O as errorToMessage, De as initMultiTenant, A as inlineStepRunner, re as isTerminalStatus, xe as mergeClientWithFallback, Q as projectControlPlaneDefaults, P as runRecordedTenantOperation, Ve as setupMultiTenancy, w as validateTenantAccess, q as withRuntimeFallback, W as withSystemResourceServerInheritance };
|