Skip to content

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

KeyValue
Git Remotehttps://git.tlab.co.id/tarantula/tarantula-v2/service/user-service.git
Branch Aktifmain
bash
git clone https://git.tlab.co.id/tarantula/tarantula-v2/service/user-service.git
cd user-service

Tech Stack

LayerTeknologi
FrameworkNestJS 10 (TypeScript)
DatabasePostgreSQL 16 via TypeORM 0.3
Cache / SessionRedis / Dragonfly (ioredis + Bull)
Object StorageMinIO (foto profil user)
Search / IndexElasticsearch 8.19 (aktivitas user)
AuthJWT (@nestjs/jwt) + bcrypt
Secret ManagementInfisical SDK v4
Loggingnest-winston + Telegram Transport
TestingJest 29 + Supertest
RuntimeNode.js (Docker)

Environment Variables

File .env (Bootstrap Infisical)

bash
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 /user di Infisical project, berbeda dengan API Tarantula yang menggunakan /.

VariableKeterangan
INFISICAL_ENVEnvironment target (dev / staging / prod)
INFISICAL_PATHPath secrets di Infisical, khusus service ini: /user
INFISICAL_SITE_URLURL Infisical server self-hosted
INFISICAL_CLIENT_IDClient ID Universal Auth
INFISICAL_CLIENT_SECRETClient Secret Universal Auth
INFISICAL_PROJECT_IDID project Infisical

Secrets via Infisical

Aplikasi

VariableDefaultKeterangan
APP_TIMEZONEUTCTimezone untuk format timestamp (created_at/updated_at) di response DTO
ORIGIN_URLBase URL frontend; dipakai membangun link reset password yang dikirim lewat email ({ORIGIN_URL}/reset-password?token=...)

Database (PostgreSQL)

VariableKeterangan
DB_HOSTHost PostgreSQL
DB_PORTPort PostgreSQL (default 5432)
DB_USERUsername PostgreSQL
DB_PASSWORDPassword PostgreSQL
DB_NAMENama database (dev: user_service)

Redis / Dragonfly

VariableDefaultKeterangan
REDIS_HOSTlocalhostHost Redis/Dragonfly
REDIS_PORT6379Port Redis
REDIS_PASSWORDPassword (opsional)

Redis digunakan untuk menyimpan access token & refresh token dengan TTL, sebagai mekanisme invalidasi session.

Mail (SMTP)

VariableKeterangan
SMTP_HOSTHost SMTP server
SMTP_PORTPort SMTP server
SMTP_USERNAMEUsername SMTP
SMTP_PASSWORDPassword SMTP
SMTP_MAILAlamat email pengirim (from) untuk email forgot password

Dipakai modul mail (via Bull queue) untuk mengirim email forgot password dengan template Handlebars.

JWT & Token

VariableKeterangan
JWT_SECRETSecret key untuk signing JWT
ACCESS_TOKEN_PREFIX_REDISPrefix key Redis untuk access token
ACCESS_TOKEN_LIFETIMETTL access token dalam detik
REFRESH_TOKEN_PREFIX_REDISPrefix key Redis untuk refresh token
REFRESH_TOKEN_LIFETIMETTL refresh token dalam detik

MinIO (Object Storage)

VariableDefaultKeterangan
MINIO_ENDPOINTlocalhostEndpoint MinIO
MINIO_PORT9000Port MinIO
MINIO_ACCESS_KEYAccess key
MINIO_SECRET_KEYSecret key
MINIO_BUCKETNama bucket; file disimpan di subfolder user-service/
MINIO_DOMAINhttps://s3.ziwardingai.xyzDomain publik MinIO; dipakai health controller untuk membentuk URL publik foto profil

Elasticsearch

VariableDefaultKeterangan
ELASTICSEARCH_HOSThttp://localhost:9200URL Elasticsearch
ELASTICSEARCH_USERNAMEUsername
ELASTICSEARCH_PASSWORDPassword
MAXIMUM_CHAT_PER_ROOM2Batas riwayat chat per room
INDEX_USER_ACTIVITY_LOGuser-activity-logNama index/alias Elasticsearch tempat activity-log menulis setiap aksi user

OPA (Open Policy Agent)

VariableDefaultKeterangan
OPA_DATABase URL opa-data service; dipanggil saat ada perubahan policy/role untuk sync

License API

VariableDefaultKeterangan
LICENSE_API_URLhttp://10.1.102.15:8003URL License management service
LICENSE_API_EMAILadmin@mail.comEmail autentikasi Basic Auth
LICENSE_API_PASSWORD123456Password autentikasi Basic Auth

Integrasi API Tarantula

VariableDefaultKeterangan
TARANTULA_API_URLBase 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

VariableDefaultKeterangan
GHOST_PASSWORDSuper@dm1nPassword akun ghost/healthcheck (healthcheck@veloint.id) yang dibuat oleh npm run seed:ghost
BASE_URLBase URL user-service; dipakai feature.seed.ts/policy.seed.ts untuk menentukan path awal feature RBAC service ini
BASE_URL_API_TARANTULABase URL api-tarantula; dipakai seed yang sama untuk path awal feature RBAC milik api-tarantula

Telegram Logging

VariableKeterangan
TELEGRAM_TOKENBot token Telegram untuk error alerting
TELEGRAM_CHAT_IDChat ID tujuan notifikasi
TELEGRAM_TOPIC_IDTopic 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.json

Arsitektur Modul

  • Authenticationauth (login/register/token), redis (token store TTL), mail (email forgot password)
  • User Managementuser (CRUD, foto, theme), disimpan lewat MinIO (foto profil)
  • RBACrole (manajemen role + level), features (feature flags), subfeatures (sub-feature), policies (role ↔ feature ↔ subfeature), shortcut-acls (akses cepat per role), opa (sync ke opa-data)
  • Supportopen-api (endpoint data RBAC untuk sync opa-data), activity-log (audit trail), infisical (secret loader), license (validasi lisensi)

Modul Penting

ModulTanggung Jawab
authLogin (email + password + bcrypt), issue JWT, refresh token, forgot/reset password
userCRUD user, upload foto profil ke MinIO, update password, update theme mode
redisMenyimpan access & refresh token dengan TTL; dipakai untuk validasi & invalidasi session
roleManajemen role dengan level hierarki; assign shortcut ACL ke role
features / subfeaturesFeature flag system; mendefinisikan fitur dan sub-fitur yang ada di platform
policiesRelasi many-to-many antara role ↔ feature ↔ subfeature; dasar keputusan otorisasi
shortcut-aclsACL shortcut: akses langsung per role ke set subfeature tertentu tanpa melalui policy penuh
opaMemanggil opa-data service setiap ada perubahan policy/role agar rule OPA selalu up-to-date
open-apiMenyediakan 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
infisicalLoader secret; preload semua env var dari Infisical sebelum modul lain berjalan
activity-logInterceptor untuk mencatat setiap aksi user (baca dari token, simpan ke DB + Elasticsearch)

Infrastruktur (Development)

Dijalankan via docker-compose.dev.yml:

bash
docker compose -f docker-compose.dev.yml up -d
ContainerImagePortKeterangan
user-jabarinDockerfile.dev (NestJS)3000Aplikasi dengan hot-reload
db-user-jabarinpostgres:16-alpine5432PostgreSQL; DB: user_service
cached-jabarindragonflydb/dragonfly6379Dragonfly (Redis-compatible); cluster mode emulated + lock_on_hashtags
minio-tarantula-userminio/minio9000 (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

ServiceEnv VariableKeterangan
opa-dataOPA_DATADipicu (GET {OPA_DATA}/role-users atau /role-grants) setiap ada perubahan role/user/feature/subfeature/policy untuk sync rule OPA
api-tarantulaTARANTULA_API_URLDipanggil (PUT {TARANTULA_API_URL}/utils/update-user-name/:id) setiap update data user, untuk sinkronisasi nama user di api-tarantula
License APILICENSE_API_URLValidasi lisensi platform via Basic Auth
InfisicalINFISICAL_SITE_URLSumber semua secrets runtime
Telegram BotTELEGRAM_TOKENAlerting error level log ke channel Telegram

Perintah Development

bash
# 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