GitGram — admin.php — GitGram
TaskGram / main / v1.00 / admin.php11,306 B↓ Raw
<?php
declare(strict_types=1);

require_once 'includes/config.php';
require_once 'includes/functions.php';

$user = require_login();

if (!is_admin($user)) {
    flash('error', 'Access denied.');
    redirect('dashboard.php');
}

/* ── Handle POST actions ──────────────────────────────────────── */
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!verify_csrf()) {
        flash('error', 'Invalid request token.');
        redirect('admin.php');
    }

    $action = $_POST['action'] ?? '';

    if ($action === 'save_footer') {
        $text = trim($_POST['footer_text'] ?? '');
        if ($text === '') $text = DEFAULT_FOOTER_TEXT;
        $cfg               = get_site_config();
        $cfg['footer_text'] = $text;
        save_site_config($cfg);
        flash('success', 'Footer text saved.');
        redirect('admin.php');
    }

    if ($action === 'reset_footer') {
        $cfg               = get_site_config();
        $cfg['footer_text'] = DEFAULT_FOOTER_TEXT;
        save_site_config($cfg);
        flash('success', 'Footer text reset to default.');
        redirect('admin.php');
    }

    if ($action === 'upload_og_logo') {
        init_uploads();
        $file = $_FILES['og_logo'] ?? null;
        if (!$file || $file['error'] === UPLOAD_ERR_NO_FILE) {
            flash('error', 'No file selected.');
        } else {
            $filename = save_uploaded_image($file, UPLOADS_DIR, 'og_logo');
            if ($filename === false) {
                flash('error', 'Upload failed. Use JPG, PNG, GIF or WebP, max 2 MB.');
            } else {
                $cfg = get_site_config();
                $cfg['og_logo'] = $filename;
                save_site_config($cfg);
                flash('success', 'OG logo updated.');
            }
        }
        redirect('admin.php');
    }

    if ($action === 'remove_og_logo') {
        delete_upload(UPLOADS_DIR, 'og_logo');
        $cfg = get_site_config();
        unset($cfg['og_logo']);
        save_site_config($cfg);
        flash('success', 'OG logo removed.');
        redirect('admin.php');
    }

    if ($action === 'toggle_admin') {
        $target = strtolower(trim($_POST['target_user'] ?? ''));
        if ($target === $user['username']) {
            flash('error', 'You cannot remove your own admin status.');
        } elseif ($target !== '') {
            $tfile   = USERS_DIR . '/' . $target . '/profile.json';
            $tprofile = read_json($tfile);
            if ($tprofile) {
                $tprofile['admin'] = !($tprofile['admin'] ?? false);
                save_json($tfile, $tprofile);
                $state = $tprofile['admin'] ? 'granted' : 'revoked';
                flash('success', "Admin access $state for @$target.");
            }
        }
        redirect('admin.php');
    }
}

/* ── Load data ────────────────────────────────────────────────── */
$cfg   = get_site_config();
$users = read_json(USERS_INDEX);
ksort($users);

$page_title = 'Site Settings';
require_once 'includes/header.php';
?>

<div class="page-wrap" style="max-width:700px; margin-top:12px; margin-bottom:16px;">

    <!-- ── OG Logo ────────────────────────────────────────── -->
    <div class="window">
        <div class="window-title"><span>&#128247; OG / Share Logo</span></div>
        <div class="window-body">
            <p style="font-size:12px; color:var(--chrome-darker); margin-bottom:10px;">
                This image appears when TaskGram links are shared on social media (Open Graph).
                Recommended: 1200&times;630 px, JPG or PNG.
            </p>

            <?php $og_logo_url = get_og_logo_url(); ?>
            <?php if ($og_logo_url !== ''): ?>
            <div style="margin-bottom:10px; display:flex; align-items:flex-start; gap:12px;">
                <img src="<?= h($og_logo_url) ?>" alt="OG Logo"
                     style="max-width:200px; max-height:100px; object-fit:contain;
                            border-top:2px solid var(--chrome-light);
                            border-left:2px solid var(--chrome-light);
                            border-bottom:2px solid var(--chrome-darker);
                            border-right:2px solid var(--chrome-darker);">
                <form method="post" action="admin.php">
                    <?= csrf_field() ?>
                    <input type="hidden" name="action" value="remove_og_logo">
                    <button type="submit" class="btn btn-sm btn-danger">Remove Logo</button>
                </form>
            </div>
            <?php else: ?>
            <p style="font-size:12px; color:var(--chrome-dark); margin-bottom:8px;">No logo uploaded yet.</p>
            <?php endif; ?>

            <form method="post" action="admin.php" enctype="multipart/form-data">
                <?= csrf_field() ?>
                <input type="hidden" name="action" value="upload_og_logo">
                <div class="form-row-inline" style="margin:0;">
                    <div class="stretch">
                        <input type="file" name="og_logo"
                               accept=".jpg,.jpeg,.png,.gif,.webp,image/*"
                               style="border:none; background:transparent; padding:2px 0; width:100%;">
                    </div>
                    <div>
                        <button type="submit" class="btn btn-primary btn-sm">Upload</button>
                    </div>
                </div>
            </form>
        </div>
    </div>

    <!-- ── Footer text ────────────────────────────────────── -->
    <div class="window">
        <div class="window-title"><span>&#9881; Site Settings — Footer Text</span></div>
        <div class="window-body">

            <div class="form-row" style="margin-bottom:10px;">
                <div style="font-size:12px; color:var(--chrome-darker); margin-bottom:6px;">
                    Use <code style="background:#FFF;border:1px solid #999;padding:1px 4px;">{year}</code>
                    to insert the current year automatically.
                </div>
                <div style="padding:6px 8px; background:#FFF;
                    border-top:2px solid var(--chrome-dark);
                    border-left:2px solid var(--chrome-dark);
                    border-bottom:2px solid var(--chrome-light);
                    border-right:2px solid var(--chrome-light);
                    font-size:12px; color:var(--chrome-darker); margin-bottom:8px;">
                    Preview: <strong><?= h(get_footer_text()) ?></strong>
                </div>
            </div>

            <form method="post" action="admin.php">
                <?= csrf_field() ?>
                <input type="hidden" name="action" value="save_footer">
                <div class="form-row">
                    <label for="footer_text">Footer Text</label>
                    <input type="text" id="footer_text" name="footer_text"
                           value="<?= h($cfg['footer_text'] ?? DEFAULT_FOOTER_TEXT) ?>"
                           maxlength="256">
                </div>
                <div class="d-flex gap-6 mt-6">
                    <button type="submit" class="btn btn-primary">Save Footer</button>
                </div>
            </form>

            <div class="sep"></div>

            <form method="post" action="admin.php">
                <?= csrf_field() ?>
                <input type="hidden" name="action" value="reset_footer">
                <button type="submit" class="btn btn-sm"
                        title="Restore to default text">Reset to Default</button>
                <span style="font-size:11px; color:var(--chrome-dark); margin-left:6px;">
                    Default: <?= h(str_replace('{year}', date('Y'), DEFAULT_FOOTER_TEXT)) ?>
                </span>
            </form>

        </div>
    </div>

    <!-- ── User admin management ──────────────────────────── -->
    <div class="window mt-10">
        <div class="window-title">
            <span>&#128100; User Management</span>
            <span style="font-size:11px;opacity:.8;"><?= count($users) ?> user<?= count($users) !== 1 ? 's' : '' ?></span>
        </div>
        <div class="window-body" style="padding:0;">
            <table>
                <thead>
                    <tr>
                        <th>Username</th>
                        <th>Display Name</th>
                        <th>Joined</th>
                        <th>Role</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($users as $uname => $udata):
                        $uprofile = read_json(USERS_DIR . '/' . $uname . '/profile.json');
                        $uadmin   = !empty($uprofile['admin']);
                        $is_self  = $uname === $user['username'];
                    ?>
                    <tr>
                        <td>
                            <a href="profile.php?user=<?= h($uname) ?>"
                               style="color:var(--title-start);text-decoration:none;">@<?= h($uname) ?></a>
                        </td>
                        <td><?= h($udata['display_name'] ?? $uname) ?></td>
                        <td style="white-space:nowrap; font-size:11px;">
                            <?= date('d M Y', strtotime($udata['created'] ?? '')) ?>
                        </td>
                        <td>
                            <?php if ($uadmin): ?>
                                <span style="color:var(--title-start); font-weight:bold; font-size:11px;">&#9733; Admin</span>
                            <?php else: ?>
                                <span style="font-size:11px; color:var(--chrome-dark);">User</span>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if (!$is_self): ?>
                            <form method="post" action="admin.php" style="display:inline;">
                                <?= csrf_field() ?>
                                <input type="hidden" name="action"      value="toggle_admin">
                                <input type="hidden" name="target_user" value="<?= h($uname) ?>">
                                <button type="submit" class="btn btn-sm <?= $uadmin ? 'btn-danger' : '' ?>">
                                    <?= $uadmin ? 'Revoke Admin' : 'Grant Admin' ?>
                                </button>
                            </form>
                            <?php else: ?>
                                <span style="font-size:11px; color:var(--chrome-dark);">(you)</span>
                            <?php endif; ?>
                        </td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    </div>

</div>

<?php require_once 'includes/footer.php'; ?>
Ready
GitGram