Thiết kế: Admin Backoffice Feature
1. Tổng quan kiến trúc
flowchart TB
subgraph AdminPortal["Admin Portal (Browser)"]
UI["Admin Web UI"]
end
subgraph AdminModule["admin module (port 8083)"]
AUTH["AuthController\n/api/admin/auth"]
AOP["AdminRequestAspect\n(logging/audit)"]
subgraph Groups["Controller Groups"]
MC["Machine Controllers\n(machine, crane, group, iot, camera)"]
UC["User Controllers\n(user, coin, ticket, kol, mission)"]
NC["NFT Controllers\n(hunter, gauntlet, ball, genesis, metadata)"]
EC["Event Controllers\n(event, leaderboard ×6)"]
PC["Payment Controllers\n(exchange, payment, tax, profit, revenue)"]
SC["System Controllers\n(setting, maintenance, feature-toggle, version)"]
DC["Dashboard Controllers\n(KPI, active-user)"]
LC["Livestream Controllers\n(livestream, ban, streamer)"]
end
JMS["JMS Listeners (×10)\n(mission, online, IoT, paymaster...)"]
end
subgraph Core["application-core"]
SVC["Business Services\n(shared with web/batch)"]
end
subgraph Infra["Infrastructure"]
DB[(MySQL)]
Redis[(Redis)]
MQ[(ActiveMQ)]
S3[(AWS S3)]
Slack[(Slack)]
end
UI --> AUTH
UI --> Groups
AUTH --> AOP
Groups --> AOP
AOP --> SVC
JMS --> SVC
SVC --> DB & Redis & MQ & S3
JMS --> Slack
2. Auth flow (admin riêng với user)
sequenceDiagram
participant UI as Admin Browser
participant AC as AdminAuthController
participant SJS as SecurityJwtService
participant RCDS as UserRCDetailsService
participant DB as MySQL
UI->>AC: POST /api/admin/auth/login {email, password}
AC->>RCDS: loadUserByUsername(email)
RCDS->>DB: SELECT admin WHERE email=?
DB-->>RCDS: AdminModel
RCDS-->>AC: UserDetails (with roles/rules)
AC->>AC: validatePassword(password, hash)
AC->>SJS: generateToken(userDetails)
SJS-->>AC: JWT (admin-scoped)
AC-->>UI: { token, admin_info }
Note over UI,DB: Subsequent requests
UI->>AC: GET /api/admin/... (Authorization: Bearer <adminJWT>)
AC->>SJS: validateToken(jwt)
SJS-->>AC: valid
AC->>DB: check role/rule
3. RBAC model
erDiagram
ADMIN {
string id
string email
string password_hash
string role_id
string status
}
ROLE {
string id
string name
string role_enum
}
RULE {
string id
string name
string rule_enum
}
ROLE_RULE {
string role_id
string rule_id
}
ADMIN }o--|| ROLE : "has"
ROLE ||--o{ ROLE_RULE : "has"
RULE ||--o{ ROLE_RULE : "assigned to"
4. Machine management flow
sequenceDiagram
participant Admin as Admin UI
participant MC as MachineController
participant MachSvc as MachineService
participant MQ as ActiveMQ
participant RS as receiver-service
participant CS as ControlServer (IoT)
Admin->>MC: PUT /api/admin/machines/{id}/change-state {state: MAINTENANCE}
MC->>MachSvc: changeMachineState(machineId, state)
MachSvc->>DB: UPDATE machine SET status=MAINTENANCE
MachSvc->>MQ: publish command to machine queue
MQ->>CS: forward command to physical machine
CS-->>Machine: IoT command
Note over Admin,Machine: Machine logs come back via receiver-service
Machine-->>CS: status report
CS->>MQ: publish to queue-control-server-health-check
MQ->>RS: JMSReceiverHealthCheckMachineListener
RS->>DB: save machine history log
5. Dashboard data flow
flowchart LR
DC["DashboardController\nGET /api/admin/dashboard"]
DC -->|"amount summary"| AS["UserSystemCoinService\nPaymentService"]
DC -->|"NFT summary"| NS["NftHunterService\nNftGauntletService\nNftBountyBallService"]
DC -->|"machine state"| MS["MachineService"]
DC -->|"event summary"| ES["EventService"]
DC -->|"active users"| AU["ActiveUserSummaryService\n(pre-computed by batch)"]
AS & NS & MS & ES & AU --> DB[(MySQL)]
AU -->|"cache"| Redis[(Redis)]
6. Feature toggle mechanism
flowchart LR
FTC["FeatureToggleController\nPUT /api/admin/feature-toggles/{key}"]
FTC --> FTS["FeatureToggleService"]
FTS --> DB[(MySQL feature_toggle table)]
FTS --> Redis["Redis cache\n(TTL refresh)"]
Client["Any module"] -->|"featureToggleService.isEnabled(key)"| Redis
Redis -->|"cache miss"| DB
7. AdminRequestAspect (audit logging)
// AOP intercepts all admin controller methods
@Aspect
@Component
public class AdminRequestAspect {
@Around("execution(* com.figpop.admin.controller..*.*(..))")
public Object logRequest(ProceedingJoinPoint pjp) throws Throwable {
// Log: adminId, endpoint, method, timestamp, request body (masked)
String adminId = SecurityContextHolder.getContext()...
LOGGER.info("[ADMIN_AUDIT] admin={} method={} class={}",
adminId, pjp.getSignature().getName(), pjp.getTarget().getClass());
Object result = pjp.proceed();
LOGGER.info("[ADMIN_AUDIT] completed in {}ms", elapsed);
return result;
}
}
8. Init data flow
sequenceDiagram
participant App as AdminApplication
participant Init as InitializeData (@PostConstruct)
participant IS as InitialService
participant DB as MySQL
App->>Init: @PostConstruct
Init->>IS: initEmailTemplates()
Init->>IS: initGimmicks()
Init->>IS: initSystemSettings()
IS->>DB: INSERT IF NOT EXISTS (idempotent)
Note over Init,DB: Safe to run on every startup
9. Security concerns
| # |
Vấn đề |
Chi tiết |
| 1 |
CheatController có AddCoinUserRequest |
Endpoint thêm coin cho user bất kỳ — cần RBAC strict |
| 2 |
TriggerBatchController |
Trigger batch thủ công — cần rate limit và audit log |
| 3 |
TestController |
Test endpoint tồn tại trong admin module |
| 4 |
InitController |
Init data endpoint — phải chặn trên prod sau khi init xong |