Skip to content

Comments

Image labeling guide and security enhancements#56

Merged
anderstorstensson merged 17 commits intomasterfrom
next
Feb 16, 2026
Merged

Image labeling guide and security enhancements#56
anderstorstensson merged 17 commits intomasterfrom
next

Conversation

@anderstorstensson
Copy link
Member

Overview

This PR introduces an image labeling guide for automated imaging instruments (IFCB, CytoSense, FlowCam, PlanktoScope) along with security hardening and dependency updates.

Features

Image labeling guide

  • Image labeling guide: New dedicated collection of guide images for plankton classification in automated imaging systems
  • Image upload features:
    • Support for single image uploads and bulk ZIP archive uploads (max 100 images, 50MB)
    • Automatic slug generation and numbering for bulk uploads
    • Shared metadata across ZIP-imported images
    • Smart form enhancements for auto-filling title and taxon from filename
  • Admin interface:
    • Dedicated ImageLabelingImage admin with specialized form (ImageLabelingImageForm)
    • ZIP upload handler with progress feedback
    • Change taxon bulk action for image organization
    • Form templates with intermediate confirmation step
  • API endpoints:
    • /media/image_labeling/ - List all labeling guide images with filters
    • /media/image_labeling/summary/ - Aggregated counts by taxon, instrument, institute, geographic area
    • /media/image_labeling/first_per_taxon/ - First image per taxon (optimized for landing pages)
    • /media/image_labeling/grouped_by_plankton/ - Taxa organized by plankton groups with unique class names
  • Metadata fields:
    • Title (class name), Imaging instrument, Contributor
    • Institute, Training dataset DOI, Contributing organization
    • Copyright holder, Caption, Sampling date
    • Geographic area, Location, Latitude/Longitude coordinates
    • License selection with Creative Commons and CC0 options

Security hardening

  • Login rate limiting: Integrated django-axes for brute-force protection
    • Max 5 failed login attempts per IP address
    • 1-hour cooloff period after threshold
    • User warnings on login page showing remaining attempts
  • Session & cookie security:
    • Secure cookies in production (SESSION_COOKIE_SECURE)
    • HttpOnly cookies (SESSION_COOKIE_HTTPONLY)
    • CSRF protection (CSRF_COOKIE_SECURE)
    • HSTS security headers (31536000 seconds)
    • Content-Type and Referrer policy protection
  • User admin controls: Prevent non-superusers from modifying superuser status

Taxon Enhancements

  • Image labeling descriptions: New image_labeling_description field on Taxon model
  • Taxon description admin:
    • Browse and edit descriptions for taxa with labeling images
    • View images associated with each taxon
    • Orphaned description management for data integrity
  • Export/Import tools:
    • exportdescriptions command for backing up descriptions during database sync
    • importdescriptions command with orphaned record handling
  • API: Image labeling description included in taxon API responses

Technical Improvements

  • Django Upgrade: 4.2.27 → 5.2.11
  • Dependency Updates:
    • Pillow: 10.4.0 → 12.1.1
    • PyYAML: 6.0.2 → 6.0.3
    • psycopg: 3.2.3 → 3.3.2
    • sqlparse: 0.5.3 → 0.5.5
  • Renditions System: Improved proxy model support for Specification lookup
  • Media Filtering: Exclude ImageLabeling images from main media collection by default
  • Gallery Filtering: New exclude_galleries parameter for media endpoints

UI/UX improvements

  • License field updates with Creative Commons 4.0 International options
  • Improved suggestion lists for image metadata tags
  • "Save and add another" button for bulk image uploads
  • Preview CSS improvements

Database changes

  • New ImageLabelingImage proxy model
  • New ImageLabelingTaxonDescription proxy model
  • New OrphanedDescription model for description orphaning/recovery
  • Migration for institute field conversion (string → array format)
  • New taxon permission: edit_image_labeling_description

API Changes

  • New image labeling endpoints (see Features above)
  • Taxon API now includes image_labeling_description field
  • Media endpoints now support exclude_galleries parameter

Breaking Changes

  • None. Backward compatibility maintained

* Add image labeling guide feature

- ZIP upload, new API endpoint, admin interface
- Database: Add image_labeling_description field, ImageLabelingImage model
- API: New /api/media/image_labeling/ endpoint and exclude_galleries parameter for /api/media/

* Apply ruff formatting

* Fix linting issues

* Format admin.py
* Enable add another for image labeling

* Only show taxa with images

* Ruff and lint
* Migrate to Django 5.2

* Add new endpoint for fetching image count summary

* Convert institute from CharField to TagField

* Add new endpoint for fetching first image per taxon
* Change multiple taxa

* Add upload limit

* Update fields

* Use priority for first page

* Change multpile taxa

* Update docs
* Use autocomplete for Taxon based on zip filename

* Ruff format
* Preserve descriptions when taxon IDs change

When taxa IDs change during taxa imports, image labeling descriptions
are now preserved in an OrphanedDescription model instead of being lost.
Administrators can review and reassign these descriptions via Django admin.

- Add OrphanedDescription model for tracking lost descriptions
- Update importdescriptions to store orphaned entries in database
- Add admin interface for reviewing and reassigning descriptions
- Show taxa with descriptions even when all images are moved
- Add "Has Images" column to Labeling Guide Descriptions admin
- Fixes issue where descriptions were lost during syncdb

* Add bulk taxon change action for regular images (not just labeling)
…usekeeping (#47)

* Remove dead code and fix minor issues

- Fix Facts.__str__ to use taxon.scientific_name instead of non-existent title
- Remove unused _result variable in MediaAdmin.update_priority_list_json_view
- Refactor duplicate change_taxon_action method to parent MediaAdmin class

* Refactor image labeling taxonomy sidebar to use plankton groups (use input)

- Add new API endpoint /api/media/image_labeling/grouped_by_plankton/
  that returns taxa organized by plankton groups (Cyanobacteria, Diatoms,
  Dinoflagellates, Ciliates, Protozoa, Other) with unique class names
- Allow ZIP uploads without taxon assignment (requires title/class name)
- Change unknown taxon identifier from __no_taxon__ to "unknown" for
  cleaner URLs
- Add OpenAPI documentation for the new grouped_by_plankton endpoint
* bump django to 5.2.11

* reformat requirements.txt
* fix: harden security settings and add login rate limiting

- Add secure cookie settings (SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE,
  SESSION_COOKIE_HTTPONLY) and HTTPS enforcement, gated on DEBUG=False
- Add django-axes for admin login brute-force protection (5 attempts,
  1 hour cooloff per IP)
- Validate syncdb log_id format in get_log_file for defense-in-depth

* fix: hide is_superuser field from non-superuser staff in admin

Non-superuser managers with user change permission could previously
grant superuser access via the admin user form. The is_superuser
field is now only visible to superusers.

* ruff format
…ging (#50)

Enable persistent access failure logging, show remaining login attempts
before lockout, and clarify the lockout message as temporary.
@anderstorstensson anderstorstensson merged commit 97a3488 into master Feb 16, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant