docs: Update README with comprehensive setup and deployment guide
- Updated project structure to reflect current domain-based organization - Added detailed local development setup with lvh.me explanation - Added production deployment instructions (quick deploy and fresh server) - Documented environment variables configuration - Added architecture diagrams for multi-tenancy and request flow - Included troubleshooting section for common issues - Updated role hierarchy documentation - Added configuration files reference table 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
655
README.md
655
README.md
@@ -1,257 +1,470 @@
|
|||||||
# SmoothSchedule - Multi-Tenant Scheduling Platform
|
# SmoothSchedule - Multi-Tenant Scheduling Platform
|
||||||
|
|
||||||
A production-ready multi-tenant SaaS platform for resource scheduling and orchestration.
|
A production-ready multi-tenant SaaS platform for resource scheduling, appointments, and business management.
|
||||||
|
|
||||||
## 🎯 Features
|
## Features
|
||||||
|
|
||||||
- ✅ **Multi-Tenancy**: PostgreSQL schema-per-tenant using django-tenants
|
- **Multi-Tenancy**: PostgreSQL schema-per-tenant using django-tenants
|
||||||
- ✅ **8-Tier Role Hierarchy**: From SUPERUSER to CUSTOMER with strict permissions
|
- **8-Tier Role Hierarchy**: SUPERUSER, PLATFORM_MANAGER, PLATFORM_SALES, PLATFORM_SUPPORT, TENANT_OWNER, TENANT_MANAGER, TENANT_STAFF, CUSTOMER
|
||||||
- ✅ **Modern Stack**: Django 5.2 + React 18 + Vite
|
- **Modern Stack**: Django 5.2 + React 19 + TypeScript + Vite
|
||||||
- ✅ **Docker Ready**: Complete production & development Docker Compose setup
|
- **Real-time Updates**: Django Channels + WebSockets
|
||||||
- ✅ **Cloud Storage**: DigitalOcean Spaces (S3-compatible) for static/media files
|
- **Background Tasks**: Celery + Redis
|
||||||
- ✅ **Auto SSL**: Let's Encrypt certificates via Traefik reverse proxy
|
- **Auto SSL**: Let's Encrypt certificates via Traefik
|
||||||
- ✅ **Task Queue**: Celery + Redis for background jobs
|
- **Cloud Storage**: DigitalOcean Spaces (S3-compatible)
|
||||||
- ✅ **Real-time**: Django Channels + WebSockets support
|
- **Docker Ready**: Complete Docker Compose setup for dev and production
|
||||||
- ✅ **Production Ready**: Fully configured for deployment
|
|
||||||
|
|
||||||
## 📚 Documentation
|
## Project Structure
|
||||||
|
|
||||||
- **[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
|
smoothschedule2/
|
||||||
- **[PRODUCTION-READY.md](PRODUCTION-READY.md)** - Production deployment status
|
├── frontend/ # React + Vite + TypeScript
|
||||||
- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Comprehensive deployment guide
|
│ ├── src/
|
||||||
- **[CLAUDE.md](CLAUDE.md)** - Development guide and architecture
|
│ │ ├── api/ # API client and hooks
|
||||||
|
│ │ ├── components/ # Reusable UI components
|
||||||
|
│ │ ├── hooks/ # React Query hooks
|
||||||
|
│ │ ├── pages/ # Page components
|
||||||
|
│ │ └── types.ts # TypeScript interfaces
|
||||||
|
│ ├── nginx.conf # Production nginx config
|
||||||
|
│ └── Dockerfile.prod # Production frontend container
|
||||||
|
│
|
||||||
|
├── smoothschedule/ # Django backend
|
||||||
|
│ ├── config/ # Django settings
|
||||||
|
│ │ └── settings/
|
||||||
|
│ │ ├── base.py # Base settings
|
||||||
|
│ │ ├── local.py # Local development
|
||||||
|
│ │ └── production.py # Production settings
|
||||||
|
│ ├── smoothschedule/ # Django apps (domain-based)
|
||||||
|
│ │ ├── identity/ # Users, tenants, authentication
|
||||||
|
│ │ │ ├── core/ # Tenant, Domain, middleware
|
||||||
|
│ │ │ └── users/ # User model, MFA, auth
|
||||||
|
│ │ ├── scheduling/ # Core scheduling
|
||||||
|
│ │ │ ├── schedule/ # Resources, Events, Services
|
||||||
|
│ │ │ ├── contracts/ # E-signatures
|
||||||
|
│ │ │ └── analytics/ # Business analytics
|
||||||
|
│ │ ├── communication/ # Notifications, SMS, mobile
|
||||||
|
│ │ ├── commerce/ # Payments, tickets
|
||||||
|
│ │ └── platform/ # Admin, public API
|
||||||
|
│ ├── docker-compose.local.yml
|
||||||
|
│ └── docker-compose.production.yml
|
||||||
|
│
|
||||||
|
├── deploy.sh # Automated deployment script
|
||||||
|
└── CLAUDE.md # Development guide
|
||||||
|
```
|
||||||
|
|
||||||
## 🚀 Quick Start
|
---
|
||||||
|
|
||||||
### Local Development
|
## Local Development Setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- **Docker** and **Docker Compose** (for backend)
|
||||||
|
- **Node.js 22+** and **npm** (for frontend)
|
||||||
|
- **Git**
|
||||||
|
|
||||||
|
### Step 1: Clone the Repository
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Start backend (Django in Docker)
|
git clone https://github.com/your-repo/smoothschedule.git
|
||||||
cd smoothschedule
|
cd smoothschedule
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Start the Backend (Django in Docker)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd smoothschedule
|
||||||
|
|
||||||
|
# Start all backend services
|
||||||
docker compose -f docker-compose.local.yml up -d
|
docker compose -f docker-compose.local.yml up -d
|
||||||
|
|
||||||
# Start frontend (React with Vite)
|
# Wait for services to initialize (first time takes longer)
|
||||||
cd ../frontend
|
sleep 30
|
||||||
npm install
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# Access the app
|
# Run database migrations
|
||||||
# Frontend: http://platform.lvh.me:5173
|
docker compose -f docker-compose.local.yml exec django python manage.py migrate
|
||||||
# Backend API: http://lvh.me:8000/api
|
|
||||||
|
# Create a superuser (optional)
|
||||||
|
docker compose -f docker-compose.local.yml exec django python manage.py createsuperuser
|
||||||
```
|
```
|
||||||
|
|
||||||
See [CLAUDE.md](CLAUDE.md) for detailed development instructions.
|
### Step 3: Start the Frontend (React with Vite)
|
||||||
|
|
||||||
### 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
|
```bash
|
||||||
# Deploy to production server (code changes only)
|
cd ../frontend
|
||||||
./deploy.sh poduck@smoothschedule.com
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Start development server
|
||||||
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
See [PRODUCTION-READY.md](PRODUCTION-READY.md) for deployment checklist and [DEPLOYMENT.md](DEPLOYMENT.md) for detailed steps.
|
### Step 4: Access the Application
|
||||||
|
|
||||||
## 🏗️ Architecture
|
The application uses `lvh.me` (resolves to 127.0.0.1) for subdomain-based multi-tenancy:
|
||||||
|
|
||||||
|
| URL | Purpose |
|
||||||
|
|-----|---------|
|
||||||
|
| http://platform.lvh.me:5173 | Platform admin dashboard |
|
||||||
|
| http://demo.lvh.me:5173 | Demo tenant (if created) |
|
||||||
|
| http://lvh.me:8000/api/ | Backend API |
|
||||||
|
| http://lvh.me:8000/admin/ | Django admin |
|
||||||
|
|
||||||
|
**Why `lvh.me`?** Browsers don't allow cookies with `domain=.localhost`, but `lvh.me` resolves to 127.0.0.1 and allows proper cookie sharing across subdomains.
|
||||||
|
|
||||||
|
### Local Development Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend commands (always use docker compose)
|
||||||
|
cd smoothschedule
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker compose -f docker-compose.local.yml logs -f django
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
docker compose -f docker-compose.local.yml exec django python manage.py migrate
|
||||||
|
|
||||||
|
# Django shell
|
||||||
|
docker compose -f docker-compose.local.yml exec django python manage.py shell
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
docker compose -f docker-compose.local.yml exec django pytest
|
||||||
|
|
||||||
|
# Stop all services
|
||||||
|
docker compose -f docker-compose.local.yml down
|
||||||
|
|
||||||
|
# Frontend commands
|
||||||
|
cd frontend
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
npm test
|
||||||
|
|
||||||
|
# Type checking
|
||||||
|
npm run typecheck
|
||||||
|
|
||||||
|
# Lint
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating a Test Tenant
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd smoothschedule
|
||||||
|
docker compose -f docker-compose.local.yml exec django python manage.py shell
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
from smoothschedule.identity.core.models import Tenant, Domain
|
||||||
|
|
||||||
|
# Create tenant
|
||||||
|
tenant = Tenant.objects.create(
|
||||||
|
name="Demo Business",
|
||||||
|
schema_name="demo",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create domain
|
||||||
|
Domain.objects.create(
|
||||||
|
domain="demo.lvh.me",
|
||||||
|
tenant=tenant,
|
||||||
|
is_primary=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"Created tenant: {tenant.name}")
|
||||||
|
print(f"Access at: http://demo.lvh.me:5173")
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Ubuntu/Debian server with Docker and Docker Compose
|
||||||
|
- Domain name with DNS configured:
|
||||||
|
- `A` record: `yourdomain.com` → Server IP
|
||||||
|
- `A` record: `*.yourdomain.com` → Server IP (wildcard)
|
||||||
|
- SSH access to the server
|
||||||
|
|
||||||
|
### Quick Deploy (Existing Server)
|
||||||
|
|
||||||
|
For routine updates to an existing production server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# From your local machine
|
||||||
|
./deploy.sh user@yourdomain.com
|
||||||
|
|
||||||
|
# Or deploy specific services
|
||||||
|
./deploy.sh user@yourdomain.com nginx
|
||||||
|
./deploy.sh user@yourdomain.com django
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fresh Server Deployment
|
||||||
|
|
||||||
|
#### Step 1: Server Setup
|
||||||
|
|
||||||
|
SSH into your server and install Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh user@yourdomain.com
|
||||||
|
|
||||||
|
# Install Docker
|
||||||
|
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||||
|
sudo sh get-docker.sh
|
||||||
|
sudo usermod -aG docker $USER
|
||||||
|
|
||||||
|
# Logout and login for group changes
|
||||||
|
exit
|
||||||
|
ssh user@yourdomain.com
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2: Clone Repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~
|
||||||
|
git clone https://github.com/your-repo/smoothschedule.git smoothschedule
|
||||||
|
cd smoothschedule
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 3: Configure Environment Variables
|
||||||
|
|
||||||
|
Create production environment files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p smoothschedule/.envs/.production
|
||||||
|
|
||||||
|
# Django configuration
|
||||||
|
cat > smoothschedule/.envs/.production/.django << 'EOF'
|
||||||
|
DJANGO_SECRET_KEY=your-random-secret-key-here
|
||||||
|
DJANGO_DEBUG=False
|
||||||
|
DJANGO_ALLOWED_HOSTS=yourdomain.com,*.yourdomain.com
|
||||||
|
|
||||||
|
DJANGO_ADMIN_URL=your-secret-admin-path/
|
||||||
|
FRONTEND_URL=https://platform.yourdomain.com
|
||||||
|
PLATFORM_BASE_URL=https://platform.yourdomain.com
|
||||||
|
|
||||||
|
REDIS_URL=redis://redis:6379/0
|
||||||
|
CELERY_BROKER_URL=redis://redis:6379/0
|
||||||
|
|
||||||
|
# DigitalOcean Spaces (or S3)
|
||||||
|
DJANGO_AWS_ACCESS_KEY_ID=your-access-key
|
||||||
|
DJANGO_AWS_SECRET_ACCESS_KEY=your-secret-key
|
||||||
|
DJANGO_AWS_STORAGE_BUCKET_NAME=your-bucket
|
||||||
|
DJANGO_AWS_S3_ENDPOINT_URL=https://nyc3.digitaloceanspaces.com
|
||||||
|
DJANGO_AWS_S3_REGION_NAME=nyc3
|
||||||
|
|
||||||
|
# SSL
|
||||||
|
DJANGO_SECURE_SSL_REDIRECT=True
|
||||||
|
DJANGO_SESSION_COOKIE_SECURE=True
|
||||||
|
DJANGO_CSRF_COOKIE_SECURE=True
|
||||||
|
|
||||||
|
# Cloudflare (for wildcard SSL)
|
||||||
|
CF_DNS_API_TOKEN=your-cloudflare-api-token
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# PostgreSQL configuration
|
||||||
|
cat > smoothschedule/.envs/.production/.postgres << 'EOF'
|
||||||
|
POSTGRES_HOST=postgres
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
POSTGRES_DB=smoothschedule
|
||||||
|
POSTGRES_USER=smoothschedule_user
|
||||||
|
POSTGRES_PASSWORD=your-secure-database-password
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 4: Build and Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/smoothschedule/smoothschedule
|
||||||
|
|
||||||
|
# Build all images
|
||||||
|
docker compose -f docker-compose.production.yml build
|
||||||
|
|
||||||
|
# Start services
|
||||||
|
docker compose -f docker-compose.production.yml up -d
|
||||||
|
|
||||||
|
# Wait for startup
|
||||||
|
sleep 30
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
docker compose -f docker-compose.production.yml exec django python manage.py migrate
|
||||||
|
|
||||||
|
# Collect static files
|
||||||
|
docker compose -f docker-compose.production.yml exec django python manage.py collectstatic --noinput
|
||||||
|
|
||||||
|
# Create superuser
|
||||||
|
docker compose -f docker-compose.production.yml exec django python manage.py createsuperuser
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 5: Verify Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all containers are running
|
||||||
|
docker compose -f docker-compose.production.yml ps
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker compose -f docker-compose.production.yml logs -f
|
||||||
|
|
||||||
|
# Test endpoints
|
||||||
|
curl https://yourdomain.com/api/health/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production URLs
|
||||||
|
|
||||||
|
| URL | Purpose |
|
||||||
|
|-----|---------|
|
||||||
|
| https://yourdomain.com | Marketing site |
|
||||||
|
| https://platform.yourdomain.com | Platform admin |
|
||||||
|
| https://*.yourdomain.com | Tenant subdomains |
|
||||||
|
| https://api.yourdomain.com | API (if configured) |
|
||||||
|
| https://yourdomain.com:5555 | Flower (Celery monitoring) |
|
||||||
|
|
||||||
|
### Production Management Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh user@yourdomain.com
|
||||||
|
cd ~/smoothschedule/smoothschedule
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker compose -f docker-compose.production.yml logs -f django
|
||||||
|
|
||||||
|
# Restart services
|
||||||
|
docker compose -f docker-compose.production.yml restart
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
docker compose -f docker-compose.production.yml exec django python manage.py migrate
|
||||||
|
|
||||||
|
# Django shell
|
||||||
|
docker compose -f docker-compose.production.yml exec django python manage.py shell
|
||||||
|
|
||||||
|
# Database backup
|
||||||
|
docker compose -f docker-compose.production.yml exec postgres pg_dump -U smoothschedule_user smoothschedule > backup.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
### Multi-Tenancy Model
|
### Multi-Tenancy Model
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────┐
|
PostgreSQL Database
|
||||||
│ PostgreSQL Database │
|
├── public (shared schema)
|
||||||
├─────────────────────────────────────────┤
|
│ ├── Tenants
|
||||||
│ public (shared schema) │
|
│ ├── Domains
|
||||||
│ ├─ Tenants │
|
│ ├── Users
|
||||||
│ ├─ Domains │
|
│ └── PermissionGrants
|
||||||
│ ├─ Users │
|
├── demo (tenant schema)
|
||||||
│ └─ PermissionGrants │
|
│ ├── Resources
|
||||||
├─────────────────────────────────────────┤
|
│ ├── Events
|
||||||
│ tenant_demo (schema for Demo Company) │
|
│ ├── Services
|
||||||
│ ├─ Appointments │
|
│ └── Customers
|
||||||
│ ├─ Resources │
|
└── acme (tenant schema)
|
||||||
│ └─ Customers │
|
├── Resources
|
||||||
├─────────────────────────────────────────┤
|
├── Events
|
||||||
│ tenant_acme (schema for Acme Corp) │
|
└── ...
|
||||||
│ ├─ Appointments │
|
|
||||||
│ ├─ Resources │
|
|
||||||
│ └─ Customers │
|
|
||||||
└─────────────────────────────────────────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Role Hierarchy
|
### Role Hierarchy
|
||||||
|
|
||||||
| Role | Level | Access Scope |
|
| Role | Level | Access |
|
||||||
|---------------------|----------|---------------------------|
|
|------|-------|--------|
|
||||||
| SUPERUSER | Platform | All tenants (god mode) |
|
| SUPERUSER | Platform | All tenants (god mode) |
|
||||||
| PLATFORM_MANAGER | Platform | All tenants |
|
| PLATFORM_MANAGER | Platform | All tenants |
|
||||||
| PLATFORM_SALES | Platform | Demo accounts only |
|
| PLATFORM_SALES | Platform | Demo accounts only |
|
||||||
| PLATFORM_SUPPORT | Platform | Tenant users |
|
| PLATFORM_SUPPORT | Platform | Can masquerade as tenant users |
|
||||||
| TENANT_OWNER | Tenant | Own tenant (full access) |
|
| TENANT_OWNER | Tenant | Full tenant access |
|
||||||
| TENANT_MANAGER | Tenant | Own tenant |
|
| TENANT_MANAGER | Tenant | Most tenant features |
|
||||||
| TENANT_STAFF | Tenant | Own tenant (limited) |
|
| TENANT_STAFF | Tenant | Limited tenant access |
|
||||||
| CUSTOMER | Tenant | Own data only |
|
| CUSTOMER | Tenant | Own data only |
|
||||||
|
|
||||||
### Masquerading Matrix
|
### Request Flow
|
||||||
|
|
||||||
| 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/
|
Browser → Traefik (SSL) → nginx (frontend) or django (API)
|
||||||
├── config/
|
↓
|
||||||
│ └── settings.py # Multi-tenancy & security config
|
React SPA
|
||||||
├── core/
|
↓
|
||||||
│ ├── models.py # Tenant, Domain, PermissionGrant
|
/api/* → django:5000
|
||||||
│ ├── permissions.py # Hijack permission matrix
|
/ws/* → django:5000 (WebSocket)
|
||||||
│ ├── 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**
|
## Configuration Files
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `smoothschedule/docker-compose.local.yml` | Local Docker services |
|
||||||
|
| `smoothschedule/docker-compose.production.yml` | Production Docker services |
|
||||||
|
| `smoothschedule/.envs/.local/` | Local environment variables |
|
||||||
|
| `smoothschedule/.envs/.production/` | Production environment variables |
|
||||||
|
| `smoothschedule/config/settings/` | Django settings |
|
||||||
|
| `smoothschedule/compose/production/traefik/traefik.yml` | Traefik routing config |
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `frontend/.env.development` | Local environment variables |
|
||||||
|
| `frontend/.env.production` | Production environment variables |
|
||||||
|
| `frontend/nginx.conf` | Production nginx config |
|
||||||
|
| `frontend/vite.config.ts` | Vite bundler config |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Backend won't start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Docker logs
|
||||||
|
docker compose -f docker-compose.local.yml logs django
|
||||||
|
|
||||||
|
# Common issues:
|
||||||
|
# - Database not ready: wait longer, then restart django
|
||||||
|
# - Missing migrations: run migrate command
|
||||||
|
# - Port conflict: check if 8000 is in use
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend can't connect to API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verify backend is running
|
||||||
|
curl http://lvh.me:8000/api/
|
||||||
|
|
||||||
|
# Check CORS settings in Django
|
||||||
|
# Ensure CORS_ALLOWED_ORIGINS includes http://platform.lvh.me:5173
|
||||||
|
```
|
||||||
|
|
||||||
|
### WebSockets disconnecting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check nginx has /ws/ proxy configured
|
||||||
|
# Verify django is running ASGI (Daphne)
|
||||||
|
# Check production traefik/nginx logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multi-tenant issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check tenant exists
|
||||||
|
docker compose exec django python manage.py shell
|
||||||
|
>>> from smoothschedule.identity.core.models import Tenant, Domain
|
||||||
|
>>> Tenant.objects.all()
|
||||||
|
>>> Domain.objects.all()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Additional Documentation
|
||||||
|
|
||||||
|
- **[CLAUDE.md](CLAUDE.md)** - Development guide, coding standards, architecture details
|
||||||
|
- **[DEPLOYMENT.md](DEPLOYMENT.md)** - Comprehensive deployment guide
|
||||||
|
- **[PRODUCTION_DEPLOYMENT.md](PRODUCTION_DEPLOYMENT.md)** - Step-by-step manual deployment
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|||||||
Reference in New Issue
Block a user