# 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](https://github.com/vallezw/Image-Uploader) 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 - **๏ฟฝ 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 ### Docker Deployment (Recommended) #### Production Environment ```bash # Start production environment ./prod.sh # Or manually: docker compose -f docker/prod/docker-compose.yml up -d ``` #### Development Environment ```bash # 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 ); ``` ### Social Media Consent Tables ``` sql -- 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 ``` sql -- 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 ``` sql -- 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 ### Consent Management - `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: ```bash # 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`](tests/TESTING-CLEANUP.md) ## Configuration ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `API_URL` | `http://localhost:5001` | Backend API endpoint | | `CLIENT_URL` | `http://localhost` | Frontend application URL | | `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 ```sh docker cp image-uploader-backend:/usr/src/app/src/data/ ./image-uploader-backup-data ``` #### Restore slideshow data ```sh 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](https://github.com/vallezw/Image-Uploader). ### 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 - Original project: [Image-Uploader by vallezw](https://github.com/vallezw/Image-Uploader)