Appearance
Auth - Technical Map
Auto-generated bởi codebase-doc-generator ngày 2026-03-23 (verified từ code thực). Không chỉnh sửa thủ công.
Routes
| Route | Path | Mục đích |
|---|---|---|
ROUTE_LOGIN | /auth/login | Trang đăng nhập email/password |
ROUTE_REGISTER | /auth/register | Trang đăng ký |
ROUTE_FORGOT_PASSWORD | /auth/forgot_password | Trang quên mật khẩu |
Navigation & Permission
| Item | Giá trị |
|---|---|
MODULE_AUTH | auth |
| Route configs | ROUTE_LOGIN, ROUTE_REGISTER, ROUTE_FORGOT_PASSWORD đều có config rỗng |
| Navigation status | navigation: [] |
| Public access | Auth routes được xem là public entry; guard auth nằm ở router/app bootstrap, không phải module navigation |
| Default FE auth provider | Firebase composition đang active; JWT composition đang comment |
FE Pages (4)
| Page | File | Vai trò |
|---|---|---|
EmailLogin | pages/EmailLogin.tsx | Wrapper submit login email/password |
Register | pages/Register.tsx | Wrapper submit register |
ForgotPassword | pages/ForgotPassword.tsx | Flow 3 bước xin OTP, verify OTP, đổi mật khẩu |
LoginSession | pages/LoginSession.tsx | Modal nhập PIN cho POS, không phải route |
FE Components / Compositions
| Component / Composition | Vai trò |
|---|---|
Layout | Shell auth page, logo, slogan, RouterView |
EmailLoginForm | Form login account/password, link qua forgot password |
RegisterForm | Form đăng ký email/password |
ForgotPasswordForm | Form stateful theo step = 1/2/3 |
useAuth | Facade auth chung, cache profile, bootstrap redirect |
useProfile | Update locale, redirect route helper |
firebase/service.ts | Firebase auth implementation |
firebase/authConfig.ts | urql auth config cho Firebase token |
jwt/useJwtAuth.ts | JWT auth implementation (inactive) |
jwt/authConfig.ts | urql auth config cho JWT token |
jwt/storage.ts | LocalStorage token storage + subject |
GraphQL Operations
File: diva-admin/src/modules/auth/graphql/profile.graphql
Profile / session
| Operation | Mục đích |
|---|---|
GetMe | Lấy profile me hiện tại |
UpdateMe | Update me để đổi locale và profile fields |
VerifyPin | Verify PIN session cho POS |
File: diva-admin/src/modules/user/graphql/account.graphql
Password reset
| Operation | Mục đích |
|---|---|
requestOTPForgetPassword | Xin OTP quên mật khẩu |
verifyOTPForgetPassword | Xác thực OTP quên mật khẩu |
staffForgetPassword | Đổi mật khẩu mới sau khi verify OTP |
File: diva-admin/src/modules/auth/compositions/jwt/graphql.ts
JWT auth
| Operation | Mục đích |
|---|---|
Login | Login lấy access_token, refresh_token |
RefreshToken | Refresh access token khi sắp hết hạn |
FE Runtime logic
configureUseAuth.ts
| Logic | Ghi chú |
|---|---|
| Platform reset | Nếu LOCAL_STORAGE_PLATFORM đổi, xóa cache profile/report roles/CRM extension state |
| Profile cache | Cache LOCAL_STORAGE_MY_PROFILE TTL 1 giờ |
| Report role cache | Cache LOCAL_STORAGE_REPORT_ROLES TTL 1 giờ |
| Auth gate | Nếu role không hợp lệ hoặc platform mismatch thì signOut và đẩy về login |
| Notification bootstrap | Sau khi auth xong sẽ notification.subscribe(profile.id) |
| Locale | Nếu profile.language tồn tại thì set i18n.locale |
| Redirect | Nếu route hiện tại không public và là route auth hợp lệ thì redirect theo redirectRoute() / home / first visible menu |
useProfile.ts
| Logic | Ghi chú |
|---|---|
| Locale update | Gọi update_me(where: {}, _set: { language }) |
| Redirect helper | Cho phép route nếu moduleId === program_management hoặc module đó nằm trong role modules |
EmailLogin.tsx
| Logic | Ghi chú |
|---|---|
| Login payload | values.email.trim() + DivaDomain |
| Post-login side effect | Gọi createAccountActivity({ type: "L" }) |
| Clear state | clearUserBehavior() sau login |
ForgotPassword.tsx
| Logic | Ghi chú |
|---|---|
| Step 1 | Gửi requestOTPForgetPassword với email ghép @diva.vn |
| Step 2 | Gửi verifyOTPForgetPassword với account_id + OTP |
| Step 3 | Gửi staffForgetPassword với account_id, otp_string, new_password |
| Timer | Interval update seconds từ otp_expiry |
LoginSession.tsx
| Logic | Ghi chú |
|---|---|
| Mount condition | Chỉ render từ AppPos.tsx khi authenticated nhưng chưa có user session |
| Prefill username | Đọc localstorage_profile_cache và cắt phần trước @ |
| Success | globalStore.setUserSession(result.verifyPin.user) |
Auth Composition
Firebase path
| Logic | Ghi chú |
|---|---|
signInWithEmailAndPassword | Gọi Firebase SDK trực tiếp |
registerWithEmailAndPassword | Gọi Firebase SDK createUserWithEmailAndPassword |
sendPasswordResetEmail | Gọi Firebase SDK |
getIdToken | Prefix token với firebase trước khi gắn vào header |
didAuthError | Match GraphQL error chứa not found in type: 'query_root' hoặc auth hook unauthorized |
JWT path
| Logic | Ghi chú |
|---|---|
signInWithEmailAndPassword | Gọi GraphQL Login với auth_provider_type: "jwt" |
| Token storage | Lưu access_token, refresh_token, expiry vào localStorage |
| Refresh flow | Khi token sắp hết hạn, gọi RefreshToken và ghi lại token mới |
getIdToken | Prefix token với jwt |
registerWithEmailAndPassword | Hiện là no-op |
sendPasswordResetEmail | Hiện là no-op |
Backend Service Map
| Service / handler | Mục đích |
|---|---|
POST /actions | Hasura action router cho toàn bộ auth actions |
POST /events | Hasura event router |
GET /verify-token | Verify token trả Hasura session vars |
POST /verify-token | Verify token qua payload headers/body |
GET /healthz | Health check trả version tag/commit |
Backend Actions
Core auth
| Action | File | Vai trò |
|---|---|---|
login | action/auth.go | Login email/phone, encode token |
register | action/auth.go | Create account theo provider |
refreshToken | action/auth.go | Refresh JWT token |
Password / account lifecycle
| Action | File | Vai trò |
|---|---|---|
adminChangePassword | action/password.go | Admin đổi password theo account_id |
changePassword | action/password.go | User đổi password của chính mình |
resetPassword | action/password.go | Reset password bằng email |
deleteAccount | action/delete_account.go | Disable account + delete Firebase user |
OTP / PIN
| Action | File | Vai trò |
|---|---|---|
requestOTP | action/otp.go | Xin OTP login |
verifyOTP | action/otp.go | Verify OTP login |
request2FaOTP | action/otp.go | Xin OTP 2FA |
verify2FaOTP | action/otp.go | Verify OTP 2FA |
requestOTPForgetPassword | action/otp.go | Xin OTP quên mật khẩu |
verifyOTPForgetPassword | action/otp.go | Verify OTP quên mật khẩu |
staffForgetPassword | action/otp.go | Đổi mật khẩu sau OTP |
requestOTPMergeAccount | action/otp_merge_account.go | Xin OTP merge account |
verifyOTPMergeAccount | action/otp_merge_account.go | Verify OTP merge account |
adminChangePin | action/pin.go | Admin đổi PIN |
verifyPin | action/pin.go | Verify PIN session POS |
staffChangePin | action/pin.go | User đổi PIN bằng PIN cũ |
Activity / audit
| Action | File | Vai trò |
|---|---|---|
createAccountActivity | action/create_activity.go | Ghi activity login/opened_at + device metadata |
Backend Event
| Event | File | Vai trò |
|---|---|---|
employee_profile_update | event/employee_profile_update.go | Generate salary, send quit notification, recalc payroll |
Data model / storage
| Object / key | Vai trò |
|---|---|
account | Profile gốc, role, enabled flags, provider data |
account_provider | Provider hiện tại của account |
account_activity | Lưu OTP/login/merge/account events |
system_config | Cấu hình SMS/OTP/Auth |
sms_template / zns_template | Template gửi OTP, password reset, quit notice |
role_module | Scope module theo role |
group_member | Nhóm quyền bổ sung như dynamic |
device_user_log_in | Device binding cho platform staff |
local_storage_my_profile | Cache profile FE |
local_storage_report_roles | Cache report role FE |
local_storage_platform | Dùng để reset cache theo platform |
AppAccessToken localStorage | JWT token storage |
Rủi ro / Findings kỹ thuật
| # | Note |
|---|---|
| 1 | LoginSession không nằm trong route module, nên khi đọc map route chỉ thấy login/register/forgot_password là chưa đủ. |
| 2 | JWT auth path đã có đủ login/refresh/storage/authConfig nhưng đang inactive ở compositions/index.ts. |
| 3 | authorizeUser() có cache Redis theo token + platform + device_id để giảm query Hasura, nhưng vẫn fallback query đầy đủ khi cache miss hoặc cache lỗi (diva-backend/services/auth/server/auth.go:132-197). |
| 4 | requestOTPMergeAccount() và requestOTPForgetPassword() đều có đoạn fallback ZNS/SMS khá dài; đây là điểm lặp lớn nhất trong backend auth. |
| 5 | deleteAccount() và một số action không dùng payload đầu vào, nghĩa là semantics của action phụ thuộc hoàn toàn vào session hiện tại. |