api.php 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <?php
  2. /**
  3. * Admin JSON API used by the browser-side uploader (assets/admin.js).
  4. *
  5. * POST JSON body: { "action": "...", ... } with X-CSRF-Token header.
  6. *
  7. * Actions:
  8. * presign { slug, name }
  9. * → presigned PUT URLs for the full-resolution original and its
  10. * browser-generated thumbnail.
  11. * register { slug, key, thumb, name, size }
  12. * → append an uploaded image to the gallery's JSON file.
  13. */
  14. require dirname(__DIR__) . '/app/bootstrap.php';
  15. if (!auth_check()) {
  16. json_response(['error' => 'Not authenticated'], 401);
  17. }
  18. if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  19. json_response(['error' => 'POST only'], 405);
  20. }
  21. csrf_verify();
  22. $body = json_decode((string)file_get_contents('php://input'), true) ?: [];
  23. $action = (string)($body['action'] ?? '');
  24. $gallery = gallery_load((string)($body['slug'] ?? ''));
  25. if ($gallery === null) {
  26. json_response(['error' => 'Unknown gallery'], 404);
  27. }
  28. $slug = $gallery['slug'];
  29. switch ($action) {
  30. case 'presign':
  31. $name = substr(safe_filename((string)($body['name'] ?? '')), 0, 120);
  32. // Random prefix avoids overwrites when two files share a name.
  33. $token = random_token(6);
  34. $key = "galleries/$slug/originals/$token-$name";
  35. $thumb = "galleries/$slug/thumbs/$token-$name.jpg";
  36. json_response([
  37. 'key' => $key,
  38. 'thumb' => $thumb,
  39. 'put_original' => s3_presign_put($key, 3600),
  40. 'put_thumb' => s3_presign_put($thumb, 3600),
  41. ]);
  42. case 'register':
  43. $key = (string)($body['key'] ?? '');
  44. $thumb = (string)($body['thumb'] ?? '');
  45. if (!str_starts_with($key, "galleries/$slug/")) {
  46. json_response(['error' => 'Key does not belong to this gallery'], 400);
  47. }
  48. if ($thumb !== '' && !str_starts_with($thumb, "galleries/$slug/")) {
  49. json_response(['error' => 'Thumb key does not belong to this gallery'], 400);
  50. }
  51. // Re-load under current state to reduce lost updates between requests.
  52. $gallery = gallery_load($slug);
  53. $gallery['images'][] = [
  54. 'key' => $key,
  55. 'thumb' => $thumb !== '' ? $thumb : null,
  56. 'name' => substr((string)($body['name'] ?? basename($key)), 0, 200),
  57. 'size' => (int)($body['size'] ?? 0),
  58. ];
  59. gallery_save($gallery);
  60. json_response(['ok' => true, 'count' => count($gallery['images'])]);
  61. default:
  62. json_response(['error' => 'Unknown action'], 400);
  63. }