Teknis — User Service
Service backend RAGA yang mengelola autentikasi, otorisasi, dan manajemen user. Bertanggung jawab atas login/logout, JWT token, manajemen role & policy (RBAC), feature flags, foto profil, serta sinkronisasi policy ke OPA (Open Policy Agent).
Repository
| Key | Value |
|---|---|
| Git Remote | https://git.tlab.co.id/tarantula/tarantula-v2/service/user-service.git |
| Branch Aktif | main |
git clone https://git.tlab.co.id/tarantula/tarantula-v2/service/user-service.git
cd user-serviceTech Stack
| Layer | Teknologi |
|---|---|
| Framework | NestJS 10 (TypeScript) |
| Database | PostgreSQL 16 via TypeORM 0.3 |
| Cache / Session | Redis / Dragonfly (ioredis + Bull) |
| Object Storage | MinIO (foto profil user) |
| Search / Index | Elasticsearch 8.19 (aktivitas user) |
| Auth | JWT (@nestjs/jwt) + bcrypt |
| Secret Management | Infisical SDK v4 |
| Logging | nest-winston + Telegram Transport |
| Testing | Jest 29 + Supertest |
| Runtime | Node.js (Docker) |
Environment Variables
File .env (Bootstrap Infisical)
INFISICAL_ENV=dev
INFISICAL_PATH=/user
INFISICAL_SITE_URL=http://10.1.102.15:8002
INFISICAL_CLIENT_ID=<client-id>
INFISICAL_CLIENT_SECRET=<client-secret>
INFISICAL_PROJECT_ID=<project-id>Catatan:
INFISICAL_PATH=/user— secrets service ini tersimpan di path/userdi Infisical project, berbeda dengan API Tarantula yang menggunakan/.
| Variable | Keterangan |
|---|---|
INFISICAL_ENV | Environment target (dev / staging / prod) |
INFISICAL_PATH | Path secrets di Infisical, khusus service ini: /user |
INFISICAL_SITE_URL | URL Infisical server self-hosted |
INFISICAL_CLIENT_ID | Client ID Universal Auth |
INFISICAL_CLIENT_SECRET | Client Secret Universal Auth |
INFISICAL_PROJECT_ID | ID project Infisical |
Secrets via Infisical
Aplikasi
| Variable | Default | Keterangan |
|---|---|---|
APP_TIMEZONE | UTC | Timezone untuk format timestamp (created_at/updated_at) di response DTO |
ORIGIN_URL | — | Base URL frontend; dipakai membangun link reset password yang dikirim lewat email ({ORIGIN_URL}/reset-password?token=...) |
Database (PostgreSQL)
| Variable | Keterangan |
|---|---|
DB_HOST | Host PostgreSQL |
DB_PORT | Port PostgreSQL (default 5432) |
DB_USER | Username PostgreSQL |
DB_PASSWORD | Password PostgreSQL |
DB_NAME | Nama database (dev: user_service) |
Redis / Dragonfly
| Variable | Default | Keterangan |
|---|---|---|
REDIS_HOST | localhost | Host Redis/Dragonfly |
REDIS_PORT | 6379 | Port Redis |
REDIS_PASSWORD | — | Password (opsional) |
Redis digunakan untuk menyimpan access token & refresh token dengan TTL, sebagai mekanisme invalidasi session.
Mail (SMTP)
| Variable | Keterangan |
|---|---|
SMTP_HOST | Host SMTP server |
SMTP_PORT | Port SMTP server |
SMTP_USERNAME | Username SMTP |
SMTP_PASSWORD | Password SMTP |
SMTP_MAIL | Alamat email pengirim (from) untuk email forgot password |
Dipakai modul mail (via Bull queue) untuk mengirim email forgot password dengan template Handlebars.
JWT & Token
| Variable | Keterangan |
|---|---|
JWT_SECRET | Secret key untuk signing JWT |
ACCESS_TOKEN_PREFIX_REDIS | Prefix key Redis untuk access token |
ACCESS_TOKEN_LIFETIME | TTL access token dalam detik |
REFRESH_TOKEN_PREFIX_REDIS | Prefix key Redis untuk refresh token |
REFRESH_TOKEN_LIFETIME | TTL refresh token dalam detik |
MinIO (Object Storage)
| Variable | Default | Keterangan |
|---|---|---|
MINIO_ENDPOINT | localhost | Endpoint MinIO |
MINIO_PORT | 9000 | Port MinIO |
MINIO_ACCESS_KEY | — | Access key |
MINIO_SECRET_KEY | — | Secret key |
MINIO_BUCKET | — | Nama bucket; file disimpan di subfolder user-service/ |
MINIO_DOMAIN | https://s3.ziwardingai.xyz | Domain publik MinIO; dipakai health controller untuk membentuk URL publik foto profil |
Elasticsearch
| Variable | Default | Keterangan |
|---|---|---|
ELASTICSEARCH_HOST | http://localhost:9200 | URL Elasticsearch |
ELASTICSEARCH_USERNAME | — | Username |
ELASTICSEARCH_PASSWORD | — | Password |
MAXIMUM_CHAT_PER_ROOM | 2 | Batas riwayat chat per room |
INDEX_USER_ACTIVITY_LOG | user-activity-log | Nama index/alias Elasticsearch tempat activity-log menulis setiap aksi user |
OPA (Open Policy Agent)
| Variable | Default | Keterangan |
|---|---|---|
OPA_DATA | — | Base URL opa-data service; dipanggil saat ada perubahan policy/role untuk sync |
License API
| Variable | Default | Keterangan |
|---|---|---|
LICENSE_API_URL | http://10.1.102.15:8003 | URL License management service |
LICENSE_API_EMAIL | admin@mail.com | Email autentikasi Basic Auth |
LICENSE_API_PASSWORD | 123456 | Password autentikasi Basic Auth |
Integrasi API Tarantula
| Variable | Default | Keterangan |
|---|---|---|
TARANTULA_API_URL | — | Base URL api-tarantula; setelah update data user, dipanggil PUT {TARANTULA_API_URL}/utils/update-user-name/:id untuk sinkronisasi nama. Jika kosong, sinkronisasi dilewati |
Seeder
| Variable | Default | Keterangan |
|---|---|---|
GHOST_PASSWORD | Super@dm1n | Password akun ghost/healthcheck (healthcheck@veloint.id) yang dibuat oleh npm run seed:ghost |
BASE_URL | — | Base URL user-service; dipakai feature.seed.ts/policy.seed.ts untuk menentukan path awal feature RBAC service ini |
BASE_URL_API_TARANTULA | — | Base URL api-tarantula; dipakai seed yang sama untuk path awal feature RBAC milik api-tarantula |
Telegram Logging
| Variable | Keterangan |
|---|---|
TELEGRAM_TOKEN | Bot token Telegram untuk error alerting |
TELEGRAM_CHAT_ID | Chat ID tujuan notifikasi |
TELEGRAM_TOPIC_ID | Topic ID (thread) dalam grup Telegram |
Jika TELEGRAM_TOKEN dan TELEGRAM_CHAT_ID tidak di-set, transport Telegram tidak diaktifkan — logging hanya ke console.
Struktur Folder
user-service/
├── src/
│ ├── app.module.ts # Root module
│ ├── main.ts # Entry point NestJS
│ │
│ ├── common/ # Shared utilities & config
│ │ ├── config/
│ │ │ ├── elastic.config.ts # Elasticsearch client + query helpers
│ │ │ ├── license.config.ts # License API client (Basic Auth)
│ │ │ ├── minio.config.ts # MinIO client + upload/download helpers
│ │ │ ├── typeorm.config.ts # TypeORM config
│ │ │ ├── infisical-cli.ts # CLI helper untuk migration via Infisical
│ │ │ └── infisical-cli-seeder.ts
│ │ ├── decorator/
│ │ ├── dto/ # PaginationDto, ParamDto
│ │ ├── exception/
│ │ ├── filter/ # Global exception filter
│ │ ├── interceptor/ # Response format interceptor
│ │ ├── logger/ # Telegram Winston transport
│ │ ├── seeder.helper.ts
│ │ └── sync-to-infisical.ts
│ │
│ ├── db/
│ │ ├── migrations/ # TypeORM migrations (13 file)
│ │ └── seeds/ # data, feature, ghost, policy seeders
│ │
│ ├── infisical/ # Infisical secret loader
│ │
│ ├── auth/ # Login, register, forgot/reset password
│ ├── user/ # CRUD user, photo profile, update password/theme
│ ├── role/ # Manajemen role; level role; assign shortcut ACL
│ ├── features/ # Feature flags (fitur yang tersedia di sistem)
│ ├── subfeatures/ # Sub-feature dari tiap feature
│ ├── policies/ # Policy RBAC (feature + subfeature + role)
│ ├── shortcut-acls/ # Shortcut ACL: akses cepat per role ke subfeature
│ ├── opa/ # Trigger sync policy ke opa-data service
│ ├── open-api/ # Endpoint data RBAC untuk sync opa-data (role-users, role-grants)
│ ├── redis/ # Redis provider, service (token store)
│ ├── mail/ # Email service (Bull queue + Handlebars template)
│ ├── activity-log/ # Log aktivitas user
│ ├── shared/ # JWT helper, shared service
│ ├── log/ # HTTP request logging middleware
│ ├── health/ # Health check endpoint
│ └── utils/ # Utility endpoint
│
├── test/ # E2E tests
├── docker-compose.dev.yml # Docker untuk development lokal
├── docker-compose.yml
├── Dockerfile.dev
├── Dockerfile
└── package.jsonArsitektur Modul
- Authentication —
auth(login/register/token),redis(token store TTL),mail(email forgot password) - User Management —
user(CRUD, foto, theme), disimpan lewat MinIO (foto profil) - RBAC —
role(manajemen role + level),features(feature flags),subfeatures(sub-feature),policies(role ↔ feature ↔ subfeature),shortcut-acls(akses cepat per role),opa(sync ke opa-data) - Support —
open-api(endpoint data RBAC untuk sync opa-data),activity-log(audit trail),infisical(secret loader),license(validasi lisensi)
Modul Penting
| Modul | Tanggung Jawab |
|---|---|
auth | Login (email + password + bcrypt), issue JWT, refresh token, forgot/reset password |
user | CRUD user, upload foto profil ke MinIO, update password, update theme mode |
redis | Menyimpan access & refresh token dengan TTL; dipakai untuk validasi & invalidasi session |
role | Manajemen role dengan level hierarki; assign shortcut ACL ke role |
features / subfeatures | Feature flag system; mendefinisikan fitur dan sub-fitur yang ada di platform |
policies | Relasi many-to-many antara role ↔ feature ↔ subfeature; dasar keputusan otorisasi |
shortcut-acls | ACL shortcut: akses langsung per role ke set subfeature tertentu tanpa melalui policy penuh |
opa | Memanggil opa-data service setiap ada perubahan policy/role agar rule OPA selalu up-to-date |
open-api | Menyediakan GET /open-api/role-users (data user + role) dan GET /open-api/role-grants (data akses role → feature/subfeature) — endpoint ini yang ditarik opa-data saat proses sync |
infisical | Loader secret; preload semua env var dari Infisical sebelum modul lain berjalan |
activity-log | Interceptor untuk mencatat setiap aksi user (baca dari token, simpan ke DB + Elasticsearch) |
Infrastruktur (Development)
Dijalankan via docker-compose.dev.yml:
docker compose -f docker-compose.dev.yml up -d| Container | Image | Port | Keterangan |
|---|---|---|---|
user-jabarin | Dockerfile.dev (NestJS) | 3000 | Aplikasi dengan hot-reload |
db-user-jabarin | postgres:16-alpine | 5432 | PostgreSQL; DB: user_service |
cached-jabarin | dragonflydb/dragonfly | 6379 | Dragonfly (Redis-compatible); cluster mode emulated + lock_on_hashtags |
minio-tarantula-user | minio/minio | 9000 (API), 9001 (Console) | Object storage untuk foto profil |
Semua container terhubung dalam network network-jabarin (subnet 123.16.238.0/24).
Dragonfly dipakai sebagai pengganti Redis karena kompatibel penuh dengan protokol Redis namun performa lebih tinggi untuk concurrent workload. Flag --cluster_mode=emulated --lock_on_hashtags diperlukan untuk kompatibilitas BullMQ.
Alur Autentikasi
opa-data kemudian menarik data terbaru lewat GET /open-api/role-users dan GET /open-api/role-grants di user-service untuk membangun ulang rule OPA-nya.
Integrasi Eksternal
| Service | Env Variable | Keterangan |
|---|---|---|
| opa-data | OPA_DATA | Dipicu (GET {OPA_DATA}/role-users atau /role-grants) setiap ada perubahan role/user/feature/subfeature/policy untuk sync rule OPA |
| api-tarantula | TARANTULA_API_URL | Dipanggil (PUT {TARANTULA_API_URL}/utils/update-user-name/:id) setiap update data user, untuk sinkronisasi nama user di api-tarantula |
| License API | LICENSE_API_URL | Validasi lisensi platform via Basic Auth |
| Infisical | INFISICAL_SITE_URL | Sumber semua secrets runtime |
| Telegram Bot | TELEGRAM_TOKEN | Alerting error level log ke channel Telegram |
Perintah Development
# Install dependencies
npm install
# Jalankan development (hot-reload)
npm run start:dev
# Build production
npm run build
# Jalankan migrations
npm run migration:run
# Buat migration baru
npm run migration:create --name=NamaMigration
# Rollback migration
npm run migration:revert
# Jalankan seeder data
npm run seed:run
# Jalankan ghost user seeder
npm run seed:ghost
# Sync secrets baru ke Infisical
npm run sync:infisical