Skip to main content

Photo Management

The Photo Management system lets carers and administrators upload, view, and manage photographs for each animal record. Photos are stored securely in private cloud storage and served through an authenticated proxy, ensuring that images are only accessible to members of the owning organisation.

Overview

Every animal in WildTrack360 can have two types of photos:

  • Primary photo -- a single profile image displayed on the animal's card and detail header
  • Gallery photos -- a collection of dated, described images shown in a carousel on the animal detail page

Both types are uploaded to private S3-compatible storage (Wasabi/AWS) and are never publicly accessible. When a user views a photo, the browser requests it through an authenticated server-side proxy that verifies the user's identity and organisation membership before returning the image bytes.

Uploading Photos

Supported Formats and Limits

ConstraintValue
Maximum file size10 MB
Allowed formatsJPEG, PNG, WebP, GIF
File name sanitisationNon-alphanumeric characters (except ., -, _) are replaced with underscores

Primary Photo Upload

The primary photo is set from the animal edit form. When a file is uploaded:

  1. The server validates the file type and size.
  2. A unique key is generated in the format orgs/{orgId}/animal-photos/{uuid}-{filename}.
  3. The file is uploaded to private S3 storage.
  4. The S3 key (not a public URL) is saved to the animal's photo field.
  5. The upload is recorded in the audit log.

Gallery photos are added from the Photo Gallery card on the animal detail page. Clicking Add Photo opens a dialog where the user:

  1. Selects an image file (with a live preview).
  2. Enters a description of the photo (required).
  3. Clicks Save Photo to upload.

The upload creates a Photo record in the database linked to the animal, storing the S3 key, description, and date.

Upload Dialog Fields

FieldRequiredDescription
PictureYesThe image file to upload (JPEG, PNG, WebP, or GIF, max 10 MB)
DescriptionYesA brief text description of the photo

The Photo Gallery appears as a card on the animal detail page. It displays uploaded gallery photos in a carousel with previous/next navigation.

Each photo in the carousel shows:

  • The image itself (scaled to fit, max height 400px)
  • The date the photo was taken, formatted as a readable date
  • The description entered at upload time

Managing Photos

Users with photo management permissions see additional controls:

ActionControlDescription
Add photoAdd Photo button in the gallery headerOpens the upload dialog
Delete photoTrash icon on each photoPermanently removes the photo from storage and the database

When a photo is deleted, the gallery updates immediately without a page reload.

Authenticated Photo Serving

Photos are served through an authenticated proxy endpoint rather than direct S3 URLs. This is a deliberate security measure -- all objects in the S3 bucket are private, and there are no pre-signed URLs or public access policies.

How It Works

  1. The browser requests /api/photos/serve?key={s3Key}.
  2. The server authenticates the user via Clerk.
  3. The organisation ID embedded in the S3 key (e.g., orgs/{orgId}/...) is extracted and compared against the user's active organisation.
  4. If the user belongs to the correct organisation, the server fetches the object from S3 and streams it back with appropriate headers.
  5. If any check fails, the request is rejected with a 401, 403, or 404 status.

Response Headers

HeaderValuePurpose
Content-TypeOriginal MIME type of the imageCorrect rendering in the browser
Cache-Controlprivate, max-age=3600, must-revalidateCaches in the user's browser for 1 hour but prevents shared/CDN caching
X-Content-Type-OptionsnosniffPrevents MIME type sniffing attacks

This approach ensures that even if an S3 key is leaked, the photo cannot be accessed without a valid authenticated session in the correct organisation.

Integration with Other Modules

ModuleIntegration
Animal Record HistoryGallery photos appear on the animal detail page alongside care records
Audit LoggingPhoto uploads are recorded as CREATE actions on the AnimalPhoto entity
Data Export & ReportingAll animal photos (primary and gallery) are included in the full data export ZIP file
Roles & PermissionsThe canManagePhotos permission controls who can add and delete gallery photos