@niledatabase/server 4.2.0 → 5.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/express.d.mts +2 -2
- package/dist/express.d.ts +2 -2
- package/dist/express.js +1225 -13
- package/dist/express.js.map +1 -1
- package/dist/express.mjs +1225 -13
- package/dist/express.mjs.map +1 -1
- package/dist/index.d.mts +335 -228
- package/dist/index.d.ts +335 -228
- package/dist/index.js +1959 -2278
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1956 -2279
- package/dist/index.mjs.map +1 -1
- package/dist/nitro.js +1 -1
- package/dist/nitro.js.map +1 -1
- package/dist/nitro.mjs +1 -1
- package/dist/nitro.mjs.map +1 -1
- package/package.json +2 -5
package/dist/index.js
CHANGED
|
@@ -2,12 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
require('dotenv/config');
|
|
4
4
|
var pg = require('pg');
|
|
5
|
-
var jose = require('jose');
|
|
6
5
|
|
|
7
6
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
7
|
|
|
9
8
|
var pg__default = /*#__PURE__*/_interopDefault(pg);
|
|
10
9
|
|
|
10
|
+
// src/types.ts
|
|
11
|
+
var APIErrorErrorCodeEnum = {
|
|
12
|
+
InternalError: "internal_error",
|
|
13
|
+
BadRequest: "bad_request",
|
|
14
|
+
EntityNotFound: "entity_not_found",
|
|
15
|
+
DuplicateEntity: "duplicate_entity",
|
|
16
|
+
InvalidCredentials: "invalid_credentials",
|
|
17
|
+
UnknownOidcProvider: "unknown_oidc_provider",
|
|
18
|
+
ProviderAlreadyExists: "provider_already_exists",
|
|
19
|
+
ProviderConfigError: "provider_config_error",
|
|
20
|
+
ProviderMismatch: "provider_mismatch",
|
|
21
|
+
ProviderUpdateError: "provider_update_error",
|
|
22
|
+
SessionStateMissing: "session_state_missing",
|
|
23
|
+
SessionStateMismatch: "session_state_mismatch",
|
|
24
|
+
OidcCodeMissing: "oidc_code_missing"
|
|
25
|
+
};
|
|
26
|
+
|
|
11
27
|
// src/users/types.ts
|
|
12
28
|
var LoginUserResponseTokenTypeEnum = {
|
|
13
29
|
AccessToken: "ACCESS_TOKEN",
|
|
@@ -15,10 +31,86 @@ var LoginUserResponseTokenTypeEnum = {
|
|
|
15
31
|
IdToken: "ID_TOKEN"
|
|
16
32
|
};
|
|
17
33
|
|
|
18
|
-
// src/api/utils/routes/
|
|
19
|
-
|
|
34
|
+
// src/api/utils/routes/index.ts
|
|
35
|
+
var NILEDB_API_URL = process.env.NILEDB_API_URL;
|
|
36
|
+
var appRoutes = (prefix = "/api") => ({
|
|
37
|
+
SIGNIN: `${prefix}${"/auth/signin" /* SIGNIN */}`,
|
|
38
|
+
PROVIDERS: `${prefix}${"/auth/providers" /* PROVIDERS */}`,
|
|
39
|
+
SESSION: `${prefix}${"/auth/session" /* SESSION */}`,
|
|
40
|
+
CSRF: `${prefix}${"/auth/csrf" /* CSRF */}`,
|
|
41
|
+
CALLBACK: `${prefix}${"/auth/callback" /* CALLBACK */}`,
|
|
42
|
+
SIGNOUT: `${prefix}${"/auth/signout" /* SIGNOUT */}`,
|
|
43
|
+
ERROR: `${prefix}/auth/error`,
|
|
44
|
+
VERIFY_REQUEST: `${prefix}/auth/verify-request`,
|
|
45
|
+
PASSWORD_RESET: `${prefix}/auth/reset-password`,
|
|
46
|
+
ME: `${prefix}${"/me" /* ME */}`,
|
|
47
|
+
USERS: `${prefix}${"/users" /* USERS */}`,
|
|
48
|
+
USER_TENANTS: `${prefix}${"/users/{userId}/tenants" /* USER_TENANTS */}`,
|
|
49
|
+
TENANTS: `${prefix}${"/tenants" /* TENANTS */}`,
|
|
50
|
+
TENANT: `${prefix}${"/tenants/{tenantId}" /* TENANT */}`,
|
|
51
|
+
TENANT_USER: `${prefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */}`,
|
|
52
|
+
TENANT_USERS: `${prefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */}`,
|
|
53
|
+
SIGNUP: `${prefix}${"/signup" /* SIGNUP */}`,
|
|
54
|
+
LOG: `${prefix}/_log`
|
|
55
|
+
});
|
|
56
|
+
var apiRoutes = (config) => ({
|
|
57
|
+
ME: makeRestUrl(config, "/me"),
|
|
58
|
+
USERS: (qp) => makeRestUrl(config, "/users", qp),
|
|
59
|
+
USER: (userId) => makeRestUrl(config, `/users/${userId}`),
|
|
60
|
+
TENANTS: makeRestUrl(config, "/tenants"),
|
|
61
|
+
TENANT: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}`),
|
|
62
|
+
SIGNUP: makeRestUrl(config, "/signup"),
|
|
63
|
+
TENANT_USERS: (tenantId) => makeRestUrl(config, `/tenants/${tenantId}/users`),
|
|
64
|
+
TENANT_USER: makeRestUrl(
|
|
65
|
+
config,
|
|
66
|
+
`/tenants/${config.tenantId}/users/${config.userId}`
|
|
67
|
+
),
|
|
68
|
+
USER_TENANTS: (userId) => makeRestUrl(config, `/users/${userId}/tenants`)
|
|
69
|
+
});
|
|
70
|
+
var proxyRoutes = (config) => ({
|
|
71
|
+
SIGNIN: makeRestUrl(config, "/auth/signin" /* SIGNIN */),
|
|
72
|
+
PROVIDERS: makeRestUrl(config, "/auth/providers" /* PROVIDERS */),
|
|
73
|
+
SESSION: makeRestUrl(config, "/auth/session" /* SESSION */),
|
|
74
|
+
CSRF: makeRestUrl(config, "/auth/csrf" /* CSRF */),
|
|
75
|
+
CALLBACK: makeRestUrl(config, "/auth/callback" /* CALLBACK */),
|
|
76
|
+
SIGNOUT: makeRestUrl(config, "/auth/signout" /* SIGNOUT */),
|
|
77
|
+
ERROR: makeRestUrl(config, "/auth/error"),
|
|
78
|
+
VERIFY_REQUEST: makeRestUrl(config, "/auth/verify-request"),
|
|
79
|
+
PASSWORD_RESET: makeRestUrl(config, "/auth/reset-password")
|
|
80
|
+
});
|
|
81
|
+
function filterNullUndefined(obj) {
|
|
82
|
+
if (!obj) {
|
|
83
|
+
return void 0;
|
|
84
|
+
}
|
|
85
|
+
return Object.fromEntries(
|
|
86
|
+
Object.entries(obj).filter(
|
|
87
|
+
([, value]) => value !== null && value !== void 0
|
|
88
|
+
)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
function makeRestUrl(config, path, qp) {
|
|
92
|
+
const url = config.apiUrl || NILEDB_API_URL;
|
|
93
|
+
if (!url) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
"An API url is required. Set it via NILEDB_API_URL. Was auto configuration run?"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const params = new URLSearchParams(
|
|
99
|
+
filterNullUndefined(qp)
|
|
100
|
+
);
|
|
101
|
+
const strParams = params.toString();
|
|
102
|
+
return `${[url, path.substring(1, path.length)].join("/")}${strParams ? `?${strParams}` : ""}`;
|
|
103
|
+
}
|
|
104
|
+
function urlMatches(requestUrl, route16) {
|
|
20
105
|
const url = new URL(requestUrl);
|
|
21
|
-
return url.pathname.startsWith(
|
|
106
|
+
return url.pathname.startsWith(route16);
|
|
107
|
+
}
|
|
108
|
+
function isUUID(value) {
|
|
109
|
+
if (!value) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
const regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5|7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
113
|
+
return regex.test(value);
|
|
22
114
|
}
|
|
23
115
|
|
|
24
116
|
// src/utils/Logger.ts
|
|
@@ -82,7 +174,6 @@ function matchesLog(configRoutes, request2) {
|
|
|
82
174
|
|
|
83
175
|
// src/utils/constants.ts
|
|
84
176
|
var X_NILE_TENANT = "nile.tenant_id";
|
|
85
|
-
var X_NILE_USER_ID = "nile.user_id";
|
|
86
177
|
var X_NILE_ORIGIN = "nile.origin";
|
|
87
178
|
var X_NILE_SECURECOOKIES = "nile.secure_cookies";
|
|
88
179
|
|
|
@@ -101,19 +192,14 @@ async function request(url, _init, config) {
|
|
|
101
192
|
String(request2.headers.get(X_NILE_TENANT))
|
|
102
193
|
);
|
|
103
194
|
}
|
|
104
|
-
if (config.
|
|
105
|
-
updatedHeaders.set(X_NILE_SECURECOOKIES, String(config.
|
|
195
|
+
if (config.secureCookies != null) {
|
|
196
|
+
updatedHeaders.set(X_NILE_SECURECOOKIES, String(config.secureCookies));
|
|
106
197
|
}
|
|
107
198
|
updatedHeaders.set("host", requestUrl.host);
|
|
108
|
-
if (config.
|
|
109
|
-
const cbUrl = new URL(config.
|
|
110
|
-
debug(
|
|
111
|
-
`Obtained origin from config.api.callbackUrl ${config.api.callbackUrl}`
|
|
112
|
-
);
|
|
199
|
+
if (config.callbackUrl) {
|
|
200
|
+
const cbUrl = new URL(config.callbackUrl);
|
|
201
|
+
debug(`Obtained origin from config.callbackUrl ${config.callbackUrl}`);
|
|
113
202
|
updatedHeaders.set(X_NILE_ORIGIN, cbUrl.origin);
|
|
114
|
-
} else if (config.api.origin) {
|
|
115
|
-
debug(`Obtained origin from config.api.origin ${config.api.origin}`);
|
|
116
|
-
updatedHeaders.set(X_NILE_ORIGIN, config.api.origin);
|
|
117
203
|
} else {
|
|
118
204
|
updatedHeaders.set(X_NILE_ORIGIN, requestUrl.origin);
|
|
119
205
|
debug(`Obtained origin from request ${requestUrl.origin}`);
|
|
@@ -134,19 +220,23 @@ async function request(url, _init, config) {
|
|
|
134
220
|
}
|
|
135
221
|
params.headers = updatedHeaders;
|
|
136
222
|
const fullUrl = `${url}${requestUrl.search}`;
|
|
223
|
+
if (config.debug) {
|
|
224
|
+
params.headers.set("request-id", crypto.randomUUID());
|
|
225
|
+
params.cache = "no-store";
|
|
226
|
+
}
|
|
137
227
|
try {
|
|
138
|
-
const res = await fetch(fullUrl, {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
);
|
|
228
|
+
const res = await fetch(fullUrl, {
|
|
229
|
+
...params
|
|
230
|
+
}).catch((e) => {
|
|
231
|
+
error("An error has occurred in the fetch", {
|
|
232
|
+
message: e.message,
|
|
233
|
+
stack: e.stack
|
|
234
|
+
});
|
|
235
|
+
return new Response(
|
|
236
|
+
"An unexpected (most likely configuration) problem has occurred",
|
|
237
|
+
{ status: 500 }
|
|
238
|
+
);
|
|
239
|
+
});
|
|
150
240
|
const loggingRes = typeof res?.clone === "function" ? res?.clone() : null;
|
|
151
241
|
info(`[${params.method ?? "GET"}] ${fullUrl}`, {
|
|
152
242
|
status: res?.status,
|
|
@@ -172,8 +262,8 @@ async function request(url, _init, config) {
|
|
|
172
262
|
async function auth(req, config) {
|
|
173
263
|
const { info, error } = Logger(config, "[nileauth]");
|
|
174
264
|
info("checking auth");
|
|
175
|
-
const sessionUrl = `${config.
|
|
176
|
-
info(`using session${sessionUrl}`);
|
|
265
|
+
const sessionUrl = `${config.apiUrl}/auth/session`;
|
|
266
|
+
info(`using session ${sessionUrl}`);
|
|
177
267
|
req.headers.delete("content-length");
|
|
178
268
|
const res = await request(sessionUrl, { request: req }, config);
|
|
179
269
|
if (!res) {
|
|
@@ -192,1105 +282,852 @@ async function auth(req, config) {
|
|
|
192
282
|
return void 0;
|
|
193
283
|
}
|
|
194
284
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
285
|
+
|
|
286
|
+
// src/api/routes/me/index.ts
|
|
287
|
+
var key = "ME";
|
|
288
|
+
async function route(request2, config) {
|
|
289
|
+
const url = apiRoutes(config)[key];
|
|
290
|
+
if (request2.method === "GET") {
|
|
291
|
+
return await GET(url, { request: request2 }, config);
|
|
199
292
|
}
|
|
200
|
-
|
|
201
|
-
};
|
|
202
|
-
var getSecureCookies = (cfg) => {
|
|
203
|
-
const { config } = cfg;
|
|
204
|
-
if (stringCheck(process.env.NILEDB_SECURECOOKIES)) {
|
|
205
|
-
return Boolean(process.env.NILEDB_SECURECOOKIES);
|
|
293
|
+
if (request2.method === "PUT") {
|
|
294
|
+
return await PUT(url, { request: request2 }, config);
|
|
206
295
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const { info } = Logger(config, "[databaseId]");
|
|
212
|
-
if (stringCheck(config?.databaseId)) {
|
|
213
|
-
logger && info(`${logger}[config] ${config?.databaseId}`);
|
|
214
|
-
return String(config?.databaseId);
|
|
215
|
-
}
|
|
216
|
-
const dbFromEnv = stringCheck(process.env.NILEDB_ID);
|
|
217
|
-
if (dbFromEnv) {
|
|
218
|
-
logger && info(`${logger}[NILEDB_ID] ${dbFromEnv}`);
|
|
219
|
-
return dbFromEnv;
|
|
220
|
-
}
|
|
221
|
-
const dbId = stringCheck(process.env.NILEDB_API_URL);
|
|
222
|
-
if (dbId) {
|
|
223
|
-
try {
|
|
224
|
-
const pgUrl = new URL(dbId);
|
|
225
|
-
return pgUrl.pathname.split("/")[3];
|
|
226
|
-
} catch (e) {
|
|
296
|
+
if (request2.method === "DELETE") {
|
|
297
|
+
const session = await auth(request2, config);
|
|
298
|
+
if (!session) {
|
|
299
|
+
return new Response(null, { status: 401 });
|
|
227
300
|
}
|
|
301
|
+
return await DELETE(url, { request: request2 }, config);
|
|
228
302
|
}
|
|
229
|
-
return
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
244
|
-
if (pg2) {
|
|
245
|
-
try {
|
|
246
|
-
const url = new URL(pg2);
|
|
247
|
-
if (url.username) {
|
|
248
|
-
return url.username;
|
|
249
|
-
}
|
|
250
|
-
} catch (e) {
|
|
251
|
-
}
|
|
303
|
+
return new Response("method not allowed", { status: 405 });
|
|
304
|
+
}
|
|
305
|
+
function matches(configRoutes, request2) {
|
|
306
|
+
return urlMatches(request2.url, configRoutes[key]);
|
|
307
|
+
}
|
|
308
|
+
async function fetchMe(config, method, body) {
|
|
309
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/me" /* ME */}`;
|
|
310
|
+
const init = {
|
|
311
|
+
headers: config.headers,
|
|
312
|
+
method: method ?? "GET"
|
|
313
|
+
};
|
|
314
|
+
if (method === "PUT") {
|
|
315
|
+
init.body = body;
|
|
252
316
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const { config, logger } = cfg;
|
|
257
|
-
const log = logProtector(logger);
|
|
258
|
-
const { info } = Logger(config, "[password]");
|
|
259
|
-
if (stringCheck(config?.password)) {
|
|
260
|
-
log && info(`${logger}[config] ***`);
|
|
261
|
-
return String(config?.password);
|
|
317
|
+
const req = new Request(clientUrl, init);
|
|
318
|
+
if (method === "DELETE") {
|
|
319
|
+
return await config.handlers.DELETE(req);
|
|
262
320
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
logger && info(`${logger}[NILEDB_PASSWORD] ***`);
|
|
266
|
-
return pass;
|
|
321
|
+
if (method === "PUT") {
|
|
322
|
+
return await config.handlers.PUT(req);
|
|
267
323
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
324
|
+
return await config.handlers.GET(req);
|
|
325
|
+
}
|
|
326
|
+
async function DELETE(url, init, config) {
|
|
327
|
+
init.method = "DELETE";
|
|
328
|
+
return await request(url, init, config);
|
|
329
|
+
}
|
|
330
|
+
async function PUT(url, init, config) {
|
|
331
|
+
init.method = "PUT";
|
|
332
|
+
return await request(url, init, config);
|
|
333
|
+
}
|
|
334
|
+
async function GET(url, init, config) {
|
|
335
|
+
const res = await request(url, init, config);
|
|
336
|
+
return res;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/utils/Event/index.ts
|
|
340
|
+
var Eventer = class {
|
|
341
|
+
events = {};
|
|
342
|
+
publish(eventName, value) {
|
|
343
|
+
const callbacks = this.events[eventName];
|
|
344
|
+
if (callbacks) {
|
|
345
|
+
for (const callback of callbacks) {
|
|
346
|
+
callback(value);
|
|
274
347
|
}
|
|
275
|
-
} catch (e) {
|
|
276
348
|
}
|
|
277
349
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
var getToken = (cfg) => {
|
|
284
|
-
const { config, logger } = cfg;
|
|
285
|
-
const { info } = Logger(config, "[token]");
|
|
286
|
-
if (stringCheck(config?.api?.token)) {
|
|
287
|
-
logger && info(`${logger}[config] ${config?.api?.token}`);
|
|
288
|
-
return String(config?.api?.token);
|
|
289
|
-
}
|
|
290
|
-
const token = stringCheck(process.env.NILEDB_TOKEN);
|
|
291
|
-
if (token) {
|
|
292
|
-
logger && info(`${logger}[NILEDB_TOKEN] ${token}`);
|
|
293
|
-
return token;
|
|
294
|
-
}
|
|
295
|
-
return void 0;
|
|
296
|
-
};
|
|
297
|
-
var getDatabaseName = (cfg) => {
|
|
298
|
-
const { config, logger } = cfg;
|
|
299
|
-
const { info } = Logger(config, "[databaseName]");
|
|
300
|
-
if (stringCheck(config?.databaseName)) {
|
|
301
|
-
logger && info(`${logger}[config] ${config?.databaseName}`);
|
|
302
|
-
return String(config?.databaseName);
|
|
303
|
-
}
|
|
304
|
-
const name = stringCheck(process.env.NILEDB_NAME);
|
|
305
|
-
if (name) {
|
|
306
|
-
logger && info(`${logger}[NILEDB_NAME] ${name}`);
|
|
307
|
-
return name;
|
|
350
|
+
subscribe(eventName, callback) {
|
|
351
|
+
if (!this.events[eventName]) {
|
|
352
|
+
this.events[eventName] = [];
|
|
353
|
+
}
|
|
354
|
+
this.events[eventName].push(callback);
|
|
308
355
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
356
|
+
unsubscribe(eventName, callback) {
|
|
357
|
+
const callbacks = this.events[eventName];
|
|
358
|
+
if (!callbacks) return;
|
|
359
|
+
const index = callbacks.indexOf(callback);
|
|
360
|
+
if (index !== -1) {
|
|
361
|
+
callbacks.splice(index, 1);
|
|
362
|
+
}
|
|
363
|
+
if (callbacks.length === 0) {
|
|
364
|
+
delete this.events[eventName];
|
|
314
365
|
}
|
|
315
366
|
}
|
|
316
|
-
return null;
|
|
317
367
|
};
|
|
318
|
-
var
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return String(config?.tenantId);
|
|
324
|
-
}
|
|
325
|
-
if (stringCheck(process.env.NILEDB_TENANT)) {
|
|
326
|
-
logger && info(`${logger}[NILEDB_TENANT] ${process.env.NILEDB_TENANT}`);
|
|
327
|
-
return String(process.env.NILEDB_TENANT);
|
|
328
|
-
}
|
|
329
|
-
return null;
|
|
368
|
+
var eventer = new Eventer();
|
|
369
|
+
var watchTenantId = (cb) => eventer.subscribe("tenantId" /* Tenant */, cb);
|
|
370
|
+
var watchUserId = (cb) => eventer.subscribe("userId" /* User */, cb);
|
|
371
|
+
var evictPool = (val) => {
|
|
372
|
+
eventer.publish("EvictPool" /* EvictPool */, val);
|
|
330
373
|
};
|
|
331
|
-
var
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (stringCheck(config?.api?.cookieKey)) {
|
|
335
|
-
logger && info(`${logger}[config] ${config?.api?.cookieKey}`);
|
|
336
|
-
return String(config?.api?.cookieKey);
|
|
337
|
-
}
|
|
338
|
-
if (stringCheck(process.env.NILEDB_COOKIE_KEY)) {
|
|
339
|
-
logger && info(`${logger}[NILEDB_COOKIE_KEY] ${process.env.NILEDB_COOKIE_KEY}`);
|
|
340
|
-
return String(process.env.NILEDB_COOKIE_KEY);
|
|
341
|
-
}
|
|
342
|
-
return "token";
|
|
374
|
+
var watchEvictPool = (cb) => eventer.subscribe("EvictPool" /* EvictPool */, cb);
|
|
375
|
+
var updateHeaders = (val) => {
|
|
376
|
+
eventer.publish("headers" /* Headers */, val);
|
|
343
377
|
};
|
|
344
|
-
var
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
const apiUrl = new URL(envUrl);
|
|
357
|
-
return apiUrl.href;
|
|
358
|
-
} catch (e) {
|
|
359
|
-
if (e instanceof Error) {
|
|
360
|
-
error(e.stack);
|
|
361
|
-
}
|
|
378
|
+
var watchHeaders = (cb) => eventer.subscribe("headers" /* Headers */, cb);
|
|
379
|
+
|
|
380
|
+
// src/utils/fetch.ts
|
|
381
|
+
function getTokenFromCookie(headers, cookieKey) {
|
|
382
|
+
const cookie = headers.get("cookie")?.split("; ");
|
|
383
|
+
const _cookies = {};
|
|
384
|
+
if (cookie) {
|
|
385
|
+
for (const parts of cookie) {
|
|
386
|
+
const cookieParts = parts.split("=");
|
|
387
|
+
const _cookie = cookieParts.slice(1).join("=");
|
|
388
|
+
const name = cookieParts[0];
|
|
389
|
+
_cookies[name] = _cookie;
|
|
362
390
|
}
|
|
363
391
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
if (stringCheck(config?.configureUrl)) {
|
|
371
|
-
logger && info(`${logger}[config] ${config?.configureUrl}`);
|
|
372
|
-
return String(config?.configureUrl);
|
|
373
|
-
}
|
|
374
|
-
const autoConfigUrl = stringCheck(process.env.NILEDB_CONFIGURE);
|
|
375
|
-
if (autoConfigUrl) {
|
|
376
|
-
logger && info(`${logger}[NILEDB_CONFIGURE] ${process.env.NILEDB_CONFIGURE}`);
|
|
377
|
-
if (!autoConfigUrl.startsWith("http")) {
|
|
378
|
-
return `https://${process.env.NILEDB_CONFIGURE}`;
|
|
392
|
+
if (cookie) {
|
|
393
|
+
for (const parts of cookie) {
|
|
394
|
+
const cookieParts = parts.split("=");
|
|
395
|
+
const _cookie = cookieParts.slice(1).join("=");
|
|
396
|
+
const name = cookieParts[0];
|
|
397
|
+
_cookies[name] = _cookie;
|
|
379
398
|
}
|
|
380
|
-
return process.env.NILEDB_CONFIGURE;
|
|
381
|
-
}
|
|
382
|
-
logger && info(`${logger}[default] https://global.thenile.dev`);
|
|
383
|
-
return "https://global.thenile.dev";
|
|
384
|
-
};
|
|
385
|
-
function getDbHost(cfg) {
|
|
386
|
-
const { config, logger } = cfg;
|
|
387
|
-
const { info } = Logger(config, "[db.host]");
|
|
388
|
-
if (stringCheck(config?.db && config.db.host)) {
|
|
389
|
-
logger && info(`${logger}[config] ${config?.db?.host}`);
|
|
390
|
-
return String(config?.db?.host);
|
|
391
|
-
}
|
|
392
|
-
if (stringCheck(process.env.NILEDB_HOST)) {
|
|
393
|
-
logger && info(`${logger}[NILEDB_HOST] ${process.env.NILEDB_HOST}`);
|
|
394
|
-
return process.env.NILEDB_HOST;
|
|
395
399
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
try {
|
|
399
|
-
const pgUrl = new URL(pg2);
|
|
400
|
-
logger && info(`${logger}[NILEDB_POSTGRES_URL] ${pgUrl.hostname}`);
|
|
401
|
-
return pgUrl.hostname;
|
|
402
|
-
} catch (e) {
|
|
403
|
-
}
|
|
400
|
+
{
|
|
401
|
+
return _cookies[cookieKey];
|
|
404
402
|
}
|
|
405
|
-
logger && info(`${logger}[default] db.thenile.dev`);
|
|
406
|
-
return "db.thenile.dev";
|
|
407
403
|
}
|
|
408
|
-
function
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
404
|
+
function getTenantFromHttp(headers, config) {
|
|
405
|
+
const cookieTenant = getTokenFromCookie(headers, X_NILE_TENANT);
|
|
406
|
+
return cookieTenant ?? headers?.get(X_NILE_TENANT) ?? config?.tenantId;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/api/routes/users/POST.ts
|
|
410
|
+
async function POST(config, init) {
|
|
411
|
+
init.body = init.request.body;
|
|
412
|
+
init.method = "POST";
|
|
413
|
+
const yurl = new URL(init.request.url);
|
|
414
|
+
const tenantId = yurl.searchParams.get("tenantId");
|
|
415
|
+
const newTenantName = yurl.searchParams.get("newTenantName");
|
|
416
|
+
const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
|
|
417
|
+
const url = apiRoutes(config).USERS({ tenantId: tenant, newTenantName });
|
|
418
|
+
return await request(url, init, config);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// src/api/routes/users/GET.ts
|
|
422
|
+
async function GET2(config, init, log) {
|
|
423
|
+
const yurl = new URL(init.request.url);
|
|
424
|
+
const tenantId = yurl.searchParams.get("tenantId");
|
|
425
|
+
const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
|
|
426
|
+
if (!tenant) {
|
|
427
|
+
log("[GET] No tenant id provided.");
|
|
428
|
+
return new Response(null, { status: 404 });
|
|
418
429
|
}
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
430
|
+
const url = apiRoutes(config).TENANT_USERS(tenant);
|
|
431
|
+
init.method = "GET";
|
|
432
|
+
return await request(url, init, config);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/api/routes/users/[userId]/PUT.ts
|
|
436
|
+
async function PUT2(config, session, init) {
|
|
437
|
+
if (!session) {
|
|
438
|
+
return new Response(null, { status: 401 });
|
|
428
439
|
}
|
|
429
|
-
|
|
430
|
-
|
|
440
|
+
init.body = init.request.body;
|
|
441
|
+
init.method = "PUT";
|
|
442
|
+
const [userId] = new URL(init.request.url).pathname.split("/").reverse();
|
|
443
|
+
const url = apiRoutes(config).USER(userId);
|
|
444
|
+
return await request(url, init, config);
|
|
431
445
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
446
|
+
|
|
447
|
+
// src/api/routes/users/index.ts
|
|
448
|
+
var key2 = "USERS";
|
|
449
|
+
async function route2(request2, config) {
|
|
450
|
+
const { info } = Logger(
|
|
451
|
+
{ ...config, debug: config.debug },
|
|
452
|
+
`[ROUTES][${key2}]`
|
|
453
|
+
);
|
|
454
|
+
const session = await auth(request2, config);
|
|
455
|
+
switch (request2.method) {
|
|
456
|
+
case "GET":
|
|
457
|
+
return await GET2(config, { request: request2 }, info);
|
|
458
|
+
case "POST":
|
|
459
|
+
return await POST(config, { request: request2 });
|
|
460
|
+
case "PUT":
|
|
461
|
+
return await PUT2(config, session, { request: request2 });
|
|
462
|
+
default:
|
|
463
|
+
return new Response("method not allowed", { status: 405 });
|
|
438
464
|
}
|
|
439
|
-
|
|
440
|
-
|
|
465
|
+
}
|
|
466
|
+
function matches2(configRoutes, request2) {
|
|
467
|
+
return urlMatches(request2.url, configRoutes[key2]);
|
|
468
|
+
}
|
|
441
469
|
|
|
442
|
-
// src/
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
this.origin = config?.api?.origin;
|
|
470
|
+
// src/api/routes/tenants/[tenantId]/users/GET.ts
|
|
471
|
+
async function GET3(config, init) {
|
|
472
|
+
const yurl = new URL(init.request.url);
|
|
473
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
474
|
+
const url = `${apiRoutes(config).TENANT_USERS(tenantId)}`;
|
|
475
|
+
return await request(url, init, config);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// src/api/routes/tenants/[tenantId]/users/POST.ts
|
|
479
|
+
async function POST2(config, session, init) {
|
|
480
|
+
const yurl = new URL(init.request.url);
|
|
481
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
482
|
+
init.body = JSON.stringify({ email: session.email });
|
|
483
|
+
init.method = "POST";
|
|
484
|
+
const url = apiRoutes(config).TENANT_USERS(tenantId);
|
|
485
|
+
return await request(url, init, config);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// src/api/routes/tenants/[tenantId]/users/index.ts
|
|
489
|
+
var key3 = "TENANT_USERS";
|
|
490
|
+
async function route3(request2, config) {
|
|
491
|
+
const { info } = Logger(
|
|
492
|
+
{ ...config, debug: config.debug },
|
|
493
|
+
`[ROUTES][${key3}]`
|
|
494
|
+
);
|
|
495
|
+
const session = await auth(request2, config);
|
|
496
|
+
if (!session) {
|
|
497
|
+
info("401");
|
|
498
|
+
return new Response(null, { status: 401 });
|
|
472
499
|
}
|
|
473
|
-
|
|
474
|
-
|
|
500
|
+
const yurl = new URL(request2.url);
|
|
501
|
+
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
502
|
+
if (!tenantId) {
|
|
503
|
+
info("No tenant id found in path");
|
|
504
|
+
return new Response(null, { status: 404 });
|
|
475
505
|
}
|
|
476
|
-
|
|
477
|
-
|
|
506
|
+
switch (request2.method) {
|
|
507
|
+
case "GET":
|
|
508
|
+
return await GET3(config, { request: request2 });
|
|
509
|
+
case "POST":
|
|
510
|
+
return await POST2(config, session, { request: request2 });
|
|
511
|
+
default:
|
|
512
|
+
return new Response("method not allowed", { status: 405 });
|
|
478
513
|
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
debug;
|
|
487
|
-
db;
|
|
488
|
-
api;
|
|
489
|
-
#tenantId;
|
|
490
|
-
#userId;
|
|
491
|
-
get tenantId() {
|
|
492
|
-
return this.#tenantId;
|
|
514
|
+
}
|
|
515
|
+
function matches3(configRoutes, request2) {
|
|
516
|
+
const url = new URL(request2.url);
|
|
517
|
+
const [userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
|
|
518
|
+
let route16 = configRoutes[key3].replace("{tenantId}", tenantId).replace("{userId}", userId);
|
|
519
|
+
if (userId === "users") {
|
|
520
|
+
route16 = configRoutes[key3].replace("{tenantId}", possibleTenantId);
|
|
493
521
|
}
|
|
494
|
-
|
|
495
|
-
|
|
522
|
+
return urlMatches(request2.url, route16);
|
|
523
|
+
}
|
|
524
|
+
async function fetchTenantUsers(config, method, payload) {
|
|
525
|
+
const { body, params } = {};
|
|
526
|
+
if (!config.tenantId) {
|
|
527
|
+
throw new Error(
|
|
528
|
+
'Unable to fetch tenant, the tenantId context is missing. Call nile.setContext({ tenantId }), set nile.tenantId = "tenantId", or add it to the function call'
|
|
529
|
+
);
|
|
496
530
|
}
|
|
497
|
-
|
|
498
|
-
|
|
531
|
+
if (!isUUID(config.tenantId) && config.logger?.warn) {
|
|
532
|
+
config.logger?.warn(
|
|
533
|
+
"nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
534
|
+
);
|
|
499
535
|
}
|
|
500
|
-
|
|
501
|
-
|
|
536
|
+
const q = new URLSearchParams();
|
|
537
|
+
if (params?.newTenantName) {
|
|
538
|
+
q.set("newTenantName", params.newTenantName);
|
|
502
539
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
this.user = getUsername(envVarConfig);
|
|
506
|
-
this.logger = config?.logger;
|
|
507
|
-
this.password = getPassword(envVarConfig);
|
|
508
|
-
if (process.env.NODE_ENV !== "TEST") {
|
|
509
|
-
if (!this.user) {
|
|
510
|
-
throw new Error(
|
|
511
|
-
"User is required. Set NILEDB_USER as an environment variable or set `user` in the config options."
|
|
512
|
-
);
|
|
513
|
-
}
|
|
514
|
-
if (!this.password) {
|
|
515
|
-
throw new Error(
|
|
516
|
-
"Password is required. Set NILEDB_PASSWORD as an environment variable or set `password` in the config options."
|
|
517
|
-
);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
this.databaseId = getDatabaseId(envVarConfig);
|
|
521
|
-
this.databaseName = getDatabaseName(envVarConfig);
|
|
522
|
-
this.#tenantId = getTenantId(envVarConfig);
|
|
523
|
-
this.debug = Boolean(config?.debug);
|
|
524
|
-
this.#userId = config?.userId;
|
|
525
|
-
const { host, port, ...dbConfig } = config?.db ?? {};
|
|
526
|
-
const configuredHost = host ?? getDbHost(envVarConfig);
|
|
527
|
-
const configuredPort = port ?? getDbPort(envVarConfig);
|
|
528
|
-
this.api = new ApiConfig(config, logger);
|
|
529
|
-
this.db = {
|
|
530
|
-
user: this.user,
|
|
531
|
-
password: this.password,
|
|
532
|
-
host: configuredHost,
|
|
533
|
-
port: configuredPort,
|
|
534
|
-
...dbConfig
|
|
535
|
-
};
|
|
536
|
-
if (this.databaseName) {
|
|
537
|
-
this.db.database = this.databaseName;
|
|
538
|
-
}
|
|
540
|
+
if (params?.tenantId) {
|
|
541
|
+
q.set("tenantId", params.tenantId);
|
|
539
542
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
let basePath = getBasePath(envVarConfig);
|
|
549
|
-
if (configuredHost && this.databaseName && this.databaseId && basePath) {
|
|
550
|
-
info("Already configured, aborting fetch");
|
|
551
|
-
this.api = new ApiConfig(config);
|
|
552
|
-
this.db = {
|
|
553
|
-
user: this.user,
|
|
554
|
-
password: this.password,
|
|
555
|
-
host: configuredHost,
|
|
556
|
-
port: configuredPort,
|
|
557
|
-
database: this.databaseName,
|
|
558
|
-
...dbConfig
|
|
559
|
-
};
|
|
560
|
-
const cloned = { ...this.db };
|
|
561
|
-
cloned.password = "***";
|
|
562
|
-
info("[config set]", { db: cloned, api: this.api });
|
|
563
|
-
return this;
|
|
564
|
-
} else {
|
|
565
|
-
const msg = [];
|
|
566
|
-
if (!configuredHost) {
|
|
567
|
-
msg.push("Database host");
|
|
568
|
-
}
|
|
569
|
-
if (!this.databaseName) {
|
|
570
|
-
msg.push("Database name");
|
|
571
|
-
}
|
|
572
|
-
if (!this.databaseId) {
|
|
573
|
-
msg.push("Database id");
|
|
574
|
-
}
|
|
575
|
-
if (!basePath) {
|
|
576
|
-
msg.push("API URL");
|
|
577
|
-
}
|
|
578
|
-
info(
|
|
579
|
-
`[autoconfigure] ${msg.join(", ")} ${msg.length > 1 ? "are" : "is"} missing from the config. Autoconfiguration will run.`
|
|
580
|
-
);
|
|
581
|
-
}
|
|
582
|
-
const cp = getControlPlane(envVarConfig);
|
|
583
|
-
const databaseName = getDatabaseName({ config, logger: "getInfo" });
|
|
584
|
-
const url = new URL(`${cp}/databases/configure`);
|
|
585
|
-
if (databaseName) {
|
|
586
|
-
url.searchParams.set("databaseName", databaseName);
|
|
587
|
-
}
|
|
588
|
-
info(`configuring from ${url.href}`);
|
|
589
|
-
const res = await fetch(url, {
|
|
590
|
-
headers: {
|
|
591
|
-
Authorization: `Bearer ${getInfoBearer({ config })}`
|
|
592
|
-
}
|
|
593
|
-
}).catch(() => {
|
|
594
|
-
error(`Unable to auto-configure. is ${url} available?`);
|
|
595
|
-
});
|
|
596
|
-
if (!res) {
|
|
597
|
-
return this;
|
|
598
|
-
}
|
|
599
|
-
let database;
|
|
600
|
-
const possibleError = res.clone();
|
|
601
|
-
try {
|
|
602
|
-
const json = await res.json();
|
|
603
|
-
if (res.status === 404) {
|
|
604
|
-
info("is the configured databaseName correct?");
|
|
605
|
-
}
|
|
606
|
-
if (json.status && json.status !== "READY") {
|
|
607
|
-
database = { message: "Database is not ready yet" };
|
|
608
|
-
} else {
|
|
609
|
-
database = json;
|
|
610
|
-
}
|
|
611
|
-
} catch (e) {
|
|
612
|
-
const message = await possibleError.text();
|
|
613
|
-
debug("Unable to auto-configure");
|
|
614
|
-
error(message);
|
|
615
|
-
database = { message };
|
|
616
|
-
}
|
|
617
|
-
info("[fetched database]", database);
|
|
618
|
-
if (process.env.NODE_ENV !== "TEST") {
|
|
619
|
-
if ("message" in database) {
|
|
620
|
-
if ("statusCode" in database) {
|
|
621
|
-
error(database);
|
|
622
|
-
throw new Error("HTTP error has occurred");
|
|
623
|
-
} else {
|
|
624
|
-
throw new Error(
|
|
625
|
-
"Unable to auto-configure. Please remove NILEDB_NAME, NILEDB_API_URL, NILEDB_POSTGRES_URL, and/or NILEDB_HOST from your environment variables."
|
|
626
|
-
);
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
if (typeof database === "object") {
|
|
630
|
-
const { apiHost, dbHost, name, id } = database;
|
|
631
|
-
basePath = basePath || apiHost;
|
|
632
|
-
this.databaseId = id;
|
|
633
|
-
this.databaseName = name;
|
|
634
|
-
const dburl = new URL(dbHost);
|
|
635
|
-
configuredHost = dburl.hostname;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
this.api = new ApiConfig(config);
|
|
639
|
-
this.db = {
|
|
640
|
-
user: this.user,
|
|
641
|
-
password: this.password,
|
|
642
|
-
host: configuredHost,
|
|
643
|
-
port: configuredPort,
|
|
644
|
-
database: this.databaseName,
|
|
645
|
-
...dbConfig
|
|
646
|
-
};
|
|
647
|
-
info("[config set]", { db: this.db, api: this.api });
|
|
648
|
-
return this;
|
|
543
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/tenants/{tenantId}/users" /* TENANT_USERS */.replace(
|
|
544
|
+
"{tenantId}",
|
|
545
|
+
config.tenantId
|
|
546
|
+
)}`;
|
|
547
|
+
const m = method;
|
|
548
|
+
const init = {
|
|
549
|
+
method: m,
|
|
550
|
+
headers: config.headers
|
|
649
551
|
};
|
|
650
|
-
|
|
552
|
+
const req = new Request(clientUrl, init);
|
|
553
|
+
return await config.handlers[m](req);
|
|
554
|
+
}
|
|
651
555
|
|
|
652
|
-
// src/
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
const callbackList = this.events[eventName];
|
|
658
|
-
if (callbackList) {
|
|
659
|
-
for (const callback of callbackList) {
|
|
660
|
-
callback(value);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
// Subscribe to events
|
|
665
|
-
subscribe(eventName, callback) {
|
|
666
|
-
if (!this.events[eventName]) {
|
|
667
|
-
this.events[eventName] = [];
|
|
668
|
-
}
|
|
669
|
-
this.events[eventName].push(callback);
|
|
556
|
+
// src/api/routes/tenants/GET.ts
|
|
557
|
+
async function GET4(config, session, init) {
|
|
558
|
+
let url = `${apiRoutes(config).USER_TENANTS(session.id)}`;
|
|
559
|
+
if (typeof session === "object" && "user" in session && session.user) {
|
|
560
|
+
url = `${apiRoutes(config).USER_TENANTS(session.user.id)}`;
|
|
670
561
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
delete this.events[eventName];
|
|
683
|
-
}
|
|
562
|
+
const res = await request(url, init, config);
|
|
563
|
+
return res;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// src/api/routes/tenants/[tenantId]/GET.ts
|
|
567
|
+
async function GET5(config, init, log) {
|
|
568
|
+
const yurl = new URL(init.request.url);
|
|
569
|
+
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
570
|
+
if (!tenantId) {
|
|
571
|
+
log("[GET] No tenant id provided.");
|
|
572
|
+
return new Response(null, { status: 404 });
|
|
684
573
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
};
|
|
690
|
-
var watchTenantId = (cb) => eventer.subscribe("tenantId" /* Tenant */, cb);
|
|
691
|
-
var updateUserId = (userId) => {
|
|
692
|
-
eventer.publish("userId" /* User */, userId);
|
|
693
|
-
};
|
|
694
|
-
var watchUserId = (cb) => eventer.subscribe("userId" /* User */, cb);
|
|
695
|
-
var watchToken = (cb) => eventer.subscribe("token" /* Token */, cb);
|
|
696
|
-
var watchEvictPool = (cb) => eventer.subscribe("EvictPool" /* EvictPool */, cb);
|
|
697
|
-
var evictPool = (val) => {
|
|
698
|
-
eventer.publish("EvictPool" /* EvictPool */, val);
|
|
699
|
-
};
|
|
574
|
+
init.method = "GET";
|
|
575
|
+
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
576
|
+
return await request(url, init, config);
|
|
577
|
+
}
|
|
700
578
|
|
|
701
|
-
// src/
|
|
702
|
-
function
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
);
|
|
712
|
-
} else if (!config.db.database) {
|
|
713
|
-
error(
|
|
714
|
-
"Database name is missing from the config. Call `nile.init()` or set NILEDB_ID in your .env"
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
const caller = target[property];
|
|
719
|
-
return function query(...args) {
|
|
720
|
-
info("query", ...args);
|
|
721
|
-
const called = caller.apply(this, args);
|
|
722
|
-
return called;
|
|
723
|
-
};
|
|
724
|
-
}
|
|
725
|
-
return target[property];
|
|
726
|
-
}
|
|
727
|
-
});
|
|
579
|
+
// src/api/routes/tenants/[tenantId]/DELETE.ts
|
|
580
|
+
async function DELETE2(config, init) {
|
|
581
|
+
const yurl = new URL(init.request.url);
|
|
582
|
+
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
583
|
+
if (!tenantId) {
|
|
584
|
+
return new Response(null, { status: 404 });
|
|
585
|
+
}
|
|
586
|
+
init.method = "DELETE";
|
|
587
|
+
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
588
|
+
return await request(url, init, config);
|
|
728
589
|
}
|
|
729
590
|
|
|
730
|
-
// src/
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
tenantId;
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
config;
|
|
737
|
-
timer;
|
|
738
|
-
constructor(config, id) {
|
|
739
|
-
const { warn, info, debug } = Logger(config, "[NileInstance]");
|
|
740
|
-
this.id = id;
|
|
741
|
-
const poolConfig = {
|
|
742
|
-
min: 0,
|
|
743
|
-
max: 10,
|
|
744
|
-
idleTimeoutMillis: 3e4,
|
|
745
|
-
...config.db
|
|
746
|
-
};
|
|
747
|
-
const { afterCreate, ...remaining } = poolConfig;
|
|
748
|
-
config.db = poolConfig;
|
|
749
|
-
this.config = config;
|
|
750
|
-
const cloned = { ...this.config.db };
|
|
751
|
-
cloned.password = "***";
|
|
752
|
-
debug(`Connection pool config ${JSON.stringify(cloned)}`);
|
|
753
|
-
this.pool = createProxyForPool(new pg__default.default.Pool(remaining), this.config);
|
|
754
|
-
if (typeof afterCreate === "function") {
|
|
755
|
-
warn(
|
|
756
|
-
"Providing an pool configuration will stop automatic tenant context setting."
|
|
757
|
-
);
|
|
758
|
-
}
|
|
759
|
-
this.startTimeout();
|
|
760
|
-
this.pool.on("connect", async (client) => {
|
|
761
|
-
debug(`pool connected ${this.id}`);
|
|
762
|
-
this.startTimeout();
|
|
763
|
-
const afterCreate2 = makeAfterCreate(
|
|
764
|
-
config,
|
|
765
|
-
`${this.id}-${this.timer}`
|
|
766
|
-
);
|
|
767
|
-
afterCreate2(client, (err) => {
|
|
768
|
-
const { error } = Logger(config, "[after create callback]");
|
|
769
|
-
if (err) {
|
|
770
|
-
clearTimeout(this.timer);
|
|
771
|
-
error("after create failed", {
|
|
772
|
-
message: err.message,
|
|
773
|
-
stack: err.stack
|
|
774
|
-
});
|
|
775
|
-
evictPool(this.id);
|
|
776
|
-
}
|
|
777
|
-
});
|
|
778
|
-
});
|
|
779
|
-
this.pool.on("error", (err) => {
|
|
780
|
-
clearTimeout(this.timer);
|
|
781
|
-
info(`pool ${this.id} failed`, {
|
|
782
|
-
message: err.message,
|
|
783
|
-
stack: err.stack
|
|
784
|
-
});
|
|
785
|
-
evictPool(this.id);
|
|
786
|
-
});
|
|
787
|
-
this.pool.on("release", (destroy) => {
|
|
788
|
-
if (destroy) {
|
|
789
|
-
clearTimeout(this.timer);
|
|
790
|
-
evictPool(this.id);
|
|
791
|
-
debug(`destroying pool ${this.id}`);
|
|
792
|
-
}
|
|
793
|
-
});
|
|
794
|
-
}
|
|
795
|
-
startTimeout() {
|
|
796
|
-
const { debug } = Logger(this.config, "[NileInstance]");
|
|
797
|
-
if (this.timer) {
|
|
798
|
-
clearTimeout(this.timer);
|
|
799
|
-
}
|
|
800
|
-
this.timer = setTimeout(() => {
|
|
801
|
-
debug(
|
|
802
|
-
`Pool reached idleTimeoutMillis. ${this.id} evicted after ${Number(this.config.db.idleTimeoutMillis) ?? 3e4}ms`
|
|
803
|
-
);
|
|
804
|
-
this.pool.end(() => {
|
|
805
|
-
clearTimeout(this.timer);
|
|
806
|
-
evictPool(this.id);
|
|
807
|
-
});
|
|
808
|
-
}, Number(this.config.db.idleTimeoutMillis) ?? 3e4);
|
|
591
|
+
// src/api/routes/tenants/[tenantId]/PUT.ts
|
|
592
|
+
async function PUT3(config, init) {
|
|
593
|
+
const yurl = new URL(init.request.url);
|
|
594
|
+
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
595
|
+
if (!tenantId) {
|
|
596
|
+
return new Response(null, { status: 404 });
|
|
809
597
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
598
|
+
init.body = init.request.body;
|
|
599
|
+
init.method = "PUT";
|
|
600
|
+
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
601
|
+
return await request(url, init, config);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// src/api/routes/tenants/POST.ts
|
|
605
|
+
async function POST3(config, init) {
|
|
606
|
+
init.body = init.request.body;
|
|
607
|
+
init.method = "POST";
|
|
608
|
+
const url = `${apiRoutes(config).TENANTS}`;
|
|
609
|
+
return await request(url, init, config);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// src/api/routes/tenants/index.ts
|
|
613
|
+
var key4 = "TENANTS";
|
|
614
|
+
async function route4(request2, config) {
|
|
615
|
+
const { info } = Logger(
|
|
616
|
+
{ ...config, debug: config.debug },
|
|
617
|
+
`[ROUTES][${key4}]`
|
|
618
|
+
);
|
|
619
|
+
const session = await auth(request2, config);
|
|
620
|
+
if (!session) {
|
|
621
|
+
info("401");
|
|
622
|
+
return new Response(null, { status: 401 });
|
|
817
623
|
}
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
conn.on("error", function errorHandler(e) {
|
|
824
|
-
error(`Connection ${id} was terminated by server`, {
|
|
825
|
-
message: e.message,
|
|
826
|
-
stack: e.stack
|
|
827
|
-
});
|
|
828
|
-
done(e, conn);
|
|
829
|
-
});
|
|
830
|
-
if (config.tenantId) {
|
|
831
|
-
const query = [`SET nile.tenant_id = '${config.tenantId}'`];
|
|
832
|
-
if (config.userId) {
|
|
833
|
-
if (!config.tenantId) {
|
|
834
|
-
warn("A user id cannot be set in context without a tenant id");
|
|
835
|
-
}
|
|
836
|
-
query.push(`SET nile.user_id = '${config.userId}'`);
|
|
624
|
+
const [possibleTenantId] = request2.url.split("/").reverse();
|
|
625
|
+
switch (request2.method) {
|
|
626
|
+
case "GET":
|
|
627
|
+
if (isUUID(possibleTenantId)) {
|
|
628
|
+
return await GET5(config, { request: request2 }, info);
|
|
837
629
|
}
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
done(err, conn);
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
done(null, conn);
|
|
630
|
+
return await GET4(config, session, { request: request2 });
|
|
631
|
+
case "POST":
|
|
632
|
+
return await POST3(config, { request: request2 });
|
|
633
|
+
case "DELETE":
|
|
634
|
+
return await DELETE2(config, { request: request2 });
|
|
635
|
+
case "PUT":
|
|
636
|
+
return await PUT3(config, { request: request2 });
|
|
637
|
+
default:
|
|
638
|
+
return new Response("method not allowed", { status: 405 });
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
function matches4(configRoutes, request2) {
|
|
642
|
+
return urlMatches(request2.url, configRoutes[key4]);
|
|
643
|
+
}
|
|
644
|
+
async function fetchTenants(config, method, body) {
|
|
645
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/tenants" /* TENANTS */}`;
|
|
646
|
+
const init = {
|
|
647
|
+
method,
|
|
648
|
+
headers: config.headers
|
|
861
649
|
};
|
|
650
|
+
{
|
|
651
|
+
init.body = body;
|
|
652
|
+
}
|
|
653
|
+
const req = new Request(clientUrl, init);
|
|
654
|
+
return await config.handlers.POST(req);
|
|
862
655
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
poolWatcherFn;
|
|
869
|
-
makeId(tenantId, userId) {
|
|
870
|
-
if (tenantId && userId) {
|
|
871
|
-
return `${tenantId}:${userId}`;
|
|
872
|
-
}
|
|
873
|
-
if (tenantId) {
|
|
874
|
-
return `${tenantId}`;
|
|
875
|
-
}
|
|
876
|
-
return "base";
|
|
656
|
+
async function fetchTenant(config, method, body) {
|
|
657
|
+
if (!config.tenantId) {
|
|
658
|
+
throw new Error(
|
|
659
|
+
'Unable to fetch tenant, the tenantId context is missing. Call nile.setContext({ tenantId }), set nile.tenantId = "tenantId", or add it to the function call'
|
|
660
|
+
);
|
|
877
661
|
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
watchEvictPool(this.poolWatcherFn);
|
|
662
|
+
if (!isUUID(config.tenantId) && config.logger?.warn) {
|
|
663
|
+
config.logger?.warn(
|
|
664
|
+
"nile.tenantId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
665
|
+
);
|
|
883
666
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
connection?.shutdown();
|
|
890
|
-
this.connections.delete(id);
|
|
891
|
-
} else {
|
|
892
|
-
warn(`missed eviction of ${id}`);
|
|
893
|
-
}
|
|
667
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/tenants/{tenantId}" /* TENANT */.replace("{tenantId}", config.tenantId)}`;
|
|
668
|
+
const m = method ?? "GET";
|
|
669
|
+
const init = {
|
|
670
|
+
method: m,
|
|
671
|
+
headers: config.headers
|
|
894
672
|
};
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
673
|
+
if (m === "PUT") {
|
|
674
|
+
init.body = body;
|
|
675
|
+
}
|
|
676
|
+
const req = new Request(clientUrl, init);
|
|
677
|
+
return await config.handlers[m](req);
|
|
678
|
+
}
|
|
679
|
+
async function fetchTenantsByUser(config) {
|
|
680
|
+
if (config.logger?.warn) {
|
|
681
|
+
if (!config.userId) {
|
|
682
|
+
config.logger?.warn(
|
|
683
|
+
"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."
|
|
684
|
+
);
|
|
685
|
+
} else if (!isUUID(config.userId)) {
|
|
686
|
+
config.logger?.warn(
|
|
687
|
+
"nile.userId is not a valid UUID. This may lead to unexpected behavior in your application."
|
|
688
|
+
);
|
|
904
689
|
}
|
|
905
|
-
const newOne = new NileInstance_default(new Config(config), id);
|
|
906
|
-
this.connections.set(id, newOne);
|
|
907
|
-
info(`created new ${id}`);
|
|
908
|
-
info(`# of instances: ${this.connections.size}`);
|
|
909
|
-
if (this.cleared) {
|
|
910
|
-
this.cleared = false;
|
|
911
|
-
}
|
|
912
|
-
return newOne.pool;
|
|
913
|
-
};
|
|
914
|
-
clear = (config) => {
|
|
915
|
-
const { info } = Logger(config, "[DBManager]");
|
|
916
|
-
info(`Clearing all connections ${this.connections.size}`);
|
|
917
|
-
this.cleared = true;
|
|
918
|
-
this.connections.forEach((connection) => {
|
|
919
|
-
connection.shutdown();
|
|
920
|
-
});
|
|
921
|
-
this.connections.clear();
|
|
922
|
-
};
|
|
923
|
-
};
|
|
924
|
-
|
|
925
|
-
// src/api/utils/routes/makeRestUrl.ts
|
|
926
|
-
var NILEDB_API_URL = process.env.NILEDB_API_URL;
|
|
927
|
-
function filterNullUndefined(obj) {
|
|
928
|
-
if (!obj) {
|
|
929
|
-
return void 0;
|
|
930
690
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
);
|
|
691
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/users/{userId}/tenants" /* USER_TENANTS */.replace(
|
|
692
|
+
"{userId}",
|
|
693
|
+
config.userId ?? "WARN_NOT_SET"
|
|
694
|
+
)}`;
|
|
695
|
+
const req = new Request(clientUrl, { headers: config.headers });
|
|
696
|
+
return await config.handlers.GET(req);
|
|
936
697
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
698
|
+
|
|
699
|
+
// src/api/routes/auth/signin.ts
|
|
700
|
+
var key5 = "SIGNIN";
|
|
701
|
+
async function route5(req, config) {
|
|
702
|
+
let url = proxyRoutes(config)[key5];
|
|
703
|
+
const init = {
|
|
704
|
+
method: req.method,
|
|
705
|
+
headers: req.headers
|
|
706
|
+
};
|
|
707
|
+
if (req.method === "POST") {
|
|
708
|
+
const [provider] = new URL(req.url).pathname.split("/").reverse();
|
|
709
|
+
url = `${proxyRoutes(config)[key5]}/${provider}`;
|
|
943
710
|
}
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
)
|
|
947
|
-
const
|
|
948
|
-
return
|
|
711
|
+
const passThroughUrl = new URL(req.url);
|
|
712
|
+
const params = new URLSearchParams(passThroughUrl.search);
|
|
713
|
+
url = `${url}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
|
|
714
|
+
const res = await request(url, { ...init, request: req }, config);
|
|
715
|
+
return res;
|
|
716
|
+
}
|
|
717
|
+
function matches5(configRoutes, request2) {
|
|
718
|
+
return urlMatches(request2.url, configRoutes[key5]);
|
|
719
|
+
}
|
|
720
|
+
async function fetchSignIn(config, provider, body) {
|
|
721
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/auth/signin" /* SIGNIN */}/${provider}`;
|
|
722
|
+
const req = new Request(clientUrl, {
|
|
723
|
+
method: "POST",
|
|
724
|
+
headers: config.headers,
|
|
725
|
+
body
|
|
726
|
+
});
|
|
727
|
+
return await config.handlers.POST(req);
|
|
949
728
|
}
|
|
950
729
|
|
|
951
|
-
// src/api/
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
USER_TENANTS: (userId) => makeRestUrl(config, `/users/${userId}/tenants`)
|
|
962
|
-
});
|
|
963
|
-
|
|
964
|
-
// src/api/routes/me/index.ts
|
|
965
|
-
var key = "ME";
|
|
966
|
-
async function GET(url, init, config) {
|
|
967
|
-
const res = await request(url, init, config);
|
|
968
|
-
return res;
|
|
730
|
+
// src/api/routes/auth/session.ts
|
|
731
|
+
async function route6(req, config) {
|
|
732
|
+
return request(
|
|
733
|
+
proxyRoutes(config).SESSION,
|
|
734
|
+
{
|
|
735
|
+
method: req.method,
|
|
736
|
+
request: req
|
|
737
|
+
},
|
|
738
|
+
config
|
|
739
|
+
);
|
|
969
740
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
switch (request2.method) {
|
|
973
|
-
case "GET":
|
|
974
|
-
return await GET(url, { request: request2 }, config);
|
|
975
|
-
default:
|
|
976
|
-
return new Response("method not allowed", { status: 405 });
|
|
977
|
-
}
|
|
741
|
+
function matches6(configRoutes, request2) {
|
|
742
|
+
return urlMatches(request2.url, configRoutes.SESSION);
|
|
978
743
|
}
|
|
979
|
-
function
|
|
980
|
-
|
|
744
|
+
async function fetchSession(config) {
|
|
745
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/auth/session" /* SESSION */}`;
|
|
746
|
+
const req = new Request(clientUrl, {
|
|
747
|
+
method: "GET",
|
|
748
|
+
headers: config.headers
|
|
749
|
+
});
|
|
750
|
+
return await config.handlers.GET(req);
|
|
981
751
|
}
|
|
982
752
|
|
|
983
|
-
// src/
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
753
|
+
// src/api/routes/auth/providers.ts
|
|
754
|
+
async function route7(req, config) {
|
|
755
|
+
return request(
|
|
756
|
+
proxyRoutes(config).PROVIDERS,
|
|
757
|
+
{
|
|
758
|
+
method: req.method,
|
|
759
|
+
request: req
|
|
760
|
+
},
|
|
761
|
+
config
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
function matches7(configRoutes, request2) {
|
|
765
|
+
return urlMatches(request2.url, configRoutes.PROVIDERS);
|
|
766
|
+
}
|
|
767
|
+
async function fetchProviders(config) {
|
|
768
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/auth/providers" /* PROVIDERS */}`;
|
|
769
|
+
const req = new Request(clientUrl, {
|
|
770
|
+
method: "GET",
|
|
771
|
+
headers: config.headers
|
|
772
|
+
});
|
|
773
|
+
return await config.handlers.GET(req);
|
|
774
|
+
}
|
|
990
775
|
|
|
991
|
-
// src/
|
|
992
|
-
function
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
if (cookie) {
|
|
1004
|
-
for (const parts of cookie) {
|
|
1005
|
-
const cookieParts = parts.split("=");
|
|
1006
|
-
const _cookie = cookieParts.slice(1).join("=");
|
|
1007
|
-
const name = cookieParts[0];
|
|
1008
|
-
_cookies[name] = _cookie;
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
if (cookieKey) {
|
|
1012
|
-
return _cookies[cookieKey];
|
|
1013
|
-
}
|
|
1014
|
-
return null;
|
|
776
|
+
// src/api/routes/auth/csrf.ts
|
|
777
|
+
async function route8(req, config) {
|
|
778
|
+
return request(
|
|
779
|
+
proxyRoutes(config).CSRF,
|
|
780
|
+
{
|
|
781
|
+
method: req.method,
|
|
782
|
+
request: req
|
|
783
|
+
},
|
|
784
|
+
config
|
|
785
|
+
);
|
|
1015
786
|
}
|
|
1016
|
-
function
|
|
1017
|
-
|
|
1018
|
-
return cookieTenant ?? headers?.get(X_NILE_TENANT) ?? config?.tenantId;
|
|
787
|
+
function matches8(configRoutes, request2) {
|
|
788
|
+
return urlMatches(request2.url, configRoutes.CSRF);
|
|
1019
789
|
}
|
|
1020
|
-
function
|
|
1021
|
-
const
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
}
|
|
1026
|
-
return
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
if (localOrigin) {
|
|
1038
|
-
headers.set(X_NILE_ORIGIN, localOrigin);
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
const cookie = headers.get("cookie");
|
|
1043
|
-
if (!cookie) {
|
|
1044
|
-
if (config.api.headers) {
|
|
1045
|
-
const configCookie = config.api.headers.get("cookie");
|
|
1046
|
-
if (configCookie) {
|
|
1047
|
-
headers.set("cookie", configCookie);
|
|
1048
|
-
}
|
|
1049
|
-
} else {
|
|
1050
|
-
if (!url.endsWith("/users")) {
|
|
1051
|
-
error(
|
|
1052
|
-
"Missing cookie header from request. Call nile.api.setContext(request) before making additional calls."
|
|
1053
|
-
);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
const authHeader = headers.get("Authorization");
|
|
1058
|
-
if (!authHeader) {
|
|
1059
|
-
const token = getTokenFromCookie(headers, cookieKey);
|
|
1060
|
-
if (token) {
|
|
1061
|
-
headers.set("Authorization", `Bearer ${token}`);
|
|
1062
|
-
} else if (getToken({ config })) {
|
|
1063
|
-
headers.set("Authorization", `Bearer ${getToken({ config })}`);
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
if (config && config.api.secureCookies != null) {
|
|
1067
|
-
headers.set(X_NILE_SECURECOOKIES, String(config.api.secureCookies));
|
|
1068
|
-
}
|
|
1069
|
-
if (config && config.api.origin) {
|
|
1070
|
-
headers.set(X_NILE_ORIGIN, config.api.origin);
|
|
1071
|
-
} else {
|
|
1072
|
-
warn(
|
|
1073
|
-
"nile.origin missing from header, which defaults to secure cookies only."
|
|
1074
|
-
);
|
|
1075
|
-
}
|
|
1076
|
-
return headers;
|
|
1077
|
-
}
|
|
1078
|
-
async function _fetch(config, path, opts) {
|
|
1079
|
-
const { debug, error } = Logger(config, "[server]");
|
|
1080
|
-
const url = `${config.api?.basePath}${path}`;
|
|
1081
|
-
const headers = new Headers(opts?.headers);
|
|
1082
|
-
const tenantId = getTenantFromHttp(headers, config);
|
|
1083
|
-
const basicHeaders = makeBasicHeaders(config, url, opts);
|
|
1084
|
-
updateTenantId(tenantId);
|
|
1085
|
-
const userId = getUserFromHttp(headers, config);
|
|
1086
|
-
updateUserId(userId);
|
|
1087
|
-
if (url.includes("{tenantId}") && !tenantId) {
|
|
1088
|
-
return new ResponseError("tenantId is not set for request", {
|
|
1089
|
-
status: 400
|
|
1090
|
-
});
|
|
1091
|
-
}
|
|
1092
|
-
const useableUrl = url.replace("{tenantId}", encodeURIComponent(String(tenantId))).replace("{userId}", encodeURIComponent(String(userId)));
|
|
1093
|
-
debug(`[fetch] ${useableUrl}`);
|
|
790
|
+
async function fetchCsrf(config) {
|
|
791
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/auth/csrf" /* CSRF */}`;
|
|
792
|
+
const req = new Request(clientUrl, {
|
|
793
|
+
method: "GET",
|
|
794
|
+
headers: config.headers
|
|
795
|
+
});
|
|
796
|
+
return await config.handlers.GET(req);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// src/api/routes/auth/callback.ts
|
|
800
|
+
var key6 = "CALLBACK";
|
|
801
|
+
async function route9(req, config) {
|
|
802
|
+
const { error } = Logger(
|
|
803
|
+
{ ...config, debug: config.debug },
|
|
804
|
+
`[ROUTES][${key6}]`
|
|
805
|
+
);
|
|
806
|
+
const [provider] = new URL(req.url).pathname.split("/").reverse();
|
|
1094
807
|
try {
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
808
|
+
const passThroughUrl = new URL(req.url);
|
|
809
|
+
const params = new URLSearchParams(passThroughUrl.search);
|
|
810
|
+
const url = `${proxyRoutes(config)[key6]}/${provider}${params.toString() !== "" ? `?${params.toString()}` : ""}`;
|
|
811
|
+
const res = await request(
|
|
812
|
+
url,
|
|
813
|
+
{
|
|
814
|
+
request: req,
|
|
815
|
+
method: req.method
|
|
816
|
+
},
|
|
817
|
+
config
|
|
818
|
+
).catch((e) => {
|
|
819
|
+
error("an error as occurred", e);
|
|
1106
820
|
});
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
821
|
+
const location = res?.headers.get("location");
|
|
822
|
+
if (location) {
|
|
823
|
+
return new Response(res?.body, {
|
|
824
|
+
status: 302,
|
|
825
|
+
headers: res?.headers
|
|
1110
826
|
});
|
|
1111
827
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
debug(
|
|
1116
|
-
`[fetch][response][${opts?.method ?? "GET"}] ${response.status} ${useableUrl}`,
|
|
1117
|
-
{
|
|
1118
|
-
body: await response.clone().json()
|
|
1119
|
-
}
|
|
1120
|
-
);
|
|
1121
|
-
} catch (e) {
|
|
1122
|
-
debug(
|
|
1123
|
-
`[fetch][response][${opts?.method ?? "GET"}] ${response.status} ${useableUrl}`,
|
|
1124
|
-
{
|
|
1125
|
-
body: await response.clone().text()
|
|
1126
|
-
}
|
|
1127
|
-
);
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
return response;
|
|
1131
|
-
}
|
|
1132
|
-
if (response?.status === 404) {
|
|
1133
|
-
return new ResponseError("Not found", { status: 404 });
|
|
1134
|
-
}
|
|
1135
|
-
if (response?.status === 401) {
|
|
1136
|
-
return new ResponseError("Unauthorized", { status: 401 });
|
|
1137
|
-
}
|
|
1138
|
-
if (response?.status === 405) {
|
|
1139
|
-
return new ResponseError("Method not allowed", { status: 405 });
|
|
1140
|
-
}
|
|
1141
|
-
const errorHandler = typeof response?.clone === "function" ? response.clone() : null;
|
|
1142
|
-
let msg = "";
|
|
1143
|
-
const res = await response?.json().catch(async (e) => {
|
|
1144
|
-
if (errorHandler) {
|
|
1145
|
-
msg = await errorHandler.text();
|
|
1146
|
-
if (msg) {
|
|
1147
|
-
error(`[fetch][response][status: ${errorHandler.status}]`, {
|
|
1148
|
-
message: msg
|
|
1149
|
-
});
|
|
1150
|
-
}
|
|
1151
|
-
return e;
|
|
1152
|
-
}
|
|
1153
|
-
if (!msg) {
|
|
1154
|
-
error("[fetch][response]", { e });
|
|
1155
|
-
}
|
|
1156
|
-
return e;
|
|
1157
|
-
});
|
|
1158
|
-
if (msg) {
|
|
1159
|
-
return new ResponseError(msg, { status: errorHandler?.status });
|
|
1160
|
-
}
|
|
1161
|
-
if (res && "message" in res) {
|
|
1162
|
-
const { message } = res;
|
|
1163
|
-
error(`[fetch][response][status: ${errorHandler?.status}] ${message}`);
|
|
1164
|
-
return new ResponseError(message, { status: 400 });
|
|
1165
|
-
}
|
|
1166
|
-
if (res && "errors" in res) {
|
|
1167
|
-
const {
|
|
1168
|
-
errors: [message]
|
|
1169
|
-
} = res;
|
|
1170
|
-
error(`[fetch][response] [status: ${errorHandler?.status}] ${message}`);
|
|
1171
|
-
return new ResponseError(message, { status: 400 });
|
|
1172
|
-
}
|
|
1173
|
-
error(
|
|
1174
|
-
`[fetch][response][status: ${errorHandler?.status}] UNHANDLED ERROR`,
|
|
1175
|
-
{
|
|
1176
|
-
response,
|
|
1177
|
-
message: await response.text()
|
|
1178
|
-
}
|
|
1179
|
-
);
|
|
1180
|
-
return new ResponseError(null, {
|
|
1181
|
-
status: response?.status ?? 500
|
|
828
|
+
return new Response(res?.body, {
|
|
829
|
+
status: res?.status,
|
|
830
|
+
headers: res?.headers
|
|
1182
831
|
});
|
|
1183
832
|
} catch (e) {
|
|
1184
|
-
|
|
1185
|
-
status: 500
|
|
1186
|
-
});
|
|
833
|
+
error(e);
|
|
1187
834
|
}
|
|
835
|
+
return new Response("An unexpected error has occurred.", { status: 400 });
|
|
1188
836
|
}
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
async function POST(config, init) {
|
|
1192
|
-
init.body = init.request.body;
|
|
1193
|
-
init.method = "POST";
|
|
1194
|
-
const yurl = new URL(init.request.url);
|
|
1195
|
-
const tenantId = yurl.searchParams.get("tenantId");
|
|
1196
|
-
const newTenantName = yurl.searchParams.get("newTenantName");
|
|
1197
|
-
const tenant = tenantId ?? getTenantFromHttp(init.request.headers);
|
|
1198
|
-
const url = apiRoutes(config).USERS({ tenantId: tenant, newTenantName });
|
|
1199
|
-
return await request(url, init, config);
|
|
837
|
+
function matches9(configRoutes, request2) {
|
|
838
|
+
return urlMatches(request2.url, configRoutes.CALLBACK);
|
|
1200
839
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
return new Response(null, { status: 404 });
|
|
1210
|
-
}
|
|
1211
|
-
const url = apiRoutes(config).TENANT_USERS(tenant);
|
|
1212
|
-
init.method = "GET";
|
|
1213
|
-
return await request(url, init, config);
|
|
840
|
+
async function fetchCallback(config, provider, body) {
|
|
841
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/auth/callback" /* CALLBACK */}/${provider}`;
|
|
842
|
+
const req = new Request(clientUrl, {
|
|
843
|
+
method: "POST",
|
|
844
|
+
headers: config.headers,
|
|
845
|
+
body
|
|
846
|
+
});
|
|
847
|
+
return await config.handlers.POST(req);
|
|
1214
848
|
}
|
|
1215
849
|
|
|
1216
|
-
// src/api/routes/
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
850
|
+
// src/api/routes/auth/signout.ts
|
|
851
|
+
var key7 = "SIGNOUT";
|
|
852
|
+
async function route10(request2, config) {
|
|
853
|
+
let url = proxyRoutes(config)[key7];
|
|
854
|
+
const init = {
|
|
855
|
+
method: request2.method
|
|
856
|
+
};
|
|
857
|
+
if (request2.method === "POST") {
|
|
858
|
+
init.body = request2.body;
|
|
859
|
+
const [provider] = new URL(request2.url).pathname.split("/").reverse();
|
|
860
|
+
url = `${proxyRoutes(config)[key7]}${provider !== "signout" ? `/${provider}` : ""}`;
|
|
861
|
+
}
|
|
862
|
+
const res = await request(url, { ...init, request: request2 }, config);
|
|
863
|
+
return res;
|
|
864
|
+
}
|
|
865
|
+
function matches10(configRoutes, request2) {
|
|
866
|
+
return urlMatches(request2.url, configRoutes[key7]);
|
|
867
|
+
}
|
|
868
|
+
async function fetchSignOut(config, body) {
|
|
869
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/auth/signout" /* SIGNOUT */}`;
|
|
870
|
+
const req = new Request(clientUrl, {
|
|
871
|
+
method: "POST",
|
|
872
|
+
body,
|
|
873
|
+
headers: config.headers
|
|
874
|
+
});
|
|
875
|
+
return await config.handlers.POST(req);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
// src/api/routes/auth/error.ts
|
|
879
|
+
var key8 = "ERROR";
|
|
880
|
+
async function route11(req, config) {
|
|
881
|
+
return request(
|
|
882
|
+
proxyRoutes(config)[key8],
|
|
883
|
+
{
|
|
884
|
+
method: req.method,
|
|
885
|
+
request: req
|
|
886
|
+
},
|
|
887
|
+
config
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
function matches11(configRoutes, request2) {
|
|
891
|
+
return urlMatches(request2.url, configRoutes[key8]);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// src/api/routes/auth/verify-request.ts
|
|
895
|
+
var key9 = "VERIFY_REQUEST";
|
|
896
|
+
async function route12(req, config) {
|
|
897
|
+
return request(
|
|
898
|
+
proxyRoutes(config)[key9],
|
|
899
|
+
{
|
|
900
|
+
method: req.method,
|
|
901
|
+
request: req
|
|
902
|
+
},
|
|
903
|
+
config
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
function matches12(configRoutes, request2) {
|
|
907
|
+
return urlMatches(request2.url, configRoutes[key9]);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// src/api/routes/auth/password-reset.ts
|
|
911
|
+
var key10 = "PASSWORD_RESET";
|
|
912
|
+
async function route13(req, config) {
|
|
913
|
+
const url = proxyRoutes(config)[key10];
|
|
914
|
+
const res = await request(
|
|
915
|
+
url,
|
|
916
|
+
{
|
|
917
|
+
method: req.method,
|
|
918
|
+
request: req
|
|
919
|
+
},
|
|
920
|
+
config
|
|
921
|
+
);
|
|
922
|
+
const location = res?.headers.get("location");
|
|
923
|
+
if (location) {
|
|
924
|
+
return new Response(res?.body, {
|
|
925
|
+
status: 302,
|
|
926
|
+
headers: res?.headers
|
|
927
|
+
});
|
|
1220
928
|
}
|
|
929
|
+
return new Response(res?.body, {
|
|
930
|
+
status: res?.status,
|
|
931
|
+
headers: res?.headers
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
function matches13(configRoutes, request2) {
|
|
935
|
+
return urlMatches(request2.url, configRoutes.PASSWORD_RESET);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// src/api/handlers/GET.ts
|
|
939
|
+
function GETTER(configRoutes, config) {
|
|
940
|
+
const { info, warn } = Logger(config, "[GET MATCHER]");
|
|
941
|
+
return async function GET6(req) {
|
|
942
|
+
if (matches(configRoutes, req)) {
|
|
943
|
+
info("matches me");
|
|
944
|
+
return route(req, config);
|
|
945
|
+
}
|
|
946
|
+
if (matches3(configRoutes, req)) {
|
|
947
|
+
info("matches tenant users");
|
|
948
|
+
return route3(req, config);
|
|
949
|
+
}
|
|
950
|
+
if (matches2(configRoutes, req)) {
|
|
951
|
+
info("matches users");
|
|
952
|
+
return route2(req, config);
|
|
953
|
+
}
|
|
954
|
+
if (matches4(configRoutes, req)) {
|
|
955
|
+
info("matches tenants");
|
|
956
|
+
return route4(req, config);
|
|
957
|
+
}
|
|
958
|
+
if (matches6(configRoutes, req)) {
|
|
959
|
+
info("matches session");
|
|
960
|
+
return route6(req, config);
|
|
961
|
+
}
|
|
962
|
+
if (matches5(configRoutes, req)) {
|
|
963
|
+
info("matches signin");
|
|
964
|
+
return route5(req, config);
|
|
965
|
+
}
|
|
966
|
+
if (matches7(configRoutes, req)) {
|
|
967
|
+
info("matches providers");
|
|
968
|
+
return route7(req, config);
|
|
969
|
+
}
|
|
970
|
+
if (matches8(configRoutes, req)) {
|
|
971
|
+
info("matches csrf");
|
|
972
|
+
return route8(req, config);
|
|
973
|
+
}
|
|
974
|
+
if (matches13(configRoutes, req)) {
|
|
975
|
+
info("matches password reset");
|
|
976
|
+
return route13(req, config);
|
|
977
|
+
}
|
|
978
|
+
if (matches9(configRoutes, req)) {
|
|
979
|
+
info("matches callback");
|
|
980
|
+
return route9(req, config);
|
|
981
|
+
}
|
|
982
|
+
if (matches10(configRoutes, req)) {
|
|
983
|
+
info("matches signout");
|
|
984
|
+
return route10(req, config);
|
|
985
|
+
}
|
|
986
|
+
if (matches12(configRoutes, req)) {
|
|
987
|
+
info("matches verify-request");
|
|
988
|
+
return route12(req, config);
|
|
989
|
+
}
|
|
990
|
+
if (matches11(configRoutes, req)) {
|
|
991
|
+
info("matches error");
|
|
992
|
+
return route11(req, config);
|
|
993
|
+
}
|
|
994
|
+
warn(`No GET routes matched ${req.url}`);
|
|
995
|
+
return new Response(null, { status: 404 });
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
// src/api/routes/signup/POST.ts
|
|
1000
|
+
async function POST4(config, init) {
|
|
1221
1001
|
init.body = init.request.body;
|
|
1222
|
-
init.method = "
|
|
1223
|
-
const
|
|
1224
|
-
const url = apiRoutes(config).USER(userId);
|
|
1002
|
+
init.method = "POST";
|
|
1003
|
+
const url = `${apiRoutes(config).SIGNUP}`;
|
|
1225
1004
|
return await request(url, init, config);
|
|
1226
1005
|
}
|
|
1227
1006
|
|
|
1228
|
-
// src/api/routes/
|
|
1229
|
-
var
|
|
1230
|
-
async function
|
|
1231
|
-
const { info } = Logger(
|
|
1232
|
-
{ ...config, debug: config.debug },
|
|
1233
|
-
`[ROUTES][${key2}]`
|
|
1234
|
-
);
|
|
1235
|
-
const session = await auth(request2, config);
|
|
1007
|
+
// src/api/routes/signup/index.tsx
|
|
1008
|
+
var key11 = "SIGNUP";
|
|
1009
|
+
async function route14(request2, config) {
|
|
1236
1010
|
switch (request2.method) {
|
|
1237
|
-
case "GET":
|
|
1238
|
-
return await GET2(config, { request: request2 }, info);
|
|
1239
1011
|
case "POST":
|
|
1240
|
-
return await
|
|
1241
|
-
case "PUT":
|
|
1242
|
-
return await PUT(config, session, { request: request2 });
|
|
1012
|
+
return await POST4(config, { request: request2 });
|
|
1243
1013
|
default:
|
|
1244
1014
|
return new Response("method not allowed", { status: 405 });
|
|
1245
1015
|
}
|
|
1246
1016
|
}
|
|
1247
|
-
function
|
|
1248
|
-
return urlMatches(request2.url, configRoutes[
|
|
1017
|
+
function matches14(configRoutes, request2) {
|
|
1018
|
+
return urlMatches(request2.url, configRoutes[key11]);
|
|
1249
1019
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1020
|
+
async function fetchSignUp(config, payload) {
|
|
1021
|
+
const { body, params } = payload ?? {};
|
|
1022
|
+
const q = new URLSearchParams();
|
|
1023
|
+
if (params?.newTenantName) {
|
|
1024
|
+
q.set("newTenantName", params.newTenantName);
|
|
1025
|
+
}
|
|
1026
|
+
if (params?.tenantId) {
|
|
1027
|
+
q.set("tenantId", params.tenantId);
|
|
1028
|
+
}
|
|
1029
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/signup" /* SIGNUP */}${q.size > 0 ? `?${q}` : ""}`;
|
|
1030
|
+
const req = new Request(clientUrl, {
|
|
1031
|
+
method: "POST",
|
|
1032
|
+
headers: config.headers,
|
|
1033
|
+
body
|
|
1034
|
+
});
|
|
1035
|
+
return await config.handlers.POST(req);
|
|
1257
1036
|
}
|
|
1258
1037
|
|
|
1259
|
-
// src/api/
|
|
1260
|
-
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1038
|
+
// src/api/handlers/POST.ts
|
|
1039
|
+
function POSTER(configRoutes, config) {
|
|
1040
|
+
const { info, warn, error } = Logger(config, "[POST MATCHER]");
|
|
1041
|
+
return async function POST5(req) {
|
|
1042
|
+
if (matchesLog(configRoutes, req)) {
|
|
1043
|
+
if (req.body) {
|
|
1044
|
+
try {
|
|
1045
|
+
const text = await req.text();
|
|
1046
|
+
error(text);
|
|
1047
|
+
return new Response(null, {
|
|
1048
|
+
status: 200
|
|
1049
|
+
});
|
|
1050
|
+
} catch (e) {
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
if (matches3(configRoutes, req)) {
|
|
1055
|
+
info("matches tenant users");
|
|
1056
|
+
return route3(req, config);
|
|
1057
|
+
}
|
|
1058
|
+
if (matches14(configRoutes, req)) {
|
|
1059
|
+
info("matches signup");
|
|
1060
|
+
return route14(req, config);
|
|
1061
|
+
}
|
|
1062
|
+
if (matches2(configRoutes, req)) {
|
|
1063
|
+
info("matches users");
|
|
1064
|
+
return route2(req, config);
|
|
1065
|
+
}
|
|
1066
|
+
if (matches4(configRoutes, req)) {
|
|
1067
|
+
info("matches tenants");
|
|
1068
|
+
return route4(req, config);
|
|
1069
|
+
}
|
|
1070
|
+
if (matches6(configRoutes, req)) {
|
|
1071
|
+
info("matches session");
|
|
1072
|
+
return route6(req, config);
|
|
1073
|
+
}
|
|
1074
|
+
if (matches5(configRoutes, req)) {
|
|
1075
|
+
info("matches signin");
|
|
1076
|
+
return route5(req, config);
|
|
1077
|
+
}
|
|
1078
|
+
if (matches13(configRoutes, req)) {
|
|
1079
|
+
info("matches password reset");
|
|
1080
|
+
return route13(req, config);
|
|
1081
|
+
}
|
|
1082
|
+
if (matches7(configRoutes, req)) {
|
|
1083
|
+
info("matches providers");
|
|
1084
|
+
return route7(req, config);
|
|
1085
|
+
}
|
|
1086
|
+
if (matches8(configRoutes, req)) {
|
|
1087
|
+
info("matches csrf");
|
|
1088
|
+
return route8(req, config);
|
|
1089
|
+
}
|
|
1090
|
+
if (matches9(configRoutes, req)) {
|
|
1091
|
+
info("matches callback");
|
|
1092
|
+
return route9(req, config);
|
|
1093
|
+
}
|
|
1094
|
+
if (matches10(configRoutes, req)) {
|
|
1095
|
+
info("matches signout");
|
|
1096
|
+
return route10(req, config);
|
|
1097
|
+
}
|
|
1098
|
+
warn(`No POST routes matched ${req.url}`);
|
|
1099
|
+
return new Response(null, { status: 404 });
|
|
1100
|
+
};
|
|
1267
1101
|
}
|
|
1268
1102
|
|
|
1269
1103
|
// src/api/routes/tenants/[tenantId]/users/[userId]/DELETE.ts
|
|
1270
|
-
async function
|
|
1104
|
+
async function DELETE3(config, init) {
|
|
1271
1105
|
const yurl = new URL(init.request.url);
|
|
1272
|
-
const [userId,
|
|
1106
|
+
const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
|
|
1107
|
+
config.tenantId = tenantId;
|
|
1108
|
+
config.userId = userId;
|
|
1273
1109
|
init.method = "DELETE";
|
|
1274
|
-
|
|
1275
|
-
const url = `${apiRoutes(config).TENANT_USER(tenantId, userId)}`;
|
|
1110
|
+
const url = `${apiRoutes(config).TENANT_USER}/link`;
|
|
1276
1111
|
return await request(url, init, config);
|
|
1277
1112
|
}
|
|
1278
1113
|
|
|
1279
|
-
// src/api/routes/tenants/[tenantId]/users/PUT.ts
|
|
1280
|
-
async function
|
|
1114
|
+
// src/api/routes/tenants/[tenantId]/users/[userId]/PUT.ts
|
|
1115
|
+
async function PUT4(config, init) {
|
|
1281
1116
|
const yurl = new URL(init.request.url);
|
|
1282
|
-
const [, tenantId] = yurl.pathname.split("/").reverse();
|
|
1117
|
+
const [, userId, , tenantId] = yurl.pathname.split("/").reverse();
|
|
1118
|
+
config.tenantId = tenantId;
|
|
1119
|
+
config.userId = userId;
|
|
1283
1120
|
init.method = "PUT";
|
|
1284
|
-
const url = `${apiRoutes(config).
|
|
1121
|
+
const url = `${apiRoutes(config).TENANT_USER}/link`;
|
|
1285
1122
|
return await request(url, init, config);
|
|
1286
1123
|
}
|
|
1287
1124
|
|
|
1288
|
-
// src/api/routes/tenants/[tenantId]/users/index.ts
|
|
1289
|
-
var
|
|
1290
|
-
async function
|
|
1125
|
+
// src/api/routes/tenants/[tenantId]/users/[userId]/index.ts
|
|
1126
|
+
var key12 = "TENANT_USER";
|
|
1127
|
+
async function route15(request2, config) {
|
|
1291
1128
|
const { info } = Logger(
|
|
1292
1129
|
{ ...config, debug: config.debug },
|
|
1293
|
-
`[ROUTES][${
|
|
1130
|
+
`[ROUTES][${key12}]`
|
|
1294
1131
|
);
|
|
1295
1132
|
const session = await auth(request2, config);
|
|
1296
1133
|
if (!session) {
|
|
@@ -1298,1140 +1135,1082 @@ async function route3(request2, config) {
|
|
|
1298
1135
|
return new Response(null, { status: 401 });
|
|
1299
1136
|
}
|
|
1300
1137
|
const yurl = new URL(request2.url);
|
|
1301
|
-
const [,
|
|
1302
|
-
if (!
|
|
1138
|
+
const [, userId] = yurl.pathname.split("/").reverse();
|
|
1139
|
+
if (!userId) {
|
|
1303
1140
|
info("No tenant id found in path");
|
|
1304
1141
|
return new Response(null, { status: 404 });
|
|
1305
1142
|
}
|
|
1306
1143
|
switch (request2.method) {
|
|
1307
|
-
case "GET":
|
|
1308
|
-
return await GET3(config, { request: request2 });
|
|
1309
|
-
case "POST":
|
|
1310
|
-
return await POST2(config, session, { request: request2 });
|
|
1311
1144
|
case "PUT":
|
|
1312
|
-
return await
|
|
1145
|
+
return await PUT4(config, { request: request2 });
|
|
1313
1146
|
case "DELETE":
|
|
1314
|
-
return await
|
|
1147
|
+
return await DELETE3(config, { request: request2 });
|
|
1315
1148
|
default:
|
|
1316
1149
|
return new Response("method not allowed", { status: 405 });
|
|
1317
1150
|
}
|
|
1318
1151
|
}
|
|
1319
|
-
function
|
|
1152
|
+
function matches15(configRoutes, request2) {
|
|
1320
1153
|
const url = new URL(request2.url);
|
|
1321
|
-
const [userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
|
|
1322
|
-
let
|
|
1154
|
+
const [, userId, possibleTenantId, tenantId] = url.pathname.split("/").reverse();
|
|
1155
|
+
let route16 = configRoutes[key12].replace("{tenantId}", tenantId).replace("{userId}", userId);
|
|
1323
1156
|
if (userId === "users") {
|
|
1324
|
-
|
|
1157
|
+
route16 = configRoutes[key12].replace("{tenantId}", possibleTenantId);
|
|
1325
1158
|
}
|
|
1326
|
-
return urlMatches(request2.url,
|
|
1159
|
+
return urlMatches(request2.url, route16);
|
|
1327
1160
|
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
url = `${apiRoutes(config).USER_TENANTS(session.user.id)}`;
|
|
1161
|
+
async function fetchTenantUser(config, method) {
|
|
1162
|
+
if (!config.tenantId) {
|
|
1163
|
+
throw new Error(
|
|
1164
|
+
"The tenantId context is missing. Call nile.setContext({ tenantId })"
|
|
1165
|
+
);
|
|
1334
1166
|
}
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
// src/api/routes/tenants/[tenantId]/GET.ts
|
|
1340
|
-
async function GET5(config, init, log) {
|
|
1341
|
-
const yurl = new URL(init.request.url);
|
|
1342
|
-
const [tenantId] = yurl.pathname.split("/").reverse();
|
|
1343
|
-
if (!tenantId) {
|
|
1344
|
-
log("[GET] No tenant id provided.");
|
|
1345
|
-
return new Response(null, { status: 404 });
|
|
1167
|
+
if (!config.userId) {
|
|
1168
|
+
throw new Error(
|
|
1169
|
+
"the userId context is missing. Call nile.setContext({ userId })"
|
|
1170
|
+
);
|
|
1346
1171
|
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1172
|
+
const clientUrl = `${config.origin}${config.routePrefix}${"/tenants/{tenantId}/users/{userId}" /* TENANT_USER */.replace(
|
|
1173
|
+
"{tenantId}",
|
|
1174
|
+
config.tenantId
|
|
1175
|
+
).replace("{userId}", config.userId)}/link`;
|
|
1176
|
+
const req = new Request(clientUrl, {
|
|
1177
|
+
headers: config.headers,
|
|
1178
|
+
method
|
|
1179
|
+
});
|
|
1180
|
+
return await config.handlers[method](req);
|
|
1350
1181
|
}
|
|
1351
1182
|
|
|
1352
|
-
// src/api/
|
|
1353
|
-
|
|
1354
|
-
const
|
|
1355
|
-
|
|
1356
|
-
|
|
1183
|
+
// src/api/handlers/DELETE.ts
|
|
1184
|
+
function DELETER(configRoutes, config) {
|
|
1185
|
+
const { info, warn } = Logger(config, "[DELETE MATCHER]");
|
|
1186
|
+
return async function DELETE4(req) {
|
|
1187
|
+
if (matches15(configRoutes, req)) {
|
|
1188
|
+
info("matches tenant user");
|
|
1189
|
+
return route15(req, config);
|
|
1190
|
+
}
|
|
1191
|
+
if (matches3(configRoutes, req)) {
|
|
1192
|
+
info("matches tenant users");
|
|
1193
|
+
return route3(req, config);
|
|
1194
|
+
}
|
|
1195
|
+
if (matches4(configRoutes, req)) {
|
|
1196
|
+
info("matches tenants");
|
|
1197
|
+
return route4(req, config);
|
|
1198
|
+
}
|
|
1199
|
+
if (matches(configRoutes, req)) {
|
|
1200
|
+
info("matches me");
|
|
1201
|
+
return route(req, config);
|
|
1202
|
+
}
|
|
1203
|
+
warn("No DELETE routes matched");
|
|
1357
1204
|
return new Response(null, { status: 404 });
|
|
1358
|
-
}
|
|
1359
|
-
init.method = "DELETE";
|
|
1360
|
-
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
1361
|
-
return await request(url, init, config);
|
|
1205
|
+
};
|
|
1362
1206
|
}
|
|
1363
1207
|
|
|
1364
|
-
// src/api/
|
|
1365
|
-
|
|
1366
|
-
const
|
|
1367
|
-
|
|
1368
|
-
|
|
1208
|
+
// src/api/handlers/PUT.ts
|
|
1209
|
+
function PUTER(configRoutes, config) {
|
|
1210
|
+
const { info, warn } = Logger(config, "[PUT MATCHER]");
|
|
1211
|
+
return async function PUT5(req) {
|
|
1212
|
+
if (matches15(configRoutes, req)) {
|
|
1213
|
+
info("matches tenant user");
|
|
1214
|
+
return route15(req, config);
|
|
1215
|
+
}
|
|
1216
|
+
if (matches3(configRoutes, req)) {
|
|
1217
|
+
info("matches tenant users");
|
|
1218
|
+
return route3(req, config);
|
|
1219
|
+
}
|
|
1220
|
+
if (matches2(configRoutes, req)) {
|
|
1221
|
+
info("matches users");
|
|
1222
|
+
return route2(req, config);
|
|
1223
|
+
}
|
|
1224
|
+
if (matches(configRoutes, req)) {
|
|
1225
|
+
info("matches me");
|
|
1226
|
+
return route(req, config);
|
|
1227
|
+
}
|
|
1228
|
+
if (matches4(configRoutes, req)) {
|
|
1229
|
+
info("matches tenants");
|
|
1230
|
+
return route4(req, config);
|
|
1231
|
+
}
|
|
1232
|
+
if (matches13(configRoutes, req)) {
|
|
1233
|
+
info("matches reset password");
|
|
1234
|
+
return route13(req, config);
|
|
1235
|
+
}
|
|
1236
|
+
warn("No PUT routes matched");
|
|
1369
1237
|
return new Response(null, { status: 404 });
|
|
1370
|
-
}
|
|
1371
|
-
init.body = init.request.body;
|
|
1372
|
-
init.method = "PUT";
|
|
1373
|
-
const url = `${apiRoutes(config).TENANT(tenantId)}`;
|
|
1374
|
-
return await request(url, init, config);
|
|
1238
|
+
};
|
|
1375
1239
|
}
|
|
1376
1240
|
|
|
1377
|
-
// src/api/
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
const
|
|
1382
|
-
|
|
1241
|
+
// src/api/handlers/index.ts
|
|
1242
|
+
function Handlers(configRoutes, config) {
|
|
1243
|
+
const GET6 = GETTER(configRoutes, config);
|
|
1244
|
+
const POST5 = POSTER(configRoutes, config);
|
|
1245
|
+
const DELETE4 = DELETER(configRoutes, config);
|
|
1246
|
+
const PUT5 = PUTER(configRoutes, config);
|
|
1247
|
+
return {
|
|
1248
|
+
GET: GET6,
|
|
1249
|
+
POST: POST5,
|
|
1250
|
+
DELETE: DELETE4,
|
|
1251
|
+
PUT: PUT5
|
|
1252
|
+
};
|
|
1383
1253
|
}
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
return false;
|
|
1254
|
+
var getApiUrl = (cfg) => {
|
|
1255
|
+
const { config } = cfg;
|
|
1256
|
+
if (config?.apiUrl != null) {
|
|
1257
|
+
return config?.apiUrl;
|
|
1389
1258
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
const { info } = Logger(
|
|
1396
|
-
{ ...config, debug: config.debug },
|
|
1397
|
-
`[ROUTES][${key4}]`
|
|
1259
|
+
if (stringCheck(process.env.NILEDB_API_URL)) {
|
|
1260
|
+
return process.env.NILEDB_API_URL;
|
|
1261
|
+
}
|
|
1262
|
+
throw new Error(
|
|
1263
|
+
"A connection to nile-auth is required. Set NILEDB_API_URL as an environment variable."
|
|
1398
1264
|
);
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1265
|
+
};
|
|
1266
|
+
var getCallbackUrl = (cfg) => {
|
|
1267
|
+
const { config } = cfg;
|
|
1268
|
+
if (stringCheck(config?.callbackUrl)) {
|
|
1269
|
+
return config?.callbackUrl;
|
|
1403
1270
|
}
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
return await GET4(config, session, { request: request2 });
|
|
1411
|
-
case "POST":
|
|
1412
|
-
return await POST3(config, { request: request2 });
|
|
1413
|
-
case "DELETE":
|
|
1414
|
-
return await DELETE2(config, { request: request2 });
|
|
1415
|
-
case "PUT":
|
|
1416
|
-
return await PUT3(config, { request: request2 });
|
|
1417
|
-
default:
|
|
1418
|
-
return new Response("method not allowed", { status: 405 });
|
|
1271
|
+
return process.env.NILEDB_CALLBACK_URL;
|
|
1272
|
+
};
|
|
1273
|
+
var getSecureCookies = (cfg) => {
|
|
1274
|
+
const { config } = cfg;
|
|
1275
|
+
if (config?.secureCookies != null) {
|
|
1276
|
+
return config?.secureCookies;
|
|
1419
1277
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
return urlMatches(request2.url, configRoutes[key4]);
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
// src/api/utils/routes/proxyRoutes.ts
|
|
1426
|
-
var proxyRoutes = (config) => ({
|
|
1427
|
-
SIGNIN: makeRestUrl(config, "/auth/signin"),
|
|
1428
|
-
PROVIDERS: makeRestUrl(config, "/auth/providers"),
|
|
1429
|
-
SESSION: makeRestUrl(config, "/auth/session"),
|
|
1430
|
-
CSRF: makeRestUrl(config, "/auth/csrf"),
|
|
1431
|
-
CALLBACK: makeRestUrl(config, "/auth/callback"),
|
|
1432
|
-
SIGNOUT: makeRestUrl(config, "/auth/signout"),
|
|
1433
|
-
ERROR: makeRestUrl(config, "/auth/error"),
|
|
1434
|
-
VERIFY_REQUEST: makeRestUrl(config, "/auth/verify-request"),
|
|
1435
|
-
PASSWORD_RESET: makeRestUrl(config, "/auth/reset-password")
|
|
1436
|
-
});
|
|
1437
|
-
|
|
1438
|
-
// src/api/routes/auth/signin.ts
|
|
1439
|
-
var key5 = "SIGNIN";
|
|
1440
|
-
async function route5(req, config) {
|
|
1441
|
-
let url = proxyRoutes(config)[key5];
|
|
1442
|
-
const init = {
|
|
1443
|
-
method: req.method,
|
|
1444
|
-
headers: req.headers
|
|
1445
|
-
};
|
|
1446
|
-
if (req.method === "POST") {
|
|
1447
|
-
const [provider] = new URL(req.url).pathname.split("/").reverse();
|
|
1448
|
-
url = `${proxyRoutes(config)[key5]}/${provider}`;
|
|
1278
|
+
if (stringCheck(process.env.NILEDB_SECURECOOKIES)) {
|
|
1279
|
+
return Boolean(process.env.NILEDB_SECURECOOKIES);
|
|
1449
1280
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
const
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1281
|
+
return void 0;
|
|
1282
|
+
};
|
|
1283
|
+
var getUsername = (cfg) => {
|
|
1284
|
+
const { config, logger } = cfg;
|
|
1285
|
+
const { info } = Logger(config, "[username]");
|
|
1286
|
+
if (config?.user) {
|
|
1287
|
+
logger && info(`${logger}[config] ${config.user}`);
|
|
1288
|
+
return String(config?.user);
|
|
1289
|
+
}
|
|
1290
|
+
const user = stringCheck(process.env.NILEDB_USER);
|
|
1291
|
+
if (user) {
|
|
1292
|
+
logger && info(`${logger}[NILEDB_USER] ${user}`);
|
|
1293
|
+
return user;
|
|
1294
|
+
}
|
|
1295
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
1296
|
+
if (pg2) {
|
|
1297
|
+
try {
|
|
1298
|
+
const url = new URL(pg2);
|
|
1299
|
+
if (url.username) {
|
|
1300
|
+
return url.username;
|
|
1301
|
+
}
|
|
1302
|
+
} catch (e) {
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
throw new Error(
|
|
1306
|
+
"A database user is required. Set NILEDB_USER as an environment variable."
|
|
1469
1307
|
);
|
|
1470
|
-
}
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1308
|
+
};
|
|
1309
|
+
var getPassword = (cfg) => {
|
|
1310
|
+
const { config, logger } = cfg;
|
|
1311
|
+
const log = logProtector(logger);
|
|
1312
|
+
const { info } = Logger(config, "[password]");
|
|
1313
|
+
if (stringCheck(config?.password)) {
|
|
1314
|
+
log && info(`${logger}[config] ***`);
|
|
1315
|
+
return String(config?.password);
|
|
1316
|
+
}
|
|
1317
|
+
const pass = stringCheck(process.env.NILEDB_PASSWORD);
|
|
1318
|
+
if (pass) {
|
|
1319
|
+
logger && info(`${logger}[NILEDB_PASSWORD] ***`);
|
|
1320
|
+
return pass;
|
|
1321
|
+
}
|
|
1322
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
1323
|
+
if (pg2) {
|
|
1324
|
+
try {
|
|
1325
|
+
const url = new URL(pg2);
|
|
1326
|
+
if (url.password) {
|
|
1327
|
+
return url.password;
|
|
1328
|
+
}
|
|
1329
|
+
} catch (e) {
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
throw new Error(
|
|
1333
|
+
"A database password is required. Set NILEDB_PASSWORD as an environment variable."
|
|
1484
1334
|
);
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
async function route9(req, config) {
|
|
1508
|
-
const { error } = Logger(
|
|
1509
|
-
{ ...config, debug: config.debug },
|
|
1510
|
-
`[ROUTES][${key6}]`
|
|
1335
|
+
};
|
|
1336
|
+
var getDatabaseName = (cfg) => {
|
|
1337
|
+
const { config, logger } = cfg;
|
|
1338
|
+
const { info } = Logger(config, "[databaseName]");
|
|
1339
|
+
if (stringCheck(config?.databaseName)) {
|
|
1340
|
+
logger && info(`${logger}[config] ${config?.databaseName}`);
|
|
1341
|
+
return String(config?.databaseName);
|
|
1342
|
+
}
|
|
1343
|
+
const name = stringCheck(process.env.NILEDB_NAME);
|
|
1344
|
+
if (name) {
|
|
1345
|
+
logger && info(`${logger}[NILEDB_NAME] ${name}`);
|
|
1346
|
+
return name;
|
|
1347
|
+
}
|
|
1348
|
+
if (process.env.NILEDB_POSTGRES_URL) {
|
|
1349
|
+
try {
|
|
1350
|
+
const pgUrl = new URL(process.env.NILEDB_POSTGRES_URL);
|
|
1351
|
+
return pgUrl.pathname.substring(1);
|
|
1352
|
+
} catch (e) {
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
throw new Error(
|
|
1356
|
+
"A database name is required. Set NILEDB_PASSWORD as an environment variable."
|
|
1511
1357
|
);
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1358
|
+
};
|
|
1359
|
+
var getTenantId = (cfg) => {
|
|
1360
|
+
const { config, logger } = cfg;
|
|
1361
|
+
const { info } = Logger(config, "[tenantId]");
|
|
1362
|
+
if (stringCheck(config?.tenantId)) {
|
|
1363
|
+
logger && info(`${logger}[config] ${config?.tenantId}`);
|
|
1364
|
+
return String(config?.tenantId);
|
|
1365
|
+
}
|
|
1366
|
+
if (stringCheck(process.env.NILEDB_TENANT)) {
|
|
1367
|
+
logger && info(`${logger}[NILEDB_TENANT] ${process.env.NILEDB_TENANT}`);
|
|
1368
|
+
return String(process.env.NILEDB_TENANT);
|
|
1369
|
+
}
|
|
1370
|
+
return null;
|
|
1371
|
+
};
|
|
1372
|
+
function getDbHost(cfg) {
|
|
1373
|
+
const { config, logger } = cfg;
|
|
1374
|
+
const { info } = Logger(config, "[db.host]");
|
|
1375
|
+
if (stringCheck(config?.db && config.db.host)) {
|
|
1376
|
+
logger && info(`${logger}[config] ${config?.db?.host}`);
|
|
1377
|
+
return String(config?.db?.host);
|
|
1378
|
+
}
|
|
1379
|
+
if (stringCheck(process.env.NILEDB_HOST)) {
|
|
1380
|
+
logger && info(`${logger}[NILEDB_HOST] ${process.env.NILEDB_HOST}`);
|
|
1381
|
+
return process.env.NILEDB_HOST;
|
|
1382
|
+
}
|
|
1383
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
1384
|
+
if (pg2) {
|
|
1385
|
+
try {
|
|
1386
|
+
const pgUrl = new URL(pg2);
|
|
1387
|
+
logger && info(`${logger}[NILEDB_POSTGRES_URL] ${pgUrl.hostname}`);
|
|
1388
|
+
return pgUrl.hostname;
|
|
1389
|
+
} catch (e) {
|
|
1533
1390
|
}
|
|
1534
|
-
return new Response(res?.body, {
|
|
1535
|
-
status: res?.status,
|
|
1536
|
-
headers: res?.headers
|
|
1537
|
-
});
|
|
1538
|
-
} catch (e) {
|
|
1539
|
-
error(e);
|
|
1540
1391
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
function matches9(configRoutes, request2) {
|
|
1544
|
-
return urlMatches(request2.url, configRoutes.CALLBACK);
|
|
1392
|
+
logger && info(`${logger}[default] db.thenile.dev`);
|
|
1393
|
+
return "db.thenile.dev";
|
|
1545
1394
|
}
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
method: request2.method
|
|
1553
|
-
};
|
|
1554
|
-
if (request2.method === "POST") {
|
|
1555
|
-
init.body = request2.body;
|
|
1556
|
-
const [provider] = new URL(request2.url).pathname.split("/").reverse();
|
|
1557
|
-
url = `${proxyRoutes(config)[key7]}${provider !== "signout" ? `/${provider}` : ""}`;
|
|
1395
|
+
function getDbPort(cfg) {
|
|
1396
|
+
const { config, logger } = cfg;
|
|
1397
|
+
const { info } = Logger(config, "[db.port]");
|
|
1398
|
+
if (config?.db?.port && config.db.port != null) {
|
|
1399
|
+
logger && info(`${logger}[config] ${config?.db.port}`);
|
|
1400
|
+
return Number(config.db?.port);
|
|
1558
1401
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
function matches10(configRoutes, request2) {
|
|
1563
|
-
return urlMatches(request2.url, configRoutes[key7]);
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
// src/api/routes/auth/error.ts
|
|
1567
|
-
var key8 = "ERROR";
|
|
1568
|
-
async function route11(req, config) {
|
|
1569
|
-
return request(
|
|
1570
|
-
proxyRoutes(config)[key8],
|
|
1571
|
-
{
|
|
1572
|
-
method: req.method,
|
|
1573
|
-
request: req
|
|
1574
|
-
},
|
|
1575
|
-
config
|
|
1576
|
-
);
|
|
1577
|
-
}
|
|
1578
|
-
function matches11(configRoutes, request2) {
|
|
1579
|
-
return urlMatches(request2.url, configRoutes[key8]);
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
// src/api/routes/auth/verify-request.ts
|
|
1583
|
-
var key9 = "VERIFY_REQUEST";
|
|
1584
|
-
async function route12(req, config) {
|
|
1585
|
-
return request(
|
|
1586
|
-
proxyRoutes(config)[key9],
|
|
1587
|
-
{
|
|
1588
|
-
method: req.method,
|
|
1589
|
-
request: req
|
|
1590
|
-
},
|
|
1591
|
-
config
|
|
1592
|
-
);
|
|
1593
|
-
}
|
|
1594
|
-
function matches12(configRoutes, request2) {
|
|
1595
|
-
return urlMatches(request2.url, configRoutes[key9]);
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
// src/api/routes/auth/password-reset.ts
|
|
1599
|
-
var key10 = "PASSWORD_RESET";
|
|
1600
|
-
async function route13(req, config) {
|
|
1601
|
-
const url = proxyRoutes(config)[key10];
|
|
1602
|
-
const res = await request(
|
|
1603
|
-
url,
|
|
1604
|
-
{
|
|
1605
|
-
method: req.method,
|
|
1606
|
-
request: req
|
|
1607
|
-
},
|
|
1608
|
-
config
|
|
1609
|
-
);
|
|
1610
|
-
const location = res?.headers.get("location");
|
|
1611
|
-
if (location) {
|
|
1612
|
-
return new Response(res?.body, {
|
|
1613
|
-
status: 302,
|
|
1614
|
-
headers: res?.headers
|
|
1615
|
-
});
|
|
1402
|
+
if (stringCheck(process.env.NILEDB_PORT)) {
|
|
1403
|
+
logger && info(`${logger}[NILEDB_PORT] ${process.env.NILEDB_PORT}`);
|
|
1404
|
+
return Number(process.env.NILEDB_PORT);
|
|
1616
1405
|
}
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1406
|
+
const pg2 = stringCheck(process.env.NILEDB_POSTGRES_URL);
|
|
1407
|
+
if (pg2) {
|
|
1408
|
+
try {
|
|
1409
|
+
const pgUrl = new URL(pg2);
|
|
1410
|
+
if (pgUrl.port) {
|
|
1411
|
+
return Number(pgUrl.port);
|
|
1412
|
+
}
|
|
1413
|
+
} catch (e) {
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
logger && info(`${logger}[default] 5432`);
|
|
1417
|
+
return 5432;
|
|
1624
1418
|
}
|
|
1419
|
+
var logProtector = (logger) => {
|
|
1420
|
+
return process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test" ? logger : null;
|
|
1421
|
+
};
|
|
1422
|
+
var stringCheck = (str) => {
|
|
1423
|
+
if (str && str !== "") {
|
|
1424
|
+
return str;
|
|
1425
|
+
}
|
|
1426
|
+
return;
|
|
1427
|
+
};
|
|
1625
1428
|
|
|
1626
|
-
// src/
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1429
|
+
// src/utils/Config/index.ts
|
|
1430
|
+
var Config = class {
|
|
1431
|
+
routes;
|
|
1432
|
+
// handlersWithContext;
|
|
1433
|
+
handlers;
|
|
1434
|
+
paths;
|
|
1435
|
+
logger;
|
|
1436
|
+
/**
|
|
1437
|
+
* Stores the set tenant id from Server for use in sub classes
|
|
1438
|
+
*/
|
|
1439
|
+
tenantId;
|
|
1440
|
+
/**
|
|
1441
|
+
* Stores the set user id from Server for use in sub classes
|
|
1442
|
+
*/
|
|
1443
|
+
userId;
|
|
1444
|
+
/**
|
|
1445
|
+
* Stores the headers to be used in `fetch` calls
|
|
1446
|
+
*/
|
|
1447
|
+
headers;
|
|
1448
|
+
/**
|
|
1449
|
+
* The nile-auth url
|
|
1450
|
+
*/
|
|
1451
|
+
apiUrl;
|
|
1452
|
+
origin;
|
|
1453
|
+
debug;
|
|
1454
|
+
/**
|
|
1455
|
+
* To use secure cookies or not in the fetch
|
|
1456
|
+
*/
|
|
1457
|
+
secureCookies;
|
|
1458
|
+
callbackUrl;
|
|
1459
|
+
/**
|
|
1460
|
+
* change the starting route
|
|
1461
|
+
*/
|
|
1462
|
+
routePrefix;
|
|
1463
|
+
db;
|
|
1464
|
+
// api: ApiConfig;
|
|
1465
|
+
constructor(config, logger) {
|
|
1466
|
+
const envVarConfig = { config, logger };
|
|
1467
|
+
this.routePrefix = config?.routePrefix ?? "/api";
|
|
1468
|
+
this.secureCookies = getSecureCookies(envVarConfig);
|
|
1469
|
+
this.callbackUrl = getCallbackUrl(envVarConfig);
|
|
1470
|
+
this.debug = config?.debug;
|
|
1471
|
+
this.origin = config?.origin ?? "http://localhost:3000";
|
|
1472
|
+
this.apiUrl = getApiUrl(envVarConfig);
|
|
1473
|
+
const user = getUsername(envVarConfig);
|
|
1474
|
+
const password = getPassword(envVarConfig);
|
|
1475
|
+
const databaseName = getDatabaseName(envVarConfig);
|
|
1476
|
+
const { host, port, ...dbConfig } = config?.db ?? {};
|
|
1477
|
+
const configuredHost = host ?? getDbHost(envVarConfig);
|
|
1478
|
+
const configuredPort = port ?? getDbPort(envVarConfig);
|
|
1479
|
+
this.db = {
|
|
1480
|
+
user,
|
|
1481
|
+
password,
|
|
1482
|
+
host: configuredHost,
|
|
1483
|
+
port: configuredPort,
|
|
1484
|
+
...dbConfig
|
|
1485
|
+
};
|
|
1486
|
+
if (databaseName) {
|
|
1487
|
+
this.db.database = databaseName;
|
|
1677
1488
|
}
|
|
1678
|
-
if (
|
|
1679
|
-
|
|
1680
|
-
|
|
1489
|
+
if (config?.headers) {
|
|
1490
|
+
this.headers = config?.headers;
|
|
1491
|
+
} else {
|
|
1492
|
+
this.headers = new Headers();
|
|
1681
1493
|
}
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
}
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1494
|
+
this.routes = {
|
|
1495
|
+
...appRoutes(config?.routePrefix),
|
|
1496
|
+
...config?.routes
|
|
1497
|
+
};
|
|
1498
|
+
this.handlers = Handlers(this.routes, this);
|
|
1499
|
+
this.paths = {
|
|
1500
|
+
get: [
|
|
1501
|
+
this.routes.ME,
|
|
1502
|
+
this.routes.TENANT_USERS,
|
|
1503
|
+
this.routes.TENANTS,
|
|
1504
|
+
this.routes.TENANT,
|
|
1505
|
+
this.routes.SESSION,
|
|
1506
|
+
this.routes.SIGNIN,
|
|
1507
|
+
this.routes.PROVIDERS,
|
|
1508
|
+
this.routes.CSRF,
|
|
1509
|
+
this.routes.PASSWORD_RESET,
|
|
1510
|
+
this.routes.CALLBACK,
|
|
1511
|
+
this.routes.SIGNOUT,
|
|
1512
|
+
this.routes.VERIFY_REQUEST,
|
|
1513
|
+
this.routes.ERROR
|
|
1514
|
+
],
|
|
1515
|
+
post: [
|
|
1516
|
+
this.routes.TENANT_USERS,
|
|
1517
|
+
this.routes.SIGNUP,
|
|
1518
|
+
this.routes.USERS,
|
|
1519
|
+
this.routes.TENANTS,
|
|
1520
|
+
this.routes.SESSION,
|
|
1521
|
+
`${this.routes.SIGNIN}/{provider}`,
|
|
1522
|
+
this.routes.PASSWORD_RESET,
|
|
1523
|
+
this.routes.PROVIDERS,
|
|
1524
|
+
this.routes.CSRF,
|
|
1525
|
+
`${this.routes.CALLBACK}/{provider}`,
|
|
1526
|
+
this.routes.SIGNOUT
|
|
1527
|
+
],
|
|
1528
|
+
put: [
|
|
1529
|
+
this.routes.TENANT_USERS,
|
|
1530
|
+
this.routes.USERS,
|
|
1531
|
+
this.routes.TENANT,
|
|
1532
|
+
this.routes.PASSWORD_RESET
|
|
1533
|
+
],
|
|
1534
|
+
delete: [this.routes.TENANT_USER, this.routes.TENANT]
|
|
1535
|
+
};
|
|
1536
|
+
this.tenantId = config?.tenantId;
|
|
1537
|
+
this.userId = config?.userId;
|
|
1538
|
+
this.logger = config?.logger;
|
|
1703
1539
|
}
|
|
1704
|
-
}
|
|
1705
|
-
function matches14(configRoutes, request2) {
|
|
1706
|
-
return urlMatches(request2.url, configRoutes[key11]);
|
|
1707
|
-
}
|
|
1540
|
+
};
|
|
1708
1541
|
|
|
1709
|
-
// src/
|
|
1710
|
-
function
|
|
1711
|
-
const { info,
|
|
1712
|
-
return
|
|
1713
|
-
|
|
1714
|
-
if (
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
})
|
|
1721
|
-
|
|
1542
|
+
// src/db/PoolProxy.ts
|
|
1543
|
+
function createProxyForPool(pool, config) {
|
|
1544
|
+
const { info, error } = Logger(config, "[pool]");
|
|
1545
|
+
return new Proxy(pool, {
|
|
1546
|
+
get(target, property) {
|
|
1547
|
+
if (property === "query") {
|
|
1548
|
+
if (!config.db.connectionString) {
|
|
1549
|
+
if (!config.db.user || !config.db.password) {
|
|
1550
|
+
error(
|
|
1551
|
+
"Cannot connect to the database. User and/or password are missing. Generate them at https://console.thenile.dev"
|
|
1552
|
+
);
|
|
1553
|
+
} else if (!config.db.database) {
|
|
1554
|
+
error(
|
|
1555
|
+
"Unable to obtain database name. Is process.env.NILEDB_POSTGRES_URL set?"
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1722
1558
|
}
|
|
1559
|
+
const caller = target[property];
|
|
1560
|
+
return function query(...args) {
|
|
1561
|
+
info("query", ...args);
|
|
1562
|
+
const called = caller.apply(this, args);
|
|
1563
|
+
return called;
|
|
1564
|
+
};
|
|
1723
1565
|
}
|
|
1566
|
+
return target[property];
|
|
1724
1567
|
}
|
|
1725
|
-
|
|
1726
|
-
info("matches tenant users");
|
|
1727
|
-
return route3(req, config);
|
|
1728
|
-
}
|
|
1729
|
-
if (matches14(configRoutes, req)) {
|
|
1730
|
-
info("matches signup");
|
|
1731
|
-
return route14(req, config);
|
|
1732
|
-
}
|
|
1733
|
-
if (matches2(configRoutes, req)) {
|
|
1734
|
-
info("matches users");
|
|
1735
|
-
return route2(req, config);
|
|
1736
|
-
}
|
|
1737
|
-
if (matches4(configRoutes, req)) {
|
|
1738
|
-
info("matches tenants");
|
|
1739
|
-
return route4(req, config);
|
|
1740
|
-
}
|
|
1741
|
-
if (matches6(configRoutes, req)) {
|
|
1742
|
-
info("matches session");
|
|
1743
|
-
return route6(req, config);
|
|
1744
|
-
}
|
|
1745
|
-
if (matches5(configRoutes, req)) {
|
|
1746
|
-
info("matches signin");
|
|
1747
|
-
return route5(req, config);
|
|
1748
|
-
}
|
|
1749
|
-
if (matches13(configRoutes, req)) {
|
|
1750
|
-
info("matches password reset");
|
|
1751
|
-
return route13(req, config);
|
|
1752
|
-
}
|
|
1753
|
-
if (matches7(configRoutes, req)) {
|
|
1754
|
-
info("matches providers");
|
|
1755
|
-
return route7(req, config);
|
|
1756
|
-
}
|
|
1757
|
-
if (matches8(configRoutes, req)) {
|
|
1758
|
-
info("matches csrf");
|
|
1759
|
-
return route8(req, config);
|
|
1760
|
-
}
|
|
1761
|
-
if (matches9(configRoutes, req)) {
|
|
1762
|
-
info("matches callback");
|
|
1763
|
-
return route9(req, config);
|
|
1764
|
-
}
|
|
1765
|
-
if (matches10(configRoutes, req)) {
|
|
1766
|
-
info("matches signout");
|
|
1767
|
-
return route10(req, config);
|
|
1768
|
-
}
|
|
1769
|
-
warn("No POST routes matched");
|
|
1770
|
-
return new Response(null, { status: 404 });
|
|
1771
|
-
};
|
|
1568
|
+
});
|
|
1772
1569
|
}
|
|
1773
1570
|
|
|
1774
|
-
// src/
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1571
|
+
// src/db/NileInstance.ts
|
|
1572
|
+
var NileDatabase = class {
|
|
1573
|
+
pool;
|
|
1574
|
+
tenantId;
|
|
1575
|
+
userId;
|
|
1576
|
+
id;
|
|
1577
|
+
config;
|
|
1578
|
+
timer;
|
|
1579
|
+
constructor(config, id) {
|
|
1580
|
+
const { warn, info, debug } = Logger(config, "[NileInstance]");
|
|
1581
|
+
this.id = id;
|
|
1582
|
+
const poolConfig = {
|
|
1583
|
+
min: 0,
|
|
1584
|
+
max: 10,
|
|
1585
|
+
idleTimeoutMillis: 3e4,
|
|
1586
|
+
...config.db
|
|
1587
|
+
};
|
|
1588
|
+
const { afterCreate, ...remaining } = poolConfig;
|
|
1589
|
+
config.db = poolConfig;
|
|
1590
|
+
this.config = config;
|
|
1591
|
+
const cloned = { ...this.config.db };
|
|
1592
|
+
cloned.password = "***";
|
|
1593
|
+
debug(`Connection pool config ${JSON.stringify(cloned)}`);
|
|
1594
|
+
this.pool = createProxyForPool(new pg__default.default.Pool(remaining), this.config);
|
|
1595
|
+
if (typeof afterCreate === "function") {
|
|
1596
|
+
warn(
|
|
1597
|
+
"Providing an pool configuration will stop automatic tenant context setting."
|
|
1598
|
+
);
|
|
1781
1599
|
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1600
|
+
this.startTimeout();
|
|
1601
|
+
this.pool.on("connect", async (client) => {
|
|
1602
|
+
debug(`pool connected ${this.id}`);
|
|
1603
|
+
this.startTimeout();
|
|
1604
|
+
const afterCreate2 = makeAfterCreate(
|
|
1605
|
+
config,
|
|
1606
|
+
`${this.id}-${this.timer}`
|
|
1607
|
+
);
|
|
1608
|
+
afterCreate2(client, (err) => {
|
|
1609
|
+
const { error } = Logger(config, "[after create callback]");
|
|
1610
|
+
if (err) {
|
|
1611
|
+
clearTimeout(this.timer);
|
|
1612
|
+
error("after create failed", {
|
|
1613
|
+
message: err.message,
|
|
1614
|
+
stack: err.stack
|
|
1615
|
+
});
|
|
1616
|
+
evictPool(this.id);
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
});
|
|
1620
|
+
this.pool.on("error", (err) => {
|
|
1621
|
+
clearTimeout(this.timer);
|
|
1622
|
+
info(`pool ${this.id} failed`, {
|
|
1623
|
+
message: err.message,
|
|
1624
|
+
stack: err.stack
|
|
1625
|
+
});
|
|
1626
|
+
evictPool(this.id);
|
|
1627
|
+
});
|
|
1628
|
+
this.pool.on("release", (destroy) => {
|
|
1629
|
+
if (destroy) {
|
|
1630
|
+
clearTimeout(this.timer);
|
|
1631
|
+
evictPool(this.id);
|
|
1632
|
+
debug(`destroying pool ${this.id}`);
|
|
1633
|
+
}
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
startTimeout() {
|
|
1637
|
+
const { debug } = Logger(this.config, "[NileInstance]");
|
|
1638
|
+
if (this.timer) {
|
|
1639
|
+
clearTimeout(this.timer);
|
|
1640
|
+
}
|
|
1641
|
+
this.timer = setTimeout(() => {
|
|
1642
|
+
debug(
|
|
1643
|
+
`Pool reached idleTimeoutMillis. ${this.id} evicted after ${Number(this.config.db.idleTimeoutMillis) ?? 3e4}ms`
|
|
1644
|
+
);
|
|
1645
|
+
this.pool.end(() => {
|
|
1646
|
+
clearTimeout(this.timer);
|
|
1647
|
+
evictPool(this.id);
|
|
1648
|
+
});
|
|
1649
|
+
}, Number(this.config.db.idleTimeoutMillis) ?? 3e4);
|
|
1650
|
+
}
|
|
1651
|
+
shutdown() {
|
|
1652
|
+
const { debug } = Logger(this.config, "[NileInstance]");
|
|
1653
|
+
debug(`attempting to shut down ${this.id}`);
|
|
1654
|
+
clearTimeout(this.timer);
|
|
1655
|
+
this.pool.end(() => {
|
|
1656
|
+
debug(`${this.id} has been shut down`);
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1660
|
+
var NileInstance_default = NileDatabase;
|
|
1661
|
+
function makeAfterCreate(config, id) {
|
|
1662
|
+
const { error, warn, debug } = Logger(config, "[afterCreate]");
|
|
1663
|
+
return (conn, done) => {
|
|
1664
|
+
conn.on("error", function errorHandler(e) {
|
|
1665
|
+
error(`Connection ${id} was terminated by server`, {
|
|
1666
|
+
message: e.message,
|
|
1667
|
+
stack: e.stack
|
|
1668
|
+
});
|
|
1669
|
+
done(e, conn);
|
|
1670
|
+
});
|
|
1671
|
+
if (config.tenantId) {
|
|
1672
|
+
const query = [`SET nile.tenant_id = '${config.tenantId}'`];
|
|
1673
|
+
if (config.userId) {
|
|
1674
|
+
if (!config.tenantId) {
|
|
1675
|
+
warn("A user id cannot be set in context without a tenant id");
|
|
1676
|
+
}
|
|
1677
|
+
query.push(`SET nile.user_id = '${config.userId}'`);
|
|
1678
|
+
}
|
|
1679
|
+
conn.query(query.join(";"), function(err) {
|
|
1680
|
+
if (err) {
|
|
1681
|
+
error("query connection failed", {
|
|
1682
|
+
cause: err.cause,
|
|
1683
|
+
stack: err.stack,
|
|
1684
|
+
message: err.message,
|
|
1685
|
+
name: err.name,
|
|
1686
|
+
id
|
|
1687
|
+
});
|
|
1688
|
+
} else {
|
|
1689
|
+
if (query.length === 1) {
|
|
1690
|
+
debug(`connection context set: tenantId=${config.tenantId}`);
|
|
1691
|
+
}
|
|
1692
|
+
if (query.length === 2) {
|
|
1693
|
+
debug(
|
|
1694
|
+
`connection context set: tenantId=${config.tenantId} userId=${config.userId}`
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
done(err, conn);
|
|
1699
|
+
});
|
|
1785
1700
|
}
|
|
1786
|
-
|
|
1787
|
-
return new Response(null, { status: 404 });
|
|
1701
|
+
done(null, conn);
|
|
1788
1702
|
};
|
|
1789
1703
|
}
|
|
1790
1704
|
|
|
1791
|
-
// src/
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1705
|
+
// src/db/DBManager.ts
|
|
1706
|
+
var DBManager = class {
|
|
1707
|
+
connections;
|
|
1708
|
+
cleared;
|
|
1709
|
+
poolWatcherFn;
|
|
1710
|
+
makeId(tenantId, userId) {
|
|
1711
|
+
if (tenantId && userId) {
|
|
1712
|
+
return `${tenantId}:${userId}`;
|
|
1798
1713
|
}
|
|
1799
|
-
if (
|
|
1800
|
-
|
|
1801
|
-
return route2(req, config);
|
|
1714
|
+
if (tenantId) {
|
|
1715
|
+
return `${tenantId}`;
|
|
1802
1716
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1717
|
+
return "base";
|
|
1718
|
+
}
|
|
1719
|
+
constructor(config) {
|
|
1720
|
+
this.cleared = false;
|
|
1721
|
+
this.connections = /* @__PURE__ */ new Map();
|
|
1722
|
+
this.poolWatcherFn = this.poolWatcher(config);
|
|
1723
|
+
watchEvictPool(this.poolWatcherFn);
|
|
1724
|
+
}
|
|
1725
|
+
poolWatcher = (config) => (id) => {
|
|
1726
|
+
const { info, warn } = Logger(config, "[DBManager]");
|
|
1727
|
+
if (id && this.connections.has(id)) {
|
|
1728
|
+
info(`Removing ${id} from db connection pool.`);
|
|
1729
|
+
const connection = this.connections.get(id);
|
|
1730
|
+
connection?.shutdown();
|
|
1731
|
+
this.connections.delete(id);
|
|
1732
|
+
} else {
|
|
1733
|
+
warn(`missed eviction of ${id}`);
|
|
1806
1734
|
}
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1735
|
+
};
|
|
1736
|
+
getConnection = (config) => {
|
|
1737
|
+
const { info } = Logger(config, "[DBManager]");
|
|
1738
|
+
const id = this.makeId(config.tenantId, config.userId);
|
|
1739
|
+
const existing = this.connections.get(id);
|
|
1740
|
+
info(`# of instances: ${this.connections.size}`);
|
|
1741
|
+
if (existing) {
|
|
1742
|
+
info(`returning existing ${id}`);
|
|
1743
|
+
existing.startTimeout();
|
|
1744
|
+
return existing.pool;
|
|
1810
1745
|
}
|
|
1811
|
-
|
|
1812
|
-
|
|
1746
|
+
const newOne = new NileInstance_default(new Config(config), id);
|
|
1747
|
+
this.connections.set(id, newOne);
|
|
1748
|
+
info(`created new ${id}`);
|
|
1749
|
+
info(`# of instances: ${this.connections.size}`);
|
|
1750
|
+
if (this.cleared) {
|
|
1751
|
+
this.cleared = false;
|
|
1752
|
+
}
|
|
1753
|
+
return newOne.pool;
|
|
1813
1754
|
};
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
return {
|
|
1823
|
-
GET: GET6,
|
|
1824
|
-
POST: POST5,
|
|
1825
|
-
DELETE: DELETE3,
|
|
1826
|
-
PUT: PUT4
|
|
1755
|
+
clear = (config) => {
|
|
1756
|
+
const { info } = Logger(config, "[DBManager]");
|
|
1757
|
+
info(`Clearing all connections ${this.connections.size}`);
|
|
1758
|
+
this.cleared = true;
|
|
1759
|
+
this.connections.forEach((connection) => {
|
|
1760
|
+
connection.shutdown();
|
|
1761
|
+
});
|
|
1762
|
+
this.connections.clear();
|
|
1827
1763
|
};
|
|
1828
|
-
}
|
|
1764
|
+
};
|
|
1829
1765
|
|
|
1830
|
-
// src/
|
|
1831
|
-
var
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1766
|
+
// src/users/index.ts
|
|
1767
|
+
var Users = class {
|
|
1768
|
+
#config;
|
|
1769
|
+
constructor(config) {
|
|
1770
|
+
this.#config = config;
|
|
1771
|
+
}
|
|
1772
|
+
async updateSelf(req, rawResponse) {
|
|
1773
|
+
const res = await fetchMe(this.#config, "PUT", JSON.stringify(req));
|
|
1774
|
+
if (rawResponse) {
|
|
1775
|
+
return res;
|
|
1776
|
+
}
|
|
1777
|
+
try {
|
|
1778
|
+
return await res?.clone().json();
|
|
1779
|
+
} catch {
|
|
1780
|
+
return res;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
async removeSelf() {
|
|
1784
|
+
const me = await this.getSelf();
|
|
1785
|
+
if ("id" in me) {
|
|
1786
|
+
this.#config.userId = me.id;
|
|
1787
|
+
}
|
|
1788
|
+
const res = await fetchMe(this.#config, "DELETE");
|
|
1789
|
+
updateHeaders(new Headers());
|
|
1790
|
+
return res;
|
|
1791
|
+
}
|
|
1792
|
+
async getSelf(rawResponse) {
|
|
1793
|
+
const res = await fetchMe(this.#config);
|
|
1794
|
+
if (rawResponse) {
|
|
1795
|
+
return res;
|
|
1796
|
+
}
|
|
1797
|
+
try {
|
|
1798
|
+
return await res?.clone().json();
|
|
1799
|
+
} catch {
|
|
1800
|
+
return res;
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1850
1804
|
|
|
1851
|
-
// src/
|
|
1852
|
-
var
|
|
1805
|
+
// src/tenants/index.ts
|
|
1806
|
+
var Tenants = class {
|
|
1807
|
+
#logger;
|
|
1808
|
+
#config;
|
|
1853
1809
|
constructor(config) {
|
|
1854
|
-
|
|
1810
|
+
this.#logger = Logger(config, "[tenants]");
|
|
1811
|
+
this.#config = config;
|
|
1855
1812
|
}
|
|
1856
|
-
async
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1813
|
+
async create(req, rawResponse) {
|
|
1814
|
+
let res;
|
|
1815
|
+
if (typeof req === "string") {
|
|
1816
|
+
res = await fetchTenants(
|
|
1817
|
+
this.#config,
|
|
1818
|
+
"POST",
|
|
1819
|
+
JSON.stringify({ name: req })
|
|
1820
|
+
);
|
|
1821
|
+
} else if (typeof req === "object" && ("name" in req || "id" in req)) {
|
|
1822
|
+
res = await fetchTenants(this.#config, "POST", JSON.stringify(req));
|
|
1823
|
+
}
|
|
1824
|
+
if (rawResponse) {
|
|
1825
|
+
return res;
|
|
1826
|
+
}
|
|
1827
|
+
try {
|
|
1828
|
+
return await res?.clone().json();
|
|
1829
|
+
} catch {
|
|
1830
|
+
return res;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
async delete(req) {
|
|
1834
|
+
if (typeof req === "string") {
|
|
1835
|
+
this.#config.tenantId = req;
|
|
1865
1836
|
}
|
|
1837
|
+
if (typeof req === "object" && "id" in req) {
|
|
1838
|
+
this.#config.tenantId = req.id;
|
|
1839
|
+
}
|
|
1840
|
+
const res = await fetchTenant(this.#config, "DELETE");
|
|
1866
1841
|
return res;
|
|
1867
1842
|
}
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
const tenantId = req.get(X_NILE_TENANT);
|
|
1883
|
-
const cookie = req.get("cookie");
|
|
1884
|
-
if (tenantId) {
|
|
1885
|
-
headers.set(X_NILE_TENANT, tenantId);
|
|
1886
|
-
}
|
|
1887
|
-
if (cookie) {
|
|
1888
|
-
headers.set("cookie", cookie);
|
|
1889
|
-
}
|
|
1890
|
-
} else if (req instanceof Request) {
|
|
1891
|
-
const _headers = new Headers(req?.headers);
|
|
1892
|
-
const tenantId = _headers.get(X_NILE_TENANT);
|
|
1893
|
-
const cookie = _headers.get("cookie");
|
|
1894
|
-
if (tenantId) {
|
|
1895
|
-
headers.set(X_NILE_TENANT, tenantId);
|
|
1896
|
-
}
|
|
1897
|
-
if (cookie) {
|
|
1898
|
-
headers.set("cookie", cookie);
|
|
1899
|
-
}
|
|
1843
|
+
async get(req, rawResponse) {
|
|
1844
|
+
if (typeof req === "string") {
|
|
1845
|
+
this.#config.tenantId = req;
|
|
1846
|
+
} else if (typeof req === "object" && "id" in req) {
|
|
1847
|
+
this.#config.tenantId = req.id;
|
|
1848
|
+
}
|
|
1849
|
+
const res = await fetchTenant(this.#config, "GET");
|
|
1850
|
+
if (rawResponse === true || req === true) {
|
|
1851
|
+
return res;
|
|
1852
|
+
}
|
|
1853
|
+
try {
|
|
1854
|
+
return await res?.clone().json();
|
|
1855
|
+
} catch {
|
|
1856
|
+
return res;
|
|
1900
1857
|
}
|
|
1901
|
-
let body = JSON.stringify(req);
|
|
1902
|
-
if (method === "GET") {
|
|
1903
|
-
body = void 0;
|
|
1904
|
-
} else if (req instanceof Request) {
|
|
1905
|
-
body = await new Response(req.body).text();
|
|
1906
|
-
} else if (
|
|
1907
|
-
// is just headers for a GET request
|
|
1908
|
-
req instanceof Headers || JSON.stringify(req) === "{}" || req && typeof req === "object" && Object.values(req).length === 0
|
|
1909
|
-
) {
|
|
1910
|
-
body = void 0;
|
|
1911
|
-
}
|
|
1912
|
-
const _init = {
|
|
1913
|
-
...init,
|
|
1914
|
-
headers
|
|
1915
|
-
};
|
|
1916
|
-
return await this.rawRequest(method, url, _init, body);
|
|
1917
1858
|
}
|
|
1918
|
-
async
|
|
1919
|
-
|
|
1920
|
-
if (
|
|
1921
|
-
const
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
} catch (e) {
|
|
1859
|
+
async update(req, rawResponse) {
|
|
1860
|
+
let res;
|
|
1861
|
+
if (typeof req === "object" && ("name" in req || "id" in req)) {
|
|
1862
|
+
const { id, ...remaining } = req;
|
|
1863
|
+
if (id) {
|
|
1864
|
+
this.#config.tenantId = id;
|
|
1925
1865
|
}
|
|
1866
|
+
res = await fetchTenant(this.#config, "PUT", JSON.stringify(remaining));
|
|
1867
|
+
}
|
|
1868
|
+
if (rawResponse) {
|
|
1869
|
+
return res;
|
|
1870
|
+
}
|
|
1871
|
+
try {
|
|
1872
|
+
return await res?.clone().json();
|
|
1873
|
+
} catch {
|
|
1874
|
+
return res;
|
|
1926
1875
|
}
|
|
1927
|
-
return response;
|
|
1928
1876
|
}
|
|
1929
|
-
async
|
|
1930
|
-
const
|
|
1931
|
-
if (
|
|
1932
|
-
return
|
|
1877
|
+
async list(req) {
|
|
1878
|
+
const res = await fetchTenantsByUser(this.#config);
|
|
1879
|
+
if (req === true) {
|
|
1880
|
+
return res;
|
|
1933
1881
|
}
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
} catch (e) {
|
|
1939
|
-
}
|
|
1882
|
+
try {
|
|
1883
|
+
return await res?.clone().json();
|
|
1884
|
+
} catch {
|
|
1885
|
+
return res;
|
|
1940
1886
|
}
|
|
1941
|
-
return response;
|
|
1942
1887
|
}
|
|
1943
|
-
async
|
|
1944
|
-
const
|
|
1945
|
-
|
|
1946
|
-
const
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
} catch (e) {
|
|
1888
|
+
async leaveTenant(req) {
|
|
1889
|
+
const me = await fetchMe(this.#config);
|
|
1890
|
+
try {
|
|
1891
|
+
const json = await me.json();
|
|
1892
|
+
if ("id" in json) {
|
|
1893
|
+
this.#config.userId = json.id;
|
|
1950
1894
|
}
|
|
1895
|
+
} catch {
|
|
1896
|
+
}
|
|
1897
|
+
if (typeof req === "string") {
|
|
1898
|
+
this.#config.tenantId = req;
|
|
1899
|
+
} else {
|
|
1900
|
+
this.#handleContext(req);
|
|
1951
1901
|
}
|
|
1952
|
-
return
|
|
1902
|
+
return await fetchTenantUser(this.#config, "DELETE");
|
|
1903
|
+
}
|
|
1904
|
+
async addMember(req, rawResponse) {
|
|
1905
|
+
if (typeof req === "string") {
|
|
1906
|
+
this.#config.userId = req;
|
|
1907
|
+
} else {
|
|
1908
|
+
this.#handleContext(req);
|
|
1909
|
+
}
|
|
1910
|
+
const res = await fetchTenantUser(this.#config, "PUT");
|
|
1911
|
+
return responseHandler(res, rawResponse);
|
|
1912
|
+
}
|
|
1913
|
+
async removeMember(req, rawResponse) {
|
|
1914
|
+
this.#handleContext(req);
|
|
1915
|
+
const res = await fetchTenantUser(this.#config, "DELETE");
|
|
1916
|
+
return responseHandler(res, rawResponse);
|
|
1917
|
+
}
|
|
1918
|
+
async users(req, rawResponse) {
|
|
1919
|
+
this.#handleContext(req);
|
|
1920
|
+
const res = await fetchTenantUsers(this.#config, "GET");
|
|
1921
|
+
return responseHandler(
|
|
1922
|
+
res,
|
|
1923
|
+
rawResponse || typeof req === "boolean" && req
|
|
1924
|
+
);
|
|
1953
1925
|
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1926
|
+
#handleContext(req) {
|
|
1927
|
+
if (typeof req === "object") {
|
|
1928
|
+
if ("tenantId" in req) {
|
|
1929
|
+
this.#config.tenantId = req.tenantId;
|
|
1930
|
+
}
|
|
1931
|
+
if ("userId" in req) {
|
|
1932
|
+
this.#config.tenantId = req.tenantId;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1957
1935
|
}
|
|
1958
1936
|
};
|
|
1937
|
+
async function responseHandler(res, rawResponse) {
|
|
1938
|
+
if (rawResponse) {
|
|
1939
|
+
return res;
|
|
1940
|
+
}
|
|
1941
|
+
try {
|
|
1942
|
+
return await res?.clone().json();
|
|
1943
|
+
} catch {
|
|
1944
|
+
return res;
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1959
1947
|
|
|
1960
1948
|
// src/auth/index.ts
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1949
|
+
var Auth = class {
|
|
1950
|
+
#logger;
|
|
1951
|
+
#config;
|
|
1952
|
+
constructor(config) {
|
|
1953
|
+
this.#config = config;
|
|
1954
|
+
this.#logger = Logger(config, "[auth]");
|
|
1955
|
+
}
|
|
1956
|
+
async getSession(rawResponse = false) {
|
|
1957
|
+
const res = await fetchSession(this.#config);
|
|
1958
|
+
if (rawResponse) {
|
|
1959
|
+
return res;
|
|
1971
1960
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1961
|
+
try {
|
|
1962
|
+
const session = await res.clone().json();
|
|
1963
|
+
if (Object.keys(session).length === 0) {
|
|
1964
|
+
return void 0;
|
|
1965
|
+
}
|
|
1966
|
+
return session;
|
|
1967
|
+
} catch {
|
|
1968
|
+
return res;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
async getCsrf(rawResponse = false) {
|
|
1972
|
+
const res = await fetchCsrf(this.#config);
|
|
1973
|
+
const csrfCook = parseCSRF(res.headers);
|
|
1974
|
+
if (csrfCook) {
|
|
1975
|
+
const [, value] = csrfCook.split("=");
|
|
1976
|
+
const [token] = decodeURIComponent(value).split("|");
|
|
1977
|
+
const setCookie = res.headers.get("set-cookie");
|
|
1978
|
+
if (setCookie) {
|
|
1979
|
+
const cookie = [
|
|
1980
|
+
csrfCook,
|
|
1981
|
+
parseCallback(res.headers),
|
|
1982
|
+
parseToken(res.headers)
|
|
1983
|
+
].filter(Boolean).join("; ");
|
|
1984
|
+
this.#config.headers.set("cookie", cookie);
|
|
1985
|
+
updateHeaders(new Headers({ cookie }));
|
|
1986
|
+
}
|
|
1987
|
+
if (!rawResponse) {
|
|
1988
|
+
return { csrfToken: token };
|
|
1989
|
+
}
|
|
1990
|
+
} else {
|
|
1991
|
+
const existingCookie = this.#config.headers.get("cookie");
|
|
1992
|
+
const cookieParts = [];
|
|
1993
|
+
if (existingCookie) {
|
|
1994
|
+
cookieParts.push(
|
|
1995
|
+
parseToken(this.#config.headers),
|
|
1996
|
+
parseCallback(this.#config.headers)
|
|
1997
|
+
);
|
|
1998
|
+
}
|
|
1999
|
+
cookieParts.push(csrfCook);
|
|
2000
|
+
const cookie = cookieParts.filter(Boolean).join("; ");
|
|
2001
|
+
this.#config.headers.set("cookie", cookie);
|
|
2002
|
+
updateHeaders(new Headers({ cookie }));
|
|
2003
|
+
}
|
|
2004
|
+
if (rawResponse) {
|
|
2005
|
+
return res;
|
|
1985
2006
|
}
|
|
1986
|
-
let providers;
|
|
1987
2007
|
try {
|
|
1988
|
-
|
|
1989
|
-
} catch
|
|
1990
|
-
|
|
1991
|
-
|
|
2008
|
+
return await res.clone().json();
|
|
2009
|
+
} catch {
|
|
2010
|
+
return res;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
async listProviders(rawResponse = false) {
|
|
2014
|
+
const res = await fetchProviders(this.#config);
|
|
2015
|
+
if (rawResponse) {
|
|
2016
|
+
return res;
|
|
1992
2017
|
}
|
|
1993
|
-
info("Obtaining csrf");
|
|
1994
|
-
const csrf = new URL(`${ORIGIN}${routes.CSRF}`);
|
|
1995
|
-
const csrfReq = new Request(csrf, {
|
|
1996
|
-
method: "GET",
|
|
1997
|
-
headers: new Headers({
|
|
1998
|
-
...baseHeaders
|
|
1999
|
-
})
|
|
2000
|
-
});
|
|
2001
|
-
const csrfRes = await handlers.POST(csrfReq);
|
|
2002
|
-
let csrfToken;
|
|
2003
2018
|
try {
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2019
|
+
return await res.clone().json();
|
|
2020
|
+
} catch {
|
|
2021
|
+
return res;
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
async signOut() {
|
|
2025
|
+
const csrfRes = await this.getCsrf();
|
|
2026
|
+
if (!("csrfToken" in csrfRes)) {
|
|
2027
|
+
throw new Error("Unable to obtain CSRF token. Sign out failed.");
|
|
2028
|
+
}
|
|
2029
|
+
const body = JSON.stringify({
|
|
2030
|
+
csrfToken: csrfRes.csrfToken,
|
|
2031
|
+
json: true
|
|
2032
|
+
});
|
|
2033
|
+
const res = await fetchSignOut(this.#config, body);
|
|
2034
|
+
updateHeaders(new Headers({}));
|
|
2035
|
+
this.#config.headers = new Headers();
|
|
2036
|
+
return res;
|
|
2037
|
+
}
|
|
2038
|
+
async signUp(payload, rawResponse) {
|
|
2039
|
+
this.#config.headers = new Headers();
|
|
2040
|
+
const { email, password, ...params } = payload;
|
|
2041
|
+
if (!email || !password) {
|
|
2042
|
+
throw new Error(
|
|
2043
|
+
"Server side sign up requires a user email and password."
|
|
2044
|
+
);
|
|
2009
2045
|
}
|
|
2046
|
+
const providers = await this.listProviders();
|
|
2010
2047
|
const { credentials } = providers ?? {};
|
|
2011
|
-
const csrfCookie = csrfRes?.headers.get("set-cookie");
|
|
2012
2048
|
if (!credentials) {
|
|
2013
2049
|
throw new Error(
|
|
2014
|
-
"Unable to obtain credential provider. Aborting server side
|
|
2050
|
+
"Unable to obtain credential provider. Aborting server side sign up."
|
|
2015
2051
|
);
|
|
2016
2052
|
}
|
|
2017
|
-
const
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2053
|
+
const csrf = await this.getCsrf();
|
|
2054
|
+
let csrfToken;
|
|
2055
|
+
if ("csrfToken" in csrf) {
|
|
2056
|
+
csrfToken = csrf.csrfToken;
|
|
2057
|
+
} else {
|
|
2058
|
+
throw new Error("Unable to obtain parse CSRF. Request blocked.");
|
|
2021
2059
|
}
|
|
2022
|
-
info(`Attempting sign in with email ${email} ${signInUrl.href}`);
|
|
2023
2060
|
const body = JSON.stringify({
|
|
2024
2061
|
email,
|
|
2025
2062
|
password,
|
|
2026
2063
|
csrfToken,
|
|
2027
2064
|
callbackUrl: credentials.callbackUrl
|
|
2028
2065
|
});
|
|
2029
|
-
const
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
"content-type": "application/json",
|
|
2034
|
-
cookie: csrfCookie.split(",").join("; ")
|
|
2035
|
-
}),
|
|
2036
|
-
body
|
|
2037
|
-
});
|
|
2038
|
-
const loginRes = await handlers.POST(postReq);
|
|
2039
|
-
const authCookie = loginRes?.headers.get("set-cookie");
|
|
2040
|
-
if (!authCookie) {
|
|
2041
|
-
throw new Error("authentication failed");
|
|
2066
|
+
const res = await fetchSignUp(this.#config, { body, params });
|
|
2067
|
+
if (res.status > 299) {
|
|
2068
|
+
this.#logger.error(await res.clone().text());
|
|
2069
|
+
return void 0;
|
|
2042
2070
|
}
|
|
2043
|
-
const token = parseToken(
|
|
2071
|
+
const token = parseToken(res.headers);
|
|
2044
2072
|
if (!token) {
|
|
2045
|
-
|
|
2046
|
-
throw new Error("Server login failed");
|
|
2073
|
+
throw new Error("Server side sign up failed. Session token not found");
|
|
2047
2074
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
});
|
|
2053
|
-
return [headers, loginRes];
|
|
2054
|
-
};
|
|
2055
|
-
}
|
|
2056
|
-
function parseToken(headers) {
|
|
2057
|
-
let authCookie = headers?.get("set-cookie");
|
|
2058
|
-
if (!authCookie) {
|
|
2059
|
-
authCookie = headers?.get("cookie");
|
|
2060
|
-
}
|
|
2061
|
-
if (!authCookie) {
|
|
2062
|
-
return void 0;
|
|
2063
|
-
}
|
|
2064
|
-
const [, token] = /((__Secure-)?nile\.session-token=[^;]+)/.exec(authCookie) ?? [];
|
|
2065
|
-
return token;
|
|
2066
|
-
}
|
|
2067
|
-
var Auth = class extends Config {
|
|
2068
|
-
headers;
|
|
2069
|
-
resetHeaders;
|
|
2070
|
-
constructor(config, headers, params) {
|
|
2071
|
-
super(config);
|
|
2072
|
-
this.logger = Logger(config, "[auth]");
|
|
2073
|
-
this.headers = headers;
|
|
2074
|
-
this.logger = Logger(config, "[auth]");
|
|
2075
|
-
this.resetHeaders = params?.resetHeaders;
|
|
2076
|
-
}
|
|
2077
|
-
handleHeaders(init) {
|
|
2078
|
-
if (this.headers) {
|
|
2079
|
-
const cburl = getCallbackUrl2(this.headers);
|
|
2080
|
-
if (cburl) {
|
|
2081
|
-
try {
|
|
2082
|
-
this.headers.set(X_NILE_ORIGIN, new URL(cburl).origin);
|
|
2083
|
-
} catch (e) {
|
|
2084
|
-
if (this.logger?.debug) {
|
|
2085
|
-
this.logger.debug("Invalid URL supplied by cookie header");
|
|
2086
|
-
}
|
|
2087
|
-
}
|
|
2088
|
-
}
|
|
2089
|
-
if (init) {
|
|
2090
|
-
init.headers = new Headers({ ...this.headers, ...init?.headers });
|
|
2091
|
-
return init;
|
|
2092
|
-
} else {
|
|
2093
|
-
init = {
|
|
2094
|
-
headers: this.headers
|
|
2095
|
-
};
|
|
2096
|
-
return init;
|
|
2097
|
-
}
|
|
2075
|
+
this.#config.headers?.append("cookie", token);
|
|
2076
|
+
updateHeaders(this.#config.headers);
|
|
2077
|
+
if (rawResponse) {
|
|
2078
|
+
return res;
|
|
2098
2079
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
}
|
|
2104
|
-
getSession = async (req, init) => {
|
|
2105
|
-
const _requester = new Requester(this);
|
|
2106
|
-
const _init = this.handleHeaders(init);
|
|
2107
|
-
const session = await _requester.get(req, this.sessionUrl, _init);
|
|
2108
|
-
if (Object.keys(session).length === 0) {
|
|
2109
|
-
return void 0;
|
|
2080
|
+
try {
|
|
2081
|
+
return await res.clone().json();
|
|
2082
|
+
} catch {
|
|
2083
|
+
return res;
|
|
2110
2084
|
}
|
|
2111
|
-
return session;
|
|
2112
|
-
};
|
|
2113
|
-
get getCsrfUrl() {
|
|
2114
|
-
return "/auth/csrf";
|
|
2115
|
-
}
|
|
2116
|
-
async getCsrf(req, init, raw = false) {
|
|
2117
|
-
const _requester = new Requester(this);
|
|
2118
|
-
const _init = this.handleHeaders(init);
|
|
2119
|
-
return await _requester.get(req, this.getCsrfUrl, _init, raw);
|
|
2120
2085
|
}
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
get signOutUrl() {
|
|
2130
|
-
return "/auth/signout";
|
|
2131
|
-
}
|
|
2132
|
-
signOut = async (req, init) => {
|
|
2133
|
-
const _requester = new Requester(this);
|
|
2134
|
-
const _init = this.handleHeaders(init);
|
|
2135
|
-
const csrf = await this.getCsrf(
|
|
2136
|
-
req,
|
|
2137
|
-
void 0,
|
|
2138
|
-
true
|
|
2139
|
-
);
|
|
2140
|
-
const csrfHeader = getCsrfToken(csrf.headers, this.headers);
|
|
2141
|
-
const callbackUrl = req && "callbackUrl" in req ? String(req.callbackUrl) : "/";
|
|
2142
|
-
if (!csrfHeader) {
|
|
2143
|
-
this.logger?.debug && this.logger.debug("Request blocked from invalid csrf header");
|
|
2144
|
-
return new Response("Request blocked", { status: 400 });
|
|
2145
|
-
}
|
|
2146
|
-
const headers = new Headers(_init?.headers);
|
|
2147
|
-
const { csrfToken } = await csrf.json() ?? {};
|
|
2148
|
-
const cooks = getCookies(headers);
|
|
2149
|
-
if (csrfHeader) {
|
|
2150
|
-
if (cooks["__Secure-nile.csrf-token"]) {
|
|
2151
|
-
cooks["__Secure-nile.csrf-token"] = encodeURIComponent(csrfHeader);
|
|
2152
|
-
}
|
|
2153
|
-
if (cooks["nile.csrf-token"]) {
|
|
2154
|
-
cooks["nile.csrf-token"] = encodeURIComponent(csrfHeader);
|
|
2155
|
-
}
|
|
2086
|
+
async signIn(provider, payload, rawResponse) {
|
|
2087
|
+
this.#config.headers = new Headers();
|
|
2088
|
+
const { info, error } = this.#logger;
|
|
2089
|
+
const { email, password } = payload ?? {};
|
|
2090
|
+
if (provider === "email" && (!email || !password)) {
|
|
2091
|
+
throw new Error(
|
|
2092
|
+
"Server side sign in requires a user email and password."
|
|
2093
|
+
);
|
|
2156
2094
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
);
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
json: String(true)
|
|
2167
|
-
}),
|
|
2168
|
-
..._init,
|
|
2169
|
-
headers
|
|
2170
|
-
});
|
|
2171
|
-
this.resetHeaders && this.resetHeaders();
|
|
2172
|
-
return res;
|
|
2173
|
-
};
|
|
2174
|
-
};
|
|
2175
|
-
function getCallbackUrl2(headers) {
|
|
2176
|
-
if (headers) {
|
|
2177
|
-
const cookies = getCookies(headers);
|
|
2178
|
-
if (cookies) {
|
|
2179
|
-
return cookies["__Secure-nile.callback-url"] || cookies["nile.callback-url"];
|
|
2095
|
+
info(`Obtaining providers for ${email}`);
|
|
2096
|
+
const providers = await this.listProviders();
|
|
2097
|
+
info("Obtaining csrf");
|
|
2098
|
+
const csrf = await this.getCsrf();
|
|
2099
|
+
let csrfToken;
|
|
2100
|
+
if ("csrfToken" in csrf) {
|
|
2101
|
+
csrfToken = csrf.csrfToken;
|
|
2102
|
+
} else {
|
|
2103
|
+
throw new Error("Unable to obtain parse CSRF. Request blocked.");
|
|
2180
2104
|
}
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
let validCookie = "";
|
|
2187
|
-
if (cookies) {
|
|
2188
|
-
validCookie = cookies["__Secure-nile.csrf-token"] || cookies["nile.csrf-token"];
|
|
2105
|
+
const { credentials } = providers ?? {};
|
|
2106
|
+
if (!credentials) {
|
|
2107
|
+
throw new Error(
|
|
2108
|
+
"Unable to obtain credential provider. Aborting server side sign in."
|
|
2109
|
+
);
|
|
2189
2110
|
}
|
|
2190
|
-
if (
|
|
2191
|
-
return
|
|
2111
|
+
if (provider !== "credentials") {
|
|
2112
|
+
return await fetchSignIn(
|
|
2113
|
+
this.#config,
|
|
2114
|
+
provider,
|
|
2115
|
+
JSON.stringify({ csrfToken })
|
|
2116
|
+
);
|
|
2192
2117
|
}
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2118
|
+
info(`Attempting sign in with email ${email}`);
|
|
2119
|
+
const body = JSON.stringify({
|
|
2120
|
+
email,
|
|
2121
|
+
password,
|
|
2122
|
+
csrfToken,
|
|
2123
|
+
callbackUrl: credentials.callbackUrl
|
|
2124
|
+
});
|
|
2125
|
+
const signInRes = await fetchCallback(this.#config, provider, body);
|
|
2126
|
+
const authCookie = signInRes?.headers.get("set-cookie");
|
|
2127
|
+
if (!authCookie) {
|
|
2128
|
+
throw new Error("authentication failed");
|
|
2198
2129
|
}
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
].filter(Boolean);
|
|
2211
|
-
return Object.fromEntries(
|
|
2212
|
-
allCookies.map((cookie) => {
|
|
2213
|
-
const [key12, ...val] = cookie.split("=");
|
|
2214
|
-
return [
|
|
2215
|
-
decodeURIComponent(key12.trim()),
|
|
2216
|
-
decodeURIComponent(val.join("=").trim())
|
|
2217
|
-
];
|
|
2218
|
-
})
|
|
2219
|
-
);
|
|
2220
|
-
};
|
|
2221
|
-
|
|
2222
|
-
// src/tenants/index.ts
|
|
2223
|
-
var Tenants = class extends Config {
|
|
2224
|
-
headers;
|
|
2225
|
-
constructor(config, headers) {
|
|
2226
|
-
super(config);
|
|
2227
|
-
this.headers = headers;
|
|
2228
|
-
}
|
|
2229
|
-
handleHeaders(init) {
|
|
2230
|
-
if (this.headers) {
|
|
2231
|
-
if (init) {
|
|
2232
|
-
init.headers = new Headers({ ...this.headers, ...init?.headers });
|
|
2233
|
-
return init;
|
|
2234
|
-
} else {
|
|
2235
|
-
init = {
|
|
2236
|
-
headers: this.headers
|
|
2237
|
-
};
|
|
2238
|
-
return init;
|
|
2130
|
+
const token = parseToken(signInRes?.headers);
|
|
2131
|
+
const possibleError = signInRes?.headers.get("location");
|
|
2132
|
+
if (possibleError) {
|
|
2133
|
+
let urlError;
|
|
2134
|
+
try {
|
|
2135
|
+
urlError = new URL(possibleError).searchParams.get("error");
|
|
2136
|
+
} catch {
|
|
2137
|
+
}
|
|
2138
|
+
if (urlError) {
|
|
2139
|
+
error("Unable to log user in", { error: urlError });
|
|
2140
|
+
return void 0;
|
|
2239
2141
|
}
|
|
2240
2142
|
}
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
}
|
|
2246
|
-
get tenantUrl() {
|
|
2247
|
-
return `/tenants/${this.tenantId ?? "{tenantId}"}`;
|
|
2248
|
-
}
|
|
2249
|
-
createTenant = async (req, init) => {
|
|
2250
|
-
let _req;
|
|
2251
|
-
if (typeof req === "string") {
|
|
2252
|
-
_req = new Request(`${this.api.basePath}${this.tenantsUrl}`, {
|
|
2253
|
-
body: JSON.stringify({ name: req }),
|
|
2254
|
-
method: "POST",
|
|
2255
|
-
headers: {
|
|
2256
|
-
"content-type": "application/json"
|
|
2257
|
-
}
|
|
2258
|
-
});
|
|
2259
|
-
} else if ("name" in req || "id" in req) {
|
|
2260
|
-
_req = new Request(`${this.api.basePath}${this.tenantsUrl}`, {
|
|
2261
|
-
body: JSON.stringify(req),
|
|
2262
|
-
method: "POST",
|
|
2263
|
-
headers: {
|
|
2264
|
-
"content-type": "application/json"
|
|
2265
|
-
}
|
|
2143
|
+
if (!token) {
|
|
2144
|
+
error("Unable to obtain auth token", {
|
|
2145
|
+
authCookie,
|
|
2146
|
+
signInRes
|
|
2266
2147
|
});
|
|
2267
|
-
|
|
2268
|
-
_req = req;
|
|
2269
|
-
}
|
|
2270
|
-
const _requester = new Requester(this);
|
|
2271
|
-
const _init = this.handleHeaders(init);
|
|
2272
|
-
return _requester.post(_req, this.tenantsUrl, _init);
|
|
2273
|
-
};
|
|
2274
|
-
getTenant = async (req, init) => {
|
|
2275
|
-
if (typeof req === "string") {
|
|
2276
|
-
this.tenantId = req;
|
|
2277
|
-
}
|
|
2278
|
-
const _requester = new Requester(this);
|
|
2279
|
-
const _init = this.handleHeaders(init);
|
|
2280
|
-
return _requester.get(req, this.tenantUrl, _init);
|
|
2281
|
-
};
|
|
2282
|
-
get tenantListUrl() {
|
|
2283
|
-
return `/users/${this.userId ?? "{userId}"}/tenants`;
|
|
2284
|
-
}
|
|
2285
|
-
listTenants = async (req, init) => {
|
|
2286
|
-
const _requester = new Requester(this);
|
|
2287
|
-
const _init = this.handleHeaders(init);
|
|
2288
|
-
return _requester.get(req, this.tenantListUrl, _init);
|
|
2289
|
-
};
|
|
2290
|
-
deleteTenant = async (req, init) => {
|
|
2291
|
-
if (typeof req === "string") {
|
|
2292
|
-
this.tenantId = req;
|
|
2148
|
+
throw new Error("Server login failed");
|
|
2293
2149
|
}
|
|
2294
|
-
|
|
2295
|
-
const
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
method: "PUT"
|
|
2304
|
-
});
|
|
2150
|
+
info("Server sign in successful", { authCookie });
|
|
2151
|
+
const setCookie = signInRes.headers.get("set-cookie");
|
|
2152
|
+
if (setCookie) {
|
|
2153
|
+
const cookie = [
|
|
2154
|
+
parseCSRF(this.#config.headers),
|
|
2155
|
+
parseCallback(signInRes.headers),
|
|
2156
|
+
parseToken(signInRes.headers)
|
|
2157
|
+
].filter(Boolean).join("; ");
|
|
2158
|
+
updateHeaders(new Headers({ cookie }));
|
|
2305
2159
|
} else {
|
|
2306
|
-
|
|
2160
|
+
error("Unable to set context after sign in", {
|
|
2161
|
+
headers: signInRes.headers
|
|
2162
|
+
});
|
|
2307
2163
|
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
return _requester.put(_req, this.tenantUrl, _init);
|
|
2311
|
-
};
|
|
2312
|
-
};
|
|
2313
|
-
|
|
2314
|
-
// src/users/index.ts
|
|
2315
|
-
var Users = class extends Config {
|
|
2316
|
-
headers;
|
|
2317
|
-
constructor(config, headers) {
|
|
2318
|
-
super(config);
|
|
2319
|
-
this.headers = headers;
|
|
2320
|
-
}
|
|
2321
|
-
usersUrl(user) {
|
|
2322
|
-
const params = new URLSearchParams();
|
|
2323
|
-
if (user.newTenantName) {
|
|
2324
|
-
params.set("newTenantName", user.newTenantName);
|
|
2164
|
+
if (rawResponse) {
|
|
2165
|
+
return signInRes;
|
|
2325
2166
|
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2167
|
+
try {
|
|
2168
|
+
return await signInRes.clone().json();
|
|
2169
|
+
} catch {
|
|
2170
|
+
return signInRes;
|
|
2328
2171
|
}
|
|
2329
|
-
return `/users?${params.size > 0 ? params : ""}`;
|
|
2330
2172
|
}
|
|
2331
|
-
|
|
2332
|
-
|
|
2173
|
+
};
|
|
2174
|
+
function parseCSRF(headers) {
|
|
2175
|
+
let cookie = headers?.get("set-cookie");
|
|
2176
|
+
if (!cookie) {
|
|
2177
|
+
cookie = headers?.get("cookie");
|
|
2333
2178
|
}
|
|
2334
|
-
|
|
2335
|
-
return
|
|
2179
|
+
if (!cookie) {
|
|
2180
|
+
return void 0;
|
|
2336
2181
|
}
|
|
2337
|
-
|
|
2338
|
-
|
|
2182
|
+
const [, token] = /((__Secure-)?nile\.csrf-token=[^;]+)/.exec(cookie) ?? [];
|
|
2183
|
+
return token;
|
|
2184
|
+
}
|
|
2185
|
+
function parseCallback(headers) {
|
|
2186
|
+
let cookie = headers?.get("set-cookie");
|
|
2187
|
+
if (!cookie) {
|
|
2188
|
+
cookie = headers?.get("cookie");
|
|
2339
2189
|
}
|
|
2340
|
-
|
|
2341
|
-
if (this.headers) {
|
|
2342
|
-
if (init) {
|
|
2343
|
-
init.headers = new Headers({ ...this.headers, ...init?.headers });
|
|
2344
|
-
return init;
|
|
2345
|
-
} else {
|
|
2346
|
-
init = {
|
|
2347
|
-
headers: this.headers
|
|
2348
|
-
};
|
|
2349
|
-
return init;
|
|
2350
|
-
}
|
|
2351
|
-
}
|
|
2190
|
+
if (!cookie) {
|
|
2352
2191
|
return void 0;
|
|
2353
2192
|
}
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
const _init = this.handleHeaders(init);
|
|
2362
|
-
return await _requester.post(req, this.tenantUsersUrl, _init);
|
|
2363
|
-
};
|
|
2364
|
-
updateUser = async (req, init) => {
|
|
2365
|
-
let _req;
|
|
2366
|
-
if (req && "id" in req) {
|
|
2367
|
-
_req = new Request(`${this.api.basePath}${this.tenantUserUrl}`, {
|
|
2368
|
-
body: JSON.stringify(req),
|
|
2369
|
-
method: "PUT"
|
|
2370
|
-
});
|
|
2371
|
-
this.userId = String(req.id);
|
|
2372
|
-
} else {
|
|
2373
|
-
_req = req;
|
|
2374
|
-
}
|
|
2375
|
-
const _requester = new Requester(this);
|
|
2376
|
-
const _init = this.handleHeaders(init);
|
|
2377
|
-
return await _requester.put(_req, this.tenantUserUrl, _init);
|
|
2378
|
-
};
|
|
2379
|
-
listUsers = async (req, init) => {
|
|
2380
|
-
const _requester = new Requester(this);
|
|
2381
|
-
const _init = this.handleHeaders(init);
|
|
2382
|
-
return await _requester.get(req, this.tenantUsersUrl, _init);
|
|
2383
|
-
};
|
|
2384
|
-
linkUser = async (req, init) => {
|
|
2385
|
-
const _requester = new Requester(this);
|
|
2386
|
-
if (typeof req === "string") {
|
|
2387
|
-
this.userId = req;
|
|
2388
|
-
} else {
|
|
2389
|
-
if ("id" in req) {
|
|
2390
|
-
this.userId = req.id;
|
|
2391
|
-
}
|
|
2392
|
-
if ("tenantId" in req) {
|
|
2393
|
-
this.tenantId = req.tenantId;
|
|
2394
|
-
}
|
|
2395
|
-
}
|
|
2396
|
-
const _init = this.handleHeaders(init);
|
|
2397
|
-
return await _requester.put(req, this.linkUsersUrl, _init);
|
|
2398
|
-
};
|
|
2399
|
-
unlinkUser = async (req, init) => {
|
|
2400
|
-
if (typeof req === "string") {
|
|
2401
|
-
this.userId = req;
|
|
2402
|
-
} else {
|
|
2403
|
-
if ("id" in req) {
|
|
2404
|
-
this.userId = req.id;
|
|
2405
|
-
}
|
|
2406
|
-
if ("tenantId" in req) {
|
|
2407
|
-
this.tenantId = req.tenantId;
|
|
2408
|
-
}
|
|
2409
|
-
}
|
|
2410
|
-
const _requester = new Requester(this);
|
|
2411
|
-
const _init = this.handleHeaders(init);
|
|
2412
|
-
return await _requester.delete(req, this.linkUsersUrl, _init);
|
|
2413
|
-
};
|
|
2414
|
-
get meUrl() {
|
|
2415
|
-
return "/me";
|
|
2193
|
+
const [, token] = /((__Secure-)?nile\.callback-url=[^;]+)/.exec(cookie) ?? [];
|
|
2194
|
+
return token;
|
|
2195
|
+
}
|
|
2196
|
+
function parseToken(headers) {
|
|
2197
|
+
let authCookie = headers?.get("set-cookie");
|
|
2198
|
+
if (!authCookie) {
|
|
2199
|
+
authCookie = headers?.get("cookie");
|
|
2416
2200
|
}
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
const _requester = new Requester(this);
|
|
2424
|
-
const _init = this.handleHeaders(init);
|
|
2425
|
-
return await _requester.put(req, this.meUrl, _init);
|
|
2426
|
-
};
|
|
2427
|
-
};
|
|
2201
|
+
if (!authCookie) {
|
|
2202
|
+
return void 0;
|
|
2203
|
+
}
|
|
2204
|
+
const [, token] = /((__Secure-)?nile\.session-token=[^;]+)/.exec(authCookie) ?? [];
|
|
2205
|
+
return token;
|
|
2206
|
+
}
|
|
2428
2207
|
|
|
2429
2208
|
// src/api/handlers/withContext/index.ts
|
|
2430
|
-
function handlersWithContext(
|
|
2431
|
-
const GET6 = GETTER(
|
|
2432
|
-
const POST5 = POSTER(
|
|
2433
|
-
const
|
|
2434
|
-
const
|
|
2209
|
+
function handlersWithContext(config) {
|
|
2210
|
+
const GET6 = GETTER(config.routes, config);
|
|
2211
|
+
const POST5 = POSTER(config.routes, config);
|
|
2212
|
+
const DELETE4 = DELETER(config.routes, config);
|
|
2213
|
+
const PUT5 = PUTER(config.routes, config);
|
|
2435
2214
|
return {
|
|
2436
2215
|
GET: async (req) => {
|
|
2437
2216
|
const response = await GET6(req);
|
|
@@ -2444,12 +2223,12 @@ function handlersWithContext(configRoutes, config) {
|
|
|
2444
2223
|
return { response, nile: new Server(updatedConfig) };
|
|
2445
2224
|
},
|
|
2446
2225
|
DELETE: async (req) => {
|
|
2447
|
-
const response = await
|
|
2226
|
+
const response = await DELETE4(req);
|
|
2448
2227
|
const updatedConfig = updateConfig(response, config);
|
|
2449
2228
|
return { response, nile: new Server(updatedConfig) };
|
|
2450
2229
|
},
|
|
2451
2230
|
PUT: async (req) => {
|
|
2452
|
-
const response = await
|
|
2231
|
+
const response = await PUT5(req);
|
|
2453
2232
|
const updatedConfig = updateConfig(response, config);
|
|
2454
2233
|
return { response, nile: new Server(updatedConfig) };
|
|
2455
2234
|
}
|
|
@@ -2461,13 +2240,14 @@ function updateConfig(response, config) {
|
|
|
2461
2240
|
if (response?.status === 302) {
|
|
2462
2241
|
const location = response.headers.get("location");
|
|
2463
2242
|
if (location) {
|
|
2464
|
-
|
|
2243
|
+
const normalized = location.endsWith("/") ? location.slice(0, -1) : location;
|
|
2244
|
+
origin = normalized;
|
|
2465
2245
|
}
|
|
2466
2246
|
}
|
|
2467
2247
|
const setCookies = [];
|
|
2468
2248
|
if (response?.headers) {
|
|
2469
|
-
for (const [
|
|
2470
|
-
if (
|
|
2249
|
+
for (const [key13, value] of response.headers) {
|
|
2250
|
+
if (key13.toLowerCase() === "set-cookie") {
|
|
2471
2251
|
setCookies.push(value);
|
|
2472
2252
|
}
|
|
2473
2253
|
}
|
|
@@ -2478,299 +2258,200 @@ function updateConfig(response, config) {
|
|
|
2478
2258
|
}
|
|
2479
2259
|
return {
|
|
2480
2260
|
...config,
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
origin,
|
|
2484
|
-
headers: headers ?? void 0
|
|
2485
|
-
}
|
|
2261
|
+
origin,
|
|
2262
|
+
headers: headers ?? void 0
|
|
2486
2263
|
};
|
|
2487
2264
|
}
|
|
2488
2265
|
|
|
2489
|
-
// src/
|
|
2490
|
-
var
|
|
2491
|
-
config;
|
|
2266
|
+
// src/Server.ts
|
|
2267
|
+
var Server = class {
|
|
2492
2268
|
users;
|
|
2493
|
-
auth;
|
|
2494
2269
|
tenants;
|
|
2495
|
-
|
|
2270
|
+
auth;
|
|
2271
|
+
#config;
|
|
2272
|
+
#handlers;
|
|
2273
|
+
#paths;
|
|
2274
|
+
#manager;
|
|
2496
2275
|
#headers;
|
|
2497
|
-
handlers;
|
|
2498
|
-
handlersWithContext;
|
|
2499
|
-
paths;
|
|
2500
2276
|
constructor(config) {
|
|
2501
|
-
this
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2277
|
+
this.#config = new Config(config, "[initial config]");
|
|
2278
|
+
watchTenantId((tenantId) => {
|
|
2279
|
+
if (tenantId !== this.#config.tenantId) {
|
|
2280
|
+
this.#config.tenantId = tenantId;
|
|
2281
|
+
this.#reset();
|
|
2282
|
+
}
|
|
2507
2283
|
});
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
};
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
this.routes.TENANT,
|
|
2522
|
-
this.routes.SESSION,
|
|
2523
|
-
this.routes.SIGNIN,
|
|
2524
|
-
this.routes.PROVIDERS,
|
|
2525
|
-
this.routes.CSRF,
|
|
2526
|
-
this.routes.PASSWORD_RESET,
|
|
2527
|
-
this.routes.CALLBACK,
|
|
2528
|
-
this.routes.SIGNOUT,
|
|
2529
|
-
this.routes.VERIFY_REQUEST,
|
|
2530
|
-
this.routes.ERROR
|
|
2531
|
-
],
|
|
2532
|
-
post: [
|
|
2533
|
-
this.routes.TENANT_USERS,
|
|
2534
|
-
this.routes.SIGNUP,
|
|
2535
|
-
this.routes.USERS,
|
|
2536
|
-
this.routes.TENANTS,
|
|
2537
|
-
this.routes.SESSION,
|
|
2538
|
-
`${this.routes.SIGNIN}/{provider}`,
|
|
2539
|
-
this.routes.PASSWORD_RESET,
|
|
2540
|
-
this.routes.PROVIDERS,
|
|
2541
|
-
this.routes.CSRF,
|
|
2542
|
-
`${this.routes.CALLBACK}/{provider}`,
|
|
2543
|
-
this.routes.SIGNOUT
|
|
2544
|
-
],
|
|
2545
|
-
put: [
|
|
2546
|
-
this.routes.TENANT_USERS,
|
|
2547
|
-
this.routes.USERS,
|
|
2548
|
-
this.routes.TENANT,
|
|
2549
|
-
this.routes.PASSWORD_RESET
|
|
2550
|
-
],
|
|
2551
|
-
delete: [this.routes.TENANT_USER, this.routes.TENANT]
|
|
2284
|
+
watchUserId((userId) => {
|
|
2285
|
+
if (userId !== this.#config.userId) {
|
|
2286
|
+
this.#config.userId = userId;
|
|
2287
|
+
this.#reset();
|
|
2288
|
+
}
|
|
2289
|
+
});
|
|
2290
|
+
watchHeaders((headers) => {
|
|
2291
|
+
this.setContext(headers);
|
|
2292
|
+
this.#reset();
|
|
2293
|
+
});
|
|
2294
|
+
this.#handlers = {
|
|
2295
|
+
...this.#config.handlers,
|
|
2296
|
+
withContext: handlersWithContext(this.#config)
|
|
2552
2297
|
};
|
|
2298
|
+
this.#paths = this.#config.paths;
|
|
2299
|
+
this.#config.tenantId = getTenantId({ config: this.#config });
|
|
2300
|
+
this.#manager = new DBManager(this.#config);
|
|
2301
|
+
this.#handleHeaders(config);
|
|
2302
|
+
this.users = new Users(this.#config);
|
|
2303
|
+
this.tenants = new Tenants(this.#config);
|
|
2304
|
+
this.auth = new Auth(this.#config);
|
|
2553
2305
|
}
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2306
|
+
get db() {
|
|
2307
|
+
const pool = this.#manager.getConnection(this.#config);
|
|
2308
|
+
return Object.assign(pool, {
|
|
2309
|
+
clearConnections: () => {
|
|
2310
|
+
this.#manager.clear(this.#config);
|
|
2311
|
+
}
|
|
2559
2312
|
});
|
|
2560
|
-
}
|
|
2561
|
-
updateConfig = (config) => {
|
|
2562
|
-
this.config = config;
|
|
2563
|
-
this.handlers = Handlers(this.routes, config);
|
|
2564
|
-
};
|
|
2565
|
-
resetHeaders = (headers) => {
|
|
2566
|
-
this.#headers = new Headers(headers ?? {});
|
|
2567
|
-
this.reset();
|
|
2568
|
-
};
|
|
2313
|
+
}
|
|
2569
2314
|
/**
|
|
2570
|
-
*
|
|
2315
|
+
* A convenience function that applies a config and ensures whatever was passed is set properly
|
|
2571
2316
|
*/
|
|
2572
|
-
|
|
2573
|
-
const
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
updates.push([key12.toLowerCase(), value]);
|
|
2581
|
-
}
|
|
2582
|
-
}
|
|
2583
|
-
const merged = {};
|
|
2584
|
-
this.#headers?.forEach((value, key12) => {
|
|
2585
|
-
if (key12.toLowerCase() !== "cookie") {
|
|
2586
|
-
merged[key12.toLowerCase()] = value;
|
|
2587
|
-
}
|
|
2588
|
-
});
|
|
2589
|
-
for (const [key12, value] of updates) {
|
|
2590
|
-
merged[key12] = value;
|
|
2591
|
-
}
|
|
2592
|
-
this.#headers = new Headers();
|
|
2593
|
-
for (const [key12, value] of Object.entries(merged)) {
|
|
2594
|
-
this.#headers.set(key12, value);
|
|
2317
|
+
getInstance(config, req) {
|
|
2318
|
+
const _config = { ...this.#config, ...config };
|
|
2319
|
+
const updatedConfig = new Config(_config);
|
|
2320
|
+
this.#config = new Config(updatedConfig);
|
|
2321
|
+
this.#config.tenantId = config.tenantId;
|
|
2322
|
+
this.#config.userId = config.userId;
|
|
2323
|
+
if (req) {
|
|
2324
|
+
this.setContext(req);
|
|
2595
2325
|
}
|
|
2596
|
-
this
|
|
2326
|
+
this.#reset();
|
|
2327
|
+
return this;
|
|
2597
2328
|
}
|
|
2598
|
-
|
|
2599
|
-
return this.#
|
|
2329
|
+
getPaths() {
|
|
2330
|
+
return this.#paths;
|
|
2600
2331
|
}
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
return parseToken(req);
|
|
2604
|
-
} else if (req instanceof Request) {
|
|
2605
|
-
return parseToken(req.headers);
|
|
2606
|
-
}
|
|
2607
|
-
return null;
|
|
2332
|
+
get handlers() {
|
|
2333
|
+
return this.#handlers;
|
|
2608
2334
|
}
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
if (res.id) {
|
|
2618
|
-
this.config.userId = res.id;
|
|
2619
|
-
}
|
|
2620
|
-
} catch (e) {
|
|
2621
|
-
const { warn } = Logger(this.config, "[API][login]");
|
|
2622
|
-
if (warn) {
|
|
2623
|
-
warn("Unable to set user id from login attempt.");
|
|
2624
|
-
}
|
|
2625
|
-
}
|
|
2626
|
-
if (config?.returnResponse) {
|
|
2627
|
-
return loginRes;
|
|
2628
|
-
}
|
|
2629
|
-
return void 0;
|
|
2630
|
-
};
|
|
2631
|
-
session = async (req) => {
|
|
2632
|
-
if (req instanceof Headers) {
|
|
2633
|
-
return this.auth.getSession(req);
|
|
2634
|
-
} else if (req instanceof Request) {
|
|
2635
|
-
return auth(req, this.config);
|
|
2636
|
-
}
|
|
2637
|
-
return this.auth.getSession(this.#headers);
|
|
2638
|
-
};
|
|
2639
|
-
setContext = (req) => {
|
|
2335
|
+
/**
|
|
2336
|
+
* Allow the setting of headers from a req or header object.
|
|
2337
|
+
* Makes it possible to handle REST requests easily
|
|
2338
|
+
* Also makes it easy to set user + tenant in some way
|
|
2339
|
+
* @param req
|
|
2340
|
+
* @returns undefined
|
|
2341
|
+
*/
|
|
2342
|
+
setContext(req) {
|
|
2640
2343
|
try {
|
|
2641
2344
|
if (req instanceof Headers) {
|
|
2642
|
-
this
|
|
2345
|
+
this.#handleHeaders(req);
|
|
2346
|
+
this.#reset();
|
|
2643
2347
|
return;
|
|
2644
2348
|
} else if (req instanceof Request) {
|
|
2645
|
-
this
|
|
2349
|
+
this.#handleHeaders(new Headers(req.headers));
|
|
2350
|
+
this.#reset();
|
|
2646
2351
|
return;
|
|
2647
2352
|
}
|
|
2353
|
+
} catch {
|
|
2354
|
+
}
|
|
2355
|
+
let ok = false;
|
|
2356
|
+
if (req && typeof req === "object" && "tenantId" in req) {
|
|
2357
|
+
ok = true;
|
|
2358
|
+
this.#config.tenantId = req.tenantId;
|
|
2359
|
+
}
|
|
2360
|
+
if (req && typeof req === "object" && "userId" in req) {
|
|
2361
|
+
ok = true;
|
|
2362
|
+
this.#config.userId = req.userId;
|
|
2363
|
+
}
|
|
2364
|
+
if (ok) {
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
if (typeof req === "object") {
|
|
2648
2368
|
const headers = new Headers(req);
|
|
2649
2369
|
if (headers) {
|
|
2650
|
-
this
|
|
2370
|
+
this.#handleHeaders(headers);
|
|
2371
|
+
this.#reset();
|
|
2651
2372
|
return;
|
|
2652
2373
|
}
|
|
2653
|
-
} catch {
|
|
2654
2374
|
}
|
|
2655
|
-
const { warn } = Logger(this
|
|
2375
|
+
const { warn } = Logger(this.#config, "[API]");
|
|
2656
2376
|
if (warn) {
|
|
2657
2377
|
warn(
|
|
2658
2378
|
"Set context expects a Request, Header instance or an object of Record<string, string>"
|
|
2659
2379
|
);
|
|
2660
2380
|
}
|
|
2661
|
-
};
|
|
2662
|
-
};
|
|
2663
|
-
|
|
2664
|
-
// src/Server.ts
|
|
2665
|
-
var Server = class {
|
|
2666
|
-
config;
|
|
2667
|
-
api;
|
|
2668
|
-
manager;
|
|
2669
|
-
constructor(config) {
|
|
2670
|
-
this.config = new Config(config, "[initial config]");
|
|
2671
|
-
this.api = new Api(this.config);
|
|
2672
|
-
this.manager = new DBManager(this.config);
|
|
2673
|
-
watchTenantId((tenantId) => {
|
|
2674
|
-
this.tenantId = tenantId;
|
|
2675
|
-
});
|
|
2676
|
-
watchUserId((userId) => {
|
|
2677
|
-
this.userId = userId;
|
|
2678
|
-
});
|
|
2679
|
-
watchToken((token) => {
|
|
2680
|
-
this.token = token;
|
|
2681
|
-
});
|
|
2682
|
-
}
|
|
2683
|
-
setConfig(cfg) {
|
|
2684
|
-
this.config = new Config(cfg);
|
|
2685
|
-
this.api.updateConfig(this.config);
|
|
2686
|
-
}
|
|
2687
|
-
async init(cfg) {
|
|
2688
|
-
const updatedConfig = await this.config.configure({
|
|
2689
|
-
...this.config,
|
|
2690
|
-
...cfg
|
|
2691
|
-
});
|
|
2692
|
-
this.setConfig(updatedConfig);
|
|
2693
|
-
return this;
|
|
2694
|
-
}
|
|
2695
|
-
set databaseId(val) {
|
|
2696
|
-
if (val) {
|
|
2697
|
-
this.config.databaseId = val;
|
|
2698
|
-
this.api.users.databaseId = val;
|
|
2699
|
-
this.api.tenants.databaseId = val;
|
|
2700
|
-
}
|
|
2701
2381
|
}
|
|
2702
|
-
|
|
2703
|
-
return
|
|
2382
|
+
getContext() {
|
|
2383
|
+
return {
|
|
2384
|
+
headers: this.#headers,
|
|
2385
|
+
userId: this.#config.userId,
|
|
2386
|
+
tenantId: this.#config.tenantId
|
|
2387
|
+
};
|
|
2704
2388
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2389
|
+
/**
|
|
2390
|
+
* Merge headers together
|
|
2391
|
+
* Internally, passed a NileConfig, externally, should be using Headers
|
|
2392
|
+
*/
|
|
2393
|
+
#handleHeaders(config) {
|
|
2394
|
+
const updates = [];
|
|
2395
|
+
let headers;
|
|
2396
|
+
this.#headers = new Headers();
|
|
2397
|
+
if (config instanceof Headers) {
|
|
2398
|
+
headers = config;
|
|
2399
|
+
} else if (config?.headers) {
|
|
2400
|
+
headers = config?.headers;
|
|
2401
|
+
if (config && config.origin) {
|
|
2402
|
+
this.#headers.set(X_NILE_ORIGIN, config.origin);
|
|
2403
|
+
}
|
|
2404
|
+
if (config && config.secureCookies != null) {
|
|
2405
|
+
this.#headers.set(X_NILE_SECURECOOKIES, String(config.secureCookies));
|
|
2406
|
+
}
|
|
2711
2407
|
}
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
this.api.users.tenantId = tenantId;
|
|
2721
|
-
this.api.tenants.tenantId = tenantId;
|
|
2408
|
+
if (headers instanceof Headers) {
|
|
2409
|
+
headers.forEach((value, key13) => {
|
|
2410
|
+
updates.push([key13.toLowerCase(), value]);
|
|
2411
|
+
});
|
|
2412
|
+
} else {
|
|
2413
|
+
for (const [key13, value] of Object.entries(headers ?? {})) {
|
|
2414
|
+
updates.push([key13.toLowerCase(), value]);
|
|
2415
|
+
}
|
|
2722
2416
|
}
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
set token(token) {
|
|
2728
|
-
if (token) {
|
|
2729
|
-
this.config.api.token = token;
|
|
2730
|
-
if (this.api) {
|
|
2731
|
-
this.api.users.api.token = token;
|
|
2732
|
-
this.api.tenants.api.token = token;
|
|
2417
|
+
const merged = {};
|
|
2418
|
+
this.#headers?.forEach((value, key13) => {
|
|
2419
|
+
if (key13.toLowerCase() !== "cookie") {
|
|
2420
|
+
merged[key13.toLowerCase()] = value;
|
|
2733
2421
|
}
|
|
2422
|
+
});
|
|
2423
|
+
for (const [key13, value] of updates) {
|
|
2424
|
+
merged[key13] = value;
|
|
2734
2425
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
clearConnections() {
|
|
2740
|
-
this.manager.clear(this.config);
|
|
2426
|
+
for (const [key13, value] of Object.entries(merged)) {
|
|
2427
|
+
this.#headers.set(key13, value);
|
|
2428
|
+
}
|
|
2429
|
+
this.#config.headers = this.#headers;
|
|
2741
2430
|
}
|
|
2742
2431
|
/**
|
|
2743
|
-
*
|
|
2432
|
+
* Allow some internal mutations to reset our config + headers
|
|
2744
2433
|
*/
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
this.
|
|
2749
|
-
this.
|
|
2750
|
-
|
|
2751
|
-
if (updatedConfig.api.token) {
|
|
2752
|
-
this.token = updatedConfig.api.token;
|
|
2753
|
-
}
|
|
2754
|
-
this.databaseId = updatedConfig.databaseId;
|
|
2755
|
-
if (req) {
|
|
2756
|
-
this.api.setContext(req);
|
|
2757
|
-
}
|
|
2758
|
-
return this;
|
|
2759
|
-
}
|
|
2434
|
+
#reset = () => {
|
|
2435
|
+
this.#config.headers = this.#headers ?? new Headers();
|
|
2436
|
+
this.users = new Users(this.#config);
|
|
2437
|
+
this.tenants = new Tenants(this.#config);
|
|
2438
|
+
this.auth = new Auth(this.#config);
|
|
2439
|
+
};
|
|
2760
2440
|
};
|
|
2761
2441
|
var server;
|
|
2762
|
-
|
|
2442
|
+
function create(config) {
|
|
2763
2443
|
if (!server) {
|
|
2764
2444
|
server = new Server(config);
|
|
2765
2445
|
}
|
|
2766
|
-
|
|
2767
|
-
return await server.init(new Config(config));
|
|
2768
|
-
}
|
|
2769
|
-
return await server.init();
|
|
2446
|
+
return server;
|
|
2770
2447
|
}
|
|
2771
2448
|
|
|
2449
|
+
exports.APIErrorErrorCodeEnum = APIErrorErrorCodeEnum;
|
|
2772
2450
|
exports.LoginUserResponseTokenTypeEnum = LoginUserResponseTokenTypeEnum;
|
|
2773
2451
|
exports.Nile = create;
|
|
2774
2452
|
exports.Server = Server;
|
|
2453
|
+
exports.parseCSRF = parseCSRF;
|
|
2454
|
+
exports.parseCallback = parseCallback;
|
|
2455
|
+
exports.parseToken = parseToken;
|
|
2775
2456
|
//# sourceMappingURL=index.js.map
|
|
2776
2457
|
//# sourceMappingURL=index.js.map
|