Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
venv/
__pycache__/
data/
logs/

env
env.backup
Expand All @@ -11,7 +10,6 @@ config.mk
*.db

src/staticfiles/*
src/media/
.idea/**


Expand Down
150 changes: 42 additions & 108 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,20 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Project Overview

This is a **Data Room Application** - a secure file upload and management system for collecting customer data files for proof-of-concept development. Built on Django with django-allauth (2FA + SSO support), it enables internal teams to provision UUID-based upload endpoints for customers while maintaining complete privacy and audit trails.
This is a Django Reference Implementation - a production-ready Django SaaS template with organizations, invitations, and authentication. It follows a pragmatic approach to building multi-tenant applications with minimal dependencies.

## Architecture

### Core Apps Structure
- **config/**: Django project configuration (settings, URLs, WSGI/ASGI)
- **myapp/**: Base application with site configuration models and templates
- **dataroom/**: File upload system with customers, endpoints, and audit logging
- **require2fa/**: Two-factor authentication enforcement middleware
- **myapp/**: Base application with site configuration models, templates, and management commands
- **organizations/**: Complete multi-tenant organization system with invitations and user management

### Key Components
- **Authentication**: Uses django-allauth with 2FA support and SSO-ready (Okta)
- **File Management**: Local filesystem storage with UUID-based endpoint privacy
- **Admin Interface**: Django admin for internal team management of customers and endpoints
- **Audit Logging**: Complete tracking of file uploads, deletions, and staff downloads
- **UI Framework**: Tailwind CSS via Play CDN with dark mode support and Heroicons
- **Templates**: Minimal, professional upload interface with responsive design

## Data Room Features

### Customer & Endpoint Management
- **Customers**: Internal tracking of companies/projects receiving upload endpoints
- **Data Endpoints**: UUID-based upload URLs that don't expose customer information
- **Multiple Endpoints**: Each customer can have multiple endpoints for different POCs
- **Status Control**: Endpoints can be active, disabled, or archived

### File Upload System
- **Anonymous Upload**: Customers upload via UUID URL (no authentication required)
- **Security**: Filename sanitization, path traversal prevention, duplicate handling
- **Soft Delete**: Customers can request deletion (immediate with audit trail)
- **File Listing**: Customers can view all files uploaded to their endpoint

### Staff Features (Django Admin)
- **Customer Management**: Create customers with freeform notes
- **Endpoint Creation**: Generate new upload endpoints with one-click URL copying
- **File Downloads**: Secure download with automatic audit logging
- **Audit Dashboard**: View all file downloads and deletion activity
- **Authentication**: Uses django-allauth with 2FA support
- **Async Processing**: Custom worker pattern using Django management commands with PostgreSQL as task queue
- **Multi-tenancy**: Organization-based tenancy with invitation system
- **Templates**: Bootstrap 5 UI with dark mode support

## Git Workflow for Claude Code

Expand Down Expand Up @@ -110,7 +87,9 @@ uv run src/manage.py <command>
# Key management commands:
uv run src/manage.py migrate
uv run src/manage.py createsuperuser
uv run src/manage.py test
uv run src/manage.py simple_async_worker
uv run src/manage.py send_email_confirmation
uv run src/manage.py send_email_invite
```

### Code Quality
Expand All @@ -137,48 +116,43 @@ uv run vulture src/ --min-confidence 80 # Find unused code (high confidence)
uv run vulture src/ --min-confidence 60 # Find unused code (medium confidence)

# Type checking
cd src && DJANGO_SETTINGS_MODULE=config.settings uv run mypy dataroom/ myapp/ config/ --ignore-missing-imports --disable-error-code=var-annotated
cd src && DJANGO_SETTINGS_MODULE=config.settings uv run mypy organizations/ myapp/ config/ --ignore-missing-imports --disable-error-code=var-annotated
```

## Development Workflow

### Local Development
- Uses Docker Compose for PostgreSQL and Mailpit
- Django runs locally or in Docker
- Uses Docker Compose for services (PostgreSQL, Mailpit, S3Proxy)
- Django can run locally or in Docker
- Environment variables configured in `env` file (copy from `env.sample`)
- File uploads stored in `src/media/uploads/{endpoint-uuid}/`

### Testing
- Tests located in `*/tests.py` or `*/tests/` directories
- Tests located in `*/tests/` directories
- Run with `uv run src/manage.py test`
- Covers models, views, upload/download functionality, and security
- Covers models, views, and forms

### URL Structure
- **Public (No Auth)**: `/upload/{uuid}/` - Customer upload page
- **Admin Only**: `/admin/` - Django admin interface
- **Staff Downloads**: Via Django admin actions (with audit logging)
### Worker System
- Custom async worker pattern using Django management commands
- Workers defined in `*/management/commands/`
- Uses PostgreSQL for task queue (no Redis/Celery required)
- Configure workers in `docker-compose.yml`

## Important Files

### Configuration
- `src/config/settings.py`: Main Django settings
- `pyproject.toml`: Project metadata and tool configuration (ruff, bandit)
- `docker-compose.yml`: Development services (PostgreSQL, Mailpit)
- `docker-compose.yml`: Development services
- `Makefile`: Development automation commands
- `env`: Environment variables (copy from `env.sample`)

### Models
- `dataroom/models.py`: Customer, DataEndpoint, UploadedFile, FileDownload
- `myapp/models/`: Site configuration model
- `require2fa/models.py`: Two-factor configuration model

### Views & Templates
- `dataroom/views.py`: Upload page, file upload handler, delete handler
- `dataroom/templates/dataroom/`: Upload page, disabled/archived templates
- `dataroom/admin.py`: Complete admin configuration with download actions
- `myapp/models/`: Site configuration and worker models
- `organizations/models.py`: Organization and invitation models

### Tests
- `dataroom/tests.py`: Comprehensive model and view tests
### Templates
- `templates/`: Global templates (base, auth, pages)
- `myapp/templates/`: App-specific templates
- `organizations/templates/`: Organization management templates

## Code Standards

Expand All @@ -189,17 +163,10 @@ cd src && DJANGO_SETTINGS_MODULE=config.settings uv run mypy dataroom/ myapp/ co

### File Organization
- Apps follow Django conventions
- Models in `models.py` or `models/` directory
- Views in `views.py` or `views/` directory
- Models in `models/` directory (may be split into multiple files)
- Views in `views/` directory
- Management commands in `management/commands/`
- Templates in `templates/` with app namespacing
- Admin configurations in `admin.py`

### Security
- **Filename Sanitization**: `sanitize_filename()` prevents path traversal
- **UUID Endpoints**: No customer information exposed in URLs
- **IP Tracking**: All uploads, deletes, and downloads log IP addresses
- **Soft Deletes**: Files marked deleted but retained for audit
- **Staff-Only Downloads**: File downloads only via authenticated admin

## Dependencies

Expand All @@ -210,63 +177,30 @@ cd src && DJANGO_SETTINGS_MODULE=config.settings uv run mypy dataroom/ myapp/ co
- Install with `uv sync` or `uv sync --extra dev`

### Core Dependencies
- Django 5.2.5
- Django 5.2.3
- Python 3.12
- PostgreSQL 16
- django-allauth (authentication with MFA and SSO support)
- django-allauth-require2fa (2FA enforcement)
- django-solo (singleton models)
- Tailwind CSS (via Play CDN - no build process required)
- Heroicons (SVG icon library)
- django-allauth (authentication)
- django-bootstrap5 (UI)
- django-storages (S3 support)

### Development Dependencies
- ruff (linting/formatting)
- pre-commit (hooks)
- mypy + django-stubs (type checking)
- bandit (security scanning)
- radon (complexity analysis)
- vulture (dead code detection)

## Environment Variables

Key environment variables (defined in `env` file):
- `DEBUG`: Development mode flag
- `SECRET_KEY`: Django secret key
- `BASE_URL`: Application base URL (used for upload URL generation)
- `DATABASE_URL`: PostgreSQL connection string
- `EMAIL_URL`: Email backend configuration (console, SMTP, etc.)

## File Storage

### Structure
```
src/media/
uploads/
{endpoint-uuid}/
filename.ext
filename-20250117143022-1.ext # Duplicate with timestamp
```

### Handling
- Files stored in MEDIA_ROOT (`src/media/`)
- Organized by endpoint UUID for isolation
- Duplicate filenames auto-renamed with timestamp
- Soft deletes keep files on disk for audit/recovery
- `BASE_URL`: Application base URL
- `DATABASE_URL`: PostgreSQL connection
- `AWS_*`: S3 configuration
- Email settings for django-allauth

## Deployment

- Docker-based deployment ready
- Heroku/Dokku compatible with `Procfile`
- Static files served via WhiteNoise
- File uploads served securely via Django (for staff only)
- Uses environment variables for all configuration
- Database migrations handled via release phase

## Future Enhancements

- SSO integration with Okta (django-allauth is already SSO-ready)
- File size limits and validation
- Virus scanning integration
- Automated file expiration/archival
- Email notifications for uploads
- Download links for customers (with expiration)
- Docker-based deployment
- Heroku/Dokku ready with `Procfile`
- Static files served by Django or S3
- Uses environment variables for configuration
8 changes: 0 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@ snapshot-local-db: ## Create a snapshot of the local database
restore-local-db: ## Restore the local database from a snapshot
docker compose exec -T postgres pg_restore -U postgres -d django_reference < django_reference.dump

logs/:
mkdir -p logs/

.PHONY: runserver
runserver: logs/ ## Run Django development server with logging to logs/server.log
@echo "Starting Django server on http://0.0.0.0:8008 (logs: logs/server.log)"
uv run src/manage.py runserver 0.0.0.0:8008 2>&1 | tee logs/server.log

##########################################################################
# DJANGO-ALLAUTH DEPENDENCY MANAGEMENT
##########################################################################
Expand Down
Binary file removed db.sqlite3
Binary file not shown.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies = [
"charset-normalizer==3.4.3",
"django-environ==0.12.0",
"Django==5.2.5",
"django-bootstrap5==25.2",
"django-solo==2.4.0",
"gunicorn==23.0.0",
"idna==3.10",
Expand Down
13 changes: 11 additions & 2 deletions src/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@

CSRF_TRUSTED_ORIGINS = [BASE_URL]

# CONFIGURATION for django-storages
AWS_ACCESS_KEY_ID = env("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = env("AWS_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = env("AWS_STORAGE_BUCKET_NAME")
AWS_S3_REGION_NAME = env("AWS_S3_REGION_NAME")
AWS_S3_ENDPOINT_URL = env("AWS_S3_ENDPOINT_URL")
AWS_S3_USE_SSL = env("AWS_S3_USE_SSL")

ALLOWED_HOSTS = ["*"]

INSTALLED_APPS = [
Expand All @@ -35,7 +43,8 @@
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.sites",
"dataroom",
"django_bootstrap5",
"organizations",
"myapp",
"require2fa",
"allauth",
Expand Down Expand Up @@ -186,4 +195,4 @@
},
}

LOGIN_REDIRECT_URL = "/admin/"
LOGIN_REDIRECT_URL = "/accounts/email/"
7 changes: 6 additions & 1 deletion src/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

import myapp.views

# import urls from the organizations app

urlpatterns = [ # noqa: RUF005
path(
"robots.txt",
Expand All @@ -19,7 +21,10 @@
path("accounts/", include("allauth.urls")),
path("", myapp.views.index, name="home"),
path("health-check/", myapp.views.health_check, name="health-check"),
path("", include("dataroom.urls")),
path(
"organizations/",
include(("organizations.urls", "organizations"), namespace="organizations"),
),
# add privacy policy and terms of service URLs here use TemplateView.as_view
path("privacy/", TemplateView.as_view(template_name="privacy.html"), name="privacy"),
path("terms/", TemplateView.as_view(template_name="terms.html"), name="terms"),
Expand Down
Loading
Loading