@niledatabase/server 5.0.0-alpha.3 → 5.0.0-alpha.31
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/index.d.mts +612 -308
- package/dist/index.d.ts +612 -308
- package/dist/index.js +1831 -959
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1825 -960
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -13
- package/dist/express.d.mts +0 -32
- package/dist/express.d.ts +0 -32
- package/dist/express.js +0 -1433
- package/dist/express.js.map +0 -1
- package/dist/express.mjs +0 -1429
- package/dist/express.mjs.map +0 -1
- package/dist/nitro.d.mts +0 -7
- package/dist/nitro.d.ts +0 -7
- package/dist/nitro.js +0 -36
- package/dist/nitro.js.map +0 -1
- package/dist/nitro.mjs +0 -34
- package/dist/nitro.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
1
2
|
import 'dotenv/config';
|
|
2
3
|
import pg from 'pg';
|
|
3
4
|
|
|
4
5
|
// src/types.ts
|
|
6
|
+
var ExtensionState = /* @__PURE__ */ ((ExtensionState2) => {
|
|
7
|
+
ExtensionState2["onHandleRequest"] = "onHandleRequest";
|
|
8
|
+
ExtensionState2["onRequest"] = "onRequest";
|
|
9
|
+
ExtensionState2["onResponse"] = "onResponse";
|
|
10
|
+
ExtensionState2["withContext"] = "withContext";
|
|
11
|
+
return ExtensionState2;
|
|
12
|
+
})(ExtensionState || {});
|
|
5
13
|
var APIErrorErrorCodeEnum = {
|
|
6
14
|
InternalError: "internal_error",
|
|
7
15
|
BadRequest: "bad_request",
|
|
@@ -25,6 +33,12 @@ var LoginUserResponseTokenTypeEnum = {
|
|
|
25
33
|
IdToken: "ID_TOKEN"
|
|
26
34
|
};
|
|
27
35
|
|
|
36
|
+
// src/utils/constants.ts
|
|
37
|
+
var TENANT_COOKIE = "nile.tenant-id";
|
|
38
|
+
var USER_COOKIE = "nile.user-id";
|
|
39
|
+
var HEADER_ORIGIN = "nile-origin";
|
|
40
|
+
var HEADER_SECURE_COOKIES = "nile-secure-cookies";
|
|
41
|
+
|
|
28
42
|
// src/api/utils/routes/index.ts
|
|
29
43
|
var NILEDB_API_URL = process.env.NILEDB_API_URL;
|
|
30
44
|
var DEFAULT_PREFIX = "/api";
|
|
@@ -47,21 +61,22 @@ var appRoutes = (prefix = DEFAULT_PREFIX) => ({
|
|
|
47
61
|
TENANT_USER: `${prefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */}`,
|
|
48
62
|
TENANT_USERS: `${prefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */}`,
|
|
49
63
|
SIGNUP: `${prefix}${"/signup" /* SIGNUP */}`,
|
|
64
|
+
INVITES: `${prefix}${"/tenants/{tenantId}/invites" /* INVITES */}`,
|
|
65
|
+
INVITE: `${prefix}${"/tenants/{tenantId}/invite" /* INVITE */}`,
|
|
50
66
|
LOG: `${prefix}/_log`
|
|
51
67
|
});
|
|
52
|
-
var apiRoutes = (
|
|
53
|
-
ME: makeRestUrl(
|
|
54
|
-
USERS: (qp) => makeRestUrl(
|
|
55
|
-
USER: (userId) => makeRestUrl(
|
|
56
|
-
TENANTS: makeRestUrl(
|
|
57
|
-
TENANT: (tenantId) => makeRestUrl(
|
|
58
|
-
SIGNUP: makeRestUrl(
|
|
59
|
-
TENANT_USERS: (tenantId) => makeRestUrl(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
),
|
|
64
|
-
USER_TENANTS: (userId) => makeRestUrl(config, `/users/${userId}/tenants`)
|
|
68
|
+
var apiRoutes = (apiUrl) => ({
|
|
69
|
+
ME: makeRestUrl(apiUrl, "/me"),
|
|
70
|
+
USERS: (qp) => makeRestUrl(apiUrl, "/users", qp),
|
|
71
|
+
USER: (userId) => makeRestUrl(apiUrl, `/users/${userId}`),
|
|
72
|
+
TENANTS: makeRestUrl(apiUrl, "/tenants"),
|
|
73
|
+
TENANT: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}`),
|
|
74
|
+
SIGNUP: makeRestUrl(apiUrl, "/signup"),
|
|
75
|
+
TENANT_USERS: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/users`),
|
|
76
|
+
INVITES: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/invites`),
|
|
77
|
+
INVITE: (tenantId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/invite`),
|
|
78
|
+
TENANT_USER: (tenantId, userId) => makeRestUrl(apiUrl, `/tenants/${tenantId}/users/${userId}`),
|
|
79
|
+
USER_TENANTS: (userId) => makeRestUrl(apiUrl, `/users/${userId}/tenants`)
|
|
65
80
|
});
|
|
66
81
|
var proxyRoutes = (config) => ({
|
|
67
82
|
SIGNIN: makeRestUrl(config, "/auth/signin" /* SIGNIN */),
|
|
@@ -85,8 +100,8 @@ function filterNullUndefined(obj) {
|
|
|
85
100
|
)
|
|
86
101
|
);
|
|
87
102
|
}
|
|
88
|
-
function makeRestUrl(
|
|
89
|
-
const url =
|
|
103
|
+
function makeRestUrl(apiUrl, path, qp) {
|
|
104
|
+
const url = apiUrl || NILEDB_API_URL;
|
|
90
105
|
if (!url) {
|
|
91
106
|
throw new Error(
|
|
92
107
|
"An API url is required. Set it via NILEDB_API_URL. Was auto configuration run?"
|
|
@@ -98,9 +113,9 @@ function makeRestUrl(config, path, qp) {
|
|
|
98
113
|
const strParams = params.toString();
|
|
99
114
|
return `${[url, path.substring(1, path.length)].join("/")}${strParams ? `?${strParams}` : ""}`;
|
|
100
115
|
}
|
|
101
|
-
function urlMatches(requestUrl,
|
|
116
|
+
function urlMatches(requestUrl, route20) {
|
|
102
117
|
const url = new URL(requestUrl);
|
|
103
|
-
return url.pathname.startsWith(
|
|
118
|
+
return url.pathname.startsWith(route20);
|
|
104
119
|
}
|
|
105
120
|
function isUUID(value) {
|
|
106
121
|
if (!value) {
|
|
@@ -117,6 +132,16 @@ var purple = "\x1B[38;2;200;160;255m";
|
|
|
117
132
|
var orange = "\x1B[38;2;255;165;0m";
|
|
118
133
|
var reset = "\x1B[0m";
|
|
119
134
|
var baseLogger = (config, ...params) => ({
|
|
135
|
+
silly(message, meta) {
|
|
136
|
+
if (config?.debug && process.env.LOG_LEVEL === "silly") {
|
|
137
|
+
console.log(
|
|
138
|
+
`${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
|
|
139
|
+
""
|
|
140
|
+
)}${reset} ${message}`,
|
|
141
|
+
meta ? `${JSON.stringify(meta)}` : ""
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
},
|
|
120
145
|
info(message, meta) {
|
|
121
146
|
if (config?.debug) {
|
|
122
147
|
console.info(
|
|
@@ -129,7 +154,7 @@ var baseLogger = (config, ...params) => ({
|
|
|
129
154
|
},
|
|
130
155
|
debug(message, meta) {
|
|
131
156
|
if (config?.debug) {
|
|
132
|
-
console.
|
|
157
|
+
console.log(
|
|
133
158
|
`${orange}[niledb]${reset}${purple}[DEBUG]${reset}${params.join(
|
|
134
159
|
""
|
|
135
160
|
)}${reset} ${message}`,
|
|
@@ -157,43 +182,267 @@ var baseLogger = (config, ...params) => ({
|
|
|
157
182
|
);
|
|
158
183
|
}
|
|
159
184
|
});
|
|
160
|
-
function Logger(config
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
185
|
+
function Logger(config) {
|
|
186
|
+
return (prefixes) => {
|
|
187
|
+
const { info, debug, warn: warn2, error, silly: silly2 } = config && typeof config?.logger === "function" ? config.logger(prefixes) : baseLogger(config, prefixes);
|
|
188
|
+
return {
|
|
189
|
+
info,
|
|
190
|
+
debug,
|
|
191
|
+
warn: warn2,
|
|
192
|
+
error,
|
|
193
|
+
silly: silly2
|
|
194
|
+
};
|
|
195
|
+
};
|
|
167
196
|
}
|
|
168
197
|
function matchesLog(configRoutes, request2) {
|
|
169
198
|
return urlMatches(request2.url, configRoutes.LOG);
|
|
170
199
|
}
|
|
171
200
|
|
|
172
|
-
// src/utils/
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
201
|
+
// src/api/utils/extensions.ts
|
|
202
|
+
function getRequestConfig(params) {
|
|
203
|
+
if (typeof params[1] === "object") {
|
|
204
|
+
return params[1];
|
|
205
|
+
}
|
|
206
|
+
return {};
|
|
207
|
+
}
|
|
208
|
+
function bindRunExtensions(instance) {
|
|
209
|
+
return async function runExtensions(toRun, config, params, _init) {
|
|
210
|
+
const { debug } = config.logger("[EXTENSIONS]");
|
|
211
|
+
const extensionConfig = getRequestConfig(
|
|
212
|
+
Array.isArray(params) ? params : [null, params]
|
|
213
|
+
);
|
|
214
|
+
if (config.extensions) {
|
|
215
|
+
for (const create2 of config.extensions) {
|
|
216
|
+
if (typeof create2 !== "function") {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
const ext = create2(instance);
|
|
220
|
+
if (extensionConfig.disableExtensions?.includes(ext.id)) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (ext.withContext && toRun === "withContext" /* withContext */) {
|
|
224
|
+
await ext.withContext(ctx);
|
|
225
|
+
}
|
|
226
|
+
if (ext.onHandleRequest && toRun === "onHandleRequest" /* onHandleRequest */) {
|
|
227
|
+
const result = await ext.onHandleRequest(
|
|
228
|
+
Array.isArray(params) ? params : [params]
|
|
229
|
+
);
|
|
230
|
+
debug(`${ext.id ?? create2.name} ran onHandleRequest`);
|
|
231
|
+
if (result != null) {
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const [param] = Array.isArray(params) ? params : [params];
|
|
236
|
+
if (ext.onRequest && toRun === "onRequest" /* onRequest */) {
|
|
237
|
+
const { ...previousContext } = ctx.get();
|
|
238
|
+
const preserveHeaders = previousContext.preserveHeaders;
|
|
239
|
+
if (preserveHeaders) {
|
|
240
|
+
ctx.set({ preserveHeaders: false });
|
|
241
|
+
}
|
|
242
|
+
if (!_init) {
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
const previousHeaders = new Headers(previousContext.headers);
|
|
246
|
+
await ext.onRequest(_init.request, ctx);
|
|
247
|
+
const updatedContext = ctx.get();
|
|
248
|
+
if (updatedContext?.headers) {
|
|
249
|
+
const cookie = updatedContext.headers.get("cookie");
|
|
250
|
+
if (cookie && param.headers) {
|
|
251
|
+
const updatedCookies = mergeCookies(
|
|
252
|
+
preserveHeaders ? previousHeaders?.get("cookie") : null,
|
|
253
|
+
updatedContext.headers.get("cookie")
|
|
254
|
+
);
|
|
255
|
+
param.headers.set("cookie", updatedCookies);
|
|
256
|
+
}
|
|
257
|
+
if (updatedContext.tenantId && param.headers) {
|
|
258
|
+
param.headers.set(
|
|
259
|
+
TENANT_COOKIE,
|
|
260
|
+
String(updatedContext.headers.get(TENANT_COOKIE))
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
ctx.set({ headers: param.headers });
|
|
264
|
+
}
|
|
265
|
+
debug(`${ext.id ?? create2.name} ran onRequest`);
|
|
266
|
+
}
|
|
267
|
+
if (ext.onResponse && toRun === "onResponse" /* onResponse */) {
|
|
268
|
+
const result = await ext.onResponse(param, ctx);
|
|
269
|
+
debug(`${ext.id ?? create2.name} ran onResponse`);
|
|
270
|
+
if (result != null) {
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return void 0;
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function buildExtensionConfig(instance) {
|
|
280
|
+
return {
|
|
281
|
+
runExtensions: bindRunExtensions(instance)
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function mergeCookies(...cookieStrings) {
|
|
285
|
+
const cookieMap = /* @__PURE__ */ new Map();
|
|
286
|
+
for (const str of cookieStrings) {
|
|
287
|
+
if (!str) continue;
|
|
288
|
+
for (const part of str.split(";")) {
|
|
289
|
+
const [key17, value] = part.split("=").map((s) => s.trim());
|
|
290
|
+
if (key17 && value) cookieMap.set(key17, value);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return [...cookieMap.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
|
|
294
|
+
}
|
|
295
|
+
async function runExtensionContext(config) {
|
|
296
|
+
await config?.extensionCtx?.runExtensions("withContext" /* withContext */, config);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// src/api/utils/request-context.ts
|
|
300
|
+
var { warn, silly } = Logger({ debug: true })("[REQUEST CONTEXT]");
|
|
301
|
+
var storage = new AsyncLocalStorage();
|
|
302
|
+
var defaultContext = {
|
|
303
|
+
headers: new Headers(),
|
|
304
|
+
tenantId: void 0,
|
|
305
|
+
userId: void 0,
|
|
306
|
+
preserveHeaders: false
|
|
307
|
+
};
|
|
308
|
+
var lastUsedContext = defaultContext;
|
|
309
|
+
var ctx = {
|
|
310
|
+
run(ctx2, fn) {
|
|
311
|
+
const merged = {
|
|
312
|
+
...defaultContext,
|
|
313
|
+
...ctx2,
|
|
314
|
+
headers: ctx2.headers instanceof Headers ? ctx2.headers : new Headers(ctx2.headers)
|
|
315
|
+
};
|
|
316
|
+
lastUsedContext = merged;
|
|
317
|
+
return storage.run(merged, fn);
|
|
318
|
+
},
|
|
319
|
+
get: () => {
|
|
320
|
+
const ctx2 = storage.getStore();
|
|
321
|
+
if (!ctx2) {
|
|
322
|
+
return { ...defaultContext };
|
|
323
|
+
}
|
|
324
|
+
silly(`[GET] ${serializeContext(ctx2)}`);
|
|
325
|
+
return ctx2;
|
|
326
|
+
},
|
|
327
|
+
/**
|
|
328
|
+
* This is a mirror of Server.getContext, but only for requests. We keep only the request
|
|
329
|
+
* information around, everything else is :above_my_pay_grade:
|
|
330
|
+
* @param partial A partial context to override
|
|
331
|
+
*/
|
|
332
|
+
set: (partial) => {
|
|
333
|
+
const store = storage.getStore();
|
|
334
|
+
if (!store) {
|
|
335
|
+
warn("ctx.set() called outside of ctx.run(). This will not persist.");
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (partial.headers === null) {
|
|
339
|
+
store.headers = new Headers();
|
|
340
|
+
} else if (partial.headers && store.headers instanceof Headers) {
|
|
341
|
+
for (const [key17, value] of new Headers(partial.headers).entries()) {
|
|
342
|
+
if (key17.toLowerCase() === "cookie") {
|
|
343
|
+
const existingCookies = parseCookieHeader(
|
|
344
|
+
store.headers.get("cookie") || ""
|
|
345
|
+
);
|
|
346
|
+
const newCookies = parseCookieHeader(value);
|
|
347
|
+
const mergedCookies = { ...existingCookies, ...newCookies };
|
|
348
|
+
store.headers.set("cookie", serializeCookies(mergedCookies));
|
|
349
|
+
} else {
|
|
350
|
+
store.headers.set(key17, value);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if ("tenantId" in partial) store.tenantId = partial.tenantId;
|
|
355
|
+
if ("userId" in partial) store.userId = partial.userId;
|
|
356
|
+
if ("preserveHeaders" in partial)
|
|
357
|
+
store.preserveHeaders = Boolean(partial.preserveHeaders);
|
|
358
|
+
silly(`[SET] ${serializeContext(store)}`);
|
|
359
|
+
lastUsedContext = { ...store };
|
|
360
|
+
},
|
|
361
|
+
// for convenience only
|
|
362
|
+
getLastUsed: () => lastUsedContext
|
|
363
|
+
};
|
|
364
|
+
function withNileContext(config, fn, name = "unknown") {
|
|
365
|
+
const initialContext = config.context;
|
|
366
|
+
const existing = ctx.get();
|
|
367
|
+
const mergedHeaders = new Headers(existing.headers);
|
|
368
|
+
if (initialContext instanceof Request) {
|
|
369
|
+
initialContext.headers.forEach((value, key17) => {
|
|
370
|
+
mergedHeaders.set(key17, value);
|
|
371
|
+
});
|
|
372
|
+
const context2 = {
|
|
373
|
+
headers: mergedHeaders,
|
|
374
|
+
tenantId: existing.tenantId,
|
|
375
|
+
userId: existing.userId,
|
|
376
|
+
preserveHeaders: existing.preserveHeaders ?? false
|
|
377
|
+
};
|
|
378
|
+
silly(`${name} [INITIAL - Request] ${serializeContext(context2)}`);
|
|
379
|
+
return ctx.run(context2, fn);
|
|
380
|
+
}
|
|
381
|
+
if (initialContext.headers) {
|
|
382
|
+
const incoming = initialContext.headers instanceof Headers ? initialContext.headers : new Headers(initialContext.headers);
|
|
383
|
+
incoming.forEach((value, key17) => {
|
|
384
|
+
mergedHeaders.set(key17, value);
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
const hasTenantId = "tenantId" in initialContext;
|
|
388
|
+
const hasUserId = "userId" in initialContext;
|
|
389
|
+
const hasPreserveHeaders = "preserveHeaders" in initialContext;
|
|
390
|
+
const context = {
|
|
391
|
+
headers: mergedHeaders,
|
|
392
|
+
tenantId: hasTenantId ? initialContext.tenantId : existing.tenantId,
|
|
393
|
+
userId: hasUserId ? initialContext.userId : existing.userId,
|
|
394
|
+
preserveHeaders: hasPreserveHeaders ? Boolean(initialContext.preserveHeaders) : existing.preserveHeaders ?? false
|
|
395
|
+
};
|
|
396
|
+
silly(`${name} [INITIAL - Partial<Context>] ${serializeContext(context)}`);
|
|
397
|
+
return ctx.run(context, async () => {
|
|
398
|
+
await runExtensionContext(config);
|
|
399
|
+
return fn();
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
function serializeContext(context) {
|
|
403
|
+
const headers = {};
|
|
404
|
+
const rawHeaders = new Headers(context.headers);
|
|
405
|
+
rawHeaders.forEach((value, key17) => {
|
|
406
|
+
headers[key17] = value;
|
|
407
|
+
});
|
|
408
|
+
return JSON.stringify({
|
|
409
|
+
headers,
|
|
410
|
+
tenantId: context.tenantId,
|
|
411
|
+
userId: context.userId,
|
|
412
|
+
preserveHeaders: context.preserveHeaders
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
function parseCookieHeader(header) {
|
|
416
|
+
return header.split(";").map((c) => c.trim()).filter(Boolean).reduce((acc, curr) => {
|
|
417
|
+
const [key17, ...val] = curr.split("=");
|
|
418
|
+
if (key17) acc[key17] = val.join("=");
|
|
419
|
+
return acc;
|
|
420
|
+
}, {});
|
|
421
|
+
}
|
|
422
|
+
function serializeCookies(cookies) {
|
|
423
|
+
return Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
424
|
+
}
|
|
176
425
|
|
|
177
426
|
// src/api/utils/request.ts
|
|
178
427
|
async function request(url, _init, config) {
|
|
179
|
-
const { debug, info, error } =
|
|
428
|
+
const { debug, info, error, warn: warn2 } = config.logger("[REQUEST]");
|
|
180
429
|
const { request: request2, ...init } = _init;
|
|
181
430
|
const requestUrl = new URL(request2.url);
|
|
182
431
|
const updatedHeaders = new Headers({});
|
|
183
432
|
if (request2.headers.get("cookie")) {
|
|
184
433
|
updatedHeaders.set("cookie", String(request2.headers.get("cookie")));
|
|
185
434
|
}
|
|
186
|
-
if (request2.headers.get(
|
|
435
|
+
if (request2.headers.get(TENANT_COOKIE)) {
|
|
187
436
|
updatedHeaders.set(
|
|
188
|
-
|
|
189
|
-
String(request2.headers.get(
|
|
437
|
+
TENANT_COOKIE,
|
|
438
|
+
String(request2.headers.get(TENANT_COOKIE))
|
|
190
439
|
);
|
|
191
440
|
}
|
|
192
441
|
if (config.secureCookies != null) {
|
|
193
|
-
updatedHeaders.set(
|
|
442
|
+
updatedHeaders.set(HEADER_SECURE_COOKIES, String(config.secureCookies));
|
|
194
443
|
} else {
|
|
195
444
|
updatedHeaders.set(
|
|
196
|
-
|
|
445
|
+
HEADER_SECURE_COOKIES,
|
|
197
446
|
process.env.NODE_ENV === "production" ? "true" : "false"
|
|
198
447
|
);
|
|
199
448
|
}
|
|
@@ -201,32 +450,42 @@ async function request(url, _init, config) {
|
|
|
201
450
|
if (config.callbackUrl) {
|
|
202
451
|
const cbUrl = new URL(config.callbackUrl);
|
|
203
452
|
debug(`Obtained origin from config.callbackUrl ${config.callbackUrl}`);
|
|
204
|
-
updatedHeaders.set(
|
|
453
|
+
updatedHeaders.set(HEADER_ORIGIN, cbUrl.origin);
|
|
205
454
|
} else if (config.origin) {
|
|
206
455
|
debug(`Obtained origin from config.origin ${config.origin}`);
|
|
207
|
-
updatedHeaders.set(
|
|
456
|
+
updatedHeaders.set(HEADER_ORIGIN, config.origin);
|
|
208
457
|
} else {
|
|
209
|
-
const passedOrigin = request2.headers.get(
|
|
458
|
+
const passedOrigin = request2.headers.get(HEADER_ORIGIN);
|
|
210
459
|
if (passedOrigin) {
|
|
211
|
-
updatedHeaders.set(
|
|
460
|
+
updatedHeaders.set(HEADER_ORIGIN, passedOrigin);
|
|
212
461
|
} else {
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
462
|
+
const { headers } = ctx.get();
|
|
463
|
+
const host = headers.get("host");
|
|
464
|
+
if (host) {
|
|
465
|
+
const serverSideOrigin = `${getProtocolFromHeaders(headers)}://${host}`;
|
|
466
|
+
updatedHeaders.set(HEADER_ORIGIN, serverSideOrigin);
|
|
467
|
+
debug(`Obtained origin from server side headers ${serverSideOrigin}`);
|
|
468
|
+
} else {
|
|
469
|
+
const reqOrigin = config.routePrefix !== DEFAULT_PREFIX ? `${requestUrl.origin}${config.routePrefix}` : requestUrl.origin;
|
|
470
|
+
updatedHeaders.set(HEADER_ORIGIN, reqOrigin);
|
|
471
|
+
debug(`Obtained origin from request ${reqOrigin}`);
|
|
472
|
+
}
|
|
216
473
|
}
|
|
217
474
|
}
|
|
218
475
|
const params = { ...init };
|
|
219
476
|
if (params.method?.toLowerCase() === "post" || params.method?.toLowerCase() === "put") {
|
|
220
477
|
try {
|
|
221
478
|
updatedHeaders.set("content-type", "application/json");
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
|
|
479
|
+
const bodyStream = _init.body ?? _init.request?.body ?? request2.body;
|
|
480
|
+
const bodyText = await new Response(bodyStream).text();
|
|
481
|
+
try {
|
|
482
|
+
params.body = JSON.stringify(JSON.parse(bodyText));
|
|
483
|
+
} catch {
|
|
484
|
+
updatedHeaders.set("content-type", "application/x-www-form-urlencoded");
|
|
485
|
+
params.body = bodyText;
|
|
486
|
+
}
|
|
225
487
|
} catch (e) {
|
|
226
|
-
|
|
227
|
-
const initBody = await new Response(_init.request.clone().body).text();
|
|
228
|
-
const requestBody = await new Response(request2.clone().body).text();
|
|
229
|
-
params.body = initBody ?? requestBody;
|
|
488
|
+
error("Failed to parse request body");
|
|
230
489
|
}
|
|
231
490
|
}
|
|
232
491
|
params.headers = updatedHeaders;
|
|
@@ -235,6 +494,12 @@ async function request(url, _init, config) {
|
|
|
235
494
|
params.headers.set("request-id", crypto.randomUUID());
|
|
236
495
|
params.cache = "no-store";
|
|
237
496
|
}
|
|
497
|
+
await config.extensionCtx?.runExtensions(
|
|
498
|
+
"onRequest" /* onRequest */,
|
|
499
|
+
config,
|
|
500
|
+
params,
|
|
501
|
+
_init
|
|
502
|
+
);
|
|
238
503
|
try {
|
|
239
504
|
const res = await fetch(fullUrl, {
|
|
240
505
|
...params
|
|
@@ -254,6 +519,14 @@ async function request(url, _init, config) {
|
|
|
254
519
|
statusText: res?.statusText,
|
|
255
520
|
text: await loggingRes?.text()
|
|
256
521
|
});
|
|
522
|
+
const updatedRes = await config.extensionCtx?.runExtensions(
|
|
523
|
+
"onResponse" /* onResponse */,
|
|
524
|
+
config,
|
|
525
|
+
{ ...params, response: res }
|
|
526
|
+
);
|
|
527
|
+
if (updatedRes) {
|
|
528
|
+
return updatedRes;
|
|
529
|
+
}
|
|
257
530
|
return res;
|
|
258
531
|
} catch (e) {
|
|
259
532
|
if (e instanceof Error) {
|
|
@@ -268,25 +541,35 @@ async function request(url, _init, config) {
|
|
|
268
541
|
);
|
|
269
542
|
}
|
|
270
543
|
}
|
|
544
|
+
function getProtocolFromHeaders(headers) {
|
|
545
|
+
const get = (key17) => headers instanceof Headers ? headers.get(key17) : headers[key17.toLowerCase()];
|
|
546
|
+
const xfp = get("x-forwarded-proto");
|
|
547
|
+
if (xfp) return xfp.toLowerCase();
|
|
548
|
+
const forwarded = get("forwarded");
|
|
549
|
+
if (forwarded) {
|
|
550
|
+
const match = forwarded.match(/proto=(https?)/i);
|
|
551
|
+
if (match) return match[1].toLowerCase();
|
|
552
|
+
}
|
|
553
|
+
const ref = get("referer") || get("origin");
|
|
554
|
+
if (ref && ref.startsWith("https")) return "https";
|
|
555
|
+
return "http";
|
|
556
|
+
}
|
|
271
557
|
|
|
272
558
|
// src/api/utils/auth.ts
|
|
273
559
|
async function auth(req, config) {
|
|
274
|
-
const { info, error } =
|
|
560
|
+
const { info, error } = config.logger("[nileauth]");
|
|
275
561
|
info("checking auth");
|
|
276
562
|
const sessionUrl = `${config.apiUrl}/auth/session`;
|
|
277
563
|
info(`using session ${sessionUrl}`);
|
|
278
564
|
req.headers.delete("content-length");
|
|
279
565
|
const res = await request(sessionUrl, { request: req }, config);
|
|
280
|
-
if (!res) {
|
|
281
|
-
info("no session found");
|
|
282
|
-
return void 0;
|
|
283
|
-
}
|
|
284
|
-
info("session active");
|
|
285
566
|
try {
|
|
286
567
|
const session = await new Response(res.body).json();
|
|
287
568
|
if (Object.keys(session).length === 0) {
|
|
569
|
+
info("no session found");
|
|
288
570
|
return void 0;
|
|
289
571
|
}
|
|
572
|
+
info("session active");
|
|
290
573
|
return session;
|
|
291
574
|
} catch (e) {
|
|
292
575
|
error(e);
|
|
@@ -297,7 +580,7 @@ async function auth(req, config) {
|
|
|
297
580
|
// src/api/routes/me/index.ts
|
|
298
581
|
var key = "ME";
|
|
299
582
|
async function route(request2, config) {
|
|
300
|
-
const url = apiRoutes(config)[key];
|
|
583
|
+
const url = apiRoutes(config.apiUrl)[key];
|
|
301
584
|
if (request2.method === "GET") {
|
|
302
585
|
return await GET(url, { request: request2 }, config);
|
|
303
586
|
}
|
|
@@ -318,8 +601,9 @@ function matches(configRoutes, request2) {
|
|
|
318
601
|
}
|
|
319
602
|
async function fetchMe(config, method, body) {
|
|
320
603
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/me" /* ME */}`;
|
|
604
|
+
const { headers } = ctx.get();
|
|
321
605
|
const init = {
|
|
322
|
-
headers
|
|
606
|
+
headers,
|
|
323
607
|
method: method ?? "GET"
|
|
324
608
|
};
|
|
325
609
|
if (method === "PUT") {
|
|
@@ -371,9 +655,9 @@ function getTokenFromCookie(headers, cookieKey) {
|
|
|
371
655
|
return _cookies[cookieKey];
|
|
372
656
|
}
|
|
373
657
|
}
|
|
374
|
-
function getTenantFromHttp(headers,
|
|
375
|
-
const cookieTenant = getTokenFromCookie(headers,
|
|
376
|
-
return cookieTenant
|
|
658
|
+
function getTenantFromHttp(headers, context) {
|
|
659
|
+
const cookieTenant = getTokenFromCookie(headers, TENANT_COOKIE);
|
|
660
|
+
return cookieTenant ? cookieTenant : context?.tenantId;
|
|
377
661
|
}
|
|
378
662
|
|
|
379
663
|
// src/api/routes/users/POST.ts
|
|
@@ -384,7 +668,10 @@ async function POST(config, init) {
|
|
|
384
668
|
const tenantId = yurl.searchParams.get("tenantId");
|
|
385
669
|
const newTenantName = yurl.searchParams.get("newTenantName");
|
|
386
670
|
const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
|
|
387
|
-
const url = apiRoutes(config).USERS({
|
|
671
|
+
const url = apiRoutes(config.apiUrl).USERS({
|
|
672
|
+
tenantId: tenant,
|
|
673
|
+
newTenantName
|
|
674
|
+
});
|
|
388
675
|
return await request(url, init, config);
|
|
389
676
|
}
|
|
390
677
|
|
|
@@ -392,43 +679,36 @@ async function POST(config, init) {
|
|
|
392
679
|
async function GET2(config, init, log) {
|
|
393
680
|
const yurl = new URL(init.request.url);
|
|
394
681
|
const tenantId = yurl.searchParams.get("tenantId");
|
|
395
|
-
const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
|
|
682
|
+
const tenant = tenantId ?? getTenantFromHttp(init.request.headers, config.context);
|
|
396
683
|
if (!tenant) {
|
|
397
684
|
log("[GET] No tenant id provided.");
|
|
398
685
|
return new Response(null, { status: 404 });
|
|
399
686
|
}
|
|
400
|
-
const url = apiRoutes(config).TENANT_USERS(tenant);
|
|
401
687
|
init.method = "GET";
|
|
688
|
+
const url = apiRoutes(config.apiUrl).TENANT_USERS(tenant);
|
|
402
689
|
return await request(url, init, config);
|
|
403
690
|
}
|
|
404
691
|
|
|
405
692
|
// src/api/routes/users/[userId]/PUT.ts
|
|
406
|
-
async function PUT2(config,
|
|
407
|
-
if (!session) {
|
|
408
|
-
return new Response(null, { status: 401 });
|
|
409
|
-
}
|
|
693
|
+
async function PUT2(config, init) {
|
|
410
694
|
init.body = init.request.body;
|
|
411
695
|
init.method = "PUT";
|
|
412
696
|
const [userId] = new URL(init.request.url).pathname.split("/").reverse();
|
|
413
|
-
const url = apiRoutes(config).USER(userId);
|
|
697
|
+
const url = apiRoutes(config.apiUrl).USER(userId);
|
|
414
698
|
return await request(url, init, config);
|
|
415
699
|
}
|
|
416
700
|
|
|
417
701
|
// src/api/routes/users/index.ts
|
|
418
702
|
var key2 = "USERS";
|
|
419
703
|
async function route2(request2, config) {
|
|
420
|
-
const { info } =
|
|
421
|
-
{ ...config, debug: config.debug },
|
|
422
|
-
`[ROUTES][${key2}]`
|
|
423
|
-
);
|
|
424
|
-
const session = await auth(request2, config);
|
|
704
|
+
const { info } = config.logger(`[ROUTES][${key2}]`);
|
|
425
705
|
switch (request2.method) {
|
|
426
706
|
case "GET":
|
|
427
707
|
return await GET2(config, { request: request2 }, info);
|
|
428
708
|
case "POST":
|
|
429
709
|
return await POST(config, { request: request2 });
|
|
430
710
|
case "PUT":
|
|
431
|
-
return await PUT2(config,
|
|
711
|
+
return await PUT2(config, { request: request2 });
|
|
432
712
|
default:
|
|
433
713
|
return new Response("method not allowed", { status: 405 });
|
|
434
714
|
}
|
|
@@ -441,32 +721,28 @@ function matches2(configRoutes, request2) {
|
|
|
441
721
|
async function GET3(config, init) {
|
|
442
722
|
const yurl = new URL(init.request.url);
|
|
443
723
|
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
444
|
-
const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
|
|
724
|
+
const url = `${apiRoutes(config.apiUrl).TENANT_USERS(tenantId)}`;
|
|
445
725
|
return await request(url, init, config);
|
|
446
726
|
}
|
|
447
727
|
|
|
448
728
|
// src/api/routes/tenants/[tenantId]/users/POST.ts
|
|
449
|
-
async function POST2(config,
|
|
729
|
+
async function POST2(config, init) {
|
|
730
|
+
const session = await auth(init.request, config);
|
|
731
|
+
if (!session) {
|
|
732
|
+
return new Response(null, { status: 401 });
|
|
733
|
+
}
|
|
450
734
|
const yurl = new URL(init.request.url);
|
|
451
735
|
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
452
736
|
init.body = JSON.stringify({ email: session.email });
|
|
453
737
|
init.method = "POST";
|
|
454
|
-
const url = apiRoutes(config).TENANT_USERS(tenantId);
|
|
738
|
+
const url = apiRoutes(config.apiUrl).TENANT_USERS(tenantId);
|
|
455
739
|
return await request(url, init, config);
|
|
456
740
|
}
|
|
457
741
|
|
|
458
742
|
// src/api/routes/tenants/[tenantId]/users/index.ts
|
|
459
743
|
var key3 = "TENANT_USERS";
|
|
460
744
|
async function route3(request2, config) {
|
|
461
|
-
const { info } =
|
|
462
|
-
{ ...config, debug: config.debug },
|
|
463
|
-
`[ROUTES][${key3}]`
|
|
464
|
-
);
|
|
465
|
-
const session = await auth(request2, config);
|
|
466
|
-
if (!session) {
|
|
467
|
-
info("401");
|
|
468
|
-
return new Response(null, { status: 401 });
|
|
469
|
-
}
|
|
745
|
+
const { info } = config.logger(`[ROUTES][${key3}]`);
|
|
470
746
|
const yurl = new URL(request2.url);
|
|
471
747
|
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
472
748
|
if (!tenantId) {
|
|
@@ -477,7 +753,7 @@ async function route3(request2, config) {
|
|
|
477
753
|
case "GET":
|
|
478
754
|
return await GET3(config, { request: request2 });
|
|
479
755
|
case "POST":
|
|
480
|
-
return await POST2(config,
|
|
756
|
+
return await POST2(config, { request: request2 });
|
|
481
757
|
default:
|
|
482
758
|
return new Response("method not allowed", { status: 405 });
|
|
483
759
|
}
|
|
@@ -485,21 +761,22 @@ async function route3(request2, config) {
|
|
|
485
761
|
function matches3(configRoutes, request2) {
|
|
486
762
|
const url = new URL(request2.url);
|
|
487
763
|
const [userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
|
|
488
|
-
let
|
|
764
|
+
let route20 = configRoutes[key3].replace("{tenantId}", tenantId).replace("{userId}", userId);
|
|
489
765
|
if (userId === "users") {
|
|
490
|
-
|
|
766
|
+
route20 = configRoutes[key3].replace("{tenantId}", possibleTenantId);
|
|
491
767
|
}
|
|
492
|
-
return urlMatches(request2.url,
|
|
768
|
+
return urlMatches(request2.url, route20);
|
|
493
769
|
}
|
|
494
770
|
async function fetchTenantUsers(config, method, payload) {
|
|
495
771
|
const { body, params } = {};
|
|
496
|
-
|
|
772
|
+
const { tenantId, headers } = ctx.get();
|
|
773
|
+
if (!tenantId) {
|
|
497
774
|
throw new Error(
|
|
498
|
-
|
|
775
|
+
"Unable to fetch the user's tenants, the tenantId context is missing. Call nile.setContext({ tenantId })"
|
|
499
776
|
);
|
|
500
777
|
}
|
|
501
|
-
if (!isUUID(
|
|
502
|
-
config.logger
|
|
778
|
+
if (!isUUID(tenantId)) {
|
|
779
|
+
config.logger("fetchTenantUsers").warn(
|
|
503
780
|
"nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
504
781
|
);
|
|
505
782
|
}
|
|
@@ -510,31 +787,160 @@ async function fetchTenantUsers(config, method, payload) {
|
|
|
510
787
|
if (params?.tenantId) {
|
|
511
788
|
q.set("tenantId", params.tenantId);
|
|
512
789
|
}
|
|
513
|
-
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */.replace(
|
|
514
|
-
"{tenantId}",
|
|
515
|
-
config.tenantId
|
|
516
|
-
)}`;
|
|
790
|
+
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */.replace("{tenantId}", tenantId)}`;
|
|
517
791
|
const m = method;
|
|
518
792
|
const init = {
|
|
519
793
|
method: m,
|
|
520
|
-
headers
|
|
794
|
+
headers
|
|
795
|
+
};
|
|
796
|
+
const req = new Request(clientUrl, init);
|
|
797
|
+
return await config.handlers[m](req);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// src/api/routes/tenants/[tenantId]/invite/PUT.ts
|
|
801
|
+
async function PUT3(config, init) {
|
|
802
|
+
const yurl = new URL(init.request.url);
|
|
803
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
804
|
+
if (!tenantId) {
|
|
805
|
+
return new Response(null, { status: 404 });
|
|
806
|
+
}
|
|
807
|
+
if (yurl.searchParams.size > 0) {
|
|
808
|
+
init.body = new URLSearchParams(yurl.searchParams).toString();
|
|
809
|
+
}
|
|
810
|
+
init.method = "PUT";
|
|
811
|
+
const url = `${apiRoutes(config.apiUrl).INVITE(tenantId)}`;
|
|
812
|
+
const res = await request(url, init, config);
|
|
813
|
+
const location = res?.headers?.get("location");
|
|
814
|
+
if (location) {
|
|
815
|
+
return new Response(res?.body, {
|
|
816
|
+
status: 302,
|
|
817
|
+
headers: res?.headers
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
return new Response(res?.body, {
|
|
821
|
+
status: res?.status,
|
|
822
|
+
headers: res?.headers
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// src/api/routes/tenants/[tenantId]/invite/POST.ts
|
|
827
|
+
async function POST3(config, init) {
|
|
828
|
+
const yurl = new URL(init.request.url);
|
|
829
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
830
|
+
if (!tenantId) {
|
|
831
|
+
return new Response(null, { status: 404 });
|
|
832
|
+
}
|
|
833
|
+
init.method = "POST";
|
|
834
|
+
init.body = init.request.body;
|
|
835
|
+
const url = `${apiRoutes(config.apiUrl).INVITE(tenantId)}`;
|
|
836
|
+
return await request(url, init, config);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/api/routes/tenants/[tenantId]/invite/index.ts
|
|
840
|
+
var key4 = "INVITE";
|
|
841
|
+
async function route4(request2, config) {
|
|
842
|
+
switch (request2.method) {
|
|
843
|
+
// the browser is a GET, but we need to PUT it into nile-auth
|
|
844
|
+
// server side, this is a put
|
|
845
|
+
case "GET":
|
|
846
|
+
case "PUT":
|
|
847
|
+
return await PUT3(config, { request: request2 });
|
|
848
|
+
case "POST":
|
|
849
|
+
return await POST3(config, { request: request2 });
|
|
850
|
+
default:
|
|
851
|
+
return new Response("method not allowed", { status: 405 });
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
function matches4(configRoutes, request2) {
|
|
855
|
+
const url = new URL(request2.url);
|
|
856
|
+
const [, tenantId] = url.pathname.split("/").reverse();
|
|
857
|
+
const route20 = configRoutes[key4].replace("{tenantId}", tenantId);
|
|
858
|
+
return urlMatches(request2.url, route20);
|
|
859
|
+
}
|
|
860
|
+
async function fetchInvite(config, method, body) {
|
|
861
|
+
const { headers, tenantId } = ctx.get();
|
|
862
|
+
if (!tenantId) {
|
|
863
|
+
throw new Error(
|
|
864
|
+
"Unable to fetch the invite for the tenant, the tenantId context is missing. Call nile.setContext({ tenantId })"
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
if (!isUUID(tenantId)) {
|
|
868
|
+
config.logger("fetchInvite").warn(
|
|
869
|
+
"nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
let clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace("{tenantId}", tenantId)}`;
|
|
873
|
+
const m = method ?? "GET";
|
|
874
|
+
const init = {
|
|
875
|
+
method: m,
|
|
876
|
+
headers
|
|
521
877
|
};
|
|
878
|
+
if (method === "POST" || method === "PUT") {
|
|
879
|
+
init.body = body;
|
|
880
|
+
}
|
|
881
|
+
if (method === "DELETE") {
|
|
882
|
+
clientUrl = `${clientUrl}/${body}`;
|
|
883
|
+
}
|
|
522
884
|
const req = new Request(clientUrl, init);
|
|
523
885
|
return await config.handlers[m](req);
|
|
524
886
|
}
|
|
525
887
|
|
|
888
|
+
// src/api/routes/tenants/[tenantId]/invites/GET.ts
|
|
889
|
+
async function GET4(config, init) {
|
|
890
|
+
const yurl = new URL(init.request.url);
|
|
891
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
892
|
+
if (!tenantId) {
|
|
893
|
+
return new Response(null, { status: 404 });
|
|
894
|
+
}
|
|
895
|
+
init.method = "GET";
|
|
896
|
+
const url = `${apiRoutes(config.apiUrl).INVITES(tenantId)}`;
|
|
897
|
+
return await request(url, init, config);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// src/api/routes/tenants/[tenantId]/invites/index.ts
|
|
901
|
+
var key5 = "INVITES";
|
|
902
|
+
async function route5(request2, config) {
|
|
903
|
+
switch (request2.method) {
|
|
904
|
+
case "GET":
|
|
905
|
+
return await GET4(config, { request: request2 });
|
|
906
|
+
default:
|
|
907
|
+
return new Response("method not allowed", { status: 405 });
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function matches5(configRoutes, request2) {
|
|
911
|
+
const url = new URL(request2.url);
|
|
912
|
+
const [, tenantId] = url.pathname.split("/").reverse();
|
|
913
|
+
const route20 = configRoutes[key5].replace("{tenantId}", tenantId);
|
|
914
|
+
return url.pathname.endsWith(route20);
|
|
915
|
+
}
|
|
916
|
+
async function fetchInvites(config) {
|
|
917
|
+
const { tenantId, headers } = ctx.get();
|
|
918
|
+
if (!tenantId) {
|
|
919
|
+
throw new Error(
|
|
920
|
+
"Unable to fetch invites for the tenant, the tenantId context is missing. Call nile.setContext({ tenantId })"
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
if (!isUUID(tenantId)) {
|
|
924
|
+
config.logger("fetchInvites").warn(
|
|
925
|
+
"nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/invites" /* INVITES */.replace("{tenantId}", tenantId)}`;
|
|
929
|
+
const req = new Request(clientUrl, { headers });
|
|
930
|
+
return await config.handlers.GET(req);
|
|
931
|
+
}
|
|
932
|
+
|
|
526
933
|
// src/api/routes/tenants/GET.ts
|
|
527
|
-
async function
|
|
528
|
-
let url = `${apiRoutes(config).USER_TENANTS(session.id)}`;
|
|
934
|
+
async function GET5(config, session, init) {
|
|
935
|
+
let url = `${apiRoutes(config.apiUrl).USER_TENANTS(session.id)}`;
|
|
529
936
|
if (typeof session === "object" && "user" in session && session.user) {
|
|
530
|
-
url = `${apiRoutes(config).USER_TENANTS(session.user.id)}`;
|
|
937
|
+
url = `${apiRoutes(config.apiUrl).USER_TENANTS(session.user.id)}`;
|
|
531
938
|
}
|
|
532
|
-
|
|
533
|
-
return res;
|
|
939
|
+
return await request(url, init, config);
|
|
534
940
|
}
|
|
535
941
|
|
|
536
942
|
// src/api/routes/tenants/[tenantId]/GET.ts
|
|
537
|
-
async function
|
|
943
|
+
async function GET6(config, init, log) {
|
|
538
944
|
const yurl = new URL(init.request.url);
|
|
539
945
|
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
540
946
|
if (!tenantId) {
|
|
@@ -542,7 +948,7 @@ async function GET5(config, init, log) {
|
|
|
542
948
|
return new Response(null, { status: 404 });
|
|
543
949
|
}
|
|
544
950
|
init.method = "GET";
|
|
545
|
-
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
951
|
+
const url = `${apiRoutes(config.apiUrl).TENANT(tenantId)}`;
|
|
546
952
|
return await request(url, init, config);
|
|
547
953
|
}
|
|
548
954
|
|
|
@@ -554,12 +960,12 @@ async function DELETE2(config, init) {
|
|
|
554
960
|
return new Response(null, { status: 404 });
|
|
555
961
|
}
|
|
556
962
|
init.method = "DELETE";
|
|
557
|
-
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
963
|
+
const url = `${apiRoutes(config.apiUrl).TENANT(tenantId)}`;
|
|
558
964
|
return await request(url, init, config);
|
|
559
965
|
}
|
|
560
966
|
|
|
561
967
|
// src/api/routes/tenants/[tenantId]/PUT.ts
|
|
562
|
-
async function
|
|
968
|
+
async function PUT4(config, init) {
|
|
563
969
|
const yurl = new URL(init.request.url);
|
|
564
970
|
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
565
971
|
if (!tenantId) {
|
|
@@ -567,25 +973,22 @@ async function PUT3(config, init) {
|
|
|
567
973
|
}
|
|
568
974
|
init.body = init.request.body;
|
|
569
975
|
init.method = "PUT";
|
|
570
|
-
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
976
|
+
const url = `${apiRoutes(config.apiUrl).TENANT(tenantId)}`;
|
|
571
977
|
return await request(url, init, config);
|
|
572
978
|
}
|
|
573
979
|
|
|
574
980
|
// src/api/routes/tenants/POST.ts
|
|
575
|
-
async function
|
|
981
|
+
async function POST4(config, init) {
|
|
576
982
|
init.body = init.request.body;
|
|
577
983
|
init.method = "POST";
|
|
578
|
-
const url = `${apiRoutes(config).TENANTS}`;
|
|
984
|
+
const url = `${apiRoutes(config.apiUrl).TENANTS}`;
|
|
579
985
|
return await request(url, init, config);
|
|
580
986
|
}
|
|
581
987
|
|
|
582
988
|
// src/api/routes/tenants/index.ts
|
|
583
|
-
var
|
|
584
|
-
async function
|
|
585
|
-
const { info } =
|
|
586
|
-
{ ...config, debug: config.debug },
|
|
587
|
-
`[ROUTES][${key4}]`
|
|
588
|
-
);
|
|
989
|
+
var key6 = "TENANTS";
|
|
990
|
+
async function route6(request2, config) {
|
|
991
|
+
const { info } = config.logger(`[ROUTES][${key6}]`);
|
|
589
992
|
const session = await auth(request2, config);
|
|
590
993
|
if (!session) {
|
|
591
994
|
info("401");
|
|
@@ -595,27 +998,28 @@ async function route4(request2, config) {
|
|
|
595
998
|
switch (request2.method) {
|
|
596
999
|
case "GET":
|
|
597
1000
|
if (isUUID(possibleTenantId)) {
|
|
598
|
-
return await
|
|
1001
|
+
return await GET6(config, { request: request2 }, info);
|
|
599
1002
|
}
|
|
600
|
-
return await
|
|
1003
|
+
return await GET5(config, session, { request: request2 });
|
|
601
1004
|
case "POST":
|
|
602
|
-
return await
|
|
1005
|
+
return await POST4(config, { request: request2 });
|
|
603
1006
|
case "DELETE":
|
|
604
1007
|
return await DELETE2(config, { request: request2 });
|
|
605
1008
|
case "PUT":
|
|
606
|
-
return await
|
|
1009
|
+
return await PUT4(config, { request: request2 });
|
|
607
1010
|
default:
|
|
608
1011
|
return new Response("method not allowed", { status: 405 });
|
|
609
1012
|
}
|
|
610
1013
|
}
|
|
611
|
-
function
|
|
612
|
-
return urlMatches(request2.url, configRoutes[
|
|
1014
|
+
function matches6(configRoutes, request2) {
|
|
1015
|
+
return urlMatches(request2.url, configRoutes[key6]);
|
|
613
1016
|
}
|
|
614
1017
|
async function fetchTenants(config, method, body) {
|
|
1018
|
+
const { headers } = ctx.get();
|
|
615
1019
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants" /* TENANTS */}`;
|
|
616
1020
|
const init = {
|
|
617
1021
|
method,
|
|
618
|
-
headers
|
|
1022
|
+
headers
|
|
619
1023
|
};
|
|
620
1024
|
{
|
|
621
1025
|
init.body = body;
|
|
@@ -624,21 +1028,22 @@ async function fetchTenants(config, method, body) {
|
|
|
624
1028
|
return await config.handlers.POST(req);
|
|
625
1029
|
}
|
|
626
1030
|
async function fetchTenant(config, method, body) {
|
|
627
|
-
|
|
1031
|
+
const { headers, tenantId } = ctx.get();
|
|
1032
|
+
if (!tenantId) {
|
|
628
1033
|
throw new Error(
|
|
629
|
-
|
|
1034
|
+
"Unable to fetch tenants, the tenantId context is missing. Call nile.setContext({ tenantId })"
|
|
630
1035
|
);
|
|
631
1036
|
}
|
|
632
|
-
if (!isUUID(
|
|
633
|
-
config.logger
|
|
1037
|
+
if (!isUUID(tenantId)) {
|
|
1038
|
+
config.logger("fetch tenant").warn(
|
|
634
1039
|
"nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
635
1040
|
);
|
|
636
1041
|
}
|
|
637
|
-
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}" /* TENANT */.replace("{tenantId}",
|
|
1042
|
+
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}" /* TENANT */.replace("{tenantId}", tenantId)}`;
|
|
638
1043
|
const m = method ?? "GET";
|
|
639
1044
|
const init = {
|
|
640
1045
|
method: m,
|
|
641
|
-
headers
|
|
1046
|
+
headers
|
|
642
1047
|
};
|
|
643
1048
|
if (m === "PUT") {
|
|
644
1049
|
init.body = body;
|
|
@@ -647,36 +1052,33 @@ async function fetchTenant(config, method, body) {
|
|
|
647
1052
|
return await config.handlers[m](req);
|
|
648
1053
|
}
|
|
649
1054
|
async function fetchTenantsByUser(config) {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
1055
|
+
const { warn: warn2 } = config.logger(" fetchTenantsByUser ");
|
|
1056
|
+
const { userId, headers } = ctx.get();
|
|
1057
|
+
if (!userId) {
|
|
1058
|
+
warn2(
|
|
1059
|
+
"nile.userId is not set. The call will still work for the API, but the database context is not set properly and may lead to unexpected behavior in your application."
|
|
1060
|
+
);
|
|
1061
|
+
} else if (!isUUID(userId)) {
|
|
1062
|
+
warn2(
|
|
1063
|
+
"nile.userId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
1064
|
+
);
|
|
660
1065
|
}
|
|
661
|
-
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/
|
|
662
|
-
|
|
663
|
-
config.userId ?? "WARN_NOT_SET"
|
|
664
|
-
)}`;
|
|
665
|
-
const req = new Request(clientUrl, { headers: config.headers });
|
|
1066
|
+
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants" /* TENANTS */}`;
|
|
1067
|
+
const req = new Request(clientUrl, { headers });
|
|
666
1068
|
return await config.handlers.GET(req);
|
|
667
1069
|
}
|
|
668
1070
|
|
|
669
1071
|
// src/api/routes/auth/signin.ts
|
|
670
|
-
var
|
|
671
|
-
async function
|
|
672
|
-
let url = proxyRoutes(config)[
|
|
1072
|
+
var key7 = "SIGNIN";
|
|
1073
|
+
async function route7(req, config) {
|
|
1074
|
+
let url = proxyRoutes(config.apiUrl)[key7];
|
|
673
1075
|
const init = {
|
|
674
1076
|
method: req.method,
|
|
675
1077
|
headers: req.headers
|
|
676
1078
|
};
|
|
677
1079
|
if (req.method === "POST") {
|
|
678
1080
|
const [provider] = new URL(req.url).pathname.split("/").reverse();
|
|
679
|
-
url = `${proxyRoutes(config)[
|
|
1081
|
+
url = `${proxyRoutes(config.apiUrl)[key7]}/${provider}`;
|
|
680
1082
|
}
|
|
681
1083
|
const passThroughUrl = new URL(req.url);
|
|
682
1084
|
const params = new URLSearchParams(passThroughUrl.search);
|
|
@@ -684,23 +1086,24 @@ async function route5(req, config) {
|
|
|
684
1086
|
const res = await request(url, { ...init, request: req }, config);
|
|
685
1087
|
return res;
|
|
686
1088
|
}
|
|
687
|
-
function
|
|
688
|
-
return urlMatches(request2.url, configRoutes[
|
|
1089
|
+
function matches7(configRoutes, request2) {
|
|
1090
|
+
return urlMatches(request2.url, configRoutes[key7]);
|
|
689
1091
|
}
|
|
690
1092
|
async function fetchSignIn(config, provider, body) {
|
|
691
1093
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/signin" /* SIGNIN */}/${provider}`;
|
|
1094
|
+
const { headers } = ctx.get();
|
|
692
1095
|
const req = new Request(clientUrl, {
|
|
693
1096
|
method: "POST",
|
|
694
|
-
|
|
695
|
-
|
|
1097
|
+
body,
|
|
1098
|
+
headers
|
|
696
1099
|
});
|
|
697
1100
|
return await config.handlers.POST(req);
|
|
698
1101
|
}
|
|
699
1102
|
|
|
700
1103
|
// src/api/routes/auth/session.ts
|
|
701
|
-
async function
|
|
1104
|
+
async function route8(req, config) {
|
|
702
1105
|
return request(
|
|
703
|
-
proxyRoutes(config).SESSION,
|
|
1106
|
+
proxyRoutes(config.apiUrl).SESSION,
|
|
704
1107
|
{
|
|
705
1108
|
method: req.method,
|
|
706
1109
|
request: req
|
|
@@ -708,22 +1111,23 @@ async function route6(req, config) {
|
|
|
708
1111
|
config
|
|
709
1112
|
);
|
|
710
1113
|
}
|
|
711
|
-
function
|
|
1114
|
+
function matches8(configRoutes, request2) {
|
|
712
1115
|
return urlMatches(request2.url, configRoutes.SESSION);
|
|
713
1116
|
}
|
|
714
1117
|
async function fetchSession(config) {
|
|
715
1118
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/session" /* SESSION */}`;
|
|
1119
|
+
const { headers } = ctx.get();
|
|
716
1120
|
const req = new Request(clientUrl, {
|
|
717
1121
|
method: "GET",
|
|
718
|
-
headers
|
|
1122
|
+
headers
|
|
719
1123
|
});
|
|
720
1124
|
return await config.handlers.GET(req);
|
|
721
1125
|
}
|
|
722
1126
|
|
|
723
1127
|
// src/api/routes/auth/providers.ts
|
|
724
|
-
async function
|
|
1128
|
+
async function route9(req, config) {
|
|
725
1129
|
return request(
|
|
726
|
-
proxyRoutes(config).PROVIDERS,
|
|
1130
|
+
proxyRoutes(config.apiUrl).PROVIDERS,
|
|
727
1131
|
{
|
|
728
1132
|
method: req.method,
|
|
729
1133
|
request: req
|
|
@@ -731,22 +1135,23 @@ async function route7(req, config) {
|
|
|
731
1135
|
config
|
|
732
1136
|
);
|
|
733
1137
|
}
|
|
734
|
-
function
|
|
1138
|
+
function matches9(configRoutes, request2) {
|
|
735
1139
|
return urlMatches(request2.url, configRoutes.PROVIDERS);
|
|
736
1140
|
}
|
|
737
1141
|
async function fetchProviders(config) {
|
|
738
1142
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/providers" /* PROVIDERS */}`;
|
|
1143
|
+
const { headers } = ctx.get();
|
|
739
1144
|
const req = new Request(clientUrl, {
|
|
740
1145
|
method: "GET",
|
|
741
|
-
headers
|
|
1146
|
+
headers
|
|
742
1147
|
});
|
|
743
1148
|
return await config.handlers.GET(req);
|
|
744
1149
|
}
|
|
745
1150
|
|
|
746
1151
|
// src/api/routes/auth/csrf.ts
|
|
747
|
-
async function
|
|
1152
|
+
async function route10(req, config) {
|
|
748
1153
|
return request(
|
|
749
|
-
proxyRoutes(config).CSRF,
|
|
1154
|
+
proxyRoutes(config.apiUrl).CSRF,
|
|
750
1155
|
{
|
|
751
1156
|
method: req.method,
|
|
752
1157
|
request: req
|
|
@@ -754,30 +1159,28 @@ async function route8(req, config) {
|
|
|
754
1159
|
config
|
|
755
1160
|
);
|
|
756
1161
|
}
|
|
757
|
-
function
|
|
1162
|
+
function matches10(configRoutes, request2) {
|
|
758
1163
|
return urlMatches(request2.url, configRoutes.CSRF);
|
|
759
1164
|
}
|
|
760
1165
|
async function fetchCsrf(config) {
|
|
761
1166
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/csrf" /* CSRF */}`;
|
|
1167
|
+
const { headers } = ctx.get();
|
|
762
1168
|
const req = new Request(clientUrl, {
|
|
763
1169
|
method: "GET",
|
|
764
|
-
headers
|
|
1170
|
+
headers
|
|
765
1171
|
});
|
|
766
1172
|
return await config.handlers.GET(req);
|
|
767
1173
|
}
|
|
768
1174
|
|
|
769
1175
|
// src/api/routes/auth/callback.ts
|
|
770
|
-
var
|
|
771
|
-
async function
|
|
772
|
-
const { error } =
|
|
773
|
-
{ ...config, debug: config.debug },
|
|
774
|
-
`[ROUTES][${key6}]`
|
|
775
|
-
);
|
|
1176
|
+
var key8 = "CALLBACK";
|
|
1177
|
+
async function route11(req, config) {
|
|
1178
|
+
const { error } = config.logger(`[ROUTES][${key8}]`);
|
|
776
1179
|
const [provider] = new URL(req.url).pathname.split("/").reverse();
|
|
777
1180
|
try {
|
|
778
1181
|
const passThroughUrl = new URL(req.url);
|
|
779
1182
|
const params = new URLSearchParams(passThroughUrl.search);
|
|
780
|
-
const url = `${proxyRoutes(config)[
|
|
1183
|
+
const url = `${proxyRoutes(config.apiUrl)[key8]}/${provider}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
|
|
781
1184
|
const res = await request(
|
|
782
1185
|
url,
|
|
783
1186
|
{
|
|
@@ -788,7 +1191,7 @@ async function route9(req, config) {
|
|
|
788
1191
|
).catch((e) => {
|
|
789
1192
|
error("an error as occurred", e);
|
|
790
1193
|
});
|
|
791
|
-
const location = res?.headers
|
|
1194
|
+
const location = res?.headers?.get("location");
|
|
792
1195
|
if (location) {
|
|
793
1196
|
return new Response(res?.body, {
|
|
794
1197
|
status: 302,
|
|
@@ -804,52 +1207,54 @@ async function route9(req, config) {
|
|
|
804
1207
|
}
|
|
805
1208
|
return new Response("An unexpected error has occurred.", { status: 400 });
|
|
806
1209
|
}
|
|
807
|
-
function
|
|
1210
|
+
function matches11(configRoutes, request2) {
|
|
808
1211
|
return urlMatches(request2.url, configRoutes.CALLBACK);
|
|
809
1212
|
}
|
|
810
1213
|
async function fetchCallback(config, provider, body, request2, method = "POST") {
|
|
1214
|
+
const { headers } = ctx.get();
|
|
811
1215
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/callback" /* CALLBACK */}/${provider}${request2 ? `?${new URL(request2.url).searchParams}` : ""}`;
|
|
812
1216
|
const req = new Request(clientUrl, {
|
|
813
1217
|
method,
|
|
814
|
-
headers
|
|
1218
|
+
headers,
|
|
815
1219
|
body
|
|
816
1220
|
});
|
|
817
1221
|
return await config.handlers.POST(req);
|
|
818
1222
|
}
|
|
819
1223
|
|
|
820
1224
|
// src/api/routes/auth/signout.ts
|
|
821
|
-
var
|
|
822
|
-
async function
|
|
823
|
-
let url = proxyRoutes(config)[
|
|
1225
|
+
var key9 = "SIGNOUT";
|
|
1226
|
+
async function route12(request2, config) {
|
|
1227
|
+
let url = proxyRoutes(config.apiUrl)[key9];
|
|
824
1228
|
const init = {
|
|
825
1229
|
method: request2.method
|
|
826
1230
|
};
|
|
827
1231
|
if (request2.method === "POST") {
|
|
828
1232
|
init.body = request2.body;
|
|
829
1233
|
const [provider] = new URL(request2.url).pathname.split("/").reverse();
|
|
830
|
-
url = `${proxyRoutes(config)[
|
|
1234
|
+
url = `${proxyRoutes(config.apiUrl)[key9]}${provider !== "signout" ? `/${provider}` : ""}`;
|
|
831
1235
|
}
|
|
832
1236
|
const res = await request(url, { ...init, request: request2 }, config);
|
|
833
1237
|
return res;
|
|
834
1238
|
}
|
|
835
|
-
function
|
|
836
|
-
return urlMatches(request2.url, configRoutes[
|
|
1239
|
+
function matches12(configRoutes, request2) {
|
|
1240
|
+
return urlMatches(request2.url, configRoutes[key9]);
|
|
837
1241
|
}
|
|
838
1242
|
async function fetchSignOut(config, body) {
|
|
839
1243
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/signout" /* SIGNOUT */}`;
|
|
1244
|
+
const { headers } = ctx.get();
|
|
840
1245
|
const req = new Request(clientUrl, {
|
|
841
1246
|
method: "POST",
|
|
842
1247
|
body,
|
|
843
|
-
headers
|
|
1248
|
+
headers
|
|
844
1249
|
});
|
|
845
1250
|
return await config.handlers.POST(req);
|
|
846
1251
|
}
|
|
847
1252
|
|
|
848
1253
|
// src/api/routes/auth/error.ts
|
|
849
|
-
var
|
|
850
|
-
async function
|
|
1254
|
+
var key10 = "ERROR";
|
|
1255
|
+
async function route13(req, config) {
|
|
851
1256
|
return request(
|
|
852
|
-
proxyRoutes(config)[
|
|
1257
|
+
proxyRoutes(config.apiUrl)[key10],
|
|
853
1258
|
{
|
|
854
1259
|
method: req.method,
|
|
855
1260
|
request: req
|
|
@@ -857,15 +1262,15 @@ async function route11(req, config) {
|
|
|
857
1262
|
config
|
|
858
1263
|
);
|
|
859
1264
|
}
|
|
860
|
-
function
|
|
861
|
-
return urlMatches(request2.url, configRoutes[
|
|
1265
|
+
function matches13(configRoutes, request2) {
|
|
1266
|
+
return urlMatches(request2.url, configRoutes[key10]);
|
|
862
1267
|
}
|
|
863
1268
|
|
|
864
1269
|
// src/api/routes/auth/verify-request.ts
|
|
865
|
-
var
|
|
866
|
-
async function
|
|
1270
|
+
var key11 = "VERIFY_REQUEST";
|
|
1271
|
+
async function route14(req, config) {
|
|
867
1272
|
return request(
|
|
868
|
-
proxyRoutes(config)[
|
|
1273
|
+
proxyRoutes(config.apiUrl)[key11],
|
|
869
1274
|
{
|
|
870
1275
|
method: req.method,
|
|
871
1276
|
request: req
|
|
@@ -873,14 +1278,14 @@ async function route12(req, config) {
|
|
|
873
1278
|
config
|
|
874
1279
|
);
|
|
875
1280
|
}
|
|
876
|
-
function
|
|
877
|
-
return urlMatches(request2.url, configRoutes[
|
|
1281
|
+
function matches14(configRoutes, request2) {
|
|
1282
|
+
return urlMatches(request2.url, configRoutes[key11]);
|
|
878
1283
|
}
|
|
879
1284
|
|
|
880
1285
|
// src/api/routes/auth/password-reset.ts
|
|
881
|
-
var
|
|
882
|
-
async function
|
|
883
|
-
const url = proxyRoutes(config)[
|
|
1286
|
+
var key12 = "PASSWORD_RESET";
|
|
1287
|
+
async function route15(req, config) {
|
|
1288
|
+
const url = proxyRoutes(config.apiUrl)[key12];
|
|
884
1289
|
const res = await request(
|
|
885
1290
|
url,
|
|
886
1291
|
{
|
|
@@ -889,7 +1294,7 @@ async function route13(req, config) {
|
|
|
889
1294
|
},
|
|
890
1295
|
config
|
|
891
1296
|
);
|
|
892
|
-
const location = res?.headers
|
|
1297
|
+
const location = res?.headers?.get("location");
|
|
893
1298
|
if (location) {
|
|
894
1299
|
return new Response(res?.body, {
|
|
895
1300
|
status: 302,
|
|
@@ -901,7 +1306,7 @@ async function route13(req, config) {
|
|
|
901
1306
|
headers: res?.headers
|
|
902
1307
|
});
|
|
903
1308
|
}
|
|
904
|
-
function
|
|
1309
|
+
function matches15(configRoutes, request2) {
|
|
905
1310
|
return urlMatches(request2.url, configRoutes.PASSWORD_RESET);
|
|
906
1311
|
}
|
|
907
1312
|
async function fetchResetPassword(config, method, body, params, useJson = true) {
|
|
@@ -909,10 +1314,11 @@ async function fetchResetPassword(config, method, body, params, useJson = true)
|
|
|
909
1314
|
if (useJson) {
|
|
910
1315
|
authParams?.set("json", "true");
|
|
911
1316
|
}
|
|
1317
|
+
const { headers } = ctx.get();
|
|
912
1318
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/reset-password" /* PASSWORD_RESET */}?${authParams?.toString()}`;
|
|
913
1319
|
const init = {
|
|
914
1320
|
method,
|
|
915
|
-
headers
|
|
1321
|
+
headers
|
|
916
1322
|
};
|
|
917
1323
|
if (body && method !== "GET") {
|
|
918
1324
|
init.body = body;
|
|
@@ -922,9 +1328,9 @@ async function fetchResetPassword(config, method, body, params, useJson = true)
|
|
|
922
1328
|
}
|
|
923
1329
|
|
|
924
1330
|
// src/api/routes/auth/verify-email.ts
|
|
925
|
-
var
|
|
926
|
-
async function
|
|
927
|
-
const url = proxyRoutes(config)[
|
|
1331
|
+
var key13 = "VERIFY_EMAIL";
|
|
1332
|
+
async function route16(req, config) {
|
|
1333
|
+
const url = proxyRoutes(config.apiUrl)[key13];
|
|
928
1334
|
const res = await request(
|
|
929
1335
|
url,
|
|
930
1336
|
{
|
|
@@ -933,7 +1339,7 @@ async function route14(req, config) {
|
|
|
933
1339
|
},
|
|
934
1340
|
config
|
|
935
1341
|
);
|
|
936
|
-
const location = res?.headers
|
|
1342
|
+
const location = res?.headers?.get("location");
|
|
937
1343
|
if (location) {
|
|
938
1344
|
return new Response(res?.body, {
|
|
939
1345
|
status: 302,
|
|
@@ -945,14 +1351,15 @@ async function route14(req, config) {
|
|
|
945
1351
|
headers: res?.headers
|
|
946
1352
|
});
|
|
947
1353
|
}
|
|
948
|
-
function
|
|
949
|
-
return urlMatches(request2.url, configRoutes[
|
|
1354
|
+
function matches16(configRoutes, request2) {
|
|
1355
|
+
return urlMatches(request2.url, configRoutes[key13]);
|
|
950
1356
|
}
|
|
951
1357
|
async function fetchVerifyEmail(config, method, body) {
|
|
952
1358
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/auth/verify-email" /* VERIFY_EMAIL */}`;
|
|
1359
|
+
const { headers } = ctx.get();
|
|
953
1360
|
const init = {
|
|
954
1361
|
method,
|
|
955
|
-
headers
|
|
1362
|
+
headers
|
|
956
1363
|
};
|
|
957
1364
|
if (body) {
|
|
958
1365
|
init.body = body;
|
|
@@ -963,89 +1370,110 @@ async function fetchVerifyEmail(config, method, body) {
|
|
|
963
1370
|
|
|
964
1371
|
// src/api/handlers/GET.ts
|
|
965
1372
|
function GETTER(configRoutes, config) {
|
|
966
|
-
const { info, warn } =
|
|
967
|
-
return async function
|
|
968
|
-
|
|
969
|
-
|
|
1373
|
+
const { error, info, warn: warn2 } = config.logger("[GET MATCHER]");
|
|
1374
|
+
return async function GET7(...params) {
|
|
1375
|
+
const handledRequest = await config.extensionCtx?.runExtensions(
|
|
1376
|
+
"onHandleRequest" /* onHandleRequest */,
|
|
1377
|
+
config,
|
|
1378
|
+
params
|
|
1379
|
+
);
|
|
1380
|
+
if (handledRequest) {
|
|
1381
|
+
return handledRequest;
|
|
1382
|
+
}
|
|
1383
|
+
const req = params[0] instanceof Request ? params[0] : null;
|
|
1384
|
+
if (!req) {
|
|
1385
|
+
error("Proxy requests failed, a Request object was not passed.");
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
if (matches(configRoutes, req)) {
|
|
1389
|
+
info("matches me");
|
|
970
1390
|
return route(req, config);
|
|
971
1391
|
}
|
|
1392
|
+
if (matches5(configRoutes, req)) {
|
|
1393
|
+
info("matches tenant invites");
|
|
1394
|
+
return route5(req, config);
|
|
1395
|
+
}
|
|
1396
|
+
if (matches4(configRoutes, req)) {
|
|
1397
|
+
info("matches invite");
|
|
1398
|
+
return route4(req, config);
|
|
1399
|
+
}
|
|
972
1400
|
if (matches3(configRoutes, req)) {
|
|
973
1401
|
info("matches tenant users");
|
|
974
1402
|
return route3(req, config);
|
|
975
1403
|
}
|
|
1404
|
+
if (matches6(configRoutes, req)) {
|
|
1405
|
+
info("matches tenants");
|
|
1406
|
+
return route6(req, config);
|
|
1407
|
+
}
|
|
976
1408
|
if (matches2(configRoutes, req)) {
|
|
977
1409
|
info("matches users");
|
|
978
1410
|
return route2(req, config);
|
|
979
1411
|
}
|
|
980
|
-
if (
|
|
981
|
-
info("matches tenants");
|
|
982
|
-
return route4(req, config);
|
|
983
|
-
}
|
|
984
|
-
if (matches6(configRoutes, req)) {
|
|
1412
|
+
if (matches8(configRoutes, req)) {
|
|
985
1413
|
info("matches session");
|
|
986
|
-
return
|
|
1414
|
+
return route8(req, config);
|
|
987
1415
|
}
|
|
988
|
-
if (
|
|
1416
|
+
if (matches7(configRoutes, req)) {
|
|
989
1417
|
info("matches signin");
|
|
990
|
-
return
|
|
1418
|
+
return route7(req, config);
|
|
991
1419
|
}
|
|
992
|
-
if (
|
|
1420
|
+
if (matches9(configRoutes, req)) {
|
|
993
1421
|
info("matches providers");
|
|
994
|
-
return
|
|
1422
|
+
return route9(req, config);
|
|
995
1423
|
}
|
|
996
|
-
if (
|
|
1424
|
+
if (matches10(configRoutes, req)) {
|
|
997
1425
|
info("matches csrf");
|
|
998
|
-
return
|
|
1426
|
+
return route10(req, config);
|
|
999
1427
|
}
|
|
1000
|
-
if (
|
|
1428
|
+
if (matches15(configRoutes, req)) {
|
|
1001
1429
|
info("matches password reset");
|
|
1002
|
-
return
|
|
1430
|
+
return route15(req, config);
|
|
1003
1431
|
}
|
|
1004
|
-
if (
|
|
1432
|
+
if (matches11(configRoutes, req)) {
|
|
1005
1433
|
info("matches callback");
|
|
1006
|
-
return
|
|
1007
|
-
}
|
|
1008
|
-
if (matches10(configRoutes, req)) {
|
|
1009
|
-
info("matches signout");
|
|
1010
|
-
return route10(req, config);
|
|
1434
|
+
return route11(req, config);
|
|
1011
1435
|
}
|
|
1012
1436
|
if (matches12(configRoutes, req)) {
|
|
1013
|
-
info("matches
|
|
1437
|
+
info("matches signout");
|
|
1014
1438
|
return route12(req, config);
|
|
1015
1439
|
}
|
|
1016
1440
|
if (matches14(configRoutes, req)) {
|
|
1017
|
-
info("matches verify-
|
|
1441
|
+
info("matches verify-request");
|
|
1018
1442
|
return route14(req, config);
|
|
1019
1443
|
}
|
|
1020
|
-
if (
|
|
1444
|
+
if (matches16(configRoutes, req)) {
|
|
1445
|
+
info("matches verify-email");
|
|
1446
|
+
return route16(req, config);
|
|
1447
|
+
}
|
|
1448
|
+
if (matches13(configRoutes, req)) {
|
|
1021
1449
|
info("matches error");
|
|
1022
|
-
return
|
|
1450
|
+
return route13(req, config);
|
|
1023
1451
|
}
|
|
1024
|
-
|
|
1452
|
+
warn2(`No GET routes matched ${req.url}`);
|
|
1025
1453
|
return new Response(null, { status: 404 });
|
|
1026
1454
|
};
|
|
1027
1455
|
}
|
|
1028
1456
|
|
|
1029
1457
|
// src/api/routes/signup/POST.ts
|
|
1030
|
-
async function
|
|
1458
|
+
async function POST5(config, init) {
|
|
1031
1459
|
init.body = init.request.body;
|
|
1032
1460
|
init.method = "POST";
|
|
1033
|
-
const url = `${apiRoutes(config).SIGNUP}`;
|
|
1461
|
+
const url = `${apiRoutes(config.apiUrl).SIGNUP}`;
|
|
1034
1462
|
return await request(url, init, config);
|
|
1035
1463
|
}
|
|
1036
1464
|
|
|
1037
1465
|
// src/api/routes/signup/index.tsx
|
|
1038
|
-
var
|
|
1039
|
-
async function
|
|
1466
|
+
var key14 = "SIGNUP";
|
|
1467
|
+
async function route17(request2, config) {
|
|
1040
1468
|
switch (request2.method) {
|
|
1041
1469
|
case "POST":
|
|
1042
|
-
return await
|
|
1470
|
+
return await POST5(config, { request: request2 });
|
|
1043
1471
|
default:
|
|
1044
1472
|
return new Response("method not allowed", { status: 405 });
|
|
1045
1473
|
}
|
|
1046
1474
|
}
|
|
1047
|
-
function
|
|
1048
|
-
return urlMatches(request2.url, configRoutes[
|
|
1475
|
+
function matches17(configRoutes, request2) {
|
|
1476
|
+
return urlMatches(request2.url, configRoutes[key14]);
|
|
1049
1477
|
}
|
|
1050
1478
|
async function fetchSignUp(config, payload) {
|
|
1051
1479
|
const { body, params } = payload ?? {};
|
|
@@ -1057,9 +1485,10 @@ async function fetchSignUp(config, payload) {
|
|
|
1057
1485
|
q.set("tenantId", params.tenantId);
|
|
1058
1486
|
}
|
|
1059
1487
|
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/signup" /* SIGNUP */}${q.size > 0 ? `?${q}` : ""}`;
|
|
1488
|
+
const { headers } = ctx.get();
|
|
1060
1489
|
const req = new Request(clientUrl, {
|
|
1061
1490
|
method: "POST",
|
|
1062
|
-
headers
|
|
1491
|
+
headers,
|
|
1063
1492
|
body
|
|
1064
1493
|
});
|
|
1065
1494
|
return await config.handlers.POST(req);
|
|
@@ -1067,8 +1496,21 @@ async function fetchSignUp(config, payload) {
|
|
|
1067
1496
|
|
|
1068
1497
|
// src/api/handlers/POST.ts
|
|
1069
1498
|
function POSTER(configRoutes, config) {
|
|
1070
|
-
const { info, warn, error } =
|
|
1071
|
-
return async function
|
|
1499
|
+
const { info, warn: warn2, error } = config.logger("[POST MATCHER]");
|
|
1500
|
+
return async function POST6(...params) {
|
|
1501
|
+
const handledRequest = await config.extensionCtx?.runExtensions(
|
|
1502
|
+
"onHandleRequest" /* onHandleRequest */,
|
|
1503
|
+
config,
|
|
1504
|
+
params
|
|
1505
|
+
);
|
|
1506
|
+
if (handledRequest) {
|
|
1507
|
+
return handledRequest;
|
|
1508
|
+
}
|
|
1509
|
+
const req = params[0] instanceof Request ? params[0] : null;
|
|
1510
|
+
if (!req) {
|
|
1511
|
+
error("Proxy requests failed, a Request object was not passed.");
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1072
1514
|
if (matchesLog(configRoutes, req)) {
|
|
1073
1515
|
try {
|
|
1074
1516
|
const json = await req.clone().json();
|
|
@@ -1082,51 +1524,51 @@ function POSTER(configRoutes, config) {
|
|
|
1082
1524
|
info("matches tenant users");
|
|
1083
1525
|
return route3(req, config);
|
|
1084
1526
|
}
|
|
1085
|
-
if (matches15(configRoutes, req)) {
|
|
1086
|
-
info("matches signup");
|
|
1087
|
-
return route15(req, config);
|
|
1088
|
-
}
|
|
1089
|
-
if (matches2(configRoutes, req)) {
|
|
1090
|
-
info("matches users");
|
|
1091
|
-
return route2(req, config);
|
|
1092
|
-
}
|
|
1093
1527
|
if (matches4(configRoutes, req)) {
|
|
1094
|
-
info("matches
|
|
1528
|
+
info("matches tenant invite");
|
|
1095
1529
|
return route4(req, config);
|
|
1096
1530
|
}
|
|
1531
|
+
if (matches17(configRoutes, req)) {
|
|
1532
|
+
info("matches signup");
|
|
1533
|
+
return route17(req, config);
|
|
1534
|
+
}
|
|
1097
1535
|
if (matches6(configRoutes, req)) {
|
|
1098
|
-
info("matches
|
|
1536
|
+
info("matches tenants");
|
|
1099
1537
|
return route6(req, config);
|
|
1100
1538
|
}
|
|
1101
|
-
if (
|
|
1539
|
+
if (matches8(configRoutes, req)) {
|
|
1540
|
+
info("matches session");
|
|
1541
|
+
return route8(req, config);
|
|
1542
|
+
}
|
|
1543
|
+
if (matches7(configRoutes, req)) {
|
|
1102
1544
|
info("matches signin");
|
|
1103
|
-
return
|
|
1545
|
+
return route7(req, config);
|
|
1104
1546
|
}
|
|
1105
|
-
if (
|
|
1547
|
+
if (matches15(configRoutes, req)) {
|
|
1106
1548
|
info("matches password reset");
|
|
1107
|
-
return
|
|
1549
|
+
return route15(req, config);
|
|
1108
1550
|
}
|
|
1109
|
-
if (
|
|
1551
|
+
if (matches9(configRoutes, req)) {
|
|
1110
1552
|
info("matches providers");
|
|
1111
|
-
return
|
|
1553
|
+
return route9(req, config);
|
|
1112
1554
|
}
|
|
1113
|
-
if (
|
|
1555
|
+
if (matches10(configRoutes, req)) {
|
|
1114
1556
|
info("matches csrf");
|
|
1115
|
-
return
|
|
1557
|
+
return route10(req, config);
|
|
1116
1558
|
}
|
|
1117
|
-
if (
|
|
1559
|
+
if (matches11(configRoutes, req)) {
|
|
1118
1560
|
info("matches callback");
|
|
1119
|
-
return
|
|
1561
|
+
return route11(req, config);
|
|
1120
1562
|
}
|
|
1121
|
-
if (
|
|
1563
|
+
if (matches12(configRoutes, req)) {
|
|
1122
1564
|
info("matches signout");
|
|
1123
|
-
return
|
|
1565
|
+
return route12(req, config);
|
|
1124
1566
|
}
|
|
1125
|
-
if (
|
|
1567
|
+
if (matches16(configRoutes, req)) {
|
|
1126
1568
|
info("matches verify-email");
|
|
1127
|
-
return
|
|
1569
|
+
return route16(req, config);
|
|
1128
1570
|
}
|
|
1129
|
-
|
|
1571
|
+
warn2(`No POST routes matched ${req.url}`);
|
|
1130
1572
|
return new Response(null, { status: 404 });
|
|
1131
1573
|
};
|
|
1132
1574
|
}
|
|
@@ -1135,31 +1577,24 @@ function POSTER(configRoutes, config) {
|
|
|
1135
1577
|
async function DELETE3(config, init) {
|
|
1136
1578
|
const yurl = new URL(init.request.url);
|
|
1137
1579
|
const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
|
|
1138
|
-
config.tenantId = tenantId;
|
|
1139
|
-
config.userId = userId;
|
|
1140
1580
|
init.method = "DELETE";
|
|
1141
|
-
const url = `${apiRoutes(config).TENANT_USER}/link`;
|
|
1581
|
+
const url = `${apiRoutes(config.apiUrl).TENANT_USER(tenantId, userId)}/link`;
|
|
1142
1582
|
return await request(url, init, config);
|
|
1143
1583
|
}
|
|
1144
1584
|
|
|
1145
1585
|
// src/api/routes/tenants/[tenantId]/users/[userId]/PUT.ts
|
|
1146
|
-
async function
|
|
1586
|
+
async function PUT5(config, init) {
|
|
1147
1587
|
const yurl = new URL(init.request.url);
|
|
1148
1588
|
const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
|
|
1149
|
-
config.tenantId = tenantId;
|
|
1150
|
-
config.userId = userId;
|
|
1151
1589
|
init.method = "PUT";
|
|
1152
|
-
const url = `${apiRoutes(config).TENANT_USER}/link`;
|
|
1590
|
+
const url = `${apiRoutes(config.apiUrl).TENANT_USER(tenantId, userId)}/link`;
|
|
1153
1591
|
return await request(url, init, config);
|
|
1154
1592
|
}
|
|
1155
1593
|
|
|
1156
1594
|
// src/api/routes/tenants/[tenantId]/users/[userId]/index.ts
|
|
1157
|
-
var
|
|
1158
|
-
async function
|
|
1159
|
-
const { info } =
|
|
1160
|
-
{ ...config, debug: config.debug },
|
|
1161
|
-
`[ROUTES][${key13}]`
|
|
1162
|
-
);
|
|
1595
|
+
var key15 = "TENANT_USER";
|
|
1596
|
+
async function route18(request2, config) {
|
|
1597
|
+
const { info } = config.logger(`[ROUTES][${key15}]`);
|
|
1163
1598
|
const session = await auth(request2, config);
|
|
1164
1599
|
if (!session) {
|
|
1165
1600
|
info("401");
|
|
@@ -1173,113 +1608,170 @@ async function route16(request2, config) {
|
|
|
1173
1608
|
}
|
|
1174
1609
|
switch (request2.method) {
|
|
1175
1610
|
case "PUT":
|
|
1176
|
-
return await
|
|
1611
|
+
return await PUT5(config, { request: request2 });
|
|
1177
1612
|
case "DELETE":
|
|
1178
1613
|
return await DELETE3(config, { request: request2 });
|
|
1179
1614
|
default:
|
|
1180
1615
|
return new Response("method not allowed", { status: 405 });
|
|
1181
1616
|
}
|
|
1182
1617
|
}
|
|
1183
|
-
function
|
|
1618
|
+
function matches18(configRoutes, request2) {
|
|
1184
1619
|
const url = new URL(request2.url);
|
|
1185
1620
|
const [, userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
|
|
1186
|
-
let
|
|
1621
|
+
let route20 = configRoutes[key15].replace("{tenantId}", tenantId).replace("{userId}", userId);
|
|
1187
1622
|
if (userId === "users") {
|
|
1188
|
-
|
|
1623
|
+
route20 = configRoutes[key15].replace("{tenantId}", possibleTenantId);
|
|
1189
1624
|
}
|
|
1190
|
-
return urlMatches(request2.url,
|
|
1625
|
+
return urlMatches(request2.url, route20);
|
|
1191
1626
|
}
|
|
1192
1627
|
async function fetchTenantUser(config, method) {
|
|
1193
|
-
|
|
1628
|
+
const { headers, tenantId, userId } = ctx.get();
|
|
1629
|
+
const action = method === "PUT" ? "add" : "delete";
|
|
1630
|
+
if (!tenantId) {
|
|
1194
1631
|
throw new Error(
|
|
1195
|
-
|
|
1632
|
+
`Unable to ${action} user to the tenant, the tenantId context is missing. Use nile.withContext({ tenantId })`
|
|
1196
1633
|
);
|
|
1197
1634
|
}
|
|
1198
|
-
if (!
|
|
1635
|
+
if (!userId) {
|
|
1199
1636
|
throw new Error(
|
|
1200
|
-
|
|
1637
|
+
`Unable to ${action} user to tenant. The userId context is missing. Use nile.withContext({ userId })`
|
|
1201
1638
|
);
|
|
1202
1639
|
}
|
|
1203
|
-
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */.replace(
|
|
1204
|
-
"{
|
|
1205
|
-
|
|
1206
|
-
)
|
|
1640
|
+
const clientUrl = `${config.serverOrigin}${config.routePrefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */.replace("{tenantId}", tenantId).replace(
|
|
1641
|
+
"{userId}",
|
|
1642
|
+
userId
|
|
1643
|
+
)}/link`;
|
|
1207
1644
|
const req = new Request(clientUrl, {
|
|
1208
|
-
headers
|
|
1645
|
+
headers,
|
|
1209
1646
|
method
|
|
1210
1647
|
});
|
|
1211
1648
|
return await config.handlers[method](req);
|
|
1212
1649
|
}
|
|
1213
1650
|
|
|
1651
|
+
// src/api/routes/tenants/[tenantId]/invite/[inviteId]/DELETE.ts
|
|
1652
|
+
async function DELETE4(config, init) {
|
|
1653
|
+
const yurl = new URL(init.request.url);
|
|
1654
|
+
const [inviteId, , tenantId] = yurl.pathname.split("/").reverse();
|
|
1655
|
+
if (!tenantId) {
|
|
1656
|
+
return new Response(null, { status: 404 });
|
|
1657
|
+
}
|
|
1658
|
+
init.method = "DELETE";
|
|
1659
|
+
const url = `${apiRoutes(config.apiUrl).INVITE(tenantId)}/${inviteId}`;
|
|
1660
|
+
return await request(url, init, config);
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
// src/api/routes/tenants/[tenantId]/invite/[inviteId]/index.ts
|
|
1664
|
+
var key16 = "INVITE";
|
|
1665
|
+
async function route19(request2, config) {
|
|
1666
|
+
switch (request2.method) {
|
|
1667
|
+
case "DELETE":
|
|
1668
|
+
return await DELETE4(config, { request: request2 });
|
|
1669
|
+
default:
|
|
1670
|
+
return new Response("method not allowed", { status: 405 });
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
function matches19(configRoutes, request2) {
|
|
1674
|
+
const url = new URL(request2.url);
|
|
1675
|
+
const [inviteId, , tenantId] = url.pathname.split("/").reverse();
|
|
1676
|
+
const route20 = configRoutes[key16].replace("{tenantId}", tenantId).replace("{inviteId}", inviteId);
|
|
1677
|
+
return urlMatches(request2.url, route20);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1214
1680
|
// src/api/handlers/DELETE.ts
|
|
1215
1681
|
function DELETER(configRoutes, config) {
|
|
1216
|
-
const { info, warn } =
|
|
1217
|
-
return async function
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1682
|
+
const { error, info, warn: warn2 } = config.logger("[DELETE MATCHER]");
|
|
1683
|
+
return async function DELETE5(...params) {
|
|
1684
|
+
const handledRequest = await config.extensionCtx?.runExtensions(
|
|
1685
|
+
"onHandleRequest" /* onHandleRequest */,
|
|
1686
|
+
config,
|
|
1687
|
+
params
|
|
1688
|
+
);
|
|
1689
|
+
if (handledRequest) {
|
|
1690
|
+
return handledRequest;
|
|
1221
1691
|
}
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1692
|
+
const req = params[0] instanceof Request ? params[0] : null;
|
|
1693
|
+
if (!req) {
|
|
1694
|
+
error("Proxy requests failed, a Request object was not passed.");
|
|
1695
|
+
return;
|
|
1225
1696
|
}
|
|
1226
|
-
if (
|
|
1697
|
+
if (matches19(configRoutes, req)) {
|
|
1698
|
+
info("matches tenant invite id");
|
|
1699
|
+
return route19(req, config);
|
|
1700
|
+
}
|
|
1701
|
+
if (matches18(configRoutes, req)) {
|
|
1702
|
+
info("matches tenant user");
|
|
1703
|
+
return route18(req, config);
|
|
1704
|
+
}
|
|
1705
|
+
if (matches6(configRoutes, req)) {
|
|
1227
1706
|
info("matches tenants");
|
|
1228
|
-
return
|
|
1707
|
+
return route6(req, config);
|
|
1229
1708
|
}
|
|
1230
1709
|
if (matches(configRoutes, req)) {
|
|
1231
1710
|
info("matches me");
|
|
1232
1711
|
return route(req, config);
|
|
1233
1712
|
}
|
|
1234
|
-
|
|
1713
|
+
warn2("No DELETE routes matched");
|
|
1235
1714
|
return new Response(null, { status: 404 });
|
|
1236
1715
|
};
|
|
1237
1716
|
}
|
|
1238
1717
|
|
|
1239
1718
|
// src/api/handlers/PUT.ts
|
|
1240
1719
|
function PUTER(configRoutes, config) {
|
|
1241
|
-
const { info, warn } =
|
|
1242
|
-
return async function
|
|
1243
|
-
|
|
1720
|
+
const { error, info, warn: warn2 } = config.logger("[PUT MATCHER]");
|
|
1721
|
+
return async function PUT6(...params) {
|
|
1722
|
+
const handledRequest = await config.extensionCtx?.runExtensions(
|
|
1723
|
+
"onHandleRequest" /* onHandleRequest */,
|
|
1724
|
+
config,
|
|
1725
|
+
params
|
|
1726
|
+
);
|
|
1727
|
+
if (handledRequest) {
|
|
1728
|
+
return handledRequest;
|
|
1729
|
+
}
|
|
1730
|
+
const req = params[0] instanceof Request ? params[0] : null;
|
|
1731
|
+
if (!req) {
|
|
1732
|
+
error("Proxy requests failed, a Request object was not passed.");
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
if (matches4(configRoutes, req)) {
|
|
1736
|
+
info("matches tenant invite");
|
|
1737
|
+
return route4(req, config);
|
|
1738
|
+
}
|
|
1739
|
+
if (matches18(configRoutes, req)) {
|
|
1244
1740
|
info("matches tenant user");
|
|
1245
|
-
return
|
|
1741
|
+
return route18(req, config);
|
|
1246
1742
|
}
|
|
1247
1743
|
if (matches3(configRoutes, req)) {
|
|
1248
1744
|
info("matches tenant users");
|
|
1249
1745
|
return route3(req, config);
|
|
1250
1746
|
}
|
|
1251
|
-
if (matches2(configRoutes, req)) {
|
|
1252
|
-
info("matches users");
|
|
1253
|
-
return route2(req, config);
|
|
1254
|
-
}
|
|
1255
1747
|
if (matches(configRoutes, req)) {
|
|
1256
1748
|
info("matches me");
|
|
1257
1749
|
return route(req, config);
|
|
1258
1750
|
}
|
|
1259
|
-
if (
|
|
1751
|
+
if (matches6(configRoutes, req)) {
|
|
1260
1752
|
info("matches tenants");
|
|
1261
|
-
return
|
|
1753
|
+
return route6(req, config);
|
|
1262
1754
|
}
|
|
1263
|
-
if (
|
|
1755
|
+
if (matches15(configRoutes, req)) {
|
|
1264
1756
|
info("matches reset password");
|
|
1265
|
-
return
|
|
1757
|
+
return route15(req, config);
|
|
1266
1758
|
}
|
|
1267
|
-
|
|
1759
|
+
warn2("No PUT routes matched");
|
|
1268
1760
|
return new Response(null, { status: 404 });
|
|
1269
1761
|
};
|
|
1270
1762
|
}
|
|
1271
1763
|
|
|
1272
1764
|
// src/api/handlers/index.ts
|
|
1273
1765
|
function Handlers(configRoutes, config) {
|
|
1274
|
-
const
|
|
1275
|
-
const
|
|
1276
|
-
const
|
|
1277
|
-
const
|
|
1766
|
+
const GET7 = GETTER(configRoutes, config);
|
|
1767
|
+
const POST6 = POSTER(configRoutes, config);
|
|
1768
|
+
const DELETE5 = DELETER(configRoutes, config);
|
|
1769
|
+
const PUT6 = PUTER(configRoutes, config);
|
|
1278
1770
|
return {
|
|
1279
|
-
GET:
|
|
1280
|
-
POST:
|
|
1281
|
-
DELETE:
|
|
1282
|
-
PUT:
|
|
1771
|
+
GET: GET7,
|
|
1772
|
+
POST: POST6,
|
|
1773
|
+
DELETE: DELETE5,
|
|
1774
|
+
PUT: PUT6
|
|
1283
1775
|
};
|
|
1284
1776
|
}
|
|
1285
1777
|
var getApiUrl = (cfg) => {
|
|
@@ -1312,15 +1804,16 @@ var getSecureCookies = (cfg) => {
|
|
|
1312
1804
|
return void 0;
|
|
1313
1805
|
};
|
|
1314
1806
|
var getUsername = (cfg) => {
|
|
1315
|
-
const { config
|
|
1316
|
-
const
|
|
1807
|
+
const { config } = cfg;
|
|
1808
|
+
const logger = config.logger;
|
|
1809
|
+
const { info } = logger();
|
|
1317
1810
|
if (config?.user) {
|
|
1318
|
-
|
|
1811
|
+
info(`[config] ${config.user}`);
|
|
1319
1812
|
return String(config?.user);
|
|
1320
1813
|
}
|
|
1321
1814
|
const user = stringCheck(process.env.NILEDB_USER);
|
|
1322
1815
|
if (user) {
|
|
1323
|
-
|
|
1816
|
+
info(`[NILEDB_USER] ${user}`);
|
|
1324
1817
|
return user;
|
|
1325
1818
|
}
|
|
1326
1819
|
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
@@ -1338,16 +1831,16 @@ var getUsername = (cfg) => {
|
|
|
1338
1831
|
);
|
|
1339
1832
|
};
|
|
1340
1833
|
var getPassword = (cfg) => {
|
|
1341
|
-
const { config
|
|
1834
|
+
const { config } = cfg;
|
|
1835
|
+
const logger = config.logger;
|
|
1342
1836
|
const log = logProtector(logger);
|
|
1343
|
-
const { info } = Logger(config, "[password]");
|
|
1344
1837
|
if (stringCheck(config?.password)) {
|
|
1345
|
-
log &&
|
|
1838
|
+
log && log("[config]").info("***");
|
|
1346
1839
|
return String(config?.password);
|
|
1347
1840
|
}
|
|
1348
1841
|
const pass = stringCheck(process.env.NILEDB_PASSWORD);
|
|
1349
1842
|
if (pass) {
|
|
1350
|
-
logger
|
|
1843
|
+
logger("[NILEDB_PASSWORD]").info("***");
|
|
1351
1844
|
return pass;
|
|
1352
1845
|
}
|
|
1353
1846
|
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
@@ -1365,15 +1858,15 @@ var getPassword = (cfg) => {
|
|
|
1365
1858
|
);
|
|
1366
1859
|
};
|
|
1367
1860
|
var getDatabaseName = (cfg) => {
|
|
1368
|
-
const { config
|
|
1369
|
-
const { info } =
|
|
1861
|
+
const { config } = cfg;
|
|
1862
|
+
const { info } = config.logger("[databaseName]");
|
|
1370
1863
|
if (stringCheck(config?.databaseName)) {
|
|
1371
|
-
|
|
1864
|
+
info(`[config] ${config?.databaseName}`);
|
|
1372
1865
|
return String(config?.databaseName);
|
|
1373
1866
|
}
|
|
1374
1867
|
const name = stringCheck(process.env.NILEDB_NAME);
|
|
1375
1868
|
if (name) {
|
|
1376
|
-
|
|
1869
|
+
info(`[NILEDB_NAME] ${name}`);
|
|
1377
1870
|
return name;
|
|
1378
1871
|
}
|
|
1379
1872
|
if (process.env.NILEDB_POSTGRES_URL) {
|
|
@@ -1388,50 +1881,52 @@ var getDatabaseName = (cfg) => {
|
|
|
1388
1881
|
);
|
|
1389
1882
|
};
|
|
1390
1883
|
var getTenantId = (cfg) => {
|
|
1391
|
-
const { config
|
|
1392
|
-
const { info } =
|
|
1884
|
+
const { config } = cfg;
|
|
1885
|
+
const { info } = config.logger("[tenantId]");
|
|
1393
1886
|
if (stringCheck(config?.tenantId)) {
|
|
1394
|
-
|
|
1887
|
+
info(`[config] ${config?.tenantId}`);
|
|
1395
1888
|
return String(config?.tenantId);
|
|
1396
1889
|
}
|
|
1397
1890
|
if (stringCheck(process.env.NILEDB_TENANT)) {
|
|
1398
|
-
|
|
1891
|
+
info(`[NILEDB_TENANT] ${process.env.NILEDB_TENANT}`);
|
|
1399
1892
|
return String(process.env.NILEDB_TENANT);
|
|
1400
1893
|
}
|
|
1401
1894
|
return null;
|
|
1402
1895
|
};
|
|
1403
1896
|
function getDbHost(cfg) {
|
|
1404
|
-
const { config
|
|
1405
|
-
const
|
|
1897
|
+
const { config } = cfg;
|
|
1898
|
+
const logger = config.logger;
|
|
1899
|
+
const { info } = logger("[db.host]");
|
|
1406
1900
|
if (stringCheck(config?.db && config.db.host)) {
|
|
1407
|
-
|
|
1901
|
+
info(`[config] ${config?.db?.host}`);
|
|
1408
1902
|
return String(config?.db?.host);
|
|
1409
1903
|
}
|
|
1410
1904
|
if (stringCheck(process.env.NILEDB_HOST)) {
|
|
1411
|
-
|
|
1905
|
+
info(`[NILEDB_HOST] ${process.env.NILEDB_HOST}`);
|
|
1412
1906
|
return process.env.NILEDB_HOST;
|
|
1413
1907
|
}
|
|
1414
1908
|
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
1415
1909
|
if (pg2) {
|
|
1416
1910
|
try {
|
|
1417
1911
|
const pgUrl = new URL(pg2);
|
|
1418
|
-
|
|
1912
|
+
info(`[NILEDB_POSTGRES_URL] ${pgUrl.hostname}`);
|
|
1419
1913
|
return pgUrl.hostname;
|
|
1420
1914
|
} catch (e) {
|
|
1421
1915
|
}
|
|
1422
1916
|
}
|
|
1423
|
-
|
|
1917
|
+
info("[default] db.thenile.dev");
|
|
1424
1918
|
return "db.thenile.dev";
|
|
1425
1919
|
}
|
|
1426
1920
|
function getDbPort(cfg) {
|
|
1427
|
-
const { config
|
|
1428
|
-
const
|
|
1921
|
+
const { config } = cfg;
|
|
1922
|
+
const logger = config.logger;
|
|
1923
|
+
const { info } = logger("[db.port]");
|
|
1429
1924
|
if (config?.db?.port && config.db.port != null) {
|
|
1430
|
-
|
|
1925
|
+
info(`[config] ${config?.db.port}`);
|
|
1431
1926
|
return Number(config.db?.port);
|
|
1432
1927
|
}
|
|
1433
1928
|
if (stringCheck(process.env.NILEDB_PORT)) {
|
|
1434
|
-
|
|
1929
|
+
info(`[NILEDB_PORT] ${process.env.NILEDB_PORT}`);
|
|
1435
1930
|
return Number(process.env.NILEDB_PORT);
|
|
1436
1931
|
}
|
|
1437
1932
|
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
@@ -1444,7 +1939,7 @@ function getDbPort(cfg) {
|
|
|
1444
1939
|
} catch (e) {
|
|
1445
1940
|
}
|
|
1446
1941
|
}
|
|
1447
|
-
|
|
1942
|
+
info("[default] 5432");
|
|
1448
1943
|
return 5432;
|
|
1449
1944
|
}
|
|
1450
1945
|
var logProtector = (logger) => {
|
|
@@ -1462,19 +1957,10 @@ var Config = class {
|
|
|
1462
1957
|
routes;
|
|
1463
1958
|
handlers;
|
|
1464
1959
|
paths;
|
|
1960
|
+
extensionCtx;
|
|
1961
|
+
extensions;
|
|
1465
1962
|
logger;
|
|
1466
|
-
|
|
1467
|
-
* Stores the set tenant id from Server for use in sub classes
|
|
1468
|
-
*/
|
|
1469
|
-
tenantId;
|
|
1470
|
-
/**
|
|
1471
|
-
* Stores the set user id from Server for use in sub classes
|
|
1472
|
-
*/
|
|
1473
|
-
userId;
|
|
1474
|
-
/**
|
|
1475
|
-
* Stores the headers to be used in `fetch` calls
|
|
1476
|
-
*/
|
|
1477
|
-
headers;
|
|
1963
|
+
context;
|
|
1478
1964
|
/**
|
|
1479
1965
|
* The nile-auth url
|
|
1480
1966
|
*/
|
|
@@ -1495,15 +1981,19 @@ var Config = class {
|
|
|
1495
1981
|
*/
|
|
1496
1982
|
routePrefix;
|
|
1497
1983
|
db;
|
|
1498
|
-
|
|
1499
|
-
constructor(config, logger) {
|
|
1500
|
-
const envVarConfig = { config, logger };
|
|
1984
|
+
constructor(config) {
|
|
1501
1985
|
this.routePrefix = config?.routePrefix ?? "/api";
|
|
1502
|
-
this.secureCookies = getSecureCookies(envVarConfig);
|
|
1503
|
-
this.callbackUrl = getCallbackUrl(envVarConfig);
|
|
1504
1986
|
this.debug = config?.debug;
|
|
1505
1987
|
this.origin = config?.origin;
|
|
1988
|
+
this.extensions = config?.extensions;
|
|
1989
|
+
this.extensionCtx = config?.extensionCtx;
|
|
1506
1990
|
this.serverOrigin = config?.origin ?? "http://localhost:3000";
|
|
1991
|
+
this.logger = Logger(config);
|
|
1992
|
+
const envVarConfig = {
|
|
1993
|
+
config: { ...config, logger: this.logger }
|
|
1994
|
+
};
|
|
1995
|
+
this.secureCookies = getSecureCookies(envVarConfig);
|
|
1996
|
+
this.callbackUrl = getCallbackUrl(envVarConfig);
|
|
1507
1997
|
this.apiUrl = getApiUrl(envVarConfig);
|
|
1508
1998
|
const user = getUsername(envVarConfig);
|
|
1509
1999
|
const password = getPassword(envVarConfig);
|
|
@@ -1521,11 +2011,12 @@ var Config = class {
|
|
|
1521
2011
|
if (databaseName) {
|
|
1522
2012
|
this.db.database = databaseName;
|
|
1523
2013
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
2014
|
+
this.context = {
|
|
2015
|
+
tenantId: config?.tenantId,
|
|
2016
|
+
userId: config?.userId,
|
|
2017
|
+
headers: config?.headers ? new Headers(config.headers) : new Headers(),
|
|
2018
|
+
preserveHeaders: false
|
|
2019
|
+
};
|
|
1529
2020
|
this.routes = {
|
|
1530
2021
|
...appRoutes(config?.routePrefix),
|
|
1531
2022
|
...config?.routes
|
|
@@ -1568,9 +2059,6 @@ var Config = class {
|
|
|
1568
2059
|
],
|
|
1569
2060
|
delete: [this.routes.TENANT_USER, this.routes.TENANT]
|
|
1570
2061
|
};
|
|
1571
|
-
this.tenantId = config?.tenantId;
|
|
1572
|
-
this.userId = config?.userId;
|
|
1573
|
-
this.logger = config?.logger;
|
|
1574
2062
|
}
|
|
1575
2063
|
};
|
|
1576
2064
|
|
|
@@ -1604,6 +2092,9 @@ var Eventer = class {
|
|
|
1604
2092
|
}
|
|
1605
2093
|
};
|
|
1606
2094
|
var eventer = new Eventer();
|
|
2095
|
+
var updateTenantId = (tenantId) => {
|
|
2096
|
+
eventer.publish("tenantId" /* Tenant */, tenantId);
|
|
2097
|
+
};
|
|
1607
2098
|
var watchTenantId = (cb) => eventer.subscribe("tenantId" /* Tenant */, cb);
|
|
1608
2099
|
var watchUserId = (cb) => eventer.subscribe("userId" /* User */, cb);
|
|
1609
2100
|
var evictPool = (val) => {
|
|
@@ -1617,7 +2108,7 @@ var watchHeaders = (cb) => eventer.subscribe("headers" /* Headers */, cb);
|
|
|
1617
2108
|
|
|
1618
2109
|
// src/db/PoolProxy.ts
|
|
1619
2110
|
function createProxyForPool(pool, config) {
|
|
1620
|
-
const { info, error } =
|
|
2111
|
+
const { info, error } = config.logger("[pool]");
|
|
1621
2112
|
return new Proxy(pool, {
|
|
1622
2113
|
get(target, property) {
|
|
1623
2114
|
if (property === "query") {
|
|
@@ -1634,7 +2125,15 @@ function createProxyForPool(pool, config) {
|
|
|
1634
2125
|
}
|
|
1635
2126
|
const caller = target[property];
|
|
1636
2127
|
return function query(...args) {
|
|
1637
|
-
|
|
2128
|
+
let log = "[QUERY]";
|
|
2129
|
+
const { userId, tenantId } = config.context;
|
|
2130
|
+
if (tenantId) {
|
|
2131
|
+
log = `${log}[TENANT:${tenantId}]`;
|
|
2132
|
+
}
|
|
2133
|
+
if (userId) {
|
|
2134
|
+
log = `${log}[USER:${userId}]`;
|
|
2135
|
+
}
|
|
2136
|
+
info(log, ...args);
|
|
1638
2137
|
const called = caller.apply(this, args);
|
|
1639
2138
|
return called;
|
|
1640
2139
|
};
|
|
@@ -1653,7 +2152,7 @@ var NileDatabase = class {
|
|
|
1653
2152
|
config;
|
|
1654
2153
|
timer;
|
|
1655
2154
|
constructor(config, id) {
|
|
1656
|
-
const { warn, info, debug } =
|
|
2155
|
+
const { warn: warn2, info, debug } = config.logger("[NileInstance]");
|
|
1657
2156
|
this.id = id;
|
|
1658
2157
|
const poolConfig = {
|
|
1659
2158
|
min: 0,
|
|
@@ -1669,7 +2168,7 @@ var NileDatabase = class {
|
|
|
1669
2168
|
debug(`Connection pool config ${JSON.stringify(cloned)}`);
|
|
1670
2169
|
this.pool = createProxyForPool(new pg.Pool(remaining), this.config);
|
|
1671
2170
|
if (typeof afterCreate === "function") {
|
|
1672
|
-
|
|
2171
|
+
warn2(
|
|
1673
2172
|
"Providing an pool configuration will stop automatic tenant context setting."
|
|
1674
2173
|
);
|
|
1675
2174
|
}
|
|
@@ -1682,7 +2181,7 @@ var NileDatabase = class {
|
|
|
1682
2181
|
`${this.id}-${this.timer}`
|
|
1683
2182
|
);
|
|
1684
2183
|
afterCreate2(client, (err) => {
|
|
1685
|
-
const { error } =
|
|
2184
|
+
const { error } = config.logger("[after create callback]");
|
|
1686
2185
|
if (err) {
|
|
1687
2186
|
clearTimeout(this.timer);
|
|
1688
2187
|
error("after create failed", {
|
|
@@ -1710,7 +2209,7 @@ var NileDatabase = class {
|
|
|
1710
2209
|
});
|
|
1711
2210
|
}
|
|
1712
2211
|
startTimeout() {
|
|
1713
|
-
const { debug } =
|
|
2212
|
+
const { debug } = this.config.logger("[NileInstance]");
|
|
1714
2213
|
if (this.timer) {
|
|
1715
2214
|
clearTimeout(this.timer);
|
|
1716
2215
|
}
|
|
@@ -1725,7 +2224,7 @@ var NileDatabase = class {
|
|
|
1725
2224
|
}, Number(this.config.db.idleTimeoutMillis) ?? 3e4);
|
|
1726
2225
|
}
|
|
1727
2226
|
shutdown() {
|
|
1728
|
-
const { debug } =
|
|
2227
|
+
const { debug } = this.config.logger("[NileInstance]");
|
|
1729
2228
|
debug(`attempting to shut down ${this.id}`);
|
|
1730
2229
|
clearTimeout(this.timer);
|
|
1731
2230
|
this.pool.end(() => {
|
|
@@ -1735,7 +2234,7 @@ var NileDatabase = class {
|
|
|
1735
2234
|
};
|
|
1736
2235
|
var NileInstance_default = NileDatabase;
|
|
1737
2236
|
function makeAfterCreate(config, id) {
|
|
1738
|
-
const { error, warn, debug } =
|
|
2237
|
+
const { error, warn: warn2, debug } = config.logger("[afterCreate]");
|
|
1739
2238
|
return (conn, done) => {
|
|
1740
2239
|
conn.on("error", function errorHandler(e) {
|
|
1741
2240
|
error(`Connection ${id} was terminated by server`, {
|
|
@@ -1744,13 +2243,14 @@ function makeAfterCreate(config, id) {
|
|
|
1744
2243
|
});
|
|
1745
2244
|
done(e, conn);
|
|
1746
2245
|
});
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
2246
|
+
const { tenantId, userId } = ctx.getLastUsed();
|
|
2247
|
+
if (tenantId) {
|
|
2248
|
+
const query = [`SET nile.tenant_id = '${tenantId}'`];
|
|
2249
|
+
if (userId) {
|
|
2250
|
+
if (!tenantId) {
|
|
2251
|
+
warn2("A user id cannot be set in context without a tenant id");
|
|
1752
2252
|
}
|
|
1753
|
-
query.push(`SET nile.user_id = '${
|
|
2253
|
+
query.push(`SET nile.user_id = '${userId}'`);
|
|
1754
2254
|
}
|
|
1755
2255
|
conn.query(query.join(";"), function(err) {
|
|
1756
2256
|
if (err) {
|
|
@@ -1763,11 +2263,11 @@ function makeAfterCreate(config, id) {
|
|
|
1763
2263
|
});
|
|
1764
2264
|
} else {
|
|
1765
2265
|
if (query.length === 1) {
|
|
1766
|
-
debug(`connection context set: tenantId=${
|
|
2266
|
+
debug(`connection context set: tenantId=${tenantId}`);
|
|
1767
2267
|
}
|
|
1768
2268
|
if (query.length === 2) {
|
|
1769
2269
|
debug(
|
|
1770
|
-
`connection context set: tenantId=${
|
|
2270
|
+
`connection context set: tenantId=${tenantId} userId=${userId}`
|
|
1771
2271
|
);
|
|
1772
2272
|
}
|
|
1773
2273
|
}
|
|
@@ -1799,19 +2299,20 @@ var DBManager = class {
|
|
|
1799
2299
|
watchEvictPool(this.poolWatcherFn);
|
|
1800
2300
|
}
|
|
1801
2301
|
poolWatcher = (config) => (id) => {
|
|
1802
|
-
const { info, warn } = Logger(config
|
|
2302
|
+
const { info, warn: warn2 } = Logger(config)("[DBManager]");
|
|
1803
2303
|
if (id && this.connections.has(id)) {
|
|
1804
2304
|
info(`Removing ${id} from db connection pool.`);
|
|
1805
2305
|
const connection = this.connections.get(id);
|
|
1806
2306
|
connection?.shutdown();
|
|
1807
2307
|
this.connections.delete(id);
|
|
1808
2308
|
} else {
|
|
1809
|
-
|
|
2309
|
+
warn2(`missed eviction of ${id}`);
|
|
1810
2310
|
}
|
|
1811
2311
|
};
|
|
1812
2312
|
getConnection = (config) => {
|
|
1813
|
-
const { info } = Logger(config
|
|
1814
|
-
const
|
|
2313
|
+
const { info } = Logger(config)("[DBManager]");
|
|
2314
|
+
const { tenantId, userId } = ctx.getLastUsed();
|
|
2315
|
+
const id = this.makeId(tenantId, userId);
|
|
1815
2316
|
const existing = this.connections.get(id);
|
|
1816
2317
|
info(`# of instances: ${this.connections.size}`);
|
|
1817
2318
|
if (existing) {
|
|
@@ -1819,7 +2320,7 @@ var DBManager = class {
|
|
|
1819
2320
|
existing.startTimeout();
|
|
1820
2321
|
return existing.pool;
|
|
1821
2322
|
}
|
|
1822
|
-
const newOne = new NileInstance_default(
|
|
2323
|
+
const newOne = new NileInstance_default(config, id);
|
|
1823
2324
|
this.connections.set(id, newOne);
|
|
1824
2325
|
info(`created new ${id}`);
|
|
1825
2326
|
info(`# of instances: ${this.connections.size}`);
|
|
@@ -1829,7 +2330,7 @@ var DBManager = class {
|
|
|
1829
2330
|
return newOne.pool;
|
|
1830
2331
|
};
|
|
1831
2332
|
clear = (config) => {
|
|
1832
|
-
const { info } = Logger(config
|
|
2333
|
+
const { info } = Logger(config)("[DBManager]");
|
|
1833
2334
|
info(`Clearing all connections ${this.connections.size}`);
|
|
1834
2335
|
this.cleared = true;
|
|
1835
2336
|
this.connections.forEach((connection) => {
|
|
@@ -1843,223 +2344,284 @@ var DBManager = class {
|
|
|
1843
2344
|
var Auth = class {
|
|
1844
2345
|
#logger;
|
|
1845
2346
|
#config;
|
|
2347
|
+
/**
|
|
2348
|
+
* Create an Auth helper.
|
|
2349
|
+
*
|
|
2350
|
+
* @param config - runtime configuration used by the underlying fetch helpers
|
|
2351
|
+
* such as `serverOrigin`, `routePrefix` and default headers.
|
|
2352
|
+
*/
|
|
1846
2353
|
constructor(config) {
|
|
1847
2354
|
this.#config = config;
|
|
1848
|
-
this.#logger =
|
|
2355
|
+
this.#logger = config.logger("[auth]");
|
|
1849
2356
|
}
|
|
1850
2357
|
async getSession(rawResponse = false) {
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
try {
|
|
1856
|
-
const session = await res.clone().json();
|
|
1857
|
-
if (Object.keys(session).length === 0) {
|
|
1858
|
-
return void 0;
|
|
2358
|
+
return withNileContext(this.#config, async () => {
|
|
2359
|
+
const res = await fetchSession(this.#config);
|
|
2360
|
+
if (rawResponse) {
|
|
2361
|
+
return res;
|
|
1859
2362
|
}
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
2363
|
+
try {
|
|
2364
|
+
const session = await res.clone().json();
|
|
2365
|
+
if (Object.keys(session).length === 0) {
|
|
2366
|
+
return void 0;
|
|
2367
|
+
}
|
|
2368
|
+
return session;
|
|
2369
|
+
} catch {
|
|
2370
|
+
return res;
|
|
2371
|
+
}
|
|
2372
|
+
});
|
|
1864
2373
|
}
|
|
1865
2374
|
async getCsrf(rawResponse = false) {
|
|
1866
|
-
return
|
|
2375
|
+
return withNileContext(this.#config, async () => {
|
|
2376
|
+
return await obtainCsrf(this.#config, rawResponse);
|
|
2377
|
+
});
|
|
1867
2378
|
}
|
|
1868
2379
|
async listProviders(rawResponse = false) {
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
2380
|
+
return withNileContext(this.#config, async () => {
|
|
2381
|
+
const res = await fetchProviders(this.#config);
|
|
2382
|
+
if (rawResponse) {
|
|
2383
|
+
return res;
|
|
2384
|
+
}
|
|
2385
|
+
try {
|
|
2386
|
+
return await res.clone().json();
|
|
2387
|
+
} catch {
|
|
2388
|
+
return res;
|
|
2389
|
+
}
|
|
2390
|
+
});
|
|
1878
2391
|
}
|
|
2392
|
+
/**
|
|
2393
|
+
* Sign the current user out by calling `/api/auth/signout`.
|
|
2394
|
+
*
|
|
2395
|
+
* The CSRF token is fetched automatically and the stored cookies are cleared
|
|
2396
|
+
* from the internal configuration once the request completes.
|
|
2397
|
+
*/
|
|
1879
2398
|
async signOut() {
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
2399
|
+
return withNileContext(this.#config, async () => {
|
|
2400
|
+
const csrfRes = await this.getCsrf();
|
|
2401
|
+
if (!("csrfToken" in csrfRes)) {
|
|
2402
|
+
throw new Error("Unable to obtain CSRF token. Sign out failed.");
|
|
2403
|
+
}
|
|
2404
|
+
const body = JSON.stringify({
|
|
2405
|
+
csrfToken: csrfRes.csrfToken,
|
|
2406
|
+
json: true
|
|
2407
|
+
});
|
|
2408
|
+
const res = await fetchSignOut(this.#config, body);
|
|
2409
|
+
updateHeaders(new Headers({}));
|
|
2410
|
+
ctx.set({ headers: null });
|
|
2411
|
+
return res;
|
|
1887
2412
|
});
|
|
1888
|
-
const res = await fetchSignOut(this.#config, body);
|
|
1889
|
-
updateHeaders(new Headers({}));
|
|
1890
|
-
this.#config.headers = new Headers();
|
|
1891
|
-
return res;
|
|
1892
2413
|
}
|
|
1893
2414
|
async signUp(payload, rawResponse) {
|
|
1894
|
-
this.#config
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
csrfToken
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
2415
|
+
return withNileContext(this.#config, async () => {
|
|
2416
|
+
ctx.set({ headers: null });
|
|
2417
|
+
const { email, password, ...params } = payload;
|
|
2418
|
+
if (!email || !password) {
|
|
2419
|
+
throw new Error(
|
|
2420
|
+
"Server side sign up requires a user email and password."
|
|
2421
|
+
);
|
|
2422
|
+
}
|
|
2423
|
+
const providers = await this.listProviders();
|
|
2424
|
+
const { credentials } = providers ?? {};
|
|
2425
|
+
if (!credentials) {
|
|
2426
|
+
throw new Error(
|
|
2427
|
+
"Unable to obtain credential provider. Aborting server side sign up."
|
|
2428
|
+
);
|
|
2429
|
+
}
|
|
2430
|
+
const csrf = await obtainCsrf(this.#config);
|
|
2431
|
+
let csrfToken;
|
|
2432
|
+
if ("csrfToken" in csrf) {
|
|
2433
|
+
csrfToken = csrf.csrfToken;
|
|
2434
|
+
} else {
|
|
2435
|
+
throw new Error("Unable to obtain parse CSRF. Request blocked.");
|
|
2436
|
+
}
|
|
2437
|
+
const body = JSON.stringify({
|
|
2438
|
+
email,
|
|
2439
|
+
password,
|
|
2440
|
+
csrfToken,
|
|
2441
|
+
callbackUrl: credentials.callbackUrl
|
|
2442
|
+
});
|
|
2443
|
+
const res = await fetchSignUp(this.#config, { body, params });
|
|
2444
|
+
if (res.status > 299) {
|
|
2445
|
+
this.#logger.error(await res.clone().text());
|
|
2446
|
+
return void 0;
|
|
2447
|
+
}
|
|
2448
|
+
const token = parseToken(res.headers);
|
|
2449
|
+
if (!token) {
|
|
2450
|
+
throw new Error("Server side sign up failed. Session token not found");
|
|
2451
|
+
}
|
|
2452
|
+
const { headers } = ctx.get();
|
|
2453
|
+
headers?.append("cookie", token);
|
|
2454
|
+
ctx.set({ headers });
|
|
2455
|
+
updateHeaders(headers);
|
|
2456
|
+
if (rawResponse) {
|
|
2457
|
+
return res;
|
|
2458
|
+
}
|
|
2459
|
+
try {
|
|
2460
|
+
const json = await res.clone().json();
|
|
2461
|
+
if (json && typeof json === "object" && "tenants" in json) {
|
|
2462
|
+
const tenantId = json.tenants[0];
|
|
2463
|
+
if (tenantId) {
|
|
2464
|
+
updateTenantId(tenantId);
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
return json;
|
|
2468
|
+
} catch {
|
|
2469
|
+
return res;
|
|
2470
|
+
}
|
|
1920
2471
|
});
|
|
1921
|
-
const res = await fetchSignUp(this.#config, { body, params });
|
|
1922
|
-
if (res.status > 299) {
|
|
1923
|
-
this.#logger.error(await res.clone().text());
|
|
1924
|
-
return void 0;
|
|
1925
|
-
}
|
|
1926
|
-
const token = parseToken(res.headers);
|
|
1927
|
-
if (!token) {
|
|
1928
|
-
throw new Error("Server side sign up failed. Session token not found");
|
|
1929
|
-
}
|
|
1930
|
-
this.#config.headers?.append("cookie", token);
|
|
1931
|
-
updateHeaders(this.#config.headers);
|
|
1932
|
-
if (rawResponse) {
|
|
1933
|
-
return res;
|
|
1934
|
-
}
|
|
1935
|
-
try {
|
|
1936
|
-
return await res.clone().json();
|
|
1937
|
-
} catch {
|
|
1938
|
-
return res;
|
|
1939
|
-
}
|
|
1940
2472
|
}
|
|
2473
|
+
/**
|
|
2474
|
+
* Request a password reset email.
|
|
2475
|
+
*
|
|
2476
|
+
* Sends a `POST` to `/api/auth/password-reset` with the provided email and
|
|
2477
|
+
* optional callback information. The endpoint responds with a redirect URL
|
|
2478
|
+
* which is returned as a {@link Response} object.
|
|
2479
|
+
*/
|
|
1941
2480
|
async forgotPassword(req) {
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
let redirectUrl = defaults.redirectUrl;
|
|
1948
|
-
if ("email" in req) {
|
|
1949
|
-
email = req.email;
|
|
1950
|
-
}
|
|
1951
|
-
if ("callbackUrl" in req) {
|
|
1952
|
-
callbackUrl = req.callbackUrl ? req.callbackUrl : null;
|
|
1953
|
-
}
|
|
1954
|
-
if ("redirectUrl" in req) {
|
|
1955
|
-
redirectUrl = req.redirectUrl ? req.redirectUrl : null;
|
|
1956
|
-
}
|
|
1957
|
-
const body = JSON.stringify({
|
|
1958
|
-
email,
|
|
1959
|
-
redirectUrl,
|
|
1960
|
-
callbackUrl
|
|
1961
|
-
});
|
|
1962
|
-
const data = await fetchResetPassword(
|
|
1963
|
-
this.#config,
|
|
1964
|
-
"POST",
|
|
1965
|
-
body,
|
|
1966
|
-
new URLSearchParams(),
|
|
1967
|
-
false
|
|
1968
|
-
);
|
|
1969
|
-
return data;
|
|
1970
|
-
}
|
|
1971
|
-
async resetPassword(req) {
|
|
1972
|
-
let email = "";
|
|
1973
|
-
let password = "";
|
|
1974
|
-
const defaults = defaultCallbackUrl({ config: this.#config });
|
|
1975
|
-
let callbackUrl = defaults.callbackUrl;
|
|
1976
|
-
let redirectUrl = defaults.redirectUrl;
|
|
1977
|
-
if (req instanceof Request) {
|
|
1978
|
-
const body2 = await req.json();
|
|
1979
|
-
email = body2.email;
|
|
1980
|
-
password = body2.password;
|
|
1981
|
-
const cbFromHeaders = parseCallback(req.headers);
|
|
1982
|
-
if (cbFromHeaders) {
|
|
1983
|
-
callbackUrl = cbFromHeaders;
|
|
1984
|
-
}
|
|
1985
|
-
if (body2.callbackUrl) {
|
|
1986
|
-
callbackUrl = body2.callbackUrl;
|
|
1987
|
-
}
|
|
1988
|
-
if (body2.redirectUrl) {
|
|
1989
|
-
redirectUrl = body2.redirectUrl;
|
|
1990
|
-
}
|
|
1991
|
-
} else {
|
|
2481
|
+
return withNileContext(this.#config, async () => {
|
|
2482
|
+
let email = "";
|
|
2483
|
+
const defaults = defaultCallbackUrl(this.#config);
|
|
2484
|
+
let callbackUrl = defaults.callbackUrl;
|
|
2485
|
+
let redirectUrl = defaults.redirectUrl;
|
|
1992
2486
|
if ("email" in req) {
|
|
1993
2487
|
email = req.email;
|
|
1994
2488
|
}
|
|
1995
|
-
if ("password" in req) {
|
|
1996
|
-
password = req.password;
|
|
1997
|
-
}
|
|
1998
2489
|
if ("callbackUrl" in req) {
|
|
1999
|
-
callbackUrl = req.callbackUrl
|
|
2490
|
+
callbackUrl = fQUrl(req.callbackUrl ?? "", this.#config);
|
|
2000
2491
|
}
|
|
2001
2492
|
if ("redirectUrl" in req) {
|
|
2002
|
-
redirectUrl = req.redirectUrl
|
|
2493
|
+
redirectUrl = fQUrl(req.redirectUrl ?? "", this.#config);
|
|
2003
2494
|
}
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
callbackUrl
|
|
2011
|
-
});
|
|
2012
|
-
let urlWithParams;
|
|
2013
|
-
try {
|
|
2014
|
-
const data = await fetchResetPassword(this.#config, "POST", body);
|
|
2015
|
-
const cloned = data.clone();
|
|
2016
|
-
if (data.status === 400) {
|
|
2017
|
-
const text = await cloned.text();
|
|
2018
|
-
this.#logger.error(text);
|
|
2019
|
-
return data;
|
|
2020
|
-
}
|
|
2021
|
-
const { url } = await data.json();
|
|
2022
|
-
urlWithParams = url;
|
|
2023
|
-
} catch {
|
|
2024
|
-
}
|
|
2025
|
-
let token;
|
|
2026
|
-
try {
|
|
2027
|
-
const worthyParams = new URL(urlWithParams).searchParams;
|
|
2028
|
-
const answer = await fetchResetPassword(
|
|
2495
|
+
const body = JSON.stringify({
|
|
2496
|
+
email,
|
|
2497
|
+
redirectUrl,
|
|
2498
|
+
callbackUrl
|
|
2499
|
+
});
|
|
2500
|
+
const data = await fetchResetPassword(
|
|
2029
2501
|
this.#config,
|
|
2030
|
-
"
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
token = parseResetToken(answer.headers);
|
|
2035
|
-
} catch {
|
|
2036
|
-
this.#logger.warn(
|
|
2037
|
-
"Unable to parse reset password url. Password not reset."
|
|
2038
|
-
);
|
|
2039
|
-
}
|
|
2040
|
-
const cookie = this.#config.headers.get("cookie")?.split("; ");
|
|
2041
|
-
if (token) {
|
|
2042
|
-
cookie?.push(token);
|
|
2043
|
-
} else {
|
|
2044
|
-
throw new Error(
|
|
2045
|
-
"Unable to reset password, reset token is missing from response"
|
|
2502
|
+
"POST",
|
|
2503
|
+
body,
|
|
2504
|
+
new URLSearchParams(),
|
|
2505
|
+
false
|
|
2046
2506
|
);
|
|
2047
|
-
|
|
2048
|
-
this.#config.headers = new Headers({
|
|
2049
|
-
...this.#config.headers,
|
|
2050
|
-
cookie: cookie?.join("; ")
|
|
2507
|
+
return data;
|
|
2051
2508
|
});
|
|
2052
|
-
const res = await fetchResetPassword(this.#config, "PUT", body);
|
|
2053
|
-
cookie?.pop();
|
|
2054
|
-
const cleaned = cookie?.filter((c) => !c.includes("nile.session")) ?? [];
|
|
2055
|
-
cleaned.push(String(parseToken(res.headers)));
|
|
2056
|
-
const updatedHeaders = new Headers({ cookie: cleaned.join("; ") });
|
|
2057
|
-
updateHeaders(updatedHeaders);
|
|
2058
|
-
return res;
|
|
2059
2509
|
}
|
|
2510
|
+
/**
|
|
2511
|
+
* Complete a password reset.
|
|
2512
|
+
*
|
|
2513
|
+
* This workflow expects a token obtained from {@link forgotPassword}. The
|
|
2514
|
+
* function performs a POST/GET/PUT sequence against
|
|
2515
|
+
* `/api/auth/password-reset` as described in the OpenAPI specification.
|
|
2516
|
+
*
|
|
2517
|
+
* @param req - either a {@link Request} with a JSON body or an object
|
|
2518
|
+
* containing the necessary fields.
|
|
2519
|
+
*/
|
|
2520
|
+
async resetPassword(req) {
|
|
2521
|
+
return withNileContext(this.#config, async () => {
|
|
2522
|
+
let email = "";
|
|
2523
|
+
let password = "";
|
|
2524
|
+
const defaults = defaultCallbackUrl(this.#config);
|
|
2525
|
+
let callbackUrl = defaults.callbackUrl;
|
|
2526
|
+
let redirectUrl = defaults.redirectUrl;
|
|
2527
|
+
if (req instanceof Request) {
|
|
2528
|
+
const body2 = await req.json();
|
|
2529
|
+
email = body2.email;
|
|
2530
|
+
password = body2.password;
|
|
2531
|
+
const cbFromHeaders = parseCallback(req.headers);
|
|
2532
|
+
if (cbFromHeaders) {
|
|
2533
|
+
callbackUrl = cbFromHeaders;
|
|
2534
|
+
}
|
|
2535
|
+
if (body2.callbackUrl) {
|
|
2536
|
+
callbackUrl = body2.callbackUrl;
|
|
2537
|
+
}
|
|
2538
|
+
if (body2.redirectUrl) {
|
|
2539
|
+
redirectUrl = body2.redirectUrl;
|
|
2540
|
+
}
|
|
2541
|
+
} else {
|
|
2542
|
+
if ("email" in req) {
|
|
2543
|
+
email = req.email;
|
|
2544
|
+
}
|
|
2545
|
+
if ("password" in req) {
|
|
2546
|
+
password = req.password;
|
|
2547
|
+
}
|
|
2548
|
+
if ("callbackUrl" in req) {
|
|
2549
|
+
callbackUrl = req.callbackUrl ? req.callbackUrl : null;
|
|
2550
|
+
}
|
|
2551
|
+
if ("redirectUrl" in req) {
|
|
2552
|
+
redirectUrl = req.redirectUrl ? req.redirectUrl : null;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
await this.getCsrf();
|
|
2556
|
+
const body = JSON.stringify({
|
|
2557
|
+
email,
|
|
2558
|
+
password,
|
|
2559
|
+
redirectUrl,
|
|
2560
|
+
callbackUrl
|
|
2561
|
+
});
|
|
2562
|
+
let urlWithParams;
|
|
2563
|
+
try {
|
|
2564
|
+
const data = await fetchResetPassword(this.#config, "POST", body);
|
|
2565
|
+
const cloned = data.clone();
|
|
2566
|
+
if (data.status === 400) {
|
|
2567
|
+
const text = await cloned.text();
|
|
2568
|
+
this.#logger.error(text);
|
|
2569
|
+
return data;
|
|
2570
|
+
}
|
|
2571
|
+
const { url } = await data.json();
|
|
2572
|
+
urlWithParams = url;
|
|
2573
|
+
} catch {
|
|
2574
|
+
}
|
|
2575
|
+
let token;
|
|
2576
|
+
try {
|
|
2577
|
+
const worthyParams = new URL(urlWithParams).searchParams;
|
|
2578
|
+
const answer = await fetchResetPassword(
|
|
2579
|
+
this.#config,
|
|
2580
|
+
"GET",
|
|
2581
|
+
null,
|
|
2582
|
+
worthyParams
|
|
2583
|
+
);
|
|
2584
|
+
token = parseResetToken(answer.headers);
|
|
2585
|
+
} catch {
|
|
2586
|
+
this.#logger.warn(
|
|
2587
|
+
"Unable to parse reset password url. Password not reset."
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
const { headers } = ctx.get();
|
|
2591
|
+
const cookie = headers?.get("cookie")?.split("; ");
|
|
2592
|
+
if (token) {
|
|
2593
|
+
cookie?.push(token);
|
|
2594
|
+
} else {
|
|
2595
|
+
throw new Error(
|
|
2596
|
+
"Unable to reset password, reset token is missing from response"
|
|
2597
|
+
);
|
|
2598
|
+
}
|
|
2599
|
+
if (cookie) {
|
|
2600
|
+
headers?.set("cookie", cookie?.join("; "));
|
|
2601
|
+
ctx.set({
|
|
2602
|
+
headers
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2605
|
+
const res = await fetchResetPassword(this.#config, "PUT", body);
|
|
2606
|
+
cookie?.pop();
|
|
2607
|
+
const cleaned = cookie?.filter((c) => !c.includes("nile.session")) ?? [];
|
|
2608
|
+
cleaned.push(String(parseToken(res.headers)));
|
|
2609
|
+
const updatedHeaders = new Headers({ cookie: cleaned.join("; ") });
|
|
2610
|
+
updateHeaders(updatedHeaders);
|
|
2611
|
+
return res;
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
/**
|
|
2615
|
+
* Low level helper used by {@link signIn} to complete provider flows.
|
|
2616
|
+
*
|
|
2617
|
+
* Depending on the provider this issues either a GET or POST request to
|
|
2618
|
+
* `/api/auth/callback/{provider}` via {@link fetchCallback}.
|
|
2619
|
+
*/
|
|
2060
2620
|
async callback(provider, body) {
|
|
2061
2621
|
if (body instanceof Request) {
|
|
2062
|
-
|
|
2622
|
+
ctx.set({
|
|
2623
|
+
headers: body.headers
|
|
2624
|
+
});
|
|
2063
2625
|
return await fetchCallback(
|
|
2064
2626
|
this.#config,
|
|
2065
2627
|
provider,
|
|
@@ -2071,109 +2633,115 @@ var Auth = class {
|
|
|
2071
2633
|
return await fetchCallback(this.#config, provider, body);
|
|
2072
2634
|
}
|
|
2073
2635
|
async signIn(provider, payload, rawResponse) {
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2636
|
+
return withNileContext(this.#config, async () => {
|
|
2637
|
+
if (payload instanceof Request) {
|
|
2638
|
+
const body2 = new URLSearchParams(await payload.text());
|
|
2639
|
+
const origin = new URL(payload.url).origin;
|
|
2640
|
+
const payloadUrl = body2?.get("callbackUrl");
|
|
2641
|
+
const csrfToken2 = body2?.get("csrfToken");
|
|
2642
|
+
const callbackUrl = `${!payloadUrl?.startsWith("http") ? origin : ""}${payloadUrl}`;
|
|
2643
|
+
if (!csrfToken2) {
|
|
2644
|
+
throw new Error(
|
|
2645
|
+
"CSRF token in missing from request. Request it by the client before calling sign in"
|
|
2646
|
+
);
|
|
2647
|
+
}
|
|
2648
|
+
const updatedHeaders = new Headers(payload.headers);
|
|
2649
|
+
updatedHeaders.set("Content-Type", "application/x-www-form-urlencoded");
|
|
2650
|
+
ctx.set({ headers: updatedHeaders });
|
|
2651
|
+
const params = new URLSearchParams({
|
|
2652
|
+
csrfToken: csrfToken2,
|
|
2653
|
+
json: String(true)
|
|
2654
|
+
});
|
|
2655
|
+
if (payloadUrl) {
|
|
2656
|
+
params.set("callbackUrl", callbackUrl);
|
|
2657
|
+
}
|
|
2658
|
+
return await fetchSignIn(this.#config, provider, params);
|
|
2659
|
+
}
|
|
2660
|
+
ctx.set({ headers: null });
|
|
2661
|
+
const { info, error } = this.#logger;
|
|
2662
|
+
const providers = await this.listProviders();
|
|
2663
|
+
info("Obtaining csrf");
|
|
2664
|
+
const csrf = await obtainCsrf(this.#config);
|
|
2665
|
+
let csrfToken;
|
|
2666
|
+
if ("csrfToken" in csrf) {
|
|
2667
|
+
csrfToken = csrf.csrfToken;
|
|
2668
|
+
} else {
|
|
2669
|
+
throw new Error("Unable to obtain parse CSRF. Request blocked.");
|
|
2670
|
+
}
|
|
2671
|
+
const { credentials } = providers ?? {};
|
|
2672
|
+
if (!credentials) {
|
|
2081
2673
|
throw new Error(
|
|
2082
|
-
"
|
|
2674
|
+
"Unable to obtain credential provider. Aborting server side sign in."
|
|
2083
2675
|
);
|
|
2084
2676
|
}
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2677
|
+
const { email, password } = payload ?? {};
|
|
2678
|
+
if (provider === "email" && (!email || !password)) {
|
|
2679
|
+
throw new Error(
|
|
2680
|
+
"Server side sign in requires a user email and password."
|
|
2681
|
+
);
|
|
2682
|
+
}
|
|
2683
|
+
info(`Obtaining providers for ${email}`);
|
|
2684
|
+
info(`Attempting sign in with email ${email}`);
|
|
2685
|
+
if (!email) {
|
|
2686
|
+
throw new Error("Email missing from payload, unable to sign in");
|
|
2687
|
+
}
|
|
2688
|
+
const body = JSON.stringify({
|
|
2689
|
+
email,
|
|
2690
|
+
password,
|
|
2691
|
+
csrfToken,
|
|
2692
|
+
callbackUrl: credentials.callbackUrl
|
|
2093
2693
|
});
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
"Unable to obtain
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
);
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2694
|
+
const signInRes = await this.callback(provider, body);
|
|
2695
|
+
const authCookie = signInRes?.headers.get("set-cookie");
|
|
2696
|
+
if (!authCookie) {
|
|
2697
|
+
throw new Error("authentication failed");
|
|
2698
|
+
}
|
|
2699
|
+
const token = parseToken(signInRes?.headers);
|
|
2700
|
+
const possibleError = signInRes?.headers.get("location");
|
|
2701
|
+
if (possibleError) {
|
|
2702
|
+
let urlError;
|
|
2703
|
+
try {
|
|
2704
|
+
urlError = new URL(possibleError).searchParams.get("error");
|
|
2705
|
+
} catch {
|
|
2706
|
+
}
|
|
2707
|
+
if (urlError) {
|
|
2708
|
+
error("Unable to log user in", { error: urlError });
|
|
2709
|
+
return new Response(urlError, { status: signInRes.status });
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
if (!token) {
|
|
2713
|
+
error("Unable to obtain auth token", {
|
|
2714
|
+
authCookie,
|
|
2715
|
+
signInRes
|
|
2716
|
+
});
|
|
2717
|
+
throw new Error("Server login failed");
|
|
2718
|
+
}
|
|
2719
|
+
info("Server sign in successful", { authCookie });
|
|
2720
|
+
const setCookie = signInRes.headers.get("set-cookie");
|
|
2721
|
+
const { headers } = ctx.get();
|
|
2722
|
+
if (setCookie) {
|
|
2723
|
+
const cookie = [
|
|
2724
|
+
parseCSRF(headers),
|
|
2725
|
+
parseCallback(signInRes.headers),
|
|
2726
|
+
parseToken(signInRes.headers)
|
|
2727
|
+
].filter(Boolean).join("; ");
|
|
2728
|
+
const uHeaders = new Headers({ cookie });
|
|
2729
|
+
updateHeaders(uHeaders);
|
|
2730
|
+
ctx.set({ headers: uHeaders, preserveHeaders: true });
|
|
2731
|
+
} else {
|
|
2732
|
+
error("Unable to set context after sign in", {
|
|
2733
|
+
headers: signInRes.headers
|
|
2734
|
+
});
|
|
2735
|
+
}
|
|
2736
|
+
if (rawResponse) {
|
|
2737
|
+
return signInRes;
|
|
2738
|
+
}
|
|
2139
2739
|
try {
|
|
2140
|
-
|
|
2740
|
+
return await signInRes.clone().json();
|
|
2141
2741
|
} catch {
|
|
2742
|
+
return signInRes;
|
|
2142
2743
|
}
|
|
2143
|
-
|
|
2144
|
-
error("Unable to log user in", { error: urlError });
|
|
2145
|
-
return void 0;
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
if (!token) {
|
|
2149
|
-
error("Unable to obtain auth token", {
|
|
2150
|
-
authCookie,
|
|
2151
|
-
signInRes
|
|
2152
|
-
});
|
|
2153
|
-
throw new Error("Server login failed");
|
|
2154
|
-
}
|
|
2155
|
-
info("Server sign in successful", { authCookie });
|
|
2156
|
-
const setCookie = signInRes.headers.get("set-cookie");
|
|
2157
|
-
if (setCookie) {
|
|
2158
|
-
const cookie = [
|
|
2159
|
-
parseCSRF(this.#config.headers),
|
|
2160
|
-
parseCallback(signInRes.headers),
|
|
2161
|
-
parseToken(signInRes.headers)
|
|
2162
|
-
].filter(Boolean).join("; ");
|
|
2163
|
-
updateHeaders(new Headers({ cookie }));
|
|
2164
|
-
} else {
|
|
2165
|
-
error("Unable to set context after sign in", {
|
|
2166
|
-
headers: signInRes.headers
|
|
2167
|
-
});
|
|
2168
|
-
}
|
|
2169
|
-
if (rawResponse) {
|
|
2170
|
-
return signInRes;
|
|
2171
|
-
}
|
|
2172
|
-
try {
|
|
2173
|
-
return await signInRes.clone().json();
|
|
2174
|
-
} catch {
|
|
2175
|
-
return signInRes;
|
|
2176
|
-
}
|
|
2744
|
+
});
|
|
2177
2745
|
}
|
|
2178
2746
|
};
|
|
2179
2747
|
function parseCSRF(headers) {
|
|
@@ -2220,22 +2788,54 @@ function parseResetToken(headers) {
|
|
|
2220
2788
|
const [, token] = /((__Secure-)?nile\.reset=[^;]+)/.exec(authCookie) ?? [];
|
|
2221
2789
|
return token;
|
|
2222
2790
|
}
|
|
2223
|
-
function
|
|
2791
|
+
function parseTenantId(headers) {
|
|
2792
|
+
let authCookie = headers?.get("set-cookie");
|
|
2793
|
+
if (!authCookie) {
|
|
2794
|
+
authCookie = headers?.get("cookie");
|
|
2795
|
+
}
|
|
2796
|
+
if (!authCookie) {
|
|
2797
|
+
return void 0;
|
|
2798
|
+
}
|
|
2799
|
+
const [, token] = /((__Secure-)?nile\.tenant-id=[^;]+)/.exec(authCookie) ?? [];
|
|
2800
|
+
if (token) {
|
|
2801
|
+
const [, tenantId] = token.split("=");
|
|
2802
|
+
return tenantId;
|
|
2803
|
+
}
|
|
2804
|
+
return null;
|
|
2805
|
+
}
|
|
2806
|
+
function defaultCallbackUrl(config) {
|
|
2224
2807
|
let cb = null;
|
|
2225
2808
|
let redirect = null;
|
|
2226
|
-
const
|
|
2809
|
+
const { headers } = ctx.get();
|
|
2810
|
+
const fallbackCb = parseCallback(headers);
|
|
2227
2811
|
if (fallbackCb) {
|
|
2228
2812
|
const [, value] = fallbackCb.split("=");
|
|
2229
2813
|
cb = decodeURIComponent(value);
|
|
2230
2814
|
if (value) {
|
|
2231
|
-
redirect = `${new URL(cb).origin}${"/auth/reset-password" /* PASSWORD_RESET */}`;
|
|
2815
|
+
redirect = `${new URL(cb).origin}${config.routePrefix}${"/auth/reset-password" /* PASSWORD_RESET */}`;
|
|
2232
2816
|
}
|
|
2233
2817
|
}
|
|
2234
2818
|
return { callbackUrl: cb, redirectUrl: redirect };
|
|
2235
2819
|
}
|
|
2820
|
+
function fQUrl(path, config) {
|
|
2821
|
+
if (path.startsWith("/")) {
|
|
2822
|
+
const { callbackUrl } = defaultCallbackUrl(config);
|
|
2823
|
+
if (callbackUrl) {
|
|
2824
|
+
const { origin } = new URL(callbackUrl);
|
|
2825
|
+
return `${origin}${path}`;
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
try {
|
|
2829
|
+
new URL(path);
|
|
2830
|
+
} catch {
|
|
2831
|
+
throw new Error("An invalid URL has been passed.");
|
|
2832
|
+
}
|
|
2833
|
+
return path;
|
|
2834
|
+
}
|
|
2236
2835
|
|
|
2237
|
-
// src/auth/
|
|
2238
|
-
async function
|
|
2836
|
+
// src/auth/obtainCsrf.ts
|
|
2837
|
+
async function obtainCsrf(config, rawResponse = false) {
|
|
2838
|
+
const { headers } = ctx.get();
|
|
2239
2839
|
const res = await fetchCsrf(config);
|
|
2240
2840
|
const csrfCook = parseCSRF(res.headers);
|
|
2241
2841
|
if (csrfCook) {
|
|
@@ -2248,28 +2848,27 @@ async function getCsrf(config, rawResponse = false) {
|
|
|
2248
2848
|
parseCallback(res.headers),
|
|
2249
2849
|
parseToken(res.headers)
|
|
2250
2850
|
].filter(Boolean).join("; ");
|
|
2251
|
-
|
|
2252
|
-
|
|
2851
|
+
headers.set("cookie", cookie);
|
|
2852
|
+
ctx.set({ headers, preserveHeaders: true });
|
|
2853
|
+
updateHeaders(headers);
|
|
2253
2854
|
}
|
|
2254
2855
|
if (!rawResponse) {
|
|
2255
2856
|
return { csrfToken: token };
|
|
2256
2857
|
}
|
|
2257
2858
|
} else {
|
|
2258
|
-
const existingCookie =
|
|
2859
|
+
const existingCookie = headers.get("cookie");
|
|
2259
2860
|
const cookieParts = [];
|
|
2260
2861
|
if (existingCookie) {
|
|
2261
|
-
cookieParts.push(
|
|
2262
|
-
parseToken(config.headers),
|
|
2263
|
-
parseCallback(config.headers)
|
|
2264
|
-
);
|
|
2862
|
+
cookieParts.push(parseToken(headers), parseCallback(headers));
|
|
2265
2863
|
}
|
|
2266
2864
|
if (csrfCook) {
|
|
2267
2865
|
cookieParts.push(csrfCook);
|
|
2268
2866
|
} else {
|
|
2269
|
-
cookieParts.push(parseCSRF(
|
|
2867
|
+
cookieParts.push(parseCSRF(headers));
|
|
2270
2868
|
}
|
|
2271
2869
|
const cookie = cookieParts.filter(Boolean).join("; ");
|
|
2272
|
-
|
|
2870
|
+
headers.set("cookie", cookie);
|
|
2871
|
+
ctx.set({ headers, preserveHeaders: true });
|
|
2273
2872
|
updateHeaders(new Headers({ cookie }));
|
|
2274
2873
|
}
|
|
2275
2874
|
if (rawResponse) {
|
|
@@ -2282,209 +2881,443 @@ async function getCsrf(config, rawResponse = false) {
|
|
|
2282
2881
|
}
|
|
2283
2882
|
}
|
|
2284
2883
|
|
|
2884
|
+
// src/utils/qualifyDomain.ts
|
|
2885
|
+
function fQUrl2(callbackUrl, path) {
|
|
2886
|
+
if (path.startsWith("/")) {
|
|
2887
|
+
if (callbackUrl) {
|
|
2888
|
+
const { origin } = new URL(callbackUrl);
|
|
2889
|
+
return `${origin}${path}`;
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
try {
|
|
2893
|
+
new URL(path);
|
|
2894
|
+
} catch {
|
|
2895
|
+
throw new Error("An invalid URL has been passed.");
|
|
2896
|
+
}
|
|
2897
|
+
return path;
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2285
2900
|
// src/users/index.ts
|
|
2286
2901
|
var Users = class {
|
|
2287
2902
|
#config;
|
|
2288
2903
|
#logger;
|
|
2904
|
+
/**
|
|
2905
|
+
* Create a new Users helper.
|
|
2906
|
+
* @param config - The configuration used for requests.
|
|
2907
|
+
*/
|
|
2289
2908
|
constructor(config) {
|
|
2290
2909
|
this.#config = config;
|
|
2291
|
-
this.#logger =
|
|
2910
|
+
this.#logger = config.logger("[me]");
|
|
2292
2911
|
}
|
|
2912
|
+
/**
|
|
2913
|
+
* Update the current user via `PUT /api/me`.
|
|
2914
|
+
*
|
|
2915
|
+
* The OpenAPI description for this endpoint can be found in
|
|
2916
|
+
* `packages/server/src/api/routes/me/index.ts` under `updateSelf`.
|
|
2917
|
+
*
|
|
2918
|
+
* @param req - Partial user fields to send.
|
|
2919
|
+
* @param [rawResponse] - When `true`, return the raw {@link Response}.
|
|
2920
|
+
*/
|
|
2293
2921
|
async updateSelf(req, rawResponse) {
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2922
|
+
return withNileContext(this.#config, async () => {
|
|
2923
|
+
const res = await fetchMe(this.#config, "PUT", JSON.stringify(req));
|
|
2924
|
+
if (rawResponse) {
|
|
2925
|
+
return res;
|
|
2926
|
+
}
|
|
2927
|
+
try {
|
|
2928
|
+
return await res?.clone().json();
|
|
2929
|
+
} catch {
|
|
2930
|
+
return res;
|
|
2931
|
+
}
|
|
2932
|
+
});
|
|
2303
2933
|
}
|
|
2934
|
+
/**
|
|
2935
|
+
* Remove the current user using `DELETE /api/me`.
|
|
2936
|
+
*
|
|
2937
|
+
* After the request the authentication headers are cleared with
|
|
2938
|
+
* {@link updateHeaders}. The OpenAPI docs for this route are in
|
|
2939
|
+
* `packages/server/src/api/routes/me/index.ts` under `removeSelf`.
|
|
2940
|
+
*/
|
|
2304
2941
|
async removeSelf() {
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2942
|
+
return withNileContext(this.#config, async () => {
|
|
2943
|
+
const me = await this.getSelf();
|
|
2944
|
+
if ("id" in me) {
|
|
2945
|
+
const userId = me.id;
|
|
2946
|
+
ctx.set({ userId });
|
|
2947
|
+
}
|
|
2948
|
+
const res = await fetchMe(this.#config, "DELETE");
|
|
2949
|
+
updateHeaders(new Headers());
|
|
2950
|
+
return res;
|
|
2951
|
+
});
|
|
2312
2952
|
}
|
|
2313
2953
|
async getSelf(rawResponse) {
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2954
|
+
return withNileContext(this.#config, async () => {
|
|
2955
|
+
const res = await fetchMe(this.#config);
|
|
2956
|
+
if (rawResponse) {
|
|
2957
|
+
return res;
|
|
2958
|
+
}
|
|
2959
|
+
try {
|
|
2960
|
+
return await res?.clone().json();
|
|
2961
|
+
} catch {
|
|
2962
|
+
return res;
|
|
2963
|
+
}
|
|
2964
|
+
});
|
|
2323
2965
|
}
|
|
2324
|
-
async verifySelf(
|
|
2325
|
-
|
|
2326
|
-
const
|
|
2327
|
-
|
|
2328
|
-
|
|
2966
|
+
async verifySelf(options, rawResponse = false) {
|
|
2967
|
+
return withNileContext(this.#config, async () => {
|
|
2968
|
+
const bypassEmail = typeof options === "object" && options?.bypassEmail === true;
|
|
2969
|
+
const callbackUrl = fQUrl2(
|
|
2970
|
+
defaultCallbackUrl2().callbackUrl,
|
|
2971
|
+
typeof options === "object" ? String(options.callbackUrl) : "/"
|
|
2972
|
+
);
|
|
2973
|
+
let res;
|
|
2974
|
+
try {
|
|
2975
|
+
const me = await this.getSelf();
|
|
2976
|
+
if (me instanceof Response) {
|
|
2977
|
+
return me;
|
|
2978
|
+
}
|
|
2979
|
+
res = await verifyEmailAddress(this.#config, me, String(callbackUrl));
|
|
2980
|
+
return res;
|
|
2981
|
+
} catch (e) {
|
|
2982
|
+
if (!bypassEmail) {
|
|
2983
|
+
let message = "Unable to verify email.";
|
|
2984
|
+
if (e instanceof Error) {
|
|
2985
|
+
message = e.message;
|
|
2986
|
+
}
|
|
2987
|
+
this.#logger?.error(
|
|
2988
|
+
`${message} you can bypass this message by setting bypassEmail: true when calling 'verifySelf'`
|
|
2989
|
+
);
|
|
2990
|
+
res = new Response(message, { status: 400 });
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
if (bypassEmail) {
|
|
2994
|
+
this.#logger?.info(
|
|
2995
|
+
"bypassing email requirements for email verification"
|
|
2996
|
+
);
|
|
2997
|
+
res = this.updateSelf({ emailVerified: true }, rawResponse);
|
|
2329
2998
|
}
|
|
2330
|
-
const res = await verifyEmailAddress(this.#config, me);
|
|
2331
2999
|
return res;
|
|
2332
|
-
}
|
|
2333
|
-
this.#logger?.warn(
|
|
2334
|
-
"Unable to verify email. The current user's email will be set to verified any way. Be sure to configure emails for production."
|
|
2335
|
-
);
|
|
2336
|
-
}
|
|
2337
|
-
if (bypassEmail) {
|
|
2338
|
-
return await this.updateSelf({ emailVerified: true }, rawResponse);
|
|
2339
|
-
}
|
|
2340
|
-
this.#logger.error(
|
|
2341
|
-
"Unable to verify email address. Configure your SMTP server in the console."
|
|
2342
|
-
);
|
|
2343
|
-
return void 0;
|
|
3000
|
+
});
|
|
2344
3001
|
}
|
|
2345
3002
|
};
|
|
2346
|
-
async function verifyEmailAddress(config, user) {
|
|
2347
|
-
|
|
2348
|
-
|
|
3003
|
+
async function verifyEmailAddress(config, user, callback) {
|
|
3004
|
+
const { headers } = ctx.get();
|
|
3005
|
+
headers?.set("content-type", "application/x-www-form-urlencoded");
|
|
3006
|
+
ctx.set({ headers });
|
|
3007
|
+
const { csrfToken } = await obtainCsrf(config);
|
|
3008
|
+
const defaults = defaultCallbackUrl2();
|
|
3009
|
+
const callbackUrl = callback ?? String(defaults.callbackUrl);
|
|
2349
3010
|
const res = await fetchVerifyEmail(
|
|
2350
3011
|
config,
|
|
2351
3012
|
"POST",
|
|
2352
|
-
new URLSearchParams({
|
|
3013
|
+
new URLSearchParams({
|
|
3014
|
+
csrfToken,
|
|
3015
|
+
email: user.email,
|
|
3016
|
+
callbackUrl
|
|
3017
|
+
}).toString()
|
|
2353
3018
|
);
|
|
2354
3019
|
if (res.status > 299) {
|
|
2355
3020
|
throw new Error(await res.text());
|
|
2356
3021
|
}
|
|
2357
3022
|
return res;
|
|
2358
3023
|
}
|
|
3024
|
+
function defaultCallbackUrl2() {
|
|
3025
|
+
let cb = null;
|
|
3026
|
+
const { headers } = ctx.get();
|
|
3027
|
+
const fallbackCb = parseCallback(headers);
|
|
3028
|
+
if (fallbackCb) {
|
|
3029
|
+
const [, value] = fallbackCb.split("=");
|
|
3030
|
+
cb = decodeURIComponent(value);
|
|
3031
|
+
}
|
|
3032
|
+
return { callbackUrl: cb };
|
|
3033
|
+
}
|
|
2359
3034
|
|
|
2360
3035
|
// src/tenants/index.ts
|
|
2361
3036
|
var Tenants = class {
|
|
2362
|
-
#logger;
|
|
2363
3037
|
#config;
|
|
2364
3038
|
constructor(config) {
|
|
2365
|
-
this.#logger = Logger(config, "[tenants]");
|
|
2366
3039
|
this.#config = config;
|
|
2367
3040
|
}
|
|
3041
|
+
/**
|
|
3042
|
+
* Create a new tenant using `POST /api/tenants`.
|
|
3043
|
+
* See `packages/server/src/api/routes/tenants/POST.ts` for the
|
|
3044
|
+
* `createTenant` operation definition.
|
|
3045
|
+
*/
|
|
2368
3046
|
async create(req, rawResponse) {
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
3047
|
+
return withNileContext(this.#config, async () => {
|
|
3048
|
+
let res;
|
|
3049
|
+
if (typeof req === "string") {
|
|
3050
|
+
res = await fetchTenants(
|
|
3051
|
+
this.#config,
|
|
3052
|
+
"POST",
|
|
3053
|
+
JSON.stringify({ name: req })
|
|
3054
|
+
);
|
|
3055
|
+
} else if (typeof req === "object" && ("name" in req || "id" in req)) {
|
|
3056
|
+
res = await fetchTenants(this.#config, "POST", JSON.stringify(req));
|
|
3057
|
+
}
|
|
3058
|
+
if (rawResponse) {
|
|
3059
|
+
return res;
|
|
3060
|
+
}
|
|
3061
|
+
try {
|
|
3062
|
+
return await res?.clone().json();
|
|
3063
|
+
} catch {
|
|
3064
|
+
return res;
|
|
3065
|
+
}
|
|
3066
|
+
});
|
|
2387
3067
|
}
|
|
3068
|
+
/**
|
|
3069
|
+
* Remove a tenant via `DELETE /api/tenants/{tenantId}`.
|
|
3070
|
+
*
|
|
3071
|
+
* @param req - The tenant to remove or context containing the id.
|
|
3072
|
+
*/
|
|
2388
3073
|
async delete(req) {
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
3074
|
+
return withNileContext(this.#config, async () => {
|
|
3075
|
+
if (typeof req === "string") {
|
|
3076
|
+
ctx.set({ tenantId: req });
|
|
3077
|
+
}
|
|
3078
|
+
if (typeof req === "object" && "id" in req) {
|
|
3079
|
+
ctx.set({ tenantId: req.id });
|
|
3080
|
+
}
|
|
3081
|
+
const res = await fetchTenant(this.#config, "DELETE");
|
|
3082
|
+
return res;
|
|
3083
|
+
});
|
|
2397
3084
|
}
|
|
3085
|
+
/**
|
|
3086
|
+
* Fetch details for a tenant using `GET /api/tenants/{tenantId}`.
|
|
3087
|
+
*
|
|
3088
|
+
* @param req - Tenant identifier or context.
|
|
3089
|
+
* @param [rawResponse] - When true, return the raw {@link Response}.
|
|
3090
|
+
*/
|
|
2398
3091
|
async get(req, rawResponse) {
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
3092
|
+
return withNileContext(this.#config, async () => {
|
|
3093
|
+
if (typeof req === "string") {
|
|
3094
|
+
ctx.set({ tenantId: req });
|
|
3095
|
+
} else if (typeof req === "object" && "id" in req) {
|
|
3096
|
+
ctx.set({ tenantId: req.id });
|
|
3097
|
+
}
|
|
3098
|
+
const res = await fetchTenant(this.#config, "GET");
|
|
3099
|
+
if (rawResponse === true || req === true) {
|
|
3100
|
+
return res;
|
|
3101
|
+
}
|
|
3102
|
+
try {
|
|
3103
|
+
return await res?.clone().json();
|
|
3104
|
+
} catch {
|
|
3105
|
+
return res;
|
|
3106
|
+
}
|
|
3107
|
+
});
|
|
2413
3108
|
}
|
|
2414
3109
|
async update(req, rawResponse) {
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
3110
|
+
return withNileContext(this.#config, async () => {
|
|
3111
|
+
let res;
|
|
3112
|
+
if (typeof req === "object" && ("name" in req || "id" in req)) {
|
|
3113
|
+
const { id, ...remaining } = req;
|
|
3114
|
+
if (id) {
|
|
3115
|
+
ctx.set({ tenantId: id });
|
|
3116
|
+
}
|
|
3117
|
+
res = await fetchTenant(this.#config, "PUT", JSON.stringify(remaining));
|
|
2420
3118
|
}
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
}
|
|
3119
|
+
if (rawResponse) {
|
|
3120
|
+
return res;
|
|
3121
|
+
}
|
|
3122
|
+
try {
|
|
3123
|
+
return await res?.clone().json();
|
|
3124
|
+
} catch {
|
|
3125
|
+
return res;
|
|
3126
|
+
}
|
|
3127
|
+
});
|
|
2431
3128
|
}
|
|
3129
|
+
/**
|
|
3130
|
+
* List tenants for the current user via `GET /api/tenants`.
|
|
3131
|
+
* See `packages/server/src/api/routes/tenants/GET.ts` for details.
|
|
3132
|
+
*/
|
|
2432
3133
|
async list(req) {
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
3134
|
+
return withNileContext(
|
|
3135
|
+
this.#config,
|
|
3136
|
+
async () => {
|
|
3137
|
+
const res = await fetchTenantsByUser(this.#config);
|
|
3138
|
+
if (req === true) {
|
|
3139
|
+
return res;
|
|
3140
|
+
}
|
|
3141
|
+
try {
|
|
3142
|
+
return await res?.clone().json();
|
|
3143
|
+
} catch {
|
|
3144
|
+
return res;
|
|
3145
|
+
}
|
|
3146
|
+
},
|
|
3147
|
+
"listTenants"
|
|
3148
|
+
);
|
|
2442
3149
|
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Leave the current tenant using `DELETE /api/tenants/{tenantId}/users/{userId}`.
|
|
3152
|
+
*
|
|
3153
|
+
* @param [req] - Optionally specify the tenant id to leave.
|
|
3154
|
+
*/
|
|
2443
3155
|
async leaveTenant(req) {
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
3156
|
+
return withNileContext(this.#config, async () => {
|
|
3157
|
+
const me = await fetchMe(this.#config);
|
|
3158
|
+
try {
|
|
3159
|
+
const json = await me.json();
|
|
3160
|
+
if ("id" in json) {
|
|
3161
|
+
ctx.set({ userId: json.id, preserveHeaders: true });
|
|
3162
|
+
}
|
|
3163
|
+
} catch {
|
|
2449
3164
|
}
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
this.#
|
|
2456
|
-
}
|
|
2457
|
-
return await fetchTenantUser(this.#config, "DELETE");
|
|
3165
|
+
if (typeof req === "string") {
|
|
3166
|
+
ctx.set({ tenantId: req, preserveHeaders: true });
|
|
3167
|
+
} else {
|
|
3168
|
+
this.#handleContext(req);
|
|
3169
|
+
}
|
|
3170
|
+
return await fetchTenantUser(this.#config, "DELETE");
|
|
3171
|
+
});
|
|
2458
3172
|
}
|
|
2459
3173
|
async addMember(req, rawResponse) {
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
3174
|
+
return withNileContext(this.#config, async () => {
|
|
3175
|
+
if (typeof req === "string") {
|
|
3176
|
+
ctx.set({ userId: req, preserveHeaders: true });
|
|
3177
|
+
} else {
|
|
3178
|
+
this.#handleContext(req);
|
|
3179
|
+
}
|
|
3180
|
+
const res = await fetchTenantUser(this.#config, "PUT");
|
|
3181
|
+
return responseHandler(res, rawResponse);
|
|
3182
|
+
});
|
|
2467
3183
|
}
|
|
3184
|
+
/**
|
|
3185
|
+
* Remove a user from a tenant with `DELETE /api/tenants/{tenantId}/users/{userId}`.
|
|
3186
|
+
*
|
|
3187
|
+
* @param req - User and tenant identifiers or context.
|
|
3188
|
+
* @param [rawResponse] - When true, return the raw {@link Response}.
|
|
3189
|
+
*/
|
|
2468
3190
|
async removeMember(req, rawResponse) {
|
|
2469
|
-
this.#
|
|
2470
|
-
|
|
2471
|
-
|
|
3191
|
+
return withNileContext(this.#config, async () => {
|
|
3192
|
+
this.#handleContext(req);
|
|
3193
|
+
if (typeof req === "string") {
|
|
3194
|
+
ctx.set({ userId: req, preserveHeaders: true });
|
|
3195
|
+
}
|
|
3196
|
+
const res = await fetchTenantUser(this.#config, "DELETE");
|
|
3197
|
+
return responseHandler(res, rawResponse);
|
|
3198
|
+
});
|
|
2472
3199
|
}
|
|
2473
3200
|
async users(req, rawResponse) {
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
3201
|
+
return withNileContext(
|
|
3202
|
+
this.#config,
|
|
3203
|
+
async () => {
|
|
3204
|
+
this.#handleContext(req);
|
|
3205
|
+
const res = await fetchTenantUsers(this.#config, "GET");
|
|
3206
|
+
return responseHandler(
|
|
3207
|
+
res,
|
|
3208
|
+
rawResponse || typeof req === "boolean" && req
|
|
3209
|
+
);
|
|
3210
|
+
},
|
|
3211
|
+
"users"
|
|
3212
|
+
);
|
|
3213
|
+
}
|
|
3214
|
+
/**
|
|
3215
|
+
* List invites for the current tenant via `GET /api/tenants/{tenantId}/invites`.
|
|
3216
|
+
*/
|
|
3217
|
+
async invites() {
|
|
3218
|
+
return withNileContext(
|
|
3219
|
+
this.#config,
|
|
3220
|
+
async () => {
|
|
3221
|
+
const res = await fetchInvites(this.#config);
|
|
3222
|
+
return responseHandler(res);
|
|
3223
|
+
},
|
|
3224
|
+
"invites"
|
|
2479
3225
|
);
|
|
2480
3226
|
}
|
|
3227
|
+
async invite(req, rawResponse) {
|
|
3228
|
+
return withNileContext(
|
|
3229
|
+
this.#config,
|
|
3230
|
+
async () => {
|
|
3231
|
+
const { csrfToken } = await obtainCsrf(
|
|
3232
|
+
this.#config
|
|
3233
|
+
);
|
|
3234
|
+
const defaults = defaultCallbackUrl3(this.#config);
|
|
3235
|
+
let identifier = req;
|
|
3236
|
+
let callbackUrl = defaults.callbackUrl;
|
|
3237
|
+
let redirectUrl = defaults.redirectUrl;
|
|
3238
|
+
if (typeof req === "object") {
|
|
3239
|
+
if ("email" in req) {
|
|
3240
|
+
identifier = req.email;
|
|
3241
|
+
}
|
|
3242
|
+
const { callbackUrl: cbUrl } = defaultCallbackUrl3(this.#config);
|
|
3243
|
+
if ("callbackUrl" in req) {
|
|
3244
|
+
callbackUrl = fQUrl2(cbUrl, req.callbackUrl ?? "/");
|
|
3245
|
+
}
|
|
3246
|
+
if ("redirectUrl" in req) {
|
|
3247
|
+
redirectUrl = fQUrl2(cbUrl, req.redirectUrl ?? "/");
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
const { headers } = ctx.get();
|
|
3251
|
+
headers?.set("Content-Type", "application/x-www-form-urlencoded");
|
|
3252
|
+
ctx.set({ headers });
|
|
3253
|
+
const res = await fetchInvite(
|
|
3254
|
+
this.#config,
|
|
3255
|
+
"POST",
|
|
3256
|
+
new URLSearchParams({
|
|
3257
|
+
identifier,
|
|
3258
|
+
csrfToken,
|
|
3259
|
+
callbackUrl,
|
|
3260
|
+
redirectUrl
|
|
3261
|
+
}).toString()
|
|
3262
|
+
);
|
|
3263
|
+
return responseHandler(res, rawResponse);
|
|
3264
|
+
},
|
|
3265
|
+
"invites"
|
|
3266
|
+
);
|
|
3267
|
+
}
|
|
3268
|
+
/**
|
|
3269
|
+
* Accept an invite using `PUT /api/tenants/{tenantId}/invite`.
|
|
3270
|
+
*
|
|
3271
|
+
* @param req - Identifier and token from the invite email.
|
|
3272
|
+
* @param [rawResponse] - When true, return the raw {@link Response}.
|
|
3273
|
+
*/
|
|
3274
|
+
async acceptInvite(req, rawResponse) {
|
|
3275
|
+
return withNileContext(this.#config, async () => {
|
|
3276
|
+
if (!req) {
|
|
3277
|
+
throw new Error("The identifier and token are required.");
|
|
3278
|
+
}
|
|
3279
|
+
const { identifier, token } = req;
|
|
3280
|
+
const { callbackUrl: cbUrl } = defaultCallbackUrl3(this.#config);
|
|
3281
|
+
const callbackUrl = fQUrl2(cbUrl, req?.callbackUrl ?? "/");
|
|
3282
|
+
const res = await fetchInvite(
|
|
3283
|
+
this.#config,
|
|
3284
|
+
"PUT",
|
|
3285
|
+
new URLSearchParams({
|
|
3286
|
+
identifier,
|
|
3287
|
+
token,
|
|
3288
|
+
callbackUrl
|
|
3289
|
+
}).toString()
|
|
3290
|
+
);
|
|
3291
|
+
return responseHandler(res, rawResponse);
|
|
3292
|
+
});
|
|
3293
|
+
}
|
|
3294
|
+
/**
|
|
3295
|
+
* Delete a pending invite using `DELETE /api/tenants/{tenantId}/invite/{inviteId}`.
|
|
3296
|
+
*
|
|
3297
|
+
* @param req - Identifier of the invite to remove.
|
|
3298
|
+
*/
|
|
3299
|
+
async deleteInvite(req) {
|
|
3300
|
+
return withNileContext(this.#config, async () => {
|
|
3301
|
+
let id = "";
|
|
3302
|
+
if (typeof req === "object") {
|
|
3303
|
+
id = req.id;
|
|
3304
|
+
} else {
|
|
3305
|
+
id = req;
|
|
3306
|
+
}
|
|
3307
|
+
if (!id) {
|
|
3308
|
+
throw new Error("An invite id is required.");
|
|
3309
|
+
}
|
|
3310
|
+
const res = await fetchInvite(this.#config, "DELETE", id);
|
|
3311
|
+
return responseHandler(res, true);
|
|
3312
|
+
});
|
|
3313
|
+
}
|
|
2481
3314
|
#handleContext(req) {
|
|
2482
3315
|
if (typeof req === "object") {
|
|
2483
3316
|
if ("tenantId" in req) {
|
|
2484
|
-
|
|
3317
|
+
ctx.set({ tenantId: req.tenantId, preserveHeaders: true });
|
|
2485
3318
|
}
|
|
2486
3319
|
if ("userId" in req) {
|
|
2487
|
-
|
|
3320
|
+
ctx.set({ userId: req.userId, preserveHeaders: true });
|
|
2488
3321
|
}
|
|
2489
3322
|
}
|
|
2490
3323
|
}
|
|
@@ -2499,31 +3332,45 @@ async function responseHandler(res, rawResponse) {
|
|
|
2499
3332
|
return res;
|
|
2500
3333
|
}
|
|
2501
3334
|
}
|
|
3335
|
+
function defaultCallbackUrl3(config) {
|
|
3336
|
+
let cb = null;
|
|
3337
|
+
let redirect = null;
|
|
3338
|
+
const { headers, tenantId } = ctx.get();
|
|
3339
|
+
const fallbackCb = parseCallback(headers);
|
|
3340
|
+
if (fallbackCb) {
|
|
3341
|
+
const [, value] = fallbackCb.split("=");
|
|
3342
|
+
cb = decodeURIComponent(value);
|
|
3343
|
+
if (value) {
|
|
3344
|
+
redirect = `${new URL(cb).origin}${config.routePrefix}${"/tenants/{tenantId}/invite" /* INVITE */.replace("{tenantId}", String(tenantId))}`;
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
return { callbackUrl: cb, redirectUrl: redirect };
|
|
3348
|
+
}
|
|
2502
3349
|
|
|
2503
3350
|
// src/api/handlers/withContext/index.ts
|
|
2504
3351
|
function handlersWithContext(config) {
|
|
2505
|
-
const
|
|
2506
|
-
const
|
|
2507
|
-
const
|
|
2508
|
-
const
|
|
3352
|
+
const GET7 = GETTER(config.routes, config);
|
|
3353
|
+
const POST6 = POSTER(config.routes, config);
|
|
3354
|
+
const DELETE5 = DELETER(config.routes, config);
|
|
3355
|
+
const PUT6 = PUTER(config.routes, config);
|
|
2509
3356
|
return {
|
|
2510
3357
|
GET: async (req) => {
|
|
2511
|
-
const response = await
|
|
3358
|
+
const response = await GET7(req);
|
|
2512
3359
|
const updatedConfig = updateConfig(response, config);
|
|
2513
3360
|
return { response, nile: new Server(updatedConfig) };
|
|
2514
3361
|
},
|
|
2515
3362
|
POST: async (req) => {
|
|
2516
|
-
const response = await
|
|
3363
|
+
const response = await POST6(req);
|
|
2517
3364
|
const updatedConfig = updateConfig(response, config);
|
|
2518
3365
|
return { response, nile: new Server(updatedConfig) };
|
|
2519
3366
|
},
|
|
2520
3367
|
DELETE: async (req) => {
|
|
2521
|
-
const response = await
|
|
3368
|
+
const response = await DELETE5(req);
|
|
2522
3369
|
const updatedConfig = updateConfig(response, config);
|
|
2523
3370
|
return { response, nile: new Server(updatedConfig) };
|
|
2524
3371
|
},
|
|
2525
3372
|
PUT: async (req) => {
|
|
2526
|
-
const response = await
|
|
3373
|
+
const response = await PUT6(req);
|
|
2527
3374
|
const updatedConfig = updateConfig(response, config);
|
|
2528
3375
|
return { response, nile: new Server(updatedConfig) };
|
|
2529
3376
|
}
|
|
@@ -2532,29 +3379,32 @@ function handlersWithContext(config) {
|
|
|
2532
3379
|
function updateConfig(response, config) {
|
|
2533
3380
|
let origin = "http://localhost:3000";
|
|
2534
3381
|
let headers = null;
|
|
2535
|
-
if (response
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
3382
|
+
if (response instanceof Response) {
|
|
3383
|
+
if (response?.status === 302) {
|
|
3384
|
+
const location = response.headers.get("location");
|
|
3385
|
+
if (location) {
|
|
3386
|
+
const urlLocation = new URL(location);
|
|
3387
|
+
origin = urlLocation.origin;
|
|
3388
|
+
}
|
|
2540
3389
|
}
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
3390
|
+
const setCookies = [];
|
|
3391
|
+
if (response?.headers) {
|
|
3392
|
+
for (const [key17, value] of response.headers) {
|
|
3393
|
+
if (key17.toLowerCase() === "set-cookie") {
|
|
3394
|
+
setCookies.push(value);
|
|
3395
|
+
}
|
|
2547
3396
|
}
|
|
2548
3397
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
3398
|
+
if (setCookies.length > 0) {
|
|
3399
|
+
const cookieHeader = setCookies.map((cookieStr) => cookieStr.split(";")[0]).join("; ");
|
|
3400
|
+
headers = new Headers({ cookie: cookieHeader });
|
|
3401
|
+
}
|
|
2553
3402
|
}
|
|
2554
3403
|
return {
|
|
2555
3404
|
...config,
|
|
2556
3405
|
origin,
|
|
2557
|
-
headers: headers ?? void 0
|
|
3406
|
+
headers: headers ?? void 0,
|
|
3407
|
+
preserveHeaders: true
|
|
2558
3408
|
};
|
|
2559
3409
|
}
|
|
2560
3410
|
|
|
@@ -2565,40 +3415,63 @@ var Server = class {
|
|
|
2565
3415
|
auth;
|
|
2566
3416
|
#config;
|
|
2567
3417
|
#handlers;
|
|
2568
|
-
#paths;
|
|
2569
3418
|
#manager;
|
|
2570
|
-
#headers;
|
|
2571
3419
|
constructor(config) {
|
|
2572
|
-
this.#config = new Config(
|
|
3420
|
+
this.#config = new Config({
|
|
3421
|
+
...config,
|
|
3422
|
+
extensionCtx: buildExtensionConfig(this)
|
|
3423
|
+
});
|
|
2573
3424
|
watchTenantId((tenantId) => {
|
|
2574
|
-
if (tenantId !== this.#config.tenantId) {
|
|
2575
|
-
this.#config.tenantId = tenantId;
|
|
3425
|
+
if (tenantId !== this.#config.context.tenantId) {
|
|
3426
|
+
this.#config.context.tenantId = String(tenantId);
|
|
2576
3427
|
this.#reset();
|
|
2577
3428
|
}
|
|
2578
3429
|
});
|
|
2579
3430
|
watchUserId((userId) => {
|
|
2580
|
-
if (userId !== this.#config.userId) {
|
|
2581
|
-
this.#config.userId = userId;
|
|
3431
|
+
if (userId !== this.#config.context.userId) {
|
|
3432
|
+
this.#config.context.userId = String(userId);
|
|
2582
3433
|
this.#reset();
|
|
2583
3434
|
}
|
|
2584
3435
|
});
|
|
2585
3436
|
watchHeaders((headers) => {
|
|
2586
|
-
|
|
2587
|
-
|
|
3437
|
+
if (headers) {
|
|
3438
|
+
this.#config.context.headers = new Headers(headers);
|
|
3439
|
+
this.#config.context.preserveHeaders = true;
|
|
3440
|
+
this.#reset();
|
|
3441
|
+
}
|
|
2588
3442
|
});
|
|
2589
3443
|
this.#handlers = {
|
|
2590
3444
|
...this.#config.handlers,
|
|
2591
3445
|
withContext: handlersWithContext(this.#config)
|
|
2592
3446
|
};
|
|
2593
|
-
this.#
|
|
2594
|
-
this.#config.tenantId = getTenantId({ config: this.#config });
|
|
3447
|
+
this.#config.context.preserveHeaders = config?.preserveHeaders ?? false;
|
|
3448
|
+
this.#config.context.tenantId = getTenantId({ config: this.#config });
|
|
2595
3449
|
this.#manager = new DBManager(this.#config);
|
|
2596
3450
|
this.#handleHeaders(config);
|
|
2597
3451
|
this.users = new Users(this.#config);
|
|
2598
3452
|
this.tenants = new Tenants(this.#config);
|
|
2599
3453
|
this.auth = new Auth(this.#config);
|
|
3454
|
+
if (config?.extensions) {
|
|
3455
|
+
for (const create2 of config.extensions) {
|
|
3456
|
+
if (typeof create2 !== "function") {
|
|
3457
|
+
continue;
|
|
3458
|
+
}
|
|
3459
|
+
const ext = create2(this);
|
|
3460
|
+
if (ext.onConfigure) {
|
|
3461
|
+
ext.onConfigure();
|
|
3462
|
+
}
|
|
3463
|
+
if (ext?.replace?.handlers) {
|
|
3464
|
+
this.#config.logger("[EXTENSION]").debug(`${ext.id} replacing handlers`);
|
|
3465
|
+
this.#handlers = ext.replace.handlers({
|
|
3466
|
+
...this.#config.handlers,
|
|
3467
|
+
withContext: handlersWithContext(this.#config)
|
|
3468
|
+
});
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
2600
3472
|
}
|
|
2601
3473
|
get db() {
|
|
3474
|
+
this.#config.context = { ...this.getContext() };
|
|
2602
3475
|
const pool = this.#manager.getConnection(this.#config);
|
|
2603
3476
|
return Object.assign(pool, {
|
|
2604
3477
|
clearConnections: () => {
|
|
@@ -2606,128 +3479,120 @@ var Server = class {
|
|
|
2606
3479
|
}
|
|
2607
3480
|
});
|
|
2608
3481
|
}
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
*/
|
|
2612
|
-
getInstance(config, req) {
|
|
2613
|
-
const _config = { ...this.#config, ...config };
|
|
2614
|
-
const updatedConfig = new Config(_config);
|
|
2615
|
-
this.#config = new Config(updatedConfig);
|
|
2616
|
-
this.#config.tenantId = config.tenantId;
|
|
2617
|
-
this.#config.userId = config.userId;
|
|
2618
|
-
if (req) {
|
|
2619
|
-
this.setContext(req);
|
|
2620
|
-
}
|
|
2621
|
-
this.#reset();
|
|
2622
|
-
return this;
|
|
3482
|
+
get logger() {
|
|
3483
|
+
return this.#config.logger;
|
|
2623
3484
|
}
|
|
2624
|
-
|
|
2625
|
-
return
|
|
3485
|
+
get extensions() {
|
|
3486
|
+
return {
|
|
3487
|
+
remove: async (id) => {
|
|
3488
|
+
if (!this.#config.extensions) return;
|
|
3489
|
+
const resolved = this.#config.extensions.map((ext) => ext(this));
|
|
3490
|
+
const index = resolved.findIndex((ext) => ext.id === id);
|
|
3491
|
+
if (index !== -1) {
|
|
3492
|
+
this.#config.extensions.splice(index, 1);
|
|
3493
|
+
}
|
|
3494
|
+
return resolved;
|
|
3495
|
+
},
|
|
3496
|
+
add: (extension) => {
|
|
3497
|
+
if (!this.#config.extensions) {
|
|
3498
|
+
this.#config.extensions = [];
|
|
3499
|
+
}
|
|
3500
|
+
this.#config.extensions.push(extension);
|
|
3501
|
+
}
|
|
3502
|
+
};
|
|
2626
3503
|
}
|
|
2627
3504
|
get handlers() {
|
|
2628
3505
|
return this.#handlers;
|
|
2629
3506
|
}
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
return;
|
|
2643
|
-
} else if (req instanceof Request) {
|
|
2644
|
-
this.#handleHeaders(new Headers(req.headers));
|
|
2645
|
-
this.#reset();
|
|
2646
|
-
return;
|
|
2647
|
-
}
|
|
2648
|
-
} catch {
|
|
2649
|
-
}
|
|
2650
|
-
let ok = false;
|
|
2651
|
-
if (req && typeof req === "object" && "tenantId" in req) {
|
|
2652
|
-
ok = true;
|
|
2653
|
-
this.#config.tenantId = req.tenantId;
|
|
2654
|
-
}
|
|
2655
|
-
if (req && typeof req === "object" && "userId" in req) {
|
|
2656
|
-
ok = true;
|
|
2657
|
-
this.#config.userId = req.userId;
|
|
2658
|
-
}
|
|
2659
|
-
if (ok) {
|
|
2660
|
-
return;
|
|
3507
|
+
get paths() {
|
|
3508
|
+
return this.#config.paths;
|
|
3509
|
+
}
|
|
3510
|
+
set paths(paths) {
|
|
3511
|
+
this.#config.paths = paths;
|
|
3512
|
+
}
|
|
3513
|
+
async withContext(context, fn) {
|
|
3514
|
+
const { ...initialContext } = context ?? defaultContext;
|
|
3515
|
+
this.#config.context = { ...initialContext };
|
|
3516
|
+
const preserve = (context && "preserveHeaders" in context && context.preserveHeaders) ?? true;
|
|
3517
|
+
if (preserve) {
|
|
3518
|
+
this.#config.context = { ...this.getContext(), ...context };
|
|
2661
3519
|
}
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
this.#handleHeaders(headers);
|
|
2666
|
-
this.#reset();
|
|
2667
|
-
return;
|
|
3520
|
+
return withNileContext(this.#config, async () => {
|
|
3521
|
+
if (fn) {
|
|
3522
|
+
return fn(this);
|
|
2668
3523
|
}
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
3524
|
+
return this;
|
|
3525
|
+
});
|
|
3526
|
+
}
|
|
3527
|
+
async noContext(fn) {
|
|
3528
|
+
this.#config.context.tenantId = void 0;
|
|
3529
|
+
this.#config.context.userId = void 0;
|
|
3530
|
+
return withNileContext(this.#config, async () => {
|
|
3531
|
+
ctx.set({ userId: void 0, tenantId: void 0 });
|
|
3532
|
+
if (fn) {
|
|
3533
|
+
return fn(this);
|
|
3534
|
+
}
|
|
3535
|
+
return this;
|
|
3536
|
+
});
|
|
2676
3537
|
}
|
|
3538
|
+
/**
|
|
3539
|
+
*
|
|
3540
|
+
* @returns the last used (basically global) context object, useful for debugging or making your own context
|
|
3541
|
+
*/
|
|
2677
3542
|
getContext() {
|
|
2678
|
-
return
|
|
2679
|
-
headers: this.#headers,
|
|
2680
|
-
userId: this.#config.userId,
|
|
2681
|
-
tenantId: this.#config.tenantId
|
|
2682
|
-
};
|
|
3543
|
+
return ctx.getLastUsed();
|
|
2683
3544
|
}
|
|
2684
3545
|
/**
|
|
2685
3546
|
* Merge headers together
|
|
3547
|
+
* Saves them in a singleton for use in a request later. It's basically the "default" value
|
|
2686
3548
|
* Internally, passed a NileConfig, externally, should be using Headers
|
|
2687
3549
|
*/
|
|
2688
3550
|
#handleHeaders(config) {
|
|
2689
3551
|
const updates = [];
|
|
2690
3552
|
let headers;
|
|
2691
|
-
this.#headers = new Headers();
|
|
3553
|
+
this.#config.context.headers = new Headers();
|
|
2692
3554
|
if (config instanceof Headers) {
|
|
2693
3555
|
headers = config;
|
|
2694
3556
|
} else if (config?.headers) {
|
|
2695
3557
|
headers = config?.headers;
|
|
2696
3558
|
if (config && config.origin) {
|
|
2697
|
-
this.#headers.set(
|
|
3559
|
+
this.#config.context.headers.set(HEADER_ORIGIN, config.origin);
|
|
2698
3560
|
}
|
|
2699
3561
|
if (config && config.secureCookies != null) {
|
|
2700
|
-
this.#headers.set(
|
|
3562
|
+
this.#config.context.headers.set(
|
|
3563
|
+
HEADER_SECURE_COOKIES,
|
|
3564
|
+
String(config.secureCookies)
|
|
3565
|
+
);
|
|
2701
3566
|
}
|
|
2702
3567
|
}
|
|
2703
3568
|
if (headers instanceof Headers) {
|
|
2704
|
-
headers.forEach((value,
|
|
2705
|
-
updates.push([
|
|
3569
|
+
headers.forEach((value, key17) => {
|
|
3570
|
+
updates.push([key17.toLowerCase(), value]);
|
|
2706
3571
|
});
|
|
2707
3572
|
} else {
|
|
2708
|
-
for (const [
|
|
2709
|
-
updates.push([
|
|
3573
|
+
for (const [key17, value] of Object.entries(headers ?? {})) {
|
|
3574
|
+
updates.push([key17.toLowerCase(), value]);
|
|
2710
3575
|
}
|
|
2711
3576
|
}
|
|
2712
3577
|
const merged = {};
|
|
2713
|
-
this.#headers?.forEach((value,
|
|
2714
|
-
if (
|
|
2715
|
-
merged[
|
|
3578
|
+
this.#config.context.headers?.forEach((value, key17) => {
|
|
3579
|
+
if (key17.toLowerCase() !== "cookie") {
|
|
3580
|
+
merged[key17.toLowerCase()] = value;
|
|
2716
3581
|
}
|
|
2717
3582
|
});
|
|
2718
|
-
for (const [
|
|
2719
|
-
merged[
|
|
3583
|
+
for (const [key17, value] of updates) {
|
|
3584
|
+
merged[key17] = value;
|
|
2720
3585
|
}
|
|
2721
|
-
for (const [
|
|
2722
|
-
this.#headers.set(
|
|
3586
|
+
for (const [key17, value] of Object.entries(merged)) {
|
|
3587
|
+
this.#config.context.headers.set(key17, value);
|
|
2723
3588
|
}
|
|
2724
|
-
this.#config.
|
|
3589
|
+
this.#config.logger("[handleHeaders]").debug(JSON.stringify(merged));
|
|
2725
3590
|
}
|
|
2726
3591
|
/**
|
|
2727
3592
|
* Allow some internal mutations to reset our config + headers
|
|
2728
3593
|
*/
|
|
2729
3594
|
#reset = () => {
|
|
2730
|
-
this.#config.
|
|
3595
|
+
this.#config.extensionCtx = buildExtensionConfig(this);
|
|
2731
3596
|
this.users = new Users(this.#config);
|
|
2732
3597
|
this.tenants = new Tenants(this.#config);
|
|
2733
3598
|
this.auth = new Auth(this.#config);
|
|
@@ -2741,6 +3606,6 @@ function create(config) {
|
|
|
2741
3606
|
return server;
|
|
2742
3607
|
}
|
|
2743
3608
|
|
|
2744
|
-
export { APIErrorErrorCodeEnum, LoginUserResponseTokenTypeEnum, create as Nile, Server, parseCSRF, parseCallback, parseToken };
|
|
3609
|
+
export { APIErrorErrorCodeEnum, ExtensionState, HEADER_ORIGIN, HEADER_SECURE_COOKIES, LoginUserResponseTokenTypeEnum, create as Nile, Server, TENANT_COOKIE, USER_COOKIE, parseCSRF, parseCallback, parseResetToken, parseTenantId, parseToken };
|
|
2745
3610
|
//# sourceMappingURL=index.mjs.map
|
|
2746
3611
|
//# sourceMappingURL=index.mjs.map
|