Initial Kaffeekasse SaaS restart
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Core\Auth;
|
||||
use App\Core\Csrf;
|
||||
use App\Core\Database;
|
||||
use App\Core\Response;
|
||||
use App\Core\Session;
|
||||
use App\Core\View;
|
||||
use App\Services\AuditService;
|
||||
use App\Services\SetupService;
|
||||
use App\Services\TenantRegistrationService;
|
||||
use RuntimeException;
|
||||
|
||||
final class PlatformController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly string $rootPath,
|
||||
private readonly array $config,
|
||||
private readonly Database $database,
|
||||
private readonly View $view,
|
||||
private readonly Session $session,
|
||||
private readonly Csrf $csrf
|
||||
) {
|
||||
}
|
||||
|
||||
public function home(): void
|
||||
{
|
||||
$setup = new SetupService($this->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.');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user