@dbx-tools/tunnel 0.6.60 → 0.6.61
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 +59 -56
- package/index.ts +6 -3
- package/lib/index.d.ts +6 -3
- package/lib/index.js +5 -3
- package/lib/src/{app.d.ts → code-email.d.ts} +10 -61
- package/lib/src/code-email.js +108 -0
- package/lib/src/gate.d.ts +60 -0
- package/lib/src/gate.js +196 -0
- package/lib/src/interceptor.d.ts +4 -4
- package/lib/src/interceptor.js +5 -5
- package/lib/src/plugin.d.ts +57 -3
- package/lib/src/plugin.js +77 -6
- package/lib/src/send-code.d.ts +28 -0
- package/lib/src/send-code.js +68 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -7
- package/src/code-email.ts +118 -0
- package/src/gate.ts +241 -0
- package/src/interceptor.ts +4 -4
- package/src/plugin.ts +136 -6
- package/src/send-code.ts +112 -0
- package/lib/src/app.js +0 -258
- package/lib/src/proxy.d.ts +0 -49
- package/lib/src/proxy.js +0 -247
- package/src/app.ts +0 -292
- package/src/proxy.ts +0 -299
package/lib/src/gate.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tunnel's in-app AUTH GATE - Express middleware + login routes the
|
|
3
|
+
* {@link AuthGatePlugin} registers on the app's OWN server via `this.context`.
|
|
4
|
+
*
|
|
5
|
+
* This replaces the old standalone reverse-proxy (`proxy.ts`): the app is now the
|
|
6
|
+
* process, so there is nothing to forward to. Instead the gate is middleware that
|
|
7
|
+
* either short-circuits (401, or answers the open login routes) or calls `next()`
|
|
8
|
+
* to let the app's real handlers run. It is the "stands in for AppKit auth" path:
|
|
9
|
+
* a portr caller proves an email via OTP, and on success the gate injects the
|
|
10
|
+
* identity headers AppKit reads, so a gated request runs like a front-door one.
|
|
11
|
+
*
|
|
12
|
+
* WHICH TRAFFIC IS GATED - the `Host` header, not the socket. portr's client
|
|
13
|
+
* forwards with Go's `httputil.NewSingleHostReverseProxy` and a `Director` that
|
|
14
|
+
* PRESERVES the original `Host`, so tunnel requests arrive with
|
|
15
|
+
* `Host: <subdomain>.<server>` (the public domain). A local process hitting the
|
|
16
|
+
* app directly sends `Host: 127.0.0.1:<port>` / `localhost`. So ONLY requests whose
|
|
17
|
+
* `Host` matches the configured public domain are gated; the platform front door
|
|
18
|
+
* and any other local client pass through untouched. There is no portr-injected
|
|
19
|
+
* identifying header and no TCP/source-IP signal to use instead (the client dials
|
|
20
|
+
* the target over plain loopback).
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
import { http, json, log, token } from "@dbx-tools/shared-core";
|
|
25
|
+
import { authRequestSchema, authVerifySchema, SESSION_COOKIE_NAME } from "@dbx-tools/shared-email";
|
|
26
|
+
import { toHeaderPolicy } from "./headers.js";
|
|
27
|
+
const logger = log.logger("tunnel:gate");
|
|
28
|
+
/** Route prefix the login flow lives under (open, answered in-process). */
|
|
29
|
+
export const AUTH_PREFIX = "/api/email/auth";
|
|
30
|
+
/**
|
|
31
|
+
* True when the request's `Host` is the tunnel's public domain - i.e. it came in
|
|
32
|
+
* over portr. Case-insensitive; the optional `:port` is ignored. When no public
|
|
33
|
+
* domain is configured, nothing is tunnel traffic.
|
|
34
|
+
*/
|
|
35
|
+
export function isTunnelHost(req, publicDomain) {
|
|
36
|
+
if (!publicDomain)
|
|
37
|
+
return false;
|
|
38
|
+
const host = (req.headers.host ?? "").toLowerCase().split(":")[0];
|
|
39
|
+
return host === publicDomain.toLowerCase().split(":")[0];
|
|
40
|
+
}
|
|
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
|
+
/**
|
|
57
|
+
* Client IP for rate-limiting: the RIGHTMOST `x-forwarded-for` entry (the value
|
|
58
|
+
* the nearest trusted hop - portr - wrote), else the socket address. Reading the
|
|
59
|
+
* rightmost, not the leftmost, stops a caller minting a fresh rate-limit bucket by
|
|
60
|
+
* varying the header. Called before {@link stripHeaders}.
|
|
61
|
+
*/
|
|
62
|
+
function clientIp(req) {
|
|
63
|
+
const forwarded = req.headers["x-forwarded-for"];
|
|
64
|
+
const chain = (Array.isArray(forwarded) ? forwarded.join(",") : (forwarded ?? ""))
|
|
65
|
+
.split(",")
|
|
66
|
+
.map((entry) => entry.trim())
|
|
67
|
+
.filter(Boolean);
|
|
68
|
+
return chain.at(-1) ?? req.socket.remoteAddress ?? "unknown";
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Remove the gate's session cookie from the `Cookie` header before the app's
|
|
72
|
+
* handlers run, so the app never sees `dbx_auth` (it is the gate's concern).
|
|
73
|
+
* Preserves other cookies; deletes the header when it becomes empty.
|
|
74
|
+
*/
|
|
75
|
+
function stripSessionCookie(req) {
|
|
76
|
+
const raw = req.headers.cookie;
|
|
77
|
+
if (!raw)
|
|
78
|
+
return;
|
|
79
|
+
const kept = raw
|
|
80
|
+
.split(";")
|
|
81
|
+
.map((c) => c.trim())
|
|
82
|
+
.filter((c) => c && !c.startsWith(`${SESSION_COOKIE_NAME}=`));
|
|
83
|
+
if (kept.length)
|
|
84
|
+
req.headers.cookie = kept.join("; ");
|
|
85
|
+
else
|
|
86
|
+
delete req.headers.cookie;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Present an OTP-authenticated caller to the app the SAME way a platform front
|
|
90
|
+
* door does: set the front-door identity headers to the verified address (AppKit
|
|
91
|
+
* reads {@link token.USER_ID_HEADER} for the OBO user id), so the app needs no
|
|
92
|
+
* gate-specific code path.
|
|
93
|
+
*
|
|
94
|
+
* What the gate CANNOT set is {@link token.ACCESS_TOKEN_HEADER}: an OTP session
|
|
95
|
+
* proves an email, not possession of a Databricks credential. Its absence is what
|
|
96
|
+
* `@dbx-tools/appkit`'s `identity: "auto"` detects, so a gated request runs as the
|
|
97
|
+
* app service principal instead of throwing.
|
|
98
|
+
*/
|
|
99
|
+
function injectIdentity(req, email) {
|
|
100
|
+
req.headers[token.USER_ID_HEADER] = email;
|
|
101
|
+
req.headers[token.USER_EMAIL_HEADER] = email;
|
|
102
|
+
}
|
|
103
|
+
function sendJson(res, status, body, setCookie) {
|
|
104
|
+
if (setCookie)
|
|
105
|
+
res.setHeader("set-cookie", setCookie);
|
|
106
|
+
res.status(status).json(body);
|
|
107
|
+
}
|
|
108
|
+
/** Read the raw request body as text (AppKit parses JSON, but the gate routes
|
|
109
|
+
* are mounted before that runs for tunnel traffic, so read defensively). */
|
|
110
|
+
function readBody(req) {
|
|
111
|
+
// AppKit's json body-parser may have already populated req.body; prefer it.
|
|
112
|
+
if (req.body !== undefined && req.body !== null) {
|
|
113
|
+
return Promise.resolve(typeof req.body === "string" ? req.body : JSON.stringify(req.body));
|
|
114
|
+
}
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
let data = "";
|
|
117
|
+
req.on("data", (chunk) => (data += chunk));
|
|
118
|
+
req.on("end", () => resolve(data));
|
|
119
|
+
req.on("error", () => resolve(data));
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Register the login routes and the gating middleware on the app's Express
|
|
124
|
+
* instance. Called from {@link AuthGatePlugin} with the router AppKit hands
|
|
125
|
+
* `injectRoutes`, plus `this.context.addMiddleware` for the global gate.
|
|
126
|
+
*
|
|
127
|
+
* `addRoute`/`addMiddleware` are used (via the passed callbacks) because the login
|
|
128
|
+
* routes live at an ABSOLUTE path (`/api/email/auth/*`, the client's contract),
|
|
129
|
+
* not under the plugin's `/api/authGate` base.
|
|
130
|
+
*/
|
|
131
|
+
export function mountGate(opts, addRoute, addMiddleware) {
|
|
132
|
+
const { gate, publicDomain, forwardHeaders } = opts;
|
|
133
|
+
const headerPolicy = toHeaderPolicy(forwardHeaders);
|
|
134
|
+
logger.debug("gate mounted", { publicDomain, forward: headerPolicy.patterns });
|
|
135
|
+
const applyHeaderPolicy = (req) => {
|
|
136
|
+
const removed = headerPolicy.apply(req.headers);
|
|
137
|
+
if (removed.length)
|
|
138
|
+
logger.debug("stripped inbound headers", { removed });
|
|
139
|
+
};
|
|
140
|
+
// --- Login routes (open on tunnel traffic; answered in-process) ---
|
|
141
|
+
const statusHandler = (async (req, res) => {
|
|
142
|
+
const cookie = http.parseCookies(req.headers.cookie ?? null)[SESSION_COOKIE_NAME];
|
|
143
|
+
sendJson(res, 200, await gate.status(cookie));
|
|
144
|
+
});
|
|
145
|
+
const requestHandler = (async (req, res) => {
|
|
146
|
+
const parsed = authRequestSchema.safeParse(json.parseRecord(await readBody(req)));
|
|
147
|
+
if (!parsed.success)
|
|
148
|
+
return sendJson(res, 200, { ok: true }); // anti-enumeration
|
|
149
|
+
sendJson(res, 200, await gate.request(parsed.data.email, clientIp(req)));
|
|
150
|
+
});
|
|
151
|
+
const verifyHandler = (async (req, res) => {
|
|
152
|
+
const parsed = authVerifySchema.safeParse(json.parseRecord(await readBody(req)));
|
|
153
|
+
if (!parsed.success)
|
|
154
|
+
return sendJson(res, 200, { ok: false });
|
|
155
|
+
const result = await gate.verify(parsed.data.email, parsed.data.code, clientIp(req));
|
|
156
|
+
const cookie = result.ok && result.token ? sessionCookie(result.token, gate.sessionTtlSeconds) : undefined;
|
|
157
|
+
sendJson(res, 200, { ok: result.ok, ...(result.retryAfter ? { retryAfter: result.retryAfter } : {}) }, cookie);
|
|
158
|
+
});
|
|
159
|
+
const logoutHandler = ((_req, res) => {
|
|
160
|
+
sendJson(res, 200, { ok: true }, `${SESSION_COOKIE_NAME}=; Path=/; HttpOnly; Max-Age=0`);
|
|
161
|
+
});
|
|
162
|
+
addRoute("get", `${AUTH_PREFIX}/status`, statusHandler);
|
|
163
|
+
addRoute("post", `${AUTH_PREFIX}/request`, requestHandler);
|
|
164
|
+
addRoute("post", `${AUTH_PREFIX}/verify`, verifyHandler);
|
|
165
|
+
addRoute("post", `${AUTH_PREFIX}/logout`, logoutHandler);
|
|
166
|
+
// --- The gate middleware (runs before static + the app's /api handlers) ---
|
|
167
|
+
const gateMiddleware = (async (req, res, next) => {
|
|
168
|
+
// Not tunnel traffic (platform front door, or any other local caller): the
|
|
169
|
+
// request is already authenticated (or is not ours to gate). Pass through.
|
|
170
|
+
if (!isTunnelHost(req, publicDomain))
|
|
171
|
+
return next();
|
|
172
|
+
const path = (req.url ?? "/").split("?")[0] ?? "/";
|
|
173
|
+
// The login flow is open so the browser can render <AuthGate> and sign in.
|
|
174
|
+
if (path.startsWith(AUTH_PREFIX))
|
|
175
|
+
return next();
|
|
176
|
+
// Anti-spoof: only the gate may assert identity on tunnel traffic.
|
|
177
|
+
applyHeaderPolicy(req);
|
|
178
|
+
// Static (non-API) loads freely so the SPA can render; drop the gate cookie.
|
|
179
|
+
if (!path.startsWith("/api/")) {
|
|
180
|
+
stripSessionCookie(req);
|
|
181
|
+
return next();
|
|
182
|
+
}
|
|
183
|
+
// Every other /api/* needs a valid OTP session.
|
|
184
|
+
const cookie = http.parseCookies(req.headers.cookie ?? null)[SESSION_COOKIE_NAME];
|
|
185
|
+
const email = await gate.session(cookie);
|
|
186
|
+
if (!email) {
|
|
187
|
+
sendJson(res, 401, { error: "authentication required", loginPath: AUTH_PREFIX });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
injectIdentity(req, email);
|
|
191
|
+
stripSessionCookie(req);
|
|
192
|
+
next();
|
|
193
|
+
});
|
|
194
|
+
addMiddleware("/", gateMiddleware);
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBRUgsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRWhFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25HLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHOUMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQUV6QywyRUFBMkU7QUFDM0UsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLGlCQUFpQixDQUFDO0FBb0I3Qzs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxHQUFZLEVBQUUsWUFBZ0M7SUFDekUsSUFBSSxDQUFDLFlBQVk7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUNoQyxNQUFNLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsRSxPQUFPLElBQUksS0FBSyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzNELENBQUM7QUFFRCx1RUFBdUU7QUFDdkUsU0FBUyxhQUFhLENBQUMsS0FBYSxFQUFFLGFBQXFCO0lBQ3pELE9BQU87UUFDTCxHQUFHLG1CQUFtQixJQUFJLEtBQUssRUFBRTtRQUNqQyxRQUFRO1FBQ1IsVUFBVTtRQUNWLGNBQWM7UUFDZCxXQUFXLGFBQWEsRUFBRTtRQUMxQiw2RUFB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RUFBRSxDQUFDLENBQUM7WUFDakYsT0FBTztRQUNULENBQUM7UUFDRCxjQUFjLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzNCLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLElBQUksRUFBRSxDQUFDO0lBQ1QsQ0FBQyxDQUFtQixDQUFDO0lBRXJCLGFBQWEsQ0FBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDckMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhlIHR1bm5lbCdzIGluLWFwcCBBVVRIIEdBVEUgLSBFeHByZXNzIG1pZGRsZXdhcmUgKyBsb2dpbiByb3V0ZXMgdGhlXG4gKiB7QGxpbmsgQXV0aEdhdGVQbHVnaW59IHJlZ2lzdGVycyBvbiB0aGUgYXBwJ3MgT1dOIHNlcnZlciB2aWEgYHRoaXMuY29udGV4dGAuXG4gKlxuICogVGhpcyByZXBsYWNlcyB0aGUgb2xkIHN0YW5kYWxvbmUgcmV2ZXJzZS1wcm94eSAoYHByb3h5LnRzYCk6IHRoZSBhcHAgaXMgbm93IHRoZVxuICogcHJvY2Vzcywgc28gdGhlcmUgaXMgbm90aGluZyB0byBmb3J3YXJkIHRvLiBJbnN0ZWFkIHRoZSBnYXRlIGlzIG1pZGRsZXdhcmUgdGhhdFxuICogZWl0aGVyIHNob3J0LWNpcmN1aXRzICg0MDEsIG9yIGFuc3dlcnMgdGhlIG9wZW4gbG9naW4gcm91dGVzKSBvciBjYWxscyBgbmV4dCgpYFxuICogdG8gbGV0IHRoZSBhcHAncyByZWFsIGhhbmRsZXJzIHJ1bi4gSXQgaXMgdGhlIFwic3RhbmRzIGluIGZvciBBcHBLaXQgYXV0aFwiIHBhdGg6XG4gKiBhIHBvcnRyIGNhbGxlciBwcm92ZXMgYW4gZW1haWwgdmlhIE9UUCwgYW5kIG9uIHN1Y2Nlc3MgdGhlIGdhdGUgaW5qZWN0cyB0aGVcbiAqIGlkZW50aXR5IGhlYWRlcnMgQXBwS2l0IHJlYWRzLCBzbyBhIGdhdGVkIHJlcXVlc3QgcnVucyBsaWtlIGEgZnJvbnQtZG9vciBvbmUuXG4gKlxuICogV0hJQ0ggVFJBRkZJQyBJUyBHQVRFRCAtIHRoZSBgSG9zdGAgaGVhZGVyLCBub3QgdGhlIHNvY2tldC4gcG9ydHIncyBjbGllbnRcbiAqIGZvcndhcmRzIHdpdGggR28ncyBgaHR0cHV0aWwuTmV3U2luZ2xlSG9zdFJldmVyc2VQcm94eWAgYW5kIGEgYERpcmVjdG9yYCB0aGF0XG4gKiBQUkVTRVJWRVMgdGhlIG9yaWdpbmFsIGBIb3N0YCwgc28gdHVubmVsIHJlcXVlc3RzIGFycml2ZSB3aXRoXG4gKiBgSG9zdDogPHN1YmRvbWFpbj4uPHNlcnZlcj5gICh0aGUgcHVibGljIGRvbWFpbikuIEEgbG9jYWwgcHJvY2VzcyBoaXR0aW5nIHRoZVxuICogYXBwIGRpcmVjdGx5IHNlbmRzIGBIb3N0OiAxMjcuMC4wLjE6PHBvcnQ+YCAvIGBsb2NhbGhvc3RgLiBTbyBPTkxZIHJlcXVlc3RzIHdob3NlXG4gKiBgSG9zdGAgbWF0Y2hlcyB0aGUgY29uZmlndXJlZCBwdWJsaWMgZG9tYWluIGFyZSBnYXRlZDsgdGhlIHBsYXRmb3JtIGZyb250IGRvb3JcbiAqIGFuZCBhbnkgb3RoZXIgbG9jYWwgY2xpZW50IHBhc3MgdGhyb3VnaCB1bnRvdWNoZWQuIFRoZXJlIGlzIG5vIHBvcnRyLWluamVjdGVkXG4gKiBpZGVudGlmeWluZyBoZWFkZXIgYW5kIG5vIFRDUC9zb3VyY2UtSVAgc2lnbmFsIHRvIHVzZSBpbnN0ZWFkICh0aGUgY2xpZW50IGRpYWxzXG4gKiB0aGUgdGFyZ2V0IG92ZXIgcGxhaW4gbG9vcGJhY2spLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBodHRwLCBqc29uLCBsb2csIHRva2VuIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgUmVxdWVzdCwgUmVxdWVzdEhhbmRsZXIsIFJlc3BvbnNlIH0gZnJvbSBcImV4cHJlc3NcIjtcbmltcG9ydCB7IGF1dGhSZXF1ZXN0U2NoZW1hLCBhdXRoVmVyaWZ5U2NoZW1hLCBTRVNTSU9OX0NPT0tJRV9OQU1FIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWVtYWlsXCI7XG5pbXBvcnQgeyB0b0hlYWRlclBvbGljeSB9IGZyb20gXCIuL2hlYWRlcnMudHNcIjtcbmltcG9ydCB0eXBlIHsgQXV0aEdhdGVBcGkgfSBmcm9tIFwiLi9wbHVnaW4udHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcInR1bm5lbDpnYXRlXCIpO1xuXG4vKiogUm91dGUgcHJlZml4IHRoZSBsb2dpbiBmbG93IGxpdmVzIHVuZGVyIChvcGVuLCBhbnN3ZXJlZCBpbi1wcm9jZXNzKS4gKi9cbmV4cG9ydCBjb25zdCBBVVRIX1BSRUZJWCA9IFwiL2FwaS9lbWFpbC9hdXRoXCI7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgbW91bnRHYXRlfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2F0ZU9wdGlvbnMge1xuICAvKiogVGhlIGluLXByb2Nlc3MgZ2F0ZSBBUEkgKHNlc3Npb24vcmVxdWVzdC92ZXJpZnkvc3RhdHVzKS4gKi9cbiAgZ2F0ZTogQXV0aEdhdGVBcGk7XG4gIC8qKlxuICAgKiBUaGUgcHVibGljIGA8c3ViZG9tYWluPi48c2VydmVyPmAgdGhhdCBpZGVudGlmaWVzIHBvcnRyIHRyYWZmaWMgYnkgYEhvc3RgLlxuICAgKiBXaGVuIGFic2VudCwgbm8gcmVxdWVzdCBpcyBldmVyIGNsYXNzaWZpZWQgYXMgdHVubmVsIHRyYWZmaWMgYW5kIHRoZSBnYXRlIGlzXG4gICAqIGluZXJ0IChldmVyeXRoaW5nIHBhc3NlcyB0aHJvdWdoKSAtIGEgdHVubmVsIHdpdGggbm8gcHVibGljIGRvbWFpbiBnYXRlc1xuICAgKiBub3RoaW5nLlxuICAgKi9cbiAgcHVibGljRG9tYWluPzogc3RyaW5nO1xuICAvKipcbiAgICogRXh0cmEgYHgtYCByZXF1ZXN0IGhlYWRlcnMgdHVubmVsIHRyYWZmaWMgbWF5IGZvcndhcmQgKHVuaW9uZWQgd2l0aCB0aGVcbiAgICogYnVpbHQtaW4gYWxsb3ctbGlzdCkuIEV2ZXJ5IG90aGVyIGB4LWAgaGVhZGVyIGlzIHN0cmlwcGVkIGZyb20gdHVubmVsIHRyYWZmaWMuXG4gICAqL1xuICBmb3J3YXJkSGVhZGVycz86IHJlYWRvbmx5IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFRydWUgd2hlbiB0aGUgcmVxdWVzdCdzIGBIb3N0YCBpcyB0aGUgdHVubmVsJ3MgcHVibGljIGRvbWFpbiAtIGkuZS4gaXQgY2FtZSBpblxuICogb3ZlciBwb3J0ci4gQ2FzZS1pbnNlbnNpdGl2ZTsgdGhlIG9wdGlvbmFsIGA6cG9ydGAgaXMgaWdub3JlZC4gV2hlbiBubyBwdWJsaWNcbiAqIGRvbWFpbiBpcyBjb25maWd1cmVkLCBub3RoaW5nIGlzIHR1bm5lbCB0cmFmZmljLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNUdW5uZWxIb3N0KHJlcTogUmVxdWVzdCwgcHVibGljRG9tYWluOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgaWYgKCFwdWJsaWNEb21haW4pIHJldHVybiBmYWxzZTtcbiAgY29uc3QgaG9zdCA9IChyZXEuaGVhZGVycy5ob3N0ID8/IFwiXCIpLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xuICByZXR1cm4gaG9zdCA9PT0gcHVibGljRG9tYWluLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCI6XCIpWzBdO1xufVxuXG4vKiogVGhlIHNlc3Npb24gY29va2llIGZvciBhIHZlcmlmaWVkIGVtYWlsLCBhcyBhIFNldC1Db29raWUgc3RyaW5nLiAqL1xuZnVuY3Rpb24gc2Vzc2lvbkNvb2tpZSh2YWx1ZTogc3RyaW5nLCBtYXhBZ2VTZWNvbmRzOiBudW1iZXIpOiBzdHJpbmcge1xuICByZXR1cm4gW1xuICAgIGAke1NFU1NJT05fQ09PS0lFX05BTUV9PSR7dmFsdWV9YCxcbiAgICBcIlBhdGg9L1wiLFxuICAgIFwiSHR0cE9ubHlcIixcbiAgICBcIlNhbWVTaXRlPUxheFwiLFxuICAgIGBNYXgtQWdlPSR7bWF4QWdlU2Vjb25kc31gLFxuICAgIC8vIFJlYWwgZW5mb3JjZW1lbnQgaW4gcHJvZHVjdGlvbjogdGhlIHNlc3Npb24gY29va2llIG11c3QgYmUgU2VjdXJlIHNvIGl0IGlzXG4gICAgLy8gbmV2ZXIgc2VudCBvdmVyIHBsYWludGV4dC4gTG9jYWwgZGV2IChodHRwKSBvbWl0cyBpdCBzbyB0aGUgY29va2llIHdvcmtzLlxuICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSBcInByb2R1Y3Rpb25cIiA/IFwiU2VjdXJlXCIgOiBcIlwiLFxuICBdXG4gICAgLmZpbHRlcihCb29sZWFuKVxuICAgIC5qb2luKFwiOyBcIik7XG59XG5cbi8qKlxuICogQ2xpZW50IElQIGZvciByYXRlLWxpbWl0aW5nOiB0aGUgUklHSFRNT1NUIGB4LWZvcndhcmRlZC1mb3JgIGVudHJ5ICh0aGUgdmFsdWVcbiAqIHRoZSBuZWFyZXN0IHRydXN0ZWQgaG9wIC0gcG9ydHIgLSB3cm90ZSksIGVsc2UgdGhlIHNvY2tldCBhZGRyZXNzLiBSZWFkaW5nIHRoZVxuICogcmlnaHRtb3N0LCBub3QgdGhlIGxlZnRtb3N0LCBzdG9wcyBhIGNhbGxlciBtaW50aW5nIGEgZnJlc2ggcmF0ZS1saW1pdCBidWNrZXQgYnlcbiAqIHZhcnlpbmcgdGhlIGhlYWRlci4gQ2FsbGVkIGJlZm9yZSB7QGxpbmsgc3RyaXBIZWFkZXJzfS5cbiAqL1xuZnVuY3Rpb24gY2xpZW50SXAocmVxOiBSZXF1ZXN0KTogc3RyaW5nIHtcbiAgY29uc3QgZm9yd2FyZGVkID0gcmVxLmhlYWRlcnNbXCJ4LWZvcndhcmRlZC1mb3JcIl07XG4gIGNvbnN0IGNoYWluID0gKEFycmF5LmlzQXJyYXkoZm9yd2FyZGVkKSA/IGZvcndhcmRlZC5qb2luKFwiLFwiKSA6IChmb3J3YXJkZWQgPz8gXCJcIikpXG4gICAgLnNwbGl0KFwiLFwiKVxuICAgIC5tYXAoKGVudHJ5KSA9PiBlbnRyeS50cmltKCkpXG4gICAgLmZpbHRlcihCb29sZWFuKTtcbiAgcmV0dXJuIGNoYWluLmF0KC0xKSA/PyByZXEuc29ja2V0LnJlbW90ZUFkZHJlc3MgPz8gXCJ1bmtub3duXCI7XG59XG5cbi8qKlxuICogUmVtb3ZlIHRoZSBnYXRlJ3Mgc2Vzc2lvbiBjb29raWUgZnJvbSB0aGUgYENvb2tpZWAgaGVhZGVyIGJlZm9yZSB0aGUgYXBwJ3NcbiAqIGhhbmRsZXJzIHJ1biwgc28gdGhlIGFwcCBuZXZlciBzZWVzIGBkYnhfYXV0aGAgKGl0IGlzIHRoZSBnYXRlJ3MgY29uY2VybikuXG4gKiBQcmVzZXJ2ZXMgb3RoZXIgY29va2llczsgZGVsZXRlcyB0aGUgaGVhZGVyIHdoZW4gaXQgYmVjb21lcyBlbXB0eS5cbiAqL1xuZnVuY3Rpb24gc3RyaXBTZXNzaW9uQ29va2llKHJlcTogUmVxdWVzdCk6IHZvaWQge1xuICBjb25zdCByYXcgPSByZXEuaGVhZGVycy5jb29raWU7XG4gIGlmICghcmF3KSByZXR1cm47XG4gIGNvbnN0IGtlcHQgPSByYXdcbiAgICAuc3BsaXQoXCI7XCIpXG4gICAgLm1hcCgoYykgPT4gYy50cmltKCkpXG4gICAgLmZpbHRlcigoYykgPT4gYyAmJiAhYy5zdGFydHNXaXRoKGAke1NFU1NJT05fQ09PS0lFX05BTUV9PWApKTtcbiAgaWYgKGtlcHQubGVuZ3RoKSByZXEuaGVhZGVycy5jb29raWUgPSBrZXB0LmpvaW4oXCI7IFwiKTtcbiAgZWxzZSBkZWxldGUgcmVxLmhlYWRlcnMuY29va2llO1xufVxuXG4vKipcbiAqIFByZXNlbnQgYW4gT1RQLWF1dGhlbnRpY2F0ZWQgY2FsbGVyIHRvIHRoZSBhcHAgdGhlIFNBTUUgd2F5IGEgcGxhdGZvcm0gZnJvbnRcbiAqIGRvb3IgZG9lczogc2V0IHRoZSBmcm9udC1kb29yIGlkZW50aXR5IGhlYWRlcnMgdG8gdGhlIHZlcmlmaWVkIGFkZHJlc3MgKEFwcEtpdFxuICogcmVhZHMge0BsaW5rIHRva2VuLlVTRVJfSURfSEVBREVSfSBmb3IgdGhlIE9CTyB1c2VyIGlkKSwgc28gdGhlIGFwcCBuZWVkcyBub1xuICogZ2F0ZS1zcGVjaWZpYyBjb2RlIHBhdGguXG4gKlxuICogV2hhdCB0aGUgZ2F0ZSBDQU5OT1Qgc2V0IGlzIHtAbGluayB0b2tlbi5BQ0NFU1NfVE9LRU5fSEVBREVSfTogYW4gT1RQIHNlc3Npb25cbiAqIHByb3ZlcyBhbiBlbWFpbCwgbm90IHBvc3Nlc3Npb24gb2YgYSBEYXRhYnJpY2tzIGNyZWRlbnRpYWwuIEl0cyBhYnNlbmNlIGlzIHdoYXRcbiAqIGBAZGJ4LXRvb2xzL2FwcGtpdGAncyBgaWRlbnRpdHk6IFwiYXV0b1wiYCBkZXRlY3RzLCBzbyBhIGdhdGVkIHJlcXVlc3QgcnVucyBhcyB0aGVcbiAqIGFwcCBzZXJ2aWNlIHByaW5jaXBhbCBpbnN0ZWFkIG9mIHRocm93aW5nLlxuICovXG5mdW5jdGlvbiBpbmplY3RJZGVudGl0eShyZXE6IFJlcXVlc3QsIGVtYWlsOiBzdHJpbmcpOiB2b2lkIHtcbiAgcmVxLmhlYWRlcnNbdG9rZW4uVVNFUl9JRF9IRUFERVJdID0gZW1haWw7XG4gIHJlcS5oZWFkZXJzW3Rva2VuLlVTRVJfRU1BSUxfSEVBREVSXSA9IGVtYWlsO1xufVxuXG5mdW5jdGlvbiBzZW5kSnNvbihyZXM6IFJlc3BvbnNlLCBzdGF0dXM6IG51bWJlciwgYm9keTogdW5rbm93biwgc2V0Q29va2llPzogc3RyaW5nKTogdm9pZCB7XG4gIGlmIChzZXRDb29raWUpIHJlcy5zZXRIZWFkZXIoXCJzZXQtY29va2llXCIsIHNldENvb2tpZSk7XG4gIHJlcy5zdGF0dXMoc3RhdHVzKS5qc29uKGJvZHkpO1xufVxuXG4vKiogUmVhZCB0aGUgcmF3IHJlcXVlc3QgYm9keSBhcyB0ZXh0IChBcHBLaXQgcGFyc2VzIEpTT04sIGJ1dCB0aGUgZ2F0ZSByb3V0ZXNcbiAqIGFyZSBtb3VudGVkIGJlZm9yZSB0aGF0IHJ1bnMgZm9yIHR1bm5lbCB0cmFmZmljLCBzbyByZWFkIGRlZmVuc2l2ZWx5KS4gKi9cbmZ1bmN0aW9uIHJlYWRCb2R5KHJlcTogUmVxdWVzdCk6IFByb21pc2U8c3RyaW5nPiB7XG4gIC8vIEFwcEtpdCdzIGpzb24gYm9keS1wYXJzZXIgbWF5IGhhdmUgYWxyZWFkeSBwb3B1bGF0ZWQgcmVxLmJvZHk7IHByZWZlciBpdC5cbiAgaWYgKHJlcS5ib2R5ICE9PSB1bmRlZmluZWQgJiYgcmVxLmJvZHkgIT09IG51bGwpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHR5cGVvZiByZXEuYm9keSA9PT0gXCJzdHJpbmdcIiA/IHJlcS5ib2R5IDogSlNPTi5zdHJpbmdpZnkocmVxLmJvZHkpKTtcbiAgfVxuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBsZXQgZGF0YSA9IFwiXCI7XG4gICAgcmVxLm9uKFwiZGF0YVwiLCAoY2h1bmspID0+IChkYXRhICs9IGNodW5rKSk7XG4gICAgcmVxLm9uKFwiZW5kXCIsICgpID0+IHJlc29sdmUoZGF0YSkpO1xuICAgIHJlcS5vbihcImVycm9yXCIsICgpID0+IHJlc29sdmUoZGF0YSkpO1xuICB9KTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlciB0aGUgbG9naW4gcm91dGVzIGFuZCB0aGUgZ2F0aW5nIG1pZGRsZXdhcmUgb24gdGhlIGFwcCdzIEV4cHJlc3NcbiAqIGluc3RhbmNlLiBDYWxsZWQgZnJvbSB7QGxpbmsgQXV0aEdhdGVQbHVnaW59IHdpdGggdGhlIHJvdXRlciBBcHBLaXQgaGFuZHNcbiAqIGBpbmplY3RSb3V0ZXNgLCBwbHVzIGB0aGlzLmNvbnRleHQuYWRkTWlkZGxld2FyZWAgZm9yIHRoZSBnbG9iYWwgZ2F0ZS5cbiAqXG4gKiBgYWRkUm91dGVgL2BhZGRNaWRkbGV3YXJlYCBhcmUgdXNlZCAodmlhIHRoZSBwYXNzZWQgY2FsbGJhY2tzKSBiZWNhdXNlIHRoZSBsb2dpblxuICogcm91dGVzIGxpdmUgYXQgYW4gQUJTT0xVVEUgcGF0aCAoYC9hcGkvZW1haWwvYXV0aC8qYCwgdGhlIGNsaWVudCdzIGNvbnRyYWN0KSxcbiAqIG5vdCB1bmRlciB0aGUgcGx1Z2luJ3MgYC9hcGkvYXV0aEdhdGVgIGJhc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb3VudEdhdGUoXG4gIG9wdHM6IEdhdGVPcHRpb25zLFxuICBhZGRSb3V0ZTogKG1ldGhvZDogXCJnZXRcIiB8IFwicG9zdFwiLCBwYXRoOiBzdHJpbmcsIGhhbmRsZXI6IFJlcXVlc3RIYW5kbGVyKSA9PiB2b2lkLFxuICBhZGRNaWRkbGV3YXJlOiAocGF0aDogc3RyaW5nLCBoYW5kbGVyOiBSZXF1ZXN0SGFuZGxlcikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBjb25zdCB7IGdhdGUsIHB1YmxpY0RvbWFpbiwgZm9yd2FyZEhlYWRlcnMgfSA9IG9wdHM7XG4gIGNvbnN0IGhlYWRlclBvbGljeSA9IHRvSGVhZGVyUG9saWN5KGZvcndhcmRIZWFkZXJzKTtcbiAgbG9nZ2VyLmRlYnVnKFwiZ2F0ZSBtb3VudGVkXCIsIHsgcHVibGljRG9tYWluLCBmb3J3YXJkOiBoZWFkZXJQb2xpY3kucGF0dGVybnMgfSk7XG5cbiAgY29uc3QgYXBwbHlIZWFkZXJQb2xpY3kgPSAocmVxOiBSZXF1ZXN0KTogdm9pZCA9PiB7XG4gICAgY29uc3QgcmVtb3ZlZCA9IGhlYWRlclBvbGljeS5hcHBseShyZXEuaGVhZGVycyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik7XG4gICAgaWYgKHJlbW92ZWQubGVuZ3RoKSBsb2dnZXIuZGVidWcoXCJzdHJpcHBlZCBpbmJvdW5kIGhlYWRlcnNcIiwgeyByZW1vdmVkIH0pO1xuICB9O1xuXG4gIC8vIC0tLSBMb2dpbiByb3V0ZXMgKG9wZW4gb24gdHVubmVsIHRyYWZmaWM7IGFuc3dlcmVkIGluLXByb2Nlc3MpIC0tLVxuXG4gIGNvbnN0IHN0YXR1c0hhbmRsZXIgPSAoYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgY29va2llID0gaHR0cC5wYXJzZUNvb2tpZXMocmVxLmhlYWRlcnMuY29va2llID8/IG51bGwpW1NFU1NJT05fQ09PS0lFX05BTUVdO1xuICAgIHNlbmRKc29uKHJlcywgMjAwLCBhd2FpdCBnYXRlLnN0YXR1cyhjb29raWUpKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG5cbiAgY29uc3QgcmVxdWVzdEhhbmRsZXIgPSAoYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgY29uc3QgcGFyc2VkID0gYXV0aFJlcXVlc3RTY2hlbWEuc2FmZVBhcnNlKGpzb24ucGFyc2VSZWNvcmQoYXdhaXQgcmVhZEJvZHkocmVxKSkpO1xuICAgIGlmICghcGFyc2VkLnN1Y2Nlc3MpIHJldHVybiBzZW5kSnNvbihyZXMsIDIwMCwgeyBvazogdHJ1ZSB9KTsgLy8gYW50aS1lbnVtZXJhdGlvblxuICAgIHNlbmRKc29uKHJlcywgMjAwLCBhd2FpdCBnYXRlLnJlcXVlc3QocGFyc2VkLmRhdGEuZW1haWwsIGNsaWVudElwKHJlcSkpKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG5cbiAgY29uc3QgdmVyaWZ5SGFuZGxlciA9IChhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBhdXRoVmVyaWZ5U2NoZW1hLnNhZmVQYXJzZShqc29uLnBhcnNlUmVjb3JkKGF3YWl0IHJlYWRCb2R5KHJlcSkpKTtcbiAgICBpZiAoIXBhcnNlZC5zdWNjZXNzKSByZXR1cm4gc2VuZEpzb24ocmVzLCAyMDAsIHsgb2s6IGZhbHNlIH0pO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGdhdGUudmVyaWZ5KHBhcnNlZC5kYXRhLmVtYWlsLCBwYXJzZWQuZGF0YS5jb2RlLCBjbGllbnRJcChyZXEpKTtcbiAgICBjb25zdCBjb29raWUgPVxuICAgICAgcmVzdWx0Lm9rICYmIHJlc3VsdC50b2tlbiA/IHNlc3Npb25Db29raWUocmVzdWx0LnRva2VuLCBnYXRlLnNlc3Npb25UdGxTZWNvbmRzKSA6IHVuZGVmaW5lZDtcbiAgICBzZW5kSnNvbihcbiAgICAgIHJlcyxcbiAgICAgIDIwMCxcbiAgICAgIHsgb2s6IHJlc3VsdC5vaywgLi4uKHJlc3VsdC5yZXRyeUFmdGVyID8geyByZXRyeUFmdGVyOiByZXN1bHQucmV0cnlBZnRlciB9IDoge30pIH0sXG4gICAgICBjb29raWUsXG4gICAgKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG5cbiAgY29uc3QgbG9nb3V0SGFuZGxlciA9ICgoX3JlcSwgcmVzKSA9PiB7XG4gICAgc2VuZEpzb24ocmVzLCAyMDAsIHsgb2s6IHRydWUgfSwgYCR7U0VTU0lPTl9DT09LSUVfTkFNRX09OyBQYXRoPS87IEh0dHBPbmx5OyBNYXgtQWdlPTBgKTtcbiAgfSkgYXMgUmVxdWVzdEhhbmRsZXI7XG5cbiAgYWRkUm91dGUoXCJnZXRcIiwgYCR7QVVUSF9QUkVGSVh9L3N0YXR1c2AsIHN0YXR1c0hhbmRsZXIpO1xuICBhZGRSb3V0ZShcInBvc3RcIiwgYCR7QVVUSF9QUkVGSVh9L3JlcXVlc3RgLCByZXF1ZXN0SGFuZGxlcik7XG4gIGFkZFJvdXRlKFwicG9zdFwiLCBgJHtBVVRIX1BSRUZJWH0vdmVyaWZ5YCwgdmVyaWZ5SGFuZGxlcik7XG4gIGFkZFJvdXRlKFwicG9zdFwiLCBgJHtBVVRIX1BSRUZJWH0vbG9nb3V0YCwgbG9nb3V0SGFuZGxlcik7XG5cbiAgLy8gLS0tIFRoZSBnYXRlIG1pZGRsZXdhcmUgKHJ1bnMgYmVmb3JlIHN0YXRpYyArIHRoZSBhcHAncyAvYXBpIGhhbmRsZXJzKSAtLS1cblxuICBjb25zdCBnYXRlTWlkZGxld2FyZSA9IChhc3luYyAocmVxLCByZXMsIG5leHQpID0+IHtcbiAgICAvLyBOb3QgdHVubmVsIHRyYWZmaWMgKHBsYXRmb3JtIGZyb250IGRvb3IsIG9yIGFueSBvdGhlciBsb2NhbCBjYWxsZXIpOiB0aGVcbiAgICAvLyByZXF1ZXN0IGlzIGFscmVhZHkgYXV0aGVudGljYXRlZCAob3IgaXMgbm90IG91cnMgdG8gZ2F0ZSkuIFBhc3MgdGhyb3VnaC5cbiAgICBpZiAoIWlzVHVubmVsSG9zdChyZXEsIHB1YmxpY0RvbWFpbikpIHJldHVybiBuZXh0KCk7XG5cbiAgICBjb25zdCBwYXRoID0gKHJlcS51cmwgPz8gXCIvXCIpLnNwbGl0KFwiP1wiKVswXSA/PyBcIi9cIjtcblxuICAgIC8vIFRoZSBsb2dpbiBmbG93IGlzIG9wZW4gc28gdGhlIGJyb3dzZXIgY2FuIHJlbmRlciA8QXV0aEdhdGU+IGFuZCBzaWduIGluLlxuICAgIGlmIChwYXRoLnN0YXJ0c1dpdGgoQVVUSF9QUkVGSVgpKSByZXR1cm4gbmV4dCgpO1xuXG4gICAgLy8gQW50aS1zcG9vZjogb25seSB0aGUgZ2F0ZSBtYXkgYXNzZXJ0IGlkZW50aXR5IG9uIHR1bm5lbCB0cmFmZmljLlxuICAgIGFwcGx5SGVhZGVyUG9saWN5KHJlcSk7XG5cbiAgICAvLyBTdGF0aWMgKG5vbi1BUEkpIGxvYWRzIGZyZWVseSBzbyB0aGUgU1BBIGNhbiByZW5kZXI7IGRyb3AgdGhlIGdhdGUgY29va2llLlxuICAgIGlmICghcGF0aC5zdGFydHNXaXRoKFwiL2FwaS9cIikpIHtcbiAgICAgIHN0cmlwU2Vzc2lvbkNvb2tpZShyZXEpO1xuICAgICAgcmV0dXJuIG5leHQoKTtcbiAgICB9XG5cbiAgICAvLyBFdmVyeSBvdGhlciAvYXBpLyogbmVlZHMgYSB2YWxpZCBPVFAgc2Vzc2lvbi5cbiAgICBjb25zdCBjb29raWUgPSBodHRwLnBhcnNlQ29va2llcyhyZXEuaGVhZGVycy5jb29raWUgPz8gbnVsbClbU0VTU0lPTl9DT09LSUVfTkFNRV07XG4gICAgY29uc3QgZW1haWwgPSBhd2FpdCBnYXRlLnNlc3Npb24oY29va2llKTtcbiAgICBpZiAoIWVtYWlsKSB7XG4gICAgICBzZW5kSnNvbihyZXMsIDQwMSwgeyBlcnJvcjogXCJhdXRoZW50aWNhdGlvbiByZXF1aXJlZFwiLCBsb2dpblBhdGg6IEFVVEhfUFJFRklYIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpbmplY3RJZGVudGl0eShyZXEsIGVtYWlsKTtcbiAgICBzdHJpcFNlc3Npb25Db29raWUocmVxKTtcbiAgICBuZXh0KCk7XG4gIH0pIGFzIFJlcXVlc3RIYW5kbGVyO1xuXG4gIGFkZE1pZGRsZXdhcmUoXCIvXCIsIGdhdGVNaWRkbGV3YXJlKTtcbn1cbiJdfQ==
|
package/lib/src/interceptor.d.ts
CHANGED
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
* 4. registers an AppKit `shutdown` lifecycle handler so an orderly app shutdown
|
|
17
17
|
* also stops portr.
|
|
18
18
|
*
|
|
19
|
-
* The email-OTP GATE is a separate concern: it is the
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* portr half - "update the host, bind portr" -
|
|
19
|
+
* The email-OTP GATE is a separate concern: it is the `authGate` AppKit plugin,
|
|
20
|
+
* which registers the login routes + a gating middleware on the app's own server.
|
|
21
|
+
* Register it in the app's `plugins` for gated traffic. This interceptor is only
|
|
22
|
+
* the portr half - "update the host, bind portr" - the smallest useful unit.
|
|
23
23
|
*
|
|
24
24
|
* @module
|
|
25
25
|
*/
|
package/lib/src/interceptor.js
CHANGED
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
* 4. registers an AppKit `shutdown` lifecycle handler so an orderly app shutdown
|
|
17
17
|
* also stops portr.
|
|
18
18
|
*
|
|
19
|
-
* The email-OTP GATE is a separate concern: it is the
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* portr half - "update the host, bind portr" -
|
|
19
|
+
* The email-OTP GATE is a separate concern: it is the `authGate` AppKit plugin,
|
|
20
|
+
* which registers the login routes + a gating middleware on the app's own server.
|
|
21
|
+
* Register it in the app's `plugins` for gated traffic. This interceptor is only
|
|
22
|
+
* the portr half - "update the host, bind portr" - the smallest useful unit.
|
|
23
23
|
*
|
|
24
24
|
* @module
|
|
25
25
|
*/
|
|
@@ -81,4 +81,4 @@ export function tunnelInterceptor(options = {}) {
|
|
|
81
81
|
logger.info(`tunnel bound: portr -> :${port} (${portrConfig.subdomain}.${portrConfig.server})`);
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdCRztBQUdILE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFFLGtCQUFrQixFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUU1RixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUM7QUFnQmhELHFGQUFxRjtBQUNyRixTQUFTLGlCQUFpQixDQUFDLElBQWE7SUFDdEMsT0FBTyxJQUFJLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLElBQUksSUFBSSxDQUFDLENBQUM7QUFDakUsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxVQUFvQyxFQUFFO0lBQ3RFLE9BQU8sQ0FBQyxHQUF1QixFQUFRLEVBQUU7UUFDdkMsNkVBQTZFO1FBQzdFLDhFQUE4RTtRQUM5RSw2REFBNkQ7UUFDN0QsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQzNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxLQUFLLEdBQUcsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1FBQ3pELENBQUM7UUFFRCxnRkFBZ0Y7UUFDaEYsZ0ZBQWdGO1FBQ2hGLHFEQUFxRDtRQUNyRCxNQUFNLElBQUksR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDN0MsTUFBTSxXQUFXLEdBQUcsa0JBQWtCLENBQUM7WUFDckMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO1lBQ2xDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixJQUFJO1NBQ0wsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsNEVBQTRFLENBQUMsQ0FBQztZQUMxRixPQUFPO1FBQ1QsQ0FBQztRQUVELCtFQUErRTtRQUMvRSxNQUFNLFFBQVEsR0FBRyxZQUFZLEVBQUUsQ0FBQztRQUNoQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDeEMsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNoRCxHQUFHLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXZCLCtFQUErRTtRQUMvRSwyREFBMkQ7UUFDM0QsR0FBRyxDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxFQUFFO1lBQy9CLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTTtnQkFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzNDLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxDQUFDLElBQUksQ0FBQywyQkFBMkIsSUFBSSxLQUFLLFdBQVcsQ0FBQyxTQUFTLElBQUksV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDbEcsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYHR1bm5lbEludGVyY2VwdG9yKClgIC0gdGhlIHtAbGluayBJbnRlcmNlcHRvcn0gdGhhdCBmcm9udHMgYW4gYXBwIHdpdGggYSBwdWJsaWNcbiAqIHBvcnRyIHR1bm5lbCwgY29uc3VtaW5nIHRoZSB7QGxpbmsgSW50ZXJjZXB0b3JDb250ZXh0fSBgQGRieC10b29scy9hcHBraXRgJ3NcbiAqIGBjcmVhdGVBcHBgIGhhbmRzIGl0LlxuICpcbiAqIFRoaXMgaXMgdGhlIGluLXByb2Nlc3MgcmVwbGFjZW1lbnQgZm9yIHRoZSBvbGQgYGRieHQtdHVubmVsIC0tIDxjbWQ+
|
|
84
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJjZXB0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZXJjZXB0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdCRztBQUdILE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFFLGtCQUFrQixFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUU1RixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUM7QUFnQmhELHFGQUFxRjtBQUNyRixTQUFTLGlCQUFpQixDQUFDLElBQWE7SUFDdEMsT0FBTyxJQUFJLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLElBQUksSUFBSSxDQUFDLENBQUM7QUFDakUsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxVQUFvQyxFQUFFO0lBQ3RFLE9BQU8sQ0FBQyxHQUF1QixFQUFRLEVBQUU7UUFDdkMsNkVBQTZFO1FBQzdFLDhFQUE4RTtRQUM5RSw2REFBNkQ7UUFDN0QsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQzNCLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxLQUFLLEdBQUcsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1FBQ3pELENBQUM7UUFFRCxnRkFBZ0Y7UUFDaEYsZ0ZBQWdGO1FBQ2hGLHFEQUFxRDtRQUNyRCxNQUFNLElBQUksR0FBRyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDN0MsTUFBTSxXQUFXLEdBQUcsa0JBQWtCLENBQUM7WUFDckMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxZQUFZO1lBQ2xDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixJQUFJO1NBQ0wsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sQ0FBQyxJQUFJLENBQUMsNEVBQTRFLENBQUMsQ0FBQztZQUMxRixPQUFPO1FBQ1QsQ0FBQztRQUVELCtFQUErRTtRQUMvRSxNQUFNLFFBQVEsR0FBRyxZQUFZLEVBQUUsQ0FBQztRQUNoQyxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDeEMsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNoRCxHQUFHLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXZCLCtFQUErRTtRQUMvRSwyREFBMkQ7UUFDM0QsR0FBRyxDQUFDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxFQUFFO1lBQy9CLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTTtnQkFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzNDLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxDQUFDLElBQUksQ0FBQywyQkFBMkIsSUFBSSxLQUFLLFdBQVcsQ0FBQyxTQUFTLElBQUksV0FBVyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDbEcsQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYHR1bm5lbEludGVyY2VwdG9yKClgIC0gdGhlIHtAbGluayBJbnRlcmNlcHRvcn0gdGhhdCBmcm9udHMgYW4gYXBwIHdpdGggYSBwdWJsaWNcbiAqIHBvcnRyIHR1bm5lbCwgY29uc3VtaW5nIHRoZSB7QGxpbmsgSW50ZXJjZXB0b3JDb250ZXh0fSBgQGRieC10b29scy9hcHBraXRgJ3NcbiAqIGBjcmVhdGVBcHBgIGhhbmRzIGl0LlxuICpcbiAqIFRoaXMgaXMgdGhlIGluLXByb2Nlc3MgcmVwbGFjZW1lbnQgZm9yIHRoZSBvbGQgYGRieHQtdHVubmVsIC0tIDxjbWQ+YCB3cmFwcGVyLlxuICogSW5zdGVhZCBvZiB0aGUgdHVubmVsIGJlaW5nIHRoZSBtYWluIHByb2Nlc3MgdGhhdCBzcGF3bnMgdGhlIGFwcCBhcyBhIGNoaWxkLCB0aGVcbiAqIEFQUCBpcyB0aGUgbWFpbiBwcm9jZXNzIGFuZCBoYW5kcyB0aGlzIGludGVyY2VwdG9yIGl0cyBjb250ZXh0LiBUaGUgaW50ZXJjZXB0b3I6XG4gKlxuICogICAxLiBhcHBsaWVzIHRoZSB3b3Jrc3BhY2UgaG9zdCB0aGUgY29udGV4dCBjb21wdXRlZCB0byBgcHJvY2Vzcy5lbnZgXG4gKiAgICAgIChgREFUQUJSSUNLU19IT1NUYCksIHNvIHBvcnRyIGFuZCBhbnkgbGF0ZXIgU0RLIGNhbGwgYWdyZWUgb24gdGhlIHdvcmtzcGFjZTtcbiAqICAgMi4gaW5zdGFsbHMgKyBsYXVuY2hlcyBwb3J0ciwgcG9pbnRlZCBhdCB0aGUgYXBwJ3MgUFVCTElDIHBvcnQ7XG4gKiAgIDMuIGBiaW5kUHJvY2Vzc2BlcyBwb3J0ciBzbyB0aGUgYXBwIGFuZCB0aGUgdHVubmVsIGxpdmUgYW5kIGRpZSBhcyBvbmUgLVxuICogICAgICBzaWduYWxzIHBhc3MgdGhyb3VnaCBhbmQgZWl0aGVyIGRlYXRoIHRlYXJzIHRoZSBwYWlyIGRvd24gKHRoZVxuICogICAgICBjb25jdXJyZW50bHktc3R5bGUgc3VwZXJ2aXNpb24gdGhhdCB1c2VkIHRvIGJlIGBzdXBlcnZpc2VFeGl0YCk7XG4gKiAgIDQuIHJlZ2lzdGVycyBhbiBBcHBLaXQgYHNodXRkb3duYCBsaWZlY3ljbGUgaGFuZGxlciBzbyBhbiBvcmRlcmx5IGFwcCBzaHV0ZG93blxuICogICAgICBhbHNvIHN0b3BzIHBvcnRyLlxuICpcbiAqIFRoZSBlbWFpbC1PVFAgR0FURSBpcyBhIHNlcGFyYXRlIGNvbmNlcm46IGl0IGlzIHRoZSBgYXV0aEdhdGVgIEFwcEtpdCBwbHVnaW4sXG4gKiB3aGljaCByZWdpc3RlcnMgdGhlIGxvZ2luIHJvdXRlcyArIGEgZ2F0aW5nIG1pZGRsZXdhcmUgb24gdGhlIGFwcCdzIG93biBzZXJ2ZXIuXG4gKiBSZWdpc3RlciBpdCBpbiB0aGUgYXBwJ3MgYHBsdWdpbnNgIGZvciBnYXRlZCB0cmFmZmljLiBUaGlzIGludGVyY2VwdG9yIGlzIG9ubHlcbiAqIHRoZSBwb3J0ciBoYWxmIC0gXCJ1cGRhdGUgdGhlIGhvc3QsIGJpbmQgcG9ydHJcIiAtIHRoZSBzbWFsbGVzdCB1c2VmdWwgdW5pdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBJbnRlcmNlcHRvciwgSW50ZXJjZXB0b3JDb250ZXh0IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgaW5zdGFsbFBvcnRyLCByZXNvbHZlUG9ydHJDb25maWcsIHN0YXJ0UG9ydHIsIHdyaXRlUG9ydHJDb25maWcgfSBmcm9tIFwiLi9wb3J0ci50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwidHVubmVsOmludGVyY2VwdG9yXCIpO1xuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIHR1bm5lbEludGVyY2VwdG9yfSAoZWFjaCBhbHNvIHJlc29sdmFibGUgZnJvbSBlbnYpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUdW5uZWxJbnRlcmNlcHRvck9wdGlvbnMge1xuICAvKiogcG9ydHIgYDxzdWJkb21haW4+LjxzZXJ2ZXI+YCB0byBzZXJ2ZSBvbi4gRW52IGBUVU5ORUxfUFVCTElDX0RPTUFJTmAuICovXG4gIHB1YmxpY0RvbWFpbj86IHN0cmluZztcbiAgLyoqIHBvcnRyIHN1YmRvbWFpbiAoZWxzZSBkZXJpdmVkIGZyb20ge0BsaW5rIHB1YmxpY0RvbWFpbn0pLiAqL1xuICBzdWJkb21haW4/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgUFVCTElDIHBvcnQgcG9ydHIgZm9yd2FyZHMgdG8gLSB0aGUgcG9ydCB0aGUgYXBwIGl0c2VsZiBsaXN0ZW5zIG9uLlxuICAgKiBEZWZhdWx0cyB0byB0aGUgRGF0YWJyaWNrcyBBcHBzIHJ1bnRpbWUgY29udHJhY3QgYERBVEFCUklDS1NfQVBQX1BPUlRgXG4gICAqICh0aGVuIGA4MDAwYCksIHdoaWNoIGlzIHRoZSBwb3J0IHRoZSBwbGF0Zm9ybSByb3V0ZXMgdG8uXG4gICAqL1xuICBwb3J0PzogbnVtYmVyO1xufVxuXG4vKiogUmVzb2x2ZSB0aGUgcHVibGljIHBvcnQgcG9ydHIgc2hvdWxkIHRhcmdldDogZXhwbGljaXQsIGVsc2UgdGhlIEFwcHMgY29udHJhY3QuICovXG5mdW5jdGlvbiByZXNvbHZlUHVibGljUG9ydChwb3J0PzogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIHBvcnQgPz8gTnVtYmVyKHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQVBQX1BPUlQgPz8gODAwMCk7XG59XG5cbi8qKlxuICogQnVpbGQgdGhlIHR1bm5lbCB7QGxpbmsgSW50ZXJjZXB0b3J9LiBQYXNzIGl0IHRvIGBjcmVhdGVBcHAoeyBpbnRlcmNlcHRvciB9KWAuXG4gKlxuICogQSBuby1vcCAobG9ncyBhbmQgcmV0dXJucykgd2hlbiBubyBwb3J0ciB0dW5uZWwgaXMgY29uZmlndXJlZCAtIG5vIGBQT1JUUl9UT0tFTmBcbiAqIG9yIG5vIHJlc29sdmFibGUgYDxzdWJkb21haW4+LjxzZXJ2ZXI+YCAtIHNvIGFuIGFwcCBjYW4gcmVnaXN0ZXIgaXRcbiAqIHVuY29uZGl0aW9uYWxseSBhbmQgb25seSBhY3R1YWxseSB0dW5uZWxzIHdoZXJlIHRoZSBkZXBsb3ltZW50IHdpcmVkIHBvcnRyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBpbXBvcnQgeyBjcmVhdGVBcHAgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbiAqIGltcG9ydCB7IHR1bm5lbEludGVyY2VwdG9yIH0gZnJvbSBcIkBkYngtdG9vbHMvdHVubmVsXCI7XG4gKlxuICogYXdhaXQgY3JlYXRlQXBwKHtcbiAqICAgcGx1Z2luczogW3NlcnZlcih7IGhvc3QsIHN0YXRpY1BhdGggfSldLFxuICogICBpbnRlcmNlcHRvcjogdHVubmVsSW50ZXJjZXB0b3IoKSxcbiAqIH0pO1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHVubmVsSW50ZXJjZXB0b3Iob3B0aW9uczogVHVubmVsSW50ZXJjZXB0b3JPcHRpb25zID0ge30pOiBJbnRlcmNlcHRvciB7XG4gIHJldHVybiAoY3R4OiBJbnRlcmNlcHRvckNvbnRleHQpOiB2b2lkID0+IHtcbiAgICAvLyAxLiBBcHBseSB0aGUgY29tcHV0ZWQgd29ya3NwYWNlIGhvc3Qgc28gcG9ydHIgKyB0aGUgU0RLIGFncmVlLiBUaGUgY29udGV4dFxuICAgIC8vICAgIGFscmVhZHkgcmVzb2x2ZWQgaXQgKGZyb20gdGhlIGVudiAvIGF1dG8tY29uZmlnKTsgc2V0IGl0IG9ubHkgd2hlbiBpdCBpc1xuICAgIC8vICAgIGtub3duIGFuZCBub3QgYWxyZWFkeSBwcmVzZW50LCBzbyBhbiBleHBsaWNpdCBlbnYgd2lucy5cbiAgICBpZiAoY3R4LmVudi5kYXRhYnJpY2tzSG9zdCkge1xuICAgICAgcHJvY2Vzcy5lbnYuREFUQUJSSUNLU19IT1NUID8/PSBjdHguZW52LmRhdGFicmlja3NIb3N0O1xuICAgIH1cblxuICAgIC8vIDIuIFJlc29sdmUgcG9ydHIgd2lyaW5nLiBObyB0b2tlbiAvIGRvbWFpbiAtPiBubyB0dW5uZWw7IGxlYXZlIHRoZSBhcHAgYWxvbmUuXG4gICAgLy8gICAgYHJlc29sdmVQb3J0ckNvbmZpZ2AgYWxyZWFkeSBmYWxscyBiYWNrIHRvIFRVTk5FTF9QVUJMSUNfRE9NQUlOIGl0c2VsZiwgc29cbiAgICAvLyAgICB0aGUgZXhwbGljaXQgb3B0aW9uIGlzIHBhc3NlZCBzdHJhaWdodCB0aHJvdWdoLlxuICAgIGNvbnN0IHBvcnQgPSByZXNvbHZlUHVibGljUG9ydChvcHRpb25zLnBvcnQpO1xuICAgIGNvbnN0IHBvcnRyQ29uZmlnID0gcmVzb2x2ZVBvcnRyQ29uZmlnKHtcbiAgICAgIHB1YmxpY0RvbWFpbjogb3B0aW9ucy5wdWJsaWNEb21haW4sXG4gICAgICBzdWJkb21haW46IG9wdGlvbnMuc3ViZG9tYWluLFxuICAgICAgcG9ydCxcbiAgICB9KTtcbiAgICBpZiAoIXBvcnRyQ29uZmlnKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcIm5vIFBPUlRSX1RPS0VOL1RVTk5FTF9QVUJMSUNfRE9NQUlOIC0gdGhlIGFwcCBydW5zIHdpdGhvdXQgYSBwdWJsaWMgdHVubmVsXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIDMuIEluc3RhbGwgKyBsYXVuY2ggcG9ydHIsIHRoZW4gYmluZCBpdDogdGhlIGFwcCBhbmQgcG9ydHIgbm93IHNoYXJlIGEgZmF0ZS5cbiAgICBjb25zdCBwb3J0ckVudiA9IGluc3RhbGxQb3J0cigpO1xuICAgIHdyaXRlUG9ydHJDb25maWcocG9ydHJDb25maWcsIHBvcnRyRW52KTtcbiAgICBjb25zdCBwb3J0ciA9IHN0YXJ0UG9ydHIocG9ydHJDb25maWcsIHBvcnRyRW52KTtcbiAgICBjdHguYmluZFByb2Nlc3MocG9ydHIpO1xuXG4gICAgLy8gNC4gQW4gb3JkZXJseSBBcHBLaXQgc2h1dGRvd24gYWxzbyBzdG9wcyBwb3J0ciAoYmVsdC1hbmQtc3VzcGVuZGVycyB3aXRoIHRoZVxuICAgIC8vICAgIHNpZ25hbCBwYXNzLXRocm91Z2ggYGJpbmRQcm9jZXNzYCBhbHJlYWR5IGluc3RhbGxlZCkuXG4gICAgY3R4Lm9uTGlmZWN5Y2xlKFwic2h1dGRvd25cIiwgKCkgPT4ge1xuICAgICAgaWYgKCFwb3J0ci5raWxsZWQpIHBvcnRyLmtpbGwoXCJTSUdURVJNXCIpO1xuICAgIH0pO1xuXG4gICAgbG9nZ2VyLmluZm8oYHR1bm5lbCBib3VuZDogcG9ydHIgLT4gOiR7cG9ydH0gKCR7cG9ydHJDb25maWcuc3ViZG9tYWlufS4ke3BvcnRyQ29uZmlnLnNlcnZlcn0pYCk7XG4gIH07XG59XG4iXX0=
|
package/lib/src/plugin.d.ts
CHANGED
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { Plugin, type BasePluginConfig } from "@databricks/appkit";
|
|
19
19
|
import type { AuthStatus } from "@dbx-tools/shared-email";
|
|
20
|
+
import type { RequestHandler } from "express";
|
|
21
|
+
import { type GateOptions } from "./gate.ts";
|
|
22
|
+
interface GateMountContext {
|
|
23
|
+
addRoute(method: string, path: string, handler: RequestHandler): void;
|
|
24
|
+
addMiddleware(path: string, handler: RequestHandler): void;
|
|
25
|
+
getPlugins(): ReadonlyMap<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
export declare function mountGateOnContext(context: GateMountContext, options: GateOptions): void;
|
|
20
28
|
/** Options for the {@link authGate} plugin (all resolvable from env - see below). */
|
|
21
29
|
export interface AuthGateConfig extends BasePluginConfig {
|
|
22
30
|
/** Allow-list patterns (domain / glob / `/regex/`). Empty = allow nobody. Env TUNNEL_AUTH_ALLOW. */
|
|
@@ -72,8 +80,31 @@ export interface AuthGateConfig extends BasePluginConfig {
|
|
|
72
80
|
* means no cutoff.
|
|
73
81
|
*/
|
|
74
82
|
sessionCutoff?: string | number | Date;
|
|
75
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* Deliver a code to an address. Defaults to sending through the host app's
|
|
85
|
+
* shared `@dbx-tools/email` transport (see `./send-code`); override to wire a
|
|
86
|
+
* different delivery path.
|
|
87
|
+
*/
|
|
76
88
|
sendCode?: (email: string, code: string, opts: SendCodeOptions) => Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* The public `<subdomain>.<server>` that identifies portr traffic by its `Host`
|
|
91
|
+
* header. Only requests whose `Host` matches this are gated; everything else
|
|
92
|
+
* (the platform front door, other local callers) passes through. Env
|
|
93
|
+
* `TUNNEL_PUBLIC_DOMAIN`. When absent, the gate is inert (nothing is tunnel
|
|
94
|
+
* traffic).
|
|
95
|
+
*/
|
|
96
|
+
publicDomain?: string;
|
|
97
|
+
/**
|
|
98
|
+
* Extra `x-` request headers tunnel traffic may forward (literal / glob /
|
|
99
|
+
* `/regex/`), unioned with the built-in allow-list. Env `TUNNEL_FORWARD_HEADERS`.
|
|
100
|
+
*/
|
|
101
|
+
forwardHeaders?: string | string[];
|
|
102
|
+
/**
|
|
103
|
+
* Run OPEN with no gate (env `TUNNEL_INSECURE=true`). The login routes and gate
|
|
104
|
+
* middleware are not mounted, and the SMTP fail-fast is skipped. Use only when
|
|
105
|
+
* the tunnel is deliberately public.
|
|
106
|
+
*/
|
|
107
|
+
insecure?: boolean;
|
|
77
108
|
}
|
|
78
109
|
/** Branding/messaging passed to {@link AuthGateConfig.sendCode}. */
|
|
79
110
|
export interface SendCodeOptions {
|
|
@@ -99,10 +130,16 @@ export interface ResolvedAuthGateConfig {
|
|
|
99
130
|
maxAttempts: number;
|
|
100
131
|
/** Force-clear cutoff in epoch ms; `0` when unset. */
|
|
101
132
|
sessionCutoffMs: number;
|
|
133
|
+
/** Public domain that identifies portr traffic by `Host`; `undefined` = inert. */
|
|
134
|
+
publicDomain?: string;
|
|
135
|
+
/** Extra `x-` headers tunnel traffic may forward (unioned with the defaults). */
|
|
136
|
+
forwardHeaders: string[];
|
|
137
|
+
/** Run OPEN with no gate. */
|
|
138
|
+
insecure: boolean;
|
|
102
139
|
}
|
|
103
140
|
/** Merge {@link AuthGateConfig} over env over defaults into a resolved config. */
|
|
104
141
|
export declare function resolveAuthGateConfig(config: AuthGateConfig): ResolvedAuthGateConfig;
|
|
105
|
-
/** The handlers the
|
|
142
|
+
/** The handlers the gate middleware calls in-process (returned by {@link AuthGatePlugin.exports}). */
|
|
106
143
|
export interface AuthGateApi {
|
|
107
144
|
/** Handle a code request. Always resolves `{ ok: true }` (anti-enumeration). */
|
|
108
145
|
request(email: string, ip: string): Promise<{
|
|
@@ -122,7 +159,13 @@ export interface AuthGateApi {
|
|
|
122
159
|
/** The gate status payload (`enabled` is always true when this plugin runs). */
|
|
123
160
|
status(token: string | undefined): Promise<AuthStatus>;
|
|
124
161
|
}
|
|
125
|
-
/**
|
|
162
|
+
/**
|
|
163
|
+
* AppKit plugin owning the email-OTP gate. On `setup()` it registers the login
|
|
164
|
+
* routes (`/api/email/auth/*`) and a gating middleware on the app's OWN Express
|
|
165
|
+
* server via `this.context`, so a public portr caller must prove an email before
|
|
166
|
+
* reaching the app's `/api/*` - see `./gate`. Front-door (platform) traffic and
|
|
167
|
+
* other local callers pass through untouched (the gate keys on the `Host` header).
|
|
168
|
+
*/
|
|
126
169
|
export declare class AuthGatePlugin extends Plugin<AuthGateConfig> {
|
|
127
170
|
static manifest: {
|
|
128
171
|
name: "authGate";
|
|
@@ -139,9 +182,20 @@ export declare class AuthGatePlugin extends Plugin<AuthGateConfig> {
|
|
|
139
182
|
private readonly requestLimiter;
|
|
140
183
|
private readonly verifyLimiter;
|
|
141
184
|
setup(): Promise<void>;
|
|
185
|
+
/**
|
|
186
|
+
* Register the login routes (`/api/email/auth/*`) and the gating middleware on
|
|
187
|
+
* the app's OWN Express server. At `setup:complete`, the deferred server plugin
|
|
188
|
+
* has constructed its Express app but has not injected plugin routes or static
|
|
189
|
+
* handling, so direct registration puts the gate first. The context's buffered
|
|
190
|
+
* route API remains a fallback for compatible non-standard server plugins.
|
|
191
|
+
*/
|
|
192
|
+
private mountGateRoutes;
|
|
193
|
+
/** The code sender: the configured `sendCode`, else the shared-transport default. */
|
|
194
|
+
private get sendCode();
|
|
142
195
|
exports(): AuthGateApi;
|
|
143
196
|
private handleRequest;
|
|
144
197
|
private handleVerify;
|
|
145
198
|
}
|
|
146
199
|
/** Factory: `authGate({ allow, subject, ... })` for an AppKit `plugins` array. */
|
|
147
200
|
export declare const authGate: import("@databricks/appkit").ToPlugin<typeof AuthGatePlugin, AuthGateConfig, "authGate">;
|
|
201
|
+
export {};
|