fix admin page

This commit is contained in:
Akurosia Kamo 2026-05-29 10:48:12 +02:00
parent 9cd3278b80
commit 0a47b126cf
2 changed files with 73 additions and 13 deletions

View File

@ -21,6 +21,8 @@ if (empty($_SESSION['admin_csrf'])) {
$_SESSION['admin_csrf'] = bin2hex(random_bytes(16)); $_SESSION['admin_csrf'] = bin2hex(random_bytes(16));
} }
$csrf = $_SESSION['admin_csrf']; $csrf = $_SESSION['admin_csrf'];
$returnPath = safe_return_path($_GET['return'] ?? null);
$adminAction = 'admin.php?return=' . rawurlencode($returnPath);
function admin_h(?string $value): string { function admin_h(?string $value): string {
return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
@ -68,6 +70,63 @@ function git_last_commit(): string {
return $out !== '' ? $out : '(unknown)'; return $out !== '' ? $out : '(unknown)';
} }
function git_current_branch(): string {
return git_output(['rev-parse', '--abbrev-ref', 'HEAD']);
}
function git_upstream_for_branch(string $branch): ?string {
$result = git_run(['rev-parse', '--abbrev-ref', $branch . '@{upstream}']);
return $result['code'] === 0 && $result['output'] !== '' ? $result['output'] : null;
}
function git_is_ancestor(string $ancestor, string $descendant): bool {
return git_run(['merge-base', '--is-ancestor', $ancestor, $descendant])['code'] === 0;
}
function git_pull_all_tracked_branches(): array {
$lines = [];
$exitCode = 0;
$fetch = git_run(['fetch', '--all', '--prune']);
$lines[] = '$ git fetch --all --prune';
$lines[] = $fetch['output'] ?: '(no output)';
if ($fetch['code'] !== 0) return ['code' => $fetch['code'], 'output' => implode("\n", $lines)];
$current = git_current_branch();
foreach (git_local_branches() as $branch) {
$upstream = git_upstream_for_branch($branch);
if ($upstream === null) {
$lines[] = '';
$lines[] = $branch . ': no upstream configured, skipped';
continue;
}
$lines[] = '';
$lines[] = $branch . ' <- ' . $upstream;
if ($branch === $current) {
$pull = git_run(['merge', '--ff-only', $upstream]);
$lines[] = '$ git merge --ff-only ' . $upstream;
$lines[] = $pull['output'] ?: '(no output)';
if ($pull['code'] !== 0) $exitCode = $pull['code'];
continue;
}
if (git_is_ancestor($branch, $upstream)) {
$update = git_run(['branch', '-f', $branch, $upstream]);
$lines[] = '$ git branch -f ' . $branch . ' ' . $upstream;
$lines[] = $update['output'] ?: '(fast-forwarded)';
if ($update['code'] !== 0) $exitCode = $update['code'];
} elseif (git_is_ancestor($upstream, $branch)) {
$lines[] = 'already up to date or ahead';
} else {
$lines[] = 'diverged, skipped';
if ($exitCode === 0) $exitCode = 1;
}
}
return ['code' => $exitCode, 'output' => implode("\n", $lines)];
}
function resolve_selected_branch_ref(string $ref, array $localBranches, array $remoteBranches, bool $preferLocalForRemote): ?string { function resolve_selected_branch_ref(string $ref, array $localBranches, array $remoteBranches, bool $preferLocalForRemote): ?string {
if (str_starts_with($ref, 'local:')) { if (str_starts_with($ref, 'local:')) {
$branch = substr($ref, 6); $branch = substr($ref, 6);
@ -94,11 +153,11 @@ if ($allowed && $_SERVER['REQUEST_METHOD'] === 'POST') {
} else { } else {
$action = $_POST['action'] ?? ''; $action = $_POST['action'] ?? '';
if ($action === 'fetch') { if ($action === 'fetch') {
$result = git_run(['fetch', '--prune']); $result = git_run(['fetch', '--all', '--prune']);
$message = 'git fetch --prune'; $message = 'git fetch --all --prune';
} elseif ($action === 'pull') { } elseif ($action === 'pull') {
$result = git_run(['pull', '--ff-only']); $result = git_pull_all_tracked_branches();
$message = 'git pull --ff-only'; $message = 'pull all tracked branches';
} elseif ($action === 'push') { } elseif ($action === 'push') {
$result = git_run(['push']); $result = git_run(['push']);
$message = 'git push'; $message = 'git push';
@ -118,6 +177,7 @@ if ($allowed && $_SERVER['REQUEST_METHOD'] === 'POST') {
} }
} elseif ($action === 'merge') { } elseif ($action === 'merge') {
$ref = trim((string)($_POST['merge_branch'] ?? '')); $ref = trim((string)($_POST['merge_branch'] ?? ''));
git_run(['fetch', '--all', '--prune']);
$localBranches = git_local_branches(); $localBranches = git_local_branches();
$remoteBranches = git_remote_branches(); $remoteBranches = git_remote_branches();
$branch = resolve_selected_branch_ref($ref, $localBranches, $remoteBranches, false); $branch = resolve_selected_branch_ref($ref, $localBranches, $remoteBranches, false);
@ -164,7 +224,7 @@ $branches = [];
$remoteBranches = []; $remoteBranches = [];
$lastCommit = ''; $lastCommit = '';
if ($allowed) { if ($allowed) {
$currentBranch = git_output(['rev-parse', '--abbrev-ref', 'HEAD']); $currentBranch = git_current_branch();
$status = git_output(['status', '-sb']); $status = git_output(['status', '-sb']);
$branches = git_local_branches(); $branches = git_local_branches();
$remoteBranches = git_remote_branches(); $remoteBranches = git_remote_branches();
@ -203,9 +263,9 @@ if ($allowed) {
<body> <body>
<div id="app"> <div id="app">
<header id="topbar"> <header id="topbar">
<a class="logo" href="index.php" style="text-decoration:none">REPORT VIEWER <span>Admin</span></a> <a class="logo" href="<?= admin_h($returnPath) ?>" style="text-decoration:none">REPORT VIEWER <span>Admin</span></a>
<div class="topbar-actions"> <div class="topbar-actions">
<a class="topbar-link" href="index.php">Back</a> <a class="topbar-link" href="<?= admin_h($returnPath) ?>">Back</a>
<div class="topbar-user"> <div class="topbar-user">
<?= $user ? admin_h($user['name'] ?: 'FFLogs User') . ' #' . admin_h($user['id']) : 'FFLogs user unavailable' ?> <?= $user ? admin_h($user['name'] ?: 'FFLogs User') . ' #' . admin_h($user['id']) : 'FFLogs user unavailable' ?>
</div> </div>
@ -242,14 +302,14 @@ if ($allowed) {
<div class="admin-grid section-gap"> <div class="admin-grid section-gap">
<div class="card"> <div class="card">
<div class="card-title">Aktionen</div> <div class="card-title">Aktionen</div>
<form method="post" class="admin-actions"> <form method="post" action="<?= admin_h($adminAction) ?>" class="admin-actions">
<input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>"> <input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>">
<button class="btn" name="action" value="fetch" type="submit">Fetch</button> <button class="btn" name="action" value="fetch" type="submit">Fetch</button>
<button class="btn btn-gold" name="action" value="pull" type="submit">Pull</button> <button class="btn btn-gold" name="action" value="pull" type="submit">Pull All</button>
<button class="btn" name="action" value="push" type="submit">Push</button> <button class="btn" name="action" value="push" type="submit">Push</button>
</form> </form>
<form method="post" class="admin-actions section-gap"> <form method="post" action="<?= admin_h($adminAction) ?>" class="admin-actions section-gap">
<input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>"> <input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>">
<input type="hidden" name="action" value="switch"> <input type="hidden" name="action" value="switch">
<div class="fg"> <div class="fg">
@ -274,7 +334,7 @@ if ($allowed) {
<button class="btn" type="submit">Switch</button> <button class="btn" type="submit">Switch</button>
</form> </form>
<form method="post" class="section-gap"> <form method="post" action="<?= admin_h($adminAction) ?>" class="section-gap">
<input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>"> <input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>">
<input type="hidden" name="action" value="commit"> <input type="hidden" name="action" value="commit">
<div class="fg"> <div class="fg">
@ -284,7 +344,7 @@ if ($allowed) {
<button class="btn btn-gold section-gap" type="submit">Commit all changes</button> <button class="btn btn-gold section-gap" type="submit">Commit all changes</button>
</form> </form>
<form method="post" class="admin-actions section-gap"> <form method="post" action="<?= admin_h($adminAction) ?>" class="admin-actions section-gap">
<input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>"> <input type="hidden" name="csrf" value="<?= admin_h($csrf) ?>">
<input type="hidden" name="action" value="merge"> <input type="hidden" name="action" value="merge">
<div class="fg"> <div class="fg">

View File

@ -8,7 +8,7 @@
<?php $fflogsUser = current_fflogs_user(); ?> <?php $fflogsUser = current_fflogs_user(); ?>
<div class="topbar-actions"> <div class="topbar-actions">
<?php if (is_admin_user()): ?> <?php if (is_admin_user()): ?>
<a class="topbar-link" href="admin.php">Admin</a> <a class="topbar-link" href="admin.php?return=<?= rawurlencode(current_return_path()) ?>">Admin</a>
<?php endif; ?> <?php endif; ?>
<div class="topbar-user"> <div class="topbar-user">
<?php if ($fflogsUser): ?> <?php if ($fflogsUser): ?>