PMB 2025 Backend - Documentation
| Document Status | ||
|---|---|---|
| Document Owner | Product Engineering 2026 | Product Engineering 2026 |
| Contributors | ||
| Project Links | https://github.com/RistekCSUI/pmb2025-backend | https://github.com/RistekCSUI/pmb2025-backend |
| Project Links | https://pmb.cs.ui.ac.id | https://pmb.cs.ui.ac.id |
| Project Links | Sentry (https://o1164500.ingest.sentry.io) | Sentry (https://o1164500.ingest.sentry.io) |
| Team | Theodore Kevin Himawan | theodore.kevin@ristek.cs.ui.ac.id |
| Team | Ari Darrell Muljono | darrell@ristek.cs.ui.ac.id |
| Team | Grace Karina | gracekarin@ristek.cs.ui.ac.id |
| Team | Yeshua Marco G. Manurung | marco@ristek.cs.ui.ac.id |
π Background
Overviewβ
The PMB 2025 Backend is the core API service powering the RISTEK PMB (Penerimaan Mahasiswa Baru) platform. It manages the entire new-student onboarding experience including SSO-based authentication, user profiles, group assignments (kelompok besar), peer matching ("pansos"/friendship puzzles), assignment submissions, leaderboards, badges, events, QR code interactions, and an admin panel for committee members to manage all entities.
Stakeholdersβ
- Users: New students (maba), senior mentors, PMB committee (panitia), WebDev, DSAI
- Upstream Dependencies: UI SSO CAS (https://sso.ui.ac.id/cas2/), RISTEK SSO LDAP (https://sso.ristek.cs.ui.ac.id), SSO Proxy (https://proxy.sso.ristek.cs.ui.ac.id), Data Science service (recommendation engine via Redis DS)
- Downstream Consumers: PMB Frontend (https://pmb.cs.ui.ac.id), Admin Panel (https://admin.pmb.cs.ui.ac.id), Gamble Frontend (https://gamble.pmb.cs.ui.ac.id), Pansos Frontend (https://pansos.pmb.cs.ui.ac.id)
Scope & Boundariesβ
- In Scope: User authentication (SSO/LDAP/SSO Proxy), user profile management, kelompok besar grouping, friendship/invitation system, puzzle matching, senior review, assignment & submission CRUD, leaderboards (individual & group), badge system, events & carousel management, QR code generation/matching, admin panel APIs, S3 file uploads, Data Science integration for interest recommendations.
- Out of Scope: Frontend applications, email delivery, Data Science model training, infrastructure provisioning.
βοΈ Architecture & Design
System Diagramβ
Architecture Decisions (ADRs)β
- Language/Framework: TypeScript / Node.js (β₯12) / Express 4.x
- ORM: Prisma 4.x with PostgreSQL
- Database: PostgreSQL 13.3 (relational data), Redis 6.2.4 (caching & sessions), Redis DS (Data Science service communication)
- Communication: Synchronous RESTful API over HTTP with JWT-based authentication (Authorization: JWT <token>)
- File Storage: AWS S3 with presigned URLs for uploads/downloads
- Error Monitoring: Sentry with tracing integration
- Template Engine: EJS (for SSO callback token handoff via window.postMessage)
- Infrastructure: Docker + Docker Compose (dev), AWS ECR + Pusilkom (staging/production), Elastic Beanstalk (legacy deploy)
π»Technical Specifications
API Documentationβ
All routes are prefixed under /api. Authentication uses Authorization: JWT <token> headers.
Public Endpoints (No Auth)β
| Method | Pathb | Description |
|---|---|---|
| GET | / | Health check (returns ok) |
| GET | /api/auth/login | SSO UI login (redirects to CAS, returns token via EJS callback) |
| POST | /api/auth/ldap | LDAP / SSO Proxy login (username + password) |
| POST | /api/auth/addUserRegister | Register user by NPM |
| GET | /api/auth/self | Get current user from Bearer token |
| GET | /api/events | List all events |
| GET | /api/events/:id | Get event detail |
| GET | /api/carousel | List carousel items |
User Endpoints (JWT Auth)
| Method | Path | Description |
|---|---|---|
| GET | /api/common/generate-put-url | Generate S3 presigned upload URL |
| GET | /api/common/generate-get-url | Generate S3 presigned download URL |
| GET | /api/token/check | Check token validity |
| POST | /api/token/generate | Generate user token |
| POST | /api/token/post | Store token |
| GET | /api/assignment | List user assignments |
| GET | /api/assignment/:id | Get assignment detail |
| POST | /api/assignment/:id/submission | Submit assignment |
| PUT | /api/assignment/submission/:id | Update submission |
| POST | /api/assignment/createassignment | Create assignment |
| PUT | /api/assignment/updateassignment/:id | Update assignment |
| GET | /api/profile/:username | Get user profile |
| POST | /api/profile/onboarding | Complete user onboarding (with authorization check) |
| PUT | /api/profile/update/:username | Update user profile |
| GET | /api/leaderboard | Get leaderboard |
| GET | /api/leaderboard/:id | Get leaderboard entry by username |
| GET | /api/leaderboard_kelompok | Get group leaderboard |
| GET | /api/leaderboard_kelompok/:id | Get group leaderboard entry |
| GET | /api/invitation/is_friend/:username | Check friendship status |
| GET | /api/invitation/invitation_request/:username | Check invitation request |
| GET | /api/invitation/sent_list | List sent invitations |
| GET | /api/invitation/received_list | List received invitations |
| POST | /api/invitation/create_invitation | Create friendship invitation |
| POST | /api/invitation/accept_invitation | Accept friendship invitation |
| GET | /api/puzzle | List puzzles |
| GET | /api/puzzle/:id | Get puzzle detail |
| POST | /api/puzzle/submit | Submit puzzle answer |
| PUT | /api/puzzle/update | Update puzzle |
| GET | /api/senior | List seniors |
| GET | /api/senior/:id | Get senior detail |
| PUT | /api/senior/:id | Update senior |
| GET | /api/interest | List interests |
| GET | /api/interest/recomendation | Get interest recommendations (DS integration) |
| POST | /api/interest/register | Register user interests |
| GET | /api/badge | List all badges |
| GET | /api/badge/owned | List owned badges |
| GET | /api/badge/detail/:badgeId | Get badge detail |
| GET | /api/message | Get user messages |
| POST | /api/qr/match/:id | Match QR code |
| POST | /api/qr/generateQR | Generate QR code |
| POST | /api/qr/generateToken | Generate QR token |
| POST | /api/qr/refresh | Refresh QR token |
Admin Endpoints (Admin JWT Auth)
| Method | Path | Description |
|---|---|---|
| POST | /api/admin/login | Admin login |
| POST | /api/admin/register | Admin registration |
| POST | /api/admin/verify | Verify admin account |
| GET/POST | /api/admin/message | Admin message CRUD |
| GET/POST/PUT/DELETE | /api/admin/user(/:id) | User management (filter, sort, paginate) |
| GET/POST/PUT/DELETE | /api/admin/assignment(/:id) | Assignment management |
| GET/POST/PUT/DELETE | /api/admin/kelompok_besar(/:id) | Kelompok besar management |
| GET/POST/PUT/DELETE | /api/admin/friends(/:id) | Friends management |
| GET/POST/PUT/DELETE | /api/admin/senior(/:id) | Senior review management |
| GET/POST/PUT/DELETE | /api/admin/puzzle(/:id) | Puzzle management |
| GET/POST/PUT/DELETE | /api/admin/maba_review(/:id) | Maba review management |
| GET/POST/PUT/DELETE | /api/admin/question(/:id) | Question management |
| GET/POST/PUT/DELETE | /api/admin/question_for_maba(/:id) | Question for maba management |
| GET/POST/PUT/DELETE | /api/admin/user_interest(/:id) | User interest management |
| GET/POST/PUT/DELETE | /api/admin/kelompok_besar_mapping(/:id) | Kelompok mapping management |
| GET/POST/PUT/DELETE | /api/admin/submission(/:id) | Submission management |
| GET/POST/DELETE | /api/admin/owned_badge(/:id) | Owned badge management |
| GET | /api/admin/badge | Badge list/detail |
| GET/POST/PUT/DELETE | /api/admin/events(/:id) | Events management |
| GET | /api/admin/events/generate-put-url | S3 upload URL for events |
| GET/POST/PUT/DELETE | /api/admin/carousel(/:id) | Carousel management |
| GET | /api/admin/carousel/generate-put-url | S3 upload URL for carousel |
| GET/POST/PUT/DELETE | /api/admin/leaderboard(/:id) | Leaderboard management |
| GET/POST/PUT/DELETE | /api/admin/leaderboard_kelompok(/:id) | Group leaderboard management |
Data Model/Schemaβ
Core entities managed via Prisma ORM. All models reside in prisma/schema.prisma.
| Model | Purpose | Key Fields |
|---|---|---|
| Admin | Committee/admin users | username, password, role, is_verified |
| User | Student profiles | username, nama_lengkap, jurusan, angkatan, kelompok_id, foto_profil, domicile, social links |
| Assignment | Assignments with deadlines | namaAssignment, dueDate, startDate, description, link |
| Submission | User submissions for assignments | fileAWSKey, submitTime, submitLink, feedback, FK to Assignment + User |
| Kelompok_Besar | Large groups with scores | nama, skor |
| Kelompok_Besar_Mapping | NPM β group assignment | npm (PK), username, FK to Kelompok_Besar |
| Friends | Mabaβmaba / mabaβsenior friendships | sender, receiver, liked, is_puzzle, unique constraint on sender+receiver |
| Senior_Review | Senior review on friendship | send, received, status, message, feedback, status_code |
| Puzzle | Friendship puzzle pairs | maba_sender, maba_receiver, is_same_group, FK to Friends |
| Maba_Review | Maba review for puzzle | status, photo, feedback, submitted_at, FK to Puzzle |
| Question | Review questions | question |
| Question_For_Maba | Answers to review questions | answer, is_correct, FK to Question + Maba_Review |
| Interest | Interest categories | nama_interest, is_it (IT-related flag) |
| User_Interest | Userβinterest mapping | FK to User + Interest |
| PMB_Badge | Badge definitions | name, description, logo, preview |
| Owned_Badge | Userβbadge ownership | Composite PK (userId, badgeId), created_at |
| Message | Admin β user messages | content, created_at, FK to Admin (sender) + User (recipient) |
| User_QR | QR code tokens | qr_token, token, FK to User |
| Event | Events listing | namaEvent, namaOrganizer, location, isInternal, dateTime, image |
| Carousel | Homepage carousel items | description, image |
| Leaderboard | Per-user monthly scores | username, score, month (unique on username+month) |
| Leaderboard_Kelompok | Per-group monthly scores | nama_kelompok, score, month (unique on nama_kelompok+month) |
Project Structureβ
pmb2025-backend/
βββ .github/
β βββ workflows/
β βββ build.yml # CI/CD: manual dispatch β AWS ECR (prod/staging)
βββ prisma/
β βββ migrations/ # 33 Prisma migration files
β βββ schema.prisma # Database schema definition
β βββ schema.sql # Raw SQL schema export
β βββ seed.ts # Database seeding script
βββ views/
β βββ index.ejs # SSO callback template (token handoff via postMessage)
βββ src/
β βββ server.ts # Express app setup, CORS, Sentry, routes, port binding
β βββ sso.ts # Custom Passport strategy for UI SSO CAS
β βββ orgcode.ts # Faculty/major mapping by UI org code
β βββ controller/ # Request handlers
β β βββ admin/ # 17 admin controllers (user, assignment, puzzle, etc.)
β β βββ auth.ts # SSO login, LDAP login, self, register
β β βββ assignment.ts # Assignment & submission logic
β β βββ profile.ts # Profile CRUD + onboarding
β β βββ invitation.ts # Friendship invitation system
β β βββ puzzle.ts # Puzzle matching
β β βββ senior.ts # Senior review
β β βββ interest.ts # Interest registration + DS recommendations
β β βββ badge.ts # Badge system
β β βββ leaderboard.ts # Individual leaderboard
β β βββ leaderboard_kelompok.ts # Group leaderboard
β β βββ message.ts # User messaging
β β βββ qr.ts # QR code generation/matching
β β βββ carousel.ts # Carousel items
β β βββ events.ts # Events listing
β β βββ file.ts # S3 file operations
β β βββ token.ts # Token management
β βββ service/ # Business logic layer
β β βββ admin/ # 17 admin services
β β βββ (user-facing services matching controllers)
β βββ repository/ # Data access layer (Prisma queries)
β β βββ admin/ # 17 admin repositories
β β βββ (user-facing repositories matching controllers)
β βββ routes/ # Express route definitions
β β βββ admin/ # 18 admin route modules
β β βββ route.ts # Root router aggregating all sub-routes
β β βββ (user-facing route modules)
β βββ middleware/
β β βββ auth.ts # User JWT verification middleware
β β βββ admin/auth.ts # Admin JWT verification middleware
β β βββ admin.ts # Role check (panitia)
β β βββ authorization.ts # Username ownership verification
β βββ libs/
β β βββ zod/
β β βββ schema/profile.ts # Zod schema for profile validation
β β βββ validator/validator.ts # Zod validation middleware
β βββ util/
β βββ const.ts # DS service URLs and token from env
β βββ headers.ts # Content-Range / X-Total-Count headers (React Admin)
β βββ listrouter.ts # Dev-time route listing utility
β βββ prisma.ts # Prisma client singleton
β βββ redis.ts # Redis client for general caching
β βββ redis-ds.ts # Redis client for Data Science service
βββ Dockerfile # Multi-stage Node 16 build
βββ docker-compose.yml # PostgreSQL 13.3 + Redis 6.2.4 for local dev
βββ deploy.sh / deploy.bat # Elastic Beanstalk deploy scripts
βββ nodemon.json # Dev server config (ts-node)
βββ tsconfig.json # TypeScript configuration
βββ .eslintrc # ESLint configuration
βββ .prettierrc # Prettier configuration
βββ .env.example # Environment variable template
βββ package.json # Dependencies and scripts
Componentsβ
| Layer | Paths | Responsibility |
|---|---|---|
| Express Server | src/server.ts | Sets up the Express application with CORS (whitelisted origins for PMB frontend, admin panel, gamble, and pansos subdomains), Passport initialization, Sentry error monitoring with tracing, Morgan request logging, and mounts all routes under /api. |
| SSO Authentication | src/sso.ts, src/controller/auth.ts | Custom Passport strategy that integrates with UI SSO CAS (sso.ui.ac.id/cas2). Validates CAS tickets, extracts student data (name, NPM, faculty/major via org code mapping), and issues JWT tokens. Supports three auth flows: SSO UI (CAS redirect), LDAP (direct POST to sso.ristek.cs.ui.ac.id), and SSO Proxy (POST to proxy.sso.ristek.cs.ui.ac.id). Can block non-maba logins via BLOCK_NON_MABA env var. |
| User JWT Middleware | src/middleware/auth.ts | Extracts and verifies JWT from Authorization: JWT <token> header using SECRET. Decodes payload containing username, nama_lengkap, angkatan, and id. |
| Admin JWT Middleware | src/middleware/admin/auth.ts | Same JWT pattern but verifies against SECRET_ADMIN. Decodes payload containing username and role. |
| Authorization Middleware | src/middleware/authorization.ts | Ensures the authenticated user can only modify their own profile by matching req.user.username against route params/query/body. |
| Controller β Service β Repository Layer | β | Follows a clean three-layer architecture. Controllers handle HTTP request/response, services contain business logic, and repositories encapsulate Prisma database queries. Both user-facing and admin modules follow this pattern across 17+ feature domains. |
| Admin Panel Support | src/util/headers.ts | Generates Content-Range and X-Total-Count response headers to support React Admin's data provider pagination interface. |
| S3 File Operations | src/controller/file.ts | Generates presigned PUT/GET URLs using AWS SDK v3 for secure file uploads and downloads to S3. |
| Data Science Integration | src/util/const.ts, src/util/redis-ds.ts | Communicates with the DSAI recommendation service via a dedicated Redis instance and HTTP endpoints for interest-based recommendations. |
| QR Code System | src/controller/qr.ts | Generates QR codes and tokens for in-person event interactions using the qrcode and nanoid libraries. |
βοΈ Operational Playbook
Infrastructureβ
- Cloud Provider: AWS (ECR for container registry) + Pusilkom instance
- CI/CD: GitHub Actions (.github/workflows/build.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/pmb-backend)
- Container: Docker (Node 16 multi-stage build), runs prisma migrate deploy on startup
- Legacy Deploy: Elastic Beanstalk via deploy.sh / deploy.bat
- Link: https://pmb.cs.ui.ac.id
Environment Variablesβ
(example)
| Key | Description | Default (Dev) | Sensitive? |
|---|---|---|---|
| PORT | Server listening port | 8000 | No |
| DATABASE_URL | PostgreSQL connection string | β | Yes |
| BASE_URL | Base URL for SSO callback | http://localhost:8000 | No |
| REDIS_URL | Main Redis connection string | β | Yes |
| SECRET | JWT secret for user tokens | β | Yes |
| SECRET_ADMIN | JWT secret for admin tokens | β | Yes |
| AWS_ACCESS_ID | AWS S3 access key ID | β | Yes |
| AWS_SECRET_KEY | AWS S3 secret access key | β | Yes |
| AWS_S3_BUCKET | S3 bucket name | β | No |
| NODE_ENV | Environment (development / production) | development | No |
| PMB_YEAR | Cohort year for maba filtering | 2025 | No |
| BLOCK_NON_MABA | Block non-maba SSO login (yes/no) | β | No |
| AUTH_PROVIDER | Auth provider (ldap / sso-proxy) | β | No |
| DEADLINE_MA | Maba deadline timestamp | β | No |
| DEADLINE_MM | Maba matching deadline timestamp | β | No |
| DS_POST_URL_PROD | Data Science POST URL (production) | β | No |
| DS_POST_URL_DEV | Data Science POST URL (development) | β | No |
| DS_FETCH_URL_PROD | Data Science fetch URL (production) | β | No |
| DS_FETCH_URL_DEV | Data Science fetch URL (development) | β | No |
| DS_TOKEN | Data Science API token | β | Yes |
| REDIS_DS_URL_PROD | DS Redis URL (production) | β | Yes |
| REDIS_DS_URL_DEV | DS Redis URL (development) | β | Yes |
| POSTGRES_USER | Docker Compose PostgreSQL user | β | Yes |
| POSTGRES_PASSWORD | Docker Compose PostgreSQL password | β | Yes |
| POSTGRES_DB | Docker Compose PostgreSQL database name | pmb | No |
| REDIS_PASSWORD | Docker Compose Redis password | β | Yes |
πQuestions
π List of frequently asked questions or question that need to be answered that is related to this initiative ..