Files
AIclinicalresearch/docs/04-开发规范/10-模块认证规范.md
HaHafeng 96290d2f76 feat(aia): Implement Protocol Agent MVP with reusable Agent framework
Sprint 1-3 Completed (Backend + Frontend):

Backend (Sprint 1-2):
- Implement 5-layer Agent framework (Query->Planner->Executor->Tools->Reflection)
- Create agent_schema with 6 tables (agent_definitions, stages, prompts, sessions, traces, reflexion_rules)
- Create protocol_schema with 2 tables (protocol_contexts, protocol_generations)
- Implement Protocol Agent core services (Orchestrator, ContextService, PromptBuilder)
- Integrate LLM service adapter (DeepSeek/Qwen/GPT-5/Claude)
- 6 API endpoints with full authentication
- 10/10 API tests passed

Frontend (Sprint 3):
- Add Protocol Agent entry in AgentHub (indigo theme card)
- Implement ProtocolAgentPage with 3-column layout
- Collapsible sidebar (Gemini style, 48px <-> 280px)
- StatePanel with 5 stage cards (scientific_question, pico, study_design, sample_size, endpoints)
- ChatArea with sync button and action cards integration
- 100% prototype design restoration (608 lines CSS)
- Detailed endpoints structure: baseline, exposure, outcomes, confounders

Features:
- 5-stage dialogue flow for research protocol design
- Conversation-driven interaction with sync-to-protocol button
- Real-time context state management
- One-click protocol generation button (UI ready, backend pending)

Database:
- agent_schema: 6 tables for reusable Agent framework
- protocol_schema: 2 tables for Protocol Agent
- Seed data: 1 agent + 5 stages + 9 prompts + 4 reflexion rules

Code Stats:
- Backend: 13 files, 4338 lines
- Frontend: 14 files, 2071 lines
- Total: 27 files, 6409 lines

Status: MVP core functionality completed, pending frontend-backend integration testing

Next: Sprint 4 - One-click protocol generation + Word export
2026-01-24 17:29:24 +08:00

6.8 KiB
Raw Blame History

模块认证规范

本文档定义了业务模块如何正确使用平台认证能力,确保所有 API 都正确携带和验证用户身份。

1. 架构概览

┌─────────────────────────────────────────────────────────────┐
│                        前端                                  │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  common/api/axios.ts  ← 带认证的 axios 实例         │   │
│  │  framework/auth/api.ts ← Token 管理 (getAccessToken)│   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                              │
                              │ Authorization: Bearer <token>
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                        后端                                  │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  common/auth/auth.middleware.ts                      │   │
│  │  - authenticate: 验证 JWT Token                     │   │
│  │  - requirePermission: 权限检查                       │   │
│  │  - requireRoles: 角色检查                            │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

2. 前端规范

2.1 使用带认证的 axios 实例(推荐)

// 导入带认证的 apiClient
import apiClient from '../../../common/api/axios';

// 使用方式与 axios 完全相同,自动携带 JWT Token
const response = await apiClient.get('/api/v2/xxx');
const response = await apiClient.post('/api/v2/xxx', data);

2.2 使用原生 fetch需手动添加 Token

import { getAccessToken } from '../../../framework/auth/api';

// 创建 getAuthHeaders 函数
function getAuthHeaders(): HeadersInit {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
  };
  const token = getAccessToken();
  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }
  return headers;
}

// 所有 fetch 请求使用 getAuthHeaders()
const response = await fetch(url, {
  headers: getAuthHeaders(),
});

// 文件上传(不设置 Content-Type
const token = getAccessToken();
const headers: HeadersInit = {};
if (token) {
  headers['Authorization'] = `Bearer ${token}`;
}
const response = await fetch(url, {
  method: 'POST',
  headers,
  body: formData,
});

3. 后端规范

3.1 路由添加认证中间件

// 导入认证中间件
import { authenticate, requirePermission } from '../../../common/auth/auth.middleware.js';

// 添加到路由
fastify.get('/xxx', { preHandler: [authenticate] }, handler);

// 需要特定权限
fastify.post('/xxx', { 
  preHandler: [authenticate, requirePermission('module:action')] 
}, handler);

3.2 控制器获取用户 ID

/**
 * 获取用户ID从JWT Token中获取
 */
function getUserId(request: FastifyRequest): string {
  const userId = (request as any).user?.userId;
  if (!userId) {
    throw new Error('User not authenticated');
  }
  return userId;
}

// 在控制器方法中使用
async function myHandler(request: FastifyRequest, reply: FastifyReply) {
  const userId = getUserId(request);
  // ... 使用 userId
}

3.3 JWT Token 结构

interface DecodedToken {
  userId: string;      // 用户ID
  phone: string;       // 手机号
  role: string;        // 角色
  tenantId: string;    // 租户ID
  tenantCode?: string; // 租户Code
  iat: number;         // 签发时间
  exp: number;         // 过期时间
}

4. 检查清单

4.1 新模块开发检查清单

  • 前端 API 文件

    • 使用 apiClient 或添加 getAuthHeaders()
    • 文件上传单独处理(不设置 Content-Type
    • 导出函数不包含测试用 userId 参数
  • 后端路由文件

    • 导入 authenticate 中间件
    • 所有需要认证的路由添加 preHandler: [authenticate]
    • 公开 API如模板列表可不添加认证
  • 后端控制器文件

    • 添加 getUserId() 辅助函数
    • 移除所有 MOCK_USER_ID 或硬编码默认值
    • 使用 getUserId(request) 获取用户 ID

4.2 已完成模块状态

模块 前端 API 后端路由 后端控制器 状态
RVW apiClient authenticate getUserId
PKB 拦截器 authenticate getUserId
ASL getAuthHeaders authenticate getUserId
DC Tool B getAuthHeaders authenticate getUserId
DC Tool C apiClient authenticate getUserId
IIT N/A (企业微信) N/A 企业微信userId
Prompt管理 getAuthHeaders authenticate getUserId

5. 常见错误和解决方案

5.1 401 Unauthorized

原因: 前端没有携带 JWT Token 或 Token 过期

解决:

  1. 检查前端 API 是否使用 apiClientgetAuthHeaders()
  2. 检查 localStorage 中是否有 accessToken
  3. 如果 Token 过期,尝试刷新或重新登录

5.2 User not authenticated

原因: 后端路由没有添加 authenticate 中间件

解决: 在路由定义中添加 preHandler: [authenticate]

5.3 TypeError: Cannot read property 'userId' of undefined

原因: 使用了错误的属性名(request.user.id 而非 request.user.userId

解决: 使用 (request as any).user?.userId

6. 参考文件

  • 前端 axios 实例: frontend-v2/src/common/api/axios.ts
  • 前端 Token 管理: frontend-v2/src/framework/auth/api.ts
  • 后端认证中间件: backend/src/common/auth/auth.middleware.ts
  • 后端 JWT 服务: backend/src/common/auth/jwt.service.ts