Restructured 13 Django apps from flat/mixed organization into 5 logical
domain packages following cookiecutter-django conventions:
- identity/: core (tenant/domain models, middleware, mixins), users
- scheduling/: schedule, contracts, analytics
- communication/: notifications, credits, mobile, messaging
- commerce/: payments, tickets
- platform/: admin, api
Key changes:
- Moved all apps to smoothschedule/smoothschedule/{domain}/{app}/
- Updated all import paths across the codebase
- Updated settings (base.py, multitenancy.py, test.py)
- Updated URL configuration in config/urls.py
- Updated middleware and permission paths
- Preserved app_label in AppConfig for migration compatibility
- Updated CLAUDE.md documentation with new structure
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
362 lines
9.6 KiB
Markdown
362 lines
9.6 KiB
Markdown
# Smooth Schedule - Installation & Setup Guide
|
|
|
|
## 🎉 Project Structure Created Successfully!
|
|
|
|
Your Smooth Schedule multi-tenant SaaS platform has been initialized with:
|
|
- ✅ Cookiecutter-Django base structure
|
|
- ✅ Multi-tenancy with django-tenants 3.9.0
|
|
- ✅ Masquerading security with django-hijack 3.7.4
|
|
- ✅ Custom 8-tier role hierarchy
|
|
- ✅ Audit logging middleware
|
|
- ✅ PostgreSQL schema-per-tenant architecture
|
|
|
|
## 📁 Project Location
|
|
|
|
```
|
|
/home/poduck/Desktop/smoothschedule2/smoothschedule/
|
|
```
|
|
|
|
## 🚀 Next Steps to Get Running
|
|
|
|
### 1. Navigate to Project Directory
|
|
|
|
```bash
|
|
cd /home/poduck/Desktop/smoothschedule2/smoothschedule
|
|
```
|
|
|
|
### 2. Configure Environment Variables
|
|
|
|
Create `.envs/.local/.django` file:
|
|
|
|
```bash
|
|
mkdir -p .envs/.local
|
|
cat > .envs/.local/.django << 'EOF'
|
|
# General
|
|
# ------------------------------------------------------------------------------
|
|
DJANGO_SETTINGS_MODULE=config.settings.local
|
|
DJANGO_SECRET_KEY=your-secret-key-here-change-in-production
|
|
DJANGO_DEBUG=True
|
|
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,.localhost,.127.0.0.1
|
|
USE_DOCKER=yes
|
|
|
|
# Database
|
|
# ------------------------------------------------------------------------------
|
|
DATABASE_URL=postgres://postgres:changeme@postgres:5432/smoothschedule
|
|
|
|
# Redis
|
|
# ------------------------------------------------------------------------------
|
|
REDIS_URL=redis://redis:6379/0
|
|
|
|
#AWS
|
|
# ------------------------------------------------------------------------------
|
|
DJANGO_AWS_ACCESS_KEY_ID=
|
|
DJANGO_AWS_SECRET_ACCESS_KEY=
|
|
DJANGO_AWS_STORAGE_BUCKET_NAME=smoothschedule-media
|
|
DJANGO_AWS_S3_REGION_NAME=us-east-1
|
|
EOF
|
|
```
|
|
|
|
Create `.envs/.local/.postgres` file:
|
|
|
|
```bash
|
|
cat > .envs/.local/.postgres << 'EOF'
|
|
# PostgreSQL
|
|
# ------------------------------------------------------------------------------
|
|
POSTGRES_HOST=postgres
|
|
POSTGRES_PORT=5432
|
|
POSTGRES_DB=smoothschedule
|
|
POSTGRES_USER=postgres
|
|
POSTGRES_PASSWORD=changeme
|
|
EOF
|
|
```
|
|
|
|
### 3. Build and Start Docker Containers
|
|
|
|
```bash
|
|
# Build the Docker images
|
|
docker-compose -f docker-compose.local.yml build
|
|
|
|
# Start all services (Django, PostgreSQL, Redis, Celery)
|
|
docker-compose -f docker-compose.local.yml up -d
|
|
|
|
# Check logs
|
|
docker-compose -f docker-compose.local.yml logs -f
|
|
```
|
|
|
|
### 4. Run Database Migrations
|
|
|
|
**IMPORTANT**: With django-tenants, you must run migrations in a specific order:
|
|
|
|
```bash
|
|
# 1. Create the shared schema (public) FIRST
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas --shared
|
|
|
|
# 2. Create a superuser (in the public schema)
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py createsuperuser
|
|
```
|
|
|
|
### 5. Create Your First Tenant
|
|
|
|
Open Django shell:
|
|
|
|
```bash
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py shell
|
|
```
|
|
|
|
In the shell, create a tenant:
|
|
|
|
```python
|
|
from core.models import Tenant, Domain
|
|
|
|
# Create the tenant
|
|
tenant = Tenant.objects.create(
|
|
name="Demo Company",
|
|
schema_name="demo", # This will be the PostgreSQL schema name
|
|
subscription_tier="PROFESSIONAL",
|
|
max_users=50,
|
|
max_resources=100,
|
|
)
|
|
|
|
# Create a domain for the tenant
|
|
domain = Domain.objects.create(
|
|
domain="demo.localhost", # For local development
|
|
tenant=tenant,
|
|
is_primary=True,
|
|
)
|
|
|
|
print(f"Created tenant: {tenant.name} with schema: {tenant.schema_name}")
|
|
print(f"Domain: {domain.domain}")
|
|
```
|
|
|
|
Exit the shell (`exit()` or Ctrl+D).
|
|
|
|
### 6. Run Tenant Migrations
|
|
|
|
Now migrate all tenant schemas:
|
|
|
|
```bash
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas
|
|
```
|
|
|
|
### 7. Access the Application
|
|
|
|
- **Django Admin**: http://localhost:8000/admin/
|
|
- Login with the superuser you created
|
|
- You can manage tenants, users, and permission grants here
|
|
|
|
- **API Documentation**: http://localhost:8000/api/schema/swagger-ui/
|
|
- DRF Spectacular auto-generated API docs
|
|
|
|
- **Tenant Access**:
|
|
- Add entry to `/etc/hosts`:
|
|
```bash
|
|
127.0.0.1 demo.localhost
|
|
```
|
|
- Access tenant at: http://demo.localhost:8000/
|
|
|
|
## 🔐 Creating Users with Roles
|
|
|
|
In Django shell or admin, create users with different roles:
|
|
|
|
```python
|
|
from smoothschedule.identity.users.models import User
|
|
from core.models import Tenant
|
|
|
|
# Get the tenant
|
|
tenant = Tenant.objects.get(schema_name="demo")
|
|
|
|
# Create a Tenant Owner
|
|
owner = User.objects.create_user(
|
|
email="owner@demo.com",
|
|
password="secure-password",
|
|
role=User.Role.TENANT_OWNER,
|
|
tenant=tenant,
|
|
first_name="John",
|
|
last_name="Owner",
|
|
)
|
|
|
|
# Create a Tenant Staff member
|
|
staff = User.objects.create_user(
|
|
email="staff@demo.com",
|
|
password="secure-password",
|
|
role=User.Role.TENANT_STAFF,
|
|
tenant=tenant,
|
|
first_name="Jane",
|
|
last_name="Staff",
|
|
)
|
|
|
|
# Create a demo account (for sales)
|
|
demo_user = User.objects.create_user(
|
|
email="demo@demo.com",
|
|
password="demo-password",
|
|
role=User.Role.TENANT_OWNER,
|
|
tenant=tenant,
|
|
is_temporary=True, # Sales can masquerade as this user
|
|
first_name="Demo",
|
|
last_name="Account",
|
|
)
|
|
|
|
# Create a Platform Support user
|
|
support = User.objects.create_user(
|
|
email="support@smoothschedule.com",
|
|
password="support-password",
|
|
role=User.Role.PLATFORM_SUPPORT,
|
|
tenant=None, # Platform users have no tenant
|
|
is_staff=True, # Needed for admin access
|
|
first_name="Support",
|
|
last_name="Team",
|
|
)
|
|
```
|
|
|
|
## 🎭 Testing Masquerading
|
|
|
|
1. Login to admin as a superuser or support user
|
|
2. Go to Users section
|
|
3. Click the "Hijack" button next to a user you can masquerade as
|
|
4. You'll now see the interface as that user
|
|
5. Check `logs/masquerade.log` for audit trail:
|
|
|
|
```bash
|
|
docker-compose -f docker-compose.local.yml exec django cat logs/masquerade.log
|
|
```
|
|
|
|
## 📊 Understanding the Architecture
|
|
|
|
### Multi-Tenancy
|
|
|
|
Each tenant gets their own PostgreSQL schema:
|
|
|
|
```
|
|
PostgreSQL Database: smoothschedule
|
|
├── public (shared schema)
|
|
│ ├── core_tenant
|
|
│ ├── core_domain
|
|
│ ├── users_user
|
|
│ └── core_permissiongrant
|
|
├── demo (tenant schema for "Demo Company")
|
|
│ └── (your tenant-scoped apps go here)
|
|
└── acme (tenant schema for "Acme Corp")
|
|
└── (completely isolated data)
|
|
```
|
|
|
|
### Role Hierarchy
|
|
|
|
| Role | Level | Can Hijack |
|
|
|------|-------|-----------|
|
|
| SUPERUSER | Platform | Everyone |
|
|
| PLATFORM_SUPPORT | Platform | Tenant users |
|
|
| PLATFORM_SALES | Platform | Demo accounts only |
|
|
| TENANT_OWNER | Tenant | Staff in same tenant |
|
|
| TENANT_MANAGER | Tenant | - |
|
|
| TENANT_STAFF | Tenant | - |
|
|
| CUSTOMER | Tenant | - |
|
|
|
|
## 🛠️ Development Workflow
|
|
|
|
### Adding Tenant-Scoped Apps
|
|
|
|
1. Create your app:
|
|
```bash
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py startapp myapp
|
|
```
|
|
|
|
2. Add to `TENANT_APPS` in `config/settings/multitenancy.py`:
|
|
```python
|
|
TENANT_APPS = [
|
|
'django.contrib.contenttypes',
|
|
'myapp', # Your new app
|
|
]
|
|
```
|
|
|
|
3. Run migrations:
|
|
```bash
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas
|
|
```
|
|
|
|
### Useful Commands
|
|
|
|
```bash
|
|
# View logs
|
|
docker-compose -f docker-compose.local.yml logs -f django
|
|
|
|
# Shell access
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py shell
|
|
|
|
# Create migrations
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py makemigrations
|
|
|
|
# Migrate all tenants
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas
|
|
|
|
# Collect static files
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py collectstatic --noinput
|
|
```
|
|
|
|
## 📝 Key Files Reference
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `config/settings/multitenancy.py` | Multi-tenancy configuration |
|
|
| `config/settings/local.py` | Local development settings |
|
|
| `smoothschedule/core/` | Tenant, Domain, PermissionGrant models |
|
|
| `smoothschedule/users/models.py` | Custom User with 8 roles |
|
|
| `core/permissions.py` | Masquerading permission matrix |
|
|
| `core/middleware.py` | Audit logging middleware |
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### Problem: "django_tenants not found"
|
|
|
|
**Solution**: Rebuild the Docker image:
|
|
```bash
|
|
docker-compose -f docker-compose.local.yml build --no-cache django
|
|
```
|
|
|
|
### Problem: "relation does not exist"
|
|
|
|
**Solution**: Run migrations in correct order:
|
|
```bash
|
|
# 1. Shared schema first
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas --shared
|
|
|
|
# 2. Then tenant schemas
|
|
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas
|
|
```
|
|
|
|
### Problem: Cannot access tenant URL
|
|
|
|
**Solution**: Add to `/etc/hosts`:
|
|
```bash
|
|
echo "127.0.0.1 demo.localhost" | sudo tee -a /etc/hosts
|
|
```
|
|
|
|
### Problem: Hijack button doesn't appear
|
|
|
|
**Solution**:
|
|
1. Ensure user has appropriate role (see permission matrix)
|
|
2. Check that `HijackUserAdminMixin` is in `users/admin.py`
|
|
3. Verify middleware order in settings
|
|
|
|
## 🎯 Production Deployment
|
|
|
|
Before deploying to production:
|
|
|
|
1. **Update SECRET_KEY**: Use environment variable
|
|
2. **Set DEBUG=False**: In production settings
|
|
3. **Configure ALLOWED_HOSTS**: Add your domain
|
|
4. **Update Database Credentials**: Use secure passwords
|
|
5. **Configure AWS**: Set real S3 and Route53 credentials
|
|
6. **Enable HTTPS**: Set `SECURE_SSL_REDIRECT = True`
|
|
7. **Review Security Settings**: Check `config/settings/production.py`
|
|
|
|
## 📚 Additional Resources
|
|
|
|
- [django-tenants Documentation](https://django-tenants.readthedocs.io/)
|
|
- [django-hijack Documentation](https://django-hijack.readthedocs.io/)
|
|
- [cookiecutter-django Documentation](https://cookiecutter-django.readthedocs.io/)
|
|
- [Django REST Framework](https://www.django-rest-framework.org/)
|
|
|
|
---
|
|
|
|
**Your multi-tenant SaaS platform is ready! 🚀**
|