Merge pull request 'fix: clarify blocked security events' (#29) from dev into main
Deploy Dashboard / deploy (push) Successful in 48s
Deploy Dashboard / deploy (push) Successful in 48s
This commit was merged in pull request #29.
This commit is contained in:
@@ -16,6 +16,7 @@ RUN apt-get update \
|
|||||||
python3 \
|
python3 \
|
||||||
ripgrep \
|
ripgrep \
|
||||||
rsync \
|
rsync \
|
||||||
|
tmux \
|
||||||
unzip \
|
unzip \
|
||||||
wget \
|
wget \
|
||||||
zip \
|
zip \
|
||||||
@@ -31,20 +32,22 @@ RUN npm install -g @anthropic-ai/claude-code
|
|||||||
|
|
||||||
RUN python3 - <<'PY'
|
RUN python3 - <<'PY'
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
path = Path("/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js")
|
path = Path("/usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js")
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
raise SystemExit(f"claude cli not found: {path}")
|
raise SystemExit(f"claude cli not found: {path}")
|
||||||
|
|
||||||
content = path.read_text()
|
content = path.read_text()
|
||||||
old = 'F8.get("https://api.anthropic.com/api/hello",{headers:K8($)}).catch((()=>!1))'
|
pattern = r'let A=U7\(\),q=new URL\(A\.TOKEN_URL\),K=\[`\$\{A\.BASE_API_URL\}/api/hello`,`\$\{q\.origin\}/v1/oauth/hello`\],Y=async\(_\)=>\{try\{let \$=await I8\.get\(_,\{headers:\{"User-Agent":ey\(\)\}\}\);if\(\$\.status!==200\)return\{success:!1,error:`Failed to connect to \$\{new URL\(_\)\.hostname\}: Status \$\{\$\.status\}`\};return\{success:!0\}\}catch\(\$\)\{'
|
||||||
if old not in content:
|
replacement = 'return'
|
||||||
|
patched, count = re.subn(pattern, replacement, content, count=1)
|
||||||
|
if count != 1:
|
||||||
raise SystemExit("preflight patch target not found in claude cli; refusing to build")
|
raise SystemExit("preflight patch target not found in claude cli; refusing to build")
|
||||||
|
|
||||||
patched = content.replace(old, "!0")
|
|
||||||
path.write_text(patched)
|
path.write_text(patched)
|
||||||
|
|
||||||
if old in path.read_text():
|
if re.search(pattern, path.read_text()):
|
||||||
raise SystemExit("preflight patch did not apply cleanly")
|
raise SystemExit("preflight patch did not apply cleanly")
|
||||||
|
|
||||||
print("Applied Claude preflight bypass patch")
|
print("Applied Claude preflight bypass patch")
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ rsync
|
|||||||
zip
|
zip
|
||||||
unzip
|
unzip
|
||||||
make
|
make
|
||||||
|
tmux
|
||||||
claude
|
claude
|
||||||
|
|||||||
@@ -16,6 +16,21 @@
|
|||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { getToken, checkAuth, setToken, setRefreshToken, currentUser, setCurrentUser, getPreferences, savePreferences } from "./lib/api.js";
|
import { getToken, checkAuth, setToken, setRefreshToken, currentUser, setCurrentUser, getPreferences, savePreferences } from "./lib/api.js";
|
||||||
|
|
||||||
|
const KNOWN_PAGES = new Set([
|
||||||
|
"dashboard",
|
||||||
|
"docker",
|
||||||
|
"gitea",
|
||||||
|
"files",
|
||||||
|
"terminal",
|
||||||
|
"openclaw",
|
||||||
|
"chat-digest",
|
||||||
|
"settings",
|
||||||
|
"security",
|
||||||
|
"litellm",
|
||||||
|
"cc-connect",
|
||||||
|
"info-engine",
|
||||||
|
]);
|
||||||
|
|
||||||
let page = $state("dashboard");
|
let page = $state("dashboard");
|
||||||
let dark = $state(false);
|
let dark = $state(false);
|
||||||
let sidebarOpen = $state(false);
|
let sidebarOpen = $state(false);
|
||||||
@@ -27,6 +42,26 @@
|
|||||||
let sidebarOrder = $state(null);
|
let sidebarOrder = $state(null);
|
||||||
let orderSaveTimer = null;
|
let orderSaveTimer = null;
|
||||||
|
|
||||||
|
function getRequestedPage() {
|
||||||
|
const requestedPage = new URLSearchParams(window.location.search).get("page");
|
||||||
|
return KNOWN_PAGES.has(requestedPage) ? requestedPage : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canOpenPage(pageId) {
|
||||||
|
if (!pageId || !KNOWN_PAGES.has(pageId)) return false;
|
||||||
|
if (pageId === "settings") return userRole === "admin";
|
||||||
|
if (["litellm", "cc-connect", "info-engine"].includes(pageId)) return hasPageAccess("dashboard");
|
||||||
|
return hasPageAccess(pageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncPageQuery(pageId) {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
if (pageId === "dashboard") url.searchParams.delete("page");
|
||||||
|
else url.searchParams.set("page", pageId);
|
||||||
|
if (pageId !== "terminal") url.searchParams.delete("host");
|
||||||
|
history.replaceState({}, "", `${url.pathname}${url.search}${url.hash}`);
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchUserInfo() {
|
async function fetchUserInfo() {
|
||||||
try {
|
try {
|
||||||
const data = await checkAuth();
|
const data = await checkAuth();
|
||||||
@@ -78,6 +113,8 @@
|
|||||||
setRefreshToken(data.refresh_token);
|
setRefreshToken(data.refresh_token);
|
||||||
authorized = true;
|
authorized = true;
|
||||||
await fetchUserInfo();
|
await fetchUserInfo();
|
||||||
|
const requestedPage = getRequestedPage();
|
||||||
|
if (canOpenPage(requestedPage)) page = requestedPage;
|
||||||
loading = false;
|
loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -96,6 +133,8 @@
|
|||||||
try {
|
try {
|
||||||
await fetchUserInfo();
|
await fetchUserInfo();
|
||||||
authorized = true;
|
authorized = true;
|
||||||
|
const requestedPage = getRequestedPage();
|
||||||
|
if (canOpenPage(requestedPage)) page = requestedPage;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Auth check failed:", e);
|
console.error("Auth check failed:", e);
|
||||||
setToken("");
|
setToken("");
|
||||||
@@ -105,6 +144,11 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (!authorized || loading || !canOpenPage(page)) return;
|
||||||
|
syncPageQuery(page);
|
||||||
|
});
|
||||||
|
|
||||||
function toggleTheme() {
|
function toggleTheme() {
|
||||||
dark = !dark;
|
dark = !dark;
|
||||||
if (dark) {
|
if (dark) {
|
||||||
|
|||||||
Reference in New Issue
Block a user