@solongate/proxy 0.82.48 → 0.82.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +108 -21
- package/dist/tui/index.js +107 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9222,6 +9222,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9222
9222
|
const [editing, setEditing] = useState4(false);
|
|
9223
9223
|
const [editVal, setEditVal] = useState4("");
|
|
9224
9224
|
const [status, setStatus] = useState4(null);
|
|
9225
|
+
const [pendingDel, setPendingDel] = useState4(null);
|
|
9225
9226
|
const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
|
|
9226
9227
|
const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
|
|
9227
9228
|
useEffect4(() => {
|
|
@@ -9244,6 +9245,11 @@ function PoliciesPanel({ focused }) {
|
|
|
9244
9245
|
};
|
|
9245
9246
|
const save = async () => {
|
|
9246
9247
|
if (!selected || !detail.data) return;
|
|
9248
|
+
const blanket = rules.findIndex(isBlanketRule);
|
|
9249
|
+
if (blanket !== -1) {
|
|
9250
|
+
setStatus(`\u2717 rule ${blanket + 1} matches EVERYTHING \u2014 pick a Constraint + Match value, or narrow Permissions`);
|
|
9251
|
+
return;
|
|
9252
|
+
}
|
|
9247
9253
|
setStatus("Saving\u2026");
|
|
9248
9254
|
try {
|
|
9249
9255
|
const res = await api.policies.update(selected.id, {
|
|
@@ -9292,9 +9298,13 @@ function PoliciesPanel({ focused }) {
|
|
|
9292
9298
|
return;
|
|
9293
9299
|
}
|
|
9294
9300
|
if (view === "list") {
|
|
9295
|
-
if (key.upArrow)
|
|
9296
|
-
|
|
9297
|
-
|
|
9301
|
+
if (key.upArrow) {
|
|
9302
|
+
setPendingDel(null);
|
|
9303
|
+
setPi((n) => Math.max(0, n - 1));
|
|
9304
|
+
} else if (key.downArrow) {
|
|
9305
|
+
setPendingDel(null);
|
|
9306
|
+
setPi((n) => Math.min(policies.length - 1, n + 1));
|
|
9307
|
+
} else if (key.return || key.rightArrow) {
|
|
9298
9308
|
setStatus(null);
|
|
9299
9309
|
setView("rules");
|
|
9300
9310
|
} else if (input === "a") {
|
|
@@ -9314,6 +9324,22 @@ function PoliciesPanel({ focused }) {
|
|
|
9314
9324
|
setStatus("\u2713 active policy: NONE \u2014 no rules enforced, w/b grants are refused");
|
|
9315
9325
|
activeQ.reload();
|
|
9316
9326
|
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
9327
|
+
} else if (input === "d") {
|
|
9328
|
+
if (!selected) return;
|
|
9329
|
+
if (pendingDel !== selected.id) {
|
|
9330
|
+
setPendingDel(selected.id);
|
|
9331
|
+
setStatus(`\u26A0 d again to DELETE policy "${selected.name}" \u2014 cannot be undone`);
|
|
9332
|
+
return;
|
|
9333
|
+
}
|
|
9334
|
+
setPendingDel(null);
|
|
9335
|
+
setStatus("Deleting\u2026");
|
|
9336
|
+
const name = selected.name;
|
|
9337
|
+
void api.policies.remove(selected.id).then(() => {
|
|
9338
|
+
setStatus(`\u2713 deleted policy "${name}"`);
|
|
9339
|
+
setPi(0);
|
|
9340
|
+
list5.reload();
|
|
9341
|
+
activeQ.reload();
|
|
9342
|
+
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
9317
9343
|
}
|
|
9318
9344
|
return;
|
|
9319
9345
|
}
|
|
@@ -9329,7 +9355,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9329
9355
|
} else if (input === " ") {
|
|
9330
9356
|
if (rules[ri]) mutate(rules.map((r, i) => i === ri ? { ...r, enabled: !r.enabled } : r));
|
|
9331
9357
|
} else if (input === "e") {
|
|
9332
|
-
if (rules[ri]) mutate(rules.map((r, i) => i === ri ?
|
|
9358
|
+
if (rules[ri]) mutate(rules.map((r, i) => i === ri ? migrateEffect(r, r.effect === "ALLOW" ? "DENY" : "ALLOW") : r));
|
|
9333
9359
|
} else if (input === "d") {
|
|
9334
9360
|
if (rules[ri]) {
|
|
9335
9361
|
const next = rules.filter((_, i) => i !== ri);
|
|
@@ -9360,9 +9386,16 @@ function PoliciesPanel({ focused }) {
|
|
|
9360
9386
|
else if (key.upArrow) setFi((n) => Math.max(0, n - 1));
|
|
9361
9387
|
else if (key.downArrow) setFi((n) => Math.min(FIELDS.length - 1, n + 1));
|
|
9362
9388
|
else if (field.kind === "effect" && (input === " " || key.rightArrow)) {
|
|
9363
|
-
mutate(rules.map((r, i) => i === ri ?
|
|
9389
|
+
mutate(rules.map((r, i) => i === ri ? migrateEffect(r, r.effect === "ALLOW" ? "DENY" : "ALLOW") : r));
|
|
9364
9390
|
} else if (field.kind === "enabled" && (input === " " || key.rightArrow)) {
|
|
9365
9391
|
mutate(rules.map((r, i) => i === ri ? { ...r, enabled: !r.enabled } : r));
|
|
9392
|
+
} else if (field.kind === "ctype" && (input === " " || key.rightArrow || key.leftArrow)) {
|
|
9393
|
+
const dir = key.leftArrow ? -1 : 1;
|
|
9394
|
+
const nextT = CTYPES[(CTYPES.indexOf(currentCType(rule2)) + dir + CTYPES.length) % CTYPES.length];
|
|
9395
|
+
mutate(rules.map((r, i) => i === ri ? setCType(r, nextT) : r));
|
|
9396
|
+
} else if (field.kind === "perms" && (input === "r" || input === "w" || input === "e" || input === "n")) {
|
|
9397
|
+
const p = { r: "READ", w: "WRITE", e: "EXECUTE", n: "NETWORK" }[input];
|
|
9398
|
+
mutate(rules.map((rr, i) => i === ri ? togglePerm(rr, p) : rr));
|
|
9366
9399
|
} else if (field.kind === "priority" && (key.rightArrow || key.leftArrow)) {
|
|
9367
9400
|
const d = key.rightArrow ? 1 : -1;
|
|
9368
9401
|
mutate(rules.map((r, i) => i === ri ? { ...r, priority: Math.max(0, r.priority + d) } : r));
|
|
@@ -9392,7 +9425,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9392
9425
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: activeBy ? ` (${activeBy})` : "" })
|
|
9393
9426
|
] }) : /* @__PURE__ */ jsx4(Text4, { color: theme.bad, bold: true, children: "\u25CB NONE \u2014 nothing enforced, grants refused" })
|
|
9394
9427
|
] }),
|
|
9395
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 n new
|
|
9428
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 n new \xB7 a activate \xB7 x deactivate \xB7 d delete \xB7 ^R refresh${lAbove ? ` \xB7 \u25B2${lAbove}` : ""}${lBelow ? ` \xB7 \u25BC${lBelow}` : ""}` : "press \u2192 to browse" }),
|
|
9396
9429
|
creating !== null ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
9397
9430
|
/* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: "new policy name: " }),
|
|
9398
9431
|
/* @__PURE__ */ jsx4(TextInput3, { value: creating, onChange: setCreating, onSubmit: commitNewPolicy })
|
|
@@ -9467,7 +9500,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9467
9500
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: rule?.id ?? "" }),
|
|
9468
9501
|
dirtyTag
|
|
9469
9502
|
] }),
|
|
9470
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit text \xB7 space/\u2192 toggle \xB7 s save \xB7 \u2190 back" }),
|
|
9503
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit text \xB7 space/\u2192 toggle \xB7 r/w/e/n perms \xB7 s save \xB7 \u2190 back" }),
|
|
9471
9504
|
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: FIELDS.map((f, i) => {
|
|
9472
9505
|
const val = rule ? f.get(rule) : "";
|
|
9473
9506
|
const active2 = i === fi;
|
|
@@ -9496,7 +9529,7 @@ function PoliciesPanel({ focused }) {
|
|
|
9496
9529
|
status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
|
|
9497
9530
|
] });
|
|
9498
9531
|
}
|
|
9499
|
-
var
|
|
9532
|
+
var CTYPES, CTYPE_GROUP, currentCType, clearConstraints, setCType, cValue, setCValue, migrateEffect, PERMS, permList, permIsAny, togglePerm, permDisplay, ruleHasValues, isBlanketRule, FIELDS;
|
|
9500
9533
|
var init_Policies = __esm({
|
|
9501
9534
|
"src/tui/panels/Policies.tsx"() {
|
|
9502
9535
|
"use strict";
|
|
@@ -9506,25 +9539,79 @@ var init_Policies = __esm({
|
|
|
9506
9539
|
init_components();
|
|
9507
9540
|
init_hooks();
|
|
9508
9541
|
init_theme();
|
|
9509
|
-
|
|
9510
|
-
|
|
9542
|
+
CTYPES = ["none", "command", "path", "filename", "url"];
|
|
9543
|
+
CTYPE_GROUP = {
|
|
9544
|
+
command: "commandConstraints",
|
|
9545
|
+
path: "pathConstraints",
|
|
9546
|
+
filename: "filenameConstraints",
|
|
9547
|
+
url: "urlConstraints"
|
|
9548
|
+
};
|
|
9549
|
+
currentCType = (r) => {
|
|
9550
|
+
if (r.filenameConstraints) return "filename";
|
|
9551
|
+
if (r.urlConstraints) return "url";
|
|
9552
|
+
if (r.commandConstraints) return "command";
|
|
9553
|
+
if (r.pathConstraints) return "path";
|
|
9554
|
+
return "none";
|
|
9555
|
+
};
|
|
9556
|
+
clearConstraints = (r) => ({
|
|
9557
|
+
...r,
|
|
9558
|
+
commandConstraints: void 0,
|
|
9559
|
+
pathConstraints: void 0,
|
|
9560
|
+
filenameConstraints: void 0,
|
|
9561
|
+
urlConstraints: void 0
|
|
9562
|
+
});
|
|
9563
|
+
setCType = (r, t) => {
|
|
9564
|
+
const base = clearConstraints(r);
|
|
9565
|
+
if (t === "none") return base;
|
|
9566
|
+
const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
|
|
9567
|
+
return { ...base, [CTYPE_GROUP[t]]: { [listKey]: [] } };
|
|
9568
|
+
};
|
|
9569
|
+
cValue = (r) => {
|
|
9570
|
+
const t = currentCType(r);
|
|
9571
|
+
if (t === "none") return "";
|
|
9572
|
+
const c2 = r[CTYPE_GROUP[t]];
|
|
9573
|
+
return [...c2?.allowed ?? [], ...c2?.denied ?? []].join(", ");
|
|
9574
|
+
};
|
|
9575
|
+
setCValue = (r, val) => {
|
|
9576
|
+
const t = currentCType(r);
|
|
9577
|
+
if (t === "none") return r;
|
|
9511
9578
|
const arr = val.split(",").map((s) => s.trim()).filter(Boolean);
|
|
9512
|
-
const
|
|
9513
|
-
return { ...r, [
|
|
9579
|
+
const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
|
|
9580
|
+
return { ...r, [CTYPE_GROUP[t]]: { [listKey]: arr } };
|
|
9581
|
+
};
|
|
9582
|
+
migrateEffect = (r, nextEffect) => {
|
|
9583
|
+
const flipped = { ...r, effect: nextEffect };
|
|
9584
|
+
const t = currentCType(r);
|
|
9585
|
+
if (t === "none") return flipped;
|
|
9586
|
+
const c2 = r[CTYPE_GROUP[t]];
|
|
9587
|
+
const items = [...c2?.allowed ?? [], ...c2?.denied ?? []];
|
|
9588
|
+
const listKey = nextEffect === "ALLOW" ? "allowed" : "denied";
|
|
9589
|
+
return { ...flipped, [CTYPE_GROUP[t]]: { [listKey]: items } };
|
|
9590
|
+
};
|
|
9591
|
+
PERMS = ["READ", "WRITE", "EXECUTE", "NETWORK"];
|
|
9592
|
+
permList = (r) => !r.permission ? [...PERMS] : Array.isArray(r.permission) ? r.permission : [r.permission];
|
|
9593
|
+
permIsAny = (r) => PERMS.every((p) => permList(r).includes(p));
|
|
9594
|
+
togglePerm = (r, p) => {
|
|
9595
|
+
const cur = permList(r);
|
|
9596
|
+
let next = cur.includes(p) ? cur.filter((x) => x !== p) : [...cur, p];
|
|
9597
|
+
if (next.length === 0) next = [p];
|
|
9598
|
+
return { ...r, permission: PERMS.every((x) => next.includes(x)) ? void 0 : next };
|
|
9599
|
+
};
|
|
9600
|
+
permDisplay = (r) => permIsAny(r) ? "any (READ WRITE EXECUTE NETWORK)" : permList(r).join(" ");
|
|
9601
|
+
ruleHasValues = (r) => {
|
|
9602
|
+
const t = currentCType(r);
|
|
9603
|
+
if (t === "none") return false;
|
|
9604
|
+
const c2 = r[CTYPE_GROUP[t]];
|
|
9605
|
+
return (c2?.allowed?.length ?? 0) + (c2?.denied?.length ?? 0) > 0;
|
|
9514
9606
|
};
|
|
9607
|
+
isBlanketRule = (r) => !ruleHasValues(r) && permIsAny(r);
|
|
9515
9608
|
FIELDS = [
|
|
9516
9609
|
{ label: "Effect", kind: "effect", get: (r) => r.effect },
|
|
9517
|
-
{ label: "
|
|
9610
|
+
{ label: "Constraint", kind: "ctype", get: (r) => currentCType(r) },
|
|
9611
|
+
{ label: "Permissions", kind: "perms", get: permDisplay },
|
|
9518
9612
|
{ label: "Priority", kind: "priority", get: (r) => String(r.priority) },
|
|
9519
9613
|
{ label: "Description", kind: "text", get: (r) => r.description ?? "", set: (r, v) => ({ ...r, description: v }) },
|
|
9520
|
-
{ label: "
|
|
9521
|
-
{ label: "Cmd deny", kind: "text", get: (r) => constr(r, "commandConstraints", "denied"), set: (r, v) => setConstr(r, "commandConstraints", "denied", v) },
|
|
9522
|
-
{ label: "Path allow", kind: "text", get: (r) => constr(r, "pathConstraints", "allowed"), set: (r, v) => setConstr(r, "pathConstraints", "allowed", v) },
|
|
9523
|
-
{ label: "Path deny", kind: "text", get: (r) => constr(r, "pathConstraints", "denied"), set: (r, v) => setConstr(r, "pathConstraints", "denied", v) },
|
|
9524
|
-
{ label: "File allow", kind: "text", get: (r) => constr(r, "filenameConstraints", "allowed"), set: (r, v) => setConstr(r, "filenameConstraints", "allowed", v) },
|
|
9525
|
-
{ label: "File deny", kind: "text", get: (r) => constr(r, "filenameConstraints", "denied"), set: (r, v) => setConstr(r, "filenameConstraints", "denied", v) },
|
|
9526
|
-
{ label: "URL allow", kind: "text", get: (r) => constr(r, "urlConstraints", "allowed"), set: (r, v) => setConstr(r, "urlConstraints", "allowed", v) },
|
|
9527
|
-
{ label: "URL deny", kind: "text", get: (r) => constr(r, "urlConstraints", "denied"), set: (r, v) => setConstr(r, "urlConstraints", "denied", v) }
|
|
9614
|
+
{ label: "Match", kind: "text", get: cValue, set: setCValue }
|
|
9528
9615
|
];
|
|
9529
9616
|
}
|
|
9530
9617
|
});
|
package/dist/tui/index.js
CHANGED
|
@@ -2420,25 +2420,79 @@ function onSectionRequest(fn) {
|
|
|
2420
2420
|
|
|
2421
2421
|
// src/tui/panels/Policies.tsx
|
|
2422
2422
|
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2423
|
-
var
|
|
2424
|
-
var
|
|
2423
|
+
var CTYPES = ["none", "command", "path", "filename", "url"];
|
|
2424
|
+
var CTYPE_GROUP = {
|
|
2425
|
+
command: "commandConstraints",
|
|
2426
|
+
path: "pathConstraints",
|
|
2427
|
+
filename: "filenameConstraints",
|
|
2428
|
+
url: "urlConstraints"
|
|
2429
|
+
};
|
|
2430
|
+
var currentCType = (r) => {
|
|
2431
|
+
if (r.filenameConstraints) return "filename";
|
|
2432
|
+
if (r.urlConstraints) return "url";
|
|
2433
|
+
if (r.commandConstraints) return "command";
|
|
2434
|
+
if (r.pathConstraints) return "path";
|
|
2435
|
+
return "none";
|
|
2436
|
+
};
|
|
2437
|
+
var clearConstraints = (r) => ({
|
|
2438
|
+
...r,
|
|
2439
|
+
commandConstraints: void 0,
|
|
2440
|
+
pathConstraints: void 0,
|
|
2441
|
+
filenameConstraints: void 0,
|
|
2442
|
+
urlConstraints: void 0
|
|
2443
|
+
});
|
|
2444
|
+
var setCType = (r, t) => {
|
|
2445
|
+
const base = clearConstraints(r);
|
|
2446
|
+
if (t === "none") return base;
|
|
2447
|
+
const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
|
|
2448
|
+
return { ...base, [CTYPE_GROUP[t]]: { [listKey]: [] } };
|
|
2449
|
+
};
|
|
2450
|
+
var cValue = (r) => {
|
|
2451
|
+
const t = currentCType(r);
|
|
2452
|
+
if (t === "none") return "";
|
|
2453
|
+
const c2 = r[CTYPE_GROUP[t]];
|
|
2454
|
+
return [...c2?.allowed ?? [], ...c2?.denied ?? []].join(", ");
|
|
2455
|
+
};
|
|
2456
|
+
var setCValue = (r, val) => {
|
|
2457
|
+
const t = currentCType(r);
|
|
2458
|
+
if (t === "none") return r;
|
|
2425
2459
|
const arr = val.split(",").map((s) => s.trim()).filter(Boolean);
|
|
2426
|
-
const
|
|
2427
|
-
return { ...r, [
|
|
2460
|
+
const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
|
|
2461
|
+
return { ...r, [CTYPE_GROUP[t]]: { [listKey]: arr } };
|
|
2462
|
+
};
|
|
2463
|
+
var migrateEffect = (r, nextEffect) => {
|
|
2464
|
+
const flipped = { ...r, effect: nextEffect };
|
|
2465
|
+
const t = currentCType(r);
|
|
2466
|
+
if (t === "none") return flipped;
|
|
2467
|
+
const c2 = r[CTYPE_GROUP[t]];
|
|
2468
|
+
const items = [...c2?.allowed ?? [], ...c2?.denied ?? []];
|
|
2469
|
+
const listKey = nextEffect === "ALLOW" ? "allowed" : "denied";
|
|
2470
|
+
return { ...flipped, [CTYPE_GROUP[t]]: { [listKey]: items } };
|
|
2471
|
+
};
|
|
2472
|
+
var PERMS = ["READ", "WRITE", "EXECUTE", "NETWORK"];
|
|
2473
|
+
var permList = (r) => !r.permission ? [...PERMS] : Array.isArray(r.permission) ? r.permission : [r.permission];
|
|
2474
|
+
var permIsAny = (r) => PERMS.every((p) => permList(r).includes(p));
|
|
2475
|
+
var togglePerm = (r, p) => {
|
|
2476
|
+
const cur = permList(r);
|
|
2477
|
+
let next = cur.includes(p) ? cur.filter((x) => x !== p) : [...cur, p];
|
|
2478
|
+
if (next.length === 0) next = [p];
|
|
2479
|
+
return { ...r, permission: PERMS.every((x) => next.includes(x)) ? void 0 : next };
|
|
2480
|
+
};
|
|
2481
|
+
var permDisplay = (r) => permIsAny(r) ? "any (READ WRITE EXECUTE NETWORK)" : permList(r).join(" ");
|
|
2482
|
+
var ruleHasValues = (r) => {
|
|
2483
|
+
const t = currentCType(r);
|
|
2484
|
+
if (t === "none") return false;
|
|
2485
|
+
const c2 = r[CTYPE_GROUP[t]];
|
|
2486
|
+
return (c2?.allowed?.length ?? 0) + (c2?.denied?.length ?? 0) > 0;
|
|
2428
2487
|
};
|
|
2488
|
+
var isBlanketRule = (r) => !ruleHasValues(r) && permIsAny(r);
|
|
2429
2489
|
var FIELDS = [
|
|
2430
2490
|
{ label: "Effect", kind: "effect", get: (r) => r.effect },
|
|
2431
|
-
{ label: "
|
|
2491
|
+
{ label: "Constraint", kind: "ctype", get: (r) => currentCType(r) },
|
|
2492
|
+
{ label: "Permissions", kind: "perms", get: permDisplay },
|
|
2432
2493
|
{ label: "Priority", kind: "priority", get: (r) => String(r.priority) },
|
|
2433
2494
|
{ label: "Description", kind: "text", get: (r) => r.description ?? "", set: (r, v) => ({ ...r, description: v }) },
|
|
2434
|
-
{ label: "
|
|
2435
|
-
{ label: "Cmd deny", kind: "text", get: (r) => constr(r, "commandConstraints", "denied"), set: (r, v) => setConstr(r, "commandConstraints", "denied", v) },
|
|
2436
|
-
{ label: "Path allow", kind: "text", get: (r) => constr(r, "pathConstraints", "allowed"), set: (r, v) => setConstr(r, "pathConstraints", "allowed", v) },
|
|
2437
|
-
{ label: "Path deny", kind: "text", get: (r) => constr(r, "pathConstraints", "denied"), set: (r, v) => setConstr(r, "pathConstraints", "denied", v) },
|
|
2438
|
-
{ label: "File allow", kind: "text", get: (r) => constr(r, "filenameConstraints", "allowed"), set: (r, v) => setConstr(r, "filenameConstraints", "allowed", v) },
|
|
2439
|
-
{ label: "File deny", kind: "text", get: (r) => constr(r, "filenameConstraints", "denied"), set: (r, v) => setConstr(r, "filenameConstraints", "denied", v) },
|
|
2440
|
-
{ label: "URL allow", kind: "text", get: (r) => constr(r, "urlConstraints", "allowed"), set: (r, v) => setConstr(r, "urlConstraints", "allowed", v) },
|
|
2441
|
-
{ label: "URL deny", kind: "text", get: (r) => constr(r, "urlConstraints", "denied"), set: (r, v) => setConstr(r, "urlConstraints", "denied", v) }
|
|
2495
|
+
{ label: "Match", kind: "text", get: cValue, set: setCValue }
|
|
2442
2496
|
];
|
|
2443
2497
|
function ruleSummary(r) {
|
|
2444
2498
|
const bits = [];
|
|
@@ -2466,6 +2520,7 @@ function PoliciesPanel({ focused }) {
|
|
|
2466
2520
|
const [editing, setEditing] = useState4(false);
|
|
2467
2521
|
const [editVal, setEditVal] = useState4("");
|
|
2468
2522
|
const [status, setStatus] = useState4(null);
|
|
2523
|
+
const [pendingDel, setPendingDel] = useState4(null);
|
|
2469
2524
|
const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
|
|
2470
2525
|
const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
|
|
2471
2526
|
useEffect4(() => {
|
|
@@ -2488,6 +2543,11 @@ function PoliciesPanel({ focused }) {
|
|
|
2488
2543
|
};
|
|
2489
2544
|
const save = async () => {
|
|
2490
2545
|
if (!selected || !detail.data) return;
|
|
2546
|
+
const blanket = rules.findIndex(isBlanketRule);
|
|
2547
|
+
if (blanket !== -1) {
|
|
2548
|
+
setStatus(`\u2717 rule ${blanket + 1} matches EVERYTHING \u2014 pick a Constraint + Match value, or narrow Permissions`);
|
|
2549
|
+
return;
|
|
2550
|
+
}
|
|
2491
2551
|
setStatus("Saving\u2026");
|
|
2492
2552
|
try {
|
|
2493
2553
|
const res = await api.policies.update(selected.id, {
|
|
@@ -2536,9 +2596,13 @@ function PoliciesPanel({ focused }) {
|
|
|
2536
2596
|
return;
|
|
2537
2597
|
}
|
|
2538
2598
|
if (view === "list") {
|
|
2539
|
-
if (key.upArrow)
|
|
2540
|
-
|
|
2541
|
-
|
|
2599
|
+
if (key.upArrow) {
|
|
2600
|
+
setPendingDel(null);
|
|
2601
|
+
setPi((n) => Math.max(0, n - 1));
|
|
2602
|
+
} else if (key.downArrow) {
|
|
2603
|
+
setPendingDel(null);
|
|
2604
|
+
setPi((n) => Math.min(policies.length - 1, n + 1));
|
|
2605
|
+
} else if (key.return || key.rightArrow) {
|
|
2542
2606
|
setStatus(null);
|
|
2543
2607
|
setView("rules");
|
|
2544
2608
|
} else if (input === "a") {
|
|
@@ -2558,6 +2622,22 @@ function PoliciesPanel({ focused }) {
|
|
|
2558
2622
|
setStatus("\u2713 active policy: NONE \u2014 no rules enforced, w/b grants are refused");
|
|
2559
2623
|
activeQ.reload();
|
|
2560
2624
|
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
2625
|
+
} else if (input === "d") {
|
|
2626
|
+
if (!selected) return;
|
|
2627
|
+
if (pendingDel !== selected.id) {
|
|
2628
|
+
setPendingDel(selected.id);
|
|
2629
|
+
setStatus(`\u26A0 d again to DELETE policy "${selected.name}" \u2014 cannot be undone`);
|
|
2630
|
+
return;
|
|
2631
|
+
}
|
|
2632
|
+
setPendingDel(null);
|
|
2633
|
+
setStatus("Deleting\u2026");
|
|
2634
|
+
const name = selected.name;
|
|
2635
|
+
void api.policies.remove(selected.id).then(() => {
|
|
2636
|
+
setStatus(`\u2713 deleted policy "${name}"`);
|
|
2637
|
+
setPi(0);
|
|
2638
|
+
list5.reload();
|
|
2639
|
+
activeQ.reload();
|
|
2640
|
+
}).catch((e) => setStatus("\u2717 " + (e instanceof Error ? e.message : String(e))));
|
|
2561
2641
|
}
|
|
2562
2642
|
return;
|
|
2563
2643
|
}
|
|
@@ -2573,7 +2653,7 @@ function PoliciesPanel({ focused }) {
|
|
|
2573
2653
|
} else if (input === " ") {
|
|
2574
2654
|
if (rules[ri]) mutate(rules.map((r, i) => i === ri ? { ...r, enabled: !r.enabled } : r));
|
|
2575
2655
|
} else if (input === "e") {
|
|
2576
|
-
if (rules[ri]) mutate(rules.map((r, i) => i === ri ?
|
|
2656
|
+
if (rules[ri]) mutate(rules.map((r, i) => i === ri ? migrateEffect(r, r.effect === "ALLOW" ? "DENY" : "ALLOW") : r));
|
|
2577
2657
|
} else if (input === "d") {
|
|
2578
2658
|
if (rules[ri]) {
|
|
2579
2659
|
const next = rules.filter((_, i) => i !== ri);
|
|
@@ -2604,9 +2684,16 @@ function PoliciesPanel({ focused }) {
|
|
|
2604
2684
|
else if (key.upArrow) setFi((n) => Math.max(0, n - 1));
|
|
2605
2685
|
else if (key.downArrow) setFi((n) => Math.min(FIELDS.length - 1, n + 1));
|
|
2606
2686
|
else if (field.kind === "effect" && (input === " " || key.rightArrow)) {
|
|
2607
|
-
mutate(rules.map((r, i) => i === ri ?
|
|
2687
|
+
mutate(rules.map((r, i) => i === ri ? migrateEffect(r, r.effect === "ALLOW" ? "DENY" : "ALLOW") : r));
|
|
2608
2688
|
} else if (field.kind === "enabled" && (input === " " || key.rightArrow)) {
|
|
2609
2689
|
mutate(rules.map((r, i) => i === ri ? { ...r, enabled: !r.enabled } : r));
|
|
2690
|
+
} else if (field.kind === "ctype" && (input === " " || key.rightArrow || key.leftArrow)) {
|
|
2691
|
+
const dir = key.leftArrow ? -1 : 1;
|
|
2692
|
+
const nextT = CTYPES[(CTYPES.indexOf(currentCType(rule2)) + dir + CTYPES.length) % CTYPES.length];
|
|
2693
|
+
mutate(rules.map((r, i) => i === ri ? setCType(r, nextT) : r));
|
|
2694
|
+
} else if (field.kind === "perms" && (input === "r" || input === "w" || input === "e" || input === "n")) {
|
|
2695
|
+
const p = { r: "READ", w: "WRITE", e: "EXECUTE", n: "NETWORK" }[input];
|
|
2696
|
+
mutate(rules.map((rr, i) => i === ri ? togglePerm(rr, p) : rr));
|
|
2610
2697
|
} else if (field.kind === "priority" && (key.rightArrow || key.leftArrow)) {
|
|
2611
2698
|
const d = key.rightArrow ? 1 : -1;
|
|
2612
2699
|
mutate(rules.map((r, i) => i === ri ? { ...r, priority: Math.max(0, r.priority + d) } : r));
|
|
@@ -2636,7 +2723,7 @@ function PoliciesPanel({ focused }) {
|
|
|
2636
2723
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: activeBy ? ` (${activeBy})` : "" })
|
|
2637
2724
|
] }) : /* @__PURE__ */ jsx4(Text4, { color: theme.bad, bold: true, children: "\u25CB NONE \u2014 nothing enforced, grants refused" })
|
|
2638
2725
|
] }),
|
|
2639
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 n new
|
|
2726
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, wrap: "truncate", children: focused ? `\u2191\u2193 select \xB7 enter open \xB7 n new \xB7 a activate \xB7 x deactivate \xB7 d delete \xB7 ^R refresh${lAbove ? ` \xB7 \u25B2${lAbove}` : ""}${lBelow ? ` \xB7 \u25BC${lBelow}` : ""}` : "press \u2192 to browse" }),
|
|
2640
2727
|
creating !== null ? /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
2641
2728
|
/* @__PURE__ */ jsx4(Text4, { color: theme.warn, children: "new policy name: " }),
|
|
2642
2729
|
/* @__PURE__ */ jsx4(TextInput3, { value: creating, onChange: setCreating, onSubmit: commitNewPolicy })
|
|
@@ -2711,7 +2798,7 @@ function PoliciesPanel({ focused }) {
|
|
|
2711
2798
|
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: rule?.id ?? "" }),
|
|
2712
2799
|
dirtyTag
|
|
2713
2800
|
] }),
|
|
2714
|
-
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit text \xB7 space/\u2192 toggle \xB7 s save \xB7 \u2190 back" }),
|
|
2801
|
+
/* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit text \xB7 space/\u2192 toggle \xB7 r/w/e/n perms \xB7 s save \xB7 \u2190 back" }),
|
|
2715
2802
|
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: FIELDS.map((f, i) => {
|
|
2716
2803
|
const val = rule ? f.get(rule) : "";
|
|
2717
2804
|
const active2 = i === fi;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solongate/proxy",
|
|
3
|
-
"version": "0.82.
|
|
3
|
+
"version": "0.82.49",
|
|
4
4
|
"description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|