feat: HR Portal - Complete Multi-Tenant System with Redis Session Storage
Major Features: - ✅ Multi-tenant architecture (tenant isolation) - ✅ Employee CRUD with lifecycle management (onboarding/offboarding) - ✅ Department tree structure with email domain management - ✅ Company info management (single-record editing) - ✅ System functions CRUD (permission management) - ✅ Email account management (multi-account per employee) - ✅ Keycloak SSO integration (auth.lab.taipei) - ✅ Redis session storage (10.1.0.254:6379) - Solves Cookie 4KB limitation - Cross-system session sharing - Sliding expiration (8 hours) - Automatic token refresh Technical Stack: Backend: - FastAPI + SQLAlchemy - PostgreSQL 16 (10.1.0.20:5433) - Keycloak Admin API integration - Docker Mailserver integration (SSH) - Alembic migrations Frontend: - Next.js 14 (App Router) - NextAuth 4 with Keycloak Provider - Redis session storage (ioredis) - Tailwind CSS Infrastructure: - Redis 7 (10.1.0.254:6379) - Session + Cache - Keycloak 26.1.0 (auth.lab.taipei) - Docker Mailserver (10.1.0.254) Architecture Highlights: - Session管理由 Keycloak + Redis 統一控制 - 支援多系統 (HR/WebMail/Calendar/Drive/Office) 共享 session - Token 自動刷新,異質服務整合 - 未來可無縫遷移到雲端 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
206
TEST-KEYCLOAK-LOGIN.md
Normal file
206
TEST-KEYCLOAK-LOGIN.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Keycloak 登入測試指南
|
||||
|
||||
## 測試前確認
|
||||
|
||||
### 1. 開發伺服器運行中
|
||||
確認前端開發伺服器正在運行:
|
||||
```bash
|
||||
cd hr-portal/frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
應該看到:
|
||||
```
|
||||
Local: http://localhost:3000/
|
||||
Network: http://10.1.0.245:3000/
|
||||
```
|
||||
|
||||
### 2. 環境變數正確
|
||||
確認 `frontend/.env` 檔案內容:
|
||||
```env
|
||||
VITE_API_BASE_URL=https://hr-api.ease.taipei
|
||||
VITE_KEYCLOAK_URL=https://auth.ease.taipei
|
||||
VITE_KEYCLOAK_REALM=porscheworld
|
||||
VITE_KEYCLOAK_CLIENT_ID=hr-portal-web
|
||||
```
|
||||
|
||||
### 3. Keycloak 可以連線
|
||||
瀏覽器開啟:
|
||||
```
|
||||
https://auth.ease.taipei/realms/porscheworld/.well-known/openid-configuration
|
||||
```
|
||||
|
||||
應該會看到一大段 JSON 配置資料。
|
||||
|
||||
## 測試步驟
|
||||
|
||||
### 步驟 1: 開啟應用
|
||||
1. 瀏覽器開啟: `http://localhost:3000`
|
||||
2. 應該會看到「HR Portal」登入頁面
|
||||
3. 畫面應該顯示:
|
||||
- 標題: "HR Portal"
|
||||
- 副標題: "企業人資管理系統"
|
||||
- 按鈕: "使用 SSO 登入"
|
||||
|
||||
**如果看到載入中畫面**:
|
||||
- 正常,表示 Keycloak 正在初始化
|
||||
- 等待幾秒鐘
|
||||
|
||||
**如果看到錯誤訊息**:
|
||||
- 開啟瀏覽器開發者工具 (F12)
|
||||
- 切換到 Console 標籤
|
||||
- 查看錯誤訊息
|
||||
- 截圖給我看
|
||||
|
||||
### 步驟 2: 點擊登入按鈕
|
||||
1. 點擊「使用 SSO 登入」按鈕
|
||||
2. 應該會**自動跳轉**到 Keycloak 登入頁面
|
||||
3. URL 應該變成 `https://auth.ease.taipei/realms/porscheworld/protocol/openid-connect/...`
|
||||
|
||||
**如果沒有跳轉**:
|
||||
- 開啟開發者工具 Console
|
||||
- 查看是否有 JavaScript 錯誤
|
||||
- 截圖錯誤訊息
|
||||
|
||||
**如果出現 "Invalid redirect_uri" 錯誤**:
|
||||
- 回到 Keycloak Admin Console
|
||||
- Clients → hr-portal-web → Settings
|
||||
- 檢查 Valid Redirect URIs 是否包含:
|
||||
```
|
||||
http://localhost:3000/*
|
||||
```
|
||||
|
||||
### 步驟 3: 在 Keycloak 登入
|
||||
1. 在 Keycloak 登入頁面輸入:
|
||||
- **Username**: porsche (或你的測試帳號)
|
||||
- **Password**: (你的密碼)
|
||||
|
||||
2. 點擊 **Sign In**
|
||||
|
||||
3. 登入成功後,應該會**自動跳轉回** HR Portal
|
||||
|
||||
**如果登入失敗**:
|
||||
- 檢查帳號密碼是否正確
|
||||
- 確認該使用者在 Keycloak 中存在且已啟用
|
||||
|
||||
### 步驟 4: 確認登入成功
|
||||
登入成功後,你應該看到:
|
||||
|
||||
1. **URL 回到**: `http://localhost:3000/` (首頁)
|
||||
|
||||
2. **Header 顯示**:
|
||||
- 左側: HR Portal Logo
|
||||
- 右側: 你的使用者名稱和 Email
|
||||
- 登出按鈕
|
||||
|
||||
3. **側邊選單**:
|
||||
- 儀表板
|
||||
- 員工管理
|
||||
- 組織架構
|
||||
|
||||
4. **主要內容區**:
|
||||
- 統計卡片 (總員工數、事業部、在職員工、本月新進)
|
||||
- 快速操作按鈕
|
||||
|
||||
### 步驟 5: 測試導航
|
||||
1. 點擊側邊選單的「員工管理」
|
||||
2. 應該看到員工列表頁面
|
||||
3. URL 變成: `http://localhost:3000/employees`
|
||||
|
||||
**如果看到空白或錯誤**:
|
||||
- 開啟開發者工具 Network 標籤
|
||||
- 查看 API 請求是否成功
|
||||
- 檢查是否有 401 Unauthorized 錯誤
|
||||
|
||||
### 步驟 6: 檢查 API Token
|
||||
1. 開啟開發者工具 (F12)
|
||||
2. 切換到 **Network** 標籤
|
||||
3. 點擊側邊選單的「員工管理」
|
||||
4. 在 Network 中找到 `employees` 請求
|
||||
5. 點擊該請求,查看 **Headers**
|
||||
6. 找到 **Request Headers** 區塊
|
||||
7. 應該看到:
|
||||
```
|
||||
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
```
|
||||
|
||||
這表示 Token 已經正確加入到 API 請求中!
|
||||
|
||||
### 步驟 7: 測試登出
|
||||
1. 點擊右上角的「登出」按鈕
|
||||
2. 應該會彈出確認對話框:「確定要登出嗎?」
|
||||
3. 點擊「確定」
|
||||
4. 應該會回到登入頁面
|
||||
5. LocalStorage 的 token 應該被清除
|
||||
|
||||
## 常見問題除錯
|
||||
|
||||
### 問題 1: Console 顯示 "Cannot read properties of undefined"
|
||||
**可能原因**: 缺少必要的檔案
|
||||
|
||||
**檢查**:
|
||||
```bash
|
||||
cd hr-portal/frontend
|
||||
ls src/contexts/AuthContext.tsx
|
||||
ls src/components/ProtectedRoute.tsx
|
||||
ls src/lib/keycloak.ts
|
||||
```
|
||||
|
||||
如果檔案不存在,請告訴我,我會幫你建立。
|
||||
|
||||
### 問題 2: "Invalid redirect_uri" 錯誤
|
||||
**解決方式**:
|
||||
1. Keycloak Admin Console
|
||||
2. Clients → hr-portal-web → Settings
|
||||
3. Valid Redirect URIs 加入:
|
||||
```
|
||||
http://localhost:3000/*
|
||||
```
|
||||
4. Save
|
||||
|
||||
### 問題 3: CORS Error
|
||||
**解決方式**:
|
||||
1. Keycloak Admin Console
|
||||
2. Clients → hr-portal-web → Settings
|
||||
3. Web Origins 加入:
|
||||
```
|
||||
http://localhost:3000
|
||||
```
|
||||
4. Save
|
||||
|
||||
### 問題 4: Token 不在 API 請求中
|
||||
**檢查**:
|
||||
1. Console 中是否有 Keycloak 錯誤
|
||||
2. LocalStorage 是否有 `access_token`
|
||||
- 開發者工具 → Application → Local Storage
|
||||
- 應該看到 `access_token` 項目
|
||||
|
||||
### 問題 5: 401 Unauthorized
|
||||
**可能原因**:
|
||||
1. Token 無效
|
||||
2. 後端 API 無法驗證 Token
|
||||
|
||||
**檢查**:
|
||||
1. 後端是否正確配置 Keycloak 驗證
|
||||
2. Keycloak Realm 和 Client 設定是否一致
|
||||
|
||||
## 成功指標
|
||||
|
||||
如果以下都正常,表示整合成功:
|
||||
|
||||
- ✅ 點擊登入會跳轉到 Keycloak
|
||||
- ✅ Keycloak 登入成功後回到應用
|
||||
- ✅ Header 顯示正確的使用者資訊
|
||||
- ✅ 可以正常瀏覽各個頁面
|
||||
- ✅ Network 中的 API 請求包含 Authorization Header
|
||||
- ✅ 登出功能正常,會清除 Token
|
||||
|
||||
## 需要幫助?
|
||||
|
||||
如果遇到任何問題:
|
||||
1. 截圖瀏覽器畫面
|
||||
2. 截圖開發者工具的 Console (錯誤訊息)
|
||||
3. 截圖開發者工具的 Network (失敗的請求)
|
||||
4. 告訴我具體在哪一步出錯
|
||||
|
||||
我會協助你排查問題!
|
||||
Reference in New Issue
Block a user