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