@qodalis/cli-server-node 1.0.0-beta.5 → 1.0.0-beta.6
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 +175 -19
- package/dist/src/auth/cli-server-auth-gate.d.ts +31 -0
- package/dist/src/auth/cli-server-auth-gate.d.ts.map +1 -0
- package/dist/src/auth/cli-server-auth-gate.js +118 -0
- package/dist/src/auth/cli-server-auth-gate.js.map +1 -0
- package/dist/src/auth/cli-server-auth.d.ts +147 -0
- package/dist/src/auth/cli-server-auth.d.ts.map +1 -0
- package/dist/src/auth/cli-server-auth.js +143 -0
- package/dist/src/auth/cli-server-auth.js.map +1 -0
- package/dist/src/auth/index.d.ts +4 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +19 -0
- package/dist/src/auth/index.js.map +1 -0
- package/dist/src/auth/ws-upgrade-auth.d.ts +30 -0
- package/dist/src/auth/ws-upgrade-auth.d.ts.map +1 -0
- package/dist/src/auth/ws-upgrade-auth.js +49 -0
- package/dist/src/auth/ws-upgrade-auth.js.map +1 -0
- package/dist/src/controllers/cli-controller.d.ts +2 -1
- package/dist/src/controllers/cli-controller.d.ts.map +1 -1
- package/dist/src/controllers/cli-controller.js +7 -2
- package/dist/src/controllers/cli-controller.js.map +1 -1
- package/dist/src/controllers/cli-version-controller.d.ts +12 -1
- package/dist/src/controllers/cli-version-controller.d.ts.map +1 -1
- package/dist/src/controllers/cli-version-controller.js +7 -2
- package/dist/src/controllers/cli-version-controller.js.map +1 -1
- package/dist/src/create-cli-server.d.ts +45 -1
- package/dist/src/create-cli-server.d.ts.map +1 -1
- package/dist/src/create-cli-server.js +71 -10
- package/dist/src/create-cli-server.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +15 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/server.js +12 -0
- package/dist/src/server.js.map +1 -1
- package/dist/src/services/cli-event-socket-manager.d.ts +37 -1
- package/dist/src/services/cli-event-socket-manager.d.ts.map +1 -1
- package/dist/src/services/cli-event-socket-manager.js +126 -28
- package/dist/src/services/cli-event-socket-manager.js.map +1 -1
- package/dist/src/services/cli-log-socket-manager.d.ts +15 -1
- package/dist/src/services/cli-log-socket-manager.d.ts.map +1 -1
- package/dist/src/services/cli-log-socket-manager.js +53 -13
- package/dist/src/services/cli-log-socket-manager.js.map +1 -1
- package/dist/src/services/cli-shell-options.d.ts +107 -0
- package/dist/src/services/cli-shell-options.d.ts.map +1 -0
- package/dist/src/services/cli-shell-options.js +139 -0
- package/dist/src/services/cli-shell-options.js.map +1 -0
- package/dist/src/services/cli-shell-session-manager.d.ts +83 -10
- package/dist/src/services/cli-shell-session-manager.d.ts.map +1 -1
- package/dist/src/services/cli-shell-session-manager.js +474 -85
- package/dist/src/services/cli-shell-session-manager.js.map +1 -1
- package/dist/src/services/index.d.ts +2 -1
- package/dist/src/services/index.d.ts.map +1 -1
- package/dist/src/services/index.js +5 -1
- package/dist/src/services/index.js.map +1 -1
- package/dist/src/services/process-tree.d.ts +38 -0
- package/dist/src/services/process-tree.d.ts.map +1 -0
- package/dist/src/services/process-tree.js +249 -0
- package/dist/src/services/process-tree.js.map +1 -0
- package/dist/src/services/session-bound-sockets.d.ts +45 -0
- package/dist/src/services/session-bound-sockets.d.ts.map +1 -0
- package/dist/src/services/session-bound-sockets.js +129 -0
- package/dist/src/services/session-bound-sockets.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliServerPermissions = void 0;
|
|
4
|
+
exports.isOriginAllowed = isOriginAllowed;
|
|
5
|
+
exports.trustedProxyHops = trustedProxyHops;
|
|
6
|
+
exports.clientAddress = clientAddress;
|
|
7
|
+
exports.requestOrigin = requestOrigin;
|
|
8
|
+
exports.isSameOrigin = isSameOrigin;
|
|
9
|
+
/** Server permissions enforced when the users plugin protects the server. */
|
|
10
|
+
exports.CliServerPermissions = {
|
|
11
|
+
CommandsExecute: 'commands:execute',
|
|
12
|
+
FilesRead: 'files:read',
|
|
13
|
+
FilesWrite: 'files:write',
|
|
14
|
+
DataQuery: 'data:query',
|
|
15
|
+
JobsRead: 'jobs:read',
|
|
16
|
+
JobsManage: 'jobs:manage',
|
|
17
|
+
LogsRead: 'logs:read',
|
|
18
|
+
ShellExecute: 'shell:execute',
|
|
19
|
+
AdminAccess: 'admin:access',
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Exact origin match. An entry ending in `:*` matches any port of that
|
|
23
|
+
* scheme+host (e.g. `http://127.0.0.1:*`).
|
|
24
|
+
*/
|
|
25
|
+
function isOriginAllowed(origin, allowed) {
|
|
26
|
+
if (!origin || !allowed || allowed.length === 0)
|
|
27
|
+
return false;
|
|
28
|
+
const o = origin.toLowerCase().replace(/\/+$/, '');
|
|
29
|
+
return allowed.some((entry) => {
|
|
30
|
+
const e = entry.toLowerCase().replace(/\/+$/, '');
|
|
31
|
+
if (e.endsWith(':*')) {
|
|
32
|
+
const base = e.slice(0, -2);
|
|
33
|
+
return o === base || (o.startsWith(base + ':') && /^\d+$/.test(o.slice(base.length + 1)));
|
|
34
|
+
}
|
|
35
|
+
return o === e;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Number of trusted reverse-proxy hops for a `trustProxy` setting:
|
|
40
|
+
* `false`/`0`/absent → 0 (untrusted), `true` → 1, a number n → n (values
|
|
41
|
+
* below 1 other than 0 count as 1).
|
|
42
|
+
*/
|
|
43
|
+
function trustedProxyHops(trustProxy) {
|
|
44
|
+
if (typeof trustProxy === 'number') {
|
|
45
|
+
if (trustProxy === 0)
|
|
46
|
+
return 0;
|
|
47
|
+
return trustProxy >= 1 ? Math.floor(trustProxy) : 1;
|
|
48
|
+
}
|
|
49
|
+
return trustProxy ? 1 : 0;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The `X-Forwarded-*` entry behind `hops` trusted proxies (for
|
|
53
|
+
* `X-Forwarded-For`: the client): index `len - hops` (with one hop, the
|
|
54
|
+
* rightmost entry, appended by the trusted proxy; leftmost entries are
|
|
55
|
+
* client-controlled). The leftmost entry when the list is shorter than `hops`;
|
|
56
|
+
* undefined when the header is absent or the selected entry is empty.
|
|
57
|
+
*/
|
|
58
|
+
function forwardedEntry(header, hops) {
|
|
59
|
+
if (hops <= 0 || header === undefined)
|
|
60
|
+
return undefined;
|
|
61
|
+
const entries = (Array.isArray(header) ? header.join(',') : header).split(',').map((e) => e.trim());
|
|
62
|
+
return entries[Math.max(0, entries.length - hops)] || undefined;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The client address: the socket address, or with `trustProxy` (a hop count,
|
|
66
|
+
* `true` = 1) the `X-Forwarded-For` entry at index `len - hops`.
|
|
67
|
+
*/
|
|
68
|
+
function clientAddress(req, trustProxy) {
|
|
69
|
+
return forwardedEntry(req.headers['x-forwarded-for'], trustedProxyHops(trustProxy)) ?? req.socket?.remoteAddress ?? 'unknown';
|
|
70
|
+
}
|
|
71
|
+
const DEFAULT_PORTS = { http: '80', https: '443' };
|
|
72
|
+
function firstHeader(value) {
|
|
73
|
+
const raw = Array.isArray(value) ? value[0] : value;
|
|
74
|
+
const first = raw?.split(',')[0]?.trim();
|
|
75
|
+
return first || undefined;
|
|
76
|
+
}
|
|
77
|
+
/** `scheme://host:port`, lower-cased, explicit port (http:80, https:443); `ws`/`wss` map to `http`/`https`. */
|
|
78
|
+
function normalizeOrigin(scheme, hostPort) {
|
|
79
|
+
let s = scheme.toLowerCase().replace(/:$/, '');
|
|
80
|
+
if (s === 'ws')
|
|
81
|
+
s = 'http';
|
|
82
|
+
if (s === 'wss')
|
|
83
|
+
s = 'https';
|
|
84
|
+
if (!DEFAULT_PORTS[s])
|
|
85
|
+
return undefined;
|
|
86
|
+
try {
|
|
87
|
+
const url = new URL(`${s}://${hostPort}`);
|
|
88
|
+
if (url.username || url.password || (url.pathname && url.pathname !== '/') || url.search || url.hash)
|
|
89
|
+
return undefined;
|
|
90
|
+
return `${s}://${url.hostname.toLowerCase()}:${url.port || DEFAULT_PORTS[s]}`;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Trusted proxy hops for the forwarded headers: from `trustProxy`, or — when it
|
|
98
|
+
* is omitted and the Express app's `trust proxy` setting trusts the socket — that
|
|
99
|
+
* setting's hop count (a number), otherwise 1.
|
|
100
|
+
*/
|
|
101
|
+
function proxyHops(req, trustProxy) {
|
|
102
|
+
if (trustProxy !== undefined)
|
|
103
|
+
return trustedProxyHops(trustProxy);
|
|
104
|
+
const fn = req.app?.get?.('trust proxy fn');
|
|
105
|
+
if (typeof fn !== 'function' || !fn(req.socket?.remoteAddress, 0))
|
|
106
|
+
return 0;
|
|
107
|
+
const setting = req.app?.get?.('trust proxy');
|
|
108
|
+
return typeof setting === 'number' ? trustedProxyHops(setting) || 1 : 1;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The request's own origin (`scheme://host:port`, normalized): the scheme from
|
|
112
|
+
* the socket (TLS or not) and the `Host` header. Behind a trusted proxy
|
|
113
|
+
* (`trustProxy`, or the Express app's `trust proxy` setting when omitted)
|
|
114
|
+
* `X-Forwarded-Proto` / `X-Forwarded-Host` win, read like `X-Forwarded-For`:
|
|
115
|
+
* the entry at index `len - hops` (the rightmost with one hop; the leftmost
|
|
116
|
+
* when the list is shorter; an empty entry is ignored).
|
|
117
|
+
*/
|
|
118
|
+
function requestOrigin(req, trustProxy) {
|
|
119
|
+
const hops = proxyHops(req, trustProxy);
|
|
120
|
+
const scheme = forwardedEntry(req.headers['x-forwarded-proto'], hops) || (req.socket?.encrypted ? 'https' : 'http');
|
|
121
|
+
const host = forwardedEntry(req.headers['x-forwarded-host'], hops) || firstHeader(req.headers['host']);
|
|
122
|
+
return host ? normalizeOrigin(scheme, host) : undefined;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* True when `origin` is the request's own origin (e.g. the bundled admin
|
|
126
|
+
* dashboard served by this server). Same-origin requests are not cross-site
|
|
127
|
+
* and always pass Origin/CSRF checks. Case-insensitive; default ports normalized.
|
|
128
|
+
*/
|
|
129
|
+
function isSameOrigin(origin, req, trustProxy) {
|
|
130
|
+
if (!origin || origin === 'null')
|
|
131
|
+
return false;
|
|
132
|
+
let o;
|
|
133
|
+
try {
|
|
134
|
+
const url = new URL(origin);
|
|
135
|
+
o = normalizeOrigin(url.protocol, url.host);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const own = requestOrigin(req, trustProxy);
|
|
141
|
+
return !!o && !!own && o === own;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=cli-server-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-server-auth.js","sourceRoot":"","sources":["../../../src/auth/cli-server-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { CliServerAuthContext, CliServerAuthError, CliServerAuditEntry, CliServerSessionEvent, ICliServerAuth, CliServerPermissions, isOriginAllowed, isSameOrigin, requestOrigin, clientAddress, trustedProxyHops, } from './cli-server-auth';
|
|
2
|
+
export { createServerAuthGate, ServerAuthGateOptions, requiredServerPermissions, processorPermissions, normalizePath, } from './cli-server-auth-gate';
|
|
3
|
+
export { authorizeWsUpgrade, rejectUpgrade, WsUpgradeAuthOptions, WsUpgradeAuthResult } from './ws-upgrade-auth';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,aAAa,EACb,gBAAgB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,aAAa,GAChB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rejectUpgrade = exports.authorizeWsUpgrade = exports.normalizePath = exports.processorPermissions = exports.requiredServerPermissions = exports.createServerAuthGate = exports.trustedProxyHops = exports.clientAddress = exports.requestOrigin = exports.isSameOrigin = exports.isOriginAllowed = exports.CliServerPermissions = void 0;
|
|
4
|
+
var cli_server_auth_1 = require("./cli-server-auth");
|
|
5
|
+
Object.defineProperty(exports, "CliServerPermissions", { enumerable: true, get: function () { return cli_server_auth_1.CliServerPermissions; } });
|
|
6
|
+
Object.defineProperty(exports, "isOriginAllowed", { enumerable: true, get: function () { return cli_server_auth_1.isOriginAllowed; } });
|
|
7
|
+
Object.defineProperty(exports, "isSameOrigin", { enumerable: true, get: function () { return cli_server_auth_1.isSameOrigin; } });
|
|
8
|
+
Object.defineProperty(exports, "requestOrigin", { enumerable: true, get: function () { return cli_server_auth_1.requestOrigin; } });
|
|
9
|
+
Object.defineProperty(exports, "clientAddress", { enumerable: true, get: function () { return cli_server_auth_1.clientAddress; } });
|
|
10
|
+
Object.defineProperty(exports, "trustedProxyHops", { enumerable: true, get: function () { return cli_server_auth_1.trustedProxyHops; } });
|
|
11
|
+
var cli_server_auth_gate_1 = require("./cli-server-auth-gate");
|
|
12
|
+
Object.defineProperty(exports, "createServerAuthGate", { enumerable: true, get: function () { return cli_server_auth_gate_1.createServerAuthGate; } });
|
|
13
|
+
Object.defineProperty(exports, "requiredServerPermissions", { enumerable: true, get: function () { return cli_server_auth_gate_1.requiredServerPermissions; } });
|
|
14
|
+
Object.defineProperty(exports, "processorPermissions", { enumerable: true, get: function () { return cli_server_auth_gate_1.processorPermissions; } });
|
|
15
|
+
Object.defineProperty(exports, "normalizePath", { enumerable: true, get: function () { return cli_server_auth_gate_1.normalizePath; } });
|
|
16
|
+
var ws_upgrade_auth_1 = require("./ws-upgrade-auth");
|
|
17
|
+
Object.defineProperty(exports, "authorizeWsUpgrade", { enumerable: true, get: function () { return ws_upgrade_auth_1.authorizeWsUpgrade; } });
|
|
18
|
+
Object.defineProperty(exports, "rejectUpgrade", { enumerable: true, get: function () { return ws_upgrade_auth_1.rejectUpgrade; } });
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/index.ts"],"names":[],"mappings":";;;AAAA,qDAY2B;AANvB,uHAAA,oBAAoB,OAAA;AACpB,kHAAA,eAAe,OAAA;AACf,+GAAA,YAAY,OAAA;AACZ,gHAAA,aAAa,OAAA;AACb,gHAAA,aAAa,OAAA;AACb,mHAAA,gBAAgB,OAAA;AAEpB,+DAMgC;AAL5B,4HAAA,oBAAoB,OAAA;AAEpB,iIAAA,yBAAyB,OAAA;AACzB,4HAAA,oBAAoB,OAAA;AACpB,qHAAA,aAAa,OAAA;AAEjB,qDAAiH;AAAxG,qHAAA,kBAAkB,OAAA;AAAE,gHAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'http';
|
|
2
|
+
import type { Duplex } from 'stream';
|
|
3
|
+
import { CliServerAuthContext, ICliServerAuth } from './cli-server-auth';
|
|
4
|
+
export interface WsUpgradeAuthOptions {
|
|
5
|
+
auth?: ICliServerAuth;
|
|
6
|
+
allowedOrigins?: string[];
|
|
7
|
+
/** Honour `X-Forwarded-Proto`/`X-Forwarded-Host` when deciding whether the Origin is the server's own. */
|
|
8
|
+
trustProxy?: boolean | number;
|
|
9
|
+
/** Permission required on top of authentication (protected mode only). */
|
|
10
|
+
permission?: string;
|
|
11
|
+
}
|
|
12
|
+
export type WsUpgradeAuthResult = {
|
|
13
|
+
ok: true;
|
|
14
|
+
ctx?: CliServerAuthContext;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
status: 401 | 403;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Authorizes a WebSocket upgrade:
|
|
21
|
+
* - when `allowedOrigins` is set, a present `Origin` header must be allowed or
|
|
22
|
+
* be the server's own origin (same-origin, e.g. the bundled dashboard) (403);
|
|
23
|
+
* - with a protecting auth provider, a valid single-use `?ticket=` is required
|
|
24
|
+
* (401) and the optional permission is checked (403);
|
|
25
|
+
* - otherwise a ticket, when present, only attaches an identity.
|
|
26
|
+
*/
|
|
27
|
+
export declare function authorizeWsUpgrade(request: IncomingMessage, url: URL, options: WsUpgradeAuthOptions): Promise<WsUpgradeAuthResult>;
|
|
28
|
+
/** Rejects an upgrade with a bare HTTP status response. */
|
|
29
|
+
export declare function rejectUpgrade(socket: Duplex, status: number): void;
|
|
30
|
+
//# sourceMappingURL=ws-upgrade-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-upgrade-auth.d.ts","sourceRoot":"","sources":["../../../src/auth/ws-upgrade-auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAiC,MAAM,mBAAmB,CAAC;AAExG,MAAM,WAAW,oBAAoB;IACjC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0GAA0G;IAC1G,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,oBAAoB,CAAA;CAAE,GACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAA;CAAE,CAAC;AAEvC;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACpC,OAAO,EAAE,eAAe,EACxB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,oBAAoB,GAC9B,OAAO,CAAC,mBAAmB,CAAC,CAyB9B;AAED,2DAA2D;AAC3D,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQlE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authorizeWsUpgrade = authorizeWsUpgrade;
|
|
4
|
+
exports.rejectUpgrade = rejectUpgrade;
|
|
5
|
+
const cli_server_auth_1 = require("./cli-server-auth");
|
|
6
|
+
/**
|
|
7
|
+
* Authorizes a WebSocket upgrade:
|
|
8
|
+
* - when `allowedOrigins` is set, a present `Origin` header must be allowed or
|
|
9
|
+
* be the server's own origin (same-origin, e.g. the bundled dashboard) (403);
|
|
10
|
+
* - with a protecting auth provider, a valid single-use `?ticket=` is required
|
|
11
|
+
* (401) and the optional permission is checked (403);
|
|
12
|
+
* - otherwise a ticket, when present, only attaches an identity.
|
|
13
|
+
*/
|
|
14
|
+
async function authorizeWsUpgrade(request, url, options) {
|
|
15
|
+
const origin = request.headers.origin;
|
|
16
|
+
if (options.allowedOrigins && options.allowedOrigins.length > 0 && origin !== undefined) {
|
|
17
|
+
if (!(0, cli_server_auth_1.isOriginAllowed)(origin, options.allowedOrigins) && !(0, cli_server_auth_1.isSameOrigin)(origin, request, options.trustProxy ?? false)) {
|
|
18
|
+
return { ok: false, status: 403 };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const auth = options.auth;
|
|
22
|
+
if (!auth) {
|
|
23
|
+
return { ok: true };
|
|
24
|
+
}
|
|
25
|
+
const ticket = url.searchParams.get('ticket');
|
|
26
|
+
const ctx = ticket ? await auth.consumeTicket(ticket).catch(() => undefined) : undefined;
|
|
27
|
+
if (!auth.protectServer) {
|
|
28
|
+
return { ok: true, ctx };
|
|
29
|
+
}
|
|
30
|
+
if (!ctx) {
|
|
31
|
+
return { ok: false, status: 401 };
|
|
32
|
+
}
|
|
33
|
+
if (options.permission && !auth.hasPermission(ctx, options.permission)) {
|
|
34
|
+
return { ok: false, status: 403 };
|
|
35
|
+
}
|
|
36
|
+
return { ok: true, ctx };
|
|
37
|
+
}
|
|
38
|
+
/** Rejects an upgrade with a bare HTTP status response. */
|
|
39
|
+
function rejectUpgrade(socket, status) {
|
|
40
|
+
const text = status === 401 ? 'Unauthorized' : status === 403 ? 'Forbidden' : status === 404 ? 'Not Found' : 'Error';
|
|
41
|
+
try {
|
|
42
|
+
socket.write(`HTTP/1.1 ${status} ${text}\r\nConnection: close\r\nContent-Length: 0\r\n\r\n`);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ignore
|
|
46
|
+
}
|
|
47
|
+
socket.destroy();
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=ws-upgrade-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-upgrade-auth.js","sourceRoot":"","sources":["../../../src/auth/ws-upgrade-auth.ts"],"names":[],"mappings":";;AAyBA,gDA6BC;AAGD,sCAQC;AA/DD,uDAAwG;AAexG;;;;;;;GAOG;AACI,KAAK,UAAU,kBAAkB,CACpC,OAAwB,EACxB,GAAQ,EACR,OAA6B;IAE7B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;IACtC,IAAI,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACtF,IAAI,CAAC,IAAA,iCAAe,EAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,IAAA,8BAAY,EAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE,CAAC;YAClH,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QACtC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACxB,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEzF,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACrE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AAC7B,CAAC;AAED,2DAA2D;AAC3D,SAAgB,aAAa,CAAC,MAAc,EAAE,MAAc;IACxD,MAAM,IAAI,GAAG,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;IACrH,IAAI,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,IAAI,IAAI,oDAAoD,CAAC,CAAC;IACjG,CAAC;IAAC,MAAM,CAAC;QACL,SAAS;IACb,CAAC;IACD,MAAM,CAAC,OAAO,EAAE,CAAC;AACrB,CAAC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { ICliCommandRegistry, ICliCommandExecutorService } from '../services';
|
|
3
|
+
import { CapabilitiesOptions } from './cli-version-controller';
|
|
3
4
|
/**
|
|
4
5
|
* Creates an Express router for the v1 CLI API with version, capabilities, commands, and execute endpoints.
|
|
5
6
|
* @param registry - Command registry to list available processors.
|
|
6
7
|
* @param executor - Service that dispatches commands to processors.
|
|
7
8
|
* @returns Configured Express router.
|
|
8
9
|
*/
|
|
9
|
-
export declare function createCliController(registry: ICliCommandRegistry, executor: ICliCommandExecutorService): Router;
|
|
10
|
+
export declare function createCliController(registry: ICliCommandRegistry, executor: ICliCommandExecutorService, options?: CapabilitiesOptions): Router;
|
|
10
11
|
//# sourceMappingURL=cli-controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-controller.d.ts","sourceRoot":"","sources":["../../../src/controllers/cli-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-controller.d.ts","sourceRoot":"","sources":["../../../src/controllers/cli-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAE,mBAAmB,EAA4B,MAAM,0BAA0B,CAAC;AAKzF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,QAAQ,EAAE,0BAA0B,EACpC,OAAO,CAAC,EAAE,mBAAmB,GAC9B,MAAM,CAmHR"}
|
|
@@ -38,6 +38,7 @@ const express_1 = require("express");
|
|
|
38
38
|
const os = __importStar(require("os"));
|
|
39
39
|
const abstractions_1 = require("../abstractions");
|
|
40
40
|
const logger_1 = require("../utils/logger");
|
|
41
|
+
const cli_version_controller_1 = require("./cli-version-controller");
|
|
41
42
|
const logger = (0, logger_1.createLogger)('CliController');
|
|
42
43
|
const SERVER_VERSION = '1.0.0';
|
|
43
44
|
/**
|
|
@@ -46,7 +47,7 @@ const SERVER_VERSION = '1.0.0';
|
|
|
46
47
|
* @param executor - Service that dispatches commands to processors.
|
|
47
48
|
* @returns Configured Express router.
|
|
48
49
|
*/
|
|
49
|
-
function createCliController(registry, executor) {
|
|
50
|
+
function createCliController(registry, executor, options) {
|
|
50
51
|
const router = (0, express_1.Router)();
|
|
51
52
|
router.get('/version', (_req, res) => {
|
|
52
53
|
res.json({ version: SERVER_VERSION });
|
|
@@ -62,7 +63,7 @@ function createCliController(registry, executor) {
|
|
|
62
63
|
? 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
|
|
63
64
|
: '/bin/bash';
|
|
64
65
|
res.json({
|
|
65
|
-
|
|
66
|
+
...(0, cli_version_controller_1.resolveShellCapabilities)(options),
|
|
66
67
|
os: detectedOs,
|
|
67
68
|
shellPath,
|
|
68
69
|
version: SERVER_VERSION,
|
|
@@ -75,6 +76,10 @@ function createCliController(registry, executor) {
|
|
|
75
76
|
});
|
|
76
77
|
router.post('/execute', async (req, res) => {
|
|
77
78
|
const command = req.body;
|
|
79
|
+
if (typeof command?.command !== 'string') {
|
|
80
|
+
res.status(400).json({ error: 'command is required' });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
78
83
|
logger.debug('Executing command: %s', command.command);
|
|
79
84
|
const abortController = new AbortController();
|
|
80
85
|
req.on('close', () => abortController.abort());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-controller.js","sourceRoot":"","sources":["../../../src/controllers/cli-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"cli-controller.js","sourceRoot":"","sources":["../../../src/controllers/cli-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
+
/** Shell part of `/capabilities`: `shellAuth` only when the shell is enabled. */
|
|
3
|
+
export interface ShellCapabilities {
|
|
4
|
+
shell: boolean;
|
|
5
|
+
shellAuth?: 'users' | 'token' | 'custom' | 'anonymous' | 'locked';
|
|
6
|
+
}
|
|
7
|
+
export interface CapabilitiesOptions {
|
|
8
|
+
/** Live shell state; when omitted `/capabilities` reports `shell: true` (legacy). */
|
|
9
|
+
shellCapabilities?: () => ShellCapabilities;
|
|
10
|
+
}
|
|
11
|
+
/** Resolves the shell fields of `/capabilities`. */
|
|
12
|
+
export declare function resolveShellCapabilities(options?: CapabilitiesOptions): ShellCapabilities;
|
|
2
13
|
/**
|
|
3
14
|
* Creates an Express router for API version discovery and server capabilities.
|
|
4
15
|
* @returns Router with `/versions` and `/capabilities` endpoints.
|
|
5
16
|
*/
|
|
6
|
-
export declare function createCliVersionController(): Router;
|
|
17
|
+
export declare function createCliVersionController(options?: CapabilitiesOptions): Router;
|
|
7
18
|
//# sourceMappingURL=cli-version-controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-version-controller.d.ts","sourceRoot":"","sources":["../../../src/controllers/cli-version-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAMjC;;;GAGG;AACH,wBAAgB,0BAA0B,
|
|
1
|
+
{"version":3,"file":"cli-version-controller.d.ts","sourceRoot":"","sources":["../../../src/controllers/cli-version-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAMjC,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;CACrE;AAED,MAAM,WAAW,mBAAmB;IAChC,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,iBAAiB,CAAC;CAC/C;AAED,oDAAoD;AACpD,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,iBAAiB,CAEzF;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAqChF"}
|
|
@@ -33,15 +33,20 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resolveShellCapabilities = resolveShellCapabilities;
|
|
36
37
|
exports.createCliVersionController = createCliVersionController;
|
|
37
38
|
const express_1 = require("express");
|
|
38
39
|
const os = __importStar(require("os"));
|
|
39
40
|
const SERVER_VERSION = '2.0.0';
|
|
41
|
+
/** Resolves the shell fields of `/capabilities`. */
|
|
42
|
+
function resolveShellCapabilities(options) {
|
|
43
|
+
return options?.shellCapabilities ? options.shellCapabilities() : { shell: true };
|
|
44
|
+
}
|
|
40
45
|
/**
|
|
41
46
|
* Creates an Express router for API version discovery and server capabilities.
|
|
42
47
|
* @returns Router with `/versions` and `/capabilities` endpoints.
|
|
43
48
|
*/
|
|
44
|
-
function createCliVersionController() {
|
|
49
|
+
function createCliVersionController(options) {
|
|
45
50
|
const router = (0, express_1.Router)();
|
|
46
51
|
router.get('/versions', (_req, res) => {
|
|
47
52
|
res.json({
|
|
@@ -64,7 +69,7 @@ function createCliVersionController() {
|
|
|
64
69
|
? 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
|
|
65
70
|
: '/bin/bash';
|
|
66
71
|
res.json({
|
|
67
|
-
|
|
72
|
+
...resolveShellCapabilities(options),
|
|
68
73
|
os: detectedOs,
|
|
69
74
|
shellPath,
|
|
70
75
|
version: SERVER_VERSION,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-version-controller.js","sourceRoot":"","sources":["../../../src/controllers/cli-version-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"cli-version-controller.js","sourceRoot":"","sources":["../../../src/controllers/cli-version-controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,4DAEC;AAMD,gEAqCC;AA/DD,qCAAiC;AACjC,uCAAyB;AAGzB,MAAM,cAAc,GAAG,OAAO,CAAC;AAa/B,oDAAoD;AACpD,SAAgB,wBAAwB,CAAC,OAA6B;IAClE,OAAO,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACtF,CAAC;AAED;;;GAGG;AACH,SAAgB,0BAA0B,CAAC,OAA6B;IACpE,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;IAExB,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAClC,GAAG,CAAC,IAAI,CAAC;YACL,iBAAiB,EAAE,CAAC,CAAC,CAAC;YACtB,gBAAgB,EAAE,CAAC;YACnB,aAAa,EAAE,cAAc;SAChC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACjC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACtC,MAAM,UAAU,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO;YACxC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,QAAQ;gBACxB,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,OAAO,CAAC;QAElB,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC;QAChE,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO;YACvC,CAAC,CAAC,gEAAgE;YAClE,CAAC,CAAC,WAAW,CAAC;QAElB,GAAG,CAAC,IAAI,CAAC;YACL,GAAG,wBAAwB,CAAC,OAAO,CAAC;YACpC,EAAE,EAAE,UAAU;YACd,SAAS;YACT,OAAO,EAAE,cAAc;YACvB,SAAS,EAAE,IAAI;SAClB,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -2,6 +2,8 @@ import { Express, Router } from 'express';
|
|
|
2
2
|
import cors from 'cors';
|
|
3
3
|
import { CliCommandRegistry, CliCommandExecutorService, CliEventSocketManager, CliLogSocketManager } from './services';
|
|
4
4
|
import { CliBuilder } from './extensions';
|
|
5
|
+
import { ICliServerAuth } from './auth/cli-server-auth';
|
|
6
|
+
import { CliShellOptions } from './services/cli-shell-options';
|
|
5
7
|
/**
|
|
6
8
|
* Generic interface for plugin results that can be auto-mounted.
|
|
7
9
|
* Plugins expose a `prefix` and `router`; some also have a
|
|
@@ -12,13 +14,53 @@ export interface MountablePlugin {
|
|
|
12
14
|
router: Router;
|
|
13
15
|
dashboardPrefix?: string;
|
|
14
16
|
dashboardRouter?: Router;
|
|
17
|
+
/**
|
|
18
|
+
* Auth provider exposed by the users plugin. Mounting such a plugin
|
|
19
|
+
* installs it: when `protectServer` is on, every server route and socket
|
|
20
|
+
* then requires a users session.
|
|
21
|
+
*/
|
|
22
|
+
serverAuth?: ICliServerAuth;
|
|
23
|
+
/** Routes that stay public under server protection, as `"METHOD /path"` (e.g. a plugin's login). */
|
|
24
|
+
publicRoutes?: string[];
|
|
15
25
|
}
|
|
16
26
|
/** Options for creating a standalone CLI server instance. */
|
|
17
27
|
export interface CliServerOptions {
|
|
18
28
|
/** Base path for CLI routes. Defaults to '/api/qcli'. */
|
|
19
29
|
basePath?: string;
|
|
20
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* CORS configuration. `true` = permissive (any origin, no credentials),
|
|
32
|
+
* `false` = disabled, or a cors options object. When omitted, CORS is
|
|
33
|
+
* enabled only for `allowedOrigins` (disabled if none are set).
|
|
34
|
+
*/
|
|
21
35
|
cors?: boolean | cors.CorsOptions;
|
|
36
|
+
/**
|
|
37
|
+
* Origins allowed for CORS and WebSocket upgrades (exact match; `http://host:*`
|
|
38
|
+
* matches any port). Every WS upgrade with an `Origin` header is checked.
|
|
39
|
+
*/
|
|
40
|
+
allowedOrigins?: string[];
|
|
41
|
+
/**
|
|
42
|
+
* Accept interactive shell WebSocket sessions (default false). When enabled,
|
|
43
|
+
* access is decided by one mode: users plugin mounted (ticket +
|
|
44
|
+
* `shell:execute`), `shell.token`, `shell.authorize` or `shell.allowAnonymous`.
|
|
45
|
+
* With none of them the shell is locked (every connection closed with 4401).
|
|
46
|
+
*/
|
|
47
|
+
enableShell?: boolean;
|
|
48
|
+
/** Remote shell security: access mode, limits, timeouts, cwd, shell binary, environment. */
|
|
49
|
+
shell?: CliShellOptions;
|
|
50
|
+
/**
|
|
51
|
+
* Behind reverse proxies: the number of trusted proxy hops (`true` = 1,
|
|
52
|
+
* `false`/0 = none, the default). The client IP (Express `req.ip`, the
|
|
53
|
+
* shell's per-address limits) is the `X-Forwarded-For` entry at index
|
|
54
|
+
* `len - hops` (with one hop, the rightmost entry, appended by the trusted
|
|
55
|
+
* proxy); the leftmost entry when the list is shorter, the socket address
|
|
56
|
+
* when the header is absent. `X-Forwarded-Proto`/`-Host` are honoured too.
|
|
57
|
+
*/
|
|
58
|
+
trustProxy?: boolean | number;
|
|
59
|
+
/**
|
|
60
|
+
* Auth provider protecting the whole server (e.g. `usersPlugin.serverAuth`).
|
|
61
|
+
* Can also be installed later with `setAuth()` or by `mountPlugin(usersPlugin)`.
|
|
62
|
+
*/
|
|
63
|
+
auth?: ICliServerAuth;
|
|
22
64
|
/** Configure processors via the builder. */
|
|
23
65
|
configure?: (builder: CliBuilder) => void;
|
|
24
66
|
}
|
|
@@ -48,6 +90,8 @@ export interface CliServerResult {
|
|
|
48
90
|
* ```
|
|
49
91
|
*/
|
|
50
92
|
mountPlugin(plugin: MountablePlugin): void;
|
|
93
|
+
/** Installs (or removes) the auth provider protecting server routes and sockets. */
|
|
94
|
+
setAuth(auth: ICliServerAuth | undefined): void;
|
|
51
95
|
}
|
|
52
96
|
export declare function createCliServer(options?: CliServerOptions): CliServerResult;
|
|
53
97
|
//# sourceMappingURL=create-cli-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-cli-server.d.ts","sourceRoot":"","sources":["../../src/create-cli-server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"create-cli-server.d.ts","sourceRoot":"","sources":["../../src/create-cli-server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAO1C,OAAO,EAAE,cAAc,EAAmD,MAAM,wBAAwB,CAAC;AAEzG,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAG/D;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,oGAAoG;IACpG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAID,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;IAClC;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4FAA4F;IAC5F,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B;;;OAGG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;CAC7C;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,yBAAyB,CAAC;IACpC,kBAAkB,EAAE,qBAAqB,CAAC;IAC1C,gBAAgB,EAAE,mBAAmB,CAAC;IACtC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC3C,oFAAoF;IACpF,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,CAAC;CACnD;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,CA6H/E"}
|
|
@@ -14,27 +14,71 @@ const filesystem_controller_1 = require("./controllers/filesystem-controller");
|
|
|
14
14
|
const cli_server_plugin_filesystem_1 = require("@qodalis/cli-server-plugin-filesystem");
|
|
15
15
|
const cli_server_plugin_data_explorer_1 = require("@qodalis/cli-server-plugin-data-explorer");
|
|
16
16
|
const logger_1 = require("./utils/logger");
|
|
17
|
+
const cli_server_auth_1 = require("./auth/cli-server-auth");
|
|
18
|
+
const cli_server_auth_gate_1 = require("./auth/cli-server-auth-gate");
|
|
17
19
|
const logger = (0, logger_1.createLogger)('Server');
|
|
18
20
|
function createCliServer(options = {}) {
|
|
19
|
-
const { basePath = '/api/qcli', cors: corsOption =
|
|
21
|
+
const { basePath = '/api/qcli', cors: corsOption, configure, allowedOrigins, enableShell = false, shell, trustProxy = false } = options;
|
|
22
|
+
if (shell && !enableShell) {
|
|
23
|
+
logger.warn('shell options are set but enableShell is false: the shell stays disabled');
|
|
24
|
+
}
|
|
20
25
|
const app = (0, express_1.default)();
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
const proxyHops = (0, cli_server_auth_1.trustedProxyHops)(trustProxy);
|
|
27
|
+
if (proxyHops > 0) {
|
|
28
|
+
app.set('trust proxy', proxyHops);
|
|
29
|
+
}
|
|
30
|
+
if (corsOption === true) {
|
|
31
|
+
app.use((0, cors_1.default)());
|
|
32
|
+
}
|
|
33
|
+
else if (corsOption && typeof corsOption === 'object') {
|
|
34
|
+
app.use((0, cors_1.default)(corsOption));
|
|
23
35
|
}
|
|
24
|
-
|
|
36
|
+
else if (corsOption === undefined && allowedOrigins && allowedOrigins.length > 0) {
|
|
37
|
+
// Same-origin requests (e.g. the bundled admin dashboard) are always allowed.
|
|
38
|
+
app.use((0, cors_1.default)((req, callback) => {
|
|
39
|
+
const origin = req.headers.origin;
|
|
40
|
+
callback(null, {
|
|
41
|
+
origin: (0, cli_server_auth_1.isOriginAllowed)(origin, allowedOrigins) || (0, cli_server_auth_1.isSameOrigin)(origin, req),
|
|
42
|
+
});
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
app.use(express_1.default.json({ limit: '1mb' }));
|
|
46
|
+
// Render body-parser failures (malformed JSON, too large) as JSON `{ error }`
|
|
47
|
+
app.use((err, _req, res, next) => {
|
|
48
|
+
if (err && (err.type === 'entity.parse.failed' || err.type === 'entity.too.large')) {
|
|
49
|
+
const status = err.type === 'entity.too.large' ? 413 : 400;
|
|
50
|
+
res.status(status).json({ error: status === 413 ? 'request body too large' : 'invalid JSON body' });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
next(err);
|
|
54
|
+
});
|
|
25
55
|
const registry = new services_1.CliCommandRegistry();
|
|
26
56
|
const builder = new extensions_1.CliBuilder(registry);
|
|
57
|
+
// Server-wide auth gate (no-op until an auth provider is installed)
|
|
58
|
+
let serverAuth;
|
|
59
|
+
const publicRoutes = new Set();
|
|
60
|
+
app.use((0, cli_server_auth_gate_1.createServerAuthGate)(() => serverAuth, {
|
|
61
|
+
registry,
|
|
62
|
+
cliPrefixes: Array.from(new Set(['/api/v1/qcli', (0, cli_server_auth_gate_1.normalizePath)(basePath)])),
|
|
63
|
+
publicRoutes,
|
|
64
|
+
}));
|
|
27
65
|
if (configure) {
|
|
28
66
|
configure(builder);
|
|
29
67
|
}
|
|
30
68
|
const executor = new services_1.CliCommandExecutorService(registry);
|
|
69
|
+
const eventSocketManager = new services_1.CliEventSocketManager({ enableShell, shell, allowedOrigins, trustProxy });
|
|
70
|
+
const logSocketManager = new services_1.CliLogSocketManager({ allowedOrigins, trustProxy });
|
|
71
|
+
const shellCapabilities = () => {
|
|
72
|
+
const mode = eventSocketManager.shellAuthMode;
|
|
73
|
+
return mode ? { shell: true, shellAuth: mode } : { shell: false };
|
|
74
|
+
};
|
|
31
75
|
// Version discovery endpoint
|
|
32
|
-
app.use('/api/qcli', (0, cli_version_controller_1.createCliVersionController)());
|
|
76
|
+
app.use('/api/qcli', (0, cli_version_controller_1.createCliVersionController)({ shellCapabilities }));
|
|
33
77
|
// API v1 routes
|
|
34
|
-
app.use('/api/v1/qcli', (0, cli_controller_1.createCliController)(registry, executor));
|
|
78
|
+
app.use('/api/v1/qcli', (0, cli_controller_1.createCliController)(registry, executor, { shellCapabilities }));
|
|
35
79
|
// Custom basePath fallback (when user overrides the default)
|
|
36
80
|
if (basePath !== '/api/v1/qcli') {
|
|
37
|
-
app.use(basePath, (0, cli_controller_1.createCliController)(registry, executor));
|
|
81
|
+
app.use(basePath, (0, cli_controller_1.createCliController)(registry, executor, { shellCapabilities }));
|
|
38
82
|
}
|
|
39
83
|
// Filesystem API — provider-based
|
|
40
84
|
let fsProvider = builder.fileStorageProvider;
|
|
@@ -51,15 +95,32 @@ function createCliServer(options = {}) {
|
|
|
51
95
|
const deExecutor = new cli_server_plugin_data_explorer_1.DataExplorerExecutor(deBuilder.registry);
|
|
52
96
|
app.use('/api/qcli/data-explorer', (0, cli_server_plugin_data_explorer_1.createDataExplorerController)(deBuilder.registry, deExecutor));
|
|
53
97
|
}
|
|
54
|
-
const eventSocketManager = new services_1.CliEventSocketManager();
|
|
55
|
-
const logSocketManager = new services_1.CliLogSocketManager();
|
|
56
98
|
logger.info('CLI server created with %d processors', registry.processors.length);
|
|
99
|
+
const setAuth = (auth) => {
|
|
100
|
+
serverAuth = auth;
|
|
101
|
+
eventSocketManager.setAuth(auth);
|
|
102
|
+
logSocketManager.setAuth(auth);
|
|
103
|
+
auth?.attachToServer?.({
|
|
104
|
+
allowedOrigins,
|
|
105
|
+
broadcast: (msg) => eventSocketManager.broadcastMessage(msg),
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
if (options.auth) {
|
|
109
|
+
setAuth(options.auth);
|
|
110
|
+
}
|
|
57
111
|
const mountPlugin = (plugin) => {
|
|
112
|
+
for (const route of plugin.publicRoutes ?? []) {
|
|
113
|
+
const [method, ...rest] = route.trim().split(/\s+/);
|
|
114
|
+
publicRoutes.add(`${method.toUpperCase()} ${(0, cli_server_auth_gate_1.normalizePath)(rest.join(' '))}`);
|
|
115
|
+
}
|
|
116
|
+
if (plugin.serverAuth && plugin.serverAuth !== serverAuth) {
|
|
117
|
+
setAuth(plugin.serverAuth);
|
|
118
|
+
}
|
|
58
119
|
app.use(plugin.prefix, plugin.router);
|
|
59
120
|
if (plugin.dashboardPrefix && plugin.dashboardRouter) {
|
|
60
121
|
app.use(plugin.dashboardPrefix, plugin.dashboardRouter);
|
|
61
122
|
}
|
|
62
123
|
};
|
|
63
|
-
return { app, registry, builder, executor, eventSocketManager, logSocketManager, mountPlugin };
|
|
124
|
+
return { app, registry, builder, executor, eventSocketManager, logSocketManager, mountPlugin, setAuth };
|
|
64
125
|
}
|
|
65
126
|
//# sourceMappingURL=create-cli-server.js.map
|