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