Webbserver - Love Blomberg

Show sourcecode

The following files exists in this folder. Click to view.

public_html/smartkortet/admin/

index.php
login.php
logout.php
statistik.php

index.php

194 lines UTF-8 Windows (CRLF)
<?php

declare(strict_types=1);

require_once 
__DIR__ '/../includes/functions.php';
startAppSession();

require_once 
__DIR__ '/../includes/auth.php';
require_once 
__DIR__ '/../config/database.php';

$admin requireAdminAuth();
$adminId = (int) $admin['id'];

if (
$_SERVER['REQUEST_METHOD'] === 'POST') {
    
verifyCsrf();
    
$action $_POST['action'] ?? '';

    if (
$action === 'toggle_admin') {
        
$targetId = (int) ($_POST['target_id'] ?? 0);

        if (
$targetId === $adminId) {
            
setFlash('error''Du kan inte ändra din egen adminroll här.');
            
redirect('/admin/index.php');
        }

        
$stmt db()->prepare('UPDATE users SET is_admin = CASE WHEN is_admin = 1 THEN 0 ELSE 1 END WHERE id = :id');
        
$stmt->execute(['id' => $targetId]);

        
setFlash('success''Adminroll uppdaterad.');
        
redirect('/admin/index.php');
    }

    if (
$action === 'reset_password') {
        
$targetId = (int) ($_POST['target_id'] ?? 0);
        
$newPassword $_POST['new_password'] ?? '';

        if (
mb_strlen($newPassword) < 8) {
            
setFlash('error''Nytt lösenord måste vara minst 8 tecken.');
            
redirect('/admin/index.php');
        }

        
$stmt db()->prepare('UPDATE users SET password_hash = :password_hash WHERE id = :id');
        
$stmt->execute([
            
'password_hash' => password_hash($newPasswordPASSWORD_DEFAULT),
            
'id' => $targetId,
        ]);

        
setFlash('success''Lösenord uppdaterat.');
        
redirect('/admin/index.php');
    }

    if (
$action === 'delete_user') {
        
$targetId = (int) ($_POST['target_id'] ?? 0);

        if (
$targetId === $adminId) {
            
setFlash('error''Du kan inte radera ditt eget konto.');
            
redirect('/admin/index.php');
        }

        
$stmt db()->prepare('DELETE FROM users WHERE id = :id');
        
$stmt->execute(['id' => $targetId]);

        
setFlash('success''Användare raderad.');
        
redirect('/admin/index.php');
    }
}

$flash getFlash();

$kpi = [
    
'users' => 0,
    
'admins' => 0,
    
'spend_entries' => 0,
    
'month_spent' => 0.0,
];

$kpi['users'] = (int) db()->query('SELECT COUNT(*) FROM users')->fetchColumn();
$kpi['admins'] = (int) db()->query('SELECT COUNT(*) FROM users WHERE is_admin = 1')->fetchColumn();
$kpi['spend_entries'] = (int) db()->query('SELECT COUNT(*) FROM spend_entries')->fetchColumn();
$kpi['month_spent'] = (float) db()->query('SELECT COALESCE(SUM(amount), 0) FROM spend_entries WHERE spent_on BETWEEN DATE_FORMAT(CURDATE(), "%Y-%m-01") AND LAST_DAY(CURDATE())')->fetchColumn();

$users db()->query('SELECT id, name, email, is_admin, created_at FROM users ORDER BY created_at DESC')->fetchAll();
?>
<!doctype html>
<html lang="sv">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
    <meta name="theme-color" content="#0b1220">
    <title>Admin Dashboard | Matkortet</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="<?= e(url('assets/css/style.css')) ?>">
</head>
<body data-theme="dark">
    <main class="app-shell">
        <header class="card panel topbar">
            <div>
                <h1>Admin Dashboard</h1>
                <p class="subtitle">Inloggad som <?= e($admin['name']) ?> (<?= e($admin['email']) ?>)</p>
            </div>
            <div class="admin-actions">
                <a class="btn btn-secondary" href="<?= e(url('index.php')) ?>">Till appen</a>
                <a class="btn btn-secondary" href="<?= e(url('database/createdb.php')) ?>">DB Console</a>
                <a class="btn btn-danger" href="<?= e(url('admin/logout.php')) ?>">Logga ut admin</a>
            </div>
        </header>

        <nav class="card panel admin-subnav">
            <a class="tab-link active" href="<?= e(url('admin/index.php')) ?>">Dashboard</a>
            <a class="tab-link" href="<?= e(url('admin/statistik.php')) ?>">Statistik</a>
        </nav>

        <?php if ($flash): ?>
            <div class="notice <?= e($flash['type']) ?>"><?= e($flash['message']) ?></div>
        <?php endif; ?>

        <section class="kpi-grid">
            <article class="card kpi">
                <span>Användare</span>
                <strong><?= e((string) $kpi['users']) ?></strong>
            </article>
            <article class="card kpi">
                <span>Admins</span>
                <strong><?= e((string) $kpi['admins']) ?></strong>
            </article>
            <article class="card kpi">
                <span>Transaktioner</span>
                <strong><?= e((string) $kpi['spend_entries']) ?></strong>
            </article>
            <article class="card kpi">
                <span>Spend denna månad</span>
                <strong><?= e(formatCurrency($kpi['month_spent'])) ?></strong>
            </article>
        </section>

        <section class="card panel" style="margin-top:16px;">
            <h3>Användarhantering</h3>
            <div class="admin-table-wrap">
                <table class="admin-table">
                    <thead>
                        <tr>
                            <th>ID</th>
                            <th>Namn</th>
                            <th>E-post</th>
                            <th>Roll</th>
                            <th>Skapad</th>
                            <th>Åtgärder</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($users as $u): ?>
                            <tr>
                                <td data-label="ID"><?= e((string) $u['id']) ?></td>
                                <td data-label="Namn"><?= e($u['name']) ?></td>
                                <td data-label="E-post"><?= e($u['email']) ?></td>
                                <td data-label="Roll"><?= ((int) $u['is_admin'] === 1) ? 'Admin' 'User' ?></td>
                                <td data-label="Skapad"><?= e((string) $u['created_at']) ?></td>
                                <td data-label="Åtgärder">
                                    <div class="admin-row-actions">
                                        <form method="post" class="inline-admin-form">
                                            <input type="hidden" name="csrf_token" value="<?= e(csrfToken()) ?>">
                                            <input type="hidden" name="action" value="toggle_admin">
                                            <input type="hidden" name="target_id" value="<?= e((string) $u['id']) ?>">
                                            <button class="btn btn-secondary" type="submit">Toggle Admin</button>
                                        </form>

                                        <form method="post" class="inline-admin-form">
                                            <input type="hidden" name="csrf_token" value="<?= e(csrfToken()) ?>">
                                            <input type="hidden" name="action" value="reset_password">
                                            <input type="hidden" name="target_id" value="<?= e((string) $u['id']) ?>">
                                            <input type="password" name="new_password" placeholder="Nytt lösenord" minlength="8" required>
                                            <button class="btn" type="submit">Reset</button>
                                        </form>

                                        <form method="post" class="inline-admin-form" onsubmit="return confirm('Radera användaren?');">
                                            <input type="hidden" name="csrf_token" value="<?= e(csrfToken()) ?>">
                                            <input type="hidden" name="action" value="delete_user">
                                            <input type="hidden" name="target_id" value="<?= e((string) $u['id']) ?>">
                                            <button class="btn btn-danger" type="submit">Radera</button>
                                        </form>
                                    </div>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        </section>
    </main>
</body>
</html>