No description
Find a file
Miguel de la Cruz 9a575bd2fb Implement Phase 4: Media Sharing - Upload, Gallery, and Anonymous Access
Complete implementation of photo and video sharing with anonymous guest access.

Features:
- Media upload with security validation (MIME type checking via magic bytes)
- File size limits (100MB max per file)
- Filesystem storage in ./media/event_{id}/ directories
- Media gallery with responsive grid layout (150px min columns)
- Share link generation with 32-byte random tokens (256-bit entropy)
- Anonymous upload and viewing via share links (no login required)
- Delete functionality (uploader or event creator only)

Handlers (server/handlers.go, ~800 new lines):
- handleMediaUpload: Multi-part upload for authenticated and anonymous users
- handleMediaGallery: Gallery view with upload form and share management
- handleMediaServe: Secure file serving with access control
- handleMediaDelete: Delete media (restricted to uploader/creator)
- handleShareLinkCreate: Generate cryptographically secure share tokens
- handleShareLinkDelete: Revoke share links
- handleSharePage: Public anonymous gallery with routing
- handleShareUpload: Anonymous file upload via share token
- handleShareMediaServe: Serve media to anonymous users

Templates:
- media_gallery.html: Authenticated gallery with grid, upload, share management
- share_page.html: Anonymous public gallery with upload capability
- Updated event_detail.html: Added "View Media Gallery" button

Routing:
- /events/{id}/media - Gallery (authenticated)
- /events/{id}/media/upload - Upload (authenticated)
- /events/{id}/media/{mediaId} - Serve file (authenticated)
- /events/{id}/media/{mediaId}/delete - Delete (authenticated)
- /events/{id}/share - Create share link (creator only)
- /events/{id}/share/{shareId}/delete - Delete share link (creator only)
- /share/{token} - Public gallery (anonymous)
- /share/{token}/upload - Anonymous upload
- /share/{token}/media/{mediaId} - Serve via share token

Security:
- MIME validation using http.DetectContentType (first 512 bytes)
- Unique filenames: {timestamp}_{random_hex}.{ext}
- Access control verification before file serving
- Anonymous uploads tracked separately for privacy
- Supported types: JPEG, PNG, GIF, WebP, MP4, MOV, AVI

Documentation:
- Updated DESIGN.md Phase 4 status: ✅ Complete
- Overall completion: 60% → 75%
- Updated implementation status table

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-08 21:02:32 +01:00
cmd/walle Fix model definitions and CLI for optional fields 2026-01-08 17:02:25 +01:00
config Add JSON configuration system and user CRUD commands 2026-01-07 23:28:50 +01:00
model Fix model definitions and CLI for optional fields 2026-01-08 17:02:25 +01:00
server Implement Phase 4: Media Sharing - Upload, Gallery, and Anonymous Access 2026-01-08 21:02:32 +01:00
store Add authentication system with login and JWT 2026-01-07 23:46:47 +01:00
.air.toml Add initial project structure with CLI and HTTP server 2026-01-04 18:16:39 +01:00
.gitignore Add initial project structure with CLI and HTTP server 2026-01-04 18:16:39 +01:00
.golangci.yml Add initial project structure with CLI and HTTP server 2026-01-04 18:16:39 +01:00
DESIGN.md Implement Phase 4: Media Sharing - Upload, Gallery, and Anonymous Access 2026-01-08 21:02:32 +01:00
docker-compose.yml Add Docker deployment support and improve documentation 2026-01-08 16:29:38 +01:00
Dockerfile Update Dockerfile to include gcc for CGO builds 2026-01-08 19:38:06 +01:00
go.mod Update go mod after a tidy 2026-01-07 23:47:41 +01:00
go.sum Update go mod after a tidy 2026-01-07 23:47:41 +01:00
Makefile Fix model definitions and CLI for optional fields 2026-01-08 17:02:25 +01:00
PROGRESS.md Add interactive item management and expense tracking to event details 2026-01-08 01:50:08 +01:00
README.md Add Docker deployment support and improve documentation 2026-01-08 16:29:38 +01:00
UI_REDESIGN_PLAN.md Implement Phase 1: Mobile-First Design System Foundation 2026-01-08 02:14:34 +01:00
UI_REDESIGN_SUMMARY.md Implement Phase 1: Mobile-First Design System Foundation 2026-01-08 02:14:34 +01:00

Walle

Walle is a web application designed to simplify event organization and management among groups of people. It is a simple, lightweight, and self-hostable application with minimal dependencies.

Core Features

Walle provides three core features:

  1. Shopping List Management: A collaborative list where members can add items and assign responsibility.
  2. Expense Settlement: Automatic calculation of who owes whom with minimum transactions.
  3. Media Sharing: Upload and share photos/videos from the event with members and guests.

Project Goals

  • Simple, lightweight application with minimal dependencies.
  • Self-hostable with SQLite as the primary database.
  • A web interface as the main UI, with a CLI available for administration.
  • Privacy-focused with secure sharing mechanisms.
  • Fast, responsive UI using HTMX patterns.

Development

Requirements

  • Go 1.24 or later.
  • Make (for using the Makefile commands).

Setup and Running

  1. Clone the repository:

    git clone <repository-url>
    cd walle
    
  2. Install dependencies:

    go mod download
    
  3. Initialize the database: This command sets up the initial database schema.

    make db-init
    
  4. Run the development server: The server will run on http://localhost:8080 by default and uses air for live reloading.

    make dev
    
  5. Use the CLI: The CLI can be used for administrative tasks. For example, to create a user:

    go run ./cmd/walle/main.go user create --email test@example.com --name "Test User"
    

    Available CLI commands:

    • walle serve - Start the web server
    • walle user create --email <email> --name <name> - Create a new user
    • walle user list - List all users
    • walle event list - List all events
    • walle event create --name <name> --creator <user-id> - Create an event

Build and Installation

Walle is designed to be deployed as a single, self-contained binary. All necessary assets like templates and migrations are embedded into the application.

Building from Source

  1. Build the binary:

    # Build both server and CLI
    make build
    
    # Or build individually
    make build-server  # Creates bin/server
    make build-cli     # Creates bin/walle
    

    The binaries will be created in the bin/ directory.

  2. Development build:

    # Run with auto-reload (requires air)
    make dev
    
    # Or install air and run manually
    go install github.com/air-verse/air@latest
    air
    

Docker Deployment

Walle includes Docker support for easy containerized deployment.

  1. Build Docker image:

    make docker-build
    # or
    docker build -t walle:latest .
    
  2. Run with Docker:

    make docker-run
    # or
    docker run -p 8080:8080 \
      -v $(pwd)/data:/app/data \
      -v $(pwd)/media:/app/media \
      walle:latest
    
  3. Run with Docker Compose:

    docker-compose up -d
    

Production Deployment

  1. Using the binary:

    • Copy the bin/server binary to your server
    • Create a systemd service or init script to run it
    • Ensure the user has write permissions for data and media directories
  2. Using Docker in production:

    • Use the provided docker-compose.yml
    • Mount persistent volumes for /app/data and /app/media
    • Configure reverse proxy (nginx/Caddy) for SSL and load balancing
  3. Environment Configuration: Set these environment variables for production:

    # Server configuration
    WALLE_HOST=0.0.0.0
    WALLE_PORT=8080
    
    # Security
    WALLE_JWT_SECRET=your-super-secret-jwt-key-here
    WALLE_SESSION_TIMEOUT=86400
    
    # Optional: External database (defaults to SQLite)
    WALLE_DATABASE_URL=postgres://user:pass@localhost/walle
    
    # Optional: File storage
    WALLE_MEDIA_PATH=/var/lib/walle/media
    WALLE_MAX_UPLOAD_SIZE=104857600  # 100MB in bytes
    
  4. Reverse Proxy Configuration (nginx example):

    server {
        listen 80;
        server_name your-domain.com;
    
        location / {
            proxy_pass http://localhost:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    
        # Cache static assets
        location /static/ {
            proxy_pass http://localhost:8080;
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
    

API

Walle provides a REST API for programmatic access. The API is primarily used by the HTMX frontend but can be used for integrations.

Health Check

GET /health

Returns: {"status":"ok","service":"walle"}

Authentication

All protected endpoints require a JWT token in the auth_token cookie or Authorization: Bearer <token> header.

Troubleshooting

Common Issues

  1. Database errors:

    • Ensure the application has write permissions to the current directory
    • Check if walle.db is corrupted: rm walle.db and restart
  2. Media upload fails:

    • Verify write permissions on the media/ directory
    • Check upload size limits in your reverse proxy
  3. JWT authentication issues:

    • Ensure WALLE_JWT_SECRET is set and consistent across restarts
    • Clear cookies if experiencing persistent auth issues
  4. Docker issues:

    • Check volume mounts: docker-compose logs walle
    • Ensure ports aren't conflicting

Logs

The application logs to stdout/stderr. In production, capture these logs with your process manager.

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make your changes with tests
  4. Run checks: make check
  5. Commit your changes: git commit -am 'Add my feature'
  6. Push to the branch: git push origin feature/my-feature
  7. Submit a pull request

Development Setup

# Clone and setup
git clone <your-fork-url>
cd walle
make deps
make install-tools
make dev

Code Quality

  • Run tests: make test
  • Format code: make fmt
  • Lint: make lint
  • Full check: make check

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For questions, issues, or contributions: