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