Skip to content

Latest commit

 

History

History
444 lines (321 loc) · 11.2 KB

backend-development.md

File metadata and controls

444 lines (321 loc) · 11.2 KB

Backend Developer Guide

Panduan ini menjelaskan cara menyiapkan, menjalankan, menguji, dan mengembangkan backend Nihongo Master pada mesin lokal.

1. Technology requirements

Backend menggunakan:

  • Go standard library net/http
  • Go module bernama nihongo-master-backend
  • GORM dan MariaDB untuk persistence akun, billing, progress, dan kamus; sesi/attempt aktif masih di memori
  • Setup database MariaDB
  • JSON REST API
  • OpenAPI 3.1 contract pada backend/openapi.yaml

Versi Go

Requirement Version
Minimum Go 1.22
Tested in this repository Go 1.26.5 windows/amd64
Recommendation Versi stable terbaru yang kompatibel dengan Go 1.22+

Go 1.22 dibutuhkan karena router memakai pola method-aware dari http.ServeMux, misalnya GET /v1/home dan path value seperti {lessonID}.

Periksa versi yang aktif:

go version

Contoh output yang valid:

go version go1.26.5 windows/amd64

Jika versi lebih rendah dari 1.22, upgrade melalui halaman download resmi Go: https://go.dev/dl/.

2. Instalasi Go

Windows

  1. Download installer Windows dari https://go.dev/dl/.
  2. Jalankan installer dengan lokasi default.
  3. Tutup dan buka kembali PowerShell atau terminal IDE.
  4. Verifikasi:
go version
go env GOROOT GOPATH

Pastikan MariaDB aktif dan backend/.env memiliki konfigurasi DB_*. Ikuti setup MariaDB sebelum menjalankan API.

Untuk menjelajahi kontrak endpoint, buka backend/openapi.yaml di Swagger Editor. Kontrak ini mencakup autentikasi, Beranda, pembelajaran, ujian, paket, profil, progress, dan achievement.

macOS

Gunakan installer resmi atau Homebrew:

brew install go
go version

Linux

Gunakan paket distribusi atau archive resmi dari https://go.dev/dl/, kemudian:

go version

Pastikan executable go tersedia pada PATH terminal dan IDE.

3. Menjalankan backend

Dari root repository:

cd backend
go run ./cmd/api

Output normal:

nihongo master API listening on http://localhost:8080

Server tetap berjalan selama terminal tersebut terbuka. Hentikan dengan Ctrl+C.

Mengubah port

PowerShell:

$env:PORT = '9090'
go run ./cmd/api

Bash/zsh:

PORT=9090 go run ./cmd/api

Environment variable backend:

Variable Required Default Kegunaan
PORT Tidak 8080 Port HTTP server
GOOGLE_CLIENT_ID Hanya Google login - Web OAuth Client ID untuk validasi audience

4. Memastikan backend aktif

Health endpoint tidak membutuhkan autentikasi.

PowerShell:

Invoke-RestMethod http://localhost:8080/healthz

curl:

curl http://localhost:8080/healthz

Contoh response:

{
  "status": "ok",
  "time": "2026-07-22T15:00:00Z"
}

5. Autentikasi

Login development account dan ambil bearer token:

$session = Invoke-RestMethod `
  -Method Post `
  -Uri http://localhost:8080/v1/auth/login `
  -ContentType application/json `
  -Body '{"email":"demo@nihongomaster.app","password":"Demo123!"}'

$authHeaders = @{
  Authorization = "Bearer $($session.data.token)"
}

Endpoint katalog bersifat public. Endpoint /v1/me/*, logout, dan memulai exam membutuhkan bearer token. Google OAuth dijelaskan lengkap pada Authentication and Google OAuth Setup.

6. Integrasi dengan Flutter

Flutter membaca base URL dari compile-time variable API_BASE_URL di lib/core/network/dio_client.dart.

Android Emulator

Android Emulator memakai 10.0.2.2 untuk mengakses localhost komputer host. Nilai ini sudah menjadi default aplikasi. Jika API_BASE_URL diisi dengan localhost atau 127.0.0.1 pada Android, aplikasi juga menormalkannya otomatis menjadi 10.0.2.2:

http://10.0.2.2:8080/v1

Jalankan backend terlebih dahulu, lalu:

flutter run

iOS Simulator, Windows, macOS, Linux, dan web

Gunakan localhost:

flutter run --dart-define=API_BASE_URL=http://localhost:8080/v1

Perangkat Android/iOS fisik

localhost dan 10.0.2.2 tidak menunjuk ke komputer developer dari perangkat fisik. Gunakan alamat IPv4 LAN komputer, misalnya:

flutter run `
  --dart-define=API_BASE_URL=http://192.168.1.20:8080/v1

Pastikan:

  1. Komputer dan perangkat berada pada jaringan yang sama.
  2. Windows Firewall atau firewall OS mengizinkan port backend.
  3. Jaringan tidak mengaktifkan client isolation.

7. Struktur backend

backend/
|- cmd/api/main.go                 Application entry point dan HTTP server
|- internal/api/server.go          Routes, middleware, request/response JSON
|- internal/api/server_test.go     HTTP contract tests
|- internal/auth/google.go         Official Google ID-token verification
|- internal/domain/auth.go         Session dan Google identity models
|- internal/domain/models.go       Domain dan API data structures
|- internal/store/auth.go          Account, bcrypt, dan revocable session
|- internal/store/memory.go        In-memory repository dan seed data
|- go.sum                          Dependency integrity checksums
|- go.mod                          Module dan minimum Go version
`- README.md                       Quick reference

Tanggung jawab masing-masing package:

  • cmd/api: composition root. Membuat dependency dan menjalankan server.
  • internal/api: transport HTTP. Tidak menyimpan business state secara global.
  • internal/auth: verifikasi identitas dari provider eksternal.
  • internal/domain: tipe domain tanpa ketergantungan pada HTTP.
  • internal/store: penyimpanan dan aturan phase-1 seperti premium access.

8. API response format

Response berhasil memakai envelope data:

{
  "data": {
    "id": "demo-user",
    "displayName": "Nihongo Learner"
  }
}

Response gagal memakai envelope error:

{
  "error": {
    "code": "premium_required",
    "message": "premium entitlement required"
  }
}

Status penting:

Status Arti
200 Request berhasil
201 Resource, misalnya exam attempt, berhasil dibuat
401 Bearer token tidak ada, salah, atau sudah dicabut
402 Fitur membutuhkan entitlement premium
404 Resource tidak ditemukan
422 JSON valid tetapi data melanggar aturan domain
500 Error internal yang tidak diharapkan

9. Endpoint dan contoh request

Dashboard

Invoke-RestMethod `
  -Uri http://localhost:8080/v1/home

Filter learning track

Invoke-RestMethod `
  -Uri 'http://localhost:8080/v1/learning/tracks?system=JLPT'

Nilai system saat ini: JLPT, NAT, atau JFT.

Update profil

Invoke-RestMethod `
  -Method Patch `
  -Uri http://localhost:8080/v1/me/profile `
  -Headers $authHeaders `
  -ContentType application/json `
  -Body '{"displayName":"Rabih","target":"JLPT N4"}'

Foto profil

Mobile memilih foto dari galeri atau kamera lalu mengirim JPEG yang sudah dikompres. Backend hanya menerima gambar JPEG, PNG, atau GIF hingga 8 MB, memeriksa batas dimensi, mengecilkannya hingga 512 px, mengubahnya ke JPEG quality 82 tanpa metadata EXIF, lalu menyimpan objek ke Tencent COS. Endpoint POST /v1/me/profile/photo membutuhkan sesi login dan field multipart photo; responsnya berisi profil terbaru dengan photoUrl. URL foto dapat dibuka oleh siapa pun yang memiliki tautannya. Pastikan COS dan URL publik dikonfigurasi seperti pada panduan backend.

Simpan lesson progress

completion harus berada antara 0 dan 100. Endpoint legacy ini tidak memberikan XP atau achievement. Lesson vocabulary, grammar, kanji, dan reading harus diselesaikan melalui kuis yang dinilai server; lihat aturan gamifikasi.

Invoke-RestMethod `
  -Method Put `
  -Uri http://localhost:8080/v1/me/progress/n5-grammar-001 `
  -Headers $authHeaders `
  -ContentType application/json `
  -Body '{"completion":100,"lastPosition":420}'

Memulai exam gratis

Invoke-RestMethod `
  -Method Post `
  -Uri http://localhost:8080/v1/exam-attempts `
  -Headers $authHeaders `
  -ContentType application/json `
  -Body '{"examId":"jlpt-n5-diagnostic"}'

Exam premium akan menghasilkan HTTP 402 untuk pengguna free.

10. Development workflow

Sebelum membuka pull request, jalankan dari folder backend:

go fmt ./...
go vet ./...
go test ./...

Menjalankan satu package:

go test ./internal/api -v

Menjalankan satu test:

go test ./internal/api -run TestFreeUserCannotStartPremiumExam -v

go mod download atau go mod tidy akan mengunduh official Google API client untuk validasi ID token dan x/crypto untuk bcrypt password hashing.

Menambah endpoint baru

  1. Tambahkan atau ubah model di internal/domain.
  2. Tambahkan operasi penyimpanan di internal/store.
  3. Daftarkan route dan handler di internal/api/server.go.
  4. Gunakan writeData, writeError, dan status HTTP yang sesuai.
  5. Tambahkan contract test dengan httptest.
  6. Jalankan formatter, vet, dan test.

11. Penyimpanan dan batasan

  • Akun, billing, XP/progress lesson, achievements, serta cache dan arsip kamus disimpan di MariaDB.
  • Session login, attempt aktif, dan detail riwayat ujian masih berada di memori.
  • Satu proses API memegang named writer lock per database untuk menjaga konsistensi cache akun/progress.
  • Schema dibuat saat startup. Data lama dapat dipindahkan melalui importer; lihat panduan MariaDB.

12. Troubleshooting

go is not recognized

Go belum terpasang atau terminal belum membaca PATH baru.

  1. Jalankan where.exe go pada Windows atau which go pada macOS/Linux.
  2. Install/upgrade Go dari https://go.dev/dl/.
  3. Tutup dan buka kembali terminal serta IDE.
  4. Jalankan go version.

Port 8080 sudah digunakan

Gunakan port lain:

$env:PORT = '9090'
go run ./cmd/api

Jangan lupa menyesuaikan Flutter:

flutter run --dart-define=API_BASE_URL=http://10.0.2.2:9090/v1

Android Emulator tidak dapat terhubung

  • Utamakan 10.0.2.2; aplikasi akan menormalkan localhost untuk Android Emulator, tetapi URL eksplisit lebih mudah diverifikasi dari log.
  • Pastikan backend masih berjalan.
  • Coba health check dari komputer terlebih dahulu.
  • Periksa firewall dan Android network security apabila memakai HTTP lokal.

Response 401 unauthorized

Login kembali dan kirim token yang baru:

Authorization: Bearer <session-token>

Data hilang setelah restart

Session login dan attempt aktif masih berada di memori. Akun, billing, dan progress lesson tersimpan di MariaDB; periksa koneksi DB_* dan database yang dipakai jika data tersebut tidak muncul.

13. Roadmap backend production

  1. Perluas persistence MariaDB untuk data pengguna yang masih berada di memori.
  2. Persistent session dengan expiry, refresh rotation, dan device management.
  3. Payment provider webhook dengan signature validation dan idempotency key.
  4. Premium/lifetime entitlement audit log.
  5. Exam question bank, scoring engine, timer, dan attempt recovery.
  6. Object storage serta signed URL untuk audio dan materi offline.
  7. Background jobs untuk streak, reminder, leaderboard, dan achievement.
  8. Observability: structured logs, tracing, metrics, dan error reporting.