Problem: Frontend JS bundle used credentials:'same-origin' which dropped cookies on cross-domain requests. Login worked (200) but the subsequent /auth/me check returned 401, leaving the user stuck on the login screen. Fix: - AuthController now sets a dtp_jwt HttpOnly cookie on login/refresh - Cookie uses Domain=.fahrschultermin.de (shared between frontend and api subdomain), Secure, SameSite=Lax, Max-Age=8h - JwtMiddleware reads JWT from Authorization header OR cookie - Added AuthController::me() endpoint (was missing, caused 500) - Logout endpoint clears the cookie - Frontend index.php patches fetch() to use credentials:'include' for all /api/v1/* calls
167 lines
5.1 KiB
PHP
Executable File
167 lines
5.1 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Repositories\StudentTenantRepository;
|
|
use App\Repositories\TenantRegistrationCodeRepository;
|
|
use App\Repositories\UserRepository;
|
|
use App\Support\Auth;
|
|
use App\Support\Request;
|
|
use App\Support\Response;
|
|
|
|
final class StudentAuthController
|
|
{
|
|
private UserRepository $userRepo;
|
|
private StudentTenantRepository $studentTenantRepo;
|
|
private TenantRegistrationCodeRepository $codeRepo;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->userRepo = new UserRepository();
|
|
$this->studentTenantRepo = new StudentTenantRepository();
|
|
$this->codeRepo = new TenantRegistrationCodeRepository();
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/auth/register-student
|
|
*/
|
|
public function register(Request $request): void
|
|
{
|
|
$payload = $request->input();
|
|
|
|
$code = trim((string) ($payload['code'] ?? ''));
|
|
$firstName = trim((string) ($payload['first_name'] ?? ''));
|
|
$lastName = trim((string) ($payload['last_name'] ?? ''));
|
|
$email = trim((string) ($payload['email'] ?? ''));
|
|
$phone = trim((string) ($payload['phone'] ?? ''));
|
|
$password = (string) ($payload['password'] ?? '');
|
|
|
|
if ($code === '' || $firstName === '' || $lastName === '' || $email === '' || $password === '') {
|
|
Response::json(['message' => 'code, first_name, last_name, email und password sind erforderlich'], 422);
|
|
}
|
|
|
|
$tenantCode = $this->codeRepo->findByCode($code);
|
|
if ($tenantCode === null) {
|
|
Response::json(['message' => 'Ungültiger Code'], 400);
|
|
}
|
|
|
|
$tenantId = (int) $tenantCode['tenant_id'];
|
|
|
|
$existing = $this->userRepo->findByEmail($email);
|
|
if ($existing !== null) {
|
|
Response::json(['message' => 'Email bereits registriert'], 400);
|
|
}
|
|
|
|
$user = $this->userRepo->create([
|
|
'tenant_id' => $tenantId,
|
|
'role' => 'student',
|
|
'email' => $email,
|
|
'password' => $password,
|
|
'first_name' => $firstName,
|
|
'last_name' => $lastName,
|
|
'is_active' => 1,
|
|
]);
|
|
|
|
if (!$user || !isset($user['id'])) {
|
|
Response::json(['message' => 'Registrierung fehlgeschlagen'], 500);
|
|
}
|
|
|
|
$userId = (int) $user['id'];
|
|
|
|
$this->studentTenantRepo->create($userId, $tenantId, 'pending');
|
|
$this->codeRepo->incrementUsedCount($tenantId);
|
|
|
|
$_SESSION['user_id'] = $userId;
|
|
$_SESSION['role'] = 'student';
|
|
$_SESSION['tenant_id'] = $tenantId;
|
|
|
|
Response::json([
|
|
'message' => 'Registrierung erfolgreich, bitte warte auf Bestätigung durch die Fahrschule',
|
|
'user' => [
|
|
'id' => $userId,
|
|
'email' => $email,
|
|
'first_name' => $firstName,
|
|
'last_name' => $lastName,
|
|
'role' => 'student',
|
|
],
|
|
'tenant_id' => $tenantId,
|
|
'tenant_name' => $tenantCode['tenant_name'],
|
|
], 201);
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/auth/login
|
|
*/
|
|
public function login(Request $request): void
|
|
{
|
|
$payload = $request->input();
|
|
$email = trim((string) ($payload['email'] ?? ''));
|
|
$password = (string) ($payload['password'] ?? '');
|
|
|
|
if ($email === '' || $password === '') {
|
|
Response::json(['message' => 'email und password sind erforderlich'], 422);
|
|
}
|
|
|
|
$user = $this->userRepo->findByEmail($email);
|
|
if ($user === null) {
|
|
Response::json(['message' => 'Ungültige Anmeldedaten'], 401);
|
|
}
|
|
|
|
if (!password_verify($password, $user['password_hash'])) {
|
|
Response::json(['message' => 'Ungültige Anmeldedaten'], 401);
|
|
}
|
|
|
|
if ($user['is_active'] !== 1) {
|
|
Response::json(['message' => 'Account ist deaktiviert'], 403);
|
|
}
|
|
|
|
$_SESSION['user_id'] = (int) $user['id'];
|
|
$_SESSION['role'] = $user['role'];
|
|
$_SESSION['tenant_id'] = (int) $user['tenant_id'];
|
|
|
|
Response::json([
|
|
'user' => [
|
|
'id' => (int) $user['id'],
|
|
'email' => $user['email'],
|
|
'first_name' => $user['first_name'],
|
|
'last_name' => $user['last_name'],
|
|
'role' => $user['role'],
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* GET /api/v1/auth/me
|
|
*/
|
|
public function me(Request $request): void
|
|
{
|
|
$user = Auth::requireUser();
|
|
|
|
$tenants = [];
|
|
if ($user['role'] === 'student') {
|
|
$tenants = $this->studentTenantRepo->getActiveForUser((int) $user['id']);
|
|
}
|
|
|
|
Response::json([
|
|
'user' => [
|
|
'id' => (int) $user['id'],
|
|
'email' => $user['email'],
|
|
'first_name' => $user['first_name'],
|
|
'last_name' => $user['last_name'],
|
|
'role' => $user['role'],
|
|
],
|
|
'tenants' => $tenants,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* POST /api/v1/auth/logout
|
|
*/
|
|
public function logout(Request $request): void
|
|
{
|
|
session_destroy();
|
|
Response::json(['message' => 'Logged out']);
|
|
}
|
|
} |