# SmoothSchedule - Multi-Tenant Scheduling Platform A production-ready multi-tenant SaaS platform for resource scheduling and orchestration. ## ๐ŸŽฏ Features - โœ… **Multi-Tenancy**: PostgreSQL schema-per-tenant using django-tenants - โœ… **8-Tier Role Hierarchy**: From SUPERUSER to CUSTOMER with strict permissions - โœ… **Modern Stack**: Django 5.2 + React 18 + Vite - โœ… **Docker Ready**: Complete production & development Docker Compose setup - โœ… **Cloud Storage**: DigitalOcean Spaces (S3-compatible) for static/media files - โœ… **Auto SSL**: Let's Encrypt certificates via Traefik reverse proxy - โœ… **Task Queue**: Celery + Redis for background jobs - โœ… **Real-time**: Django Channels + WebSockets support - โœ… **Production Ready**: Fully configured for deployment ## ๐Ÿ“š Documentation - **[PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md)** - **Manual step-by-step production deployment** (start here for fresh deployments) - **[QUICK-REFERENCE.md](QUICK-REFERENCE.md)** - Common commands and quick start - **[PRODUCTION-READY.md](PRODUCTION-READY.md)** - Production deployment status - **[DEPLOYMENT.md](DEPLOYMENT.md)** - Comprehensive deployment guide - **[CLAUDE.md](CLAUDE.md)** - Development guide and architecture ## ๐Ÿš€ Quick Start ### Local Development ```bash # Start backend (Django in Docker) cd smoothschedule docker compose -f docker-compose.local.yml up -d # Start frontend (React with Vite) cd ../frontend npm install npm run dev # Access the app # Frontend: http://platform.lvh.me:5173 # Backend API: http://lvh.me:8000/api ``` See [CLAUDE.md](CLAUDE.md) for detailed development instructions. ### Production Deployment For **fresh deployments or complete reset**, follow [PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md) for manual step-by-step instructions. For **routine updates**, use the automated script: ```bash # Deploy to production server (code changes only) ./deploy.sh poduck@smoothschedule.com ``` See [PRODUCTION-READY.md](PRODUCTION-READY.md) for deployment checklist and [DEPLOYMENT.md](DEPLOYMENT.md) for detailed steps. ## ๐Ÿ—๏ธ Architecture ### Multi-Tenancy Model ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ PostgreSQL Database โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ public (shared schema) โ”‚ โ”‚ โ”œโ”€ Tenants โ”‚ โ”‚ โ”œโ”€ Domains โ”‚ โ”‚ โ”œโ”€ Users โ”‚ โ”‚ โ””โ”€ PermissionGrants โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ tenant_demo (schema for Demo Company) โ”‚ โ”‚ โ”œโ”€ Appointments โ”‚ โ”‚ โ”œโ”€ Resources โ”‚ โ”‚ โ””โ”€ Customers โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ tenant_acme (schema for Acme Corp) โ”‚ โ”‚ โ”œโ”€ Appointments โ”‚ โ”‚ โ”œโ”€ Resources โ”‚ โ”‚ โ””โ”€ Customers โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` ### Role Hierarchy | Role | Level | Access Scope | |---------------------|----------|---------------------------| | SUPERUSER | Platform | All tenants (god mode) | | PLATFORM_MANAGER | Platform | All tenants | | PLATFORM_SALES | Platform | Demo accounts only | | PLATFORM_SUPPORT | Platform | Tenant users | | TENANT_OWNER | Tenant | Own tenant (full access) | | TENANT_MANAGER | Tenant | Own tenant | | TENANT_STAFF | Tenant | Own tenant (limited) | | CUSTOMER | Tenant | Own data only | ### Masquerading Matrix | Hijacker Role | Can Masquerade As | |--------------------|----------------------------------| | SUPERUSER | Anyone | | PLATFORM_SUPPORT | Tenant users | | PLATFORM_SALES | Demo accounts (`is_temporary=True`) | | TENANT_OWNER | Staff in same tenant | | Others | No one | **Security Rules:** - Cannot hijack yourself - Cannot hijack SUPERUSERs (except by other SUPERUSERs) - Maximum depth: 1 (no hijack chains) - All attempts logged to `logs/masquerade.log` ## ๐Ÿ“ Project Structure ``` smoothschedule/ โ”œโ”€โ”€ config/ โ”‚ โ””โ”€โ”€ settings.py # Multi-tenancy & security config โ”œโ”€โ”€ core/ โ”‚ โ”œโ”€โ”€ models.py # Tenant, Domain, PermissionGrant โ”‚ โ”œโ”€โ”€ permissions.py # Hijack permission matrix โ”‚ โ”œโ”€โ”€ middleware.py # Masquerade audit logging โ”‚ โ””โ”€โ”€ admin.py # Django admin for core models โ”œโ”€โ”€ users/ โ”‚ โ”œโ”€โ”€ models.py # Custom User with 8-tier roles โ”‚ โ””โ”€โ”€ admin.py # User admin with hijack button โ”œโ”€โ”€ logs/ โ”‚ โ”œโ”€โ”€ security.log # General security events โ”‚ โ””โ”€โ”€ masquerade.log # Hijack activity (JSON) โ””โ”€โ”€ setup_project.sh # Automated setup script ``` ## ๐Ÿ” Security Features ### Audit Logging All masquerade activity is logged in JSON format: ```json { "timestamp": "2024-01-15T10:30:00Z", "action": "HIJACK_START", "hijacker_email": "support@smoothschedule.com", "hijacked_email": "customer@demo.com", "ip_address": "192.168.1.1", "session_key": "abc123..." } ``` ### Permission Grants (30-Minute Window) Time-limited elevated permissions: ```python from core.models import PermissionGrant grant = PermissionGrant.create_grant( grantor=admin_user, grantee=support_user, action="view_billing", reason="Customer requested billing support", duration_minutes=30, ) # Check if active if grant.is_active(): # Perform privileged action pass ``` ## ๐Ÿงช Testing Masquerading 1. Access Django Admin: `http://localhost:8000/admin/` 2. Create test users with different roles 3. Click "Hijack" button next to a user 4. Verify audit logs: `docker-compose exec django cat logs/masquerade.log` ## ๐Ÿ“Š Admin Interface - **Tenant Management**: View tenants, domains, subscription tiers - **User Management**: Color-coded roles, masquerade buttons - **Permission Grants**: Active/expired/revoked status, bulk revoke - **Domain Verification**: AWS Route53 integration status ## ๐Ÿ› ๏ธ Development ### Adding Tenant Apps Edit `config/settings.py`: ```python TENANT_APPS = [ 'django.contrib.contenttypes', 'appointments', # Your app 'resources', # Your app 'billing', # Your app ] ``` ### Custom Domain Setup ```python domain = Domain.objects.create( domain="app.customdomain.com", tenant=tenant, is_custom_domain=True, route53_zone_id="Z1234567890ABC", ) ``` Then configure Route53 CNAME: `app.customdomain.com` โ†’ `smoothschedule.yourhost.com` ## ๐Ÿ“– Key Files Reference | File | Purpose | |------|---------| | `setup_project.sh` | Automated project initialization | | `config/settings.py` | Multi-tenancy, middleware, security config | | `core/models.py` | Tenant, Domain, PermissionGrant models | | `core/permissions.py` | Masquerading permission matrix | | `core/middleware.py` | Audit logging for masquerading | | `users/models.py` | Custom User with 8-tier roles | ## ๐Ÿ“ Important Notes - **Django Admin**: The ONLY HTML interface (everything else is API) - **Middleware Order**: `TenantMainMiddleware` must be first, `MasqueradeAuditMiddleware` after `HijackUserMiddleware` - **Tenant Isolation**: Each tenant's data is in a separate PostgreSQL schema - **Production**: Update `SECRET_KEY`, database credentials, and AWS keys via environment variables ## ๐Ÿ› Troubleshooting **Cannot create tenant users:** - Error: "Users with role TENANT_STAFF must be assigned to a tenant" - Solution: Set `user.tenant = tenant_instance` before saving **Hijack button doesn't appear:** - Check `HIJACK_AUTHORIZATION_CHECK` in settings - Verify `HijackUserAdminMixin` in `users/admin.py` - Ensure user has permission per matrix rules **Migrations fail:** - Run shared migrations first: `migrate_schemas --shared` - Then run tenant migrations: `migrate_schemas` ## ๐Ÿ“„ License MIT ## ๐Ÿค Contributing This is a production skeleton. Extend `TENANT_APPS` with your business logic. --- **Built with โค๏ธ for multi-tenant SaaS perfection**