THE ACTUAL CAUSE of "codegit is just a black box". Sections 4 and 5 were real bugs but
neither was it; this is.
CHAIN
1. install/process.php stores a RELATIVE folder name -> projects.db {"Blog":"blog"}
2. common.php::loadState() does $projectPath = reset($projectList) -> "blog", and
SESSION("projectPath","blog") PERSISTS it, so the bad value sticks across logins
3. filetree puts it straight into the DOM: <a id="project-root" data-path="blog">
4. codegit sends repo="blog"; getWorkspacePath("blog") fails checkPath() ->
traits/path.php:67 Common::send(403, "Client does not have access.")
5. modal.js SILENTLY discards it:
settled: function(reply,status){ if (status !== 200) return; ... }
No toast, no console error, #content left empty.
That last step is why it presents as an empty black dialog rather than an error - the request
fails and nothing reports it. Which is exactly why it survived the CSS fixes.
PINNED DOWN BY CAPTURING THE REAL REQUEST, not by reading CSS:
POST /dialog.php {"target":"codegit","action":"codegit","repo":"blog"} -> 403
#content innerHTML length: 0
getWorkspacePath("blog") -> 403
projects store -> {"Blog":"blog"}
FIX (scripts/fix-project-path.sh) - both parts required:
A. resolve the path in loadState and re-store it, which also HEALS sessions already
holding the relative value (and re-persists so it stays healed)
B. make the projects store absolute, so array_search() can still map path -> name for
the tree label. Fixing only (A) would silently break the label: the path would resolve
but array_search would return false and the tree would show an empty project name.
VERIFIED from a deliberately poisoned session ("blog"): it self-heals to the absolute path,
dialog returns 200, #content fills with 1758 chars. An EXISTING browser session heals on its
next page load - no hard refresh or re-login needed.
Tests: 47 passed, 0 failed, 1 accepted-risk
+ projects store must hold an absolute path
+ loadState must resolve a relative projectPath
Also marks section 4 as superseded so a future reader doesn't stop at the CSS explanation.
71 lines
3.8 KiB
Bash
71 lines
3.8 KiB
Bash
#!/bin/sh
|
|
# Fix: dialogs (CodeGit, Macro, Market, Settings) rendered EMPTY.
|
|
#
|
|
# Root cause: the project was registered with a RELATIVE path, and the UI used it verbatim.
|
|
#
|
|
# 1. install/process.php stores a relative folder name: projects.db -> {"Blog": "blog"}
|
|
# 2. common.php::loadState() does $projectPath = reset($projectList) -> "blog"
|
|
# and persists it to the session, so the bad value STICKS.
|
|
# 3. filetree puts it straight into the DOM: <a id="project-root" data-path="blog">
|
|
# 4. codegit sends repo="blog"; getWorkspacePath("blog") fails checkPath() -> 403
|
|
# 5. modal.js does `if (status !== 200) return;` -> SWALLOWS the error -> #content stays empty
|
|
#
|
|
# That last step is why it presents as an empty/black dialog rather than an error: the request
|
|
# fails, nothing is rendered, and nothing is reported.
|
|
#
|
|
# Atheos's own project-creation code resolves relative -> WORKSPACE/<name>, so a relative value in
|
|
# the store is legitimate - loadState() simply fails to resolve it. Both fixes are needed:
|
|
# A. resolve at load time (this also heals sessions already holding the relative value)
|
|
# B. store absolute paths, so array_search() can still map path -> name for the tree label
|
|
#
|
|
# Usage: run ON the guest as root. Idempotent.
|
|
set -e
|
|
A=/var/www/atheos
|
|
|
|
echo "=== A. resolve a relative projectPath in loadState() ==="
|
|
S=$A/common.php
|
|
if [ ! -f "$S" ]; then echo " !! $S not found"; exit 1; fi
|
|
if grep -q 'isAbsPath($projectPath)' "$S"; then
|
|
echo " already applied"
|
|
else
|
|
[ -f "$S.orig" ] || cp -a "$S" "$S.orig"
|
|
php83 -r '
|
|
$f=$argv[1]; $s=file_get_contents($f);
|
|
$old = " \$openFiles_db = Common::getObjStore(\"activeFiles\", \"users/\" . \$activeUser);";
|
|
if (strpos($s,$old) === false) { fwrite(STDERR," !! anchor not found in loadState\n"); exit(1); }
|
|
$new = " // A project may be registered with a RELATIVE folder name (the installer stores it\n // that way). Handing that to the UI yields data-path=\"blog\", and every later\n // getWorkspacePath() call then fails its access check with 403 - which the modal\n // silently swallows, leaving the dialog empty. Resolve it once here, and re-store it\n // so sessions already holding the relative value heal on their next load.\n if (!Common::isAbsPath(\$projectPath)) {\n \$projectPath = Common::getWorkspacePath(\$projectPath, true);\n SESSION(\"projectPath\", \$projectPath);\n }\n\n" . $old;
|
|
file_put_contents($f, str_replace($old,$new,$s)); echo " patched loadState\n";' "$S"
|
|
php83 -l "$S" >/dev/null 2>&1 || { echo " !! SYNTAX ERROR - restore $S.orig"; exit 1; }
|
|
fi
|
|
|
|
echo "=== B. store absolute paths in the projects store ==="
|
|
P=$A/data/projects.db.json.php
|
|
if [ ! -f "$P" ]; then
|
|
echo " !! $P not found"
|
|
elif grep -q '"\/' "$P"; then
|
|
echo " already absolute"
|
|
else
|
|
cp -a "$P" "$P.bak-$(date +%Y%m%d-%H%M%S)"
|
|
php83 -r '
|
|
$f=$argv[1]; $ws="/var/www/atheos/workspace";
|
|
$raw=file_get_contents($f);
|
|
preg_match("/<\?php\/\*\|(.*)\|\*\/\?>/s",$raw,$m);
|
|
$d=json_decode($m[1],true);
|
|
if(!is_array($d)){ fwrite(STDERR," !! store unreadable\n"); exit(1); }
|
|
$c=false;
|
|
foreach($d as $n=>$p){ if(!preg_match("#^(/|[A-Za-z]:)#",$p)){ $d[$n]=$ws."/".ltrim($p,"/"); $c=true; } }
|
|
if(!$c){ echo " already absolute\n"; exit(0); }
|
|
file_put_contents($f,"<?php/*|\n".json_encode($d, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)."\n|*/?>");
|
|
echo " store rewritten -> ".json_encode($d)."\n";' "$P"
|
|
chown atheos:atheos "$P" 2>/dev/null || true
|
|
fi
|
|
|
|
echo "=== verify ==="
|
|
php83 -r '
|
|
$raw=file_get_contents("/var/www/atheos/data/projects.db.json.php");
|
|
preg_match("/<\?php\/\*\|(.*)\|\*\/\?>/s",$raw,$m); $d=json_decode($m[1],true);
|
|
$p=reset($d); $n=array_search($p,$d);
|
|
printf(" path=%s name=%s\n",$p,var_export($n,true));
|
|
printf(" absolute: %s\n", preg_match("#^(/|[A-Za-z]:)#",$p) ? "yes" : "NO");' 2>&1
|
|
echo "=== done ==="
|