reset.php 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. <?php
  2. declare(strict_types=1);
  3. use App\App\Bootstrap;
  4. use App\Security\Csrf;
  5. use App\Security\RateLimiter;
  6. use App\Storage\FileSystem;
  7. use App\Storage\JsonStore;
  8. require dirname(__DIR__) . '/src/autoload.php';
  9. Bootstrap::init();
  10. if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  11. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Method not allowed'], 405);
  12. }
  13. $csrf = $_POST['csrf'] ?? '';
  14. if (!Csrf::validate(is_string($csrf) ? $csrf : null)) {
  15. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Ungültiges CSRF-Token.'], 419);
  16. }
  17. if (trim((string) ($_POST['website'] ?? '')) !== '') {
  18. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Anfrage blockiert.'], 400);
  19. }
  20. $email = strtolower(trim((string) ($_POST['email'] ?? '')));
  21. if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
  22. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Bitte gültige E-Mail eingeben.'], 422);
  23. }
  24. $app = Bootstrap::config('app');
  25. $limiter = new RateLimiter();
  26. $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
  27. $rateKey = sprintf('reset:%s:%s', $ip, $email);
  28. if (!$limiter->allow($rateKey, (int) $app['rate_limit']['requests'], (int) $app['rate_limit']['window_seconds'])) {
  29. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Zu viele Löschanfragen. Bitte später erneut versuchen.'], 429);
  30. }
  31. $store = new JsonStore();
  32. try {
  33. $result = $store->withEmailLock($email, static function () use ($store, $app, $email): array {
  34. $hadDraft = $store->getDraft($email) !== null;
  35. $submission = $store->getSubmissionByEmail($email);
  36. $hadSubmission = $submission !== null;
  37. if ($hadSubmission) {
  38. return [
  39. 'ok' => false,
  40. 'status' => 409,
  41. 'message' => 'Für diese E-Mail liegt bereits ein abgeschlossener Antrag vor. Ein Zurücksetzen ist nicht möglich.',
  42. 'had_draft' => $hadDraft,
  43. 'had_submission' => true,
  44. ];
  45. }
  46. $store->deleteDraft($email);
  47. $uploadDir = rtrim((string) $app['storage']['uploads'], '/') . '/' . $store->emailKey($email);
  48. FileSystem::removeTree($uploadDir);
  49. return [
  50. 'ok' => true,
  51. 'status' => 200,
  52. 'had_draft' => $hadDraft,
  53. 'had_submission' => $hadSubmission,
  54. ];
  55. });
  56. } catch (Throwable $e) {
  57. Bootstrap::log('app', 'reset error: ' . $e->getMessage());
  58. Bootstrap::jsonResponse(['ok' => false, 'message' => 'Daten konnten nicht gelöscht werden.'], 500);
  59. }
  60. if (($result['ok'] ?? false) !== true) {
  61. Bootstrap::jsonResponse([
  62. 'ok' => false,
  63. 'message' => (string) ($result['message'] ?? 'Daten konnten nicht gelöscht werden.'),
  64. 'had_draft' => (bool) ($result['had_draft'] ?? false),
  65. 'had_submission' => (bool) ($result['had_submission'] ?? false),
  66. ], (int) ($result['status'] ?? 422));
  67. }
  68. Bootstrap::jsonResponse([
  69. 'ok' => true,
  70. 'message' => 'Gespeicherte Daten wurden gelöscht.',
  71. 'had_draft' => (bool) ($result['had_draft'] ?? false),
  72. 'had_submission' => (bool) ($result['had_submission'] ?? false),
  73. ]);