Skip to content

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 CheatControllerAddCoinUserRequest 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