# 🏢 人資管理系統架構設計 ## 📋 系統概述 **HR Portal** - 整合 Keycloak SSO 的企業人資管理平台 ### 核心功能 1. ✅ **SSO 統一登入** - Keycloak OAuth2/OIDC 2. 👤 **員工基本資料管理** 3. 📧 **電子郵件帳號管理** - Docker Mailserver 整合 4. 💾 **網路硬碟配額管理** - NAS 整合 5. 🔐 **系統權限管理** 6. 📊 **個人化儀表板** --- ## 🏗️ 技術架構 ### 技術堆疊 #### 前端 - **框架**: React 18 + TypeScript - **UI 庫**: Ant Design / Material-UI - **狀態管理**: React Query + Zustand - **路由**: React Router v6 - **HTTP**: Axios - **認證**: @react-keycloak/web #### 後端 - **框架**: FastAPI (Python 3.11+) - **資料庫**: PostgreSQL 16 - **ORM**: SQLAlchemy 2.0 - **認證**: python-keycloak - **API 文檔**: OpenAPI/Swagger #### 基礎設施 - **反向代理**: Traefik - **SSO**: Keycloak - **郵件**: Docker Mailserver - **儲存**: Synology NAS (WebDAV/SMB) - **容器化**: Docker + Docker Compose --- ## 🗂️ 資料庫設計 ### 員工資料表 (employees) ```sql CREATE TABLE employees ( id SERIAL PRIMARY KEY, keycloak_user_id UUID UNIQUE NOT NULL, -- Keycloak User ID employee_id VARCHAR(20) UNIQUE NOT NULL, -- 員工編號 username VARCHAR(100) UNIQUE NOT NULL, -- 登入帳號 -- 基本資料 first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, chinese_name VARCHAR(50), email VARCHAR(255) UNIQUE NOT NULL, phone VARCHAR(20), mobile VARCHAR(20), -- 任職資訊 department VARCHAR(100), position VARCHAR(100), job_title VARCHAR(100), employment_type VARCHAR(20), -- full-time, part-time, contractor hire_date DATE, termination_date DATE, -- 狀態 status VARCHAR(20) DEFAULT 'active', -- active, inactive, suspended -- 審計欄位 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by VARCHAR(100), updated_by VARCHAR(100) ); -- 索引 CREATE INDEX idx_employees_keycloak_id ON employees(keycloak_user_id); CREATE INDEX idx_employees_status ON employees(status); CREATE INDEX idx_employees_department ON employees(department); ``` ### 郵件帳號表 (email_accounts) ```sql CREATE TABLE email_accounts ( id SERIAL PRIMARY KEY, employee_id INTEGER REFERENCES employees(id) ON DELETE CASCADE, email_address VARCHAR(255) UNIQUE NOT NULL, mailbox_quota_mb INTEGER DEFAULT 1024, -- 郵箱配額 (MB) mailbox_used_mb INTEGER DEFAULT 0, -- 郵件設定 forward_to VARCHAR(255), auto_reply BOOLEAN DEFAULT FALSE, auto_reply_message TEXT, -- 狀態 is_active BOOLEAN DEFAULT TRUE, -- 審計 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_email_accounts_employee ON email_accounts(employee_id); ``` ### 網路硬碟表 (network_drives) ```sql CREATE TABLE network_drives ( id SERIAL PRIMARY KEY, employee_id INTEGER REFERENCES employees(id) ON DELETE CASCADE, -- 硬碟資訊 drive_name VARCHAR(100) NOT NULL, -- 個人硬碟名稱 drive_path VARCHAR(500) NOT NULL, -- NAS 路徑 quota_gb INTEGER DEFAULT 10, -- 配額 (GB) used_gb DECIMAL(10,2) DEFAULT 0, -- WebDAV 設定 webdav_url VARCHAR(500), smb_path VARCHAR(500), -- 權限 can_share BOOLEAN DEFAULT FALSE, -- 狀態 is_active BOOLEAN DEFAULT TRUE, -- 審計 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_network_drives_employee ON network_drives(employee_id); ``` ### 系統權限表 (system_permissions) ```sql CREATE TABLE system_permissions ( id SERIAL PRIMARY KEY, employee_id INTEGER REFERENCES employees(id) ON DELETE CASCADE, system_name VARCHAR(100) NOT NULL, -- gitea, keycloak, portainer 等 system_url VARCHAR(500), access_level VARCHAR(50), -- admin, user, readonly -- 狀態 is_active BOOLEAN DEFAULT TRUE, granted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, granted_by VARCHAR(100), UNIQUE(employee_id, system_name) ); CREATE INDEX idx_system_permissions_employee ON system_permissions(employee_id); ``` ### 審計日誌表 (audit_logs) ```sql CREATE TABLE audit_logs ( id SERIAL PRIMARY KEY, employee_id INTEGER REFERENCES employees(id), action VARCHAR(50) NOT NULL, -- create, update, delete, login resource_type VARCHAR(50), -- employee, email, drive resource_id INTEGER, old_value JSONB, new_value JSONB, ip_address VARCHAR(50), user_agent TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_audit_logs_employee ON audit_logs(employee_id); CREATE INDEX idx_audit_logs_created_at ON audit_logs(created_at); ``` --- ## 🔐 SSO 認證流程 ### 登入流程 ``` 用戶訪問 https://hr.porscheworld.tw ↓ 檢查是否已登入 (檢查 Token) ↓ 未登入 → 重定向到 Keycloak ↓ Keycloak 認證 ↓ 返回 Authorization Code ↓ 後端用 Code 換取 Access Token ↓ 驗證 Token + 取得用戶資訊 ↓ 查詢/創建員工記錄 ↓ 返回用戶 Session ↓ 顯示個人化儀表板 ``` --- ## 🌐 API 端點設計 ### 認證相關 ``` GET /api/auth/login - 發起 SSO 登入 GET /api/auth/callback - SSO 回調處理 POST /api/auth/logout - 登出 GET /api/auth/me - 取得當前用戶資訊 GET /api/auth/refresh - 刷新 Token ``` ### 員工管理 ``` GET /api/employees - 列出員工 (支援分頁/搜尋) GET /api/employees/:id - 取得員工詳情 POST /api/employees - 創建員工 PUT /api/employees/:id - 更新員工 DELETE /api/employees/:id - 刪除員工 GET /api/employees/me - 取得當前登入員工資訊 PUT /api/employees/me - 更新個人資料 ``` ### 郵件帳號管理 ``` GET /api/emails - 列出所有郵件帳號 GET /api/emails/:id - 取得郵件帳號詳情 POST /api/emails - 創建郵件帳號 PUT /api/emails/:id - 更新郵件帳號 DELETE /api/emails/:id - 刪除郵件帳號 POST /api/emails/:id/quota - 調整郵箱配額 GET /api/emails/me - 取得我的郵件帳號 ``` ### 網路硬碟管理 ``` GET /api/drives - 列出所有網路硬碟 GET /api/drives/:id - 取得硬碟詳情 POST /api/drives - 創建硬碟配額 PUT /api/drives/:id - 更新硬碟設定 DELETE /api/drives/:id - 刪除硬碟配額 GET /api/drives/me - 取得我的硬碟資訊 GET /api/drives/me/usage - 取得硬碟使用量 ``` ### 系統權限管理 ``` GET /api/permissions - 列出權限 POST /api/permissions - 授予權限 DELETE /api/permissions/:id - 撤銷權限 GET /api/permissions/me - 取得我的系統權限列表 ``` ### 儀表板 ``` GET /api/dashboard/stats - 取得統計數據 GET /api/dashboard/activity - 取得最近活動 ``` ### 審計日誌 ``` GET /api/audit-logs - 查詢審計日誌 GET /api/audit-logs/me - 查詢我的操作記錄 ``` --- ## 🎨 前端頁面結構 ### 公開頁面 - `/login` - 登入頁 (重定向到 Keycloak) - `/callback` - SSO 回調頁面 ### 管理端 (需要 admin 權限) - `/admin/dashboard` - 管理儀表板 - `/admin/employees` - 員工列表 - `/admin/employees/new` - 新增員工 - `/admin/employees/:id` - 員工詳情/編輯 - `/admin/emails` - 郵件帳號管理 - `/admin/drives` - 硬碟配額管理 - `/admin/permissions` - 權限管理 - `/admin/audit-logs` - 審計日誌 ### 個人端 (所有登入用戶) - `/` - 個人儀表板 - `/profile` - 個人資料 - `/my-email` - 我的郵件設定 - `/my-drive` - 我的網路硬碟 - `/my-systems` - 我的系統權限 --- ## 🔗 系統整合 ### 1. Keycloak 整合 ```python # 創建員工時同步到 Keycloak def create_employee(employee_data): # 1. 在 Keycloak 創建用戶 kc_user = keycloak_admin.create_user({ 'username': employee_data['username'], 'email': employee_data['email'], 'firstName': employee_data['first_name'], 'lastName': employee_data['last_name'], 'enabled': True }) # 2. 在本地資料庫創建記錄 employee = Employee( keycloak_user_id=kc_user['id'], **employee_data ) db.add(employee) return employee ``` ### 2. Docker Mailserver 整合 ```python # 創建郵件帳號 def create_email_account(employee_id, email, password): # 1. 在 Docker Mailserver 創建帳號 docker_exec( 'mailserver', f'setup email add {email} {password}' ) # 2. 記錄到資料庫 email_account = EmailAccount( employee_id=employee_id, email_address=email, mailbox_quota_mb=1024 ) db.add(email_account) return email_account ``` ### 3. NAS 儲存整合 ```python # 創建網路硬碟 def create_network_drive(employee): username = employee.username # 1. 在 NAS 創建個人資料夾 nas_path = f'/volume1/homes/{username}' create_nas_folder(nas_path) # 2. 設定配額 set_nas_quota(username, quota_gb=10) # 3. 記錄到資料庫 drive = NetworkDrive( employee_id=employee.id, drive_name=f'{username}_personal', drive_path=nas_path, quota_gb=10, webdav_url=f'https://nas.porscheworld.tw/webdav/{username}', smb_path=f'\\\\10.1.0.30\\homes\\{username}' ) db.add(drive) return drive ``` --- ## 📦 部署架構 ### Docker Compose 服務 ```yaml services: hr-portal-backend: image: hr-portal-backend:latest ports: - "8000:8000" environment: - DATABASE_URL=postgresql://... - KEYCLOAK_URL=https://auth.ease.taipei - MAILSERVER_HOST=10.1.0.254 - NAS_HOST=10.1.0.30 labels: - "traefik.enable=true" - "traefik.http.routers.hr-api.rule=Host(`hr.porscheworld.tw`) && PathPrefix(`/api`)" hr-portal-frontend: image: hr-portal-frontend:latest labels: - "traefik.enable=true" - "traefik.http.routers.hr-web.rule=Host(`hr.porscheworld.tw`)" hr-portal-db: image: postgres:16 volumes: - hr-db-data:/var/lib/postgresql/data ``` ### 網域配置 ``` https://hr.porscheworld.tw - 前端應用 https://hr.porscheworld.tw/api - 後端 API https://auth.ease.taipei - Keycloak SSO (已有) ``` --- ## 🚀 開發流程 ### 階段 1: 基礎設施 - ✅ 資料庫 Schema - ✅ Keycloak Client 設定 - ✅ 後端 API 框架 ### 階段 2: 核心功能 - ✅ SSO 認證整合 - ✅ 員工 CRUD - ✅ 郵件帳號管理 - ✅ 網路硬碟管理 ### 階段 3: 前端開發 - ✅ 管理端介面 - ✅ 個人端介面 - ✅ 儀表板 ### 階段 4: 整合測試 - ✅ 端到端測試 - ✅ 效能測試 - ✅ 安全測試 ### 階段 5: 部署上線 - ✅ Docker 容器化 - ✅ 生產環境部署 - ✅ 監控告警 --- ## 📊 使用案例 ### 案例 1: 新員工入職 ``` HR 管理員操作: 1. 登入 HR Portal (SSO) 2. 點擊「新增員工」 3. 填寫基本資料 4. 系統自動: - 在 Keycloak 創建帳號 - 創建郵件帳號 (user@ease.taipei) - 配置網路硬碟 (10GB) - 授予基本系統權限 5. 發送歡迎郵件給新員工 ``` ### 案例 2: 員工自助服務 ``` 員工操作: 1. 訪問 https://hr.porscheworld.tw 2. 用 Keycloak 帳號登入 3. 查看個人儀表板: - 基本資料 - 郵箱使用量: 500MB / 1GB - 硬碟使用量: 3GB / 10GB - 可訪問系統列表 4. 更新個人聯絡資訊 5. 設定郵件自動回覆 ``` ### 案例 3: 員工離職 ``` HR 管理員操作: 1. 搜尋員工 2. 點擊「離職處理」 3. 系統自動: - 停用 Keycloak 帳號 - 停用郵件帳號 (或轉發) - 備份個人硬碟 - 撤銷所有系統權限 4. 記錄審計日誌 ``` --- **這個架構設計可以作為開發的藍圖,接下來我們可以開始實作!** 🚀