Ristek Tutor Backend - Documentation
π Background
Overviewβ
Ristek Tutor Kelas is a peer tutoring platform backend that connects UI students seeking academic help (tutees) with qualified student tutors. The service handles user registration via UI SSO, tutor applications with course score verification, session scheduling and availability management, booking with payment proof uploads, session rescheduling flows, and post-session logging with admin verification and payment tracking.
Stakeholdersβ
- Users: UI students (tutees), student tutors, admin/panitia (session log verification & payment)
- Upstream Dependencies: UI SSO CAS (https://sso.ui.ac.id/cas2), MinIO/S3 (file storage for profile pictures, payment proofs, log proofs)
- Downstream Consumers: Ristek Tutor Kelas Frontend
Scope & Boundariesβ
- In Scope: User authentication (SSO JWT, SSO CAS ticket, dev login), user profile management, tutor application & approval workflow, tutor session CRUD, tutee booking with payment proof, session rescheduling (request + confirm), tutor log submission with proof, admin log verification/rejection/payment marking, mata kuliah management, file uploads to S3/MinIO.
- Out of Scope: Frontend application, payment gateway integration, notification/email system, advanced scheduling algorithms.
βοΈ Architecture & Design
System Diagramβ
Architecture Decisions (ADRs)β
- Language/Framework: Python 3.11 / Django 5.2.4 / Django REST Framework 3.16.0
- Database: SQLite3 (default; libpq-dev installed in Docker for potential PostgreSQL migration)
- Authentication: SimpleJWT 5.5.0 with custom token serializer (30-day access token lifetime), SSO UI integration via CAS v2 client and JWT verification
- File Storage: S3-compatible storage via MinIO + django-storages (boto3/S3Boto3Storage) for profile pictures, payment proofs, and log proofs
- API Documentation: drf-spectacular 0.28.0 (OpenAPI 3.0 schema with Swagger UI and ReDoc)
- Communication: Synchronous RESTful API over HTTP
- Static Files: WhiteNoise for serving Django admin and DRF static assets
- CORS: django-cors-headers with configurable allowed origins
π»Technical Specifications
API Documentationβ
The application auto-generates OpenAPI specs via drf-spectacular. Interactive documentation is available at: Swagger UI: /api/schema/swagger-ui/ ReDoc: /api/schema/redoc/ Raw Schema: /api/schema/
User Endpoints (/user/)β
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /user/sso/login/ | β | SSO JWT login (accepts sso_token, returns JWT access + refresh) |
| POST | /user/sso/callback/ | β | SSO CAS ticket validation (accepts ticket + service, returns JWT) |
| POST | /user/login/ | β | Dev login with username/password (returns JWT access + refresh) |
| GET | /user/me/ | JWT | Get current user profile |
| PATCH | /user/update_profile/ | JWT | Update user profile (onboarding; marks is_complete) |
| PUT | /user/tutor_profile/ | JWT | Update tutor profile (tutor only) |
| POST | /user/apply/ | JWT | Apply to become a tutor (with course scores) |
| GET | /user/tutors/ | JWT | List all tutors |
| POST | /user/course_score_info/ | JWT | Create course score entry for tutor |
Tutor Session Endpoints (/tutor-session/)β
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /tutor-session/sessions/ | JWT | List available sessions (filterable by matkul, tutor, date range) |
| GET | /tutor-session/matkul/ | JWT | List all mata kuliah |
| POST | /tutor-session/create-session/ | JWT | Create a new tutor session |
| GET | /tutor-session/my-sessions/ | JWT | List own sessions (as tutor or tutee) |
| GET | /tutor-session/my-sessions/<pk>/ | JWT | Get session detail |
| PUT | /tutor-session/my-sessions/<pk>/ | JWT | Update session (meeting link, resources, status) |
| DELETE | /tutor-session/my-sessions/<pk>/ | JWT | Cancel session |
| POST | /tutor-session/availability/ | JWT | Create tutor availability slot |
| GET | /tutor-session/tutee/sessions/ | JWT | List tutee's booked sessions |
| GET | /tutor-session/tutee/sessions/<pk>/ | JWT | Get tutee session detail |
| PUT | /tutor-session/tutee/sessions/<pk>/ | JWT | Update booking (session type, emails) |
| PATCH | /tutor-session/tutee/sessions/<pk>/emails/ | JWT | Update booking participant emails |
| POST | /tutor-session/tutee/book/<pk>/ | JWT | Book a session (with payment proof upload) |
| POST | /tutor-session/tutee/reschedule/request/<pk>/ | JWT | Request session reschedule |
| POST | /tutor-session/tutee/reschedule/confirm/<pk>/ | JWT | Confirm reschedule with new time slot |
Tutor Logs Endpoints (/logs/)β
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /logs/tutor/logs | JWT | List tutor's own logs |
| POST | /logs/tutor/logs | JWT | Create log (with participant count + image proof) |
| GET | /logs/tutor/logs/<pk> | JWT | Get log detail |
| PUT | /logs/tutor/logs/<pk> | JWT | Update log |
| DELETE | /logs/tutor/logs/<pk> | JWT | Delete log (only if pending or rejected) |
| GET | /logs/admin/logs | JWT + Admin | List all logs (admin view) |
| GET | /logs/admin/logs/<pk> | JWT + Admin | Get log detail (admin) |
| PUT | /logs/admin/logs/<pk>/verify | JWT + Admin | Verify log β set status to approved |
| PUT | /logs/admin/logs/<pk>/pay | JWT + Admin | Mark log as paid |
| PUT | /logs/admin/logs/<pk>/reject | JWT + Admin | Reject log |
Admin & Documentationβ
| Method | Path | Description |
|---|---|---|
| * | /admin/ | Django Admin panel |
| GET | /api/schema/ | OpenAPI 3.0 schema (JSON/YAML) |
| GET | /api/schema/swagger-ui/ | Swagger UI |
| GET | /api/schema/redoc/ | ReDoc |
Data Model/Schemaβ
User Appβ
| Model | Key Fields | Purpose |
|---|---|---|
| UserProfile | user (OneToOne β auth.User), npm, jurusan (JSON), is_tutor, profile_picture_url (S3 ImageField), batch, line_id, phone_number, default_class_type (Reguler/Teman Belajar), preferred_subjects (M2M β MataKuliah), is_complete | Student profile with onboarding status |
| TutorProfile | user (OneToOne β auth.User), subjects (M2M β MataKuliah), gpa, is_complete | Tutor-specific profile |
| UpgradeToTutorRequest | user (OneToOne β UserProfile), request_date, status (Pending/Approved/Rejected) | Tutor application workflow |
| CourseScoreInfo | course (FK β MataKuliah), score (Float), tutor (FK β TutorProfile) | Course score evidence for tutor applications |
Tutor Session Appβ
| Model | Key Fields | Purpose |
|---|---|---|
| MataKuliah | name (unique, max 1024) | Course/subject catalog |
| TutorSession | tutor (FK β TutorProfile), tutee (FK β UserProfile, nullable), session_date, start_time, end_time (computed: +90min), mata_kuliah (FK), meeting_link, resource_link, status, is_rescheduled_session, original_session (FK β self) | Tutoring session with lifecycle status |
| Booking | session (FK β TutorSession), tutee (FK β UserProfile), name, mata_kuliah (FK), payment_proof (S3 ImageField), session_type (individual/duo/triad/penta/hepta/deca), emails (JSONField) | Session booking with payment proof |
| BookingEmail | booking (FK β Booking), email | Legacy email model (unused; Booking.emails JSONField used instead) |
| Session statuses: tersedia β telah dipesan β dikonfirmasi β dibooking | direschedule | in request reschedule |
| Session types: individual, duo, triad, penta, hepta, deca |
Tutor Logs Appβ
| Model | Key Fields | Purpose |
|---|---|---|
| Log | tutor_session (OneToOne β TutorSession), participant_count, image_proof_url (S3 ImageField), status (pending/approved/paid/rejected), created_at | Post-session log with admin verification workflow |
| Log statuses: pending (Dalam Peninjauan) β approved (Menunggu Pembayaran) β paid (Sudah Dibayar) | rejected (Ditolak) |
Project Structureβ
ristek-tutor-backend/
βββ .github/
β βββ workflows/
β βββ build-and-deploy.yml # Manual deploy to staging/prod via AWS ECR
βββ scripts/
β βββ docker-entrypoint.sh # collectstatic β migrate β gunicorn
βββ tutorkelas/ # Django project module
β βββ settings.py # Django config (DB, JWT, CORS, MinIO/S3, SSO)
β βββ urls.py # Root URL config (admin, user, sessions, logs, docs)
β βββ wsgi.py # WSGI application
β βββ asgi.py # ASGI application
βββ user/ # User & auth Django app
β βββ models.py # UserProfile, TutorProfile, UpgradeToTutorRequest, CourseScoreInfo
β βββ views.py # SSO login, CAS callback, dev login, profile CRUD, tutor application
β βββ serializers.py # DRF serializers + custom JWT token serializer
β βββ urls.py # User route definitions
β βββ admin.py # Django admin registration
β βββ cas_client.py # CAS v2 client for SSO UI ticket verification
β βββ prodi.py # Faculty codes, study program mappings (kd_org)
β βββ management/commands/
β β βββ fake_profile.py # Management command to generate fake users/tutors (Faker)
β βββ migrations/ # 7 migration files
βββ tutor_session/ # Session & booking Django app
β βββ models.py # MataKuliah, TutorSession, Booking, BookingEmail
β βββ views.py # Session CRUD, booking, reschedule request/confirm
β βββ serializers.py # DRF serializers for sessions and bookings
β βββ urls.py # Session route definitions
β βββ admin.py # Django admin registration
β βββ tests.py # Empty test placeholder
β βββ migrations/ # 9 migration files
βββ tutor_logs/ # Log & verification Django app
β βββ models.py # Log model (proof + status workflow)
β βββ views.py # Tutor log CRUD, admin verify/pay/reject
β βββ serializers.py # DRF serializers for logs
β βββ urls.py # Log route definitions
β βββ admin.py # Django admin registration
β βββ tests.py # Empty test placeholder
β βββ migrations/ # 4 migration files
βββ staticfiles/ # Collected static files (DRF, admin)
βββ Dockerfile # Python 3.11-slim, pip install, entrypoint
βββ docker-compose.yml # MinIO + backend services
βββ .env.example # Environment variable template
βββ requirements.txt # Python dependencies (pinned versions)
βββ manage.py # Django management script
βββ db.sqlite3 # SQLite database file
Componentsβ
| Layer | Paths | Responsibility |
|---|---|---|
| User App | user/ | Handles all authentication and user management. Provides three login methods: SSO JWT token verification (sso_login), SSO CAS ticket validation via a custom CAS v2 client (sso_cas_callback), and username/password authentication for development (dev_login). All login endpoints return SimpleJWT access + refresh tokens with custom claims (nama, user, npm, jurusan, fakultas). Manages user profiles with onboarding flow (update_user_profile marks is_complete), tutor profiles, tutor application workflow (apply_for_tutor creates UpgradeToTutorRequest + CourseScoreInfo entries), and tutor listing. |
| CAS Client | user/cas_client.py | Custom CAS v2 protocol client that validates tickets against the SSO UI CAS server. Parses the XML service validation response using BeautifulSoup to extract user attributes (username, nama, npm, kd_org). |
| Prodi Mapping | user/prodi.py | Maps UI faculty/study program codes (kd_org) to human-readable faculty and program names. Used during SSO authentication to enrich user profiles. |
| Tutor Session App | tutor_session/ | Core scheduling module. Tutors create availability sessions with date, time, and mata kuliah. Tutees browse available sessions (filterable by subject, tutor, date range), book sessions with payment proof uploads, and can request rescheduling. Sessions have an 8-state lifecycle from tersedia through booking, confirmation, rescheduling, to expiry or cancellation. Each session is 90 minutes (computed end_time). Supports multiple session types (individual through deca/10-person groups) with participant email collection. |
| Tutor Logs App | tutor_logs/ | Post-session verification system. After a session is completed, tutors submit logs with participant count and image proof. Admins can verify (approve), reject, or mark logs as paid through dedicated endpoints. Logs follow a 4-state workflow: pending β approved β paid, or pending β rejected. |
| Custom JWT Serializer | user/serializers.py | Extends SimpleJWT's TokenObtainPairSerializer to include custom claims: nama (full name), user (username), npm, jurusan, and fakultas in the JWT payload. |
| Data Seeding | user/management/commands/fake_profile.py | Django management command that generates fake users, tutor profiles, and sessions using the Faker library for development/testing purposes. |
βοΈ Operational Playbook
Infrastructureβ
- Cloud Provider: AWS ECR + Pusilkom instance
- CI/CD: GitHub Actions (build-and-deploy.yml), manual workflow dispatch for production (stable tag) and staging (latest tag) builds, pushed to AWS ECR (638207107223.dkr.ecr.ap-southeast-1.amazonaws.com/ristek-tutor-backend)
- Runtime: Gunicorn (2 workers) behind Docker, port configurable via $PORT (default 8000)
- File Storage: MinIO (S3-compatible), runs alongside backend in Docker Compose (ports 9000/9001)
- Static Files: WhiteNoise serving collected static assets
- Database: SQLite3 (volume-mounted db.sqlite3 in Docker Compose)
- Startup: docker-entrypoint.sh runs collectstatic β migrate β gunicorn
Environment Variablesβ
(example)
| Key | Description | Default (Dev) | Sensitive? |
|---|---|---|---|
| DJANGO_SECRET_KEY | Django cryptographic secret key | β | Yes |
| DEBUG | Debug mode (True/False) | False | No |
| ALLOWED_HOSTS | Comma-separated allowed hosts | * | No |
| CORS_ALLOWED_ORIGINS | Comma-separated CORS origins (also used for CSRF trusted origins) | http://localhost:3000 | No |
| SSO_AUTH_HOST | SSO CAS base URL | https://sso.ui.ac.id/cas2 | No |
| SSO_JWT_SECRET | Secret key for verifying SSO JWT tokens | β | Yes |
| MINIO_STORAGE_ENDPOINT | MinIO internal endpoint | minio:9000 | No |
| MINIO_PUBLIC_ENDPOINT | MinIO public-facing endpoint | Same as internal | No |
| MINIO_STORAGE_ACCESS_KEY | MinIO access key | β | Yes |
| MINIO_STORAGE_SECRET_KEY | MinIO secret key | β | Yes |
| MINIO_STORAGE_USE_HTTPS | Use HTTPS for MinIO | false | No |
| MINIO_STORAGE_MEDIA_BUCKET_NAME | MinIO media bucket name | media | No |
| MINIO_STORAGE_AUTO_CREATE_MEDIA_POLICY | Bucket access policy | public-read | No |
| MINIO_ROOT_USER | MinIO root user (Docker Compose) | β | Yes |
| MINIO_ROOT_PASSWORD | MinIO root password (Docker Compose) | β | Yes |
| MINIO_DEFAULT_BUCKETS | Default buckets to create (Docker Compose) | tutorkelas | No |
| PORT | Gunicorn bind port | 8000 | No |
πQuestions
π List of frequently asked questions or question that need to be answered that is related to this initiative ..