237 lines
6.5 KiB
Markdown
237 lines
6.5 KiB
Markdown
# Open edX Tenant API
|
|
|
|
REST API for programmatic tenant creation in Open edX with eox-tenant.
|
|
|
|
## Features
|
|
|
|
- Create tenants with automatic MFE configuration
|
|
- List all provisioned tenants
|
|
- Delete tenants
|
|
- Health check endpoint
|
|
- Audit logging of all tenant operations
|
|
|
|
## Installation
|
|
|
|
### 1. Add to Tutor Config
|
|
|
|
Edit your Tutor `config.yml`:
|
|
|
|
```yaml
|
|
MOUNTS:
|
|
- /path/to/openedx-tenant-api
|
|
|
|
OPENEDX_EXTRA_PIP_REQUIREMENTS:
|
|
- -e /mnt/openedx-tenant-api
|
|
```
|
|
|
|
### 2. Restart LMS
|
|
|
|
```bash
|
|
tutor dev restart lms
|
|
```
|
|
|
|
### 3. Install Package and Run Migrations
|
|
|
|
```bash
|
|
# Install in running container
|
|
docker exec tutor_dev-lms-1 sh -c "pip install -e /mnt/openedx-tenant-api --no-build-isolation"
|
|
|
|
# Create migrations
|
|
docker exec tutor_dev-lms-1 sh -c "cd /openedx/edx-platform && python manage.py lms makemigrations openedx_tenant_api"
|
|
|
|
# Run migrations
|
|
docker exec tutor_dev-lms-1 sh -c "cd /openedx/edx-platform && python manage.py lms migrate openedx_tenant_api"
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
| Endpoint | Method | Auth Required | Description |
|
|
|----------|--------|---------------|-------------|
|
|
| `/api/tenant/v1/health` | GET | No | Health check |
|
|
| `/api/tenant/v1/list` | GET | Yes (Admin) | List all tenants |
|
|
| `/api/tenant/v1/create` | POST | Yes (Admin) | Create new tenant |
|
|
| `/api/tenant/v1/delete/{tenant_name}` | DELETE | Yes (Admin) | Delete tenant |
|
|
|
|
## Usage
|
|
|
|
### Health Check
|
|
|
|
```bash
|
|
curl http://local.openedx.io:8000/api/tenant/v1/health
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"eox_tenant_installed": true,
|
|
"tenant_count": 2
|
|
}
|
|
```
|
|
|
|
### Create Tenant
|
|
|
|
Requires admin user authentication. Supports Basic Auth, JWT Bearer, or Session auth.
|
|
|
|
```python
|
|
import requests
|
|
|
|
# Using Basic Authentication (simplest)
|
|
response = requests.post(
|
|
'http://local.openedx.io:8000/api/tenant/v1/create',
|
|
auth=('admin', 'your-password'),
|
|
json={
|
|
'tenant_name': 'talent1',
|
|
'platform_name': 'Talent 1 Learning',
|
|
'theme_name': 'indigo',
|
|
'org_filter': ['org1'] # Optional
|
|
}
|
|
)
|
|
|
|
print(response.json())
|
|
```
|
|
|
|
```bash
|
|
# Using cURL with Basic Auth
|
|
curl -X POST http://local.openedx.io:8000/api/tenant/v1/create \
|
|
-u admin:your-password \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"tenant_name": "talent1",
|
|
"platform_name": "Talent 1 Learning",
|
|
"theme_name": "indigo"
|
|
}'
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"tenant_id": 123,
|
|
"tenant_name": "talent1",
|
|
"lms_url": "http://talent1.local.openedx.io:8000",
|
|
"authn_url": "http://talent1.apps.local.openedx.io:1999/authn",
|
|
"learner_dashboard_url": "http://talent1.apps.local.openedx.io:1996/learner-dashboard/",
|
|
"message": "Tenant created successfully. Add DNS entries to your hosts file."
|
|
}
|
|
```
|
|
|
|
### List Tenants
|
|
|
|
```python
|
|
import requests
|
|
|
|
response = requests.get(
|
|
'http://local.openedx.io:8000/api/tenant/v1/list',
|
|
headers={'Authorization': 'Bearer YOUR_TOKEN'}
|
|
)
|
|
|
|
print(response.json())
|
|
```
|
|
|
|
### Delete Tenant
|
|
|
|
```python
|
|
import requests
|
|
|
|
response = requests.delete(
|
|
'http://local.openedx.io:8000/api/tenant/v1/delete/talent1',
|
|
headers={'Authorization': 'Bearer YOUR_TOKEN'}
|
|
)
|
|
|
|
print(response.json())
|
|
```
|
|
|
|
## Testing via Django Shell
|
|
|
|
For testing without authentication:
|
|
|
|
```bash
|
|
docker exec tutor_dev-lms-1 sh -c "cd /openedx/edx-platform && python manage.py lms shell" << 'EOF'
|
|
import django
|
|
django.setup()
|
|
|
|
from django.db import transaction
|
|
from django.contrib.auth import get_user_model
|
|
from eox_tenant.models import TenantConfig, Route
|
|
|
|
User = get_user_model()
|
|
admin = User.objects.filter(is_superuser=True).first()
|
|
|
|
tenant_name = 'talent1'
|
|
platform_name = 'Talent 1 Learning'
|
|
theme_name = 'indigo'
|
|
|
|
external_key = f'{tenant_name}.local.openedx.io'
|
|
lms_domain = f'{tenant_name}.local.openedx.io'
|
|
|
|
# Generate MFE config
|
|
lms_configs = {
|
|
'LMS_BASE': f'{lms_domain}:8000',
|
|
'SITE_NAME': lms_domain,
|
|
'PLATFORM_NAME': platform_name,
|
|
'THEME_NAME': theme_name,
|
|
'BASE_URL': f'http://{tenant_name}.apps.local.openedx.io',
|
|
'LMS_BASE_URL': f'http://{lms_domain}:8000',
|
|
'LEARNER_HOME_MICROFRONTEND_URL': f'http://{tenant_name}.apps.local.openedx.io:1996/learner-dashboard/',
|
|
'AUTHN_MICROFRONTEND_URL': f'http://{tenant_name}.apps.local.openedx.io:1999/authn',
|
|
# ... add other MFE URLs as needed
|
|
}
|
|
|
|
with transaction.atomic():
|
|
tenant_config = TenantConfig.objects.create(
|
|
external_key=external_key,
|
|
lms_configs=lms_configs,
|
|
theming_configs={'THEME_NAME': theme_name},
|
|
meta={'created_by': admin.username}
|
|
)
|
|
Route.objects.create(domain=lms_domain, config=tenant_config)
|
|
print(f'Tenant {tenant_name} created!')
|
|
EOF
|
|
```
|
|
|
|
## Hosts File Configuration
|
|
|
|
After creating a tenant, add these entries to your hosts file:
|
|
|
|
```
|
|
127.0.0.1 talent1.local.openedx.io
|
|
127.0.0.1 talent1.apps.local.openedx.io
|
|
127.0.0.1 studio.talent1.local.openedx.io
|
|
```
|
|
|
|
## MFE Configuration
|
|
|
|
The API automatically generates MFE URLs for the tenant:
|
|
|
|
- Authn: `http://{tenant}.apps.local.openedx.io:1999/authn`
|
|
- Learner Dashboard: `http://{tenant}.apps.local.openedx.io:1996/learner-dashboard/`
|
|
- Account: `http://{tenant}.apps.local.openedx.io:1997/account/`
|
|
- Profile: `http://{tenant}.apps.local.openedx.io:1995/profile/u/`
|
|
- Learning: `http://{tenant}.apps.local.openedx.io:2000/learning`
|
|
- Discussions: `http://{tenant}.apps.local.openedx.io:2002/discussions`
|
|
- Gradebook: `http://{tenant}.apps.local.openedx.io:1994/gradebook`
|
|
- Communications: `http://{tenant}.apps.local.openedx.io:1984/communications`
|
|
- ORA Grading: `http://{tenant}.apps.local.openedx.io:1993/ora-grading`
|
|
- Admin Console: `http://{tenant}.apps.local.openedx.io:2025/admin-console`
|
|
- Course Authoring: `http://{tenant}.apps.local.openedx.io:2001/authoring`
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
|
│ External App │────▶│ Tenant API │────▶│ eox-tenant │
|
|
│ (Your System) │ │ (Django REST) │ │ (TenantConfig) │
|
|
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
|
│
|
|
▼
|
|
┌──────────────────┐
|
|
│ TenantProvisioningLog │
|
|
│ (Audit Trail) │
|
|
└──────────────────┘
|
|
```
|
|
|
|
## License
|
|
|
|
MIT
|