3fef0d5749074ed79f818edb03e42c91acb48f5a
Added complete plugin documentation with visual mockups and expanded template
variable system with CONTEXT, DATE helpers, and default values.
Backend Changes:
- Extended template_parser.py to support all new template types
- Added PROMPT with default values: {{PROMPT:var|desc|default}}
- Added CONTEXT variables: {{CONTEXT:business_name}}, {{CONTEXT:owner_email}}
- Added DATE helpers: {{DATE:today}}, {{DATE:+7d}}, {{DATE:monday}}
- Implemented date expression evaluation for relative dates
- Updated compile_template to handle all template types
- Added context parameter for business data auto-fill
Frontend Changes:
- Created comprehensive HelpPluginDocs.tsx with Stripe-style API docs
- Added visual mockup of plugin configuration form
- Documented all template types with examples and benefits
- Added Command Reference section with allowed/blocked Python commands
- Documented all HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Added URL whitelisting requirements and approval process
- Created Platform Staff management page with edit modal
- Added can_approve_plugins and can_whitelist_urls permissions
Platform Staff Features:
- List all platform_manager and platform_support users
- Edit user details with role-based permissions
- Superusers can edit anyone
- Platform managers can only edit platform_support users
- Permission cascade: users can only grant permissions they have
- Real-time updates via React Query cache invalidation
Documentation Highlights:
- 4 template types: PROMPT, CONTEXT, DATE, and automatic validation
- Visual form mockup showing exactly what users see
- All allowed control flow (if/elif/else, for, while, try/except, etc.)
- All allowed built-in functions (len, range, min, max, etc.)
- All blocked operations (import, exec, eval, class/function defs)
- Complete HTTP API reference with examples
- URL whitelisting process: contact pluginaccess@smoothschedule.com
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Smooth Schedule - Multi-Tenant SaaS Platform
A production-grade Django skeleton with strict data isolation and high-trust security for resource orchestration.
🎯 Features
- ✅ Multi-Tenancy: PostgreSQL schema-per-tenant using django-tenants
- ✅ 8-Tier Role Hierarchy: From SUPERUSER to CUSTOMER with strict permissions
- ✅ Secure Masquerading: django-hijack with custom permission matrix
- ✅ Full Audit Trail: Structured logging of all masquerade activity
- ✅ Headless API: Django Rest Framework (no server-side HTML)
- ✅ Docker Ready: Complete Docker Compose setup via cookiecutter-django
- ✅ AWS Integration: S3 storage + Route53 DNS for custom domains
📋 Prerequisites
- Python 3.9+
- PostgreSQL 14+
- Docker & Docker Compose
- Cookiecutter (
pip install cookiecutter)
🚀 Quick Start
1. Run Setup Script
chmod +x setup_project.sh
./setup_project.sh
cd smoothschedule
2. Configure Environment
Create .env file:
# Database
POSTGRES_DB=smoothschedule_db
POSTGRES_USER=smoothschedule_user
POSTGRES_PASSWORD=your_secure_password
# Django
DJANGO_SECRET_KEY=your_secret_key_here
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
# AWS
AWS_ACCESS_KEY_ID=your_aws_key
AWS_SECRET_ACCESS_KEY=your_aws_secret
AWS_STORAGE_BUCKET_NAME=smoothschedule-media
AWS_ROUTE53_HOSTED_ZONE_ID=your_zone_id
3. Start Services
docker-compose build
docker-compose up -d
4. Run Migrations
# Shared schema
docker-compose run --rm django python manage.py migrate_schemas --shared
# Create superuser
docker-compose run --rm django python manage.py createsuperuser
5. Create First Tenant
docker-compose run --rm django python manage.py shell
from core.models import Tenant, Domain
tenant = Tenant.objects.create(
name="Demo Company",
schema_name="demo",
subscription_tier="PROFESSIONAL",
)
Domain.objects.create(
domain="demo.smoothschedule.local",
tenant=tenant,
is_primary=True,
)
# Run tenant migrations
docker-compose run --rm django python manage.py migrate_schemas
🏗️ 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:
{
"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:
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
- Access Django Admin:
http://localhost:8000/admin/ - Create test users with different roles
- Click "Hijack" button next to a user
- 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:
TENANT_APPS = [
'django.contrib.contenttypes',
'appointments', # Your app
'resources', # Your app
'billing', # Your app
]
Custom Domain Setup
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:
TenantMainMiddlewaremust be first,MasqueradeAuditMiddlewareafterHijackUserMiddleware - 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_instancebefore saving
Hijack button doesn't appear:
- Check
HIJACK_AUTHORIZATION_CHECKin settings - Verify
HijackUserAdminMixininusers/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
Description
Languages
TypeScript
58.2%
Python
21.8%
HTML
18.8%
JavaScript
0.4%
Shell
0.3%
Other
0.4%