rootPath); $stats = null; if ($setup->isInstalled() && $this->database->isConfigured()) { try { $pdo = $this->database->pdo(); $stats = [ 'tenants' => (int) $pdo->query('SELECT COUNT(*) FROM tenants')->fetchColumn(), 'members' => (int) $pdo->query('SELECT COUNT(*) FROM members')->fetchColumn(), 'events' => (int) $pdo->query('SELECT COUNT(*) FROM consumption_events')->fetchColumn(), ]; } catch (\Throwable) { $stats = null; } } $this->view->render('home/index', [ 'title' => 'Kaffeekasse fuer Teams, Vereine und Coworking', 'setupComplete' => $setup->isInstalled(), 'stats' => $stats, ]); } public function installForm(): void { $setup = new SetupService($this->rootPath); if ($setup->isInstalled()) { Response::redirect('/admin/login'); } $this->view->render('install/index', [ 'title' => 'Installation', ]); } public function installSubmit(): void { $this->assertCsrf(); $setup = new SetupService($this->rootPath); try { $setup->install($_POST); $this->session->flash('success', 'Die Installation wurde abgeschlossen. Jetzt kannst du dich als Plattform-Admin anmelden.'); Response::redirect('/admin/login'); } catch (\Throwable $throwable) { remember_old_input($_POST); $this->session->flash('error', $throwable->getMessage()); Response::redirect('/install'); } } public function registerForm(): void { if (!(new SetupService($this->rootPath))->isInstalled()) { Response::redirect('/install'); } $this->view->render('home/register', [ 'title' => 'Mandant registrieren', ]); } public function registerSubmit(): void { $this->assertCsrf(); try { $pdo = $this->database->pdo(); $audit = new AuditService($pdo); $service = new TenantRegistrationService($pdo, $audit); $slug = $service->register($_POST); $this->session->flash('success', 'Dein Mandant wurde angelegt. Du kannst dich jetzt anmelden.'); Response::redirect('/t/' . rawurlencode($slug) . '/login'); } catch (\Throwable $throwable) { remember_old_input($_POST); $this->session->flash('error', $throwable->getMessage()); Response::redirect('/register'); } } public function adminLoginForm(): void { $this->view->render('admin/login', [ 'title' => 'Plattform-Login', ]); } public function adminLoginSubmit(): void { $this->assertCsrf(); try { $pdo = $this->database->pdo(); $auth = new Auth($pdo, $this->session); $audit = new AuditService($pdo); $success = $auth->attemptPlatformLogin((string) ($_POST['email'] ?? ''), (string) ($_POST['password'] ?? '')); $audit->log(null, null, 'platform.login', 'user', null, $success ? 'success' : 'failure', [ 'email' => mb_strtolower(trim((string) ($_POST['email'] ?? ''))), ]); if (!$success) { throw new RuntimeException('Die Zugangsdaten konnten nicht verifiziert werden.'); } $this->session->flash('success', 'Willkommen im Plattformbereich.'); Response::redirect('/admin'); } catch (\Throwable $throwable) { remember_old_input($_POST); $this->session->flash('error', $throwable->getMessage()); Response::redirect('/admin/login'); } } public function adminDashboard(): void { $pdo = $this->database->pdo(); $auth = new Auth($pdo, $this->session); if (!$auth->checkPlatformAdmin()) { $this->session->flash('error', 'Bitte zuerst als Plattform-Admin anmelden.'); Response::redirect('/admin/login'); } $tenants = $pdo->query( 'SELECT t.*, COUNT(DISTINCT m.id) AS member_count, COUNT(DISTINCT p.id) AS product_count FROM tenants t LEFT JOIN members m ON m.tenant_id = t.id LEFT JOIN products p ON p.tenant_id = t.id GROUP BY t.id ORDER BY t.created_at DESC' )->fetchAll(); $this->view->render('admin/index', [ 'title' => 'Plattform-Dashboard', 'tenants' => $tenants, ]); } public function adminLogout(): void { $this->assertCsrf(); $pdo = $this->database->pdo(); $auth = new Auth($pdo, $this->session); $auth->logout(); $this->session->flash('success', 'Du wurdest aus dem Plattformbereich abgemeldet.'); Response::redirect('/admin/login'); } private function assertCsrf(): void { if (!request_origin_matches_host() || !$this->csrf->validate($_POST['_token'] ?? null)) { throw new RuntimeException('Die Anfrage konnte nicht bestaetigt werden. Bitte erneut versuchen.'); } } }