dBillionaire-Dev/insighta-labs-plus-api

GitHub: dBillionaire-Dev/insighta-labs-plus-api

基于 Node.js 和 PostgreSQL 的安全人口统计情报平台,通过 GitHub OAuth 认证和角色权限控制,为 CLI 与 Web 客户端提供自然语言查询和 CSV 导出服务。

Stars: 0 | Forks: 0

# Insighta Labs+ — 后端 API 一个安全、多接口的人口统计情报平台,基于第二阶段的人口统计情报系统构建。支持 GitHub OAuth 身份验证、基于角色的访问控制、自然语言查询、CSV 导出,并通过单一后端同时为 CLI 工具和 Web 门户提供服务。 ## 系统架构 ``` ┌─────────────────────────┐ │ Insighta Labs+ │ │ Backend API │ │ (Node.js + Express) │ └────────────┬────────────┘ │ ┌─────────────────────┼─────────────────────┐ │ │ │ ┌──────▼──────┐ ┌───────▼──────┐ ┌───────▼──────┐ │ CLI Tool │ │ Web Portal │ │ Grader / │ │ (insighta) │ │ (React/SPA) │ │ Direct API │ │ Bearer token│ │ HTTP-only │ │ clients │ └─────────────┘ │ cookies │ └─────────────┘ └─────────────┘ ┌─────────────────────────┐ │ PostgreSQL DB │ │ profiles | users | │ │ refresh_tokens │ └─────────────────────────┘ ``` 三个独立的仓库共享一个后端: - **后端 (Backend)** — Express API,PostgreSQL,JWT 身份验证,OAuth - **CLI** — 可全局安装的 `insighta` 终端工具 - **Web 门户 (Web Portal)** — 使用 HTTP-only cookie 的浏览器界面 ## 技术栈 - **运行时 (Runtime)**: Node.js + TypeScript - **框架 (Framework)**: Express - **数据库 (Database)**: PostgreSQL - **身份验证 (Auth)**: 带有 PKCE 的 GitHub OAuth 2.0 - **令牌 (Tokens)**: JSON Web Tokens (JWT) - **部署 (Deployment)**: Railway ## 本地设置 ### 前置条件 - Node.js 18+ - 本地运行的 PostgreSQL ### 步骤 ``` git clone cd profiles-api npm install cp .env.example .env # fill in all values npm run build npm run migrate # creates all tables + indexes npm run seed # seeds 2026 profiles npm run dev ``` ### 环境变量 | 变量 | 描述 | |---|---| | `PORT` | 服务器端口(默认为 3000) | | `DATABASE_URL` | PostgreSQL 连接字符串 | | `NODE_ENV` | `development` 或 `production` | | `GITHUB_CLIENT_ID` | 来自 GitHub OAuth App 设置 | | `GITHUB_CLIENT_SECRET` | 来自 GitHub OAuth App 设置 | | `GITHUB_CALLBACK_URL` | 必须与在 GitHub 上注册的完全一致 | | `JWT_ACCESS_SECRET` | 用于签名 access token 的长随机字符串 | | `JWT_REFRESH_SECRET` | 用于签名 refresh token 的长随机字符串 | | `FRONTEND_URL` | Web 门户源(用于 CORS + cookie 重定向) | | `CSRF_SECRET` | 用于生成 CSRF token 的密钥 | ## 身份验证流程 ### GitHub OAuth — Web 门户 ``` Browser → GET /auth/github ← Redirect to GitHub login page → User approves → GitHub redirects to /auth/github/callback?code=... ← Backend exchanges code for GitHub token ← Fetches GitHub user profile ← Creates/updates user in DB ← Sets HTTP-only access_token + refresh_token cookies ← Redirects browser to /dashboard ``` ### GitHub OAuth — CLI (PKCE 流程) ``` CLI generates code_verifier + code_challenge (SHA-256) CLI opens browser → GET /auth/github?code_challenge=...&code_verifier=... GitHub redirects → /auth/github/callback?code=...&code_verifier=... Backend verifies PKCE, exchanges code, returns JSON: { access_token, refresh_token, user } CLI saves tokens to ~/.insighta/credentials.json ``` PKCE 可防止 token 被拦截——`code_verifier` 绝不会发送到 GitHub,只会发送其 challenge hash。后端会在签发 token 之前验证它们是否匹配。 ## Token 处理 | Token | 有效期 | 存储 (CLI) | 存储 (Web) | |---|---|---|---| | Access token | 3 分钟 | `~/.insighta/credentials.json` | HTTP-only cookie | | Refresh token | 5 分钟 | `~/.insighta/credentials.json` | HTTP-only cookie | **轮换 (Rotation):** 每次使用 refresh token 时,它会立即从数据库中删除,并签发一对新的 token。重复使用旧的 refresh token 将返回 401。 **自动刷新:** 当 CLI 收到 401 响应时,会自动调用 `POST /auth/refresh`,使用新的 access token 重试原始请求,并将新 token 保存到磁盘。 ## 角色权限控制 系统存在两种角色:`admin` 和 `analyst`。新用户在首次登录时默认被分配 `analyst` 角色。 | 端点 | analyst | admin | |---|---|---| | `GET /api/profiles` | ✅ | ✅ | | `GET /api/profiles/:id` | ✅ | ✅ | | `GET /api/profiles/search` | ✅ | ✅ | | `GET /api/profiles/export` | ✅ | ✅ | | `POST /api/profiles` | ❌ | ✅ | | `DELETE /api/profiles/:id` | ❌ | ✅ | 角色信息被编码在 JWT payload 中,并在每次请求时由 `requireRole()` 中间件进行验证。同时,每次请求也会通过 `requireAuth` 与数据库进行交叉比对。 ## API 版本控制 对 `/api/*` 的每一个请求都必须包含以下标头: ``` X-API-Version: 1 ``` 缺失或版本不正确将返回: ``` { "status": "error", "message": "API version header required" } ``` ## API 端点 ### 身份验证 | 方法 | 端点 | 描述 | |---|---|---| | `GET` | `/auth/github` | 重定向至 GitHub OAuth | | `GET` | `/auth/github/callback` | OAuth 回调——签发 token | | `POST` | `/auth/refresh` | 刷新 access + refresh token | | `POST` | `/auth/logout` | 使 refresh token 失效 | | `GET` | `/auth/me` | 获取当前用户的个人资料 | ### 档案(均需要身份验证 + `X-API-Version: 1`) | 方法 | 端点 | 角色 | 描述 | |---|---|---|---| | `GET` | `/api/profiles` | 任意 | 列表,支持过滤、排序、分页 | | `GET` | `/api/profiles/search?q=` | 任意 | 自然语言搜索 | | `GET` | `/api/profiles/export` | 任意 | 下载 CSV | | `GET` | `/api/profiles/:id` | 任意 | 获取单个档案 | | `POST` | `/api/profiles` | admin | 创建档案 | | `DELETE` | `/api/profiles/:id` | admin | 删除档案 | ### 过滤参数(`GET /api/profiles`) | 参数 | 类型 | 示例 | |---|---|---| | `gender` | string | `male` | | `age_group` | string | `adult` | | `country_id` | string | `NG` | | `min_age` | number | `25` | | `max_age` | number | `40` | | `min_gender_probability` | float | `0.8` | | `min_country_probability` | float | `0.5` | | `sort_by` | string | `age` / `created_at` / `gender_probability` | | `order` | string | `asc` / `desc` | | `page` | number | `1` | | `limit` | number | `10`(最大 50) | ### 分页响应结构 ``` { "status": "success", "page": 1, "limit": 10, "total": 2026, "total_pages": 203, "data": [...] } ``` ## 自然语言解析 端点:`GET /api/profiles/search?q=` 基于规则的解析——不使用 AI,不使用 LLM。 | 查询 | 解析出的过滤器 | |---|---| | `young males from nigeria` | gender=male, min_age=16, max_age=24, country_id=NG | | `females above 30` | gender=female, min_age=30 | | `adult males from kenya` | gender=male, age_group=adult, country_id=KE | | `seniors from ghana` | age_group=senior, country_id=GH | | `people between 20 and 40` | min_age=20, max_age=40 | **规则:** - `young` → min_age=16, max_age=24(仅用于解析,不是已存储的年龄组) - `above/over X` → min_age=X - `below/under X` → max_age=X - `between X and Y` → min_age=X, max_age=Y - 性别词汇:male/man/men/boy → male;female/woman/women/girl → female - 国家名称 → ISO 2 字母代码(已映射 65 个国家) - 年龄组词汇:child/kids,teen/teenager,adult,senior/elderly/old 无法解析的查询将返回: ``` { "status": "error", "message": "Unable to interpret query" } ``` ## 速率限制 | 路由 | 限制 | |---|---| | `/auth/*` | 每分钟 10 次请求 | | `/api/*` | 每分钟每个用户 60 次请求 | ## 请求日志 每次请求都会记录:`[timestamp] METHOD /path STATUS_CODE duration_ms` 示例: ``` [2026-04-27T08:00:00.000Z] GET /api/profiles 200 12ms ``` ## CSV 导出 `GET /api/profiles/export` —— 支持所有的过滤参数,流式传输带有以下标头的 `.csv` 文件: ``` id, name, gender, gender_probability, age, age_group, country_id, country_name, country_probability, created_at ``` ## 数据库架构 ``` -- profiles id, name, gender, gender_probability, sample_size, age, age_group, country_id, country_name, country_probability, created_at -- users id, github_id, username, email, avatar_url, role, is_active, last_login_at, created_at -- refresh_tokens id, user_id, token, expires_at, created_at ``` ## 部署 (Railway) 启动命令: ``` npm run build && npm run migrate && npm run seed && npm start ``` 在 Railway 上需要配置的环境变量: ``` DATABASE_URL (auto-injected from Postgres plugin) NODE_ENV=production GITHUB_CLIENT_ID GITHUB_CLIENT_SECRET GITHUB_CALLBACK_URL JWT_ACCESS_SECRET JWT_REFRESH_SECRET FRONTEND_URL CSRF_SECRET ```
标签:API后端, Bearer Token, B/S架构, Express, GitHub OAuth, GNU通用公共许可证, HTTP-only Cookies, MITM代理, Node.js, PostgreSQL, RBAC权限控制, React, RESTful API, Syscalls, Web门户, 人口统计智能平台, 单页应用, 安全认证, 提示词优化, 数据分析平台, 数据导出, 测试用例, 用户画像分析, 用户画像分析系统, 自动化攻击, 自然语言查询, 身份验证与授权