feat: pet photo upload via presigned S3 URLs (GH #93, GRO-123)
- DB migration 0012: add photo_key and photo_uploaded_at columns to pets table - S3 client utility (apps/api/src/lib/s3.ts): presigned PUT/GET, delete via Rook-Ceph RGW - API photo routes on petsRouter: - POST /:petId/photo/upload-url — returns presigned PUT URL + object key - POST /:petId/photo/confirm — records key in DB after successful upload - DELETE /:petId/photo — deletes from storage and clears DB - GET /:petId/photo — returns presigned GET URL - RBAC: all staff roles (manager, receptionist, groomer) may upload/delete photos; restructured index.ts guards so groomer-accessible photo paths don't overlap with the manager/receptionist-only general pets write guard - Frontend PetPhotoDisplay: responsive image with shimmer skeleton and paw placeholder - Frontend PetPhotoUpload: client-side resize to max 1200px, XHR with progress, presigned PUT flow — binary data never passes through the API server - Wired both components into Clients.tsx staff portal pet cards - Unit tests: 14 test cases covering all four routes (happy path + error cases) Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -21,7 +21,9 @@
|
||||
"node-cron": "^3.0.3",
|
||||
"nodemailer": "^6.9.16",
|
||||
"openid-client": "^6.1.7",
|
||||
"zod": "^3.24.1"
|
||||
"zod": "^3.24.1",
|
||||
"@aws-sdk/client-s3": "^3.800.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.800.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.7",
|
||||
|
||||
Reference in New Issue
Block a user