Mit dieser Webapp kann der Nutzer von offenen Werkstätten die Bilder von seinem Projekt hochladen und eine Kurze Beschreibung ergänzen.
Go to file
matthias.lotz dd71dcab44 feat: ENV-Struktur massiv vereinfacht (Phase 6)
- Von 16 .env Dateien auf 2 zentrale reduziert
  * docker/dev/.env - Development Secrets
  * docker/prod/.env - Production Secrets

- Alle ENV-Variablen jetzt in docker-compose.yml environment sections
- .env COPY aus allen Dockerfiles entfernt (wurden durch volume mounts überschrieben)
- Frontend env.sh umgeschrieben: Liest ENV-Variablen statt .env Datei
- CLIENT_URL komplett entfernt (wurde nirgendwo verwendet)

- Fix: management.js nutzt platform_name statt name (DB-Schema korrekt)

ENV-Handling jetzt deutlich einfacher und wartbarer!
Von 4 Frontend ENV-Variablen auf 3 reduziert (API_URL, PUBLIC_HOST, INTERNAL_HOST)
2025-11-30 13:19:24 +01:00
.copilot TODOs aktualisiert 2025-11-01 14:00:53 +01:00
.github/ISSUES chore(upgrade): add issue template and upgrade plan for deps upgrade 2025-10-28 20:13:57 +01:00
backend feat: ENV-Struktur massiv vereinfacht (Phase 6) 2025-11-30 13:19:24 +01:00
docker feat: ENV-Struktur massiv vereinfacht (Phase 6) 2025-11-30 13:19:24 +01:00
FeatureRequests feat: ENV-Struktur massiv vereinfacht (Phase 6) 2025-11-30 13:19:24 +01:00
frontend feat: ENV-Struktur massiv vereinfacht (Phase 6) 2025-11-30 13:19:24 +01:00
scripts docs(telegram): complete Phase 5 documentation and security improvements 2025-11-30 11:40:59 +01:00
test_photos Initial Commit 2025-10-15 21:33:00 +02:00
tests fix(docker): Add sqlite3 to production backend image 2025-11-08 16:05:35 +01:00
.dockerignore feat: Complete image description feature implementation 2025-11-07 23:20:50 +01:00
.gitignore feat: Add Telegram Bot standalone test (Phase 1) 2025-11-29 20:05:40 +01:00
AUTHENTICATION.md fix: changed ADMIN_SESSION_COOKIE_SECURE=true with pre-commit script 2025-11-24 20:15:46 +01:00
CHANGELOG.md chore: release v1.10.2 2025-11-29 17:47:55 +01:00
dev.sh Feature Request: admin session security 2025-11-23 21:18:42 +01:00
LICENSE Initial Commit 2025-10-15 21:33:00 +02:00
package-lock.json feat: Add TelegramNotificationService (Phase 2) 2025-11-29 22:41:38 +01:00
package.json chore: Improve release script with tag-based commit detection 2025-11-29 16:52:19 +01:00
prod.sh feat: Add Telegram notification feature request and improve prod.sh Docker registry push 2025-11-29 19:28:23 +01:00
README.dev.md feat: Add TelegramNotificationService (Phase 2) 2025-11-29 22:41:38 +01:00
README.md feat: ENV-Struktur massiv vereinfacht (Phase 6) 2025-11-30 13:19:24 +01:00
test-error-page.html refactor: Consolidate error pages into single ErrorPage component 2025-11-29 12:17:51 +01:00
test-loading.html refactor: Consolidate error pages into single ErrorPage component 2025-11-29 12:17:51 +01:00
TODO.md feat: Add Telegram notification feature request and improve prod.sh Docker registry push 2025-11-29 19:28:23 +01:00

Image Uploader with Multi-Upload & Slideshow

A self-hosted image uploader with multi-image upload capabilities and automatic slideshow functionality.

Features

Multi-Image Upload: Upload multiple images at once with batch processing
Telegram Notifications: 🆕 Real-time notifications for uploads, consent changes, deletions, and daily warnings
Social Media Consent Management: 🆕 GDPR-compliant consent system for workshop display and social media publishing
Automatic Cleanup: 🆕 Unapproved groups are automatically deleted after 7 days
Deletion Log: 🆕 Complete audit trail of automatically deleted content
Drag-and-Drop Reordering: 🆕 User during upload and admins can reorder images via intuitive drag-and-drop interface
Slideshow Mode: Automatic fullscreen slideshow with smooth transitions (respects custom ordering)
Preview Image Optimization: Automatic thumbnail generation for faster gallery loading (96-98% size reduction)
Touch-Friendly Interface: 🆕 Mobile-optimized drag handles and responsive design
Moderation Panel: Dedicated moderation interface with consent filtering and export
Persistent Storage: Docker volumes ensure data persistence across restarts
Clean UI: Minimalist design focused on user experience
Self-Hosted: Complete control over your data and infrastructure

What's New

This project extends the original Image-Uploader by vallezw with enhanced multi-upload and slideshow capabilities.

🆕 Latest Features (November 2025)

  • 📱 Telegram Bot Notifications (Nov 30):

    • Real-time notifications for all critical events
    • 4 notification types: Upload, Consent Changes, Group Deletion, Daily Warnings
    • Upload notifications with name, year, title, image count, and consent status
    • Consent change tracking (workshop display + social media platforms)
    • Group deletion confirmations with uploader and statistics
    • Daily deletion warnings (09:00) for groups pending auto-cleanup (24h notice)
    • Cron-scheduled automation via node-cron
    • Admin endpoint for manual trigger: POST /api/admin/telegram/warning
    • Optional feature via TELEGRAM_ENABLED environment variable
    • Complete setup guide in scripts/README.telegram.md
  • 🌐 Public/Internal Host Separation (Nov 25):

    • Subdomain-based feature separation for production deployment
    • Public host (deinprojekt.hobbyhimmel.de): Upload + UUID Management only
    • Internal host (deinprojekt.lan.hobbyhimmel.de): Full admin access
    • Frontend code splitting with React.lazy() for optimized bundle size
    • Backend API protection via hostGate middleware
    • Rate limiting: 20 uploads/hour on public host
    • Audit log tracking with source host information
    • Complete local testing support via /etc/hosts entries
    • Zero configuration overhead for single-host deployments
  • 🧪 Comprehensive Test Suite (Nov 16):

    • 45 automated tests covering all API endpoints (100% passing)
    • Jest + Supertest integration testing framework
    • Unit tests for authentication middleware
    • API tests for admin, consent, migration, and upload endpoints
    • In-memory SQLite database for isolated testing
    • Coverage: 26% statements, 15% branches (realistic starting point)
    • Test execution time: ~10 seconds for full suite
    • CI/CD ready with proper teardown and cleanup
  • 🔒 Admin Session Authentication (Nov 16):

    • Server-managed HTTP sessions for all admin/system endpoints
    • CSRF protection on every mutating request via X-CSRF-Token
    • Secure ADMIN_SESSION_SECRET configuration keeps cookies tamper-proof
    • Protected routes: /api/admin/*, /api/system/migration/migrate, /api/system/migration/rollback
    • Session-aware moderation UI with login + first-admin setup wizard
    • Complete authentication documentation in AUTHENTICATION.md
  • 📋 API Route Documentation (Nov 16):

    • Single Source of Truth: backend/src/routes/routeMappings.js
    • Comprehensive route overview in backend/src/routes/README.md
    • Critical Express routing order documented (specific before generic)
    • Frontend-ready route reference with authentication requirements
    • OpenAPI specification auto-generation integrated
  • 🔐 Social Media Consent Management (Phase 1 Complete - Nov 9-10):

    • GDPR-compliant consent system for image usage
    • Mandatory workshop display consent (no upload without approval)
    • Optional per-platform consents (Facebook, Instagram, TikTok)
    • Consent badges and filtering in moderation panel
    • CSV/JSON export for legal documentation
    • Group ID tracking for consent withdrawal requests
  • 🔑 Self-Service Management Portal (Phase 2 Complete - Nov 11-15):

    • Secure UUID-based management tokens for user self-service
    • Frontend portal at /manage/:token for consent management
    • Revoke/restore consents for workshop and social media
    • Edit metadata (title, description) after upload
    • Add/delete images after upload (with moderation re-approval)
    • Complete group deletion with audit trail
    • IP-based rate limiting (10 requests/hour)
    • Brute-force protection (20 failed attempts → 24h ban)
    • Management audit log for security tracking
  • 🎨 Modular UI Architecture (Nov 15):

    • Reusable components: ConsentManager, GroupMetadataEditor, ImageDescriptionManager
    • Multi-mode support: upload/edit/moderate modes for maximum reusability
    • Code reduction: 62% in ModerationGroupImagesPage (281→107 lines)
    • Consistent design: HTML buttons, Paper boxes, Material-UI Alerts
    • Individual save/discard per component section
    • Zero code duplication between pages
  • <EFBFBD> Slideshow Optimization: Intelligent image preloading eliminates loading delays and duplicate images

  • 📅 Chronological Display: Slideshows now play in chronological order (year → upload date)

  • Automatic Cleanup: Unapproved groups are automatically deleted after 7 days

  • Deletion Log: Complete audit trail with statistics (groups, images, storage freed)

  • Countdown Display: Visual indicator showing days until automatic deletion

  • Approval Feedback: SweetAlert2 notifications for moderation actions

  • Manual Cleanup Trigger: Admin API endpoints for testing and manual cleanup

  • Image Descriptions: Add optional descriptions to individual images (max 200 characters)

  • Edit Mode: Edit descriptions for uploaded images in upload preview and moderation interface

  • Slideshow Display: Image descriptions shown as overlays during slideshow presentation

  • Public Display: Descriptions visible in public group views and galleries

Previous Features (October 2025)

  • Drag-and-Drop Image Reordering: Admins can now reorder images using intuitive drag-and-drop
  • Touch-Friendly Interface: Mobile-optimized controls with always-visible drag handles
  • Slideshow Integration: Custom image order automatically applies to slideshow mode
  • Optimistic UI Updates: Immediate visual feedback with error recovery
  • Comprehensive Admin Panel: Dedicated moderation interface for content curation

Core Features

  • Multi-image batch upload with progress tracking
  • Automatic slideshow presentation mode
  • Image grouping with descriptions and metadata
  • Random slideshow rotation with custom ordering support
  • Keyboard navigation support (Slideshow: Space/Arrow keys, Escape to exit)
  • Mobile-responsive design with touch-first interactions

Quick Start

Production Environment

# Start production environment
./prod.sh

# Or manually:
docker compose -f docker/prod/docker-compose.yml up -d

Development Environment

# Start development environment  
./dev.sh

# Or manually:
docker compose -f docker/dev/docker-compose.yml up -d
### Access URLs

#### Production (Port 80):
- Upload Interface: `http://localhost`
- Slideshow Mode: `http://localhost/slideshow`
- Groups Overview: `http://localhost/groups`
- Moderation Panel: `http://localhost/moderation` (requires authentication)

#### Development (Port 3000):
- Upload Interface: `http://localhost:3000`
- Backend API: `http://localhost:5001`
- Slideshow Mode: `http://localhost:3000/slideshow`

### Multi-Image Upload

1. Visit `http://localhost`
2. Drag & drop multiple images or click to select
3. Add an optional description for your image collection
4. **Grant Consent** (mandatory):
   - ✅ **Workshop Display**: Required consent to display images on local monitor
   - ☐ **Social Media** (optional): Per-platform consent for Facebook, Instagram, TikTok
5. Click "Upload Images" to process the batch
6. Receive your **Group ID** and **Management Link** as reference
7. Images are grouped and await moderation approval

### Self-Service Management Portal

After upload, users receive a unique management link (`/manage/:token`) to:

- **View Upload**: See all images and metadata
- **Manage Consents**: Revoke or restore workshop/social media consents
- **Edit Metadata**: Update title, description, year (triggers re-moderation)
- **Manage Images**: Add new images or delete existing ones
- **Delete Group**: Complete removal with double-confirmation
- **Email Contact**: Request deletion of already published social media posts

**Security Features**:
- No authentication required (token-based access)
- Rate limiting: 10 requests per hour per IP
- Brute-force protection: 20 failed attempts → 24h ban
- Complete audit trail of all management actions

### Slideshow Mode

- **Automatic Access**: Navigate to `http://localhost/slideshow`  
- **Features**:
  - Fullscreen presentation
  - 4-second display per image            
  - Automatic progression through all slideshow collections
  - **🆕 Chronological order**: Groups play from oldest to newest (year → upload date)
  - **🆕 Intelligent preloading**: Next images load in background for seamless transitions
  - **🆕 Zero loading delays**: Pre-cached images for instant display
  - Smooth fade transitions (0.5s)  

- **Keyboard Controls**:
  - **ESC**: Exit slideshow / Return to upload page
  - **Spacebar / Arrow Right**: Manually advance to next image
  - **Home Button**: Return to main upload interface

### Preview Image Optimization

The application automatically generates optimized preview thumbnails for all uploaded images to significantly improve gallery loading performance.

- **Automatic Generation**:
  - Preview images are created automatically on server startup
  - Existing images without previews are processed on-demand
  - New uploads generate previews immediately during upload

- **Technical Specifications**:
  - **Max Width**: 800px (maintains aspect ratio)
  - **Format**: JPEG with 85% quality
  - **Size Reduction**: 96-98% smaller than originals (e.g., 2076KB → 58.5KB)
  - **Performance**: ~30x faster gallery loading times

- **Smart Image Loading**:
  - **Galleries & Overview**: Load lightweight preview images (~50-100KB)
  - **Slideshow Mode**: Uses full-resolution originals for best quality
  - **Fallback**: Automatically uses originals if preview generation fails

- **Storage**:
  - Originals: `backend/src/data/images/` (~2-4MB per image)
  - Previews: `backend/src/data/previews/` (~50-100KB per image)
  - Database: `preview_path` column stores preview filename

### Moderation Interface (Protected)

- **Access**: `http://localhost/moderation` (requires admin session)
- **Authentication Flow**:
  - Built-in login form establishes a server session stored in HttpOnly cookies
  - First-time setup wizard creates the initial admin user once `ADMIN_SESSION_SECRET` is configured
  - CSRF token must be included (header `X-CSRF-Token`) for any mutating admin API call
  - `AUTHENTICATION.md` documents CLI/cURL examples for managing sessions and CSRF tokens
- **Protected Endpoints**: All `/api/admin/*` routes require authentication
- **Features**:
  - Review pending image groups before public display
  - Visual countdown showing days until automatic deletion (7 days for unapproved groups)
  - **Consent Management**:
    - Visual consent badges showing social media platforms
    - Filter by consent status (All / Workshop-only / Facebook / Instagram / TikTok)
    - Export consent data as CSV/JSON for legal compliance
    - Consent timestamp tracking
  - Approve or reject submitted collections with instant feedback
  - Delete individual images from approved groups  
  - View group details (title, creator, description, image count)
  - **Deletion Log** (bottom of moderation page):
    - Statistics: Total groups/images deleted, storage freed
    - Detailed history table with timestamps and reasons
    - Toggle between last 10 entries and complete history
  - Bulk moderation actions

- **Automatic Cleanup**:
  - Unapproved groups are automatically deleted after 7 days
  - Daily cleanup runs at 10:00 AM (Europe/Berlin timezone)
  - Complete removal: Database entries + physical files (originals + previews)
  - Full audit trail logged for compliance
  - **Note**: Approved groups are NEVER automatically deleted

- **Security Features**:
  - Password protected access via nginx HTTP Basic Auth
  - Hidden from search engines (`robots.txt` + `noindex` meta tags)
  - No public links or references in main interface    

### Public Overview of all approved slideshows 
- **Group Management**: Navigate to `http://localhost/groups`
  - Overview of all approved slideshow collections
  - Launch slideshow mode from any group
  - View group statistics and metadata
     

## Docker Structure

The application uses separate Docker configurations for development and production:

docker/ ├── .env.backend.example # Backend environment variables documentation ├── .env.frontend.example # Frontend environment variables documentation ├── dev/ # Development environment │ ├── docker-compose.yml # Development services configuration │ ├── backend/ │ │ ├── config/.env # Development backend configuration │ │ └── Dockerfile # Development backend container │ └── frontend/ │ ├── config/.env # Development frontend configuration │ ├── config/env.sh # Runtime configuration script │ ├── Dockerfile # Development frontend container │ ├── nginx.conf # Development nginx configuration │ └── start.sh # Development startup script └── prod/ # Production environment ├── docker-compose.yml # Production services configuration ├── backend/ │ ├── config/.env # Production backend configuration │ └── Dockerfile # Production backend container └── frontend/ ├── config/.env # Production frontend configuration ├── config/env.sh # Runtime configuration script ├── config/htpasswd # HTTP Basic Auth credentials ├── Dockerfile # Production frontend container └── nginx.conf # Production nginx configuration


### Environment Configuration

- **Development**: Uses `docker/dev/` configuration with live reloading
- **Production**: Uses `docker/prod/` configuration with optimized builds
- **Scripts**: Use `./dev.sh` or `./prod.sh` for easy deployment

## Data Structure 

Data are stored in SQLite database. The structure is as follows:

### Core Tables

``` sql
-- Groups table (extended with consent fields)
CREATE TABLE groups (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    group_id TEXT UNIQUE NOT NULL,
    year INTEGER NOT NULL,
    title TEXT NOT NULL,
    description TEXT,
    name TEXT,
    upload_date DATETIME NOT NULL,
    approved BOOLEAN DEFAULT FALSE,
    display_in_workshop BOOLEAN NOT NULL DEFAULT 0,  -- Consent for workshop display
    consent_timestamp DATETIME,                       -- When consent was granted
    management_token TEXT,                            -- For Phase 2: Self-service portal
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Images table
CREATE TABLE images (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    group_id TEXT NOT NULL,
    file_name TEXT NOT NULL,
    original_name TEXT NOT NULL,
    file_path TEXT NOT NULL,
    preview_path TEXT,                               -- Optimized thumbnail path
    image_description TEXT,                          -- Individual image description
    upload_order INTEGER NOT NULL,
    file_size INTEGER,
    mime_type TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (group_id) REFERENCES groups(group_id) ON DELETE CASCADE
);

-- Deletion log for audit trail
CREATE TABLE deletion_log (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    group_id TEXT NOT NULL,
    title TEXT,
    name TEXT,
    upload_date DATETIME,
    image_count INTEGER,
    total_size INTEGER,
    deletion_reason TEXT,
    deleted_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- Configurable social media platforms
CREATE TABLE social_media_platforms (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    platform_name TEXT UNIQUE NOT NULL,    -- e.g., 'facebook', 'instagram', 'tiktok'
    display_name TEXT NOT NULL,             -- e.g., 'Facebook', 'Instagram', 'TikTok'
    icon_name TEXT,                         -- Material-UI Icon name
    is_active BOOLEAN DEFAULT 1,
    sort_order INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Per-group, per-platform consent tracking
CREATE TABLE group_social_media_consents (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    group_id TEXT NOT NULL,
    platform_id INTEGER NOT NULL,
    consented BOOLEAN NOT NULL DEFAULT 0,
    consent_timestamp DATETIME NOT NULL,
    revoked BOOLEAN DEFAULT 0,               -- For Phase 2: Consent revocation
    revoked_timestamp DATETIME,              -- When consent was revoked
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (group_id) REFERENCES groups(group_id) ON DELETE CASCADE,
    FOREIGN KEY (platform_id) REFERENCES social_media_platforms(id) ON DELETE CASCADE,
    UNIQUE(group_id, platform_id)
);

-- Management audit log (Phase 2)
CREATE TABLE management_audit_log (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    group_id TEXT,
    management_token TEXT,                   -- First 8 characters only (masked)
    action TEXT NOT NULL,                     -- validate_token, revoke_consent, edit_metadata, add_images, delete_image, delete_group
    success BOOLEAN NOT NULL,
    error_message TEXT,
    ip_address TEXT,
    user_agent TEXT,
    request_data TEXT,                        -- JSON of request body
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (group_id) REFERENCES groups(group_id) ON DELETE SET NULL
);

-- Indexes for performance
CREATE INDEX IF NOT EXISTS idx_audit_group_id ON management_audit_log(group_id);
CREATE INDEX IF NOT EXISTS idx_audit_action ON management_audit_log(action);
CREATE INDEX IF NOT EXISTS idx_audit_success ON management_audit_log(success);
CREATE INDEX IF NOT EXISTS idx_audit_created_at ON management_audit_log(created_at);
CREATE INDEX IF NOT EXISTS idx_audit_ip_address ON management_audit_log(ip_address);
    revoked_timestamp DATETIME,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (group_id) REFERENCES groups(group_id) ON DELETE CASCADE,
    FOREIGN KEY (platform_id) REFERENCES social_media_platforms(id) ON DELETE CASCADE,
    UNIQUE(group_id, platform_id)
);

-- Migration tracking
CREATE TABLE schema_migrations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    migration_name TEXT UNIQUE NOT NULL,
    applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Indexes

-- Groups indexes
CREATE INDEX idx_groups_group_id ON groups(group_id);
CREATE INDEX idx_groups_year ON groups(year);
CREATE INDEX idx_groups_upload_date ON groups(upload_date);
CREATE INDEX idx_groups_display_consent ON groups(display_in_workshop);
CREATE UNIQUE INDEX idx_groups_management_token ON groups(management_token) WHERE management_token IS NOT NULL;

-- Images indexes
CREATE INDEX idx_images_group_id ON images(group_id);
CREATE INDEX idx_images_upload_order ON images(upload_order);

-- Consent indexes
CREATE INDEX idx_consents_group_id ON group_social_media_consents(group_id);
CREATE INDEX idx_consents_platform_id ON group_social_media_consents(platform_id);
CREATE INDEX idx_consents_consented ON group_social_media_consents(consented);

Triggers

-- Update timestamp on groups modification
CREATE TRIGGER update_groups_timestamp 
AFTER UPDATE ON groups
FOR EACH ROW
BEGIN
    UPDATE groups SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
END;

-- Update timestamp on consent modification
CREATE TRIGGER update_consents_timestamp 
AFTER UPDATE ON group_social_media_consents
FOR EACH ROW
BEGIN
    UPDATE group_social_media_consents SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
END;

Architecture

Backend (Node.js + Express)

  • Multi-upload API: /api/upload/batch - Handles batch file processing
  • Groups API: /api/groups - Retrieves slideshow collections
  • Preview Generation: Automatic thumbnail creation using Sharp (800px JPEG, 85% quality)
  • File Storage: Organized in /upload directory (originals) and /data/previews (thumbnails)
  • Database Storage: sqlite database in /app/src/data/db/image_uploader.db

Frontend (React + Material-UI)

  • Multi-Upload Interface: Drag & drop with preview gallery
  • Progress Tracking: Real-time upload status
  • Spacebar / Arrow Right: Manually advance to next image
  • Slideshow Engine: Fullscreen presentation with automatic progression
  • Responsive Design: Mobile and desktop optimized
  • Home Button: Return to main upload interface

Storage Architecture

Docker Volume (app-data)
src
└── app
    ├── src
        ├── upload (originals, ~2-4MB each)
        │   ├── ZMmHXzHbqw.jpg
        │   ├── tjjnngOmXS.jpg
        │   └── ...
        └── data
            ├── previews (thumbnails, ~50-100KB each)
            │   ├── ZMmHXzHbqw.jpg
            │   ├── tjjnngOmXS.jpg
            │   └── ...
            └── db
                └── image_uploader.db

Hosting it with Docker

  • Frontend: React 17, Material-UI, React Router
  • Backend: Node.js, Express, Multer (file handling)
  • Containerization: Docker, Docker Compose
  • Reverse Proxy: nginx (routing & file serving)[In order to host the project you will need to create a docker-compose file. These files are combining multiple docker images to interact with each other.
  • File Upload: Drag & drop with react-dropzone
  • Notifications: SweetAlert2

API Endpoints

Upload Operations

  • POST /api/upload/batch - Upload multiple images with description and consent data
  • GET /api/groups - Retrieve all slideshow groups
  • GET /api/groups/:id - Get specific slideshow group
  • GET /api/social-media/platforms - Get list of active social media platforms
  • POST /api/groups/:groupId/consents - Save consent data for a group
  • GET /api/groups/:groupId/consents - Get consent data for a group
  • GET /api/admin/groups/by-consent - Filter groups by consent status (query params: ?workshopConsent=true&platform=facebook)
  • GET /api/admin/consents/export - Export all consent data as CSV/JSON

User Self-Service Management Portal (Phase 2 - Backend Complete)

Management Portal APIs (Token-based authentication):

  • GET /api/manage/:token - Validate management token and retrieve group data
  • PUT /api/manage/:token/consents - Revoke or restore consents (workshop & social media)
  • PUT /api/manage/:token/metadata - Edit group title and description (resets approval status)
  • POST /api/manage/:token/images - Add new images to existing group (max 50 total, resets approval)
  • DELETE /api/manage/:token/images/:imageId - Delete individual image (prevents deleting last image)
  • DELETE /api/manage/:token - Delete entire group with all images and data

Management Audit Log APIs (Admin access only):

  • GET /api/admin/management-audit?limit=N - Retrieve recent management actions (default: 10)
  • GET /api/admin/management-audit/stats - Get statistics (total actions, success rate, unique IPs)
  • GET /api/admin/management-audit/group/:groupId - Get audit log for specific group

Security Features:

  • IP-based rate limiting: 10 requests per hour per IP
  • Brute-force protection: 20 failed token validations → 24-hour IP ban
  • Complete audit trail: All management actions logged with IP, User-Agent, timestamp
  • Token masking: Only first 8 characters stored in audit log for privacy
  • Automatic file cleanup: Physical deletion of images when removed via API

Moderation Operations (Protected)

  • GET /moderation/groups - Get all groups pending moderation (includes consent info)
  • PATCH /groups/:id/approve - Approve/unapprove a group for public display
  • DELETE /groups/:id - Delete an entire group
  • DELETE /groups/:id/images/:imageId - Delete individual image from group

Admin Operations (Protected by /moderation access)

  • GET /api/admin/deletion-log?limit=N - Get recent deletion log entries (default: 10)
  • GET /api/admin/deletion-log/all - Get complete deletion history
  • GET /api/admin/deletion-log/stats - Get deletion statistics (total groups/images deleted, storage freed)
  • POST /api/admin/cleanup/trigger - Manually trigger cleanup (for testing)
  • GET /api/admin/cleanup/preview - Preview which groups would be deleted (dry-run)

File Access

  • GET /api/upload/:filename - Access uploaded image files (legacy, use /api/download instead)
  • GET /api/download/:filename - Download original full-resolution images
  • GET /api/previews/:filename - Access optimized preview thumbnails (~100KB, 800px width)

Testing

Automatic Cleanup Testing

The application includes comprehensive testing tools for the automatic cleanup feature:

# Run interactive test helper (recommended)
./tests/test-cleanup.sh

# Available test operations:
# 1. View unapproved groups with age
# 2. Backdate groups for testing (simulate 7+ day old groups)
# 3. Preview cleanup (dry-run)
# 4. Execute cleanup manually
# 5. View deletion log history

Testing Workflow:

  1. Upload a test group (don't approve it)
  2. Use test script to backdate it by 8 days
  3. Preview what would be deleted
  4. Execute cleanup and verify deletion log

For detailed testing instructions, see: tests/TESTING-CLEANUP.md

Configuration

Environment Variables

Variable Default Description
API_URL http://localhost:5001 Backend API endpoint
TELEGRAM_ENABLED false Enable/disable Telegram notifications
TELEGRAM_BOT_TOKEN - Telegram Bot API token (from @BotFather)
TELEGRAM_CHAT_ID - Telegram chat/group ID for notifications

Telegram Setup: See scripts/README.telegram.md for complete configuration guide.

Volume Configuration

  • Upload Limits: 100MB maximum file size for batch uploads
  • Supported Formats: JPG, JPEG, PNG, GIF, WebP

Backup & Restore

Backup slideshow data

docker cp image-uploader-backend:/usr/src/app/src/data/ ./image-uploader-backup-data

Restore slideshow data

docker cp ./image-uploader-backup-data image-uploader-backend:/usr/src/app/src/data

Contributing

Contributions are welcome!
This project extends the original work by vallezw.

Development Setup

  1. Fork the repository
  2. Create feature branch: git checkout -b feature/amazing-feature
  3. Commit changes: git commit -m 'Add amazing feature'
  4. Push to branch: git push origin feature/amazing-feature| Field | Type | Description |#### Changing the URL
  5. Open a Pull Request

License

This project is distributed under the MIT License. See LICENSE for more information.

Acknowledgments