Đăng xuất Admin

Mô tả Tổng quan

Tính năng Đăng xuất Admin cung cấp cách thức an toàn để kết thúc phiên làm việc quản trị. Nó đảm bảo rằng tất cả các token xác thực, cookie phiên làm việc, và dữ liệu phiên làm việc được xóa sạch một cách an toàn. Tính năng này hỗ trợ cả đăng xuất admin thông thường và đăng xuất đại diện, đảm bảo rằng không có dữ liệu nhạy cảm nào bị để lại trong hệ thống.

Biểu đồ Hoạt động

---
config:
  theme: base
  layout: dagre
  flowchart:
    curve: linear
    htmlLabels: true
  themeVariables:
    edgeLabelBackground: "transparent"
---
flowchart TD
    %% Main components
    AdminUser[Admin User]
    LogoutController[LogoutController]
    AuthService[AuthService]
    SessionDB[(Session Store)]
    CookieDB[(Cookie Store)]
    
    %% Process steps with numbering
    AdminUser --- Step1[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>1</span>
            <p style='margin-top: 8px'>Gửi Yêu cầu Đăng xuất</p>
        </div>
    ]
    Step1 --> ValidateRequest[Xác thực Yêu cầu]
    
    ValidateRequest --- Step2[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>2</span>
            <p style='margin-top: 8px'>Kiểm tra Phiên làm việc</p>
        </div>
    ]
    Step2 --> CheckSession[Kiểm tra Phiên làm việc Hiện tại]
    
    CheckSession --- Step3[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>3</span>
            <p style='margin-top: 8px'>Xác định Loại Phiên làm việc</p>
        </div>
    ]
    Step3 --> SessionType{Loại Phiên làm việc?}
    
    SessionType --- Step4A[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4A</span>
            <p style='margin-top: 8px'>Admin Thông thường</p>
        </div>
    ]
    Step4A -->|Admin| AdminLogout[Đăng xuất Admin]
    
    SessionType --- Step4B[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4B</span>
            <p style='margin-top: 8px'>Đại diện</p>
        </div>
    ]
    Step4B -->|Representative| RepLogout[Đăng xuất Đại diện]
    
    AdminLogout --- Step5A[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>5A</span>
            <p style='margin-top: 8px'>Xóa Phiên làm việc Admin</p>
        </div>
    ]
    Step5A --> ClearAdminSession[Xóa Phiên làm việc Admin]
    
    RepLogout --- Step5B[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>5B</span>
            <p style='margin-top: 8px'>Xóa Phiên làm việc Đại diện</p>
        </div>
    ]
    Step5B --> ClearRepSession[Xóa Phiên làm việc Đại diện]
    
    ClearAdminSession --- Step6A[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>6A</span>
            <p style='margin-top: 8px'>Xóa Cookie Admin</p>
        </div>
    ]
    Step6A --> ClearAdminCookie[Xóa Admin Cookie]
    
    ClearRepSession --- Step6B[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>6B</span>
            <p style='margin-top: 8px'>Xóa Cookie Đại diện</p>
        </div>
    ]
    Step6B --> ClearRepCookie[Xóa Representative Cookie]
    
    ClearAdminCookie --- Step7A[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>7A</span>
            <p style='margin-top: 8px'>Ghi log Đăng xuất</p>
        </div>
    ]
    Step7A --> LogAdminLogout[Ghi log Đăng xuất Admin]
    
    ClearRepCookie --- Step7B[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>7B</span>
            <p style='margin-top: 8px'>Ghi log Đăng xuất</p>
        </div>
    ]
    Step7B --> LogRepLogout[Ghi log Đăng xuất Đại diện]
    
    LogAdminLogout --- Step8A[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>8A</span>
            <p style='margin-top: 8px'>Trả về Phản hồi</p>
        </div>
    ]
    Step8A --> Success[Trả về Thành công]
    
    LogRepLogout --- Step8B[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>8B</span>
            <p style='margin-top: 8px'>Trả về Phản hồi</p>
        </div>
    ]
    Step8B --> Success
    
    %% Styling
    style AdminUser fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style LogoutController fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style AuthService fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style SessionDB fill:#ffe6cc,stroke:#ff9900,stroke-width:2px
    style CookieDB fill:#ffe6cc,stroke:#ff9900,stroke-width:2px
    style ValidateRequest fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style CheckSession fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style AdminLogout fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style RepLogout fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ClearAdminSession fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ClearRepSession fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ClearAdminCookie fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ClearRepCookie fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style LogAdminLogout fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style LogRepLogout fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style Success fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style SessionType fill:#ffe6cc,stroke:#ff9900,stroke-width:2px
    style Step1 fill:transparent,stroke:transparent,stroke-width:1px
    style Step2 fill:transparent,stroke:transparent,stroke-width:1px
    style Step3 fill:transparent,stroke:transparent,stroke-width:1px
    style Step4A fill:transparent,stroke:transparent,stroke-width:1px
    style Step4B fill:transparent,stroke:transparent,stroke-width:1px
    style Step5A fill:transparent,stroke:transparent,stroke-width:1px
    style Step5B fill:transparent,stroke:transparent,stroke-width:1px
    style Step6A fill:transparent,stroke:transparent,stroke-width:1px
    style Step6B fill:transparent,stroke:transparent,stroke-width:1px
    style Step7A fill:transparent,stroke:transparent,stroke-width:1px
    style Step7B fill:transparent,stroke:transparent,stroke-width:1px
    style Step8A fill:transparent,stroke:transparent,stroke-width:1px
    style Step8B fill:transparent,stroke:transparent,stroke-width:1px

Tài liệu Trường hợp

Trường hợp 1: Đăng xuất Admin Thành công

Biểu đồ Tuần tự

sequenceDiagram
    participant Admin
    participant API as LogoutController
    participant Service as AuthService
    participant SessionDB as Database
    participant CookieDB as Cookie Store

    Note over Admin,API: Bước 1: Gửi Yêu cầu Đăng xuất
    Admin->>API: GET /api/v1/admin/auth/logout
    
    Note over API,Service: Bước 2: Xử lý Đăng xuất
    API->>Service: logout()
    
    Note over Service,Service: Bước 3: Xác định Loại Phiên làm việc
    Service->>Service: determineSessionType()
    
    Note over Service,SessionDB: Bước 4: Xóa Phiên làm việc
    Service->>SessionDB: clearAdminSession()
    SessionDB-->>Service: Xác nhận xóa
    
    Note over Service,CookieDB: Bước 5: Xóa Cookie
    Service->>CookieDB: clearAdminCookies()
    CookieDB-->>Service: Xác nhận xóa
    
    Note over Service,Service: Bước 6: Ghi log
    Service->>Service: logLogout()
    
    Note over API,Admin: Bước 7: Trả về Phản hồi
    API-->>Admin: 200 OK với thông báo đăng xuất

Trường hợp 2: Đăng xuất Đại diện

Biểu đồ Tuần tự

sequenceDiagram
    participant Admin
    participant API as LogoutController
    participant Service as AuthService
    participant SessionDB as Database
    participant CookieDB as Cookie Store

    Note over Admin,API: Bước 1: Gửi Yêu cầu Đăng xuất
    Admin->>API: GET /api/v1/admin/auth/logout
    
    Note over API,Service: Bước 2: Xử lý Đăng xuất
    API->>Service: logout()
    
    Note over Service,Service: Bước 3: Xác định Loại Phiên làm việc
    Service->>Service: determineSessionType()
    
    Note over Service,SessionDB: Bước 4: Xóa Phiên làm việc Đại diện
    Service->>SessionDB: clearRepresentativeSession()
    SessionDB-->>Service: Xác nhận xóa
    
    Note over Service,CookieDB: Bước 5: Xóa Cookie Đại diện
    Service->>CookieDB: clearRepresentativeCookies()
    CookieDB-->>Service: Xác nhận xóa
    
    Note over Service,Service: Bước 6: Ghi log
    Service->>Service: logRepresentativeLogout()
    
    Note over API,Admin: Bước 7: Trả về Phản hồi
    API-->>Admin: 200 OK với thông báo đăng xuất đại diện

Các Bước

Bước 1: Gửi Yêu cầu Đăng xuất

  • Mô tả: Admin gửi yêu cầu đăng xuất
  • Yêu cầu: GET /api/v1/admin/auth/logout
  • Headers:
    • Không cần (sử dụng cookie phiên làm việc hiện tại)
  • Xác thực:
    • Kiểm tra phiên làm việc hiện tại
    • Xác minh quyền truy cập

Bước 2: Xử lý Đăng xuất

  • Mô tả: Controller xác thực yêu cầu và chuyển cho service
  • Hành động:
    • Xác minh phiên làm việc hiện tại
    • Gọi service xác thực cho quá trình đăng xuất
    • Ghi log yêu cầu đăng xuất

Bước 3: Xác định Loại Phiên làm việc

  • Mô tả: Xác định loại phiên làm việc hiện tại
  • Hành động:
    • Kiểm tra cookie phiên làm việc
    • Xác định xem là admin thông thường hay đại diện
    • Chuẩn bị quy trình đăng xuất phù hợp

Bước 4: Xóa Phiên làm việc

  • Mô tả: Xóa dữ liệu phiên làm việc khỏi cơ sở dữ liệu
  • Hành động:
    • Xóa bản ghi phiên làm việc admin
    • Hoặc xóa bản ghi phiên làm việc đại diện
    • Cập nhật trạng thái phiên làm việc

Bước 5: Xóa Cookie

  • Mô tả: Xóa cookie phiên làm việc khỏi trình duyệt
  • Hành động:
    • Xóa admin cookie
    • Hoặc xóa representative cookie
    • Đặt thời gian hết hạn về quá khứ

Bước 6: Ghi log

  • Mô tả: Ghi lại thông tin đăng xuất
  • Hành động:
    • Ghi log đăng xuất admin
    • Hoặc ghi log đăng xuất đại diện
    • Lưu thời gian và thông tin phiên làm việc

Bước 7: Trả về Phản hồi

  • Mô tả: Gửi phản hồi thành công
  • Phản hồi:
    • Thành công: 200 OK với thông báo đăng xuất
    • Xóa cookie trong phản hồi
    • Xác nhận kết thúc phiên làm việc

API Endpoint

Endpoint: GET /api/v1/admin/auth/logout

Headers:

  • Không cần (sử dụng cookie phiên làm việc hiện tại)

Body Parameters:

  • Không có

Response:

{
    "success": true,
    "message": "Đăng xuất thành công",
    "data": {
        "logout_type": "admin", // hoặc "representative"
        "logout_time": "2024-01-01T08:00:00.000000Z",
        "session_cleared": true
    }
}

Bảng Cơ sở Dữ liệu Liên quan & Trường

erDiagram
    users {
        bigint id PK
        string name "Tên đầy đủ của user"
        string email "Địa chỉ email của user (duy nhất)"
        string uid "Firebase user ID (duy nhất)"
        int status "Trạng thái tài khoản: 1: hoạt động, 0: không hoạt động"
        timestamp created_at
        timestamp updated_at
    }
    admin_sessions {
        bigint id PK
        bigint user_id FK "Tham chiếu đến bảng users"
        string session_id "Định danh phiên làm việc duy nhất"
        timestamp expires_at "Thời gian hết hạn phiên làm việc"
        boolean is_active "Trạng thái hoạt động: 1: hoạt động, 0: không hoạt động"
        timestamp created_at
        timestamp updated_at
    }
    representative_sessions {
        bigint id PK
        bigint admin_user_id FK "Tham chiếu đến bảng users (admin)"
        bigint representative_user_id FK "Tham chiếu đến bảng users (đại diện)"
        string session_id "Định danh phiên làm việc duy nhất"
        timestamp expires_at "Thời gian hết hạn phiên làm việc"
        boolean is_active "Trạng thái hoạt động: 1: hoạt động, 0: không hoạt động"
        timestamp created_at
        timestamp updated_at
    }
    logout_logs {
        bigint id PK
        bigint user_id FK "Tham chiếu đến bảng users"
        string session_type "Loại phiên làm việc: admin, representative"
        string session_id "Định danh phiên làm việc đã đăng xuất"
        timestamp logout_time "Thời gian đăng xuất"
        string ip_address "Địa chỉ IP của user"
        timestamp created_at
    }

    users ||--o{ admin_sessions : has
    users ||--o{ representative_sessions : admin_creates
    users ||--o{ representative_sessions : is_represented
    users ||--o{ logout_logs : logs

Xử lý Lỗi

  • Ghi log

    • Tất cả các yêu cầu đăng xuất được ghi vào log ứng dụng
    • Lỗi xóa phiên làm việc được ghi lại
    • (Tùy chọn) Gửi tin nhắn slack cho các sự kiện bảo mật
  • Chi tiết Lỗi:

    Mã Trạng thái Thông báo Lỗi Mô tả
    401 "Phiên làm việc không hợp lệ." Khi không có phiên làm việc hoạt động
    403 "Không có quyền truy cập." Khi không có quyền đăng xuất
    500 Lỗi chung với thông báo exception Khi xảy ra lỗi không mong đợi

Ghi chú Bổ sung

  • Bảo mật: Tất cả các phiên làm việc được xóa sạch khi đăng xuất
  • Cookie: Cookie được xóa khỏi trình duyệt với thời gian hết hạn quá khứ
  • Ghi log: Tất cả các lần đăng xuất đều được ghi lại để kiểm tra bảo mật
  • Phiên làm việc: Hỗ trợ cả đăng xuất admin và đại diện
  • Tự động: Phiên làm việc cũng có thể hết hạn tự động sau thời gian không hoạt động
  • Cân nhắc triển khai:
    • Xác nhận đăng xuất trước khi xóa dữ liệu
    • Gửi email thông báo đăng xuất
    • Theo dõi hoạt động đăng xuất bất thường
    • Tự động đăng xuất khi phát hiện hoạt động đáng ngờ