Files
Task_Reporter/openspec/changes/archive/2025-11-16-add-user-authentication/tasks.md
egg c8966477b9 feat: Initial commit - Task Reporter incident response system
Complete implementation of the production line incident response system (生產線異常即時反應系統) including:

Backend (FastAPI):
- User authentication with AD integration and session management
- Chat room management (create, list, update, members, roles)
- Real-time messaging via WebSocket (typing indicators, reactions)
- File storage with MinIO (upload, download, image preview)

Frontend (React + Vite):
- Authentication flow with token management
- Room list with filtering, search, and pagination
- Real-time chat interface with WebSocket
- File upload with drag-and-drop and image preview
- Member management and room settings
- Breadcrumb navigation
- 53 unit tests (Vitest)

Specifications:
- authentication: AD auth, sessions, JWT tokens
- chat-room: rooms, members, templates
- realtime-messaging: WebSocket, messages, reactions
- file-storage: MinIO integration, file management
- frontend-core: React SPA structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 17:42:52 +08:00

6.8 KiB

Implementation Tasks

1. Database Schema

  • 1.1 Create user_sessions table with columns:
    • id (PK)
    • username (email from AD)
    • display_name (for chat display)
    • internal_token (our own session token, UUID, indexed for fast lookup)
    • ad_token (token from AD API)
    • encrypted_password (AES-256 encrypted password for auto-refresh)
    • ad_token_expires_at (timestamp when AD token expires)
    • refresh_attempt_count (counter for failed refresh attempts, default 0)
    • last_activity (timestamp of last API request, indexed)
    • created_at
  • 1.2 Add database migration script
  • 1.3 Create SQLAlchemy model for UserSession in app/modules/auth/models.py

2. Backend API Implementation (Modular Structure)

  • 2.1 Create standalone app/modules/auth/ directory structure:

    • __init__.py (export public interfaces)
    • router.py (FastAPI router with auth endpoints)
    • models.py (SQLAlchemy UserSession model)
    • schemas.py (Pydantic request/response models)
    • services/ subdirectory:
      • ad_client.py (AD API communication)
      • session_service.py (session CRUD operations)
      • encryption.py (password encryption/decryption)
    • middleware.py (AuthMiddleware for protected routes)
    • dependencies.py (FastAPI dependency injection for current user)
  • 2.2 Implement services/encryption.py - EncryptionService

    • 2.2.1 Use cryptography.fernet for symmetric encryption
    • 2.2.2 Load encryption key from environment variable (FERNET_KEY)
    • 2.2.3 Function: encrypt_password(plaintext: str) -> str
    • 2.2.4 Function: decrypt_password(ciphertext: str) -> str
  • 2.3 Implement services/ad_client.py - ADAuthService

    • 2.3.1 Function: authenticate(username: str, password: str) -> dict (calls AD API)
    • 2.3.2 Parse AD response and extract token, username
    • 2.3.3 Estimate token expiry (assume 1 hour if not provided)
    • 2.3.4 Handle connection errors and return appropriate exceptions
  • 2.4 Implement services/session_service.py - SessionService

    • 2.4.1 Function: create_session(username, display_name, ad_token, encrypted_pwd, expires_at)
    • 2.4.2 Function: get_session_by_token(internal_token: str) -> UserSession
    • 2.4.3 Function: update_activity(session_id: int)
    • 2.4.4 Function: refresh_ad_token(session: UserSession) -> bool (returns success/failure)
    • 2.4.5 Function: delete_session(session_id: int)
    • 2.4.6 Function: increment_refresh_attempts(session_id: int)
    • 2.4.7 Function: reset_refresh_attempts(session_id: int)
  • 2.5 Implement router.py - Auth endpoints

    • 2.5.1 POST /api/auth/login
      • Accept LoginRequest (username, password)
      • Call ADAuthService.authenticate()
      • Encrypt password using EncryptionService
      • Generate internal_token (UUID4)
      • Call SessionService.create_session()
      • Return LoginResponse (token, display_name)
    • 2.5.2 POST /api/auth/logout
      • Accept Authorization header
      • Call SessionService.delete_session()
      • Return success message
  • 2.6 Implement middleware.py - AuthMiddleware

    • 2.6.1 Extract internal_token from Authorization header
    • 2.6.2 Query session using SessionService.get_session_by_token()
    • 2.6.3 Check if last_activity > 3 days → delete session, return 401
    • 2.6.4 Check if refresh_attempt_count >= 3 → delete session, return 401 with message
    • 2.6.5 Check if ad_token_expires_at < 5 minutes → trigger auto-refresh
    • 2.6.6 Update last_activity timestamp
    • 2.6.7 Attach user info to request.state.user
  • 2.7 Implement auto-refresh logic in middleware

    • 2.7.1 Decrypt stored password using EncryptionService
    • 2.7.2 Call ADAuthService.authenticate() with decrypted password
    • 2.7.3 If success: update ad_token, expires_at, reset refresh_attempt_count to 0
    • 2.7.4 If failure: increment refresh_attempt_count
    • 2.7.5 If refresh_attempt_count reaches 3: delete session, return 401 with "Password may have changed"
    • 2.7.6 Log all refresh attempts for security audit
  • 2.8 Implement dependencies.py - FastAPI dependency

    • 2.8.1 get_current_user() dependency that retrieves request.state.user
    • 2.8.2 Export for use in other modules: from app.modules.auth import get_current_user

3. Testing

  • 3.1 Write unit tests for EncryptionService
    • 3.1.1 Test encrypt/decrypt roundtrip
    • 3.1.2 Test that encrypted output differs from plaintext
  • 3.2 Write unit tests for ADAuthService
    • 3.2.1 Mock successful AD API response
    • 3.2.2 Mock failed authentication (401)
    • 3.2.3 Mock network error (503)
  • 3.3 Write unit tests for SessionService
    • 3.3.1 Test create_session and get_session_by_token
    • 3.3.2 Test update_activity
    • 3.3.3 Test increment/reset refresh_attempts
  • 3.4 Write integration test for login flow
    • 3.4.1 Mock AD API response
    • 3.4.2 Verify session created in database
    • 3.4.3 Verify password is encrypted in DB
    • 3.4.4 Verify response contains internal_token
  • 3.5 Write integration test for logout flow
    • 3.5.1 Create session, then logout
    • 3.5.2 Verify session deleted from database
  • 3.6 Write test for auto-refresh logic
    • 3.6.1 Mock time to simulate token near expiry
    • 3.6.2 Mock successful AD re-authentication
    • 3.6.3 Verify ad_token updated and refresh_attempt_count reset
  • 3.7 Write test for refresh failure and retry limit
    • 3.7.1 Mock 3 consecutive AD auth failures
    • 3.7.2 Verify session deleted after 3rd attempt
    • 3.7.3 Verify 401 response with appropriate message
  • 3.8 Write test for 3-day inactivity timeout
    • 3.8.1 Mock time to simulate 72+ hours since last_activity
    • 3.8.2 Verify session rejected with 401
  • 3.9 Test with actual credentials: ymirliu@panjit.com.tw / 4RFV5tgb6yhn
  • 3.10 Verify encrypted password storage and retrieval from database

4. Documentation

  • 4.1 Document API endpoints in OpenAPI/Swagger format
    • POST /api/auth/login (LoginRequest → LoginResponse)
    • POST /api/auth/logout (requires Authorization header)
  • 4.2 Write module-level README in app/modules/auth/README.md
    • Explain dual-token architecture
    • Document auto-refresh behavior and 3-retry limit
    • Document 3-day inactivity policy
    • Provide usage example for other modules
  • 4.3 Add inline code comments explaining:
    • Password encryption/decryption flow
    • Auto-refresh trigger logic (5-minute threshold)
    • Retry counter and forced logout mechanism
  • 4.4 Document environment variable requirements
    • FERNET_KEY (encryption key for passwords)