@authhero/multi-tenancy 15.3.0 → 15.4.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 +1366 -621
- package/dist/types/inheritance/report.d.ts +6 -2
- package/dist/types/inheritance/report.d.ts.map +1 -1
- package/dist/types/init.d.ts +57 -2
- package/dist/types/init.d.ts.map +1 -1
- package/dist/types/middleware/config-sync-mode.d.ts +4 -1
- package/dist/types/middleware/config-sync-mode.d.ts.map +1 -1
- package/dist/types/operations/detach.d.ts +85 -0
- package/dist/types/operations/detach.d.ts.map +1 -0
- package/dist/types/operations/index.d.ts +4 -0
- package/dist/types/operations/index.d.ts.map +1 -1
- package/dist/types/operations/sync-defaults.d.ts +4 -1
- package/dist/types/operations/sync-defaults.d.ts.map +1 -1
- package/dist/types/operations/tenant-members-request.d.ts +97 -0
- package/dist/types/operations/tenant-members-request.d.ts.map +1 -0
- package/dist/types/rollout/resolved-sync.d.ts +21 -0
- package/dist/types/rollout/resolved-sync.d.ts.map +1 -1
- package/dist/types/rollouts/index.d.ts +2 -0
- package/dist/types/rollouts/index.d.ts.map +1 -1
- package/dist/types/rollouts/status.d.ts +1 -1
- package/dist/types/rollouts/status.d.ts.map +1 -1
- package/dist/types/rollouts/verify.d.ts +50 -0
- package/dist/types/rollouts/verify.d.ts.map +1 -0
- package/dist/types/routes/tenants.d.ts.map +1 -1
- package/dist/types/types.d.ts +9 -1
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/tenant-settings.d.ts +13 -0
- package/dist/types/utils/tenant-settings.d.ts.map +1 -0
- package/package.json +5 -5
package/dist/multi-tenancy.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Hono as e } from "hono";
|
|
2
|
-
import { LogTypes as t, MANAGEMENT_API_AUDIENCE as n, MANAGEMENT_API_SCOPES as r,
|
|
3
|
-
import { HTTPException as
|
|
4
|
-
import { OpenAPIHono as
|
|
2
|
+
import { LogTypes as t, MANAGEMENT_API_AUDIENCE as n, MANAGEMENT_API_SCOPES as r, TenantMemberRequestRejected as i, actionInsertSchema as a, auth0QuerySchema as o, brandingSchema as s, canDecrypt as c, connectionInsertSchema as l, connectionOptionsSchema as u, connectionSchema as d, deepMergePatch as f, emailProviderSchema as p, escapeLuceneValue as m, executeTenantMemberRequest as h, fetchAll as g, hookCodeInsertSchema as _, hookInsertSchema as v, init as y, isInteractiveClient as b, isSyncedRowId as x, listControlPlaneKeys as S, promptSettingSchema as C, provisionDefaultClients as w, resourceServerInsertSchema as T, tenantInsertSchema as E, tenantSchema as D } from "authhero";
|
|
3
|
+
import { HTTPException as O } from "hono/http-exception";
|
|
4
|
+
import { OpenAPIHono as k, createRoute as A, z as j } from "@hono/zod-openapi";
|
|
5
|
+
import { escapeLuceneValue as ee } from "@authhero/adapter-interfaces";
|
|
5
6
|
//#region src/hooks/access-control.ts
|
|
6
|
-
function
|
|
7
|
+
function M(e) {
|
|
7
8
|
let { controlPlaneTenantId: t, requireOrganizationMatch: n = !0 } = e;
|
|
8
9
|
return { async onTenantAccessValidation(e, r) {
|
|
9
10
|
if (r === t) return !0;
|
|
@@ -14,14 +15,14 @@ function ne(e) {
|
|
|
14
15
|
return !0;
|
|
15
16
|
} };
|
|
16
17
|
}
|
|
17
|
-
function
|
|
18
|
+
function N(e, t, n, r) {
|
|
18
19
|
if (t === n) return !0;
|
|
19
20
|
let i = r || e;
|
|
20
21
|
return i ? i.toLowerCase() === t.toLowerCase() : !1;
|
|
21
22
|
}
|
|
22
23
|
//#endregion
|
|
23
24
|
//#region src/hooks/database.ts
|
|
24
|
-
function
|
|
25
|
+
function te(e) {
|
|
25
26
|
return { async resolveDataAdapters(t) {
|
|
26
27
|
try {
|
|
27
28
|
return await e.getAdapters(t);
|
|
@@ -33,18 +34,18 @@ function re(e) {
|
|
|
33
34
|
}
|
|
34
35
|
//#endregion
|
|
35
36
|
//#region src/operations/instance-id.ts
|
|
36
|
-
var
|
|
37
|
-
function
|
|
37
|
+
var P = 64;
|
|
38
|
+
function ne(e) {
|
|
38
39
|
return e.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
39
40
|
}
|
|
40
|
-
function
|
|
41
|
-
let t =
|
|
42
|
-
return `op-${r}-${
|
|
41
|
+
function re(e) {
|
|
42
|
+
let t = ne(e.id), n = Math.max(0, P - (5 + t.length)), r = ne(e.kind).slice(0, n), i = 3 + r.length + 2 + t.length, a = Math.max(0, P - i);
|
|
43
|
+
return `op-${r}-${ne(e.tenant_id ?? "fleet").slice(0, a)}-${t}`.slice(0, P);
|
|
43
44
|
}
|
|
44
45
|
//#endregion
|
|
45
46
|
//#region src/operations/recorder.ts
|
|
46
|
-
var
|
|
47
|
-
function
|
|
47
|
+
var ie = 2048;
|
|
48
|
+
function F(e) {
|
|
48
49
|
let t;
|
|
49
50
|
if (e instanceof Error) t = e.message;
|
|
50
51
|
else try {
|
|
@@ -52,9 +53,9 @@ function se(e) {
|
|
|
52
53
|
} catch {
|
|
53
54
|
t = Object.prototype.toString.call(e);
|
|
54
55
|
}
|
|
55
|
-
return t.slice(0,
|
|
56
|
+
return t.slice(0, ie);
|
|
56
57
|
}
|
|
57
|
-
function
|
|
58
|
+
function I(e) {
|
|
58
59
|
let { tenantOperations: t, tenantOperationEvents: n } = e;
|
|
59
60
|
return {
|
|
60
61
|
async markRunning(e, n) {
|
|
@@ -88,24 +89,24 @@ function A(e) {
|
|
|
88
89
|
async markFailed(e, n) {
|
|
89
90
|
await t.update(e, {
|
|
90
91
|
status: "failed",
|
|
91
|
-
error:
|
|
92
|
+
error: F(n),
|
|
92
93
|
finished_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
96
|
};
|
|
96
97
|
}
|
|
97
|
-
function
|
|
98
|
+
function L(e) {
|
|
98
99
|
return e === "succeeded" || e === "failed" || e === "cancelled";
|
|
99
100
|
}
|
|
100
101
|
//#endregion
|
|
101
102
|
//#region src/operations/inline-executor.ts
|
|
102
|
-
var
|
|
103
|
+
var ae = { async do(e, t, n) {
|
|
103
104
|
let r = typeof t == "function" ? t : n;
|
|
104
105
|
if (!r) throw Error("StepRunner.do called without a function");
|
|
105
106
|
return r();
|
|
106
107
|
} };
|
|
107
|
-
function
|
|
108
|
-
let t =
|
|
108
|
+
function oe(e) {
|
|
109
|
+
let t = I(e.stores);
|
|
109
110
|
return {
|
|
110
111
|
engine: "inline",
|
|
111
112
|
async start(n) {
|
|
@@ -124,7 +125,7 @@ function le(e) {
|
|
|
124
125
|
try {
|
|
125
126
|
let r = await e.run({
|
|
126
127
|
operation: n,
|
|
127
|
-
step:
|
|
128
|
+
step: ae
|
|
128
129
|
});
|
|
129
130
|
await t.appendEvent(n.id, {
|
|
130
131
|
step: e.name,
|
|
@@ -135,7 +136,7 @@ function le(e) {
|
|
|
135
136
|
throw await t.appendEvent(n.id, {
|
|
136
137
|
step: e.name,
|
|
137
138
|
outcome: "failed",
|
|
138
|
-
detail: { message:
|
|
139
|
+
detail: { message: F(r) }
|
|
139
140
|
}), await t.markFailed(n.id, r), r;
|
|
140
141
|
}
|
|
141
142
|
}
|
|
@@ -145,7 +146,7 @@ function le(e) {
|
|
|
145
146
|
}
|
|
146
147
|
//#endregion
|
|
147
148
|
//#region src/operations/enqueue.ts
|
|
148
|
-
async function
|
|
149
|
+
async function se(e, t, n) {
|
|
149
150
|
let r = await e.tenantOperations.create({
|
|
150
151
|
tenant_id: t.tenant_id,
|
|
151
152
|
rollout_id: t.rollout_id,
|
|
@@ -155,12 +156,12 @@ async function M(e, t, n) {
|
|
|
155
156
|
target_worker_version: t.target_worker_version,
|
|
156
157
|
target_database_version: t.target_database_version,
|
|
157
158
|
input: t.input
|
|
158
|
-
}), i =
|
|
159
|
+
}), i = re(r);
|
|
159
160
|
try {
|
|
160
161
|
await e.tenantOperations.update(r.id, { engine_instance_id: i });
|
|
161
162
|
} catch (t) {
|
|
162
163
|
try {
|
|
163
|
-
await
|
|
164
|
+
await I(e).markFailed(r.id, t);
|
|
164
165
|
} catch {}
|
|
165
166
|
throw t;
|
|
166
167
|
}
|
|
@@ -169,15 +170,15 @@ async function M(e, t, n) {
|
|
|
169
170
|
engine_instance_id: i
|
|
170
171
|
};
|
|
171
172
|
}
|
|
172
|
-
async function
|
|
173
|
-
let i =
|
|
173
|
+
async function ce(e, t, n, r = {}) {
|
|
174
|
+
let i = I(e), a = await se(e, n, t.engine);
|
|
174
175
|
try {
|
|
175
176
|
await t.start(a);
|
|
176
177
|
} catch (t) {
|
|
177
178
|
let n = null;
|
|
178
179
|
try {
|
|
179
180
|
let r = await e.tenantOperations.get(a.id);
|
|
180
|
-
r && !
|
|
181
|
+
r && !L(r.status) && await i.markFailed(a.id, t), n = await e.tenantOperations.get(a.id);
|
|
181
182
|
} catch (e) {
|
|
182
183
|
console.warn("Failed to record tenant operation failure:", e);
|
|
183
184
|
}
|
|
@@ -190,17 +191,17 @@ async function ue(e, t, n, r = {}) {
|
|
|
190
191
|
return console.warn("Failed to re-fetch tenant operation after start:", e), a;
|
|
191
192
|
}
|
|
192
193
|
}
|
|
193
|
-
async function
|
|
194
|
+
async function le(e) {
|
|
194
195
|
let { tenantId: t, parentTenantId: n, getTenant: r, getChildren: i } = e, a = e.maxDepth ?? 2;
|
|
195
196
|
if (!n) return;
|
|
196
|
-
if (t && n === t) throw new
|
|
197
|
+
if (t && n === t) throw new O(400, { message: "A tenant cannot be its own parent" });
|
|
197
198
|
let o = new Set(t ? [t] : []), s = 0, c = n;
|
|
198
199
|
for (; c;) {
|
|
199
|
-
if (o.has(c)) throw new
|
|
200
|
+
if (o.has(c)) throw new O(400, { message: `Setting parent_tenant_id to '${n}' would create a cycle` });
|
|
200
201
|
o.add(c);
|
|
201
202
|
let e = await r(c);
|
|
202
|
-
if (!e) throw new
|
|
203
|
-
if (s += 1, s > a) throw new
|
|
203
|
+
if (!e) throw new O(400, { message: `Parent tenant '${c}' not found` });
|
|
204
|
+
if (s += 1, s > a) throw new O(400, { message: `Tenant tree is limited to ${a} levels above a tenant` });
|
|
204
205
|
c = e.parent_tenant_id;
|
|
205
206
|
}
|
|
206
207
|
if (t && i) {
|
|
@@ -208,20 +209,20 @@ async function de(e) {
|
|
|
208
209
|
for (; o.length > 0;) {
|
|
209
210
|
let t = [];
|
|
210
211
|
for (let n of o) for (let r of await i(n)) e.has(r) || (e.add(r), t.push(r));
|
|
211
|
-
if (t.length > 0 && (r += 1, s + r > a)) throw new
|
|
212
|
+
if (t.length > 0 && (r += 1, s + r > a)) throw new O(400, { message: `Moving tenant under '${n}' would make its descendant '${t[0]}' exceed the tenant tree limit of ${a} levels` });
|
|
212
213
|
o = t;
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
217
|
//#endregion
|
|
217
218
|
//#region src/inheritance/chain.ts
|
|
218
|
-
async function
|
|
219
|
+
async function R(e) {
|
|
219
220
|
let { tenantId: t, getTenant: n, legacyControlPlane: r } = e, i = e.maxDepth ?? 2, a = await n(t);
|
|
220
221
|
if (!a?.parent_tenant_id) return r && r !== t ? [r] : [];
|
|
221
222
|
let o = [], s = new Set([t]), c = a.parent_tenant_id;
|
|
222
223
|
for (; c;) {
|
|
223
|
-
if (s.has(c)) throw new
|
|
224
|
-
if (s.add(c), o.length >= i) throw new
|
|
224
|
+
if (s.has(c)) throw new O(400, { message: `Tenant chain for '${t}' contains a cycle at '${c}'` });
|
|
225
|
+
if (s.add(c), o.length >= i) throw new O(400, { message: `Tenant chain for '${t}' is deeper than ${i}` });
|
|
225
226
|
let e = await n(c);
|
|
226
227
|
if (!e) break;
|
|
227
228
|
o.push(c), c = e.parent_tenant_id;
|
|
@@ -230,18 +231,18 @@ async function N(e) {
|
|
|
230
231
|
}
|
|
231
232
|
//#endregion
|
|
232
233
|
//#region src/inheritance/legacy.ts
|
|
233
|
-
function
|
|
234
|
+
function ue(e) {
|
|
234
235
|
let t = {};
|
|
235
236
|
for (let n of e ?? []) n.value !== void 0 && (t[n.name] = n.value);
|
|
236
237
|
return t;
|
|
237
238
|
}
|
|
238
|
-
function
|
|
239
|
+
function de(e, t) {
|
|
239
240
|
if (!e.inherit) return e;
|
|
240
241
|
let n = t.find((t) => t.name === e.name && t.is_system);
|
|
241
242
|
if (!n) return e;
|
|
242
243
|
let r = {
|
|
243
|
-
...
|
|
244
|
-
...
|
|
244
|
+
...ue(n.secrets),
|
|
245
|
+
...ue(e.secrets)
|
|
245
246
|
};
|
|
246
247
|
return {
|
|
247
248
|
...e,
|
|
@@ -252,15 +253,15 @@ function pe(e, t) {
|
|
|
252
253
|
}))
|
|
253
254
|
};
|
|
254
255
|
}
|
|
255
|
-
function
|
|
256
|
+
function fe(e, t) {
|
|
256
257
|
if (!t) return e;
|
|
257
|
-
let n = new Set(e.hooks.map((e) => e.hook_id)), r = t.hooks.filter((e) =>
|
|
258
|
+
let n = new Set(e.hooks.map((e) => e.hook_id)), r = t.hooks.filter((e) => He(e) && !n.has(e.hook_id));
|
|
258
259
|
return {
|
|
259
|
-
connections: e.connections.map((e) =>
|
|
260
|
+
connections: e.connections.map((e) => Ne(e, t.connections)),
|
|
260
261
|
resourceServers: e.resourceServers.map((e) => e.is_system ? Ie(e, t.resourceServers.find((t) => t.id === e.id) ?? null) : e),
|
|
261
262
|
hooks: [...e.hooks, ...r],
|
|
262
263
|
hookCode: e.hookCode,
|
|
263
|
-
actions: e.actions.map((e) =>
|
|
264
|
+
actions: e.actions.map((e) => de(e, t.actions)),
|
|
264
265
|
emailProvider: e.emailProvider ?? t.emailProvider,
|
|
265
266
|
branding: e.branding,
|
|
266
267
|
promptSettings: e.promptSettings
|
|
@@ -268,7 +269,7 @@ function me(e, t) {
|
|
|
268
269
|
}
|
|
269
270
|
//#endregion
|
|
270
271
|
//#region src/rollout/defaults-projection.ts
|
|
271
|
-
function
|
|
272
|
+
function pe(e = {}) {
|
|
272
273
|
return {
|
|
273
274
|
connections: e.connections ?? !0,
|
|
274
275
|
resourceServers: e.resourceServers ?? !0,
|
|
@@ -278,28 +279,28 @@ function he(e = {}) {
|
|
|
278
279
|
promptSettings: e.promptSettings ?? !0
|
|
279
280
|
};
|
|
280
281
|
}
|
|
281
|
-
function
|
|
282
|
+
function z() {
|
|
282
283
|
return {
|
|
283
284
|
upserted: 0,
|
|
284
285
|
errors: []
|
|
285
286
|
};
|
|
286
287
|
}
|
|
287
|
-
function
|
|
288
|
+
function me(e) {
|
|
288
289
|
return {
|
|
289
290
|
tenantId: e,
|
|
290
|
-
connections:
|
|
291
|
-
resourceServers:
|
|
292
|
-
hooks:
|
|
293
|
-
emailProvider:
|
|
294
|
-
branding:
|
|
295
|
-
promptSettings:
|
|
291
|
+
connections: z(),
|
|
292
|
+
resourceServers: z(),
|
|
293
|
+
hooks: z(),
|
|
294
|
+
emailProvider: z(),
|
|
295
|
+
branding: z(),
|
|
296
|
+
promptSettings: z()
|
|
296
297
|
};
|
|
297
298
|
}
|
|
298
|
-
function
|
|
299
|
+
function he(e) {
|
|
299
300
|
let t = e.metadata;
|
|
300
301
|
return !!(t && t.inheritable === !0);
|
|
301
302
|
}
|
|
302
|
-
async function
|
|
303
|
+
async function B(e, t, n, r) {
|
|
303
304
|
try {
|
|
304
305
|
await r();
|
|
305
306
|
} catch (r) {
|
|
@@ -308,17 +309,17 @@ async function F(e, t, n, r) {
|
|
|
308
309
|
e.errors.push(i);
|
|
309
310
|
}
|
|
310
311
|
}
|
|
311
|
-
async function
|
|
312
|
+
async function ge(e, t, n) {
|
|
312
313
|
return {
|
|
313
|
-
connections: n.connections ? await
|
|
314
|
+
connections: n.connections ? await g((n) => e.connections.list(t, n), "connections", {
|
|
314
315
|
cursorField: "id",
|
|
315
316
|
pageSize: 100
|
|
316
317
|
}) : [],
|
|
317
|
-
resourceServers: n.resourceServers ? await
|
|
318
|
+
resourceServers: n.resourceServers ? await g((n) => e.resourceServers.list(t, n), "resource_servers", {
|
|
318
319
|
cursorField: "id",
|
|
319
320
|
pageSize: 100
|
|
320
321
|
}) : [],
|
|
321
|
-
hooks: n.hooks ? await
|
|
322
|
+
hooks: n.hooks ? await g((n) => e.hooks.list(t, n), "hooks", {
|
|
322
323
|
cursorField: "hook_id",
|
|
323
324
|
pageSize: 100
|
|
324
325
|
}) : [],
|
|
@@ -327,46 +328,46 @@ async function ve(e, t, n) {
|
|
|
327
328
|
promptSettings: n.promptSettings ? await e.promptSettings.get(t) ?? null : null
|
|
328
329
|
};
|
|
329
330
|
}
|
|
330
|
-
async function
|
|
331
|
+
async function _e(e, t, n, r, i, a) {
|
|
331
332
|
if (r.connections) for (let r of e.connections) {
|
|
332
333
|
let e = r.id;
|
|
333
|
-
e && await
|
|
334
|
-
let i =
|
|
334
|
+
e && await B(a.connections, `connection ${e}`, i, async () => {
|
|
335
|
+
let i = l.parse(r);
|
|
335
336
|
await t.connections.get(n, e) ? await t.connections.update(n, e, i) : await t.connections.create(n, i), a.connections.upserted += 1;
|
|
336
337
|
});
|
|
337
338
|
}
|
|
338
|
-
if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await
|
|
339
|
-
let e =
|
|
339
|
+
if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await B(a.resourceServers, `resource_server ${r.id}`, i, async () => {
|
|
340
|
+
let e = T.parse(r);
|
|
340
341
|
await t.resourceServers.get(n, r.id) ? await t.resourceServers.update(n, r.id, e) : await t.resourceServers.create(n, e), a.resourceServers.upserted += 1;
|
|
341
342
|
});
|
|
342
|
-
if (r.hooks) for (let r of e.hooks) !
|
|
343
|
-
let e =
|
|
343
|
+
if (r.hooks) for (let r of e.hooks) !he(r) || !r.hook_id || await B(a.hooks, `hook ${r.hook_id}`, i, async () => {
|
|
344
|
+
let e = v.parse(r);
|
|
344
345
|
await t.hooks.get(n, r.hook_id) ? await t.hooks.update(n, r.hook_id, e) : await t.hooks.create(n, e), a.hooks.upserted += 1;
|
|
345
346
|
});
|
|
346
|
-
r.emailProvider && e.emailProvider && await
|
|
347
|
+
r.emailProvider && e.emailProvider && await B(a.emailProvider, "email_provider", i, async () => {
|
|
347
348
|
let r = e.emailProvider;
|
|
348
349
|
await t.emailProviders.get(n) ? await t.emailProviders.update(n, r) : await t.emailProviders.create(n, r), a.emailProvider.upserted += 1;
|
|
349
|
-
}), r.branding && e.branding && await
|
|
350
|
+
}), r.branding && e.branding && await B(a.branding, "branding", i, async () => {
|
|
350
351
|
await t.branding.set(n, e.branding), a.branding.upserted += 1;
|
|
351
|
-
}), r.promptSettings && e.promptSettings && await
|
|
352
|
+
}), r.promptSettings && e.promptSettings && await B(a.promptSettings, "prompt_settings", i, async () => {
|
|
352
353
|
await t.promptSettings.set(n, e.promptSettings), a.promptSettings.upserted += 1;
|
|
353
354
|
});
|
|
354
355
|
}
|
|
355
|
-
async function
|
|
356
|
-
let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s =
|
|
357
|
-
return await
|
|
356
|
+
async function ve(e, t) {
|
|
357
|
+
let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s = pe(a), c = await ge(await r(), n, s), l = await i(t), u = me(t);
|
|
358
|
+
return await _e(c, l, n, s, o, u), u;
|
|
358
359
|
}
|
|
359
360
|
//#endregion
|
|
360
361
|
//#region src/inheritance/read.ts
|
|
361
|
-
async function
|
|
362
|
-
let n = await
|
|
362
|
+
async function V(e, t) {
|
|
363
|
+
let n = await ge(e, t, {
|
|
363
364
|
connections: !0,
|
|
364
365
|
resourceServers: !0,
|
|
365
366
|
hooks: !0,
|
|
366
367
|
emailProvider: !0,
|
|
367
368
|
branding: !0,
|
|
368
369
|
promptSettings: !0
|
|
369
|
-
}), r = await
|
|
370
|
+
}), r = await g((n) => e.actions.list(t, n), "actions", {
|
|
370
371
|
cursorField: "id",
|
|
371
372
|
pageSize: 100
|
|
372
373
|
}), i = new Set(r.map((e) => e.id)), a = /* @__PURE__ */ new Set();
|
|
@@ -387,7 +388,7 @@ async function I(e, t) {
|
|
|
387
388
|
}
|
|
388
389
|
//#endregion
|
|
389
390
|
//#region src/inheritance/shadow.ts
|
|
390
|
-
var
|
|
391
|
+
var ye = /secret|password|private_key|api_key|token/i, be = new Set([
|
|
391
392
|
"id",
|
|
392
393
|
"tenant_id",
|
|
393
394
|
"created_at",
|
|
@@ -397,40 +398,40 @@ var xe = /secret|password|private_key|api_key|token/i, Se = new Set([
|
|
|
397
398
|
"enforce",
|
|
398
399
|
"enabled_clients"
|
|
399
400
|
]);
|
|
400
|
-
async function
|
|
401
|
+
async function H(e) {
|
|
401
402
|
let t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
|
|
402
403
|
return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("").slice(0, 16);
|
|
403
404
|
}
|
|
404
|
-
async function
|
|
405
|
+
async function xe(e, t = "") {
|
|
405
406
|
if (Array.isArray(e)) {
|
|
406
407
|
if (t === "secrets") {
|
|
407
408
|
let t = {};
|
|
408
|
-
for (let n of e) t[n.name] = n.value === void 0 ? null : `sha256:${await
|
|
409
|
+
for (let n of e) t[n.name] = n.value === void 0 ? null : `sha256:${await H(n.value)}`;
|
|
409
410
|
return t;
|
|
410
411
|
}
|
|
411
|
-
return Promise.all(e.map((e) =>
|
|
412
|
+
return Promise.all(e.map((e) => xe(e, t)));
|
|
412
413
|
}
|
|
413
414
|
if (e && typeof e == "object") {
|
|
414
415
|
let t = {};
|
|
415
416
|
for (let n of Object.keys(e).sort()) {
|
|
416
417
|
let r = e[n];
|
|
417
|
-
r != null && (t[n] = typeof r == "string" &&
|
|
418
|
+
r != null && (t[n] = typeof r == "string" && ye.test(n) ? `sha256:${await H(r)}` : await xe(r, n));
|
|
418
419
|
}
|
|
419
420
|
return t;
|
|
420
421
|
}
|
|
421
422
|
return e;
|
|
422
423
|
}
|
|
423
|
-
async function
|
|
424
|
+
async function Se(e) {
|
|
424
425
|
let t = {};
|
|
425
|
-
for (let [n, r] of Object.entries(e))
|
|
426
|
-
return await
|
|
426
|
+
for (let [n, r] of Object.entries(e)) be.has(n) || (t[n] = r);
|
|
427
|
+
return await xe(t);
|
|
427
428
|
}
|
|
428
|
-
var
|
|
429
|
+
var Ce = {
|
|
429
430
|
connection: (e) => `${e.strategy}:${e.name}`,
|
|
430
431
|
resourceServer: (e) => e.identifier,
|
|
431
432
|
hook: (e) => e.hook_id,
|
|
432
433
|
action: (e) => e.name
|
|
433
|
-
},
|
|
434
|
+
}, we = new Set([
|
|
434
435
|
"connection",
|
|
435
436
|
"resourceServer",
|
|
436
437
|
"action",
|
|
@@ -438,12 +439,12 @@ var Te = {
|
|
|
438
439
|
"branding",
|
|
439
440
|
"promptSettings"
|
|
440
441
|
]);
|
|
441
|
-
async function
|
|
442
|
+
async function Te(e) {
|
|
442
443
|
let t = /* @__PURE__ */ new Map(), n = async (e, n, r) => {
|
|
443
444
|
let i = t.get(e) ?? /* @__PURE__ */ new Map();
|
|
444
|
-
i.set(n, await
|
|
445
|
+
i.set(n, await Se(r)), t.set(e, i);
|
|
445
446
|
};
|
|
446
|
-
for (let [t, r] of Object.entries(
|
|
447
|
+
for (let [t, r] of Object.entries(Ce)) {
|
|
447
448
|
let i = e[{
|
|
448
449
|
connection: "connections",
|
|
449
450
|
resourceServer: "resourceServers",
|
|
@@ -459,8 +460,8 @@ async function De(e) {
|
|
|
459
460
|
]) e[t] && await n(t, "singleton", e[t]);
|
|
460
461
|
return t;
|
|
461
462
|
}
|
|
462
|
-
async function
|
|
463
|
-
let [n, r] = await Promise.all([
|
|
463
|
+
async function Ee(e, t) {
|
|
464
|
+
let [n, r] = await Promise.all([Te(e), Te(t)]), i = [], a = new Set([...n.keys(), ...r.keys()]);
|
|
464
465
|
for (let e of a) {
|
|
465
466
|
let t = n.get(e) ?? /* @__PURE__ */ new Map(), a = r.get(e) ?? /* @__PURE__ */ new Map();
|
|
466
467
|
for (let n of new Set([...t.keys(), ...a.keys()])) {
|
|
@@ -477,7 +478,7 @@ async function Oe(e, t) {
|
|
|
477
478
|
key: n,
|
|
478
479
|
kind: "extra",
|
|
479
480
|
fields: [],
|
|
480
|
-
expected:
|
|
481
|
+
expected: we.has(e)
|
|
481
482
|
});
|
|
482
483
|
else if (r && o) {
|
|
483
484
|
let t = JSON.stringify(r), a = JSON.stringify(o);
|
|
@@ -489,54 +490,54 @@ async function Oe(e, t) {
|
|
|
489
490
|
kind: "changed",
|
|
490
491
|
fields: s,
|
|
491
492
|
expected: !1,
|
|
492
|
-
legacy_hash: await
|
|
493
|
-
new_hash: await
|
|
493
|
+
legacy_hash: await H(t),
|
|
494
|
+
new_hash: await H(a)
|
|
494
495
|
});
|
|
495
496
|
}
|
|
496
497
|
}
|
|
497
498
|
}
|
|
498
499
|
return i;
|
|
499
500
|
}
|
|
500
|
-
async function
|
|
501
|
-
let { adapters: t, tenantId: n, legacyControlPlane: r } = e, i = await
|
|
501
|
+
async function De(e) {
|
|
502
|
+
let { adapters: t, tenantId: n, legacyControlPlane: r } = e, i = await R({
|
|
502
503
|
tenantId: n,
|
|
503
504
|
getTenant: (e) => t.tenants.get(e),
|
|
504
505
|
legacyControlPlane: r,
|
|
505
506
|
maxDepth: e.maxDepth
|
|
506
|
-
}), a = await
|
|
507
|
-
return (await
|
|
507
|
+
}), a = await V(t, n), o = await Promise.all(i.map((e) => V(t, e))), s = r && r !== n ? await V(t, r) : void 0, { hidden: c, ...l } = $e(o, a), u = new Set(c);
|
|
508
|
+
return (await Ee(fe(a, s), l)).filter((e) => !u.has(`${e.entity}:${e.key}`));
|
|
508
509
|
}
|
|
509
510
|
//#endregion
|
|
510
511
|
//#region src/inheritance/report.ts
|
|
511
|
-
var
|
|
512
|
-
function
|
|
512
|
+
var Oe = 3600 * 1e3, ke = 1e4;
|
|
513
|
+
function Ae(e, t) {
|
|
513
514
|
let n = t.sample ?? 1, r = t.intervalMs ?? 6e4, i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map();
|
|
514
515
|
async function s(n, r) {
|
|
515
|
-
let i = await
|
|
516
|
+
let i = await De({
|
|
516
517
|
adapters: e,
|
|
517
518
|
tenantId: n,
|
|
518
519
|
legacyControlPlane: r
|
|
519
520
|
}), a = Date.now();
|
|
520
|
-
o.size >
|
|
521
|
+
o.size > ke && o.clear();
|
|
521
522
|
for (let s of i) {
|
|
522
523
|
if (s.expected && !t.includeExpected) continue;
|
|
523
|
-
let i = await
|
|
524
|
+
let i = await H([
|
|
524
525
|
n,
|
|
525
526
|
s.entity,
|
|
526
527
|
s.key,
|
|
527
528
|
s.kind,
|
|
528
529
|
s.fields.join(",")
|
|
529
530
|
].join("|")), c = o.get(i);
|
|
530
|
-
c !== void 0 && a - c <
|
|
531
|
+
c !== void 0 && a - c < Oe || (o.set(i, a), await je(e, n, s, r));
|
|
531
532
|
}
|
|
532
533
|
}
|
|
533
534
|
return { schedule(e, t) {
|
|
534
535
|
if (a.has(e) || n < 1 && Math.random() >= n) return;
|
|
535
536
|
let o = Date.now(), c = i.get(e);
|
|
536
|
-
c !== void 0 && o - c < r
|
|
537
|
+
if (!(c !== void 0 && o - c < r)) return i.set(e, o), a.add(e), s(e, t).catch(() => {}).finally(() => a.delete(e));
|
|
537
538
|
} };
|
|
538
539
|
}
|
|
539
|
-
async function
|
|
540
|
+
async function je(e, n, r, i) {
|
|
540
541
|
await e.logs.create(n, {
|
|
541
542
|
type: t.CONFIG_INHERITANCE_DIFF,
|
|
542
543
|
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -549,20 +550,18 @@ async function Ne(e, n, r, i) {
|
|
|
549
550
|
}
|
|
550
551
|
});
|
|
551
552
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
function Pe(e) {
|
|
555
|
-
let { base: t, getTenant: n, controlPlaneTenantId: r } = e, i = e.ttlMs ?? 3e4, a = e.maxEntries ?? 1e3, o = /* @__PURE__ */ new Map();
|
|
553
|
+
function Me(e) {
|
|
554
|
+
let { base: t, getTenant: n, controlPlaneTenantId: r } = e, i = e.ttlMs ?? 1e4, a = e.maxEntries ?? 1e3, o = /* @__PURE__ */ new Map();
|
|
556
555
|
async function s(e) {
|
|
557
556
|
if (e === r) return !1;
|
|
558
557
|
let t = o.get(e), s = Date.now();
|
|
559
558
|
if (t && t.expires > s) return t.synced;
|
|
560
559
|
try {
|
|
561
|
-
let t =
|
|
560
|
+
let t = await n(e), r = t?.config_sync === "synced" || t?.config_sync === "detached";
|
|
562
561
|
return o.size >= a && o.clear(), o.set(e, {
|
|
563
|
-
synced:
|
|
562
|
+
synced: r,
|
|
564
563
|
expires: s + i
|
|
565
|
-
}),
|
|
564
|
+
}), r;
|
|
566
565
|
} catch {
|
|
567
566
|
return !1;
|
|
568
567
|
}
|
|
@@ -580,19 +579,19 @@ function Pe(e) {
|
|
|
580
579
|
}
|
|
581
580
|
//#endregion
|
|
582
581
|
//#region src/middleware/settings-inheritance.ts
|
|
583
|
-
function
|
|
582
|
+
function Ne(e, t) {
|
|
584
583
|
let n = t.find((t) => t.strategy === e.strategy);
|
|
585
584
|
if (!n?.options) return e;
|
|
586
|
-
let r =
|
|
585
|
+
let r = d.passthrough().parse({
|
|
587
586
|
...n,
|
|
588
587
|
...e
|
|
589
588
|
});
|
|
590
|
-
return r.options =
|
|
589
|
+
return r.options = u.passthrough().parse({
|
|
591
590
|
...n.options || {},
|
|
592
591
|
...e.options
|
|
593
592
|
}), r;
|
|
594
593
|
}
|
|
595
|
-
function
|
|
594
|
+
function Pe(e, t) {
|
|
596
595
|
let n = [...t || [], ...e || []];
|
|
597
596
|
return [...new Set(n)];
|
|
598
597
|
}
|
|
@@ -613,10 +612,10 @@ function Ie(e, t) {
|
|
|
613
612
|
function Le(e, t) {
|
|
614
613
|
return t ? {
|
|
615
614
|
...e,
|
|
616
|
-
callbacks:
|
|
617
|
-
web_origins:
|
|
618
|
-
allowed_logout_urls:
|
|
619
|
-
allowed_origins:
|
|
615
|
+
callbacks: Pe(e.callbacks, t.callbacks),
|
|
616
|
+
web_origins: Pe(e.web_origins, t.web_origins),
|
|
617
|
+
allowed_logout_urls: Pe(e.allowed_logout_urls, t.allowed_logout_urls),
|
|
618
|
+
allowed_origins: Pe(e.allowed_origins, t.allowed_origins)
|
|
620
619
|
} : e;
|
|
621
620
|
}
|
|
622
621
|
function Re(e) {
|
|
@@ -667,7 +666,7 @@ function Be(e, t) {
|
|
|
667
666
|
};
|
|
668
667
|
}
|
|
669
668
|
function Ve(e, t) {
|
|
670
|
-
let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i, inheritanceShadow: a } = t, o = t.configSync ??
|
|
669
|
+
let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i, inheritanceShadow: a } = t, o = t.configSync ?? Me({
|
|
671
670
|
base: Re({
|
|
672
671
|
controlPlaneTenantId: n,
|
|
673
672
|
controlPlaneClientId: r,
|
|
@@ -675,7 +674,7 @@ function Ve(e, t) {
|
|
|
675
674
|
}),
|
|
676
675
|
getTenant: async (t) => await e.tenants.get(t) ?? null,
|
|
677
676
|
controlPlaneTenantId: n
|
|
678
|
-
}), s = (e) => o.resolve({ tenant_id: e }), c = a ?
|
|
677
|
+
}), s = (e) => o.resolve({ tenant_id: e }), c = a ? Ae(e, a === !0 ? {} : a) : void 0, l = c ? async (e) => {
|
|
679
678
|
let t = await s(e);
|
|
680
679
|
return await o.isSynced(e) || c.schedule(e, t?.tenantId), t;
|
|
681
680
|
} : s;
|
|
@@ -692,12 +691,12 @@ function Ve(e, t) {
|
|
|
692
691
|
let r = await e.connections.get(t, n);
|
|
693
692
|
if (!r) return r;
|
|
694
693
|
let i = await l(t);
|
|
695
|
-
return !i || t === i.tenantId ? r :
|
|
694
|
+
return !i || t === i.tenantId ? r : Ne(r, (await e.connections.list(i.tenantId)).connections || []);
|
|
696
695
|
},
|
|
697
696
|
list: async (t, n) => {
|
|
698
697
|
let r = await e.connections.list(t, n), i = await l(t);
|
|
699
698
|
if (!i || t === i.tenantId) return r;
|
|
700
|
-
let a = await e.connections.list(i.tenantId), o = r.connections.map((e) =>
|
|
699
|
+
let a = await e.connections.list(i.tenantId), o = r.connections.map((e) => Ne(e, a.connections || []));
|
|
701
700
|
return {
|
|
702
701
|
...r,
|
|
703
702
|
connections: o
|
|
@@ -712,7 +711,7 @@ function Ve(e, t) {
|
|
|
712
711
|
let i = await l(t);
|
|
713
712
|
if (!i || t === i.tenantId) return r;
|
|
714
713
|
let a = await e.connections.list(i.tenantId);
|
|
715
|
-
return r.map((e) =>
|
|
714
|
+
return r.map((e) => Ne(e, a.connections || []));
|
|
716
715
|
}
|
|
717
716
|
},
|
|
718
717
|
emailProviders: {
|
|
@@ -725,24 +724,24 @@ function Ve(e, t) {
|
|
|
725
724
|
}
|
|
726
725
|
},
|
|
727
726
|
resourceServers: ze(e, l),
|
|
728
|
-
hooks:
|
|
727
|
+
hooks: Ue(e, l)
|
|
729
728
|
};
|
|
730
729
|
}
|
|
731
|
-
function
|
|
730
|
+
function He(e) {
|
|
732
731
|
if (!e || typeof e != "object") return !1;
|
|
733
732
|
let t = e.metadata;
|
|
734
733
|
return !t || typeof t != "object" ? !1 : t.inheritable === !0;
|
|
735
734
|
}
|
|
736
|
-
function
|
|
735
|
+
function Ue(e, t) {
|
|
737
736
|
return {
|
|
738
737
|
...e.hooks,
|
|
739
738
|
list: async (n, r) => {
|
|
740
739
|
let i = await e.hooks.list(n, r), a = await t(n);
|
|
741
740
|
if (!a || n === a.tenantId) return i;
|
|
742
|
-
let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(
|
|
741
|
+
let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(He);
|
|
743
742
|
if (o.length === 0) return i;
|
|
744
743
|
let s = new Set((i.hooks || []).map((e) => e.hook_id)), c = [];
|
|
745
|
-
for (let e of o) s.has(e.hook_id) || e.hook_id && s.has(await
|
|
744
|
+
for (let e of o) s.has(e.hook_id) || e.hook_id && s.has(await it("hook", n, e.hook_id)) || c.push(e);
|
|
746
745
|
return {
|
|
747
746
|
...i,
|
|
748
747
|
hooks: [...i.hooks || [], ...c],
|
|
@@ -755,16 +754,16 @@ function He(e, t) {
|
|
|
755
754
|
let a = await t(n);
|
|
756
755
|
if (!a || n === a.tenantId) return i;
|
|
757
756
|
let o = await e.hooks.get(a.tenantId, r);
|
|
758
|
-
return o &&
|
|
757
|
+
return o && He(o) ? o : null;
|
|
759
758
|
}
|
|
760
759
|
};
|
|
761
760
|
}
|
|
762
|
-
function
|
|
761
|
+
function We(e, t) {
|
|
763
762
|
return Ve(e, t);
|
|
764
763
|
}
|
|
765
764
|
//#endregion
|
|
766
765
|
//#region src/inheritance/types.ts
|
|
767
|
-
var
|
|
766
|
+
var Ge = () => ({
|
|
768
767
|
connections: [],
|
|
769
768
|
resourceServers: [],
|
|
770
769
|
hooks: [],
|
|
@@ -776,28 +775,28 @@ var We = () => ({
|
|
|
776
775
|
});
|
|
777
776
|
//#endregion
|
|
778
777
|
//#region src/inheritance/merge.ts
|
|
779
|
-
function
|
|
778
|
+
function U(e, t) {
|
|
780
779
|
if (t.scope) return t.scope;
|
|
781
780
|
switch (e) {
|
|
782
781
|
case "connection":
|
|
783
782
|
case "emailProvider": return "shared";
|
|
784
783
|
case "resourceServer":
|
|
785
784
|
case "action": return t.is_system ? "shared" : "local";
|
|
786
|
-
case "hook": return
|
|
785
|
+
case "hook": return He(t) ? "shared" : "local";
|
|
787
786
|
default: return "local";
|
|
788
787
|
}
|
|
789
788
|
}
|
|
790
|
-
function
|
|
789
|
+
function Ke(e) {
|
|
791
790
|
return e.override ?? "fields";
|
|
792
791
|
}
|
|
793
|
-
var
|
|
794
|
-
function
|
|
792
|
+
var qe = /secret|password|private_key|api_key|token/i;
|
|
793
|
+
function Je(e, t) {
|
|
795
794
|
let n = { ...e ?? {} };
|
|
796
|
-
for (let [e, r] of Object.entries(t ?? {}))
|
|
795
|
+
for (let [e, r] of Object.entries(t ?? {})) qe.test(e) && (n[e] = r);
|
|
797
796
|
return n;
|
|
798
797
|
}
|
|
799
|
-
function
|
|
800
|
-
switch (
|
|
798
|
+
function Ye(e, t) {
|
|
799
|
+
switch (Ke(e)) {
|
|
801
800
|
case "none": return {
|
|
802
801
|
...e,
|
|
803
802
|
id: t.id
|
|
@@ -805,7 +804,7 @@ function qe(e, t) {
|
|
|
805
804
|
case "secrets": return {
|
|
806
805
|
...e,
|
|
807
806
|
id: t.id,
|
|
808
|
-
options:
|
|
807
|
+
options: Je(e.options, t.options)
|
|
809
808
|
};
|
|
810
809
|
default: return {
|
|
811
810
|
...e,
|
|
@@ -817,8 +816,8 @@ function qe(e, t) {
|
|
|
817
816
|
};
|
|
818
817
|
}
|
|
819
818
|
}
|
|
820
|
-
function
|
|
821
|
-
switch (
|
|
819
|
+
function Xe(e, t) {
|
|
820
|
+
switch (Ke(e)) {
|
|
822
821
|
case "none": return {
|
|
823
822
|
...e,
|
|
824
823
|
id: t.id
|
|
@@ -834,42 +833,42 @@ function Je(e, t) {
|
|
|
834
833
|
};
|
|
835
834
|
}
|
|
836
835
|
}
|
|
837
|
-
function
|
|
836
|
+
function Ze(e) {
|
|
838
837
|
return new Map((e ?? []).map((e) => [e.name, e]));
|
|
839
838
|
}
|
|
840
|
-
function
|
|
841
|
-
let n =
|
|
839
|
+
function Qe(e, t) {
|
|
840
|
+
let n = Ke(e);
|
|
842
841
|
if (n === "none") return {
|
|
843
842
|
...e,
|
|
844
843
|
id: t.id
|
|
845
844
|
};
|
|
846
|
-
let r =
|
|
847
|
-
if (n === "secrets" || n === "fields") for (let [e, n] of
|
|
845
|
+
let r = Ze(e.secrets);
|
|
846
|
+
if (n === "secrets" || n === "fields") for (let [e, n] of Ze(t.secrets)) r.set(e, n);
|
|
848
847
|
return {
|
|
849
848
|
...n === "fields" && !t.inherit ? t : e,
|
|
850
849
|
id: t.id,
|
|
851
850
|
secrets: [...r.values()]
|
|
852
851
|
};
|
|
853
852
|
}
|
|
854
|
-
function
|
|
853
|
+
function $e(e, t) {
|
|
855
854
|
let n = /* @__PURE__ */ new Set(), r = [...e].reverse().concat(t), i = (e, t, r, i) => r ? t : t.filter((t) => {
|
|
856
|
-
let r =
|
|
855
|
+
let r = U(e, t);
|
|
857
856
|
return r === "local" ? !1 : (r === "platform" && n.add(`${e}:${i(t)}`), !0);
|
|
858
|
-
}), a =
|
|
857
|
+
}), a = Ge(), o = (e) => `${e.strategy}:${e.name}`, s = (e) => e.identifier, c = (e) => e.hook_id ?? "", l = (e) => e.name, u = /* @__PURE__ */ new Map(), d = [], f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map();
|
|
859
858
|
r.forEach((e, t) => {
|
|
860
859
|
let h = t === r.length - 1;
|
|
861
860
|
for (let t of i("connection", e.connections, h, o)) {
|
|
862
861
|
let e = u.get(t.strategy);
|
|
863
|
-
h ? d.push(e ?
|
|
862
|
+
h ? d.push(e ? Ye(e, t) : t) : u.set(t.strategy, e ? Ye(e, t) : t);
|
|
864
863
|
}
|
|
865
864
|
for (let t of i("resourceServer", e.resourceServers, h, s)) {
|
|
866
865
|
let e = f.get(s(t));
|
|
867
|
-
f.set(s(t), e ?
|
|
866
|
+
f.set(s(t), e ? Xe(e, t) : t);
|
|
868
867
|
}
|
|
869
868
|
for (let t of i("hook", e.hooks, h, c)) p.set(c(t), t);
|
|
870
869
|
for (let t of i("action", e.actions, h, l)) {
|
|
871
870
|
let e = m.get(l(t));
|
|
872
|
-
m.set(l(t), e ?
|
|
871
|
+
m.set(l(t), e ? Qe(e, t) : t);
|
|
873
872
|
}
|
|
874
873
|
for (let t of [
|
|
875
874
|
"emailProvider",
|
|
@@ -877,7 +876,7 @@ function Ze(e, t) {
|
|
|
877
876
|
"promptSettings"
|
|
878
877
|
]) {
|
|
879
878
|
let r = e[t];
|
|
880
|
-
r && (h ||
|
|
879
|
+
r && (h || U(t, r) !== "local") && (!h && U(t, r) === "platform" && n.add(`${t}:singleton`), a[t] = r);
|
|
881
880
|
}
|
|
882
881
|
});
|
|
883
882
|
let h = new Set(r[r.length - 1].connections.map((e) => e.strategy));
|
|
@@ -891,25 +890,32 @@ function Ze(e, t) {
|
|
|
891
890
|
}
|
|
892
891
|
//#endregion
|
|
893
892
|
//#region src/rollout/resolved-sync.ts
|
|
894
|
-
|
|
895
|
-
|
|
893
|
+
var et = [
|
|
894
|
+
"connection",
|
|
895
|
+
"resourceServer",
|
|
896
|
+
"hookCode",
|
|
897
|
+
"action",
|
|
898
|
+
"hook"
|
|
899
|
+
];
|
|
900
|
+
function tt(e) {
|
|
901
|
+
return Array.isArray(e) ? `[${e.map(tt).join(",")}]` : e && typeof e == "object" ? `{${Object.entries(e).filter(([, e]) => e !== void 0).sort(([e], [t]) => e < t ? -1 : 1).map(([e, t]) => `${JSON.stringify(e)}:${tt(t)}`).join(",")}}` : JSON.stringify(e) ?? "null";
|
|
896
902
|
}
|
|
897
|
-
async function
|
|
903
|
+
async function nt(e) {
|
|
898
904
|
let t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
|
|
899
905
|
return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("");
|
|
900
906
|
}
|
|
901
|
-
var
|
|
907
|
+
var rt = {
|
|
902
908
|
connection: "con_",
|
|
903
909
|
resourceServer: "api_",
|
|
904
910
|
hook: "h_",
|
|
905
911
|
hookCode: "hc_",
|
|
906
912
|
action: "act_"
|
|
907
913
|
};
|
|
908
|
-
async function
|
|
909
|
-
let r = await
|
|
910
|
-
return `${
|
|
914
|
+
async function it(e, t, n) {
|
|
915
|
+
let r = await nt(`${t}|${e}|${n}`);
|
|
916
|
+
return `${rt[e]}sy${r.slice(0, 15)}`;
|
|
911
917
|
}
|
|
912
|
-
function
|
|
918
|
+
function W(e, t) {
|
|
913
919
|
let n = t;
|
|
914
920
|
switch (e) {
|
|
915
921
|
case "connection": return `${n.strategy}:${n.name}`;
|
|
@@ -919,13 +925,13 @@ function G(e, t) {
|
|
|
919
925
|
case "hook": return n.hook_id;
|
|
920
926
|
}
|
|
921
927
|
}
|
|
922
|
-
async function
|
|
923
|
-
let r = await
|
|
928
|
+
async function at(e, t, n = {}) {
|
|
929
|
+
let r = await R({
|
|
924
930
|
tenantId: t,
|
|
925
931
|
getTenant: (t) => e.tenants.get(t),
|
|
926
932
|
legacyControlPlane: n.legacyControlPlane,
|
|
927
933
|
maxDepth: n.maxDepth
|
|
928
|
-
}), i =
|
|
934
|
+
}), i = $e(await Promise.all(r.map((t) => V(e, t))), Ge()), a = {
|
|
929
935
|
version: 1,
|
|
930
936
|
chain: r,
|
|
931
937
|
connections: i.connections,
|
|
@@ -941,107 +947,146 @@ async function et(e, t, n = {}) {
|
|
|
941
947
|
};
|
|
942
948
|
return {
|
|
943
949
|
...a,
|
|
944
|
-
hash: await
|
|
950
|
+
hash: await nt(tt(a))
|
|
945
951
|
};
|
|
946
952
|
}
|
|
947
|
-
function
|
|
953
|
+
function ot(e, t) {
|
|
948
954
|
if (typeof e == "string") e.startsWith("enc:v1:") && t.add(e);
|
|
949
|
-
else if (Array.isArray(e)) for (let n of e)
|
|
950
|
-
else if (e && typeof e == "object") for (let n of Object.values(e))
|
|
955
|
+
else if (Array.isArray(e)) for (let n of e) ot(n, t);
|
|
956
|
+
else if (e && typeof e == "object") for (let n of Object.values(e)) ot(n, t);
|
|
951
957
|
}
|
|
952
|
-
function
|
|
958
|
+
function st(e) {
|
|
953
959
|
let t = e.slice(7), n = t.indexOf(":");
|
|
954
960
|
return n === -1 ? "default" : t.slice(0, n);
|
|
955
961
|
}
|
|
956
|
-
async function
|
|
962
|
+
async function ct(e, t) {
|
|
957
963
|
let n = /* @__PURE__ */ new Set();
|
|
958
|
-
|
|
964
|
+
ot(e, n);
|
|
959
965
|
let r = /* @__PURE__ */ new Set();
|
|
960
|
-
for (let e of n) await
|
|
966
|
+
for (let e of n) await c(e, t) || r.add(st(e));
|
|
961
967
|
return [...r].sort();
|
|
962
968
|
}
|
|
963
|
-
var
|
|
969
|
+
var G = () => ({
|
|
964
970
|
added: 0,
|
|
965
971
|
changed: 0,
|
|
966
972
|
unchanged: 0,
|
|
967
973
|
deleted: 0,
|
|
968
974
|
errors: []
|
|
969
|
-
}),
|
|
970
|
-
async function
|
|
971
|
-
let { dryRun:
|
|
972
|
-
|
|
975
|
+
}), lt = (e) => tt(e);
|
|
976
|
+
async function ut(e, t, n, r = {}) {
|
|
977
|
+
let { dryRun: i = !1, continueOnError: o = !0 } = r;
|
|
978
|
+
if (r.prune && e.chain.length === 0) throw Error(`Cannot prune '${n}': the block resolved no ancestors, so every synced copy would look stale. Nothing was written.`);
|
|
979
|
+
let c = {
|
|
980
|
+
status: i ? "dry-run" : "applied",
|
|
973
981
|
hash: e.hash,
|
|
974
982
|
entities: {
|
|
975
|
-
connection:
|
|
976
|
-
resourceServer:
|
|
977
|
-
hookCode:
|
|
978
|
-
action:
|
|
979
|
-
hook:
|
|
980
|
-
emailProvider:
|
|
981
|
-
branding:
|
|
982
|
-
promptSettings:
|
|
983
|
+
connection: G(),
|
|
984
|
+
resourceServer: G(),
|
|
985
|
+
hookCode: G(),
|
|
986
|
+
action: G(),
|
|
987
|
+
hook: G(),
|
|
988
|
+
emailProvider: G(),
|
|
989
|
+
branding: G(),
|
|
990
|
+
promptSettings: G()
|
|
983
991
|
},
|
|
984
|
-
changes: []
|
|
992
|
+
changes: [],
|
|
993
|
+
rows: []
|
|
985
994
|
}, u = await t.tenants.get(n), d = !!r.deletes && e.deletes.length > 0;
|
|
986
|
-
if (!
|
|
987
|
-
...
|
|
995
|
+
if (!i && !r.force && !d && !r.prune && u?.config_sync_hash === e.hash) return {
|
|
996
|
+
...c,
|
|
988
997
|
status: "up-to-date"
|
|
989
998
|
};
|
|
990
999
|
if (r.keyRing) {
|
|
991
|
-
let t = await
|
|
1000
|
+
let t = await ct(e, r.keyRing);
|
|
992
1001
|
if (t.length > 0) throw Error(`Cannot sync config to '${n}': its key ring cannot decrypt key id(s) ${t.map((e) => `"${e}"`).join(", ")} carried by the payload. Nothing was written.`);
|
|
993
1002
|
}
|
|
994
|
-
let
|
|
995
|
-
|
|
1003
|
+
let f = await V(t, n), m = (i || r.prune) && e.chain.length > 0 ? f : null, h = {
|
|
1004
|
+
connection: /* @__PURE__ */ new Set(),
|
|
1005
|
+
resourceServer: /* @__PURE__ */ new Set(),
|
|
1006
|
+
action: /* @__PURE__ */ new Set()
|
|
1007
|
+
};
|
|
1008
|
+
for (let e of f.connections) x(e.id) || h.connection.add(W("connection", e));
|
|
1009
|
+
for (let e of f.resourceServers) x(e.id) || h.resourceServer.add(W("resourceServer", e));
|
|
1010
|
+
for (let e of f.actions) x(e.id) || h.action.add(W("action", e));
|
|
1011
|
+
let y = async (e, t, n) => {
|
|
1012
|
+
let r = c.entities[e];
|
|
996
1013
|
try {
|
|
997
1014
|
let i = await n();
|
|
998
|
-
r[i] += 1, i !== "unchanged" &&
|
|
1015
|
+
r[i] += 1, i !== "unchanged" && (c.changes.push(`${e}:${t}`), c.rows.push({
|
|
1016
|
+
entity: e,
|
|
1017
|
+
key: t,
|
|
1018
|
+
action: i
|
|
1019
|
+
}));
|
|
999
1020
|
} catch (n) {
|
|
1000
1021
|
let i = `${e} ${t}: ${n instanceof Error ? n.message : String(n)}`;
|
|
1001
|
-
if (!
|
|
1022
|
+
if (!o) throw Error(i, { cause: n });
|
|
1002
1023
|
r.errors.push(i);
|
|
1003
1024
|
}
|
|
1004
|
-
},
|
|
1005
|
-
for (let t of e.hookCode)
|
|
1006
|
-
for (let t of e.actions)
|
|
1025
|
+
}, b = async (e) => e.existing ? lt(e.view(e.existing)) === lt(e.view(e.desired)) ? "unchanged" : (i || await e.update(), "changed") : (i || await e.create(), "added"), S = (e, t) => it(e, n, t), w = /* @__PURE__ */ new Map();
|
|
1026
|
+
for (let t of e.hookCode) w.set(t.id, await S("hookCode", W("hookCode", t)));
|
|
1027
|
+
for (let t of e.actions) w.set(t.id, await S("action", W("action", t)));
|
|
1028
|
+
let E, D = async (e) => {
|
|
1029
|
+
if (!E) {
|
|
1030
|
+
E = [];
|
|
1031
|
+
let e = await g((e) => t.clients.list(n, e), "clients", {
|
|
1032
|
+
cursorField: "client_id",
|
|
1033
|
+
pageSize: 100
|
|
1034
|
+
});
|
|
1035
|
+
for (let r of e) (await t.clientConnections.listByClient(n, r.client_id)).length > 0 && E.push(r.client_id);
|
|
1036
|
+
}
|
|
1037
|
+
for (let r of E) await t.clientConnections.addClientToConnection(n, e, r);
|
|
1038
|
+
}, O = (e, t) => h[e].has(t) ? (c.changes.push(`skip ${e}:${t} (the tenant has its own)`), c.rows.push({
|
|
1039
|
+
entity: e,
|
|
1040
|
+
key: t,
|
|
1041
|
+
action: "skipped"
|
|
1042
|
+
}), !0) : !1;
|
|
1007
1043
|
for (let r of e.connections) {
|
|
1008
|
-
let e =
|
|
1009
|
-
await
|
|
1010
|
-
|
|
1011
|
-
|
|
1044
|
+
let e = W("connection", r), i = await S("connection", e);
|
|
1045
|
+
await y("connection", e, async () => {
|
|
1046
|
+
if (O("connection", e)) return "unchanged";
|
|
1047
|
+
let { enabled_clients: a, ...o } = r, s = l.parse({
|
|
1048
|
+
...o,
|
|
1012
1049
|
id: i
|
|
1013
|
-
}),
|
|
1014
|
-
return
|
|
1015
|
-
existing:
|
|
1016
|
-
desired:
|
|
1017
|
-
create: () =>
|
|
1018
|
-
|
|
1050
|
+
}), c = await t.connections.get(n, i);
|
|
1051
|
+
return b({
|
|
1052
|
+
existing: c ? l.parse(c) : null,
|
|
1053
|
+
desired: s,
|
|
1054
|
+
create: async () => {
|
|
1055
|
+
await t.connections.create(n, s);
|
|
1056
|
+
try {
|
|
1057
|
+
await D(i);
|
|
1058
|
+
} catch (e) {
|
|
1059
|
+
throw await t.connections.remove(n, i).catch(() => {}), e;
|
|
1060
|
+
}
|
|
1061
|
+
},
|
|
1062
|
+
update: () => t.connections.update(n, i, s),
|
|
1019
1063
|
view: (e) => e
|
|
1020
1064
|
});
|
|
1021
1065
|
});
|
|
1022
1066
|
}
|
|
1023
1067
|
for (let r of e.resourceServers) {
|
|
1024
|
-
let e =
|
|
1025
|
-
await
|
|
1026
|
-
|
|
1068
|
+
let e = W("resourceServer", r), i = await S("resourceServer", e);
|
|
1069
|
+
await y("resourceServer", e, async () => {
|
|
1070
|
+
if (O("resourceServer", e)) return "unchanged";
|
|
1071
|
+
let a = T.parse({
|
|
1027
1072
|
...r,
|
|
1028
1073
|
id: i
|
|
1029
|
-
}),
|
|
1030
|
-
return
|
|
1031
|
-
existing:
|
|
1032
|
-
desired:
|
|
1033
|
-
create: () => t.resourceServers.create(n,
|
|
1034
|
-
update: () => t.resourceServers.update(n, i,
|
|
1074
|
+
}), o = await t.resourceServers.get(n, i);
|
|
1075
|
+
return b({
|
|
1076
|
+
existing: o ? T.parse(o) : null,
|
|
1077
|
+
desired: a,
|
|
1078
|
+
create: () => t.resourceServers.create(n, a),
|
|
1079
|
+
update: () => t.resourceServers.update(n, i, a),
|
|
1035
1080
|
view: (e) => e
|
|
1036
1081
|
});
|
|
1037
1082
|
});
|
|
1038
1083
|
}
|
|
1039
1084
|
for (let r of e.hookCode) {
|
|
1040
|
-
let e =
|
|
1041
|
-
await
|
|
1042
|
-
let e =
|
|
1043
|
-
return
|
|
1044
|
-
existing: a ?
|
|
1085
|
+
let e = W("hookCode", r), i = w.get(r.id);
|
|
1086
|
+
await y("hookCode", e, async () => {
|
|
1087
|
+
let e = _.parse(r), a = await t.hookCode.get(n, i);
|
|
1088
|
+
return b({
|
|
1089
|
+
existing: a ? _.parse(a) : null,
|
|
1045
1090
|
desired: e,
|
|
1046
1091
|
create: () => t.hookCode.create(n, e, { importMetadata: { id: i } }),
|
|
1047
1092
|
update: () => t.hookCode.update(n, i, e),
|
|
@@ -1050,28 +1095,29 @@ async function at(e, t, n, r = {}) {
|
|
|
1050
1095
|
});
|
|
1051
1096
|
}
|
|
1052
1097
|
for (let r of e.actions) {
|
|
1053
|
-
let e =
|
|
1054
|
-
await
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1098
|
+
let e = W("action", r), i = w.get(r.id);
|
|
1099
|
+
await y("action", e, async () => {
|
|
1100
|
+
if (O("action", e)) return "unchanged";
|
|
1101
|
+
let o = a.parse(r), s = await t.actions.get(n, i);
|
|
1102
|
+
return b({
|
|
1103
|
+
existing: s ? a.parse(s) : null,
|
|
1104
|
+
desired: o,
|
|
1105
|
+
create: () => t.actions.create(n, o, { importMetadata: { id: i } }),
|
|
1106
|
+
update: () => t.actions.update(n, i, o),
|
|
1061
1107
|
view: (e) => e
|
|
1062
1108
|
});
|
|
1063
1109
|
});
|
|
1064
1110
|
}
|
|
1065
1111
|
for (let r of e.hooks) {
|
|
1066
|
-
let e =
|
|
1067
|
-
await
|
|
1068
|
-
let e = r.code_id, a =
|
|
1112
|
+
let e = W("hook", r), i = await S("hook", e);
|
|
1113
|
+
await y("hook", e, async () => {
|
|
1114
|
+
let e = r.code_id, a = v.parse({
|
|
1069
1115
|
...r,
|
|
1070
1116
|
hook_id: i,
|
|
1071
|
-
...e ? { code_id:
|
|
1117
|
+
...e ? { code_id: w.get(e) ?? e } : {}
|
|
1072
1118
|
}), o = await t.hooks.get(n, i);
|
|
1073
|
-
return
|
|
1074
|
-
existing: o ?
|
|
1119
|
+
return b({
|
|
1120
|
+
existing: o ? v.parse(o) : null,
|
|
1075
1121
|
desired: a,
|
|
1076
1122
|
create: () => t.hooks.create(n, a),
|
|
1077
1123
|
update: () => t.hooks.update(n, i, a),
|
|
@@ -1079,29 +1125,109 @@ async function at(e, t, n, r = {}) {
|
|
|
1079
1125
|
});
|
|
1080
1126
|
});
|
|
1081
1127
|
}
|
|
1082
|
-
e.
|
|
1083
|
-
let
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1128
|
+
let k = (e) => e.override === "none" || e.enforce === !0, A = (e, t, n) => lt(e.parse(t)) === lt(n), j = (e, t) => {
|
|
1129
|
+
let n = { ...t };
|
|
1130
|
+
for (let [t, r] of Object.entries(e)) r != null && n[t] === void 0 && (n[t] = null);
|
|
1131
|
+
return n;
|
|
1132
|
+
};
|
|
1133
|
+
e.emailProvider && await y("emailProvider", "singleton", async () => {
|
|
1134
|
+
let r = p.parse(e.emailProvider), a = await t.emailProviders.get(n);
|
|
1135
|
+
if (!a) return i || await t.emailProviders.create(n, r), "added";
|
|
1136
|
+
if (!k(r) || A(p, a, r)) return "unchanged";
|
|
1137
|
+
if (!i) {
|
|
1138
|
+
let e = p.parse(a);
|
|
1139
|
+
await t.emailProviders.update(n, j(e, r));
|
|
1140
|
+
}
|
|
1141
|
+
return "changed";
|
|
1142
|
+
}), e.branding && await y("branding", "singleton", async () => {
|
|
1143
|
+
let r = s.parse(e.branding), a = await t.branding.get(n);
|
|
1144
|
+
if (!a) return i || await t.branding.set(n, r), "added";
|
|
1145
|
+
if (!k(r) || A(s, a, r)) return "unchanged";
|
|
1146
|
+
if (!i) {
|
|
1147
|
+
let e = s.parse(a), i = j(e, r);
|
|
1148
|
+
e.colors && !r.colors && (i.colors = { primary: null }), e.font && !r.font && (i.font = { url: null }), await t.branding.set(n, i);
|
|
1149
|
+
}
|
|
1150
|
+
return "changed";
|
|
1151
|
+
}), e.promptSettings && k(e.promptSettings) && await y("promptSettings", "singleton", async () => {
|
|
1152
|
+
let r = C.parse(e.promptSettings);
|
|
1153
|
+
return A(C, await t.promptSettings.get(n), r) ? "unchanged" : (i || await t.promptSettings.set(n, r), "changed");
|
|
1088
1154
|
});
|
|
1089
|
-
for (let
|
|
1090
|
-
let e = await
|
|
1155
|
+
for (let a of e.deletes) {
|
|
1156
|
+
let e = await S(a.entity, a.key), o = `${a.entity}:${a.key}`;
|
|
1091
1157
|
try {
|
|
1092
|
-
if (!await
|
|
1093
|
-
|
|
1158
|
+
if (!await pt(t, n, a.entity, e)) continue;
|
|
1159
|
+
c.changes.push(`delete ${o}`), c.rows.push({
|
|
1160
|
+
entity: a.entity,
|
|
1161
|
+
key: a.key,
|
|
1162
|
+
action: "delete"
|
|
1163
|
+
}), r.deletes && !i && (await mt(t, n, a.entity, e), c.entities[a.entity].deleted += 1);
|
|
1094
1164
|
} catch (e) {
|
|
1095
|
-
|
|
1165
|
+
c.entities[a.entity].errors.push(`delete ${o}: ${e instanceof Error ? e.message : e}`);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
let ee = () => Object.values(c.entities).some((e) => e.errors.length > 0);
|
|
1169
|
+
if (m && !ee()) {
|
|
1170
|
+
let a = /* @__PURE__ */ new Set();
|
|
1171
|
+
for (let t of et) for (let n of dt(e, t)) (t === "connection" || t === "resourceServer" || t === "action") && h[t].has(W(t, n)) || a.add(t === "hookCode" || t === "action" ? w.get(n.id) : await S(t, W(t, n)));
|
|
1172
|
+
for (let e of ft(m, a)) {
|
|
1173
|
+
let a = `${e.entity}:${e.label}`;
|
|
1174
|
+
try {
|
|
1175
|
+
c.changes.push(`delete ${a}`), c.rows.push({
|
|
1176
|
+
entity: e.entity,
|
|
1177
|
+
key: e.label,
|
|
1178
|
+
action: "delete"
|
|
1179
|
+
}), r.prune && !i && (await mt(t, n, e.entity, e.id), c.entities[e.entity].deleted += 1);
|
|
1180
|
+
} catch (t) {
|
|
1181
|
+
c.entities[e.entity].errors.push(`delete ${a}: ${t instanceof Error ? t.message : t}`);
|
|
1182
|
+
}
|
|
1096
1183
|
}
|
|
1097
1184
|
}
|
|
1098
|
-
let
|
|
1099
|
-
return !
|
|
1185
|
+
let M = ee();
|
|
1186
|
+
return !i && !M && u && await t.tenants.update(n, {
|
|
1100
1187
|
config_sync_hash: e.hash,
|
|
1101
1188
|
config_synced_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1102
|
-
}),
|
|
1189
|
+
}), c;
|
|
1190
|
+
}
|
|
1191
|
+
function dt(e, t) {
|
|
1192
|
+
switch (t) {
|
|
1193
|
+
case "connection": return e.connections;
|
|
1194
|
+
case "resourceServer": return e.resourceServers;
|
|
1195
|
+
case "hookCode": return e.hookCode;
|
|
1196
|
+
case "action": return e.actions;
|
|
1197
|
+
case "hook": return e.hooks;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
function ft(e, t) {
|
|
1201
|
+
let n = (e) => !!e && x(e) && !t.has(e);
|
|
1202
|
+
return [
|
|
1203
|
+
...e.hooks.filter((e) => n(e.hook_id)).map((e) => ({
|
|
1204
|
+
entity: "hook",
|
|
1205
|
+
id: e.hook_id,
|
|
1206
|
+
label: e.hook_id
|
|
1207
|
+
})),
|
|
1208
|
+
...e.actions.filter((e) => n(e.id)).map((e) => ({
|
|
1209
|
+
entity: "action",
|
|
1210
|
+
id: e.id,
|
|
1211
|
+
label: e.name
|
|
1212
|
+
})),
|
|
1213
|
+
...e.hookCode.filter((e) => n(e.id)).map((e) => ({
|
|
1214
|
+
entity: "hookCode",
|
|
1215
|
+
id: e.id,
|
|
1216
|
+
label: e.id
|
|
1217
|
+
})),
|
|
1218
|
+
...e.connections.filter((e) => n(e.id)).map((e) => ({
|
|
1219
|
+
entity: "connection",
|
|
1220
|
+
id: e.id,
|
|
1221
|
+
label: `${e.strategy}:${e.name}`
|
|
1222
|
+
})),
|
|
1223
|
+
...e.resourceServers.filter((e) => n(e.id)).map((e) => ({
|
|
1224
|
+
entity: "resourceServer",
|
|
1225
|
+
id: e.id,
|
|
1226
|
+
label: e.identifier
|
|
1227
|
+
}))
|
|
1228
|
+
];
|
|
1103
1229
|
}
|
|
1104
|
-
async function
|
|
1230
|
+
async function pt(e, t, n, r) {
|
|
1105
1231
|
switch (n) {
|
|
1106
1232
|
case "connection": return !!await e.connections.get(t, r);
|
|
1107
1233
|
case "resourceServer": return !!await e.resourceServers.get(t, r);
|
|
@@ -1110,7 +1236,7 @@ async function ot(e, t, n, r) {
|
|
|
1110
1236
|
case "hook": return !!await e.hooks.get(t, r);
|
|
1111
1237
|
}
|
|
1112
1238
|
}
|
|
1113
|
-
async function
|
|
1239
|
+
async function mt(e, t, n, r) {
|
|
1114
1240
|
switch (n) {
|
|
1115
1241
|
case "connection":
|
|
1116
1242
|
await e.connections.remove(t, r);
|
|
@@ -1131,22 +1257,27 @@ async function st(e, t, n, r) {
|
|
|
1131
1257
|
}
|
|
1132
1258
|
//#endregion
|
|
1133
1259
|
//#region src/operations/sync-defaults.ts
|
|
1134
|
-
function
|
|
1260
|
+
function ht(e) {
|
|
1135
1261
|
let t = e.input ?? {};
|
|
1136
1262
|
return {
|
|
1137
1263
|
dryRun: t.dry_run === !0,
|
|
1138
|
-
force: t.force === !0
|
|
1264
|
+
force: t.force === !0,
|
|
1265
|
+
prune: t.prune === !0
|
|
1139
1266
|
};
|
|
1140
1267
|
}
|
|
1141
|
-
function
|
|
1268
|
+
function gt(e) {
|
|
1142
1269
|
return Object.values(e.entities).flatMap((e) => e.errors);
|
|
1143
1270
|
}
|
|
1144
|
-
|
|
1271
|
+
var _t = 20, vt = 300;
|
|
1272
|
+
function yt(e, t) {
|
|
1145
1273
|
return {
|
|
1146
1274
|
dry_run: t.dryRun,
|
|
1275
|
+
prune: t.prune,
|
|
1147
1276
|
status: e.status,
|
|
1148
1277
|
hash: e.hash,
|
|
1149
1278
|
changes: e.changes,
|
|
1279
|
+
rows: e.rows ?? [],
|
|
1280
|
+
error_messages: gt(e).slice(0, _t).map((e) => e.slice(0, vt)),
|
|
1150
1281
|
entities: Object.fromEntries(Object.entries(e.entities).map(([e, t]) => [e, {
|
|
1151
1282
|
added: t.added,
|
|
1152
1283
|
changed: t.changed,
|
|
@@ -1156,47 +1287,315 @@ function ut(e, t) {
|
|
|
1156
1287
|
}]))
|
|
1157
1288
|
};
|
|
1158
1289
|
}
|
|
1159
|
-
async function
|
|
1290
|
+
async function bt(e) {
|
|
1160
1291
|
let { operation: t, syncConfig: n, recorder: r } = e;
|
|
1161
1292
|
if (!t.tenant_id) throw Error("sync-defaults operations require a tenant_id");
|
|
1162
|
-
let i =
|
|
1293
|
+
let i = ht(t), a = await n(t.tenant_id, i), o = yt(a, i);
|
|
1163
1294
|
await r.setResult(t.id, o);
|
|
1164
|
-
let s =
|
|
1295
|
+
let s = gt(a);
|
|
1165
1296
|
if (s.length > 0) {
|
|
1166
1297
|
let e = s.slice(0, 3).join("; ");
|
|
1167
1298
|
throw Error(`sync-defaults reported ${s.length} error(s): ${e}${s.length > 3 ? "; ..." : ""}`);
|
|
1168
1299
|
}
|
|
1169
1300
|
return o;
|
|
1170
1301
|
}
|
|
1171
|
-
function
|
|
1302
|
+
function xt(e, t) {
|
|
1172
1303
|
return async (n, r) => {
|
|
1173
1304
|
let i = await e.tenants.get(n);
|
|
1174
1305
|
if (!i) throw Error(`Tenant "${n}" not found`);
|
|
1306
|
+
if (i.config_sync === "detached") throw Error(`Tenant "${n}" is detached from its parent: set config_sync back to "inherit-on-read" or "synced" before syncing it`);
|
|
1175
1307
|
if (i.deployment_type === "wfp") throw Error(`Tenant "${n}" has its own database: configure a dispatch sync (syncDefaults) for it`);
|
|
1176
|
-
return
|
|
1308
|
+
return ut(await at(e, n, {
|
|
1177
1309
|
legacyControlPlane: (t.resolveControlPlane ? await t.resolveControlPlane({ tenant_id: n }) : { tenantId: t.controlPlaneTenantId })?.tenantId,
|
|
1178
1310
|
maxDepth: t.maxDepth
|
|
1179
1311
|
}), e, n, {
|
|
1180
1312
|
dryRun: r.dryRun,
|
|
1181
|
-
force: r.force
|
|
1313
|
+
force: r.force,
|
|
1314
|
+
prune: r.prune
|
|
1182
1315
|
});
|
|
1183
1316
|
};
|
|
1184
1317
|
}
|
|
1185
1318
|
//#endregion
|
|
1319
|
+
//#region src/operations/detach.ts
|
|
1320
|
+
function St(e) {
|
|
1321
|
+
let t = e.input ?? {};
|
|
1322
|
+
return {
|
|
1323
|
+
dryRun: t.dry_run === !0,
|
|
1324
|
+
clean: t.clean === !0
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
var Ct = 20, wt = 300;
|
|
1328
|
+
function Tt(e) {
|
|
1329
|
+
return Object.entries(e.entities).flatMap(([e, t]) => t.errors.map((t) => `${e} ${t}`));
|
|
1330
|
+
}
|
|
1331
|
+
function Et(e, t) {
|
|
1332
|
+
return {
|
|
1333
|
+
dry_run: t.dryRun,
|
|
1334
|
+
clean: t.clean,
|
|
1335
|
+
status: e.status,
|
|
1336
|
+
changes: e.changes,
|
|
1337
|
+
rows: e.rows ?? [],
|
|
1338
|
+
error_messages: Tt(e).slice(0, Ct).map((e) => e.slice(0, wt)),
|
|
1339
|
+
entities: Object.fromEntries(Object.entries(e.entities).map(([e, t]) => [e, {
|
|
1340
|
+
converted: t.converted,
|
|
1341
|
+
removed: t.removed,
|
|
1342
|
+
skipped: t.skipped,
|
|
1343
|
+
errors: t.errors.length
|
|
1344
|
+
}]))
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
async function Dt(e) {
|
|
1348
|
+
let { operation: t, detachTenant: n, recorder: r, onDetached: i } = e;
|
|
1349
|
+
if (!t.tenant_id) throw Error("detach operations require a tenant_id");
|
|
1350
|
+
let a = St(t), o = await n(t.tenant_id, a), s = Et(o, a);
|
|
1351
|
+
await r.setResult(t.id, s);
|
|
1352
|
+
let c = Tt(o);
|
|
1353
|
+
if (c.length === 0 && !a.dryRun && o.status === "detached" && i?.(t.tenant_id), c.length > 0) {
|
|
1354
|
+
let e = c.slice(0, 3).join("; ");
|
|
1355
|
+
throw Error(`detach reported ${c.length} error(s): ${e}${c.length > 3 ? "; ..." : ""}`);
|
|
1356
|
+
}
|
|
1357
|
+
return s;
|
|
1358
|
+
}
|
|
1359
|
+
var K = () => ({
|
|
1360
|
+
converted: 0,
|
|
1361
|
+
removed: 0,
|
|
1362
|
+
skipped: 0,
|
|
1363
|
+
errors: []
|
|
1364
|
+
});
|
|
1365
|
+
function q(e) {
|
|
1366
|
+
let { id: t, hook_id: n, scope: r, override: i, enforce: a, ...o } = e;
|
|
1367
|
+
return o;
|
|
1368
|
+
}
|
|
1369
|
+
function Ot(e) {
|
|
1370
|
+
return {
|
|
1371
|
+
status: e,
|
|
1372
|
+
changes: [],
|
|
1373
|
+
rows: [],
|
|
1374
|
+
entities: {
|
|
1375
|
+
connection: K(),
|
|
1376
|
+
resourceServer: K(),
|
|
1377
|
+
hookCode: K(),
|
|
1378
|
+
action: K(),
|
|
1379
|
+
hook: K()
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
function kt(e, t) {
|
|
1384
|
+
if (t.config_sync !== "synced") throw Error(`Tenant "${e}" is not synced: sync its parent's config into it (config_sync "synced") before detaching, otherwise it would lose what it inherits`);
|
|
1385
|
+
}
|
|
1386
|
+
async function At(e, t) {
|
|
1387
|
+
await e.tenants.update(t, {
|
|
1388
|
+
parent_tenant_id: null,
|
|
1389
|
+
config_sync: "detached",
|
|
1390
|
+
config_sync_hash: null,
|
|
1391
|
+
config_synced_at: null
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
async function jt(e, t, n) {
|
|
1395
|
+
let r = Ot(n.dryRun ? "dry-run" : "detached"), { dryRun: i, clean: o } = n, s = await V(e, t), c = {
|
|
1396
|
+
connection: s.connections.filter((e) => x(e.id)),
|
|
1397
|
+
resourceServer: s.resourceServers.filter((e) => x(e.id)),
|
|
1398
|
+
hookCode: s.hookCode.filter((e) => x(e.id)),
|
|
1399
|
+
action: s.actions.filter((e) => x(e.id)),
|
|
1400
|
+
hook: s.hooks.filter((e) => x(e.hook_id))
|
|
1401
|
+
}, u = (e) => e.scope === "platform", d = /* @__PURE__ */ new Set();
|
|
1402
|
+
for (let e of c.hook) {
|
|
1403
|
+
let t = e.code_id;
|
|
1404
|
+
u(e) && t && d.add(t);
|
|
1405
|
+
}
|
|
1406
|
+
for (let e of c.action) u(e) && d.add(e.id);
|
|
1407
|
+
let f = (e, t, n, i = "") => {
|
|
1408
|
+
r.changes.push(`${t} ${e}:${n}${i}`), r.rows.push({
|
|
1409
|
+
entity: e,
|
|
1410
|
+
key: n,
|
|
1411
|
+
action: t === "convert" ? "converted" : t === "remove" ? "removed" : "kept"
|
|
1412
|
+
});
|
|
1413
|
+
}, p = async (e, t, n) => {
|
|
1414
|
+
try {
|
|
1415
|
+
await n();
|
|
1416
|
+
} catch (n) {
|
|
1417
|
+
r.entities[e].errors.push(`${t}: ${n instanceof Error ? n.message : String(n)}`);
|
|
1418
|
+
}
|
|
1419
|
+
}, m = (e, t) => {
|
|
1420
|
+
r.entities[e].skipped += 1, f(e, "skip", t, " (platform: stays a copy)");
|
|
1421
|
+
}, h = [];
|
|
1422
|
+
if (o) {
|
|
1423
|
+
let n = async (n) => {
|
|
1424
|
+
for (let r of await e.clientConnections.listByConnection(t, n)) await e.clientConnections.removeClientFromConnection(t, n, r);
|
|
1425
|
+
}, a = [
|
|
1426
|
+
...c.hook.map((n) => [
|
|
1427
|
+
"hook",
|
|
1428
|
+
n.hook_id,
|
|
1429
|
+
() => e.hooks.remove(t, n.hook_id)
|
|
1430
|
+
]),
|
|
1431
|
+
...c.action.map((n) => [
|
|
1432
|
+
"action",
|
|
1433
|
+
n.name,
|
|
1434
|
+
() => e.actions.remove(t, n.id)
|
|
1435
|
+
]),
|
|
1436
|
+
...c.hookCode.map((n) => [
|
|
1437
|
+
"hookCode",
|
|
1438
|
+
n.id,
|
|
1439
|
+
() => e.hookCode.remove(t, n.id)
|
|
1440
|
+
]),
|
|
1441
|
+
...c.connection.map((r) => [
|
|
1442
|
+
"connection",
|
|
1443
|
+
`${r.strategy}:${r.name}`,
|
|
1444
|
+
async () => {
|
|
1445
|
+
await n(r.id), await e.connections.remove(t, r.id);
|
|
1446
|
+
}
|
|
1447
|
+
]),
|
|
1448
|
+
...c.resourceServer.map((n) => [
|
|
1449
|
+
"resourceServer",
|
|
1450
|
+
n.identifier,
|
|
1451
|
+
() => e.resourceServers.remove(t, n.id)
|
|
1452
|
+
])
|
|
1453
|
+
];
|
|
1454
|
+
for (let [e, t, n] of a) f(e, "remove", t), await p(e, t, async () => {
|
|
1455
|
+
i || await n(), r.entities[e].removed += 1;
|
|
1456
|
+
});
|
|
1457
|
+
} else {
|
|
1458
|
+
let n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set();
|
|
1459
|
+
for (let a of c.hookCode) {
|
|
1460
|
+
if (d.has(a.id)) {
|
|
1461
|
+
m("hookCode", a.id);
|
|
1462
|
+
continue;
|
|
1463
|
+
}
|
|
1464
|
+
f("hookCode", "convert", a.id), o.add(a.id), await p("hookCode", a.id, async () => {
|
|
1465
|
+
if (!i) {
|
|
1466
|
+
let r = await e.hookCode.create(t, _.parse(q(a)));
|
|
1467
|
+
n.set(a.id, r.id), h.push(async () => {
|
|
1468
|
+
await e.hookCode.remove(t, a.id);
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
r.entities.hookCode.converted += 1;
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
for (let s of c.action) {
|
|
1475
|
+
if (u(s)) {
|
|
1476
|
+
m("action", s.name);
|
|
1477
|
+
continue;
|
|
1478
|
+
}
|
|
1479
|
+
f("action", "convert", s.name), o.add(s.id), await p("action", s.name, async () => {
|
|
1480
|
+
if (!i) {
|
|
1481
|
+
let r = await e.actions.create(t, a.parse(q(s)));
|
|
1482
|
+
n.set(s.id, r.id), h.push(async () => {
|
|
1483
|
+
await e.actions.remove(t, s.id);
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
r.entities.action.converted += 1;
|
|
1487
|
+
});
|
|
1488
|
+
}
|
|
1489
|
+
let s = i ? [] : await g((n) => e.organizations.list(t, n), "organizations", {
|
|
1490
|
+
cursorField: "id",
|
|
1491
|
+
pageSize: 100
|
|
1492
|
+
});
|
|
1493
|
+
for (let n of c.connection) {
|
|
1494
|
+
let a = `${n.strategy}:${n.name}`;
|
|
1495
|
+
if (u(n)) {
|
|
1496
|
+
m("connection", a);
|
|
1497
|
+
continue;
|
|
1498
|
+
}
|
|
1499
|
+
f("connection", "convert", a), await p("connection", a, async () => {
|
|
1500
|
+
if (!i) {
|
|
1501
|
+
let { enabled_clients: r, ...i } = q(n), a = await e.connections.create(t, l.parse(i));
|
|
1502
|
+
for (let r of await e.clientConnections.listByConnection(t, n.id)) await e.clientConnections.addClientToConnection(t, a.id, r), await e.clientConnections.removeClientFromConnection(t, n.id, r);
|
|
1503
|
+
for (let r of s) {
|
|
1504
|
+
let i = (await e.organizationConnections.list(t, r.id)).find((e) => e.connection_id === n.id);
|
|
1505
|
+
if (!i) continue;
|
|
1506
|
+
let { connection_id: o, organization_id: s, ...c } = i;
|
|
1507
|
+
await e.organizationConnections.create(t, r.id, {
|
|
1508
|
+
...c,
|
|
1509
|
+
connection_id: a.id
|
|
1510
|
+
}), await e.organizationConnections.remove(t, r.id, n.id);
|
|
1511
|
+
}
|
|
1512
|
+
h.push(async () => {
|
|
1513
|
+
await e.connections.remove(t, n.id);
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
r.entities.connection.converted += 1;
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
for (let n of c.resourceServer) {
|
|
1520
|
+
if (u(n)) {
|
|
1521
|
+
m("resourceServer", n.identifier);
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
f("resourceServer", "convert", n.identifier), await p("resourceServer", n.identifier, async () => {
|
|
1525
|
+
if (!i) {
|
|
1526
|
+
await e.resourceServers.remove(t, n.id);
|
|
1527
|
+
try {
|
|
1528
|
+
await e.resourceServers.create(t, T.parse(q(n)));
|
|
1529
|
+
} catch (r) {
|
|
1530
|
+
throw await e.resourceServers.create(t, T.parse(n)), r;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
r.entities.resourceServer.converted += 1;
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
let y = [];
|
|
1537
|
+
for (let a of c.hook) {
|
|
1538
|
+
let s = a.hook_id, c = a.code_id;
|
|
1539
|
+
if (u(a)) {
|
|
1540
|
+
m("hook", s);
|
|
1541
|
+
continue;
|
|
1542
|
+
}
|
|
1543
|
+
if (c && !(i ? o.has(c) : n.has(c))) {
|
|
1544
|
+
r.entities.hook.skipped += 1, f("hook", "skip", s, " (its code is not converted)");
|
|
1545
|
+
continue;
|
|
1546
|
+
}
|
|
1547
|
+
f("hook", "convert", s), await p("hook", s, async () => {
|
|
1548
|
+
i || (await e.hooks.create(t, v.parse({
|
|
1549
|
+
...q(a),
|
|
1550
|
+
...c ? { code_id: n.get(c) } : {}
|
|
1551
|
+
})), y.push(async () => {
|
|
1552
|
+
await e.hooks.remove(t, s);
|
|
1553
|
+
})), r.entities.hook.converted += 1;
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
h.unshift(...y);
|
|
1557
|
+
}
|
|
1558
|
+
if (Object.values(r.entities).some((e) => e.errors.length > 0)) return {
|
|
1559
|
+
...r,
|
|
1560
|
+
status: "partial"
|
|
1561
|
+
};
|
|
1562
|
+
if (i) return r;
|
|
1563
|
+
for (let e of h) try {
|
|
1564
|
+
await e();
|
|
1565
|
+
} catch (e) {
|
|
1566
|
+
r.entities.hook.errors.push(`remove: ${e instanceof Error ? e.message : String(e)}`);
|
|
1567
|
+
}
|
|
1568
|
+
return Object.values(r.entities).some((e) => e.errors.length > 0) ? {
|
|
1569
|
+
...r,
|
|
1570
|
+
status: "partial"
|
|
1571
|
+
} : r;
|
|
1572
|
+
}
|
|
1573
|
+
function Mt(e) {
|
|
1574
|
+
return async (t, n) => {
|
|
1575
|
+
let r = await e.tenants.get(t);
|
|
1576
|
+
if (!r) throw Error(`Tenant "${t}" not found`);
|
|
1577
|
+
if (r.deployment_type === "wfp") throw Error(`Tenant "${t}" has its own database: configure a dispatch detach for it`);
|
|
1578
|
+
if (r.config_sync === "detached") return Ot("already-detached");
|
|
1579
|
+
kt(t, r);
|
|
1580
|
+
let i = await jt(e, t, n);
|
|
1581
|
+
return i.status === "detached" && await At(e, t), i;
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
//#endregion
|
|
1186
1585
|
//#region src/operations/record-provision.ts
|
|
1187
|
-
function
|
|
1586
|
+
function Nt(e) {
|
|
1188
1587
|
if (e.tenantOperations && e.tenantOperationEvents) return {
|
|
1189
1588
|
tenantOperations: e.tenantOperations,
|
|
1190
1589
|
tenantOperationEvents: e.tenantOperationEvents
|
|
1191
1590
|
};
|
|
1192
1591
|
}
|
|
1193
|
-
async function
|
|
1194
|
-
let r =
|
|
1592
|
+
async function Pt(e, t, n) {
|
|
1593
|
+
let r = Nt(e);
|
|
1195
1594
|
if (!r) {
|
|
1196
1595
|
await n(void 0);
|
|
1197
1596
|
return;
|
|
1198
1597
|
}
|
|
1199
|
-
let i =
|
|
1598
|
+
let i = I(r), a = async (e) => {
|
|
1200
1599
|
try {
|
|
1201
1600
|
await e();
|
|
1202
1601
|
} catch (e) {
|
|
@@ -1204,7 +1603,7 @@ async function mt(e, t, n) {
|
|
|
1204
1603
|
}
|
|
1205
1604
|
}, o;
|
|
1206
1605
|
if (await a(async () => {
|
|
1207
|
-
let e = await
|
|
1606
|
+
let e = await se(r, t, "inline");
|
|
1208
1607
|
o = e.id, await i.markRunning(e.id);
|
|
1209
1608
|
}), !o) {
|
|
1210
1609
|
await n(void 0);
|
|
@@ -1226,7 +1625,7 @@ async function mt(e, t, n) {
|
|
|
1226
1625
|
c || await i.appendEvent(s, {
|
|
1227
1626
|
step: t.kind,
|
|
1228
1627
|
outcome: "failed",
|
|
1229
|
-
detail: { message:
|
|
1628
|
+
detail: { message: F(e) }
|
|
1230
1629
|
}), await i.markFailed(s, e);
|
|
1231
1630
|
}), e;
|
|
1232
1631
|
}
|
|
@@ -1238,29 +1637,154 @@ async function mt(e, t, n) {
|
|
|
1238
1637
|
});
|
|
1239
1638
|
}
|
|
1240
1639
|
//#endregion
|
|
1640
|
+
//#region src/operations/tenant-members-request.ts
|
|
1641
|
+
function Ft(e) {
|
|
1642
|
+
let t = () => {
|
|
1643
|
+
if (!e.tenantMemberRequests) throw Error("The data adapter has no tenantMemberRequests adapter");
|
|
1644
|
+
return e.tenantMemberRequests;
|
|
1645
|
+
};
|
|
1646
|
+
return {
|
|
1647
|
+
get: (e, n) => t().get(e, n),
|
|
1648
|
+
async report(e, n, r) {
|
|
1649
|
+
return t().update(e, n, {
|
|
1650
|
+
status: r.status,
|
|
1651
|
+
result: r.result ?? null,
|
|
1652
|
+
error: r.error ?? null,
|
|
1653
|
+
finished_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1654
|
+
}, "pending");
|
|
1655
|
+
},
|
|
1656
|
+
async listPending(e, { olderThan: n }) {
|
|
1657
|
+
return (await t().list(e, {
|
|
1658
|
+
status: "pending",
|
|
1659
|
+
created_before: n,
|
|
1660
|
+
per_page: 100
|
|
1661
|
+
})).requests;
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
function It(e) {
|
|
1666
|
+
let t = e.input?.request_id;
|
|
1667
|
+
return typeof t == "string" && t ? t : void 0;
|
|
1668
|
+
}
|
|
1669
|
+
var Lt = 300;
|
|
1670
|
+
async function Rt(e) {
|
|
1671
|
+
let { operation: t, store: n, getBackend: r, recorder: a } = e, o = t.tenant_id, s = It(t);
|
|
1672
|
+
if (!o || !s) throw Error("tenant-members-request operations require a tenant_id and a request_id");
|
|
1673
|
+
let c = await n.get(o, s);
|
|
1674
|
+
if (!c) throw Error(`Request ${s} was not found for tenant ${o}`);
|
|
1675
|
+
if (c.status !== "pending") {
|
|
1676
|
+
let e = {
|
|
1677
|
+
request_id: s,
|
|
1678
|
+
outcome: "already_finished",
|
|
1679
|
+
status: c.status
|
|
1680
|
+
};
|
|
1681
|
+
return await a.setResult(t.id, e), e;
|
|
1682
|
+
}
|
|
1683
|
+
let l;
|
|
1684
|
+
try {
|
|
1685
|
+
l = {
|
|
1686
|
+
status: "succeeded",
|
|
1687
|
+
result: await h(await r(), o, c, e.executeOptions)
|
|
1688
|
+
};
|
|
1689
|
+
} catch (e) {
|
|
1690
|
+
if (!(e instanceof i)) throw e;
|
|
1691
|
+
l = {
|
|
1692
|
+
status: "failed",
|
|
1693
|
+
error: F(e).slice(0, Lt)
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
let u = await n.report(o, s, l), d = {
|
|
1697
|
+
request_id: s,
|
|
1698
|
+
outcome: l.status,
|
|
1699
|
+
reported: u,
|
|
1700
|
+
...l.status === "failed" ? { reason: l.error } : {}
|
|
1701
|
+
};
|
|
1702
|
+
return await a.setResult(t.id, d), d;
|
|
1703
|
+
}
|
|
1704
|
+
var zt = 5;
|
|
1705
|
+
async function Bt(e, t, n, r = {}) {
|
|
1706
|
+
let { operations: i } = await e.stores.tenantOperations.list({
|
|
1707
|
+
tenant_id: t,
|
|
1708
|
+
kind: "tenant-members-request",
|
|
1709
|
+
per_page: 100
|
|
1710
|
+
});
|
|
1711
|
+
return i.find((e) => It(e) === n && (e.status === "pending" || e.status === "running" || e.status === "succeeded")) || ce(e.stores, e.executor, {
|
|
1712
|
+
kind: "tenant-members-request",
|
|
1713
|
+
tenant_id: t,
|
|
1714
|
+
initiated_by: r.initiatedBy,
|
|
1715
|
+
input: { request_id: n }
|
|
1716
|
+
}, { returnFailed: !0 });
|
|
1717
|
+
}
|
|
1718
|
+
async function Vt(e) {
|
|
1719
|
+
let t = e.now?.() ?? /* @__PURE__ */ new Date(), n = new Date(t.getTime() - (e.graceMs ?? 5 * 6e4)).toISOString(), r = e.maxAttempts ?? 5, i = {
|
|
1720
|
+
checked: 0,
|
|
1721
|
+
enqueued: 0,
|
|
1722
|
+
gaveUp: 0,
|
|
1723
|
+
unreachable: []
|
|
1724
|
+
};
|
|
1725
|
+
for (let t of await e.tenantIds()) {
|
|
1726
|
+
let a;
|
|
1727
|
+
try {
|
|
1728
|
+
a = await e.store.listPending(t, { olderThan: n });
|
|
1729
|
+
} catch (e) {
|
|
1730
|
+
console.warn(`[tenant-members] could not read the requests of ${t}:`, e), i.unreachable.push(t);
|
|
1731
|
+
continue;
|
|
1732
|
+
}
|
|
1733
|
+
if (a.length === 0) continue;
|
|
1734
|
+
let { operations: o } = await e.stores.tenantOperations.list({
|
|
1735
|
+
tenant_id: t,
|
|
1736
|
+
kind: "tenant-members-request",
|
|
1737
|
+
per_page: 100
|
|
1738
|
+
});
|
|
1739
|
+
for (let n of a) {
|
|
1740
|
+
i.checked += 1;
|
|
1741
|
+
let a = o.filter((e) => It(e) === n.id);
|
|
1742
|
+
if (!a.some((e) => e.status === "pending" || e.status === "running")) {
|
|
1743
|
+
if (a.filter((e) => e.status === "failed").length >= r) {
|
|
1744
|
+
try {
|
|
1745
|
+
await e.store.report(t, n.id, {
|
|
1746
|
+
status: "failed",
|
|
1747
|
+
error: "The control plane could not carry out this request"
|
|
1748
|
+
}) && (i.gaveUp += 1);
|
|
1749
|
+
} catch (e) {
|
|
1750
|
+
console.warn(`[tenant-members] could not report request ${n.id} as failed:`, e);
|
|
1751
|
+
}
|
|
1752
|
+
continue;
|
|
1753
|
+
}
|
|
1754
|
+
try {
|
|
1755
|
+
await Bt(e, t, n.id), i.enqueued += 1;
|
|
1756
|
+
} catch (e) {
|
|
1757
|
+
console.warn(`[tenant-members] could not enqueue request ${n.id}:`, e);
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
return i;
|
|
1763
|
+
}
|
|
1764
|
+
//#endregion
|
|
1241
1765
|
//#region src/hooks/provisioning.ts
|
|
1242
|
-
function
|
|
1766
|
+
function Ht(e) {
|
|
1243
1767
|
return `urn:authhero:tenant:${e.toLowerCase()}`;
|
|
1244
1768
|
}
|
|
1245
|
-
function
|
|
1769
|
+
function Ut(e) {
|
|
1246
1770
|
return {
|
|
1247
1771
|
async beforeCreate(e, t) {
|
|
1248
1772
|
return !t.audience && t.id ? {
|
|
1249
1773
|
...t,
|
|
1250
|
-
audience:
|
|
1774
|
+
audience: Ht(t.id)
|
|
1251
1775
|
} : t;
|
|
1252
1776
|
},
|
|
1253
1777
|
async afterCreate(t, i) {
|
|
1254
1778
|
let { accessControl: a, databaseIsolation: o } = e;
|
|
1255
|
-
if (a && t.ctx && await
|
|
1779
|
+
if (a && t.ctx && await Wt(t, i, a), o?.onProvision) {
|
|
1256
1780
|
let e = o.onProvision;
|
|
1257
|
-
o.recordProvisionOperations === !1 ? await e(i.id) : await
|
|
1781
|
+
o.recordProvisionOperations === !1 ? await e(i.id) : await Pt(t.adapters, {
|
|
1258
1782
|
kind: "provision",
|
|
1259
1783
|
tenant_id: i.id,
|
|
1260
1784
|
initiated_by: t.ctx?.var.user?.sub
|
|
1261
1785
|
}, (t) => e(i.id, t));
|
|
1262
1786
|
} else try {
|
|
1263
|
-
await
|
|
1787
|
+
await w(t.adapters, i.id, {
|
|
1264
1788
|
managementApiIdentifier: n,
|
|
1265
1789
|
managementApiScopes: r
|
|
1266
1790
|
});
|
|
@@ -1284,14 +1808,14 @@ function gt(e) {
|
|
|
1284
1808
|
}
|
|
1285
1809
|
};
|
|
1286
1810
|
}
|
|
1287
|
-
async function
|
|
1811
|
+
async function Wt(e, t, n) {
|
|
1288
1812
|
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, {
|
|
1289
1813
|
name: t.id,
|
|
1290
1814
|
display_name: t.friendly_name || t.id
|
|
1291
1815
|
}), d;
|
|
1292
|
-
if (o && (d = await
|
|
1816
|
+
if (o && (d = await Kt(e, r, s, c)), l && e.ctx) {
|
|
1293
1817
|
let t = e.ctx.var.user;
|
|
1294
|
-
if (t?.sub && !await
|
|
1818
|
+
if (t?.sub && !await Gt(e, r, t.sub)) try {
|
|
1295
1819
|
await e.adapters.userOrganizations.create(r, {
|
|
1296
1820
|
user_id: t.sub,
|
|
1297
1821
|
organization_id: u.id
|
|
@@ -1302,12 +1826,12 @@ async function _t(e, t, n) {
|
|
|
1302
1826
|
}
|
|
1303
1827
|
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}`);
|
|
1304
1828
|
}
|
|
1305
|
-
async function
|
|
1829
|
+
async function Gt(e, t, r) {
|
|
1306
1830
|
let i = await e.adapters.userRoles.list(t, r, void 0, "");
|
|
1307
1831
|
for (let r of i) if ((await e.adapters.rolePermissions.list(t, r.id, { per_page: 1e3 })).some((e) => e.permission_name === "admin:organizations" && e.resource_server_identifier === n)) return !0;
|
|
1308
1832
|
return !1;
|
|
1309
1833
|
}
|
|
1310
|
-
async function
|
|
1834
|
+
async function Kt(e, t, i, a) {
|
|
1311
1835
|
let o = (await e.adapters.roles.list(t, {})).roles.find((e) => e.name === i);
|
|
1312
1836
|
if (o) return o.id;
|
|
1313
1837
|
let s = await e.adapters.roles.create(t, {
|
|
@@ -1322,11 +1846,11 @@ async function yt(e, t, i, a) {
|
|
|
1322
1846
|
}
|
|
1323
1847
|
//#endregion
|
|
1324
1848
|
//#region src/hooks/sync.ts
|
|
1325
|
-
function
|
|
1849
|
+
function qt(e, t, n = () => !0) {
|
|
1326
1850
|
let { controlPlaneTenantId: r, getChildTenantIds: i, getAdapters: a } = e, o = /* @__PURE__ */ new Map();
|
|
1327
1851
|
async function s(e, n, r) {
|
|
1328
1852
|
return (await t(e).list(n, {
|
|
1329
|
-
q: `name:${
|
|
1853
|
+
q: `name:${m(r)}`,
|
|
1330
1854
|
per_page: 1
|
|
1331
1855
|
}))[0] ?? null;
|
|
1332
1856
|
}
|
|
@@ -1377,11 +1901,11 @@ function bt(e, t, n = () => !0) {
|
|
|
1377
1901
|
}
|
|
1378
1902
|
};
|
|
1379
1903
|
}
|
|
1380
|
-
function
|
|
1904
|
+
function Jt(e, t, n = () => !0) {
|
|
1381
1905
|
let { controlPlaneTenantId: r, getControlPlaneAdapters: i, getAdapters: a } = e;
|
|
1382
1906
|
return { async afterCreate(e, o) {
|
|
1383
1907
|
if (o.id !== r) try {
|
|
1384
|
-
let e = await i(), s = await a(o.id), c = t(e), l = t(s), u = await
|
|
1908
|
+
let e = await i(), s = await a(o.id), c = t(e), l = t(s), u = await g((e) => c.listPaginated(r, e), c.listKey, {
|
|
1385
1909
|
cursorField: "id",
|
|
1386
1910
|
pageSize: 100
|
|
1387
1911
|
});
|
|
@@ -1401,7 +1925,7 @@ function xt(e, t, n = () => !0) {
|
|
|
1401
1925
|
}
|
|
1402
1926
|
} };
|
|
1403
1927
|
}
|
|
1404
|
-
var
|
|
1928
|
+
var Yt = (e) => ({
|
|
1405
1929
|
list: async (t, n) => (await e.resourceServers.list(t, n)).resource_servers,
|
|
1406
1930
|
listPaginated: (t, n) => e.resourceServers.list(t, n),
|
|
1407
1931
|
get: (t, n) => e.resourceServers.get(t, n),
|
|
@@ -1419,7 +1943,7 @@ var St = (e) => ({
|
|
|
1419
1943
|
token_lifetime: e.token_lifetime,
|
|
1420
1944
|
token_lifetime_for_web: e.token_lifetime_for_web
|
|
1421
1945
|
})
|
|
1422
|
-
}),
|
|
1946
|
+
}), Xt = (e) => ({
|
|
1423
1947
|
list: async (t, n) => (await e.roles.list(t, n)).roles,
|
|
1424
1948
|
listPaginated: (t, n) => e.roles.list(t, n),
|
|
1425
1949
|
get: (t, n) => e.roles.get(t, n),
|
|
@@ -1434,15 +1958,15 @@ var St = (e) => ({
|
|
|
1434
1958
|
description: e.description
|
|
1435
1959
|
})
|
|
1436
1960
|
});
|
|
1437
|
-
function
|
|
1961
|
+
function Zt(e) {
|
|
1438
1962
|
return e.metadata?.sync !== !1;
|
|
1439
1963
|
}
|
|
1440
|
-
function
|
|
1441
|
-
let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) =>
|
|
1964
|
+
function Qt(e) {
|
|
1965
|
+
let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) => Zt(e) ? n.resourceServers ? n.resourceServers(e) : !0 : !1, o = (e) => Zt(e) ? n.roles ? n.roles(e) : !0 : !1, s = r ? qt(e, Yt, a) : void 0, c = i ? qt(e, Xt, o) : void 0, l = r ? Jt(e, Yt, a) : void 0, u = i ? Jt(e, Xt, o) : void 0, d = i ? { async afterCreate(t, r) {
|
|
1442
1966
|
if (r.id !== e.controlPlaneTenantId) {
|
|
1443
1967
|
await u?.afterCreate?.(t, r);
|
|
1444
1968
|
try {
|
|
1445
|
-
let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await
|
|
1969
|
+
let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await g((n) => t.roles.list(e.controlPlaneTenantId, n), "roles", {
|
|
1446
1970
|
cursorField: "id",
|
|
1447
1971
|
pageSize: 100
|
|
1448
1972
|
}), o = /* @__PURE__ */ new Map();
|
|
@@ -1470,7 +1994,7 @@ function Tt(e) {
|
|
|
1470
1994
|
} } : void 0;
|
|
1471
1995
|
async function f(e, t, n) {
|
|
1472
1996
|
return (await e.roles.list(t, {
|
|
1473
|
-
q: `name:${
|
|
1997
|
+
q: `name:${m(n)}`,
|
|
1474
1998
|
per_page: 1
|
|
1475
1999
|
})).roles[0] ?? null;
|
|
1476
2000
|
}
|
|
@@ -1493,54 +2017,67 @@ function Tt(e) {
|
|
|
1493
2017
|
}
|
|
1494
2018
|
//#endregion
|
|
1495
2019
|
//#region src/middleware/request-data.ts
|
|
1496
|
-
function
|
|
2020
|
+
function J(e) {
|
|
1497
2021
|
return e.var.data ?? e.env.data;
|
|
1498
2022
|
}
|
|
1499
2023
|
//#endregion
|
|
2024
|
+
//#region src/utils/tenant-settings.ts
|
|
2025
|
+
async function $t(e, t, n) {
|
|
2026
|
+
let r = !n || n === t, { totals: i } = await e.list({
|
|
2027
|
+
per_page: 1,
|
|
2028
|
+
include_totals: !0,
|
|
2029
|
+
...r ? {} : { q: `parent_tenant_id:${ee(t)}` }
|
|
2030
|
+
});
|
|
2031
|
+
return {
|
|
2032
|
+
is_control_plane: r,
|
|
2033
|
+
has_children: (i?.length ?? 0) > +!!r
|
|
2034
|
+
};
|
|
2035
|
+
}
|
|
2036
|
+
//#endregion
|
|
1500
2037
|
//#region src/routes/tenants.ts
|
|
1501
|
-
var
|
|
1502
|
-
sub:
|
|
1503
|
-
tenant_id:
|
|
1504
|
-
org_id:
|
|
1505
|
-
scope:
|
|
1506
|
-
permissions:
|
|
2038
|
+
var en = j.object({
|
|
2039
|
+
sub: j.string(),
|
|
2040
|
+
tenant_id: j.string().optional(),
|
|
2041
|
+
org_id: j.string().optional(),
|
|
2042
|
+
scope: j.string().optional(),
|
|
2043
|
+
permissions: j.array(j.string()).optional()
|
|
1507
2044
|
}).passthrough();
|
|
1508
|
-
function
|
|
1509
|
-
let t =
|
|
2045
|
+
function tn(e) {
|
|
2046
|
+
let t = en.safeParse(e);
|
|
1510
2047
|
return t.success ? t.data : void 0;
|
|
1511
2048
|
}
|
|
1512
|
-
function
|
|
2049
|
+
function nn(e, t, n) {
|
|
1513
2050
|
return t ? !e || n ? !1 : e.tenant_id === t : !0;
|
|
1514
2051
|
}
|
|
1515
|
-
function
|
|
2052
|
+
function rn(e) {
|
|
1516
2053
|
let t = e.permissions ?? [], n = e.scope ? e.scope.split(" ").filter(Boolean) : [], r = new Set([...t, ...n]);
|
|
1517
2054
|
return r.has("delete:tenants") || r.has("admin:organizations");
|
|
1518
2055
|
}
|
|
1519
|
-
function
|
|
1520
|
-
let n = new
|
|
1521
|
-
let n =
|
|
1522
|
-
return
|
|
1523
|
-
};
|
|
1524
|
-
if (n.openapi(
|
|
2056
|
+
function an(e, t) {
|
|
2057
|
+
let n = new k(), r = (t) => {
|
|
2058
|
+
let n = tn(t.var.user);
|
|
2059
|
+
return nn(n, e.accessControl?.controlPlaneTenantId ?? J(t).multiTenancyConfig?.controlPlaneTenantId, !!(n?.org_id ?? t.var.organization_id ?? t.var.org_name));
|
|
2060
|
+
}, i = (t, n) => $t(J(t).tenants, n, e.accessControl?.controlPlaneTenantId ?? J(t).multiTenancyConfig?.controlPlaneTenantId);
|
|
2061
|
+
if (n.openapi(A({
|
|
1525
2062
|
tags: ["tenants"],
|
|
1526
2063
|
method: "get",
|
|
1527
2064
|
path: "/",
|
|
1528
|
-
request: { query:
|
|
2065
|
+
request: { query: o },
|
|
1529
2066
|
security: [{ Bearer: [] }],
|
|
1530
2067
|
responses: { 200: {
|
|
1531
|
-
content: { "application/json": { schema:
|
|
1532
|
-
tenants:
|
|
1533
|
-
start:
|
|
1534
|
-
limit:
|
|
1535
|
-
length:
|
|
1536
|
-
total:
|
|
2068
|
+
content: { "application/json": { schema: j.object({
|
|
2069
|
+
tenants: j.array(D),
|
|
2070
|
+
start: j.number().optional(),
|
|
2071
|
+
limit: j.number().optional(),
|
|
2072
|
+
length: j.number().optional(),
|
|
2073
|
+
total: j.number().optional()
|
|
1537
2074
|
}) } },
|
|
1538
2075
|
description: "List of tenants"
|
|
1539
2076
|
} }
|
|
1540
2077
|
}), async (t) => {
|
|
1541
2078
|
let { page: n, per_page: r, include_totals: i, q: a } = t.req.valid("query"), o = t.var.user, s = o?.permissions || [];
|
|
1542
2079
|
if (!(o?.org_id ?? t.var.organization_id) && s.includes("admin:organizations")) {
|
|
1543
|
-
let e = await
|
|
2080
|
+
let e = await J(t).tenants.list({
|
|
1544
2081
|
page: n,
|
|
1545
2082
|
per_page: r,
|
|
1546
2083
|
include_totals: i,
|
|
@@ -1554,10 +2091,10 @@ function At(e, t) {
|
|
|
1554
2091
|
total: e.totals?.length
|
|
1555
2092
|
}) : t.json({ tenants: e.tenants });
|
|
1556
2093
|
}
|
|
1557
|
-
let c = e.accessControl?.controlPlaneTenantId ??
|
|
1558
|
-
if (c && !o?.sub) throw new
|
|
2094
|
+
let c = e.accessControl?.controlPlaneTenantId ?? J(t).multiTenancyConfig?.controlPlaneTenantId;
|
|
2095
|
+
if (c && !o?.sub) throw new O(403, { message: "Access denied: token has no subject" });
|
|
1559
2096
|
if (c && o?.sub) {
|
|
1560
|
-
let e = (await
|
|
2097
|
+
let e = (await g((e) => J(t).userOrganizations.listUserOrganizations(c, o.sub, e), "organizations")).map((e) => e.name);
|
|
1561
2098
|
if (e.length === 0) return i ? t.json({
|
|
1562
2099
|
tenants: [],
|
|
1563
2100
|
start: 0,
|
|
@@ -1573,20 +2110,20 @@ function At(e, t) {
|
|
|
1573
2110
|
length: 0,
|
|
1574
2111
|
total: s
|
|
1575
2112
|
}) : t.json({ tenants: [] });
|
|
1576
|
-
let p = f.map((e) => `id:${e}`).join(" OR "),
|
|
1577
|
-
q:
|
|
2113
|
+
let p = f.map((e) => `id:${e}`).join(" OR "), m = a ? `(${p}) AND (${a})` : p, h = await J(t).tenants.list({
|
|
2114
|
+
q: m,
|
|
1578
2115
|
per_page: u,
|
|
1579
2116
|
include_totals: !1
|
|
1580
2117
|
});
|
|
1581
2118
|
return i ? t.json({
|
|
1582
|
-
tenants:
|
|
2119
|
+
tenants: h.tenants,
|
|
1583
2120
|
start: d,
|
|
1584
2121
|
limit: u,
|
|
1585
|
-
length:
|
|
2122
|
+
length: h.tenants.length,
|
|
1586
2123
|
total: s
|
|
1587
|
-
}) : t.json({ tenants:
|
|
2124
|
+
}) : t.json({ tenants: h.tenants });
|
|
1588
2125
|
}
|
|
1589
|
-
let l = await
|
|
2126
|
+
let l = await J(t).tenants.list({
|
|
1590
2127
|
page: n,
|
|
1591
2128
|
per_page: r,
|
|
1592
2129
|
include_totals: i,
|
|
@@ -1599,44 +2136,44 @@ function At(e, t) {
|
|
|
1599
2136
|
length: l.tenants.length,
|
|
1600
2137
|
total: l.totals?.length
|
|
1601
2138
|
}) : t.json({ tenants: l.tenants });
|
|
1602
|
-
}), n.openapi(
|
|
2139
|
+
}), n.openapi(A({
|
|
1603
2140
|
tags: ["tenants"],
|
|
1604
2141
|
method: "post",
|
|
1605
2142
|
path: "/",
|
|
1606
|
-
request: { body: { content: { "application/json": { schema:
|
|
2143
|
+
request: { body: { content: { "application/json": { schema: E } } } },
|
|
1607
2144
|
security: [{ Bearer: [] }],
|
|
1608
2145
|
responses: {
|
|
1609
2146
|
201: {
|
|
1610
|
-
content: { "application/json": { schema:
|
|
2147
|
+
content: { "application/json": { schema: D } },
|
|
1611
2148
|
description: "Tenant created"
|
|
1612
2149
|
},
|
|
1613
2150
|
400: { description: "Validation error" },
|
|
1614
2151
|
409: { description: "Tenant with this ID already exists" }
|
|
1615
2152
|
}
|
|
1616
2153
|
}), async (n) => {
|
|
1617
|
-
if (!n.var.user?.sub) throw new
|
|
2154
|
+
if (!n.var.user?.sub) throw new O(401, { message: "Authentication required to create tenants" });
|
|
1618
2155
|
let { config_sync_hash: i, config_synced_at: a, config_sync: o, ...s } = n.req.valid("json"), c = s;
|
|
1619
|
-
if (c.parent_tenant_id && !r(n)) throw new
|
|
2156
|
+
if (c.parent_tenant_id && !r(n)) throw new O(403, { message: "Only the control plane can set a tenant's parent" });
|
|
1620
2157
|
o !== void 0 && r(n) && (c = {
|
|
1621
2158
|
...c,
|
|
1622
2159
|
config_sync: o
|
|
1623
2160
|
});
|
|
1624
2161
|
let l = {
|
|
1625
|
-
adapters:
|
|
2162
|
+
adapters: J(n),
|
|
1626
2163
|
ctx: n
|
|
1627
2164
|
};
|
|
1628
|
-
t.tenants?.beforeCreate && (c = await t.tenants.beforeCreate(l, c)), await
|
|
2165
|
+
t.tenants?.beforeCreate && (c = await t.tenants.beforeCreate(l, c)), await le({
|
|
1629
2166
|
tenantId: c.id,
|
|
1630
2167
|
parentTenantId: c.parent_tenant_id,
|
|
1631
|
-
getTenant: (e) =>
|
|
2168
|
+
getTenant: (e) => J(n).tenants.get(e)
|
|
1632
2169
|
});
|
|
1633
|
-
let u = await
|
|
2170
|
+
let u = await J(n).tenants.create(c);
|
|
1634
2171
|
return t.tenants?.afterCreate && await t.tenants.afterCreate(l, u), e.onConfigSyncChange?.(u.id), n.json(u, 201);
|
|
1635
|
-
}), n.openapi(
|
|
2172
|
+
}), n.openapi(A({
|
|
1636
2173
|
tags: ["tenants"],
|
|
1637
2174
|
method: "delete",
|
|
1638
2175
|
path: "/{id}",
|
|
1639
|
-
request: { params:
|
|
2176
|
+
request: { params: j.object({ id: j.string() }) },
|
|
1640
2177
|
security: [{ Bearer: ["delete:tenants"] }],
|
|
1641
2178
|
responses: {
|
|
1642
2179
|
204: { description: "Tenant deleted" },
|
|
@@ -1644,44 +2181,103 @@ function At(e, t) {
|
|
|
1644
2181
|
404: { description: "Tenant not found" }
|
|
1645
2182
|
}
|
|
1646
2183
|
}), async (n) => {
|
|
1647
|
-
let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ??
|
|
2184
|
+
let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ?? J(n).multiTenancyConfig?.controlPlaneTenantId;
|
|
1648
2185
|
if (i) {
|
|
1649
|
-
let e =
|
|
1650
|
-
if (!e?.sub) throw new
|
|
1651
|
-
if (r === i) throw new
|
|
2186
|
+
let e = tn(n.var.user);
|
|
2187
|
+
if (!e?.sub) throw new O(401, { message: "Authentication required" });
|
|
2188
|
+
if (r === i) throw new O(403, { message: "Cannot delete the control plane" });
|
|
1652
2189
|
let t = n.var.org_name, a = r.toLowerCase(), o = !!t && t.toLowerCase() === a;
|
|
1653
2190
|
if (!o) {
|
|
1654
2191
|
let r = !!(e.org_id ?? n.var.organization_id ?? t), a = !e.tenant_id || e.tenant_id === i;
|
|
1655
|
-
!r && a &&
|
|
2192
|
+
!r && a && rn(e) && (o = !0);
|
|
1656
2193
|
}
|
|
1657
|
-
if (o ||= (await
|
|
2194
|
+
if (o ||= (await g((t) => J(n).userOrganizations.listUserOrganizations(i, e.sub, t), "organizations")).some((e) => e.name?.toLowerCase() === a), !o) throw new O(403, { message: "Access denied to this tenant" });
|
|
1658
2195
|
}
|
|
1659
|
-
if (!await
|
|
2196
|
+
if (!await J(n).tenants.get(r)) throw new O(404, { message: "Tenant not found" });
|
|
1660
2197
|
let a = {
|
|
1661
|
-
adapters:
|
|
2198
|
+
adapters: J(n),
|
|
1662
2199
|
ctx: n
|
|
1663
2200
|
};
|
|
1664
|
-
return t.tenants?.beforeDelete && await t.tenants.beforeDelete(a, r), await
|
|
1665
|
-
}), e.
|
|
2201
|
+
return t.tenants?.beforeDelete && await t.tenants.beforeDelete(a, r), await J(n).tenants.remove(r), t.tenants?.afterDelete && await t.tenants.afterDelete(a, r), n.body(null, 204);
|
|
2202
|
+
}), e.verifyConfigSync) {
|
|
2203
|
+
let t = e.verifyConfigSync;
|
|
2204
|
+
n.openapi(A({
|
|
2205
|
+
tags: ["tenants"],
|
|
2206
|
+
method: "get",
|
|
2207
|
+
path: "/{id}/config-sync/verify",
|
|
2208
|
+
request: { params: j.object({ id: j.string() }) },
|
|
2209
|
+
security: [{ Bearer: ["read:tenants"] }],
|
|
2210
|
+
responses: {
|
|
2211
|
+
200: {
|
|
2212
|
+
content: { "application/json": { schema: j.object({
|
|
2213
|
+
tenant_id: j.string(),
|
|
2214
|
+
config_sync: j.enum([
|
|
2215
|
+
"inherit-on-read",
|
|
2216
|
+
"synced",
|
|
2217
|
+
"detached"
|
|
2218
|
+
]),
|
|
2219
|
+
method: j.enum([
|
|
2220
|
+
"read-time",
|
|
2221
|
+
"sync-dry-run",
|
|
2222
|
+
"not-applicable"
|
|
2223
|
+
]),
|
|
2224
|
+
ok: j.boolean(),
|
|
2225
|
+
differences: j.array(j.object({
|
|
2226
|
+
entity: j.string(),
|
|
2227
|
+
key: j.string(),
|
|
2228
|
+
kind: j.enum([
|
|
2229
|
+
"missing",
|
|
2230
|
+
"extra",
|
|
2231
|
+
"changed",
|
|
2232
|
+
"stale"
|
|
2233
|
+
]),
|
|
2234
|
+
fields: j.array(j.string()).optional()
|
|
2235
|
+
})),
|
|
2236
|
+
errors: j.array(j.string())
|
|
2237
|
+
}) } },
|
|
2238
|
+
description: "The tenant's config compared with what its parents publish"
|
|
2239
|
+
},
|
|
2240
|
+
403: { description: "Not allowed to verify this tenant" },
|
|
2241
|
+
404: { description: "Tenant not found" },
|
|
2242
|
+
502: { description: "The tenant's database could not be reached" }
|
|
2243
|
+
}
|
|
2244
|
+
}), async (e) => {
|
|
2245
|
+
let { id: n } = e.req.valid("param");
|
|
2246
|
+
if (n !== e.var.tenant_id && !r(e)) throw new O(403, { message: "Config can only be verified for your own tenant" });
|
|
2247
|
+
let i;
|
|
2248
|
+
try {
|
|
2249
|
+
i = await t(n);
|
|
2250
|
+
} catch (e) {
|
|
2251
|
+
throw console.error(`[multi-tenancy] config verify failed for "${n}":`, e), new O(502, { message: "Could not verify: the tenant's config could not be checked" });
|
|
2252
|
+
}
|
|
2253
|
+
if (!i) throw new O(404, { message: "Tenant not found" });
|
|
2254
|
+
return e.json(i);
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2257
|
+
if (e.configSyncStatus) {
|
|
1666
2258
|
let t = e.configSyncStatus;
|
|
1667
|
-
n.openapi(
|
|
2259
|
+
n.openapi(A({
|
|
1668
2260
|
tags: ["tenants"],
|
|
1669
2261
|
method: "get",
|
|
1670
2262
|
path: "/{id}/config-sync",
|
|
1671
|
-
request: { params:
|
|
2263
|
+
request: { params: j.object({ id: j.string() }) },
|
|
1672
2264
|
security: [{ Bearer: ["read:tenants"] }],
|
|
1673
2265
|
responses: {
|
|
1674
2266
|
200: {
|
|
1675
|
-
content: { "application/json": { schema:
|
|
1676
|
-
tenant_id:
|
|
1677
|
-
parent_tenant_id:
|
|
1678
|
-
config_sync:
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
2267
|
+
content: { "application/json": { schema: j.object({
|
|
2268
|
+
tenant_id: j.string(),
|
|
2269
|
+
parent_tenant_id: j.string().nullable(),
|
|
2270
|
+
config_sync: j.enum([
|
|
2271
|
+
"inherit-on-read",
|
|
2272
|
+
"synced",
|
|
2273
|
+
"detached"
|
|
2274
|
+
]),
|
|
2275
|
+
config_sync_hash: j.string().nullable(),
|
|
2276
|
+
config_synced_at: j.string().nullable(),
|
|
2277
|
+
expected_hash: j.string().nullable(),
|
|
2278
|
+
drifted: j.boolean(),
|
|
2279
|
+
chain: j.array(j.string()),
|
|
2280
|
+
inherited: j.record(j.string(), j.string())
|
|
1685
2281
|
}) } },
|
|
1686
2282
|
description: "Config sync status of the tenant"
|
|
1687
2283
|
},
|
|
@@ -1690,70 +2286,76 @@ function At(e, t) {
|
|
|
1690
2286
|
}
|
|
1691
2287
|
}), async (e) => {
|
|
1692
2288
|
let { id: n } = e.req.valid("param");
|
|
1693
|
-
if (n !== e.var.tenant_id && !r(e)) throw new
|
|
2289
|
+
if (n !== e.var.tenant_id && !r(e)) throw new O(403, { message: "Config sync status is only readable for your own tenant" });
|
|
1694
2290
|
let i = await t(n);
|
|
1695
|
-
if (!i) throw new
|
|
2291
|
+
if (!i) throw new O(404, { message: "Tenant not found" });
|
|
1696
2292
|
return e.json(i);
|
|
1697
2293
|
});
|
|
1698
2294
|
}
|
|
1699
|
-
return n.openapi(
|
|
2295
|
+
return n.openapi(A({
|
|
1700
2296
|
tags: ["tenants", "settings"],
|
|
1701
2297
|
method: "get",
|
|
1702
2298
|
path: "/settings",
|
|
1703
|
-
request: { headers:
|
|
2299
|
+
request: { headers: j.object({ "tenant-id": j.string().optional() }) },
|
|
1704
2300
|
security: [{ Bearer: ["read:tenants"] }],
|
|
1705
2301
|
responses: { 200: {
|
|
1706
|
-
content: { "application/json": { schema:
|
|
2302
|
+
content: { "application/json": { schema: D } },
|
|
1707
2303
|
description: "Current tenant settings"
|
|
1708
2304
|
} }
|
|
1709
2305
|
}), async (e) => {
|
|
1710
|
-
let t = await
|
|
1711
|
-
if (!t) throw new
|
|
1712
|
-
return e.json(
|
|
1713
|
-
|
|
2306
|
+
let t = await J(e).tenants.get(e.var.tenant_id);
|
|
2307
|
+
if (!t) throw new O(404, { message: "Tenant not found" });
|
|
2308
|
+
return e.json({
|
|
2309
|
+
...t,
|
|
2310
|
+
...await i(e, t.id)
|
|
2311
|
+
});
|
|
2312
|
+
}), n.openapi(A({
|
|
1714
2313
|
tags: ["tenants", "settings"],
|
|
1715
2314
|
method: "patch",
|
|
1716
2315
|
path: "/settings",
|
|
1717
2316
|
request: {
|
|
1718
|
-
headers:
|
|
1719
|
-
body: { content: { "application/json": { schema:
|
|
2317
|
+
headers: j.object({ "tenant-id": j.string().optional() }),
|
|
2318
|
+
body: { content: { "application/json": { schema: j.object(E.shape).partial() } } }
|
|
1720
2319
|
},
|
|
1721
2320
|
security: [{ Bearer: ["update:tenants"] }],
|
|
1722
2321
|
responses: { 200: {
|
|
1723
|
-
content: { "application/json": { schema:
|
|
2322
|
+
content: { "application/json": { schema: D } },
|
|
1724
2323
|
description: "Updated tenant settings"
|
|
1725
2324
|
} }
|
|
1726
2325
|
}), async (t) => {
|
|
1727
|
-
let { id: n, config_sync_hash:
|
|
1728
|
-
if (!
|
|
1729
|
-
if ("config_sync" in
|
|
1730
|
-
if ("default_client_id" in
|
|
1731
|
-
let e =
|
|
2326
|
+
let { id: n, config_sync_hash: a, config_synced_at: o, ...s } = t.req.valid("json"), c = await J(t).tenants.get(t.var.tenant_id);
|
|
2327
|
+
if (!c) throw new O(404, { message: "Tenant not found" });
|
|
2328
|
+
if ("config_sync" in s && (s.config_sync ?? "inherit-on-read") !== (c.config_sync ?? "inherit-on-read") && !r(t)) throw new O(403, { message: "Only the control plane can change a tenant's config_sync mode" });
|
|
2329
|
+
if ("default_client_id" in s) {
|
|
2330
|
+
let e = s.default_client_id;
|
|
1732
2331
|
if (typeof e == "string" && e.length > 0) {
|
|
1733
|
-
let n = await
|
|
1734
|
-
if (!n) throw new
|
|
1735
|
-
if (!
|
|
2332
|
+
let n = await J(t).clients.get(t.var.tenant_id, e);
|
|
2333
|
+
if (!n) throw new O(400, { message: `Client with id '${e}' not found` });
|
|
2334
|
+
if (!b(n)) throw new O(400, { message: `Client '${e}' is not an interactive client and cannot be used as the default client` });
|
|
1736
2335
|
}
|
|
1737
2336
|
}
|
|
1738
|
-
if ("parent_tenant_id" in
|
|
1739
|
-
if ((
|
|
1740
|
-
await
|
|
2337
|
+
if ("parent_tenant_id" in s) {
|
|
2338
|
+
if ((s.parent_tenant_id ?? null) !== (c.parent_tenant_id ?? null) && !r(t)) throw new O(403, { message: "Only the control plane can change a tenant's parent" });
|
|
2339
|
+
await le({
|
|
1741
2340
|
tenantId: t.var.tenant_id,
|
|
1742
|
-
parentTenantId:
|
|
1743
|
-
getTenant: (e) =>
|
|
1744
|
-
getChildren: async (e) => (await
|
|
2341
|
+
parentTenantId: s.parent_tenant_id,
|
|
2342
|
+
getTenant: (e) => J(t).tenants.get(e),
|
|
2343
|
+
getChildren: async (e) => (await g((e) => J(t).tenants.list(e), "tenants")).filter((t) => t.parent_tenant_id === e).map((e) => e.id)
|
|
1745
2344
|
});
|
|
1746
2345
|
}
|
|
1747
|
-
let
|
|
1748
|
-
await
|
|
1749
|
-
let
|
|
1750
|
-
if (!
|
|
1751
|
-
return t.json(
|
|
2346
|
+
let l = f(c, s);
|
|
2347
|
+
await J(t).tenants.update(t.var.tenant_id, l), "config_sync" in s && e.onConfigSyncChange?.(t.var.tenant_id);
|
|
2348
|
+
let u = await J(t).tenants.get(t.var.tenant_id);
|
|
2349
|
+
if (!u) throw new O(500, { message: "Failed to retrieve updated tenant" });
|
|
2350
|
+
return t.json({
|
|
2351
|
+
...u,
|
|
2352
|
+
...await i(t, u.id)
|
|
2353
|
+
});
|
|
1752
2354
|
}), n;
|
|
1753
2355
|
}
|
|
1754
2356
|
//#endregion
|
|
1755
2357
|
//#region src/middleware/protect-synced.ts
|
|
1756
|
-
function
|
|
2358
|
+
function on(e) {
|
|
1757
2359
|
for (let { pattern: t, type: n } of [
|
|
1758
2360
|
{
|
|
1759
2361
|
pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
|
|
@@ -1776,7 +2378,7 @@ function jt(e) {
|
|
|
1776
2378
|
}
|
|
1777
2379
|
return null;
|
|
1778
2380
|
}
|
|
1779
|
-
async function
|
|
2381
|
+
async function sn(e, t, n) {
|
|
1780
2382
|
try {
|
|
1781
2383
|
switch (n.type) {
|
|
1782
2384
|
case "resource_server": return (await e.resourceServers.get(t, n.id))?.is_system === !0;
|
|
@@ -1788,14 +2390,14 @@ async function Mt(e, t, n) {
|
|
|
1788
2390
|
return !1;
|
|
1789
2391
|
}
|
|
1790
2392
|
}
|
|
1791
|
-
function
|
|
2393
|
+
function cn(e) {
|
|
1792
2394
|
return {
|
|
1793
2395
|
resource_server: "resource server",
|
|
1794
2396
|
role: "role",
|
|
1795
2397
|
connection: "connection"
|
|
1796
2398
|
}[e];
|
|
1797
2399
|
}
|
|
1798
|
-
function
|
|
2400
|
+
function ln(e) {
|
|
1799
2401
|
for (let { pattern: t, type: n } of [
|
|
1800
2402
|
{
|
|
1801
2403
|
pattern: /\/api\/v2\/connections\/([^/]+)$/,
|
|
@@ -1826,7 +2428,7 @@ function Pt(e) {
|
|
|
1826
2428
|
}
|
|
1827
2429
|
return null;
|
|
1828
2430
|
}
|
|
1829
|
-
async function
|
|
2431
|
+
async function un(e, t, n) {
|
|
1830
2432
|
try {
|
|
1831
2433
|
switch (n.type) {
|
|
1832
2434
|
case "connection": return await e.connections.get(t, n.id);
|
|
@@ -1839,38 +2441,38 @@ async function Ft(e, t, n) {
|
|
|
1839
2441
|
return null;
|
|
1840
2442
|
}
|
|
1841
2443
|
}
|
|
1842
|
-
var
|
|
2444
|
+
var dn = {
|
|
1843
2445
|
connection: ["options"],
|
|
1844
2446
|
resource_server: ["signing_secret"],
|
|
1845
2447
|
action: ["secrets"],
|
|
1846
2448
|
hook: [],
|
|
1847
2449
|
hook_code: []
|
|
1848
|
-
},
|
|
2450
|
+
}, fn = new Set([
|
|
1849
2451
|
"client_secret",
|
|
1850
2452
|
"app_secret",
|
|
1851
2453
|
"twilio_token"
|
|
1852
2454
|
]);
|
|
1853
|
-
function
|
|
2455
|
+
function pn(e, t) {
|
|
1854
2456
|
let n = (e) => {
|
|
1855
2457
|
let { client_secret: t, ...n } = e ?? {};
|
|
1856
2458
|
return n;
|
|
1857
2459
|
};
|
|
1858
|
-
return
|
|
2460
|
+
return mn(n(e), n(t));
|
|
1859
2461
|
}
|
|
1860
|
-
var
|
|
1861
|
-
function
|
|
1862
|
-
return new
|
|
2462
|
+
var mn = (e, t) => JSON.stringify(e) === JSON.stringify(t);
|
|
2463
|
+
function Y(e, t) {
|
|
2464
|
+
return new O(403, { message: `This ${e.type.replace("_", " ")} is synced from a parent tenant and ${t}. Make changes in the parent tenant instead.` });
|
|
1863
2465
|
}
|
|
1864
|
-
async function
|
|
1865
|
-
let r = await
|
|
2466
|
+
async function hn(e, t, n) {
|
|
2467
|
+
let r = await un(J(e), t, n);
|
|
1866
2468
|
if (!r) return;
|
|
1867
|
-
if (n.type === "hook_code") throw
|
|
2469
|
+
if (n.type === "hook_code") throw Y(n, "cannot be modified");
|
|
1868
2470
|
if (e.req.method === "DELETE") {
|
|
1869
|
-
if (r.enforce === !0) throw
|
|
2471
|
+
if (r.enforce === !0) throw Y(n, "cannot be deleted");
|
|
1870
2472
|
return;
|
|
1871
2473
|
}
|
|
1872
2474
|
let i = r.override ?? "fields";
|
|
1873
|
-
if (i === "none") throw
|
|
2475
|
+
if (i === "none") throw Y(n, "cannot be edited");
|
|
1874
2476
|
let a = {};
|
|
1875
2477
|
try {
|
|
1876
2478
|
let t = await e.req.raw.clone().json();
|
|
@@ -1880,56 +2482,56 @@ async function Bt(e, t, n) {
|
|
|
1880
2482
|
"scope",
|
|
1881
2483
|
"override",
|
|
1882
2484
|
"enforce"
|
|
1883
|
-
]) if (e in a && !
|
|
1884
|
-
if (r.enforce === !0 && a.enabled === !1) throw
|
|
2485
|
+
]) if (e in a && !mn(a[e] ?? null, r[e] ?? null)) throw Y(n, `has a locked ${e}`);
|
|
2486
|
+
if (r.enforce === !0 && a.enabled === !1) throw Y(n, "cannot be disabled");
|
|
1885
2487
|
if (i === "secrets") {
|
|
1886
|
-
let e =
|
|
2488
|
+
let e = dn[n.type];
|
|
1887
2489
|
for (let [t, i] of Object.entries(a)) if (![
|
|
1888
2490
|
"scope",
|
|
1889
2491
|
"override",
|
|
1890
2492
|
"enforce"
|
|
1891
|
-
].includes(t) && !
|
|
1892
|
-
if (!e.includes(t)) throw
|
|
2493
|
+
].includes(t) && !mn(i, r[t])) {
|
|
2494
|
+
if (!e.includes(t)) throw Y(n, `only allows its secrets to be changed (not ${t})`);
|
|
1893
2495
|
if (t === "options" && i && typeof i == "object") {
|
|
1894
2496
|
let e = r.options ?? {};
|
|
1895
|
-
for (let [t, r] of Object.entries(i)) if (!
|
|
2497
|
+
for (let [t, r] of Object.entries(i)) if (!mn(r, e[t]) && !t.endsWith("_hint") && !(fn.has(t) || t === "configuration" && pn(r, e[t]))) throw Y(n, `only allows its secrets to be changed (not options.${t})`);
|
|
1896
2498
|
}
|
|
1897
2499
|
}
|
|
1898
2500
|
}
|
|
1899
2501
|
}
|
|
1900
|
-
function
|
|
2502
|
+
function gn() {
|
|
1901
2503
|
return async (e, t) => {
|
|
1902
2504
|
if (![
|
|
1903
2505
|
"PATCH",
|
|
1904
2506
|
"PUT",
|
|
1905
2507
|
"DELETE"
|
|
1906
2508
|
].includes(e.req.method)) return t();
|
|
1907
|
-
let n =
|
|
2509
|
+
let n = on(e.req.path), r = ln(e.req.path);
|
|
1908
2510
|
if (!n && !r) return t();
|
|
1909
2511
|
let i = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
|
|
1910
2512
|
if (!i) return t();
|
|
1911
|
-
if (n && await
|
|
1912
|
-
return r &&
|
|
2513
|
+
if (n && await sn(J(e), i, n)) throw new O(403, { message: `This ${cn(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.` });
|
|
2514
|
+
return r && x(r.id) && await hn(e, i, r), t();
|
|
1913
2515
|
};
|
|
1914
2516
|
}
|
|
1915
2517
|
//#endregion
|
|
1916
2518
|
//#region src/middleware/index.ts
|
|
1917
|
-
function
|
|
2519
|
+
function _n(e) {
|
|
1918
2520
|
return async (t, n) => {
|
|
1919
2521
|
let r = t.var.user;
|
|
1920
2522
|
return r?.tenant_id === e && r.org_name && t.set("tenant_id", r.org_name), n();
|
|
1921
2523
|
};
|
|
1922
2524
|
}
|
|
1923
|
-
function
|
|
2525
|
+
function vn(e) {
|
|
1924
2526
|
return async (t, r) => {
|
|
1925
2527
|
if (!e.accessControl) return r();
|
|
1926
2528
|
let { controlPlaneTenantId: i } = e.accessControl, a = t.var.org_name, o = t.var.organization_id, s = a || o, c = t.var.tenant_id, l = t.var.user, u = (l?.aud ? Array.isArray(l.aud) ? l.aud : [l.aud] : []).includes(n);
|
|
1927
|
-
if (!c && s && u && (t.set("tenant_id", s), c = s), !c) throw new
|
|
1928
|
-
if (!
|
|
2529
|
+
if (!c && s && u && (t.set("tenant_id", s), c = s), !c) throw new O(400, { message: "Tenant ID not found in request" });
|
|
2530
|
+
if (!N(o, c, i, a)) throw new O(403, { message: `Access denied to tenant ${c}` });
|
|
1929
2531
|
return r();
|
|
1930
2532
|
};
|
|
1931
2533
|
}
|
|
1932
|
-
function
|
|
2534
|
+
function yn(e) {
|
|
1933
2535
|
return async (t, n) => {
|
|
1934
2536
|
if (!e.subdomainRouting) return n();
|
|
1935
2537
|
let { baseDomain: r, reservedSubdomains: i = [], resolveSubdomain: a } = e.subdomainRouting, o = t.req.header("x-forwarded-host") || t.req.header("host") || "", s = null;
|
|
@@ -1941,18 +2543,18 @@ function Wt(e) {
|
|
|
1941
2543
|
let c = null;
|
|
1942
2544
|
if (a) c = await a(s);
|
|
1943
2545
|
else if (e.subdomainRouting.useOrganizations !== !1 && e.accessControl) try {
|
|
1944
|
-
let n = await
|
|
2546
|
+
let n = await J(t).organizations.get(e.accessControl.controlPlaneTenantId, s);
|
|
1945
2547
|
n && (c = n.id);
|
|
1946
2548
|
} catch {}
|
|
1947
|
-
if (!c) throw new
|
|
2549
|
+
if (!c) throw new O(404, { message: `Tenant not found for subdomain: ${s}` });
|
|
1948
2550
|
return t.set("tenant_id", c), n();
|
|
1949
2551
|
};
|
|
1950
2552
|
}
|
|
1951
|
-
function
|
|
2553
|
+
function bn(e) {
|
|
1952
2554
|
return async (t, n) => {
|
|
1953
2555
|
if (!e.databaseIsolation) return n();
|
|
1954
2556
|
let r = t.var.tenant_id;
|
|
1955
|
-
if (!r) throw new
|
|
2557
|
+
if (!r) throw new O(400, { message: "Tenant ID not found in request" });
|
|
1956
2558
|
try {
|
|
1957
2559
|
let n = await e.databaseIsolation.getAdapters(r);
|
|
1958
2560
|
t.set("baseData", n), t.env = {
|
|
@@ -1960,39 +2562,39 @@ function Gt(e) {
|
|
|
1960
2562
|
data: n
|
|
1961
2563
|
};
|
|
1962
2564
|
} catch (e) {
|
|
1963
|
-
throw console.error(`Failed to resolve database for tenant ${r}:`, e), new
|
|
2565
|
+
throw console.error(`Failed to resolve database for tenant ${r}:`, e), new O(500, { message: "Failed to resolve tenant database" });
|
|
1964
2566
|
}
|
|
1965
2567
|
return n();
|
|
1966
2568
|
};
|
|
1967
2569
|
}
|
|
1968
|
-
function
|
|
1969
|
-
let t =
|
|
2570
|
+
function xn(e) {
|
|
2571
|
+
let t = yn(e), n = vn(e), r = bn(e);
|
|
1970
2572
|
return async (e, i) => (await t(e, async () => {}), await n(e, async () => {}), await r(e, async () => {}), i());
|
|
1971
2573
|
}
|
|
1972
2574
|
//#endregion
|
|
1973
2575
|
//#region src/rollouts/config.ts
|
|
1974
|
-
var
|
|
2576
|
+
var Sn = [
|
|
1975
2577
|
10,
|
|
1976
2578
|
50,
|
|
1977
2579
|
100
|
|
1978
|
-
],
|
|
2580
|
+
], X = {
|
|
1979
2581
|
canary: 1,
|
|
1980
|
-
waves:
|
|
2582
|
+
waves: Sn,
|
|
1981
2583
|
failure_threshold: .1,
|
|
1982
2584
|
max_concurrent: 25,
|
|
1983
2585
|
debounce_ms: 6e4
|
|
1984
2586
|
};
|
|
1985
|
-
function
|
|
2587
|
+
function Z(e) {
|
|
1986
2588
|
let t = e.config ?? {};
|
|
1987
2589
|
return {
|
|
1988
|
-
...
|
|
2590
|
+
...X,
|
|
1989
2591
|
trigger: "manual",
|
|
1990
2592
|
root_tenant_id: "",
|
|
1991
2593
|
...t,
|
|
1992
|
-
waves: Array.isArray(t.waves) && t.waves.length > 0 ? t.waves : [...
|
|
2594
|
+
waves: Array.isArray(t.waves) && t.waves.length > 0 ? t.waves : [...Sn]
|
|
1993
2595
|
};
|
|
1994
2596
|
}
|
|
1995
|
-
function
|
|
2597
|
+
function Cn(e, t, n) {
|
|
1996
2598
|
let r = Array(e).fill(0);
|
|
1997
2599
|
if (e === 0) return r;
|
|
1998
2600
|
let i = Math.min(Math.max(t, 0), e), a = [], o = i;
|
|
@@ -2010,8 +2612,8 @@ function Jt(e, t, n) {
|
|
|
2010
2612
|
}
|
|
2011
2613
|
//#endregion
|
|
2012
2614
|
//#region src/rollouts/enumerate.ts
|
|
2013
|
-
async function
|
|
2014
|
-
let r = n.maxDepth ?? 8, i = await
|
|
2615
|
+
async function wn(e, t, n) {
|
|
2616
|
+
let r = n.maxDepth ?? 8, i = await g((t) => e.tenants.list(t), "tenants", {
|
|
2015
2617
|
cursorField: "id",
|
|
2016
2618
|
pageSize: 100
|
|
2017
2619
|
}), a = new Map(i.map((e) => [e.id, e])), o = async (e) => e.parent_tenant_id ?? (e.id === t ? void 0 : await n.resolveLegacyParent(e.id)), s = [];
|
|
@@ -2037,19 +2639,19 @@ async function Yt(e, t, n) {
|
|
|
2037
2639
|
}
|
|
2038
2640
|
//#endregion
|
|
2039
2641
|
//#region src/rollouts/hashes.ts
|
|
2040
|
-
async function
|
|
2642
|
+
async function Q(e, t) {
|
|
2041
2643
|
return e.resolveControlPlane ? (await e.resolveControlPlane({ tenant_id: t }))?.tenantId : e.controlPlaneTenantId;
|
|
2042
2644
|
}
|
|
2043
|
-
function
|
|
2645
|
+
function Tn(e) {
|
|
2044
2646
|
let t = /* @__PURE__ */ new Map();
|
|
2045
2647
|
return async (n) => {
|
|
2046
|
-
let r = await
|
|
2648
|
+
let r = await Q(e, n), i = (await R({
|
|
2047
2649
|
tenantId: n,
|
|
2048
2650
|
getTenant: (t) => e.adapters.tenants.get(t),
|
|
2049
2651
|
legacyControlPlane: r,
|
|
2050
2652
|
maxDepth: e.maxDepth
|
|
2051
2653
|
})).join(">"), a = t.get(i);
|
|
2052
|
-
return a || (a =
|
|
2654
|
+
return a || (a = at(e.adapters, n, {
|
|
2053
2655
|
legacyControlPlane: r,
|
|
2054
2656
|
maxDepth: e.maxDepth
|
|
2055
2657
|
}).then((e) => e.hash), t.set(i, a)), a;
|
|
@@ -2057,13 +2659,13 @@ function Zt(e) {
|
|
|
2057
2659
|
}
|
|
2058
2660
|
//#endregion
|
|
2059
2661
|
//#region src/rollouts/plan.ts
|
|
2060
|
-
var
|
|
2662
|
+
var En = [
|
|
2061
2663
|
"pending",
|
|
2062
2664
|
"canary",
|
|
2063
2665
|
"rolling",
|
|
2064
2666
|
"paused"
|
|
2065
2667
|
];
|
|
2066
|
-
function
|
|
2668
|
+
function Dn(e) {
|
|
2067
2669
|
let { tenantOperations: t, tenantOperationEvents: n } = e.adapters;
|
|
2068
2670
|
if (!t || !n) throw Error("Fleet rollouts need the tenant operations adapters");
|
|
2069
2671
|
return {
|
|
@@ -2071,20 +2673,20 @@ function $t(e) {
|
|
|
2071
2673
|
tenantOperationEvents: n
|
|
2072
2674
|
};
|
|
2073
2675
|
}
|
|
2074
|
-
function
|
|
2676
|
+
function $(e) {
|
|
2075
2677
|
if (!e.adapters.rollouts) throw Error("Fleet rollouts need the rollouts adapter");
|
|
2076
2678
|
return e.adapters.rollouts;
|
|
2077
2679
|
}
|
|
2078
|
-
async function
|
|
2079
|
-
let r =
|
|
2080
|
-
resolveLegacyParent: (t) =>
|
|
2680
|
+
async function On(e, t, n = {}) {
|
|
2681
|
+
let r = $(e), i = Dn(e), a = Z(t), o = await wn(e.adapters, a.root_tenant_id, {
|
|
2682
|
+
resolveLegacyParent: (t) => Q(e, t),
|
|
2081
2683
|
maxDepth: e.maxDepth
|
|
2082
2684
|
});
|
|
2083
2685
|
if (n.tenantIds) {
|
|
2084
2686
|
let e = new Set(n.tenantIds);
|
|
2085
2687
|
o = o.filter((t) => e.has(t.tenantId));
|
|
2086
2688
|
}
|
|
2087
|
-
let s =
|
|
2689
|
+
let s = Tn(e), c = [];
|
|
2088
2690
|
for (let e of o) (a.force || e.appliedHash !== await s(e.tenantId)) && c.push(e);
|
|
2089
2691
|
let l = o.length - c.length;
|
|
2090
2692
|
if (c.length === 0) return a.trigger === "write" ? await r.remove(t.id) : await r.update(t.id, {
|
|
@@ -2099,8 +2701,8 @@ async function en(e, t, n = {}) {
|
|
|
2099
2701
|
planned: 0,
|
|
2100
2702
|
upToDate: l
|
|
2101
2703
|
};
|
|
2102
|
-
let u = new Set((await
|
|
2103
|
-
for (let [n, r] of c.entries()) u.has(r.tenantId) || await
|
|
2704
|
+
let u = new Set((await kn(e, t.id)).map((e) => e.tenant_id)), d = Cn(c.length, a.canary, a.waves);
|
|
2705
|
+
for (let [n, r] of c.entries()) u.has(r.tenantId) || await se(i, {
|
|
2104
2706
|
kind: "sync-defaults",
|
|
2105
2707
|
tenant_id: r.tenantId,
|
|
2106
2708
|
rollout_id: t.id,
|
|
@@ -2123,8 +2725,8 @@ async function en(e, t, n = {}) {
|
|
|
2123
2725
|
upToDate: l
|
|
2124
2726
|
};
|
|
2125
2727
|
}
|
|
2126
|
-
async function
|
|
2127
|
-
let { tenantOperations: n } =
|
|
2728
|
+
async function kn(e, t) {
|
|
2729
|
+
let { tenantOperations: n } = Dn(e), r = [];
|
|
2128
2730
|
for (let e = 0;; e++) {
|
|
2129
2731
|
let { operations: i } = await n.list({
|
|
2130
2732
|
rollout_id: t,
|
|
@@ -2137,45 +2739,45 @@ async function Q(e, t) {
|
|
|
2137
2739
|
}
|
|
2138
2740
|
//#endregion
|
|
2139
2741
|
//#region src/rollouts/advance.ts
|
|
2140
|
-
var
|
|
2742
|
+
var An = (e) => {
|
|
2141
2743
|
let t = e.input?.wave;
|
|
2142
2744
|
return typeof t == "number" ? t : 0;
|
|
2143
|
-
},
|
|
2144
|
-
function
|
|
2145
|
-
let r = t.filter((e) =>
|
|
2745
|
+
}, jn = (e) => e.status === "failed" || e.status === "cancelled";
|
|
2746
|
+
function Mn(e, t, n) {
|
|
2747
|
+
let r = t.filter((e) => An(e) === n), i = r.filter(jn).length, a = n === 0 && e.canary > 0, o = a ? 0 : e.failure_threshold;
|
|
2146
2748
|
return r.length === 0 || i === 0 || i / r.length <= o ? null : `${a ? "canary" : `wave ${n}`} failed for ${i} of ${r.length} tenant(s)`;
|
|
2147
2749
|
}
|
|
2148
|
-
async function
|
|
2149
|
-
let n =
|
|
2750
|
+
async function Nn(e, t) {
|
|
2751
|
+
let n = $(e), r = e.now?.() ?? Date.now(), i = typeof t == "string" ? await n.get(t) : t;
|
|
2150
2752
|
if (!i || i.kind !== "config-sync") return {
|
|
2151
2753
|
rolloutId: String(i?.id ?? t),
|
|
2152
2754
|
outcome: "skipped",
|
|
2153
2755
|
started: 0
|
|
2154
2756
|
};
|
|
2155
2757
|
let a = i.id;
|
|
2156
|
-
if (!
|
|
2758
|
+
if (!En.includes(i.status) || i.status === "paused") return {
|
|
2157
2759
|
rolloutId: a,
|
|
2158
2760
|
outcome: "skipped",
|
|
2159
2761
|
started: 0
|
|
2160
2762
|
};
|
|
2161
|
-
let o =
|
|
2763
|
+
let o = Z(i);
|
|
2162
2764
|
if (!o.planned) {
|
|
2163
2765
|
if (r - Date.parse(i.updated_at) < o.debounce_ms) return {
|
|
2164
2766
|
rolloutId: a,
|
|
2165
2767
|
outcome: "waiting",
|
|
2166
2768
|
started: 0
|
|
2167
2769
|
};
|
|
2168
|
-
let { planned: t } = await
|
|
2770
|
+
let { planned: t } = await On(e, i);
|
|
2169
2771
|
if (t === 0) return {
|
|
2170
2772
|
rolloutId: a,
|
|
2171
2773
|
outcome: "planned-empty",
|
|
2172
2774
|
started: 0
|
|
2173
2775
|
};
|
|
2174
|
-
i = await n.get(a) ?? i, o =
|
|
2776
|
+
i = await n.get(a) ?? i, o = Z(i);
|
|
2175
2777
|
}
|
|
2176
|
-
let s = await
|
|
2778
|
+
let s = await kn(e, a), c = s.filter((e) => !L(e.status));
|
|
2177
2779
|
if (c.length === 0) {
|
|
2178
|
-
let e = Math.max(0, ...s.map(
|
|
2780
|
+
let e = Math.max(0, ...s.map(An)), t = s.length > 0 && e > (o.accepted_through ?? -1) ? Mn(o, s, e) : null;
|
|
2179
2781
|
return await n.update(a, {
|
|
2180
2782
|
status: t ? "failed" : "done",
|
|
2181
2783
|
...t ? { paused_reason: t } : {},
|
|
@@ -2186,9 +2788,9 @@ async function rn(e, t) {
|
|
|
2186
2788
|
started: 0
|
|
2187
2789
|
};
|
|
2188
2790
|
}
|
|
2189
|
-
let l = Math.min(...c.map(
|
|
2791
|
+
let l = Math.min(...c.map(An)), u = l - 1;
|
|
2190
2792
|
if (u >= 0 && u > (o.accepted_through ?? -1)) {
|
|
2191
|
-
let e =
|
|
2793
|
+
let e = Mn(o, s, u);
|
|
2192
2794
|
if (e) return await n.update(a, {
|
|
2193
2795
|
status: "paused",
|
|
2194
2796
|
paused_reason: e
|
|
@@ -2201,7 +2803,7 @@ async function rn(e, t) {
|
|
|
2201
2803
|
}
|
|
2202
2804
|
let d = l === 0 ? "canary" : "rolling";
|
|
2203
2805
|
i.status !== d && await n.update(a, { status: d });
|
|
2204
|
-
let f = c.filter((e) =>
|
|
2806
|
+
let f = c.filter((e) => An(e) === l), p = f.filter((e) => e.status === "running").length, m = Math.max(0, o.max_concurrent - p), { tenantOperations: h, tenantOperationEvents: g } = Dn(e), _ = I({
|
|
2205
2807
|
tenantOperations: h,
|
|
2206
2808
|
tenantOperationEvents: g
|
|
2207
2809
|
}), v = 0;
|
|
@@ -2211,7 +2813,7 @@ async function rn(e, t) {
|
|
|
2211
2813
|
} catch (e) {
|
|
2212
2814
|
try {
|
|
2213
2815
|
let n = await h.get(t.id);
|
|
2214
|
-
n && !
|
|
2816
|
+
n && !L(n.status) && await _.markFailed(t.id, e);
|
|
2215
2817
|
} catch {}
|
|
2216
2818
|
}
|
|
2217
2819
|
v++;
|
|
@@ -2223,8 +2825,8 @@ async function rn(e, t) {
|
|
|
2223
2825
|
wave: l
|
|
2224
2826
|
};
|
|
2225
2827
|
}
|
|
2226
|
-
async function
|
|
2227
|
-
let { rollouts: n } = await
|
|
2828
|
+
async function Pn(e, t = {}) {
|
|
2829
|
+
let { rollouts: n } = await $(e).list({
|
|
2228
2830
|
kind: "config-sync",
|
|
2229
2831
|
status: [
|
|
2230
2832
|
"pending",
|
|
@@ -2234,24 +2836,24 @@ async function an(e, t = {}) {
|
|
|
2234
2836
|
per_page: t.limit ?? 20
|
|
2235
2837
|
}), r = [];
|
|
2236
2838
|
for (let i of n) try {
|
|
2237
|
-
r.push(await
|
|
2839
|
+
r.push(await Nn(e, i));
|
|
2238
2840
|
} catch (e) {
|
|
2239
2841
|
t.logger?.warn(`Advancing rollout ${i.id} failed:`, e);
|
|
2240
2842
|
}
|
|
2241
2843
|
return r;
|
|
2242
2844
|
}
|
|
2243
|
-
async function
|
|
2244
|
-
let r =
|
|
2845
|
+
async function Fn(e, t, n = "paused by an operator") {
|
|
2846
|
+
let r = $(e), i = await r.get(t);
|
|
2245
2847
|
return !i || i.kind !== "config-sync" ? null : i.status === "done" || i.status === "failed" ? i : (await r.update(t, {
|
|
2246
2848
|
status: "paused",
|
|
2247
2849
|
paused_reason: n
|
|
2248
2850
|
}), r.get(t));
|
|
2249
2851
|
}
|
|
2250
|
-
async function
|
|
2251
|
-
let n =
|
|
2852
|
+
async function In(e, t) {
|
|
2853
|
+
let n = $(e), r = await n.get(t);
|
|
2252
2854
|
if (!r || r.kind !== "config-sync") return null;
|
|
2253
2855
|
if (r.status !== "paused") return r;
|
|
2254
|
-
let i =
|
|
2856
|
+
let i = Z(r), a = (await kn(e, t)).filter((e) => !L(e.status)), o = a.length > 0 ? Math.min(...a.map(An)) : 0;
|
|
2255
2857
|
return await n.update(t, {
|
|
2256
2858
|
status: o === 0 ? "canary" : "rolling",
|
|
2257
2859
|
paused_reason: null,
|
|
@@ -2262,21 +2864,110 @@ async function sn(e, t) {
|
|
|
2262
2864
|
}), n.get(t);
|
|
2263
2865
|
}
|
|
2264
2866
|
//#endregion
|
|
2867
|
+
//#region src/rollouts/verify.ts
|
|
2868
|
+
var Ln = {
|
|
2869
|
+
added: "missing",
|
|
2870
|
+
changed: "changed",
|
|
2871
|
+
delete: "stale"
|
|
2872
|
+
};
|
|
2873
|
+
function Rn(e) {
|
|
2874
|
+
return (e.rows ?? e.changes.flatMap((e) => {
|
|
2875
|
+
if (e.startsWith("skip ")) return [];
|
|
2876
|
+
let t = /^delete ([^:\s]+):(.*)$/.exec(e);
|
|
2877
|
+
if (t) return [{
|
|
2878
|
+
entity: t[1],
|
|
2879
|
+
key: t[2],
|
|
2880
|
+
action: "delete"
|
|
2881
|
+
}];
|
|
2882
|
+
let n = /^([^:\s]+):(.*)$/.exec(e);
|
|
2883
|
+
return n ? [{
|
|
2884
|
+
entity: n[1],
|
|
2885
|
+
key: n[2],
|
|
2886
|
+
action: "changed"
|
|
2887
|
+
}] : [];
|
|
2888
|
+
})).flatMap((e) => {
|
|
2889
|
+
let t = Ln[e.action];
|
|
2890
|
+
return t ? [{
|
|
2891
|
+
entity: e.entity,
|
|
2892
|
+
key: e.key,
|
|
2893
|
+
kind: t
|
|
2894
|
+
}] : [];
|
|
2895
|
+
});
|
|
2896
|
+
}
|
|
2897
|
+
async function zn(e, t) {
|
|
2898
|
+
let n = await e.adapters.tenants.get(t);
|
|
2899
|
+
if (!n) return null;
|
|
2900
|
+
let r = n.config_sync ?? "inherit-on-read", i = {
|
|
2901
|
+
tenant_id: t,
|
|
2902
|
+
config_sync: r,
|
|
2903
|
+
errors: []
|
|
2904
|
+
};
|
|
2905
|
+
if (r === "detached") return {
|
|
2906
|
+
...i,
|
|
2907
|
+
method: "not-applicable",
|
|
2908
|
+
ok: !0,
|
|
2909
|
+
differences: []
|
|
2910
|
+
};
|
|
2911
|
+
if (r === "inherit-on-read") {
|
|
2912
|
+
let n = (await De({
|
|
2913
|
+
adapters: e.adapters,
|
|
2914
|
+
tenantId: t,
|
|
2915
|
+
legacyControlPlane: await Q(e, t),
|
|
2916
|
+
maxDepth: e.maxDepth
|
|
2917
|
+
})).filter((e) => !e.expected).map((e) => ({
|
|
2918
|
+
entity: e.entity,
|
|
2919
|
+
key: e.key,
|
|
2920
|
+
kind: e.kind,
|
|
2921
|
+
...e.fields.length > 0 ? { fields: e.fields } : {}
|
|
2922
|
+
}));
|
|
2923
|
+
return {
|
|
2924
|
+
...i,
|
|
2925
|
+
method: "read-time",
|
|
2926
|
+
ok: n.length === 0,
|
|
2927
|
+
differences: n
|
|
2928
|
+
};
|
|
2929
|
+
}
|
|
2930
|
+
let a = await e.syncConfig(t, {
|
|
2931
|
+
dryRun: !0,
|
|
2932
|
+
force: !1,
|
|
2933
|
+
prune: !1
|
|
2934
|
+
}), o = Rn(a), s = Object.entries(a.entities).filter(([, e]) => e.errors.length > 0).map(([e, t]) => `${e}: the sync dry run reported ${t.errors.length} error(s)`);
|
|
2935
|
+
return {
|
|
2936
|
+
...i,
|
|
2937
|
+
method: "sync-dry-run",
|
|
2938
|
+
ok: o.length === 0 && s.length === 0,
|
|
2939
|
+
differences: o,
|
|
2940
|
+
errors: s.slice(0, 20)
|
|
2941
|
+
};
|
|
2942
|
+
}
|
|
2943
|
+
//#endregion
|
|
2265
2944
|
//#region src/rollouts/status.ts
|
|
2266
|
-
async function
|
|
2945
|
+
async function Bn(e, t) {
|
|
2267
2946
|
let n = await e.adapters.tenants.get(t);
|
|
2268
2947
|
if (!n) return null;
|
|
2269
|
-
|
|
2948
|
+
if (n.config_sync === "detached") return {
|
|
2949
|
+
tenant_id: t,
|
|
2950
|
+
parent_tenant_id: null,
|
|
2951
|
+
config_sync: "detached",
|
|
2952
|
+
config_sync_hash: null,
|
|
2953
|
+
config_synced_at: null,
|
|
2954
|
+
expected_hash: null,
|
|
2955
|
+
drifted: !1,
|
|
2956
|
+
chain: [],
|
|
2957
|
+
inherited: {}
|
|
2958
|
+
};
|
|
2959
|
+
let r = n.config_sync === "synced", i = await R({
|
|
2270
2960
|
tenantId: t,
|
|
2271
2961
|
getTenant: (t) => e.adapters.tenants.get(t),
|
|
2272
|
-
legacyControlPlane: await
|
|
2962
|
+
legacyControlPlane: await Q(e, t),
|
|
2273
2963
|
maxDepth: e.maxDepth
|
|
2274
|
-
}), a = r ? await
|
|
2964
|
+
}), a = r ? await Tn(e)(t) : null, o = n.config_sync_hash ?? null, s = {};
|
|
2275
2965
|
for (let n of [...i].reverse()) {
|
|
2276
|
-
let r = await
|
|
2966
|
+
let r = await V(e.adapters, n), i = (e, t) => U(e, t) === "shared", a = async (e, r, a) => {
|
|
2277
2967
|
for (let o of r) {
|
|
2278
|
-
|
|
2279
|
-
|
|
2968
|
+
if (!i(a, o)) continue;
|
|
2969
|
+
let r = await it(e, t, W(e, o)), c = o.id ?? o.hook_id;
|
|
2970
|
+
c && x(c) && s[r] || (s[r] = n);
|
|
2280
2971
|
}
|
|
2281
2972
|
};
|
|
2282
2973
|
await a("connection", r.connections, "connection"), await a("resourceServer", r.resourceServers, "resourceServer"), await a("action", r.actions, "action"), await a("hook", r.hooks, "hook"), r.emailProvider && i("emailProvider", r.emailProvider) && (s.emailProvider = n), r.branding && i("branding", r.branding) && (s.branding = n), r.promptSettings && i("promptSettings", r.promptSettings) && (s.promptSettings = n);
|
|
@@ -2295,11 +2986,11 @@ async function cn(e, t) {
|
|
|
2295
2986
|
}
|
|
2296
2987
|
//#endregion
|
|
2297
2988
|
//#region src/rollouts/reconcile.ts
|
|
2298
|
-
async function
|
|
2299
|
-
let r =
|
|
2300
|
-
resolveLegacyParent: (t) =>
|
|
2989
|
+
async function Vn(e, n = {}) {
|
|
2990
|
+
let r = $(e), i = n.rootTenantId ?? e.controlPlaneTenantId, a = n.limit ?? 500, o = await wn(e.adapters, i, {
|
|
2991
|
+
resolveLegacyParent: (t) => Q(e, t),
|
|
2301
2992
|
maxDepth: e.maxDepth
|
|
2302
|
-
}), s =
|
|
2993
|
+
}), s = Tn(e), c = [];
|
|
2303
2994
|
for (let e of o) {
|
|
2304
2995
|
if (c.length >= a) break;
|
|
2305
2996
|
try {
|
|
@@ -2322,10 +3013,10 @@ async function ln(e, n = {}) {
|
|
|
2322
3013
|
if (c.length === 0) return l;
|
|
2323
3014
|
let u = /* @__PURE__ */ new Set(), { rollouts: d } = await r.list({
|
|
2324
3015
|
kind: "config-sync",
|
|
2325
|
-
status: [...
|
|
3016
|
+
status: [...En],
|
|
2326
3017
|
per_page: 100
|
|
2327
3018
|
});
|
|
2328
|
-
for (let t of d) for (let n of await
|
|
3019
|
+
for (let t of d) for (let n of await kn(e, t.id)) n.tenant_id && !L(n.status) && u.add(n.tenant_id);
|
|
2329
3020
|
for (let r of c) try {
|
|
2330
3021
|
await e.adapters.logs.create(r.tenantId, {
|
|
2331
3022
|
type: t.CONFIG_DRIFT,
|
|
@@ -2345,7 +3036,7 @@ async function ln(e, n = {}) {
|
|
|
2345
3036
|
}
|
|
2346
3037
|
let f = c.filter((e) => !u.has(e.tenantId));
|
|
2347
3038
|
l.alreadyCovered = c.length - f.length;
|
|
2348
|
-
let { tenantOperations: p } =
|
|
3039
|
+
let { tenantOperations: p } = Dn(e), m = e.now?.() ?? Date.now(), h = n.retryAfterMs ?? 36e5, g = [];
|
|
2349
3040
|
for (let e of f) {
|
|
2350
3041
|
try {
|
|
2351
3042
|
let { operations: t } = await p.list({
|
|
@@ -2367,33 +3058,33 @@ async function ln(e, n = {}) {
|
|
|
2367
3058
|
kind: "config-sync",
|
|
2368
3059
|
initiated_by: "reconcile",
|
|
2369
3060
|
config: {
|
|
2370
|
-
...
|
|
3061
|
+
...X,
|
|
2371
3062
|
trigger: "reconcile",
|
|
2372
3063
|
root_tenant_id: i,
|
|
2373
3064
|
planned: !1
|
|
2374
3065
|
}
|
|
2375
3066
|
});
|
|
2376
|
-
return await
|
|
3067
|
+
return await On(e, _, { tenantIds: g.map((e) => e.tenantId) }), l.rolloutId = _.id, l;
|
|
2377
3068
|
}
|
|
2378
3069
|
//#endregion
|
|
2379
3070
|
//#region src/rollouts/trigger.ts
|
|
2380
|
-
function
|
|
2381
|
-
return e === "hookCode" ? !0 : !t || typeof t != "object" ? !1 :
|
|
3071
|
+
function Hn(e, t) {
|
|
3072
|
+
return e === "hookCode" ? !0 : !t || typeof t != "object" ? !1 : U(e, t) !== "local";
|
|
2382
3073
|
}
|
|
2383
|
-
async function
|
|
2384
|
-
let r =
|
|
3074
|
+
async function Un(e, t, n) {
|
|
3075
|
+
let r = $(e), { rollouts: i } = await r.list({
|
|
2385
3076
|
kind: "config-sync",
|
|
2386
3077
|
status: "pending",
|
|
2387
3078
|
per_page: 100
|
|
2388
3079
|
}), a = i.find((e) => {
|
|
2389
|
-
let n =
|
|
3080
|
+
let n = Z(e);
|
|
2390
3081
|
return n.trigger === "write" && n.planned !== !0 && n.origin_tenant_id === t;
|
|
2391
3082
|
});
|
|
2392
3083
|
return a ? (await r.update(a.id, {}), await r.get(a.id) ?? a) : r.create({
|
|
2393
3084
|
kind: "config-sync",
|
|
2394
3085
|
initiated_by: n ?? `write:${t}`,
|
|
2395
3086
|
config: {
|
|
2396
|
-
...
|
|
3087
|
+
...X,
|
|
2397
3088
|
trigger: "write",
|
|
2398
3089
|
root_tenant_id: t,
|
|
2399
3090
|
origin_tenant_id: t,
|
|
@@ -2401,7 +3092,7 @@ async function dn(e, t, n) {
|
|
|
2401
3092
|
}
|
|
2402
3093
|
});
|
|
2403
3094
|
}
|
|
2404
|
-
async function
|
|
3095
|
+
async function Wn(e, t) {
|
|
2405
3096
|
if (t === e.controlPlaneTenantId) return !0;
|
|
2406
3097
|
try {
|
|
2407
3098
|
let { tenants: n } = await e.adapters.tenants.list({
|
|
@@ -2413,19 +3104,19 @@ async function fn(e, t) {
|
|
|
2413
3104
|
return !0;
|
|
2414
3105
|
}
|
|
2415
3106
|
}
|
|
2416
|
-
function
|
|
3107
|
+
function Gn(e, t = {}) {
|
|
2417
3108
|
let n = async (n) => {
|
|
2418
3109
|
try {
|
|
2419
|
-
await
|
|
3110
|
+
await Wn(e, n) && await Un(e, n);
|
|
2420
3111
|
} catch (e) {
|
|
2421
3112
|
t.logger?.warn(`Could not record a config change for ${n}:`, e);
|
|
2422
3113
|
}
|
|
2423
3114
|
}, r = (e) => ({
|
|
2424
3115
|
afterCreate: async (t, r) => {
|
|
2425
|
-
|
|
3116
|
+
Hn(e, r) && await n(t.tenantId);
|
|
2426
3117
|
},
|
|
2427
3118
|
afterUpdate: async (t, r, i) => {
|
|
2428
|
-
|
|
3119
|
+
Hn(e, i) && await n(t.tenantId);
|
|
2429
3120
|
},
|
|
2430
3121
|
afterDelete: async (e) => n(e.tenantId)
|
|
2431
3122
|
});
|
|
@@ -2439,79 +3130,89 @@ function pn(e, t = {}) {
|
|
|
2439
3130
|
}
|
|
2440
3131
|
//#endregion
|
|
2441
3132
|
//#region src/rollouts/controller.ts
|
|
2442
|
-
function
|
|
3133
|
+
function Kn(e) {
|
|
2443
3134
|
return {
|
|
2444
3135
|
async create(t) {
|
|
2445
3136
|
let n = {
|
|
2446
|
-
...
|
|
2447
|
-
waves: t.waves ?? [...
|
|
2448
|
-
canary: t.canary ??
|
|
2449
|
-
failure_threshold: t.failureThreshold ??
|
|
2450
|
-
max_concurrent: t.maxConcurrent ??
|
|
3137
|
+
...X,
|
|
3138
|
+
waves: t.waves ?? [...X.waves],
|
|
3139
|
+
canary: t.canary ?? X.canary,
|
|
3140
|
+
failure_threshold: t.failureThreshold ?? X.failure_threshold,
|
|
3141
|
+
max_concurrent: t.maxConcurrent ?? X.max_concurrent,
|
|
2451
3142
|
trigger: "manual",
|
|
2452
3143
|
root_tenant_id: t.rootTenantId ?? e.controlPlaneTenantId,
|
|
2453
3144
|
dry_run: t.dryRun,
|
|
2454
3145
|
force: t.force,
|
|
2455
3146
|
planned: !1
|
|
2456
|
-
}, r =
|
|
3147
|
+
}, r = $(e), i = await r.create({
|
|
2457
3148
|
kind: "config-sync",
|
|
2458
3149
|
initiated_by: t.initiatedBy,
|
|
2459
3150
|
config: n
|
|
2460
3151
|
});
|
|
2461
|
-
return await
|
|
3152
|
+
return await On(e, i, { tenantIds: t.tenantIds }), await Nn(e, i.id), await r.get(i.id) ?? i;
|
|
2462
3153
|
},
|
|
2463
|
-
pause: (t, n) =>
|
|
2464
|
-
resume: (t) =>
|
|
3154
|
+
pause: (t, n) => Fn(e, t, n),
|
|
3155
|
+
resume: (t) => In(e, t)
|
|
2465
3156
|
};
|
|
2466
3157
|
}
|
|
2467
3158
|
//#endregion
|
|
2468
3159
|
//#region src/init.ts
|
|
2469
|
-
function
|
|
2470
|
-
let { dataAdapter: t, controlPlane: n, controlPlane: { tenantId: r = "control_plane", clientId: i } = {}, resolveControlPlane: a, inheritanceShadow: o, syncDefaults: s,
|
|
3160
|
+
function qn(e) {
|
|
3161
|
+
let { dataAdapter: t, controlPlane: n, controlPlane: { tenantId: r = "control_plane", clientId: i } = {}, resolveControlPlane: a, inheritanceShadow: o, syncDefaults: s, detachTenant: c, tenantMemberRequests: l, rolloutExecutor: u, sync: d = {
|
|
2471
3162
|
resourceServers: !0,
|
|
2472
3163
|
roles: !0
|
|
2473
|
-
}, defaultPermissions:
|
|
3164
|
+
}, defaultPermissions: f = ["tenant:admin"], requireOrganizationMatch: p = !1, managementApiExtensions: m = [], entityHooks: h, getChildTenantIds: _, getAdapters: v, ...b } = e;
|
|
2474
3165
|
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.");
|
|
2475
|
-
let
|
|
3166
|
+
let x = t, S = t, C;
|
|
2476
3167
|
if (n) {
|
|
2477
|
-
let
|
|
3168
|
+
let n = Me({
|
|
2478
3169
|
base: Re({
|
|
2479
3170
|
controlPlaneTenantId: r,
|
|
2480
3171
|
controlPlaneClientId: i,
|
|
2481
3172
|
resolveControlPlane: a
|
|
2482
3173
|
}),
|
|
2483
3174
|
getTenant: async (e) => await t.tenants.get(e) ?? null,
|
|
2484
|
-
controlPlaneTenantId: r
|
|
3175
|
+
controlPlaneTenantId: r,
|
|
3176
|
+
ttlMs: e.configSyncCacheTtlMs
|
|
2485
3177
|
});
|
|
2486
|
-
|
|
3178
|
+
C = (e) => n.invalidate(e), x = We(t, {
|
|
2487
3179
|
controlPlaneTenantId: r,
|
|
2488
3180
|
controlPlaneClientId: i,
|
|
2489
3181
|
resolveControlPlane: a,
|
|
2490
3182
|
inheritanceShadow: o,
|
|
2491
|
-
configSync:
|
|
2492
|
-
}),
|
|
3183
|
+
configSync: n
|
|
3184
|
+
}), S = {
|
|
2493
3185
|
...Be(t, {
|
|
2494
3186
|
controlPlaneTenantId: r,
|
|
2495
|
-
resolveControlPlane:
|
|
3187
|
+
resolveControlPlane: n.resolve
|
|
2496
3188
|
}),
|
|
2497
3189
|
multiTenancyConfig: {
|
|
2498
3190
|
controlPlaneTenantId: r,
|
|
2499
3191
|
controlPlaneClientId: i,
|
|
2500
|
-
resolveControlPlane:
|
|
3192
|
+
resolveControlPlane: n.resolve
|
|
2501
3193
|
}
|
|
2502
3194
|
};
|
|
2503
3195
|
}
|
|
2504
|
-
let
|
|
3196
|
+
let w = b.tenantOperationExecutor, T, E;
|
|
2505
3197
|
if (t.tenantOperations && t.tenantOperationEvents) {
|
|
2506
3198
|
let e = {
|
|
2507
3199
|
tenantOperations: t.tenantOperations,
|
|
2508
3200
|
tenantOperationEvents: t.tenantOperationEvents
|
|
2509
|
-
}, n =
|
|
3201
|
+
}, n = b.tenantUpgrade, i = I(e), o = s ?? xt(t, {
|
|
2510
3202
|
controlPlaneTenantId: r,
|
|
2511
3203
|
resolveControlPlane: a
|
|
2512
|
-
}), c =
|
|
3204
|
+
}), u = c ?? Mt(t), d = l ? l.store ?? Ft(t) : void 0, f = oe({
|
|
2513
3205
|
stores: e,
|
|
2514
3206
|
definitions: {
|
|
3207
|
+
detach: (e) => [{
|
|
3208
|
+
name: "detach",
|
|
3209
|
+
run: () => Dt({
|
|
3210
|
+
operation: e,
|
|
3211
|
+
detachTenant: u,
|
|
3212
|
+
recorder: i,
|
|
3213
|
+
onDetached: (e) => C?.(e)
|
|
3214
|
+
})
|
|
3215
|
+
}],
|
|
2515
3216
|
...n ? { upgrade: (e) => [{
|
|
2516
3217
|
name: "upgrade",
|
|
2517
3218
|
async run() {
|
|
@@ -2521,113 +3222,157 @@ function hn(e) {
|
|
|
2521
3222
|
}] } : {},
|
|
2522
3223
|
"sync-defaults": (e) => [{
|
|
2523
3224
|
name: "sync-defaults",
|
|
2524
|
-
run: () =>
|
|
3225
|
+
run: () => bt({
|
|
2525
3226
|
operation: e,
|
|
2526
3227
|
syncConfig: o,
|
|
2527
3228
|
recorder: i
|
|
2528
3229
|
})
|
|
2529
|
-
}]
|
|
3230
|
+
}],
|
|
3231
|
+
...d && l ? { "tenant-members-request": (e) => [{
|
|
3232
|
+
name: "tenant-members-request",
|
|
3233
|
+
run: () => Rt({
|
|
3234
|
+
operation: e,
|
|
3235
|
+
store: d,
|
|
3236
|
+
getBackend: l.getBackend,
|
|
3237
|
+
recorder: i,
|
|
3238
|
+
executeOptions: { isRequesterAllowed: l.isRequesterAllowed }
|
|
3239
|
+
})
|
|
3240
|
+
}] } : {}
|
|
2530
3241
|
}
|
|
2531
3242
|
});
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
3243
|
+
if (T = f, d) {
|
|
3244
|
+
let n = {
|
|
3245
|
+
stores: e,
|
|
3246
|
+
executor: f
|
|
3247
|
+
};
|
|
3248
|
+
E = {
|
|
3249
|
+
enqueue: (e, t) => Bt(n, e, t),
|
|
3250
|
+
reconcile: (e = {}) => Vt({
|
|
3251
|
+
...n,
|
|
3252
|
+
store: d,
|
|
3253
|
+
tenantIds: e.tenantIds ?? (async () => (await g((e) => t.tenants.list(e), "tenants", {
|
|
3254
|
+
cursorField: "id",
|
|
3255
|
+
pageSize: 100
|
|
3256
|
+
})).map((e) => e.id).filter((e) => e !== r)),
|
|
3257
|
+
graceMs: e.graceMs,
|
|
3258
|
+
maxAttempts: e.maxAttempts
|
|
3259
|
+
})
|
|
3260
|
+
};
|
|
3261
|
+
}
|
|
3262
|
+
w ??= {
|
|
3263
|
+
engine: f.engine,
|
|
3264
|
+
kinds: n ? [
|
|
3265
|
+
"upgrade",
|
|
3266
|
+
"sync-defaults",
|
|
3267
|
+
"detach"
|
|
3268
|
+
] : ["sync-defaults", "detach"],
|
|
3269
|
+
enqueue: (t) => ce(e, f, {
|
|
2536
3270
|
...t,
|
|
2537
3271
|
tenant_id: t.tenant_id
|
|
2538
|
-
}, { returnFailed: t.kind === "sync-defaults" })
|
|
3272
|
+
}, { returnFailed: t.kind === "sync-defaults" || t.kind === "detach" })
|
|
2539
3273
|
};
|
|
2540
3274
|
}
|
|
2541
|
-
|
|
3275
|
+
if (l && !E) throw Error("initMultiTenant: `tenantMemberRequests` requires the `tenantOperations` and `tenantOperationEvents` adapters on the data adapter, which run the `tenant-members-request` operation.");
|
|
3276
|
+
let D = u ?? T, O = D && t.rollouts && t.tenantOperations && t.tenantOperationEvents ? {
|
|
2542
3277
|
adapters: t,
|
|
2543
|
-
executor:
|
|
3278
|
+
executor: D,
|
|
2544
3279
|
controlPlaneTenantId: r,
|
|
2545
3280
|
resolveControlPlane: a
|
|
2546
|
-
} : void 0,
|
|
2547
|
-
resourceServers:
|
|
2548
|
-
roles:
|
|
3281
|
+
} : void 0, k = O ? Kn(O) : void 0, A = O ? Gn(O, { logger: console }) : void 0, j = d !== !1, ee = j ? {
|
|
3282
|
+
resourceServers: d.resourceServers ?? !0,
|
|
3283
|
+
roles: d.roles ?? !0
|
|
2549
3284
|
} : {
|
|
2550
3285
|
resourceServers: !1,
|
|
2551
3286
|
roles: !1
|
|
2552
|
-
}, { entityHooks:
|
|
3287
|
+
}, { entityHooks: M, tenantHooks: N } = Qt({
|
|
2553
3288
|
controlPlaneTenantId: r,
|
|
2554
|
-
getChildTenantIds:
|
|
3289
|
+
getChildTenantIds: _ ?? (async () => (await g((e) => x.tenants.list(e), "tenants", {
|
|
2555
3290
|
cursorField: "id",
|
|
2556
3291
|
pageSize: 100
|
|
2557
3292
|
})).filter((e) => e.id !== r).map((e) => e.id)),
|
|
2558
|
-
getAdapters:
|
|
2559
|
-
getControlPlaneAdapters: async () =>
|
|
2560
|
-
sync:
|
|
2561
|
-
}),
|
|
3293
|
+
getAdapters: v ?? (async () => x),
|
|
3294
|
+
getControlPlaneAdapters: async () => x,
|
|
3295
|
+
sync: ee
|
|
3296
|
+
}), te = {
|
|
2562
3297
|
resourceServers: [
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
...
|
|
3298
|
+
M.resourceServers,
|
|
3299
|
+
A?.resourceServers,
|
|
3300
|
+
...h?.resourceServers ?? []
|
|
2566
3301
|
],
|
|
2567
|
-
roles: [
|
|
2568
|
-
connections: [
|
|
2569
|
-
tenants:
|
|
2570
|
-
rolePermissions:
|
|
2571
|
-
actions: [
|
|
2572
|
-
hooks: [
|
|
2573
|
-
hookCode: [
|
|
2574
|
-
},
|
|
3302
|
+
roles: [M.roles, ...h?.roles ?? []],
|
|
3303
|
+
connections: [A?.connections, ...h?.connections ?? []],
|
|
3304
|
+
tenants: h?.tenants ?? [],
|
|
3305
|
+
rolePermissions: h?.rolePermissions ?? [],
|
|
3306
|
+
actions: [A?.actions, ...h?.actions ?? []],
|
|
3307
|
+
hooks: [A?.hooks, ...h?.hooks ?? []],
|
|
3308
|
+
hookCode: [A?.hookCode, ...h?.hookCode ?? []]
|
|
3309
|
+
}, P = Ut({ accessControl: {
|
|
2575
3310
|
controlPlaneTenantId: r,
|
|
2576
|
-
requireOrganizationMatch:
|
|
2577
|
-
defaultPermissions:
|
|
2578
|
-
} }),
|
|
3311
|
+
requireOrganizationMatch: p,
|
|
3312
|
+
defaultPermissions: f
|
|
3313
|
+
} }), ne = an({
|
|
2579
3314
|
accessControl: {
|
|
2580
3315
|
controlPlaneTenantId: r,
|
|
2581
|
-
requireOrganizationMatch:
|
|
2582
|
-
defaultPermissions:
|
|
3316
|
+
requireOrganizationMatch: p,
|
|
3317
|
+
defaultPermissions: f
|
|
2583
3318
|
},
|
|
2584
|
-
onConfigSyncChange: (e) =>
|
|
2585
|
-
configSyncStatus: (e) =>
|
|
3319
|
+
onConfigSyncChange: (e) => C?.(e),
|
|
3320
|
+
configSyncStatus: (e) => Bn({
|
|
2586
3321
|
adapters: t,
|
|
2587
3322
|
controlPlaneTenantId: r,
|
|
2588
3323
|
resolveControlPlane: a
|
|
3324
|
+
}, e),
|
|
3325
|
+
verifyConfigSync: (e) => zn({
|
|
3326
|
+
adapters: t,
|
|
3327
|
+
controlPlaneTenantId: r,
|
|
3328
|
+
resolveControlPlane: a,
|
|
3329
|
+
syncConfig: s ?? xt(t, {
|
|
3330
|
+
controlPlaneTenantId: r,
|
|
3331
|
+
resolveControlPlane: a
|
|
3332
|
+
})
|
|
2589
3333
|
}, e)
|
|
2590
3334
|
}, { tenants: {
|
|
2591
3335
|
async beforeCreate(e, t) {
|
|
2592
|
-
return
|
|
3336
|
+
return P.beforeCreate && (t = await P.beforeCreate(e, t)), N.beforeCreate && (t = await N.beforeCreate(e, t)), t;
|
|
2593
3337
|
},
|
|
2594
3338
|
async afterCreate(e, t) {
|
|
2595
|
-
await
|
|
3339
|
+
await P.afterCreate?.(e, t), await N.afterCreate?.(e, t);
|
|
2596
3340
|
},
|
|
2597
3341
|
async beforeDelete(e, t) {
|
|
2598
|
-
await
|
|
2599
|
-
}
|
|
2600
|
-
} }), { app:
|
|
2601
|
-
dataAdapter:
|
|
2602
|
-
managementDataAdapter:
|
|
2603
|
-
...
|
|
2604
|
-
tenantOperationExecutor:
|
|
2605
|
-
...
|
|
2606
|
-
entityHooks:
|
|
2607
|
-
managementApiExtensions: [...
|
|
3342
|
+
await P.beforeDelete?.(e, t), await N.beforeDelete?.(e, t);
|
|
3343
|
+
}
|
|
3344
|
+
} }), { app: re } = y({
|
|
3345
|
+
dataAdapter: x,
|
|
3346
|
+
managementDataAdapter: S,
|
|
3347
|
+
...b,
|
|
3348
|
+
tenantOperationExecutor: w,
|
|
3349
|
+
...k ? { rolloutController: k } : {},
|
|
3350
|
+
entityHooks: te,
|
|
3351
|
+
managementApiExtensions: [...m, {
|
|
2608
3352
|
path: "/tenants",
|
|
2609
|
-
router:
|
|
3353
|
+
router: ne
|
|
2610
3354
|
}],
|
|
2611
|
-
managementApiMiddleware: [...
|
|
3355
|
+
managementApiMiddleware: [...b.managementApiMiddleware ?? [], ...j ? [gn()] : []]
|
|
2612
3356
|
});
|
|
2613
3357
|
return {
|
|
2614
|
-
app:
|
|
3358
|
+
app: re,
|
|
2615
3359
|
controlPlaneTenantId: r,
|
|
2616
|
-
rollouts:
|
|
3360
|
+
rollouts: O,
|
|
3361
|
+
memberRequests: E
|
|
2617
3362
|
};
|
|
2618
3363
|
}
|
|
2619
3364
|
//#endregion
|
|
2620
3365
|
//#region src/rollout/payload.ts
|
|
2621
|
-
function
|
|
3366
|
+
function Jn(e) {
|
|
2622
3367
|
let { pkcs7: t, tenant_id: n, ...r } = e;
|
|
2623
3368
|
return r;
|
|
2624
3369
|
}
|
|
2625
|
-
async function
|
|
2626
|
-
let i =
|
|
3370
|
+
async function Yn(e, t, n = {}, r) {
|
|
3371
|
+
let i = pe(n), a = n.signingKeys ?? !0, o = n.tenants ?? !0, s = await ge(e, t, i), c = a ? (await S(e.keys)).map(Jn) : [], l = o ? await Xn(e, t, r) : [];
|
|
2627
3372
|
return {
|
|
2628
3373
|
connections: s.connections,
|
|
2629
3374
|
resourceServers: s.resourceServers.filter((e) => e.is_system),
|
|
2630
|
-
hooks: s.hooks.filter(
|
|
3375
|
+
hooks: s.hooks.filter(he),
|
|
2631
3376
|
emailProvider: s.emailProvider,
|
|
2632
3377
|
branding: s.branding,
|
|
2633
3378
|
promptSettings: s.promptSettings,
|
|
@@ -2635,7 +3380,7 @@ async function _n(e, t, n = {}, r) {
|
|
|
2635
3380
|
tenants: l
|
|
2636
3381
|
};
|
|
2637
3382
|
}
|
|
2638
|
-
async function
|
|
3383
|
+
async function Xn(e, t, n) {
|
|
2639
3384
|
let r = n && n !== t ? [t, n] : [t], i = [];
|
|
2640
3385
|
for (let t of r) {
|
|
2641
3386
|
let n = await e.tenants.get(t);
|
|
@@ -2646,19 +3391,19 @@ async function vn(e, t, n) {
|
|
|
2646
3391
|
}
|
|
2647
3392
|
return i;
|
|
2648
3393
|
}
|
|
2649
|
-
async function
|
|
2650
|
-
let r =
|
|
3394
|
+
async function Zn(e, t, n) {
|
|
3395
|
+
let r = z();
|
|
2651
3396
|
if (e.length === 0) return r;
|
|
2652
|
-
let i = await
|
|
2653
|
-
for (let i of e) await
|
|
2654
|
-
let e =
|
|
3397
|
+
let i = await S(t.keys), a = new Set(i.map((e) => e.kid));
|
|
3398
|
+
for (let i of e) await B(r, `signing_key ${i.kid}`, n, async () => {
|
|
3399
|
+
let e = Jn(i);
|
|
2655
3400
|
a.has(e.kid) || (await t.keys.create(e), a.add(e.kid), r.upserted += 1);
|
|
2656
3401
|
});
|
|
2657
3402
|
return r;
|
|
2658
3403
|
}
|
|
2659
|
-
async function
|
|
2660
|
-
let r =
|
|
2661
|
-
for (let i of e) await
|
|
3404
|
+
async function Qn(e, t, n) {
|
|
3405
|
+
let r = z();
|
|
3406
|
+
for (let i of e) await B(r, `tenant ${i.id}`, n, async () => {
|
|
2662
3407
|
await t.tenants.get(i.id) || (await t.tenants.create({
|
|
2663
3408
|
id: i.id,
|
|
2664
3409
|
friendly_name: i.friendly_name
|
|
@@ -2666,50 +3411,50 @@ async function bn(e, t, n) {
|
|
|
2666
3411
|
});
|
|
2667
3412
|
return r;
|
|
2668
3413
|
}
|
|
2669
|
-
async function
|
|
2670
|
-
let i = r.continueOnError ?? !1, a =
|
|
3414
|
+
async function $n(e, t, n, r = {}) {
|
|
3415
|
+
let i = r.continueOnError ?? !1, a = pe(r.entities), o = r.entities?.signingKeys ?? !0, c = r.entities?.tenants ?? !0, l = {
|
|
2671
3416
|
connections: e.connections,
|
|
2672
3417
|
resourceServers: e.resourceServers,
|
|
2673
3418
|
hooks: e.hooks,
|
|
2674
|
-
emailProvider: e.emailProvider ?
|
|
2675
|
-
branding: e.branding ?
|
|
2676
|
-
promptSettings: e.promptSettings ?
|
|
2677
|
-
}, u = c ? await
|
|
2678
|
-
await
|
|
2679
|
-
let
|
|
3419
|
+
emailProvider: e.emailProvider ? p.parse(e.emailProvider) : null,
|
|
3420
|
+
branding: e.branding ? s.parse(e.branding) : null,
|
|
3421
|
+
promptSettings: e.promptSettings ? C.parse(e.promptSettings) : null
|
|
3422
|
+
}, u = c ? await Qn(e.tenants ?? [], t, i) : z(), d = me(n);
|
|
3423
|
+
await _e(l, t, n, a, i, d);
|
|
3424
|
+
let f = o ? await Zn(e.signingKeys, t, i) : z(), m = e.resolved && r.resolved ? await ut(e.resolved, t, r.resolved.tenantId, {
|
|
2680
3425
|
continueOnError: i,
|
|
2681
3426
|
...r.resolved
|
|
2682
3427
|
}) : void 0;
|
|
2683
3428
|
return {
|
|
2684
3429
|
...d,
|
|
2685
|
-
signingKeys:
|
|
3430
|
+
signingKeys: f,
|
|
2686
3431
|
tenants: u,
|
|
2687
3432
|
...m ? { resolved: m } : {}
|
|
2688
3433
|
};
|
|
2689
3434
|
}
|
|
2690
3435
|
//#endregion
|
|
2691
3436
|
//#region src/rollout/index.ts
|
|
2692
|
-
function
|
|
3437
|
+
function er(e) {
|
|
2693
3438
|
return {
|
|
2694
|
-
syncDefaults: (t) =>
|
|
3439
|
+
syncDefaults: (t) => ve(e, t),
|
|
2695
3440
|
syncDefaultsToTenants: async (t) => {
|
|
2696
3441
|
let n = [];
|
|
2697
|
-
for (let r of t) n.push(await
|
|
3442
|
+
for (let r of t) n.push(await ve(e, r));
|
|
2698
3443
|
return n;
|
|
2699
3444
|
}
|
|
2700
3445
|
};
|
|
2701
3446
|
}
|
|
2702
3447
|
//#endregion
|
|
2703
3448
|
//#region src/plugin.ts
|
|
2704
|
-
function
|
|
2705
|
-
let t =
|
|
3449
|
+
function tr(e) {
|
|
3450
|
+
let t = nr(e);
|
|
2706
3451
|
return {
|
|
2707
3452
|
name: "multi-tenancy",
|
|
2708
|
-
middleware:
|
|
3453
|
+
middleware: xn(e),
|
|
2709
3454
|
hooks: t,
|
|
2710
3455
|
routes: [{
|
|
2711
3456
|
path: "/management",
|
|
2712
|
-
handler:
|
|
3457
|
+
handler: an(e, t)
|
|
2713
3458
|
}],
|
|
2714
3459
|
onRegister: async () => {
|
|
2715
3460
|
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");
|
|
@@ -2718,29 +3463,29 @@ function Cn(e) {
|
|
|
2718
3463
|
}
|
|
2719
3464
|
//#endregion
|
|
2720
3465
|
//#region src/index.ts
|
|
2721
|
-
function
|
|
2722
|
-
let t = e.accessControl ?
|
|
3466
|
+
function nr(e) {
|
|
3467
|
+
let t = e.accessControl ? M(e.accessControl) : {}, n = e.databaseIsolation ? te(e.databaseIsolation) : {}, r = Ut(e);
|
|
2723
3468
|
return {
|
|
2724
3469
|
...t,
|
|
2725
3470
|
...n,
|
|
2726
3471
|
tenants: r
|
|
2727
3472
|
};
|
|
2728
3473
|
}
|
|
2729
|
-
function
|
|
2730
|
-
let n = new e(), r =
|
|
2731
|
-
return n.route("/tenants",
|
|
3474
|
+
function rr(t) {
|
|
3475
|
+
let n = new e(), r = nr(t);
|
|
3476
|
+
return n.route("/tenants", an(t, r)), n;
|
|
2732
3477
|
}
|
|
2733
|
-
function
|
|
3478
|
+
function ir(e) {
|
|
2734
3479
|
return {
|
|
2735
|
-
hooks:
|
|
2736
|
-
middleware:
|
|
2737
|
-
app:
|
|
3480
|
+
hooks: nr(e),
|
|
3481
|
+
middleware: xn(e),
|
|
3482
|
+
app: rr(e),
|
|
2738
3483
|
config: e,
|
|
2739
|
-
wrapAdapters: (t, n) =>
|
|
3484
|
+
wrapAdapters: (t, n) => We(t, {
|
|
2740
3485
|
controlPlaneTenantId: e.accessControl?.controlPlaneTenantId,
|
|
2741
3486
|
controlPlaneClientId: n?.controlPlaneClientId
|
|
2742
3487
|
})
|
|
2743
3488
|
};
|
|
2744
3489
|
}
|
|
2745
3490
|
//#endregion
|
|
2746
|
-
export {
|
|
3491
|
+
export { X as DEFAULT_ROLLOUT_SETTINGS, Sn as DEFAULT_ROLLOUT_WAVES, zt as MAX_MEMBER_REQUEST_ATTEMPTS, Nn as advanceRollout, Pn as advanceRollouts, $n as applyControlPlaneDefaultsPayload, ut as applyResolvedConfigBlock, kt as assertDetachEligible, Cn as assignWaves, Yn as buildControlPlaneDefaultsPayload, re as buildEngineInstanceId, at as buildResolvedConfigBlock, De as compareShadow, fe as computeLegacyConfig, M as createAccessControlHooks, vn as createAccessControlMiddleware, Me as createConfigSyncResolver, _n as createControlPlaneTenantMiddleware, te as createDatabaseHooks, bn as createDatabaseMiddleware, er as createDirectRolloutAdapter, Tn as createExpectedHash, Mt as createInProcessDetach, Ft as createInProcessMemberRequestStore, xt as createInProcessSyncConfig, oe as createInlineExecutor, rr as createMultiTenancy, nr as createMultiTenancyHooks, xn as createMultiTenancyMiddleware, tr as createMultiTenancyPlugin, I as createOperationRecorder, se as createOperationRow, gn as createProtectSyncedMiddleware, Ut as createProvisioningHooks, Kn as createRolloutController, Gn as createRolloutWriteHooks, Ve as createRuntimeFallbackAdapter, Ae as createShadowReporter, yn as createSubdomainMiddleware, Qt as createSyncHooks, an as createTenantsOpenAPIRouter, Tt as detachErrors, St as detachOptionsOf, jt as detachTenantRows, Ee as diffConfig, Ke as effectiveOverride, U as effectiveScope, Ot as emptyDetachResult, Bt as enqueueTenantMemberRequest, ce as enqueueTenantOperation, F as errorToMessage, ct as findUndecryptableKeyIds, Bn as getConfigSyncStatus, qn as initMultiTenant, ae as inlineStepRunner, Hn as isPublishedRow, L as isTerminalStatus, kn as listRolloutOperations, wn as listSyncedDescendants, At as markTenantDetached, It as memberRequestIdOf, Le as mergeClientWithFallback, $e as mergeConfig, Fn as pauseRollout, On as planRollout, ve as projectControlPlaneDefaults, V as readConfigRows, Z as readRolloutConfig, Vn as reconcileConfigDrift, Vt as reconcileTenantMemberRequests, Un as requestRollout, R as resolveTenantChain, In as resumeRollout, Dt as runDetachStep, Pt as runRecordedTenantOperation, bt as runSyncDefaultsStep, Rt as runTenantMembersRequestStep, ir as setupMultiTenancy, Et as summarizeDetachResult, yt as summarizeSyncResult, gt as syncErrors, ht as syncOptionsOf, it as syncedRowId, N as validateTenantAccess, zn as verifyTenantConfig, We as withRuntimeFallback, Be as withSystemResourceServerInheritance };
|