- Add list-docs, fix-stuck-docs, reprocess-doc CLI commands - Create ADMIN.md with deployment, CLI, database, and troubleshooting docs - Add HIBP warning to Settings page password change - Remove separate Account nav link (already in Settings) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
179 lines
5.4 KiB
Markdown
179 lines
5.4 KiB
Markdown
# PedsHub — Admin Guide
|
|
|
|
## Deployment
|
|
|
|
```bash
|
|
# Start everything
|
|
docker compose up -d
|
|
|
|
# Rebuild after code changes (restart alone won't pick up changes)
|
|
docker compose build --no-cache backend celery frontend
|
|
docker compose up -d backend celery frontend --force-recreate
|
|
|
|
# View logs
|
|
docker compose logs backend --tail=50
|
|
docker compose logs celery --tail=50
|
|
docker compose logs frontend --tail=50
|
|
```
|
|
|
|
## CLI Management Tool
|
|
|
|
All commands run inside the backend container:
|
|
|
|
```bash
|
|
docker compose exec backend python -m app.cli <command>
|
|
```
|
|
|
|
### User Management
|
|
|
|
```bash
|
|
# List all users
|
|
docker compose exec backend python -m app.cli list-users
|
|
|
|
# Reset a user's password
|
|
docker compose exec backend python -m app.cli reset-password user@example.com newpassword
|
|
|
|
# Change user role (admin / moderator / user)
|
|
docker compose exec backend python -m app.cli set-role user@example.com moderator
|
|
|
|
# Force-verify a user's email (skip email confirmation)
|
|
docker compose exec backend python -m app.cli verify-email user@example.com
|
|
|
|
# Delete a user (interactive confirmation)
|
|
docker compose exec backend python -m app.cli delete-user user@example.com
|
|
|
|
# Export users to CSV
|
|
docker compose exec backend python -m app.cli export-users > users.csv
|
|
```
|
|
|
|
### Documents
|
|
|
|
```bash
|
|
# List all documents with status
|
|
docker compose exec backend python -m app.cli list-docs
|
|
|
|
# Fix documents stuck in 'processing' (>30 min)
|
|
docker compose exec backend python -m app.cli fix-stuck-docs
|
|
|
|
# Requeue a specific document for processing
|
|
docker compose exec backend python -m app.cli reprocess-doc 32
|
|
```
|
|
|
|
**Why documents get stuck:** If the Celery worker restarts while processing a PDF, the task is lost and the document stays at "processing" forever. `fix-stuck-docs` resets these to "ready" so they can be reprocessed.
|
|
|
|
### Courses & Quizzes
|
|
|
|
```bash
|
|
# List all courses
|
|
docker compose exec backend python -m app.cli list-courses
|
|
|
|
# List quizzes (active only)
|
|
docker compose exec backend python -m app.cli list-quizzes
|
|
|
|
# List all quizzes including deleted
|
|
docker compose exec backend python -m app.cli list-quizzes --all
|
|
```
|
|
|
|
### Maintenance
|
|
|
|
```bash
|
|
# Platform statistics
|
|
docker compose exec backend python -m app.cli stats
|
|
|
|
# Clean up orphaned Redis keys (quiz progress with no expiry)
|
|
docker compose exec backend python -m app.cli cleanup-redis
|
|
```
|
|
|
|
## Database
|
|
|
|
### Direct Access
|
|
|
|
```bash
|
|
docker compose exec postgres psql -U pedquiz -d pedquiz
|
|
```
|
|
|
|
### Backups
|
|
|
|
Automated daily backups run via the `db-backup` service (prodrigestivill/postgres-backup-local). Retention: 14 daily, 4 weekly, 6 monthly. Stored in `./backups/`.
|
|
|
|
```bash
|
|
# Check backup status
|
|
docker compose logs db-backup --tail=10
|
|
|
|
# List backups
|
|
ls -la backups/
|
|
|
|
# Manual backup
|
|
docker compose exec postgres pg_dump -U pedquiz pedquiz > manual-backup.sql
|
|
|
|
# Restore from backup
|
|
cat backups/daily/pedquiz-YYYYMMDD-HHMMSS.sql.gz | gunzip | \
|
|
docker compose exec -T postgres psql -U pedquiz -d pedquiz
|
|
```
|
|
|
|
## User Roles
|
|
|
|
| Role | Capabilities |
|
|
|------|-------------|
|
|
| `user` | Take quizzes, study flashcards, enroll in courses, create quizzes from question bank |
|
|
| `moderator` | All user abilities + create courses, upload PDFs, manage documents |
|
|
| `admin` | All moderator abilities + admin dashboard, user management, model config, system settings |
|
|
|
|
## Common Issues
|
|
|
|
### Document stuck in "processing"
|
|
```bash
|
|
docker compose exec backend python -m app.cli fix-stuck-docs
|
|
```
|
|
Cause: Celery worker restarted mid-task. The fix resets status to "ready".
|
|
|
|
### DDL race condition on startup
|
|
One or two backend workers may fail on startup with `Application startup failed`. This is normal — multiple uvicorn workers race to run ALTER TABLE migrations, and losers get a deadlock error. The surviving workers handle all traffic. Check with:
|
|
```bash
|
|
docker compose logs backend --tail=10 | grep "startup complete"
|
|
```
|
|
|
|
### Celery task not running
|
|
```bash
|
|
# Check Celery is connected
|
|
docker compose logs celery --tail=5
|
|
|
|
# Check if tasks are registered
|
|
docker compose exec celery celery -A app.tasks inspect registered
|
|
|
|
# Check active tasks (don't restart if tasks are running!)
|
|
docker compose exec celery celery -A app.tasks inspect active
|
|
```
|
|
|
|
### Password reset without email
|
|
```bash
|
|
docker compose exec backend python -m app.cli reset-password user@example.com newpassword
|
|
```
|
|
|
|
### User can't log in (unverified email)
|
|
```bash
|
|
docker compose exec backend python -m app.cli verify-email user@example.com
|
|
```
|
|
|
|
## Environment
|
|
|
|
Key settings in `backend/.env`:
|
|
|
|
| Variable | Purpose |
|
|
|----------|---------|
|
|
| `APP_URL` | Base URL for email links (e.g. `https://pedshub.com`) |
|
|
| `SECRET_KEY` | JWT signing key — change in production |
|
|
| `MAIL_FROM` | Sender email for verification/reset emails |
|
|
| `LITELLM_API_BASE` | LiteLLM proxy URL for AI features |
|
|
| `LITELLM_API_KEY` | API key for LiteLLM proxy |
|
|
| `TURNSTILE_SITE_KEY` / `TURNSTILE_SECRET_KEY` | Cloudflare Turnstile bot protection |
|
|
| `BBB_SERVER_URL` / `BBB_SECRET` | BigBlueButton integration for live sessions |
|
|
|
|
## Security Notes
|
|
|
|
- Passwords are hashed with **bcrypt** (one-way, irreversible)
|
|
- Registration checks passwords against **Have I Been Pwned** breach database (warns, doesn't block)
|
|
- Only the first 5 characters of the SHA-1 hash are sent to HIBP (k-anonymity)
|
|
- JWT tokens auto-refresh via sliding expiration (12h age or <1h remaining)
|
|
- Rate limiting on login (10 attempts per IP per 15 min) via Redis
|
|
- Email verification required for new accounts
|