@dbx-tools/tunnel 0.6.90 → 0.6.92
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/README.md +22 -31
- package/index.ts +2 -6
- package/lib/index.d.ts +2 -6
- package/lib/index.js +3 -6
- package/lib/src/allowlist.d.ts +1 -1
- package/lib/src/allowlist.js +2 -2
- package/lib/src/gate.d.ts +12 -9
- package/lib/src/gate.js +60 -82
- package/lib/src/interceptor.d.ts +1 -1
- package/lib/src/interceptor.js +2 -2
- package/lib/src/plugin.d.ts +45 -32
- package/lib/src/plugin.js +104 -72
- package/lib/src/signing-key.d.ts +2 -2
- package/lib/src/signing-key.js +4 -4
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/allowlist.ts +1 -1
- package/src/gate.ts +64 -95
- package/src/interceptor.ts +1 -1
- package/src/plugin.ts +142 -93
- package/src/signing-key.ts +3 -3
- package/lib/src/otp.d.ts +0 -49
- package/lib/src/otp.js +0 -130
- package/lib/src/rate-limit.d.ts +0 -35
- package/lib/src/rate-limit.js +0 -53
- package/src/otp.ts +0 -143
- package/src/rate-limit.ts +0 -59
package/lib/src/gate.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* nothing to forward to. It either short-circuits (401, or answers the open login
|
|
7
7
|
* routes) or calls `next()` to let the app's real handlers run. It is the
|
|
8
8
|
* "stands in for AppKit auth" path:
|
|
9
|
-
* a portr caller
|
|
10
|
-
*
|
|
9
|
+
* a portr caller authenticates with Better Auth OTP or a passkey, and on
|
|
10
|
+
* success the gate injects the identity headers AppKit reads.
|
|
11
11
|
*
|
|
12
12
|
* WHICH TRAFFIC IS GATED - the `Host` header, not the socket. portr's client
|
|
13
13
|
* forwards with Go's `httputil.NewSingleHostReverseProxy` and a `Director` that
|
|
@@ -21,11 +21,9 @@
|
|
|
21
21
|
*
|
|
22
22
|
* @module
|
|
23
23
|
*/
|
|
24
|
-
import {
|
|
25
|
-
import { authRequestSchema, authVerifySchema, SESSION_COOKIE_NAME } from "@dbx-tools/shared-email";
|
|
24
|
+
import { log, token } from "@dbx-tools/shared-core";
|
|
26
25
|
import { toHeaderPolicy } from "./headers.js";
|
|
27
26
|
const logger = log.logger("tunnel:gate");
|
|
28
|
-
/** Route prefix the login flow lives under (open, answered in-process). */
|
|
29
27
|
export const AUTH_PREFIX = "/api/email/auth";
|
|
30
28
|
/**
|
|
31
29
|
* True when the request's `Host` is the tunnel's public domain - i.e. it came in
|
|
@@ -38,21 +36,6 @@ export function isTunnelHost(req, publicDomain) {
|
|
|
38
36
|
const host = (req.headers.host ?? "").toLowerCase().split(":")[0];
|
|
39
37
|
return host === publicDomain.toLowerCase().split(":")[0];
|
|
40
38
|
}
|
|
41
|
-
/** The session cookie for a verified email, as a Set-Cookie string. */
|
|
42
|
-
function sessionCookie(value, maxAgeSeconds) {
|
|
43
|
-
return [
|
|
44
|
-
`${SESSION_COOKIE_NAME}=${value}`,
|
|
45
|
-
"Path=/",
|
|
46
|
-
"HttpOnly",
|
|
47
|
-
"SameSite=Lax",
|
|
48
|
-
`Max-Age=${maxAgeSeconds}`,
|
|
49
|
-
// Real enforcement in production: the session cookie must be Secure so it is
|
|
50
|
-
// never sent over plaintext. Local dev (http) omits it so the cookie works.
|
|
51
|
-
process.env.NODE_ENV === "production" ? "Secure" : "",
|
|
52
|
-
]
|
|
53
|
-
.filter(Boolean)
|
|
54
|
-
.join("; ");
|
|
55
|
-
}
|
|
56
39
|
/**
|
|
57
40
|
* Client IP for rate-limiting: the RIGHTMOST `x-forwarded-for` entry (the value
|
|
58
41
|
* the nearest trusted hop - portr - wrote), else the socket address. Reading the
|
|
@@ -79,19 +62,19 @@ function stripSessionCookie(req) {
|
|
|
79
62
|
const kept = raw
|
|
80
63
|
.split(";")
|
|
81
64
|
.map((c) => c.trim())
|
|
82
|
-
.filter((c) => c && !c.startsWith(
|
|
65
|
+
.filter((c) => c && !c.startsWith("dbx-tools-auth=") && !c.startsWith("dbx-tools-passkey="));
|
|
83
66
|
if (kept.length)
|
|
84
67
|
req.headers.cookie = kept.join("; ");
|
|
85
68
|
else
|
|
86
69
|
delete req.headers.cookie;
|
|
87
70
|
}
|
|
88
71
|
/**
|
|
89
|
-
* Present
|
|
72
|
+
* Present a passwordless-authenticated caller to the app the SAME way a platform front
|
|
90
73
|
* door does: set the front-door identity headers to the verified address (AppKit
|
|
91
74
|
* reads {@link token.USER_ID_HEADER} for the OBO user id), so the app needs no
|
|
92
75
|
* gate-specific code path.
|
|
93
76
|
*
|
|
94
|
-
* What the gate CANNOT set is {@link token.ACCESS_TOKEN_HEADER}: an
|
|
77
|
+
* What the gate CANNOT set is {@link token.ACCESS_TOKEN_HEADER}: an auth session
|
|
95
78
|
* proves an email, not possession of a Databricks credential. Its absence is what
|
|
96
79
|
* `@dbx-tools/appkit`'s `identity: "auto"` detects, so a gated request runs as the
|
|
97
80
|
* app service principal instead of throwing.
|
|
@@ -100,11 +83,6 @@ function injectIdentity(req, email) {
|
|
|
100
83
|
req.headers[token.USER_ID_HEADER] = email;
|
|
101
84
|
req.headers[token.USER_EMAIL_HEADER] = email;
|
|
102
85
|
}
|
|
103
|
-
function sendJson(res, status, body, setCookie) {
|
|
104
|
-
if (setCookie)
|
|
105
|
-
res.setHeader("set-cookie", setCookie);
|
|
106
|
-
res.status(status).json(body);
|
|
107
|
-
}
|
|
108
86
|
/** Read the raw request body as text (AppKit parses JSON, but the gate routes
|
|
109
87
|
* are mounted before that runs for tunnel traffic, so read defensively). */
|
|
110
88
|
function readBody(req) {
|
|
@@ -119,6 +97,43 @@ function readBody(req) {
|
|
|
119
97
|
req.on("error", () => resolve(data));
|
|
120
98
|
});
|
|
121
99
|
}
|
|
100
|
+
export function webHeaders(req) {
|
|
101
|
+
const headers = new Headers();
|
|
102
|
+
for (const [name, value] of Object.entries(req.headers)) {
|
|
103
|
+
if (Array.isArray(value)) {
|
|
104
|
+
for (const item of value)
|
|
105
|
+
headers.append(name, item);
|
|
106
|
+
}
|
|
107
|
+
else if (value !== undefined) {
|
|
108
|
+
headers.set(name, value);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
headers.set("x-real-ip", clientIp(req));
|
|
112
|
+
return headers;
|
|
113
|
+
}
|
|
114
|
+
export async function webRequest(req) {
|
|
115
|
+
const host = req.headers.host ?? "localhost";
|
|
116
|
+
const hostname = host.split(":")[0]?.toLowerCase();
|
|
117
|
+
const protocol = hostname === "localhost" || hostname === "127.0.0.1" ? "http" : "https";
|
|
118
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
119
|
+
const body = method === "GET" || method === "HEAD" ? undefined : await readBody(req);
|
|
120
|
+
return new globalThis.Request(`${protocol}://${host}${req.originalUrl || req.url}`, {
|
|
121
|
+
method,
|
|
122
|
+
headers: webHeaders(req),
|
|
123
|
+
...(body ? { body } : {}),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
export async function sendWebResponse(res, response) {
|
|
127
|
+
for (const [name, value] of response.headers.entries()) {
|
|
128
|
+
if (name.toLowerCase() !== "set-cookie")
|
|
129
|
+
res.setHeader(name, value);
|
|
130
|
+
}
|
|
131
|
+
const cookies = response.headers.getSetCookie();
|
|
132
|
+
if (cookies.length)
|
|
133
|
+
res.setHeader("set-cookie", cookies);
|
|
134
|
+
const body = Buffer.from(await response.arrayBuffer());
|
|
135
|
+
res.status(response.status).send(body);
|
|
136
|
+
}
|
|
122
137
|
/**
|
|
123
138
|
* THE gating decision, for one request, independent of how it will be answered.
|
|
124
139
|
*
|
|
@@ -154,9 +169,8 @@ export async function gateRequest(req, options) {
|
|
|
154
169
|
stripSessionCookie(req);
|
|
155
170
|
return "pass";
|
|
156
171
|
}
|
|
157
|
-
// Every other /api/* needs a valid
|
|
158
|
-
const
|
|
159
|
-
const email = await gate.session(cookie);
|
|
172
|
+
// Every other /api/* needs a valid Better Auth session.
|
|
173
|
+
const email = await gate.session(webHeaders(req));
|
|
160
174
|
if (!email)
|
|
161
175
|
return "deny";
|
|
162
176
|
injectIdentity(req, email);
|
|
@@ -168,12 +182,6 @@ export const UNAUTHORIZED_BODY = {
|
|
|
168
182
|
error: "authentication required",
|
|
169
183
|
loginPath: AUTH_PREFIX,
|
|
170
184
|
};
|
|
171
|
-
/** The `Set-Cookie` value that issues a verified session. */
|
|
172
|
-
export function sessionSetCookie(sessionToken, maxAgeSeconds) {
|
|
173
|
-
return sessionCookie(sessionToken, maxAgeSeconds);
|
|
174
|
-
}
|
|
175
|
-
/** The `Set-Cookie` value that clears the session. */
|
|
176
|
-
export const LOGOUT_SET_COOKIE = `${SESSION_COOKIE_NAME}=; Path=/; HttpOnly; Max-Age=0`;
|
|
177
185
|
/**
|
|
178
186
|
* Register the login routes and the gating middleware on the app's Express
|
|
179
187
|
* instance. Called from {@link AuthGatePlugin} with the router AppKit hands
|
|
@@ -183,64 +191,34 @@ export const LOGOUT_SET_COOKIE = `${SESSION_COOKIE_NAME}=; Path=/; HttpOnly; Max
|
|
|
183
191
|
* routes live at an ABSOLUTE path (`/api/email/auth/*`, the client's contract),
|
|
184
192
|
* not under the plugin's `/api/authGate` base.
|
|
185
193
|
*/
|
|
186
|
-
export function mountGate(opts,
|
|
194
|
+
export function mountGate(opts, _addRoute, addMiddleware) {
|
|
187
195
|
const { gate, publicDomain, forwardHeaders } = opts;
|
|
188
196
|
const headerPolicy = toHeaderPolicy(forwardHeaders);
|
|
189
197
|
logger.debug("gate mounted", { publicDomain, forward: headerPolicy.patterns });
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// the gate does not apply - not the session state of a cookie it would never
|
|
194
|
-
// check. Without this, a browser on `localhost` renders the OTP login screen
|
|
195
|
-
// for a request that would have passed through untouched.
|
|
196
|
-
if (!isTunnelHost(req, publicDomain)) {
|
|
197
|
-
sendJson(res, 200, { authenticated: false, enabled: false });
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
const cookie = http.parseCookies(req.headers.cookie ?? null)[SESSION_COOKIE_NAME];
|
|
201
|
-
sendJson(res, 200, await gate.status(cookie));
|
|
202
|
-
});
|
|
203
|
-
const requestHandler = (async (req, res) => {
|
|
204
|
-
if (!isTunnelHost(req, publicDomain)) {
|
|
205
|
-
sendJson(res, 404, { error: "not found" });
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
const parsed = authRequestSchema.safeParse(json.parseRecord(await readBody(req)));
|
|
209
|
-
if (!parsed.success)
|
|
210
|
-
return sendJson(res, 200, { ok: true }); // anti-enumeration
|
|
211
|
-
sendJson(res, 200, await gate.request(parsed.data.email, clientIp(req)));
|
|
212
|
-
});
|
|
213
|
-
const verifyHandler = (async (req, res) => {
|
|
214
|
-
if (!isTunnelHost(req, publicDomain)) {
|
|
215
|
-
sendJson(res, 404, { error: "not found" });
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
const parsed = authVerifySchema.safeParse(json.parseRecord(await readBody(req)));
|
|
219
|
-
if (!parsed.success)
|
|
220
|
-
return sendJson(res, 200, { ok: false });
|
|
221
|
-
const result = await gate.verify(parsed.data.email, parsed.data.code, clientIp(req));
|
|
222
|
-
const cookie = result.ok && result.token ? sessionCookie(result.token, gate.sessionTtlSeconds) : undefined;
|
|
223
|
-
sendJson(res, 200, { ok: result.ok, ...(result.retryAfter ? { retryAfter: result.retryAfter } : {}) }, cookie);
|
|
224
|
-
});
|
|
225
|
-
const logoutHandler = ((req, res) => {
|
|
198
|
+
// Better Auth and the compatibility routes share one fetch-compatible
|
|
199
|
+
// handler in both hosting modes.
|
|
200
|
+
const authHandler = (async (req, res) => {
|
|
226
201
|
if (!isTunnelHost(req, publicDomain)) {
|
|
227
|
-
|
|
202
|
+
const path = (req.url ?? "/").split("?")[0] ?? "/";
|
|
203
|
+
if (path.endsWith("/status")) {
|
|
204
|
+
res.status(200).json({ authenticated: false, enabled: false, passkeysEnabled: false });
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
res.status(404).json({ error: "not found" });
|
|
208
|
+
}
|
|
228
209
|
return;
|
|
229
210
|
}
|
|
230
|
-
|
|
211
|
+
await sendWebResponse(res, await gate.handler(await webRequest(req)));
|
|
231
212
|
});
|
|
232
|
-
|
|
233
|
-
addRoute("post", `${AUTH_PREFIX}/request`, requestHandler);
|
|
234
|
-
addRoute("post", `${AUTH_PREFIX}/verify`, verifyHandler);
|
|
235
|
-
addRoute("post", `${AUTH_PREFIX}/logout`, logoutHandler);
|
|
213
|
+
addMiddleware(AUTH_PREFIX, authHandler);
|
|
236
214
|
// --- The gate middleware (runs before static + the app's /api handlers) ---
|
|
237
215
|
const gateMiddleware = (async (req, res, next) => {
|
|
238
216
|
const action = await gateRequest(req, { gate, publicDomain, headerPolicy });
|
|
239
217
|
if (action === "deny")
|
|
240
|
-
|
|
218
|
+
res.status(401).json(UNAUTHORIZED_BODY);
|
|
241
219
|
else
|
|
242
220
|
next();
|
|
243
221
|
});
|
|
244
222
|
addMiddleware("/", gateMiddleware);
|
|
245
223
|
}
|
|
246
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBR0gsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRW5HLE9BQU8sRUFBRSxjQUFjLEVBQXFCLE1BQU0sY0FBYyxDQUFDO0FBR2pFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7QUFFekMsMkVBQTJFO0FBQzNFLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQztBQW9CN0M7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsR0FBb0IsRUFBRSxZQUFnQztJQUNqRixJQUFJLENBQUMsWUFBWTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ2hDLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLE9BQU8sSUFBSSxLQUFLLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQUVELHVFQUF1RTtBQUN2RSxTQUFTLGFBQWEsQ0FBQyxLQUFhLEVBQUUsYUFBcUI7SUFDekQsT0FBTztRQUNMLEdBQUcsbUJBQW1CLElBQUksS0FBSyxFQUFFO1FBQ2pDLFFBQVE7UUFDUixVQUFVO1FBQ1YsY0FBYztRQUNkLFdBQVcsYUFBYSxFQUFFO1FBQzFCLDZF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QUcsV0FBVyxTQUFTLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDekQsUUFBUSxDQUFDLE1BQU0sRUFBRSxHQUFHLFdBQVcsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBRXpELDZFQUE2RTtJQUU3RSxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFO1FBQy9DLE1BQU0sTUFBTSxHQUFHLE1BQU0sV0FBVyxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUM1RSxJQUFJLE1BQU0sS0FBSyxNQUFNO1lBQUUsUUFBUSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsaUJBQWlCLENBQUMsQ0FBQzs7WUFDeEQsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDLENBQW1CLENBQUM7SUFFckIsYUFBYSxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgdHVubmVsJ3MgaW4tYXBwIEFVVEggR0FURSAtIEV4cHJlc3MgbWlkZGxld2FyZSArIGxvZ2luIHJvdXRlcyB0aGVcbiAqIHtAbGluayBBdXRoR2F0ZVBsdWdpbn0gcmVnaXN0ZXJzIG9uIHRoZSBhcHAncyBPV04gc2VydmVyIHZpYSBgdGhpcy5jb250ZXh0YC5cbiAqXG4gKiBUaGUgZ2F0ZSBpcyBNSURETEVXQVJFLCBub3QgYSByZXZlcnNlIHByb3h5IC0gdGhlIGFwcCBpcyB0aGUgcHJvY2Vzcywgc28gdGhlcmUgaXNcbiAqIG5vdGhpbmcgdG8gZm9yd2FyZCB0by4gSXQgZWl0aGVyIHNob3J0LWNpcmN1aXRzICg0MDEsIG9yIGFuc3dlcnMgdGhlIG9wZW4gbG9naW5cbiAqIHJvdXRlcykgb3IgY2FsbHMgYG5leHQoKWAgdG8gbGV0IHRoZSBhcHAncyByZWFsIGhhbmRsZXJzIHJ1bi4gSXQgaXMgdGhlXG4gKiBcInN0YW5kcyBpbiBmb3IgQXBwS2l0IGF1dGhcIiBwYXRoOlxuICogYSBwb3J0ciBjYWxsZXIgcHJvdmVzIGFuIGVtYWlsIHZpYSBPVFAsIGFuZCBvbiBzdWNjZXNzIHRoZSBnYXRlIGluamVjdHMgdGhlXG4gKiBpZGVudGl0eSBoZWFkZXJzIEFwcEtpdCByZWFkcywgc28gYSBnYXRlZCByZXF1ZXN0IHJ1bnMgbGlrZSBhIGZyb250LWRvb3Igb25lLlxuICpcbiAqIFdISUNIIFRSQUZGSUMgSVMgR0FURUQgLSB0aGUgYEhvc3RgIGhlYWRlciwgbm90IHRoZSBzb2NrZXQuIHBvcnRyJ3MgY2xpZW50XG4gKiBmb3J3YXJkcyB3aXRoIEdvJ3MgYGh0dHB1dGlsLk5ld1NpbmdsZUhvc3RSZXZlcnNlUHJveHlgIGFuZCBhIGBEaXJlY3RvcmAgdGhhdFxuICogUFJFU0VSVkVTIHRoZSBvcmlnaW5hbCBgSG9zdGAsIHNvIHR1bm5lbCByZXF1ZXN0cyBhcnJpdmUgd2l0aFxuICogYEhvc3Q6IDxzdWJkb21haW4+LjxzZXJ2ZXI+YCAodGhlIHB1YmxpYyBkb21haW4pLiBBIGxvY2FsIHByb2Nlc3MgaGl0dGluZyB0aGVcbiAqIGFwcCBkaXJlY3RseSBzZW5kcyBgSG9zdDogMTI3LjAuMC4xOjxwb3J0PmAgLyBgbG9jYWxob3N0YC4gU28gT05MWSByZXF1ZXN0cyB3aG9zZVxuICogYEhvc3RgIG1hdGNoZXMgdGhlIGNvbmZpZ3VyZWQgcHVibGljIGRvbWFpbiBhcmUgZ2F0ZWQ7IHRoZSBwbGF0Zm9ybSBmcm9udCBkb29yXG4gKiBhbmQgYW55IG90aGVyIGxvY2FsIGNsaWVudCBwYXNzIHRocm91Z2ggdW50b3VjaGVkLiBUaGVyZSBpcyBubyBwb3J0ci1pbmplY3RlZFxuICogaWRlbnRpZnlpbmcgaGVhZGVyIGFuZCBubyBUQ1Avc291cmNlLUlQIHNpZ25hbCB0byB1c2UgaW5zdGVhZCAodGhlIGNsaWVudCBkaWFsc1xuICogdGhlIHRhcmdldCBvdmVyIHBsYWluIGxvb3BiYWNrKS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBJbmNvbWluZ01lc3NhZ2UgfSBmcm9tIFwibm9kZTpodHRwXCI7XG5pbXBvcnQgeyBodHRwLCBqc29uLCBsb2csIHRva2VuIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGF1dGhSZXF1ZXN0U2NoZW1hLCBhdXRoVmVyaWZ5U2NoZW1hLCBTRVNTSU9OX0NPT0tJRV9OQU1FIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWVtYWlsXCI7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3QsIFJlcXVlc3RIYW5kbGVyLCBSZXNwb25zZSB9IGZyb20gXCJleHByZXNzXCI7XG5pbXBvcnQgeyB0b0hlYWRlclBvbGljeSwgdHlwZSBIZWFkZXJQb2xpY3kgfSBmcm9tIFwiLi9oZWFkZXJzLnRzXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhHYXRlQXBpIH0gZnJvbSBcIi4vcGx1Z2luLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6Z2F0ZVwiKTtcblxuLyoqIFJvdXRlIHByZWZpeCB0aGUgbG9naW4gZmxvdyBsaXZlcyB1bmRlciAob3BlbiwgYW5zd2VyZWQgaW4tcHJvY2VzcykuICovXG5leHBvcnQgY29uc3QgQVVUSF9QUkVGSVggPSBcIi9hcGkvZW1haWwvYXV0aFwiO1xuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIG1vdW50R2F0ZX0uICovXG5leHBvcnQgaW50ZXJmYWNlIEdhdGVPcHRpb25zIHtcbiAgLyoqIFRoZSBpbi1wcm9jZXNzIGdhdGUgQVBJIChzZXNzaW9uL3JlcXVlc3QvdmVyaWZ5L3N0YXR1cykuICovXG4gIGdhdGU6IEF1dGhHYXRlQXBpO1xuICAvKipcbiAgICogVGhlIHB1YmxpYyBgPHN1YmRvbWFpbj4uPHNlcnZlcj5gIHRoYXQgaWRlbnRpZmllcyBwb3J0ciB0cmFmZmljIGJ5IGBIb3N0YC5cbiAgICogV2hlbiBhYnNlbnQsIG5vIHJlcXVlc3QgaXMgZXZlciBjbGFzc2lmaWVkIGFzIHR1bm5lbCB0cmFmZmljIGFuZCB0aGUgZ2F0ZSBpc1xuICAgKiBpbmVydCAoZXZlcnl0aGluZyBwYXNzZXMgdGhyb3VnaCkgLSBhIHR1bm5lbCB3aXRoIG5vIHB1YmxpYyBkb21haW4gZ2F0ZXNcbiAgICogbm90aGluZy5cbiAgICovXG4gIHB1YmxpY0RvbWFpbj86IHN0cmluZztcbiAgLyoqXG4gICAqIEV4dHJhIGB4LWAgcmVxdWVzdCBoZWFkZXJzIHR1bm5lbCB0cmFmZmljIG1heSBmb3J3YXJkICh1bmlvbmVkIHdpdGggdGhlXG4gICAqIGJ1aWx0LWluIGFsbG93LWxpc3QpLiBFdmVyeSBvdGhlciBgeC1gIGhlYWRlciBpcyBzdHJpcHBlZCBmcm9tIHR1bm5lbCB0cmFmZmljLlxuICAgKi9cbiAgZm9yd2FyZEhlYWRlcnM/OiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUcnVlIHdoZW4gdGhlIHJlcXVlc3QncyBgSG9zdGAgaXMgdGhlIHR1bm5lbCdzIHB1YmxpYyBkb21haW4gLSBpLmUuIGl0IGNhbWUgaW5cbiAqIG92ZXIgcG9ydHIuIENhc2UtaW5zZW5zaXRpdmU7IHRoZSBvcHRpb25hbCBgOnBvcnRgIGlzIGlnbm9yZWQuIFdoZW4gbm8gcHVibGljXG4gKiBkb21haW4gaXMgY29uZmlndXJlZCwgbm90aGluZyBpcyB0dW5uZWwgdHJhZmZpYy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHVubmVsSG9zdChyZXE6IEluY29taW5nTWVzc2FnZSwgcHVibGljRG9tYWluOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFwdWJsaWNEb21haW4pIHJldHVybiBmYWxzZTtcbiAgY29uc3QgaG9zdCA9IChyZXEuaGVhZGVycy5ob3N0ID8/IFwiXCIpLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xuICByZXR1cm4gaG9zdCA9PT0gcHVibGljRG9tYWluLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xufVxuXG4vKiogVGhlIHNlc3Npb24gY29va2llIGZvciBhIHZlcmlmaWVkIGVtYWlsLCBhcyBhIFNldC1Db29raWUgc3RyaW5nLiAqL1xuZnVuY3Rpb24gc2Vzc2lvbkNvb2tpZSh2YWx1ZTogc3RyaW5nLCBtYXhBZ2VTZWNvbmRzOiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gW1xuICAgIGAke1NFU1NJT05fQ09PS0lFX05BTUV9PSR7dmFsdWV9YCxcbiAgICBcIlBhdGg9L1wiLFxuICAgIFwiSHR0cE9ubHlcIixcbiAgICBcIlNhbWVTaXRlPUxheFwiLFxuICAgIGBNYXgtQWdlPSR7bWF4QWdlU2Vjb25kc31gLFxuICAgIC8vIFJlYWwgZW5mb3JjZW1lbnQgaW4gcHJvZHVjdGlvbjogdGhlIHNlc3Npb24gY29va2llIG11c3QgYmUgU2VjdXJlIHNvIGl0IGlzXG4gICAgLy8gbmV2ZXIgc2VudCBvdmVyIHBsYWludGV4dC4gTG9jYWwgZGV2IChodHRwKSBvbWl0cyBpdCBzbyB0aGUgY29va2llIHdvcmtzLlxuICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSBcInByb2R1Y3Rpb25cIiA/IFwiU2VjdXJlXCIgOiBcIlwiLFxuICBdXG4gICAgLmZpbHRlcihCb29sZWFuKVxuICAgIC5qb2luKFwiOyBcIik7XG59XG5cbi8qKlxuICogQ2xpZW50IElQIGZvciByYXRlLWxpbWl0aW5nOiB0aGUgUklHSFRNT1NUIGB4LWZvcndhcmRlZC1mb3JgIGVudHJ5ICh0aGUgdmFsdWVcbiAqIHRoZSBuZWFyZXN0IHRydXN0ZWQgaG9wIC0gcG9ydHIgLSB3cm90ZSksIGVsc2UgdGhlIHNvY2tldCBhZGRyZXNzLiBSZWFkaW5nIHRoZVxuICogcmlnaHRtb3N0LCBub3QgdGhlIGxlZnRtb3N0LCBzdG9wcyBhIGNhbGxlciBtaW50aW5nIGEgZnJlc2ggcmF0ZS1saW1pdCBidWNrZXQgYnlcbiAqIHZhcnlpbmcgdGhlIGhlYWRlci4gQ2FsbGVkIGJlZm9yZSB7QGxpbmsgc3RyaXBIZWFkZXJzfS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsaWVudElwKHJlcTogSW5jb21pbmdNZXNzYWdlKTogc3RyaW5nIHtcbiAgY29uc3QgZm9yd2FyZGVkID0gcmVxLmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1mb3JcIl07XG4gIGNvbnN0IGNoYWluID0gKEFycmF5LmlzQXJyYXkoZm9yd2FyZGVkKSA/IGZvcndhcmRlZC5qb2luKFwiLFwiKSA6IChmb3J3YXJkZWQgPz8gXCJcIikpXG4gICAgLnNwbGl0KFwiLFwiKVxuICAgIC5tYXAoKGVudHJ5KSA9PiBlbnRyeS50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbiAgcmV0dXJuIGNoYWluLmF0KC0xKSA/PyByZXEuc29ja2V0LnJlbW90ZUFkZHJlc3MgPz8gXCJ1bmtub3duXCI7XG59XG5cbi8qKlxuICogUmVtb3ZlIHRoZSBnYXRlJ3Mgc2Vzc2lvbiBjb29raWUgZnJvbSB0aGUgYENvb2tpZWAgaGVhZGVyIGJlZm9yZSB0aGUgYXBwJ3NcbiAqIGhhbmRsZXJzIHJ1biwgc28gdGhlIGFwcCBuZXZlciBzZWVzIGBkYnhfYXV0aGAgKGl0IGlzIHRoZSBnYXRlJ3MgY29uY2VybikuXG4gKiBQcmVzZXJ2ZXMgb3RoZXIgY29va2llczsgZGVsZXRlcyB0aGUgaGVhZGVyIHdoZW4gaXQgYmVjb21lcyBlbXB0eS5cbiAqL1xuZnVuY3Rpb24gc3RyaXBTZXNzaW9uQ29va2llKHJlcTogSW5jb21pbmdNZXNzYWdlKTogdm9pZCB7XG4gIGNvbnN0IHJhdyA9IHJlcS5oZWFkZXJzLmNvb2tpZTtcbiAgaWYgKCFyYXcpIHJldHVybjtcbiAgY29uc3Qga2VwdCA9IHJhd1xuICAgIC5zcGxpdChcIjtcIilcbiAgICAubWFwKChjKSA9PiBjLnRyaW0oKSlcbiAgICAuZmlsdGVyKChjKSA9PiBjICYmICFjLnN0YXJ0c1dpdGgoYCR7U0VTU0lPTl9DT09LSUVfTkFNRX09YCkpO1xuICBpZiAoa2VwdC5sZW5ndGgpIHJlcS5oZWFkZXJzLmNvb2tpZSA9IGtlcHQuam9pbihcIjsgXCIpO1xuICBlbHNlIGRlbGV0ZSByZXEuaGVhZGVycy5jb29raWU7XG59XG5cbi8qKlxuICogUHJlc2VudCBhbiBPVFAtYXV0aGVudGljYXRlZCBjYWxsZXIgdG8gdGhlIGFwcCB0aGUgU0FNRSB3YXkgYSBwbGF0Zm9ybSBmcm9udFxuICogZG9vciBkb2VzOiBzZXQgdGhlIGZyb250LWRvb3IgaWRlbnRpdHkgaGVhZGVycyB0byB0aGUgdmVyaWZpZWQgYWRkcmVzcyAoQXBwS2l0XG4gKiByZWFkcyB7QGxpbmsgdG9rZW4uVVNFUl9JRF9IRUFERVJ9IGZvciB0aGUgT0JPIHVzZXIgaWQpLCBzbyB0aGUgYXBwIG5lZWRzIG5vXG4gKiBnYXRlLXNwZWNpZmljIGNvZGUgcGF0aC5cbiAqXG4gKiBXaGF0IHRoZSBnYXRlIENBTk5PVCBzZXQgaXMge0BsaW5rIHRva2VuLkFDQ0VTU19UT0tFTl9IRUFERVJ9OiBhbiBPVFAgc2Vzc2lvblxuICogcHJvdmVzIGFuIGVtYWlsLCBub3QgcG9zc2Vzc2lvbiBvZiBhIERhdGFicmlja3MgY3JlZGVudGlhbC4gSXRzIGFic2VuY2UgaXMgd2hhdFxuICogYEBkYngtdG9vbHMvYXBwa2l0YCdzIGBpZGVudGl0eTogXCJhdXRvXCJgIGRldGVjdHMsIHNvIGEgZ2F0ZWQgcmVxdWVzdCBydW5zIGFzIHRoZVxuICogYXBwIHNlcnZpY2UgcHJpbmNpcGFsIGluc3RlYWQgb2YgdGhyb3dpbmcuXG4gKi9cbmZ1bmN0aW9uIGluamVjdElkZW50aXR5KHJlcTogSW5jb21pbmdNZXNzYWdlLCBlbWFpbDogc3RyaW5nKTogdm9pZCB7XG4gIHJlcS5oZWFkZXJzW3Rva2VuLlVTRVJfSURfSEVBREVSXSA9IGVtYWlsO1xuICByZXEuaGVhZGVyc1t0b2tlbi5VU0VSX0VNQUlMX0hFQURFUl0gPSBlbWFpbDtcbn1cblxuZnVuY3Rpb24gc2VuZEpzb24ocmVzOiBSZXNwb25zZSwgc3RhdHVzOiBudW1iZXIsIGJvZHk6IHVua25vd24sIHNldENvb2tpZT86IHN0cmluZyk6IHZvaWQge1xuICBpZiAoc2V0Q29va2llKSByZXMuc2V0SGVhZGVyKFwic2V0LWNvb2tpZVwiLCBzZXRDb29raWUpO1xuICByZXMuc3RhdHVzKHN0YXR1cykuanNvbihib2R5KTtcbn1cblxuLyoqIFJlYWQgdGhlIHJhdyByZXF1ZXN0IGJvZHkgYXMgdGV4dCAoQXBwS2l0IHBhcnNlcyBKU09OLCBidXQgdGhlIGdhdGUgcm91dGVzXG4gKiBhcmUgbW91bnRlZCBiZWZvcmUgdGhhdCBydW5zIGZvciB0dW5uZWwgdHJhZmZpYywgc28gcmVhZCBkZWZlbnNpdmVseSkuICovXG5mdW5jdGlvbiByZWFkQm9keShyZXE6IFJlcXVlc3QpOiBQcm9taXNlPHN0cmluZz4ge1xuICAvLyBBcHBLaXQncyBqc29uIGJvZHktcGFyc2VyIG1heSBoYXZlIGFscmVhZHkgcG9wdWxhdGVkIHJlcS5ib2R5OyBwcmVmZXIgaXQuXG4gIGlmIChyZXEuYm9keSAhPT0gdW5kZWZpbmVkICYmIHJlcS5ib2R5ICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0eXBlb2YgcmVxLmJvZHkgPT09IFwic3RyaW5nXCIgPyByZXEuYm9keSA6IEpTT04uc3RyaW5naWZ5KHJlcS5ib2R5KSk7XG4gIH1cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgbGV0IGRhdGEgPSBcIlwiO1xuICAgIHJlcS5vbihcImRhdGFcIiwgKGNodW5rKSA9PiAoZGF0YSArPSBjaHVuaykpO1xuICAgIHJlcS5vbihcImVuZFwiLCAoKSA9PiByZXNvbHZlKGRhdGEpKTtcbiAgICByZXEub24oXCJlcnJvclwiLCAoKSA9PiByZXNvbHZlKGRhdGEpKTtcbiAgfSk7XG59XG5cbi8qKlxuICogV2hhdCB0aGUgY2FsbGVyIHNob3VsZCBkbyB3aXRoIGEgcmVxdWVzdCwgZnJvbSB7QGxpbmsgZ2F0ZVJlcXVlc3R9LlxuICpcbiAqICAgLSBgcGFzc2AgLSBub3QgdHVubmVsIHRyYWZmaWMsIG9yIGFuIG9wZW4gbG9naW4gcm91dGUuIEZvcndhcmQgdW50b3VjaGVkLlxuICogICAtIGBhbGxvd2AgLSB0dW5uZWwgdHJhZmZpYyB0aGF0IGlzIGF1dGhvcml6ZWQuIFRoZSByZXF1ZXN0J3MgaGVhZGVycyBoYXZlXG4gKiAgICAgQUxSRUFEWSBiZWVuIHJld3JpdHRlbiAocG9saWN5IGFwcGxpZWQsIGlkZW50aXR5IGluamVjdGVkLCBzZXNzaW9uIGNvb2tpZVxuICogICAgIHN0cmlwcGVkKSwgc28gZm9yd2FyZCBpdCBhcyBpdCBub3cgc3RhbmRzLlxuICogICAtIGBkZW55YCAtIHR1bm5lbCB0cmFmZmljIHdpdGggbm8gdmFsaWQgc2Vzc2lvbi4gQW5zd2VyIGA0MDFgIHdpdGhcbiAqICAgICB7QGxpbmsgQVVUSF9QUkVGSVh9IGFzIHRoZSBsb2dpbiBwYXRoLlxuICovXG5leHBvcnQgdHlwZSBHYXRlQWN0aW9uID0gXCJwYXNzXCIgfCBcImFsbG93XCIgfCBcImRlbnlcIjtcblxuLyoqXG4gKiBUSEUgZ2F0aW5nIGRlY2lzaW9uLCBmb3Igb25lIHJlcXVlc3QsIGluZGVwZW5kZW50IG9mIGhvdyBpdCB3aWxsIGJlIGFuc3dlcmVkLlxuICpcbiAqIEJvdGggcGF0aHMgY2FsbCB0aGlzOiB0aGUgRXhwcmVzcyBtaWRkbGV3YXJlIGJlbG93ICh3aGVyZSB0aGUgYXBwIGlzIHRoZVxuICogcHJvY2VzcykgYW5kIGBAZGJ4LXRvb2xzL2NsaS10dW5uZWxgJ3MgcmV2ZXJzZSBwcm94eSAod2hlcmUgdGhlIGFwcCBpcyBhIGNoaWxkXG4gKiBwcm9jZXNzIG9uIGEgcHJpdmF0ZSBwb3J0KS4gQSBkaXZlcmdlbmNlIGJldHdlZW4gdGhlbSB3b3VsZCBiZSBhIHNlY3VyaXR5IGJ1Z1xuICogdGhlIHNlY29uZCBwYXRoIGNvdWxkIG5vdCBiZSB0ZXN0ZWQgaW50byBhZ3JlZW1lbnQgLSBvbmUgcGF0aCBmb3JnZXR0aW5nIHRvXG4gKiBzdHJpcCBgeC1mb3J3YXJkZWQtYWNjZXNzLXRva2VuYCBpcyBlbm91Z2ggLSBzbyB0aGUgZGVjaXNpb24sIHRoZSBoZWFkZXJcbiAqIHJld3JpdGluZywgYW5kIHRoZSBpZGVudGl0eSBpbmplY3Rpb24gbGl2ZSBoZXJlIG9uY2UgYW5kIHRoZSB0cmFuc3BvcnRzIG9ubHlcbiAqIGRpZmZlciBpbiBob3cgdGhleSBXUklURSB0aGUgb3V0Y29tZS5cbiAqXG4gKiBNdXRhdGVzIGByZXEuaGVhZGVyc2Agb24gdGhlIGBhbGxvd2AvYHBhc3NgLXdpdGgtY29va2llIHBhdGhzLCB3aGljaCBpcyBleGFjdGx5XG4gKiB3aGF0IGJvdGggY2FsbGVycyB3YW50OiBFeHByZXNzIGhhbmRzIHRoZSBzYW1lIG9iamVjdCB0byB0aGUgYXBwJ3MgaGFuZGxlcnMsIGFuZFxuICogdGhlIHByb3h5IGZvcndhcmRzIGl0IHVwc3RyZWFtLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2F0ZVJlcXVlc3QoXG4gIHJlcTogSW5jb21pbmdNZXNzYWdlLFxuICBvcHRpb25zOiBHYXRlT3B0aW9ucyAmIHsgaGVhZGVyUG9saWN5PzogSGVhZGVyUG9saWN5IH0sXG4pOiBQcm9taXNlPEdhdGVBY3Rpb24+IHtcbiAgY29uc3QgeyBnYXRlLCBwdWJsaWNEb21haW4gfSA9IG9wdGlvbnM7XG4gIC8vIE5vdCB0dW5uZWwgdHJhZmZpYyAocGxhdGZvcm0gZnJvbnQgZG9vciwgb3IgYW55IG90aGVyIGxvY2FsIGNhbGxlcik6IHRoZVxuICAvLyByZXF1ZXN0IGlzIGFscmVhZHkgYXV0aGVudGljYXRlZCwgb3IgaXMgbm90IG91cnMgdG8gZ2F0ZS5cbiAgaWYgKCFpc1R1bm5lbEhvc3QocmVxLCBwdWJsaWNEb21haW4pKSByZXR1cm4gXCJwYXNzXCI7XG5cbiAgY29uc3QgcGF0aCA9IChyZXEudXJsID8/IFwiL1wiKS5zcGxpdChcIj9cIilbMF0gPz8gXCIvXCI7XG4gIC8vIFRoZSBsb2dpbiBmbG93IGlzIG9wZW4gc28gdGhlIGJyb3dzZXIgY2FuIHJlbmRlciA8QXV0aEdhdGU+IGFuZCBzaWduIGluLlxuICBpZiAocGF0aC5zdGFydHNXaXRoKEFVVEhfUFJFRklYKSkgcmV0dXJuIFwicGFzc1wiO1xuXG4gIC8vIEFudGktc3Bvb2Y6IG9ubHkgdGhlIGdhdGUgbWF5IGFzc2VydCBpZGVudGl0eSBvbiB0dW5uZWwgdHJhZmZpYy5cbiAgY29uc3QgcG9saWN5ID0gb3B0aW9ucy5oZWFkZXJQb2xpY3kgPz8gdG9IZWFkZXJQb2xpY3kob3B0aW9ucy5mb3J3YXJkSGVhZGVycyk7XG4gIGNvbnN0IHJlbW92ZWQgPSBwb2xpY3kuYXBwbHkocmVxLmhlYWRlcnMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pO1xuICBpZiAocmVtb3ZlZC5sZW5ndGgpIGxvZ2dlci5kZWJ1ZyhcInN0cmlwcGVkIGluYm91bmQgaGVhZGVyc1wiLCB7IHJlbW92ZWQgfSk7XG5cbiAgLy8gU3RhdGljIChub24tQVBJKSBsb2FkcyBmcmVlbHkgc28gdGhlIFNQQSBjYW4gcmVuZGVyOyBkcm9wIHRoZSBnYXRlIGNvb2tpZS5cbiAgaWYgKCFwYXRoLnN0YXJ0c1dpdGgoXCIvYXBpL1wiKSkge1xuICAgIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXEpO1xuICAgIHJldHVybiBcInBhc3NcIjtcbiAgfVxuXG4gIC8vIEV2ZXJ5IG90aGVyIC9hcGkvKiBuZWVkcyBhIHZhbGlkIE9UUCBzZXNzaW9uLlxuICBjb25zdCBjb29raWUgPSBodHRwLnBhcnNlQ29va2llcyhyZXEuaGVhZGVycy5jb29raWUgPz8gbnVsbClbU0VTU0lPTl9DT09LSUVfTkFNRV07XG4gIGNvbnN0IGVtYWlsID0gYXdhaXQgZ2F0ZS5zZXNzaW9uKGNvb2tpZSk7XG4gIGlmICghZW1haWwpIHJldHVybiBcImRlbnlcIjtcbiAgaW5qZWN0SWRlbnRpdHkocmVxLCBlbWFpbCk7XG4gIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXEpO1xuICByZXR1cm4gXCJhbGxvd1wiO1xufVxuXG4vKiogVGhlIGJvZHkgb2YgYSBgZGVueWAsIHNoYXJlZCBzbyBib3RoIHBhdGhzIGFuc3dlciBhIDQwMSBpZGVudGljYWxseS4gKi9cbmV4cG9ydCBjb25zdCBVTkFVVEhPUklaRURfQk9EWSA9IHtcbiAgZXJyb3I6IFwiYXV0aGVudGljYXRpb24gcmVxdWlyZWRcIixcbiAgbG9naW5QYXRoOiBBVVRIX1BSRUZJWCxcbn0gYXMgY29uc3Q7XG5cbi8qKiBUaGUgYFNldC1Db29raWVgIHZhbHVlIHRoYXQgaXNzdWVzIGEgdmVyaWZpZWQgc2Vzc2lvbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXNzaW9uU2V0Q29va2llKHNlc3Npb25Ub2tlbjogc3RyaW5nLCBtYXhBZ2VTZWNvbmRzOiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gc2Vzc2lvbkNvb2tpZShzZXNzaW9uVG9rZW4sIG1heEFnZVNlY29uZHMpO1xufVxuXG4vKiogVGhlIGBTZXQtQ29va2llYCB2YWx1ZSB0aGF0IGNsZWFycyB0aGUgc2Vzc2lvbi4gKi9cbmV4cG9ydCBjb25zdCBMT0dPVVRfU0VUX0NPT0tJRSA9IGAke1NFU1NJT05fQ09PS0lFX05BTUV9PTsgUGF0aD0vOyBIdHRwT25seTsgTWF4LUFnZT0wYDtcblxuLyoqXG4gKiBSZWdpc3RlciB0aGUgbG9naW4gcm91dGVzIGFuZCB0aGUgZ2F0aW5nIG1pZGRsZXdhcmUgb24gdGhlIGFwcCdzIEV4cHJlc3NcbiAqIGluc3RhbmNlLiBDYWxsZWQgZnJvbSB7QGxpbmsgQXV0aEdhdGVQbHVnaW59IHdpdGggdGhlIHJvdXRlciBBcHBLaXQgaGFuZHNcbiAqIGBpbmplY3RSb3V0ZXNgLCBwbHVzIGB0aGlzLmNvbnRleHQuYWRkTWlkZGxld2FyZWAgZm9yIHRoZSBnbG9iYWwgZ2F0ZS5cbiAqXG4gKiBgYWRkUm91dGVgL2BhZGRNaWRkbGV3YXJlYCBhcmUgdXNlZCAodmlhIHRoZSBwYXNzZWQgY2FsbGJhY2tzKSBiZWNhdXNlIHRoZSBsb2dpblxuICogcm91dGVzIGxpdmUgYXQgYW4gQUJTT0xVVEUgcGF0aCAoYC9hcGkvZW1haWwvYXV0aC8qYCwgdGhlIGNsaWVudCdzIGNvbnRyYWN0KSxcbiAqIG5vdCB1bmRlciB0aGUgcGx1Z2luJ3MgYC9hcGkvYXV0aEdhdGVgIGJhc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb3VudEdhdGUoXG4gIG9wdHM6IEdhdGVPcHRpb25zLFxuICBhZGRSb3V0ZTogKG1ldGhvZDogXCJnZXRcIiB8IFwicG9zdFwiLCBwYXRoOiBzdHJpbmcsIGhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSA9PiB2b2lkLFxuICBhZGRNaWRkbGV3YXJlOiAocGF0aDogc3RyaW5nLCBoYW5kbGVyOiBSZXF1ZXN0SGFuZGxlcikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBjb25zdCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgZm9yd2FyZEhlYWRlcnMgfSA9IG9wdHM7XG4gIGNvbnN0IGhlYWRlclBvbGljeSA9IHRvSGVhZGVyUG9saWN5KGZvcndhcmRIZWFkZXJzKTtcbiAgbG9nZ2VyLmRlYnVnKFwiZ2F0ZSBtb3VudGVkXCIsIHsgcHVibGljRG9tYWluLCBmb3J3YXJkOiBoZWFkZXJQb2xpY3kucGF0dGVybnMgfSk7XG5cbiAgLy8gLS0tIExvZ2luIHJvdXRlcyAob3BlbiBvbiB0dW5uZWwgdHJhZmZpYzsgYW5zd2VyZWQgaW4tcHJvY2VzcykgLS0tXG5cbiAgY29uc3Qgc3RhdHVzSGFuZGxlciA9IChhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICAvLyBBIGxvY2FsIG9yIGZyb250LWRvb3IgY2FsbGVyIGlzIG5ldmVyIGdhdGVkLCBzbyB0aGUgaG9uZXN0IGFuc3dlciBpcyB0aGF0XG4gICAgLy8gdGhlIGdhdGUgZG9lcyBub3QgYXBwbHkgLSBub3QgdGhlIHNlc3Npb24gc3RhdGUgb2YgYSBjb29raWUgaXQgd291bGQgbmV2ZXJcbiAgICAvLyBjaGVjay4gV2l0aG91dCB0aGlzLCBhIGJyb3dzZXIgb24gYGxvY2FsaG9zdGAgcmVuZGVycyB0aGUgT1RQIGxvZ2luIHNjcmVlblxuICAgIC8vIGZvciBhIHJlcXVlc3QgdGhhdCB3b3VsZCBoYXZlIHBhc3NlZCB0aHJvdWdoIHVudG91Y2hlZC5cbiAgICBpZiAoIWlzVHVubmVsSG9zdChyZXEsIHB1YmxpY0RvbWFpbikpIHtcbiAgICAgIHNlbmRKc29uKHJlcywgMjAwLCB7IGF1dGhlbnRpY2F0ZWQ6IGZhbHNlLCBlbmFibGVkOiBmYWxzZSB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY29va2llID0gaHR0cC5wYXJzZUNvb2tpZXMocmVxLmhlYWRlcnMuY29va2llID8/IG51bGwpW1NFU1NJT05fQ09PS0lFX05BTUVdO1xuICAgIHNlbmRKc29uKHJlcywgMjAwLCBhd2FpdCBnYXRlLnN0YXR1cyhjb29raWUpKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG5cbiAgY29uc3QgcmVxdWVzdEhhbmRsZXIgPSAoYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgaWYgKCFpc1R1bm5lbEhvc3QocmVxLCBwdWJsaWNEb21haW4pKSB7XG4gICAgICBzZW5kSnNvbihyZXMsIDQwNCwgeyBlcnJvcjogXCJub3QgZm91bmRcIiB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcGFyc2VkID0gYXV0aFJlcXVlc3RTY2hlbWEuc2FmZVBhcnNlKGpzb24ucGFyc2VSZWNvcmQoYXdhaXQgcmVhZEJvZHkocmVxKSkpO1xuICAgIGlmICghcGFyc2VkLnN1Y2Nlc3MpIHJldHVybiBzZW5kSnNvbihyZXMsIDIwMCwgeyBvazogdHJ1ZSB9KTsgLy8gYW50aS1lbnVtZXJhdGlvblxuICAgIHNlbmRKc29uKHJlcywgMjAwLCBhd2FpdCBnYXRlLnJlcXVlc3QocGFyc2VkLmRhdGEuZW1haWwsIGNsaWVudElwKHJlcSkpKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG5cbiAgY29uc3QgdmVyaWZ5SGFuZGxlciA9IChhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBpZiAoIWlzVHVubmVsSG9zdChyZXEsIHB1YmxpY0RvbWFpbikpIHtcbiAgICAgIHNlbmRKc29uKHJlcywgNDA0LCB7IGVycm9yOiBcIm5vdCBmb3VuZFwiIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBwYXJzZWQgPSBhdXRoVmVyaWZ5U2NoZW1hLnNhZmVQYXJzZShqc29uLnBhcnNlUmVjb3JkKGF3YWl0IHJlYWRCb2R5KHJlcSkpKTtcbiAgICBpZiAoIXBhcnNlZC5zdWNjZXNzKSByZXR1cm4gc2VuZEpzb24ocmVzLCAyMDAsIHsgb2s6IGZhbHNlIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdhdGUudmVyaWZ5KHBhcnNlZC5kYXRhLmVtYWlsLCBwYXJzZWQuZGF0YS5jb2RlLCBjbGllbnRJcChyZXEpKTtcbiAgICBjb25zdCBjb29raWUgPVxuICAgICAgcmVzdWx0Lm9rICYmIHJlc3VsdC50b2tlbiA/IHNlc3Npb25Db29raWUocmVzdWx0LnRva2VuLCBnYXRlLnNlc3Npb25UdGxTZWNvbmRzKSA6IHVuZGVmaW5lZDtcbiAgICBzZW5kSnNvbihcbiAgICAgIHJlcyxcbiAgICAgIDIwMCxcbiAgICAgIHsgb2s6IHJlc3VsdC5vaywgLi4uKHJlc3VsdC5yZXRyeUFmdGVyID8geyByZXRyeUFmdGVyOiByZXN1bHQucmV0cnlBZnRlciB9IDoge30pIH0sXG4gICAgICBjb29raWUsXG4gICAgKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG5cbiAgY29uc3QgbG9nb3V0SGFuZGxlciA9ICgocmVxLCByZXMpID0+IHtcbiAgICBpZiAoIWlzVHVubmVsSG9zdChyZXEsIHB1YmxpY0RvbWFpbikpIHtcbiAgICAgIHNlbmRKc29uKHJlcywgNDA0LCB7IGVycm9yOiBcIm5vdCBmb3VuZFwiIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzZW5kSnNvbihyZXMsIDIwMCwgeyBvazogdHJ1ZSB9LCBMT0dPVVRfU0VUX0NPT0tJRSk7XG4gIH0pIGFzIFJlcXVlc3RIYW5kbGVyO1xuXG4gIGFkZFJvdXRlKFwiZ2V0XCIsIGAke0FVVEhfUFJFRklYfS9zdGF0dXNgLCBzdGF0dXNIYW5kbGVyKTtcbiAgYWRkUm91dGUoXCJwb3N0XCIsIGAke0FVVEhfUFJFRklYfS9yZXF1ZXN0YCwgcmVxdWVzdEhhbmRsZXIpO1xuICBhZGRSb3V0ZShcInBvc3RcIiwgYCR7QVVUSF9QUkVGSVh9L3ZlcmlmeWAsIHZlcmlmeUhhbmRsZXIpO1xuICBhZGRSb3V0ZShcInBvc3RcIiwgYCR7QVVUSF9QUkVGSVh9L2xvZ291dGAsIGxvZ291dEhhbmRsZXIpO1xuXG4gIC8vIC0tLSBUaGUgZ2F0ZSBtaWRkbGV3YXJlIChydW5zIGJlZm9yZSBzdGF0aWMgKyB0aGUgYXBwJ3MgL2FwaSBoYW5kbGVycykgLS0tXG5cbiAgY29uc3QgZ2F0ZU1pZGRsZXdhcmUgPSAoYXN5bmMgKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgY29uc3QgYWN0aW9uID0gYXdhaXQgZ2F0ZVJlcXVlc3QocmVxLCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgaGVhZGVyUG9saWN5IH0pO1xuICAgIGlmIChhY3Rpb24gPT09IFwiZGVueVwiKSBzZW5kSnNvbihyZXMsIDQwMSwgVU5BVVRIT1JJWkVEX0JPRFkpO1xuICAgIGVsc2UgbmV4dCgpO1xuICB9KSBhcyBSZXF1ZXN0SGFuZGxlcjtcblxuICBhZGRNaWRkbGV3YXJlKFwiL1wiLCBnYXRlTWlkZGxld2FyZSk7XG59XG4iXX0=
|
|
224
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsY0FBYyxFQUFxQixNQUFNLGNBQWMsQ0FBQztBQUdqRSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBT3pDLE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxpQkFBaUIsQ0FBQztBQW9CN0M7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQUMsR0FBb0IsRUFBRSxZQUFnQztJQUNqRixJQUFJLENBQUMsWUFBWTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ2hDLE1BQU0sSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLE9BQU8sSUFBSSxLQUFLLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxHQUFvQjtJQUMzQyxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDakQsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUMv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TUFBTSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLENBQUMsQ0FBbUIsQ0FBQztJQUNyQixhQUFhLENBQUMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBRXhDLDZFQUE2RTtJQUU3RSxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFO1FBQy9DLE1BQU0sTUFBTSxHQUFHLE1BQU0sV0FBVyxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUM1RSxJQUFJLE1BQU0sS0FBSyxNQUFNO1lBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQzs7WUFDMUQsSUFBSSxFQUFFLENBQUM7SUFDZCxDQUFDLENBQW1CLENBQUM7SUFFckIsYUFBYSxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgdHVubmVsJ3MgaW4tYXBwIEFVVEggR0FURSAtIEV4cHJlc3MgbWlkZGxld2FyZSArIGxvZ2luIHJvdXRlcyB0aGVcbiAqIHtAbGluayBBdXRoR2F0ZVBsdWdpbn0gcmVnaXN0ZXJzIG9uIHRoZSBhcHAncyBPV04gc2VydmVyIHZpYSBgdGhpcy5jb250ZXh0YC5cbiAqXG4gKiBUaGUgZ2F0ZSBpcyBNSURETEVXQVJFLCBub3QgYSByZXZlcnNlIHByb3h5IC0gdGhlIGFwcCBpcyB0aGUgcHJvY2Vzcywgc28gdGhlcmUgaXNcbiAqIG5vdGhpbmcgdG8gZm9yd2FyZCB0by4gSXQgZWl0aGVyIHNob3J0LWNpcmN1aXRzICg0MDEsIG9yIGFuc3dlcnMgdGhlIG9wZW4gbG9naW5cbiAqIHJvdXRlcykgb3IgY2FsbHMgYG5leHQoKWAgdG8gbGV0IHRoZSBhcHAncyByZWFsIGhhbmRsZXJzIHJ1bi4gSXQgaXMgdGhlXG4gKiBcInN0YW5kcyBpbiBmb3IgQXBwS2l0IGF1dGhcIiBwYXRoOlxuICogYSBwb3J0ciBjYWxsZXIgYXV0aGVudGljYXRlcyB3aXRoIEJldHRlciBBdXRoIE9UUCBvciBhIHBhc3NrZXksIGFuZCBvblxuICogc3VjY2VzcyB0aGUgZ2F0ZSBpbmplY3RzIHRoZSBpZGVudGl0eSBoZWFkZXJzIEFwcEtpdCByZWFkcy5cbiAqXG4gKiBXSElDSCBUUkFGRklDIElTIEdBVEVEIC0gdGhlIGBIb3N0YCBoZWFkZXIsIG5vdCB0aGUgc29ja2V0LiBwb3J0cidzIGNsaWVudFxuICogZm9yd2FyZHMgd2l0aCBHbydzIGBodHRwdXRpbC5OZXdTaW5nbGVIb3N0UmV2ZXJzZVByb3h5YCBhbmQgYSBgRGlyZWN0b3JgIHRoYXRcbiAqIFBSRVNFUlZFUyB0aGUgb3JpZ2luYWwgYEhvc3RgLCBzbyB0dW5uZWwgcmVxdWVzdHMgYXJyaXZlIHdpdGhcbiAqIGBIb3N0OiA8c3ViZG9tYWluPi48c2VydmVyPmAgKHRoZSBwdWJsaWMgZG9tYWluKS4gQSBsb2NhbCBwcm9jZXNzIGhpdHRpbmcgdGhlXG4gKiBhcHAgZGlyZWN0bHkgc2VuZHMgYEhvc3Q6IDEyNy4wLjAuMTo8cG9ydD5gIC8gYGxvY2FsaG9zdGAuIFNvIE9OTFkgcmVxdWVzdHMgd2hvc2VcbiAqIGBIb3N0YCBtYXRjaGVzIHRoZSBjb25maWd1cmVkIHB1YmxpYyBkb21haW4gYXJlIGdhdGVkOyB0aGUgcGxhdGZvcm0gZnJvbnQgZG9vclxuICogYW5kIGFueSBvdGhlciBsb2NhbCBjbGllbnQgcGFzcyB0aHJvdWdoIHVudG91Y2hlZC4gVGhlcmUgaXMgbm8gcG9ydHItaW5qZWN0ZWRcbiAqIGlkZW50aWZ5aW5nIGhlYWRlciBhbmQgbm8gVENQL3NvdXJjZS1JUCBzaWduYWwgdG8gdXNlIGluc3RlYWQgKHRoZSBjbGllbnQgZGlhbHNcbiAqIHRoZSB0YXJnZXQgb3ZlciBwbGFpbiBsb29wYmFjaykuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB0eXBlIHsgSW5jb21pbmdNZXNzYWdlIH0gZnJvbSBcIm5vZGU6aHR0cFwiO1xuaW1wb3J0IHsgbG9nLCB0b2tlbiB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RIYW5kbGVyLCBSZXNwb25zZSB9IGZyb20gXCJleHByZXNzXCI7XG5pbXBvcnQgeyB0b0hlYWRlclBvbGljeSwgdHlwZSBIZWFkZXJQb2xpY3kgfSBmcm9tIFwiLi9oZWFkZXJzLnRzXCI7XG5pbXBvcnQgdHlwZSB7IEF1dGhHYXRlQXBpIH0gZnJvbSBcIi4vcGx1Z2luLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJ0dW5uZWw6Z2F0ZVwiKTtcblxudHlwZSBXZWJSZXF1ZXN0SW5wdXQgPSBJbmNvbWluZ01lc3NhZ2UgJiB7XG4gIGJvZHk/OiB1bmtub3duO1xuICBvcmlnaW5hbFVybD86IHN0cmluZztcbn07XG5cbmV4cG9ydCBjb25zdCBBVVRIX1BSRUZJWCA9IFwiL2FwaS9lbWFpbC9hdXRoXCI7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgbW91bnRHYXRlfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2F0ZU9wdGlvbnMge1xuICAvKiogVGhlIGluLXByb2Nlc3MgZ2F0ZSBBUEkgKHNlc3Npb24vcmVxdWVzdC92ZXJpZnkvc3RhdHVzKS4gKi9cbiAgZ2F0ZTogQXV0aEdhdGVBcGk7XG4gIC8qKlxuICAgKiBUaGUgcHVibGljIGA8c3ViZG9tYWluPi48c2VydmVyPmAgdGhhdCBpZGVudGlmaWVzIHBvcnRyIHRyYWZmaWMgYnkgYEhvc3RgLlxuICAgKiBXaGVuIGFic2VudCwgbm8gcmVxdWVzdCBpcyBldmVyIGNsYXNzaWZpZWQgYXMgdHVubmVsIHRyYWZmaWMgYW5kIHRoZSBnYXRlIGlzXG4gICAqIGluZXJ0IChldmVyeXRoaW5nIHBhc3NlcyB0aHJvdWdoKSAtIGEgdHVubmVsIHdpdGggbm8gcHVibGljIGRvbWFpbiBnYXRlc1xuICAgKiBub3RoaW5nLlxuICAgKi9cbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICAvKipcbiAgICogRXh0cmEgYHgtYCByZXF1ZXN0IGhlYWRlcnMgdHVubmVsIHRyYWZmaWMgbWF5IGZvcndhcmQgKHVuaW9uZWQgd2l0aCB0aGVcbiAgICogYnVpbHQtaW4gYWxsb3ctbGlzdCkuIEV2ZXJ5IG90aGVyIGB4LWAgaGVhZGVyIGlzIHN0cmlwcGVkIGZyb20gdHVubmVsIHRyYWZmaWMuXG4gICAqL1xuICBmb3J3YXJkSGVhZGVycz86IHJlYWRvbmx5IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFRydWUgd2hlbiB0aGUgcmVxdWVzdCdzIGBIb3N0YCBpcyB0aGUgdHVubmVsJ3MgcHVibGljIGRvbWFpbiAtIGkuZS4gaXQgY2FtZSBpblxuICogb3ZlciBwb3J0ci4gQ2FzZS1pbnNlbnNpdGl2ZTsgdGhlIG9wdGlvbmFsIGA6cG9ydGAgaXMgaWdub3JlZC4gV2hlbiBubyBwdWJsaWNcbiAqIGRvbWFpbiBpcyBjb25maWd1cmVkLCBub3RoaW5nIGlzIHR1bm5lbCB0cmFmZmljLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNUdW5uZWxIb3N0KHJlcTogSW5jb21pbmdNZXNzYWdlLCBwdWJsaWNEb21haW46IHN0cmluZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICBpZiAoIXB1YmxpY0RvbWFpbikgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBob3N0ID0gKHJlcS5oZWFkZXJzLmhvc3QgPz8gXCJcIikudG9Mb3dlckNhc2UoKS5zcGxpdChcIjpcIilbMF07XG4gIHJldHVybiBob3N0ID09PSBwdWJsaWNEb21haW4udG9Mb3dlckNhc2UoKS5zcGxpdChcIjpcIilbMF07XG59XG5cbi8qKlxuICogQ2xpZW50IElQIGZvciByYXRlLWxpbWl0aW5nOiB0aGUgUklHSFRNT1NUIGB4LWZvcndhcmRlZC1mb3JgIGVudHJ5ICh0aGUgdmFsdWVcbiAqIHRoZSBuZWFyZXN0IHRydXN0ZWQgaG9wIC0gcG9ydHIgLSB3cm90ZSksIGVsc2UgdGhlIHNvY2tldCBhZGRyZXNzLiBSZWFkaW5nIHRoZVxuICogcmlnaHRtb3N0LCBub3QgdGhlIGxlZnRtb3N0LCBzdG9wcyBhIGNhbGxlciBtaW50aW5nIGEgZnJlc2ggcmF0ZS1saW1pdCBidWNrZXQgYnlcbiAqIHZhcnlpbmcgdGhlIGhlYWRlci4gQ2FsbGVkIGJlZm9yZSB7QGxpbmsgc3RyaXBIZWFkZXJzfS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsaWVudElwKHJlcTogSW5jb21pbmdNZXNzYWdlKTogc3RyaW5nIHtcbiAgY29uc3QgZm9yd2FyZGVkID0gcmVxLmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1mb3JcIl07XG4gIGNvbnN0IGNoYWluID0gKEFycmF5LmlzQXJyYXkoZm9yd2FyZGVkKSA/IGZvcndhcmRlZC5qb2luKFwiLFwiKSA6IChmb3J3YXJkZWQgPz8gXCJcIikpXG4gICAgLnNwbGl0KFwiLFwiKVxuICAgIC5tYXAoKGVudHJ5KSA9PiBlbnRyeS50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbiAgcmV0dXJuIGNoYWluLmF0KC0xKSA/PyByZXEuc29ja2V0LnJlbW90ZUFkZHJlc3MgPz8gXCJ1bmtub3duXCI7XG59XG5cbi8qKlxuICogUmVtb3ZlIHRoZSBnYXRlJ3Mgc2Vzc2lvbiBjb29raWUgZnJvbSB0aGUgYENvb2tpZWAgaGVhZGVyIGJlZm9yZSB0aGUgYXBwJ3NcbiAqIGhhbmRsZXJzIHJ1biwgc28gdGhlIGFwcCBuZXZlciBzZWVzIGBkYnhfYXV0aGAgKGl0IGlzIHRoZSBnYXRlJ3MgY29uY2VybikuXG4gKiBQcmVzZXJ2ZXMgb3RoZXIgY29va2llczsgZGVsZXRlcyB0aGUgaGVhZGVyIHdoZW4gaXQgYmVjb21lcyBlbXB0eS5cbiAqL1xuZnVuY3Rpb24gc3RyaXBTZXNzaW9uQ29va2llKHJlcTogSW5jb21pbmdNZXNzYWdlKTogdm9pZCB7XG4gIGNvbnN0IHJhdyA9IHJlcS5oZWFkZXJzLmNvb2tpZTtcbiAgaWYgKCFyYXcpIHJldHVybjtcbiAgY29uc3Qga2VwdCA9IHJhd1xuICAgIC5zcGxpdChcIjtcIilcbiAgICAubWFwKChjKSA9PiBjLnRyaW0oKSlcbiAgICAuZmlsdGVyKChjKSA9PiBjICYmICFjLnN0YXJ0c1dpdGgoXCJkYngtdG9vbHMtYXV0aD1cIikgJiYgIWMuc3RhcnRzV2l0aChcImRieC10b29scy1wYXNza2V5PVwiKSk7XG4gIGlmIChrZXB0Lmxlbmd0aCkgcmVxLmhlYWRlcnMuY29va2llID0ga2VwdC5qb2luKFwiOyBcIik7XG4gIGVsc2UgZGVsZXRlIHJlcS5oZWFkZXJzLmNvb2tpZTtcbn1cblxuLyoqXG4gKiBQcmVzZW50IGEgcGFzc3dvcmRsZXNzLWF1dGhlbnRpY2F0ZWQgY2FsbGVyIHRvIHRoZSBhcHAgdGhlIFNBTUUgd2F5IGEgcGxhdGZvcm0gZnJvbnRcbiAqIGRvb3IgZG9lczogc2V0IHRoZSBmcm9udC1kb29yIGlkZW50aXR5IGhlYWRlcnMgdG8gdGhlIHZlcmlmaWVkIGFkZHJlc3MgKEFwcEtpdFxuICogcmVhZHMge0BsaW5rIHRva2VuLlVTRVJfSURfSEVBREVSfSBmb3IgdGhlIE9CTyB1c2VyIGlkKSwgc28gdGhlIGFwcCBuZWVkcyBub1xuICogZ2F0ZS1zcGVjaWZpYyBjb2RlIHBhdGguXG4gKlxuICogV2hhdCB0aGUgZ2F0ZSBDQU5OT1Qgc2V0IGlzIHtAbGluayB0b2tlbi5BQ0NFU1NfVE9LRU5fSEVBREVSfTogYW4gYXV0aCBzZXNzaW9uXG4gKiBwcm92ZXMgYW4gZW1haWwsIG5vdCBwb3NzZXNzaW9uIG9mIGEgRGF0YWJyaWNrcyBjcmVkZW50aWFsLiBJdHMgYWJzZW5jZSBpcyB3aGF0XG4gKiBgQGRieC10b29scy9hcHBraXRgJ3MgYGlkZW50aXR5OiBcImF1dG9cImAgZGV0ZWN0cywgc28gYSBnYXRlZCByZXF1ZXN0IHJ1bnMgYXMgdGhlXG4gKiBhcHAgc2VydmljZSBwcmluY2lwYWwgaW5zdGVhZCBvZiB0aHJvd2luZy5cbiAqL1xuZnVuY3Rpb24gaW5qZWN0SWRlbnRpdHkocmVxOiBJbmNvbWluZ01lc3NhZ2UsIGVtYWlsOiBzdHJpbmcpOiB2b2lkIHtcbiAgcmVxLmhlYWRlcnNbdG9rZW4uVVNFUl9JRF9IRUFERVJdID0gZW1haWw7XG4gIHJlcS5oZWFkZXJzW3Rva2VuLlVTRVJfRU1BSUxfSEVBREVSXSA9IGVtYWlsO1xufVxuXG4vKiogUmVhZCB0aGUgcmF3IHJlcXVlc3QgYm9keSBhcyB0ZXh0IChBcHBLaXQgcGFyc2VzIEpTT04sIGJ1dCB0aGUgZ2F0ZSByb3V0ZXNcbiAqIGFyZSBtb3VudGVkIGJlZm9yZSB0aGF0IHJ1bnMgZm9yIHR1bm5lbCB0cmFmZmljLCBzbyByZWFkIGRlZmVuc2l2ZWx5KS4gKi9cbmZ1bmN0aW9uIHJlYWRCb2R5KHJlcTogV2ViUmVxdWVzdElucHV0KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgLy8gQXBwS2l0J3MganNvbiBib2R5LXBhcnNlciBtYXkgaGF2ZSBhbHJlYWR5IHBvcHVsYXRlZCByZXEuYm9keTsgcHJlZmVyIGl0LlxuICBpZiAocmVxLmJvZHkgIT09IHVuZGVmaW5lZCAmJiByZXEuYm9keSAhPT0gbnVsbCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHlwZW9mIHJlcS5ib2R5ID09PSBcInN0cmluZ1wiID8gcmVxLmJvZHkgOiBKU09OLnN0cmluZ2lmeShyZXEuYm9keSkpO1xuICB9XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGxldCBkYXRhID0gXCJcIjtcbiAgICByZXEub24oXCJkYXRhXCIsIChjaHVuaykgPT4gKGRhdGEgKz0gY2h1bmspKTtcbiAgICByZXEub24oXCJlbmRcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gICAgcmVxLm9uKFwiZXJyb3JcIiwgKCkgPT4gcmVzb2x2ZShkYXRhKSk7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2ViSGVhZGVycyhyZXE6IEluY29taW5nTWVzc2FnZSk6IEhlYWRlcnMge1xuICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHJlcS5oZWFkZXJzKSkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbHVlKSBoZWFkZXJzLmFwcGVuZChuYW1lLCBpdGVtKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGhlYWRlcnMuc2V0KG5hbWUsIHZhbHVlKTtcbiAgICB9XG4gIH1cbiAgaGVhZGVycy5zZXQoXCJ4LXJlYWwtaXBcIiwgY2xpZW50SXAocmVxKSk7XG4gIHJldHVybiBoZWFkZXJzO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2ViUmVxdWVzdChyZXE6IFdlYlJlcXVlc3RJbnB1dCk6IFByb21pc2U8Z2xvYmFsVGhpcy5SZXF1ZXN0PiB7XG4gIGNvbnN0IGhvc3QgPSByZXEuaGVhZGVycy5ob3N0ID8/IFwibG9jYWxob3N0XCI7XG4gIGNvbnN0IGhvc3RuYW1lID0gaG9zdC5zcGxpdChcIjpcIilbMF0/LnRvTG93ZXJDYXNlKCk7XG4gIGNvbnN0IHByb3RvY29sID0gaG9zdG5hbWUgPT09IFwibG9jYWxob3N0XCIgfHwgaG9zdG5hbWUgPT09IFwiMTI3LjAuMC4xXCIgPyBcImh0dHBcIiA6IFwiaHR0cHNcIjtcbiAgY29uc3QgbWV0aG9kID0gKHJlcS5tZXRob2QgPz8gXCJHRVRcIikudG9VcHBlckNhc2UoKTtcbiAgY29uc3QgYm9keSA9IG1ldGhvZCA9PT0gXCJHRVRcIiB8fCBtZXRob2QgPT09IFwiSEVBRFwiID8gdW5kZWZpbmVkIDogYXdhaXQgcmVhZEJvZHkocmVxKTtcbiAgcmV0dXJuIG5ldyBnbG9iYWxUaGlzLlJlcXVlc3QoYCR7cHJvdG9jb2x9Oi8vJHtob3N0fSR7cmVxLm9yaWdpbmFsVXJsIHx8IHJlcS51cmx9YCwge1xuICAgIG1ldGhvZCxcbiAgICBoZWFkZXJzOiB3ZWJIZWFkZXJzKHJlcSksXG4gICAgLi4uKGJvZHkgPyB7IGJvZHkgfSA6IHt9KSxcbiAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kV2ViUmVzcG9uc2UocmVzOiBSZXNwb25zZSwgcmVzcG9uc2U6IGdsb2JhbFRoaXMuUmVzcG9uc2UpOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIHJlc3BvbnNlLmhlYWRlcnMuZW50cmllcygpKSB7XG4gICAgaWYgKG5hbWUudG9Mb3dlckNhc2UoKSAhPT0gXCJzZXQtY29va2llXCIpIHJlcy5zZXRIZWFkZXIobmFtZSwgdmFsdWUpO1xuICB9XG4gIGNvbnN0IGNvb2tpZXMgPSByZXNwb25zZS5oZWFkZXJzLmdldFNldENvb2tpZSgpO1xuICBpZiAoY29va2llcy5sZW5ndGgpIHJlcy5zZXRIZWFkZXIoXCJzZXQtY29va2llXCIsIGNvb2tpZXMpO1xuICBjb25zdCBib2R5ID0gQnVmZmVyLmZyb20oYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKSk7XG4gIHJlcy5zdGF0dXMocmVzcG9uc2Uuc3RhdHVzKS5zZW5kKGJvZHkpO1xufVxuXG4vKipcbiAqIFdoYXQgdGhlIGNhbGxlciBzaG91bGQgZG8gd2l0aCBhIHJlcXVlc3QsIGZyb20ge0BsaW5rIGdhdGVSZXF1ZXN0fS5cbiAqXG4gKiAgIC0gYHBhc3NgIC0gbm90IHR1bm5lbCB0cmFmZmljLCBvciBhbiBvcGVuIGxvZ2luIHJvdXRlLiBGb3J3YXJkIHVudG91Y2hlZC5cbiAqICAgLSBgYWxsb3dgIC0gdHVubmVsIHRyYWZmaWMgdGhhdCBpcyBhdXRob3JpemVkLiBUaGUgcmVxdWVzdCdzIGhlYWRlcnMgaGF2ZVxuICogICAgIEFMUkVBRFkgYmVlbiByZXdyaXR0ZW4gKHBvbGljeSBhcHBsaWVkLCBpZGVudGl0eSBpbmplY3RlZCwgc2Vzc2lvbiBjb29raWVcbiAqICAgICBzdHJpcHBlZCksIHNvIGZvcndhcmQgaXQgYXMgaXQgbm93IHN0YW5kcy5cbiAqICAgLSBgZGVueWAgLSB0dW5uZWwgdHJhZmZpYyB3aXRoIG5vIHZhbGlkIHNlc3Npb24uIEFuc3dlciBgNDAxYCB3aXRoXG4gKiAgICAge0BsaW5rIEFVVEhfUFJFRklYfSBhcyB0aGUgbG9naW4gcGF0aC5cbiAqL1xuZXhwb3J0IHR5cGUgR2F0ZUFjdGlvbiA9IFwicGFzc1wiIHwgXCJhbGxvd1wiIHwgXCJkZW55XCI7XG5cbi8qKlxuICogVEhFIGdhdGluZyBkZWNpc2lvbiwgZm9yIG9uZSByZXF1ZXN0LCBpbmRlcGVuZGVudCBvZiBob3cgaXQgd2lsbCBiZSBhbnN3ZXJlZC5cbiAqXG4gKiBCb3RoIHBhdGhzIGNhbGwgdGhpczogdGhlIEV4cHJlc3MgbWlkZGxld2FyZSBiZWxvdyAod2hlcmUgdGhlIGFwcCBpcyB0aGVcbiAqIHByb2Nlc3MpIGFuZCBgQGRieC10b29scy9jbGktdHVubmVsYCdzIHJldmVyc2UgcHJveHkgKHdoZXJlIHRoZSBhcHAgaXMgYSBjaGlsZFxuICogcHJvY2VzcyBvbiBhIHByaXZhdGUgcG9ydCkuIEEgZGl2ZXJnZW5jZSBiZXR3ZWVuIHRoZW0gd291bGQgYmUgYSBzZWN1cml0eSBidWdcbiAqIHRoZSBzZWNvbmQgcGF0aCBjb3VsZCBub3QgYmUgdGVzdGVkIGludG8gYWdyZWVtZW50IC0gb25lIHBhdGggZm9yZ2V0dGluZyB0b1xuICogc3RyaXAgYHgtZm9yd2FyZGVkLWFjY2Vzcy10b2tlbmAgaXMgZW5vdWdoIC0gc28gdGhlIGRlY2lzaW9uLCB0aGUgaGVhZGVyXG4gKiByZXdyaXRpbmcsIGFuZCB0aGUgaWRlbnRpdHkgaW5qZWN0aW9uIGxpdmUgaGVyZSBvbmNlIGFuZCB0aGUgdHJhbnNwb3J0cyBvbmx5XG4gKiBkaWZmZXIgaW4gaG93IHRoZXkgV1JJVEUgdGhlIG91dGNvbWUuXG4gKlxuICogTXV0YXRlcyBgcmVxLmhlYWRlcnNgIG9uIHRoZSBgYWxsb3dgL2BwYXNzYC13aXRoLWNvb2tpZSBwYXRocywgd2hpY2ggaXMgZXhhY3RseVxuICogd2hhdCBib3RoIGNhbGxlcnMgd2FudDogRXhwcmVzcyBoYW5kcyB0aGUgc2FtZSBvYmplY3QgdG8gdGhlIGFwcCdzIGhhbmRsZXJzLCBhbmRcbiAqIHRoZSBwcm94eSBmb3J3YXJkcyBpdCB1cHN0cmVhbS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdhdGVSZXF1ZXN0KFxuICByZXE6IEluY29taW5nTWVzc2FnZSxcbiAgb3B0aW9uczogR2F0ZU9wdGlvbnMgJiB7IGhlYWRlclBvbGljeT86IEhlYWRlclBvbGljeSB9LFxuKTogUHJvbWlzZTxHYXRlQWN0aW9uPiB7XG4gIGNvbnN0IHsgZ2F0ZSwgcHVibGljRG9tYWluIH0gPSBvcHRpb25zO1xuICAvLyBOb3QgdHVubmVsIHRyYWZmaWMgKHBsYXRmb3JtIGZyb250IGRvb3IsIG9yIGFueSBvdGhlciBsb2NhbCBjYWxsZXIpOiB0aGVcbiAgLy8gcmVxdWVzdCBpcyBhbHJlYWR5IGF1dGhlbnRpY2F0ZWQsIG9yIGlzIG5vdCBvdXJzIHRvIGdhdGUuXG4gIGlmICghaXNUdW5uZWxIb3N0KHJlcSwgcHVibGljRG9tYWluKSkgcmV0dXJuIFwicGFzc1wiO1xuXG4gIGNvbnN0IHBhdGggPSAocmVxLnVybCA/PyBcIi9cIikuc3BsaXQoXCI/XCIpWzBdID8/IFwiL1wiO1xuICAvLyBUaGUgbG9naW4gZmxvdyBpcyBvcGVuIHNvIHRoZSBicm93c2VyIGNhbiByZW5kZXIgPEF1dGhHYXRlPiBhbmQgc2lnbiBpbi5cbiAgaWYgKHBhdGguc3RhcnRzV2l0aChBVVRIX1BSRUZJWCkpIHJldHVybiBcInBhc3NcIjtcblxuICAvLyBBbnRpLXNwb29mOiBvbmx5IHRoZSBnYXRlIG1heSBhc3NlcnQgaWRlbnRpdHkgb24gdHVubmVsIHRyYWZmaWMuXG4gIGNvbnN0IHBvbGljeSA9IG9wdGlvbnMuaGVhZGVyUG9saWN5ID8/IHRvSGVhZGVyUG9saWN5KG9wdGlvbnMuZm9yd2FyZEhlYWRlcnMpO1xuICBjb25zdCByZW1vdmVkID0gcG9saWN5LmFwcGx5KHJlcS5oZWFkZXJzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgaWYgKHJlbW92ZWQubGVuZ3RoKSBsb2dnZXIuZGVidWcoXCJzdHJpcHBlZCBpbmJvdW5kIGhlYWRlcnNcIiwgeyByZW1vdmVkIH0pO1xuXG4gIC8vIFN0YXRpYyAobm9uLUFQSSkgbG9hZHMgZnJlZWx5IHNvIHRoZSBTUEEgY2FuIHJlbmRlcjsgZHJvcCB0aGUgZ2F0ZSBjb29raWUuXG4gIGlmICghcGF0aC5zdGFydHNXaXRoKFwiL2FwaS9cIikpIHtcbiAgICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgICByZXR1cm4gXCJwYXNzXCI7XG4gIH1cblxuICAvLyBFdmVyeSBvdGhlciAvYXBpLyogbmVlZHMgYSB2YWxpZCBCZXR0ZXIgQXV0aCBzZXNzaW9uLlxuICBjb25zdCBlbWFpbCA9IGF3YWl0IGdhdGUuc2Vzc2lvbih3ZWJIZWFkZXJzKHJlcSkpO1xuICBpZiAoIWVtYWlsKSByZXR1cm4gXCJkZW55XCI7XG4gIGluamVjdElkZW50aXR5KHJlcSwgZW1haWwpO1xuICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgcmV0dXJuIFwiYWxsb3dcIjtcbn1cblxuLyoqIFRoZSBib2R5IG9mIGEgYGRlbnlgLCBzaGFyZWQgc28gYm90aCBwYXRocyBhbnN3ZXIgYSA0MDEgaWRlbnRpY2FsbHkuICovXG5leHBvcnQgY29uc3QgVU5BVVRIT1JJWkVEX0JPRFkgPSB7XG4gIGVycm9yOiBcImF1dGhlbnRpY2F0aW9uIHJlcXVpcmVkXCIsXG4gIGxvZ2luUGF0aDogQVVUSF9QUkVGSVgsXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIFJlZ2lzdGVyIHRoZSBsb2dpbiByb3V0ZXMgYW5kIHRoZSBnYXRpbmcgbWlkZGxld2FyZSBvbiB0aGUgYXBwJ3MgRXhwcmVzc1xuICogaW5zdGFuY2UuIENhbGxlZCBmcm9tIHtAbGluayBBdXRoR2F0ZVBsdWdpbn0gd2l0aCB0aGUgcm91dGVyIEFwcEtpdCBoYW5kc1xuICogYGluamVjdFJvdXRlc2AsIHBsdXMgYHRoaXMuY29udGV4dC5hZGRNaWRkbGV3YXJlYCBmb3IgdGhlIGdsb2JhbCBnYXRlLlxuICpcbiAqIGBhZGRSb3V0ZWAvYGFkZE1pZGRsZXdhcmVgIGFyZSB1c2VkICh2aWEgdGhlIHBhc3NlZCBjYWxsYmFja3MpIGJlY2F1c2UgdGhlIGxvZ2luXG4gKiByb3V0ZXMgbGl2ZSBhdCBhbiBBQlNPTFVURSBwYXRoIChgL2FwaS9lbWFpbC9hdXRoLypgLCB0aGUgY2xpZW50J3MgY29udHJhY3QpLFxuICogbm90IHVuZGVyIHRoZSBwbHVnaW4ncyBgL2FwaS9hdXRoR2F0ZWAgYmFzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vdW50R2F0ZShcbiAgb3B0czogR2F0ZU9wdGlvbnMsXG4gIF9hZGRSb3V0ZTogKG1ldGhvZDogXCJnZXRcIiB8IFwicG9zdFwiLCBwYXRoOiBzdHJpbmcsIGhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSA9PiB2b2lkLFxuICBhZGRNaWRkbGV3YXJlOiAocGF0aDogc3RyaW5nLCBoYW5kbGVyOiBSZXF1ZXN0SGFuZGxlcikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBjb25zdCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgZm9yd2FyZEhlYWRlcnMgfSA9IG9wdHM7XG4gIGNvbnN0IGhlYWRlclBvbGljeSA9IHRvSGVhZGVyUG9saWN5KGZvcndhcmRIZWFkZXJzKTtcbiAgbG9nZ2VyLmRlYnVnKFwiZ2F0ZSBtb3VudGVkXCIsIHsgcHVibGljRG9tYWluLCBmb3J3YXJkOiBoZWFkZXJQb2xpY3kucGF0dGVybnMgfSk7XG5cbiAgLy8gQmV0dGVyIEF1dGggYW5kIHRoZSBjb21wYXRpYmlsaXR5IHJvdXRlcyBzaGFyZSBvbmUgZmV0Y2gtY29tcGF0aWJsZVxuICAvLyBoYW5kbGVyIGluIGJvdGggaG9zdGluZyBtb2Rlcy5cbiAgY29uc3QgYXV0aEhhbmRsZXIgPSAoYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgaWYgKCFpc1R1bm5lbEhvc3QocmVxLCBwdWJsaWNEb21haW4pKSB7XG4gICAgICBjb25zdCBwYXRoID0gKHJlcS51cmwgPz8gXCIvXCIpLnNwbGl0KFwiP1wiKVswXSA/PyBcIi9cIjtcbiAgICAgIGlmIChwYXRoLmVuZHNXaXRoKFwiL3N0YXR1c1wiKSkge1xuICAgICAgICByZXMuc3RhdHVzKDIwMCkuanNvbih7IGF1dGhlbnRpY2F0ZWQ6IGZhbHNlLCBlbmFibGVkOiBmYWxzZSwgcGFzc2tleXNFbmFibGVkOiBmYWxzZSB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcy5zdGF0dXMoNDA0KS5qc29uKHsgZXJyb3I6IFwibm90IGZvdW5kXCIgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGF3YWl0IHNlbmRXZWJSZXNwb25zZShyZXMsIGF3YWl0IGdhdGUuaGFuZGxlcihhd2FpdCB3ZWJSZXF1ZXN0KHJlcSkpKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG4gIGFkZE1pZGRsZXdhcmUoQVVUSF9QUkVGSVgsIGF1dGhIYW5kbGVyKTtcblxuICAvLyAtLS0gVGhlIGdhdGUgbWlkZGxld2FyZSAocnVucyBiZWZvcmUgc3RhdGljICsgdGhlIGFwcCdzIC9hcGkgaGFuZGxlcnMpIC0tLVxuXG4gIGNvbnN0IGdhdGVNaWRkbGV3YXJlID0gKGFzeW5jIChyZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgIGNvbnN0IGFjdGlvbiA9IGF3YWl0IGdhdGVSZXF1ZXN0KHJlcSwgeyBnYXRlLCBwdWJsaWNEb21haW4sIGhlYWRlclBvbGljeSB9KTtcbiAgICBpZiAoYWN0aW9uID09PSBcImRlbnlcIikgcmVzLnN0YXR1cyg0MDEpLmpzb24oVU5BVVRIT1JJWkVEX0JPRFkpO1xuICAgIGVsc2UgbmV4dCgpO1xuICB9KSBhcyBSZXF1ZXN0SGFuZGxlcjtcblxuICBhZGRNaWRkbGV3YXJlKFwiL1wiLCBnYXRlTWlkZGxld2FyZSk7XG59XG4iXX0=
|
package/lib/src/interceptor.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* app's public port, binds the child process to the app, and stops portr during an
|
|
10
10
|
* orderly AppKit shutdown.
|
|
11
11
|
*
|
|
12
|
-
* The
|
|
12
|
+
* The passwordless GATE is a separate concern: it is the `authGate` AppKit plugin,
|
|
13
13
|
* which registers the login routes + a gating middleware on the app's own server.
|
|
14
14
|
* Register it in the app's `plugins` for gated traffic. This interceptor is only
|
|
15
15
|
* the portr half - "update the host, bind portr" - the smallest useful unit.
|
package/lib/src/interceptor.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* app's public port, binds the child process to the app, and stops portr during an
|
|
10
10
|
* orderly AppKit shutdown.
|
|
11
11
|
*
|
|
12
|
-
* The
|
|
12
|
+
* The passwordless GATE is a separate concern: it is the `authGate` AppKit plugin,
|
|
13
13
|
* which registers the login routes + a gating middleware on the app's own server.
|
|
14
14
|
* Register it in the app's `plugins` for gated traffic. This interceptor is only
|
|
15
15
|
* the portr half - "update the host, bind portr" - the smallest useful unit.
|
|
@@ -65,4 +65,4 @@ export function tunnelInterceptor(options = {}) {
|
|
|
65
65
|
logger.info(`tunnel bound: portr -> :${port} (${portrConfig.subdomain}.${portrConfig.server})`);
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBaUJHO0FBR0gsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLGtCQUFrQixFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUU1RixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUM7QUFnQmhELHFGQUFxRjtBQUNyRixTQUFTLGlCQUFpQixDQUFDLElBQWE7SUFDdEMsT0FBTyxJQUFJLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLElBQUksSUFBSSxDQUFDO0FBQzFFLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQUMsVUFBb0MsRUFBRTtJQUN0RSxPQUFPLEtBQUssRUFBRSxHQUF1QixFQUFpQixFQUFFO1FBQ3RELElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUMzQixPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsS0FBSyxHQUFHLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQztRQUN6RCxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsaUJBQWlCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdDLE1BQU0sV0FBVyxHQUFHLGtCQUFrQixDQUFDO1lBQ3JDLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtZQUNsQyxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7WUFDNUIsSUFBSTtTQUNMLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNqQixNQUFNLENBQUMsSUFBSSxDQUFDLDRFQUE0RSxDQUFDLENBQUM7WUFDMUYsT0FBTztRQUNULENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLFlBQVksRUFBRSxDQUFDO1FBQ3RDLE1BQU0sZ0JBQWdCLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN0RCxHQUFHLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXZCLEdBQUcsQ0FBQyxXQUFXLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRTtZQUMvQixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU07Z0JBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMzQyxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLElBQUksS0FBSyxXQUFXLENBQUMsU0FBUyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2xHLENBQUMsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGB0dW5uZWxJbnRlcmNlcHRvcigpYCAtIHRoZSB7QGxpbmsgSW50ZXJjZXB0b3J9IHRoYXQgZnJvbnRzIGFuIGFwcCB3aXRoIGEgcHVibGljXG4gKiBwb3J0ciB0dW5uZWwsIGNvbnN1bWluZyB0aGUge0BsaW5rIEludGVyY2VwdG9yQ29udGV4dH0gYEBkYngtdG9vbHMvYXBwa2l0YCdzXG4gKiBgY3JlYXRlQXBwYCBoYW5kcyBpdC5cbiAqXG4gKiBUaGUgdHVubmVsIHJ1bnMgSU4tUFJPQ0VTUzogdGhlIEFQUCBpcyB0aGUgbWFpbiBwcm9jZXNzIGFuZCBoYW5kcyB0aGlzIGludGVyY2VwdG9yXG4gKiBpdHMgY29udGV4dCwgcmF0aGVyIHRoYW4gYSB3cmFwcGVyIHByb2Nlc3Mgc3Bhd25pbmcgdGhlIGFwcCBhcyBhIGNoaWxkLiBUaGVcbiAqIGludGVyY2VwdG9yIGFwcGxpZXMgdGhlIGNvbXB1dGVkIHdvcmtzcGFjZSBob3N0LCBpbnN0YWxscyBhbmQgbGF1bmNoZXMgcG9ydHIgb24gdGhlXG4gKiBhcHAncyBwdWJsaWMgcG9ydCwgYmluZHMgdGhlIGNoaWxkIHByb2Nlc3MgdG8gdGhlIGFwcCwgYW5kIHN0b3BzIHBvcnRyIGR1cmluZyBhblxuICogb3JkZXJseSBBcHBLaXQgc2h1dGRvd24uXG4gKlxuICogVGhlIHBhc3N3b3JkbGVzcyBHQVRFIGlzIGEgc2VwYXJhdGUgY29uY2VybjogaXQgaXMgdGhlIGBhdXRoR2F0ZWAgQXBwS2l0IHBsdWdpbixcbiAqIHdoaWNoIHJlZ2lzdGVycyB0aGUgbG9naW4gcm91dGVzICsgYSBnYXRpbmcgbWlkZGxld2FyZSBvbiB0aGUgYXBwJ3Mgb3duIHNlcnZlci5cbiAqIFJlZ2lzdGVyIGl0IGluIHRoZSBhcHAncyBgcGx1Z2luc2AgZm9yIGdhdGVkIHRyYWZmaWMuIFRoaXMgaW50ZXJjZXB0b3IgaXMgb25seVxuICogdGhlIHBvcnRyIGhhbGYgLSBcInVwZGF0ZSB0aGUgaG9zdCwgYmluZCBwb3J0clwiIC0gdGhlIHNtYWxsZXN0IHVzZWZ1bCB1bml0LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IEludGVyY2VwdG9yLCBJbnRlcmNlcHRvckNvbnRleHQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGxvZywgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGluc3RhbGxQb3J0ciwgcmVzb2x2ZVBvcnRyQ29uZmlnLCBzdGFydFBvcnRyLCB3cml0ZVBvcnRyQ29uZmlnIH0gZnJvbSBcIi4vcG9ydHIudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDppbnRlcmNlcHRvclwiKTtcblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayB0dW5uZWxJbnRlcmNlcHRvcn0gKGVhY2ggYWxzbyByZXNvbHZhYmxlIGZyb20gZW52KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHVubmVsSW50ZXJjZXB0b3JPcHRpb25zIHtcbiAgLyoqIHBvcnRyIGA8c3ViZG9tYWluPi48c2VydmVyPmAgdG8gc2VydmUgb24uIEVudiBgVFVOTkVMX1BVQkxJQ19ET01BSU5gLiAqL1xuICBwdWJsaWNEb21haW4/OiBzdHJpbmc7XG4gIC8qKiBwb3J0ciBzdWJkb21haW4gKGVsc2UgZGVyaXZlZCBmcm9tIHtAbGluayBwdWJsaWNEb21haW59KS4gKi9cbiAgc3ViZG9tYWluPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIFBVQkxJQyBwb3J0IHBvcnRyIGZvcndhcmRzIHRvIC0gdGhlIHBvcnQgdGhlIGFwcCBpdHNlbGYgbGlzdGVucyBvbi5cbiAgICogRGVmYXVsdHMgdG8gdGhlIERhdGFicmlja3MgQXBwcyBydW50aW1lIGNvbnRyYWN0IGBEQVRBQlJJQ0tTX0FQUF9QT1JUYFxuICAgKiAodGhlbiBgODAwMGApLCB3aGljaCBpcyB0aGUgcG9ydCB0aGUgcGxhdGZvcm0gcm91dGVzIHRvLlxuICAgKi9cbiAgcG9ydD86IG51bWJlcjtcbn1cblxuLyoqIFJlc29sdmUgdGhlIHB1YmxpYyBwb3J0IHBvcnRyIHNob3VsZCB0YXJnZXQ6IGV4cGxpY2l0LCBlbHNlIHRoZSBBcHBzIGNvbnRyYWN0LiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVB1YmxpY1BvcnQocG9ydD86IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBwb3J0ID8/IG9iamVjdC50b051bWJlcihwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0FQUF9QT1JUKSA/PyA4MDAwO1xufVxuXG4vKipcbiAqIEJ1aWxkIHRoZSB0dW5uZWwge0BsaW5rIEludGVyY2VwdG9yfS4gUGFzcyBpdCB0byBgY3JlYXRlQXBwKHsgaW50ZXJjZXB0b3IgfSlgLlxuICpcbiAqIEEgbm8tb3AgKGxvZ3MgYW5kIHJldHVybnMpIHdoZW4gbm8gcG9ydHIgdHVubmVsIGlzIGNvbmZpZ3VyZWQgLSBubyBgUE9SVFJfVE9LRU5gXG4gKiBvciBubyByZXNvbHZhYmxlIGA8c3ViZG9tYWluPi48c2VydmVyPmAgLSBzbyBhbiBhcHAgY2FuIHJlZ2lzdGVyIGl0XG4gKiB1bmNvbmRpdGlvbmFsbHkgYW5kIG9ubHkgYWN0dWFsbHkgdHVubmVscyB3aGVyZSB0aGUgZGVwbG95bWVudCB3aXJlZCBwb3J0ci5cbiAqXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHsgYXBwa2l0IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG4gKiBpbXBvcnQgeyB0dW5uZWxJbnRlcmNlcHRvciB9IGZyb20gXCJAZGJ4LXRvb2xzL3R1bm5lbFwiO1xuICpcbiAqIGF3YWl0IGFwcGtpdC5jcmVhdGVBcHAoe1xuICogICBwbHVnaW5zOiBbc2VydmVyKHsgaG9zdCwgc3RhdGljUGF0aCB9KV0sXG4gKiAgIGludGVyY2VwdG9yOiB0dW5uZWxJbnRlcmNlcHRvcigpLFxuICogfSk7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0dW5uZWxJbnRlcmNlcHRvcihvcHRpb25zOiBUdW5uZWxJbnRlcmNlcHRvck9wdGlvbnMgPSB7fSk6IEludGVyY2VwdG9yIHtcbiAgcmV0dXJuIGFzeW5jIChjdHg6IEludGVyY2VwdG9yQ29udGV4dCk6IFByb21pc2U8dm9pZD4gPT4ge1xuICAgIGlmIChjdHguZW52LmRhdGFicmlja3NIb3N0KSB7XG4gICAgICBwcm9jZXNzLmVudi5EQVRBQlJJQ0tTX0hPU1QgPz89IGN0eC5lbnYuZGF0YWJyaWNrc0hvc3Q7XG4gICAgfVxuXG4gICAgY29uc3QgcG9ydCA9IHJlc29sdmVQdWJsaWNQb3J0KG9wdGlvbnMucG9ydCk7XG4gICAgY29uc3QgcG9ydHJDb25maWcgPSByZXNvbHZlUG9ydHJDb25maWcoe1xuICAgICAgcHVibGljRG9tYWluOiBvcHRpb25zLnB1YmxpY0RvbWFpbixcbiAgICAgIHN1YmRvbWFpbjogb3B0aW9ucy5zdWJkb21haW4sXG4gICAgICBwb3J0LFxuICAgIH0pO1xuICAgIGlmICghcG9ydHJDb25maWcpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFwibm8gUE9SVFJfVE9LRU4vVFVOTkVMX1BVQkxJQ19ET01BSU4gLSB0aGUgYXBwIHJ1bnMgd2l0aG91dCBhIHB1YmxpYyB0dW5uZWxcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcG9ydHJFbnYgPSBhd2FpdCBpbnN0YWxsUG9ydHIoKTtcbiAgICBhd2FpdCB3cml0ZVBvcnRyQ29uZmlnKHBvcnRyQ29uZmlnLCBwb3J0ckVudik7XG4gICAgY29uc3QgcG9ydHIgPSBhd2FpdCBzdGFydFBvcnRyKHBvcnRyQ29uZmlnLCBwb3J0ckVudik7XG4gICAgY3R4LmJpbmRQcm9jZXNzKHBvcnRyKTtcblxuICAgIGN0eC5vbkxpZmVjeWNsZShcInNodXRkb3duXCIsICgpID0+IHtcbiAgICAgIGlmICghcG9ydHIua2lsbGVkKSBwb3J0ci5raWxsKFwiU0lHVEVSTVwiKTtcbiAgICB9KTtcblxuICAgIGxvZ2dlci5pbmZvKGB0dW5uZWwgYm91bmQ6IHBvcnRyIC0+IDoke3BvcnR9ICgke3BvcnRyQ29uZmlnLnN1YmRvbWFpbn0uJHtwb3J0ckNvbmZpZy5zZXJ2ZXJ9KWApO1xuICB9O1xufVxuIl19
|
package/lib/src/plugin.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `authGate()` - the AppKit
|
|
2
|
+
* `authGate()` - the AppKit adapter around `@dbx-tools/auth`.
|
|
3
3
|
*
|
|
4
4
|
* It has NO routes of its own: the tunnel PROXY (not an HTTP server) calls the
|
|
5
5
|
* handlers this plugin exposes via {@link AuthGatePlugin.exports}. The plugin
|
|
6
|
-
* owns
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* this plugin is where the gate logic lives.
|
|
6
|
+
* owns tunnel authorization, AppKit Lakebase discovery, email delivery, and
|
|
7
|
+
* transport mounting. Better Auth owns users, OTPs, sessions, rate limits, and
|
|
8
|
+
* passkeys. `createApp` can run this plugin with or without `server()`.
|
|
10
9
|
*
|
|
11
10
|
* Options come from CLI flags OR env, with sensible defaults - see
|
|
12
11
|
* {@link resolveAuthGateConfig}. The one runtime dependency the plugin can't
|
|
@@ -15,8 +14,9 @@
|
|
|
15
14
|
*
|
|
16
15
|
* @module
|
|
17
16
|
*/
|
|
18
|
-
import { Plugin, type BasePluginConfig } from "@databricks/appkit";
|
|
19
|
-
import type
|
|
17
|
+
import { Plugin, type BasePluginConfig, type ResourceRequirement, ResourceType } from "@databricks/appkit";
|
|
18
|
+
import { type AuthorizeIdentity, type AuthStorageConfig, type AuthStorageMode } from "@dbx-tools/auth";
|
|
19
|
+
import type { AuthStatus } from "@dbx-tools/shared-auth";
|
|
20
20
|
import type { RequestHandler } from "express";
|
|
21
21
|
import { type GateOptions } from "./gate.ts";
|
|
22
22
|
interface GateMountContext {
|
|
@@ -26,7 +26,7 @@ interface GateMountContext {
|
|
|
26
26
|
}
|
|
27
27
|
export declare function mountGateOnContext(context: GateMountContext, options: GateOptions): void;
|
|
28
28
|
/** Options for the {@link authGate} plugin (all resolvable from env - see below). */
|
|
29
|
-
export interface AuthGateConfig extends BasePluginConfig {
|
|
29
|
+
export interface AuthGateConfig extends BasePluginConfig, AuthStorageConfig {
|
|
30
30
|
/** Allow-list patterns (domain / glob / `/regex/`). Empty = allow nobody. Env TUNNEL_AUTH_ALLOW. */
|
|
31
31
|
allow?: string | string[];
|
|
32
32
|
/**
|
|
@@ -86,6 +86,11 @@ export interface AuthGateConfig extends BasePluginConfig {
|
|
|
86
86
|
* different delivery path.
|
|
87
87
|
*/
|
|
88
88
|
sendCode?: (email: string, code: string, opts: SendCodeOptions) => Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Identity authorization independent of authentication. Defaults to the
|
|
91
|
+
* configured allow-list and is re-evaluated for every accepted session.
|
|
92
|
+
*/
|
|
93
|
+
authorizeIdentity?: AuthorizeIdentity;
|
|
89
94
|
/**
|
|
90
95
|
* The public `<subdomain>.<server>` that identifies portr traffic by its `Host`
|
|
91
96
|
* header. Only requests whose `Host` matches this are gated; everything else
|
|
@@ -136,31 +141,26 @@ export interface ResolvedAuthGateConfig {
|
|
|
136
141
|
forwardHeaders: string[];
|
|
137
142
|
/** Run OPEN with no gate. */
|
|
138
143
|
insecure: boolean;
|
|
144
|
+
storage: AuthStorageMode;
|
|
145
|
+
sqlitePath?: string;
|
|
139
146
|
}
|
|
140
147
|
/** Merge {@link AuthGateConfig} over env over defaults into a resolved config. */
|
|
141
148
|
export declare function resolveAuthGateConfig(config: AuthGateConfig): ResolvedAuthGateConfig;
|
|
142
149
|
/** The handlers the gate middleware calls in-process (returned by {@link AuthGatePlugin.exports}). */
|
|
143
150
|
export interface AuthGateApi {
|
|
144
|
-
/**
|
|
145
|
-
request
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}>;
|
|
155
|
-
/** Resolve the authenticated email for a session token, or undefined. */
|
|
156
|
-
session(token: string | undefined): Promise<string | undefined>;
|
|
157
|
-
/** Session TTL in seconds (for the cookie Max-Age). */
|
|
158
|
-
readonly sessionTtlSeconds: number;
|
|
159
|
-
/** The gate status payload (`enabled` is always true when this plugin runs). */
|
|
160
|
-
status(token: string | undefined): Promise<AuthStatus>;
|
|
151
|
+
/** Better Auth and compatibility routes under `/api/email/auth/*`. */
|
|
152
|
+
handler(request: Request): Promise<Response>;
|
|
153
|
+
/** Resolve the authorized email for request headers, or undefined. */
|
|
154
|
+
session(headers: Headers): Promise<string | undefined>;
|
|
155
|
+
/** The gate status payload. */
|
|
156
|
+
status(headers: Headers): Promise<AuthStatus>;
|
|
157
|
+
/** Whether the runtime exposes passkey enrollment and authentication. */
|
|
158
|
+
readonly passkeysEnabled: boolean;
|
|
159
|
+
/** Close auth storage owned by this runtime. */
|
|
160
|
+
close(): Promise<void>;
|
|
161
161
|
}
|
|
162
162
|
/**
|
|
163
|
-
* AppKit plugin
|
|
163
|
+
* AppKit plugin adapting `@dbx-tools/auth` to tunnel traffic. On `setup()` it registers the login
|
|
164
164
|
* routes (`/api/email/auth/*`) and a gating middleware on the app's OWN Express
|
|
165
165
|
* server via `this.context`, so a public portr caller must prove an email before
|
|
166
166
|
* reaching the app's `/api/*` - see `./gate`. Front-door (platform) traffic and
|
|
@@ -174,14 +174,28 @@ export declare class AuthGatePlugin extends Plugin<AuthGateConfig> {
|
|
|
174
174
|
stability: "beta";
|
|
175
175
|
resources: {
|
|
176
176
|
required: never[];
|
|
177
|
-
optional:
|
|
177
|
+
optional: {
|
|
178
|
+
type: ResourceType.POSTGRES;
|
|
179
|
+
alias: string;
|
|
180
|
+
resourceKey: string;
|
|
181
|
+
description: string;
|
|
182
|
+
permission: "CAN_CONNECT_AND_CREATE";
|
|
183
|
+
fields: {
|
|
184
|
+
instance_name: {
|
|
185
|
+
env: string;
|
|
186
|
+
};
|
|
187
|
+
database_name: {
|
|
188
|
+
env: string;
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
}[];
|
|
178
192
|
};
|
|
179
193
|
};
|
|
180
194
|
private resolved;
|
|
181
|
-
private
|
|
182
|
-
|
|
183
|
-
private readonly verifyLimiter;
|
|
195
|
+
private runtime?;
|
|
196
|
+
static getResourceRequirements(config: AuthGateConfig): ResourceRequirement[];
|
|
184
197
|
setup(): Promise<void>;
|
|
198
|
+
shutdown(): Promise<void>;
|
|
185
199
|
/**
|
|
186
200
|
* Register the login routes (`/api/email/auth/*`) and the gating middleware on
|
|
187
201
|
* the app's OWN Express server. At `setup:complete`, the deferred server plugin
|
|
@@ -192,9 +206,8 @@ export declare class AuthGatePlugin extends Plugin<AuthGateConfig> {
|
|
|
192
206
|
private mountGateRoutes;
|
|
193
207
|
/** The code sender: the configured `sendCode`, else the shared-transport default. */
|
|
194
208
|
private get sendCode();
|
|
209
|
+
private authorizeIdentity;
|
|
195
210
|
exports(): AuthGateApi;
|
|
196
|
-
private handleRequest;
|
|
197
|
-
private handleVerify;
|
|
198
211
|
}
|
|
199
212
|
/** Factory: `authGate({ allow, subject, ... })` for an AppKit `plugins` array. */
|
|
200
213
|
export declare const authGate: import("@databricks/appkit").ToPlugin<typeof AuthGatePlugin, AuthGateConfig, "authGate">;
|