check($ip)) { Http::fail(429, 'rate_limited', 'Zu viele Anfragen.'); } $service = new LicenseService($db); $action = resolveLicenseAction(); switch ($action) { case 'validate': if (Http::method() !== 'POST') { Http::fail(405, 'method_not_allowed', 'Diese Aktion erwartet POST.'); } // Bewusst oeffentlich: Client-Anwendungen pruefen hier ihre Lizenz. // Die Antwort verraet nichts ueber fremde Lizenzen. Http::ok(['result' => $service->validate(Http::body(), $ip)]); case 'deactivate': if (Http::method() !== 'POST') { Http::fail(405, 'method_not_allowed', 'Diese Aktion erwartet POST.'); } ApiAuth::requireScope($db, 'license:deactivate'); Http::ok(['result' => $service->deactivate(Http::body(), $ip)]); case 'status': Http::ok(['module' => 'license', 'version' => '2.0']); default: Http::fail(404, 'unknown_action', 'Endpunkt nicht gefunden.', null, [ 'available' => ['validate', 'deactivate', 'status'], ]); } function resolveLicenseAction(): string { $explicit = Http::str('action'); if ($explicit !== null) { return strtolower($explicit); } $segments = array_values(array_filter( explode('/', trim(Http::path(), '/')), static fn(string $s): bool => $s !== '' )); $last = strtolower((string)end($segments)); return match ($last) { 'validate', 'deactivate', 'status' => $last, default => 'status', }; }