view('register', [ 'title' => 'Zugriff beschränkt', 'valid' => false, 'errorMessage' => 'Die Registrierung auf dieser Plattform ist nur über einen persönlichen Einladungslink möglich.' ]); return; } $invitationModel = $this->model('Invitation'); $invitation = $invitationModel->getByToken($token); if (!$invitation) { $this->view('register', [ 'title' => 'Ungültiger Einladungslink', 'valid' => false, 'errorMessage' => 'Dieser Einladungslink ist leider ungültig, abgelaufen oder wurde bereits verwendet.' ]); return; } // Get modules assigned to this invitation $assignedModules = []; foreach ($invitation['assigned_projects'] as $slug) { $mod = ModuleService::getBySlug($slug); if ($mod) { $assignedModules[] = $mod; } } $this->view('register', [ 'title' => 'Account Registrierung', 'valid' => true, 'token' => $token, 'note' => $invitation['note'] ?? null, 'recipientEmail' => $invitation['recipient_email'] ?? null, 'assignedModules' => $assignedModules ]); } public function submit() { if ($_SERVER['REQUEST_METHOD'] !== 'POST') { header('Location: ' . Config::get('BASE_URL', '/')); exit; } $token = trim($_POST['token'] ?? $_POST['TOKEN'] ?? ''); $name = trim($_POST['name'] ?? ''); $email = trim(strtolower($_POST['email'] ?? '')); $password = $_POST['password'] ?? ''; $passwordConfirm = $_POST['password_confirm'] ?? ''; $redirectUrl = Config::get('BASE_URL', '/') . 'register?token=' . urlencode($token); try { Security::checkCsrf($_POST['csrf_token'] ?? ''); if (empty($token)) { throw new Exception('Einladungs-Token fehlt.'); } $invitationModel = $this->model('Invitation'); $invitation = $invitationModel->getByToken($token); if (!$invitation) { throw new Exception('Der Einladungslink ist ungültig oder abgelaufen.'); } // Enforce verified recipient email if invitation is personalized if (!empty($invitation['recipient_email'])) { if (strtolower($email) !== strtolower($invitation['recipient_email'])) { throw new Exception('Dieser Einladungslink ist personengebunden und gilt ausschließlich für ' . $invitation['recipient_email']); } } if (empty($name)) { throw new Exception('Bitte gib deinen Namen ein.'); } if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new Exception('Bitte gib eine gültige E-Mail-Adresse ein.'); } if (strlen($password) < 8) { throw new Exception('Das Passwort muss mindestens 8 Zeichen lang sein.'); } if ($password !== $passwordConfirm) { throw new Exception('Die eingegebenen Passwörter stimmen nicht überein.'); } // Check if user email already exists $userModel = $this->model('User'); $db = new Database(); $db->query("SELECT id FROM home_users WHERE email = :email"); $db->bind(':email', $email); if ($db->single()) { throw new Exception('Diese E-Mail-Adresse ist bereits registriert. Bitte melde dich an.'); } // Save new user $userData = [ 'name' => $name, 'email' => $email, 'password' => $password, 'projects' => implode(',', $invitation['assigned_projects'] ?? []), 'is_admin' => 0, 'status' => 'Active' ]; $userModel->save($userData); // Record token usage $invitationModel->recordUse($token); // Auto-login user session_regenerate_id(true); $_SESSION['user_email'] = $email; $_SESSION['user_projects'] = $invitation['assigned_projects'] ?? []; $_SESSION['is_admin'] = false; $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'] ?? ''; Flash::set('Willkommen, ' . htmlspecialchars($name) . '! Dein Account wurde erfolgreich eingerichtet.', 'success'); header('Location: ' . Config::get('BASE_URL', '/')); exit; } catch (Exception $e) { Flash::set($e->getMessage(), 'error'); header('Location: ' . $redirectUrl); exit; } } }