Skip to content

API dan auth

Bagaimana frontend menjangkau backend, dan bagaimana backend memutuskan siapa boleh melakukan apa.

Cara halaman ini diverifikasi

Dibaca pada 2026-09-15 dari config GraphQL backend, main.ts, guard dan strategy, dan setup Apollo/axios kedua frontend.

Tiga jalan masuk

Backend membuka tiga surface, semuanya di bawah prefix global APP_PREFIX (be-api di lokal, gapi di prod):

  1. GraphQL di /{prefix}/graphql — code-first (autoSchemaFile: true, tanpa schema.gql yang di-commit). Semua read dan write apa pun tanpa file. Hanya sebagian modul yang ada di include GraphQL: admins, catalogs, users, orders, promotions, journals.
  2. Controller REST — create/update yang meng-upload file (multipart FormData), misalnya POST catalogs/products. Frontend admin memakai axios untuk ini; storefront jarang membutuhkannya.
  3. REST webhooks/* — callback masuk dari DOKU, Biteship dan WMS. Bukan GraphQL. Lihat Third parties.

Penamaan operasi: GraphQL storefront diberi prefix front* (frontProducts, frontMemberCart); GraphQL admin/CMS polos (products, createVoucher).

Ada satu ValidationPipe global (custom exceptionFactory yang meratakan error class-validator) dan tidak ada exception filter, interceptor, atau guard global. GraphQL punya formatError custom untuk error add-to-cart (mengembalikan message, code, dan cartId opsional).

Dua realm auth

User admin dan member storefront adalah realm JWT terpisah, masing-masing dengan secret dan strategy sendiri. Guard dipasang per-resolver — tidak ada guard global.

Admin / CMSStorefront / member
Op loginlogin, loginWithGoogleloginAsMember
Strategyjwt (JWT_ACCESS_TOKEN_SECRET_KEY), jwt-refreshjwt-member (JWT_ACCESS_TOKEN_STOREFRONT_SECRET_KEY), jwt-member-refresh
GuardJwtAuthGuard, LastActivityGuard, RoleAbilityGuardJwtMemberAuthGuard
EkstraGoogle OAuth (passport-google-oauth20); auto-logout saat idleverifikasi email saat register; password bcrypt

Resolver admin yang khas menumpuk ketiga guard: @UseGuards(JwtAuthGuard, LastActivityGuard, RoleAbilityGuard). @Public() melewatinya (login, reset-password, homepage yang menghadap storefront). LastActivityGuard menegakkan auto-logout saat idle setelah CMS_AUTO_LOGOUT_MAX_INACTIVE_SECONDS (default 1800).

RBAC (admin saja)

Role membawa sekumpulan menu, masing-masing dengan lima ability: view, add, update, delete, export. Modelnya rolesroles_menusmenus.

  • Backend menegakkannya dengan @RoleCheck({ slug, action }) + RoleAbilityGuard (src/admins/guards/role-check.guard.ts), yang memeriksa role.menus milik admin untuk slug menu dan ability itu.
  • Frontend admin mencerminkannya di sisi client dengan useAccess(slug, action) (src/hooks/useAccess.tsx): ia menyembunyikan item sidebar dan mengarahkan halaman yang ditolak ke /404. Permission berasal dari query me backend, bukan hard-coded.

Member tidak punya layer role/ability — sebuah member terautentikasi atau tidak.

Bagaimana frontend mengirim token

Kedua frontend menyimpan token di session JWT NextAuth, bukan di localStorage, dan mengirimnya sebagai Authorization: Bearer <token> pada setiap request.

  • Storefront — provider Credentials NextAuth → loginAsMember. Link Apollo dan client axios keduanya membaca session dan melampirkan bearer. Saat access token kedaluwarsa, callback jwt memanggil frontRefreshToken; saat gagal, client memaksa sign-out ke /auth/signin?autologout=true.
  • Admin — Credentials NextAuth + Google. Link Apollo melampirkan bearer; client axios (src/lib/http.ts) melakukan hal sama untuk upload. Ia auto-logout pada pesan backend "no activity" dan "Access token expired".

Client GraphQL admin memakai cache: "no-store", jadi ia tidak bergantung pada cache Apollo.