Skip to content

数据库结构 v4(外部 API Key 与分配 + Assignments step 绑定)

本版本新增两张表用于管理外部聚合服务的 API Key 以及其在学校/用户范围内的分配关系;并兼容此前的迁移记录与运行中库的重复执行。

依赖:Alembic 迁移 9f1e2d3c4b5a_add_external_api_key_tables.py(down_revision: 20250101_000002)。

变更摘要:

  • 新增表 external_api_keys
  • 新增表 external_api_key_assignments
  • 旧列名 metadata 调整为 meta(迁移脚本将自动检查并重命名)
  • 对关键索引做了“幂等”检查,避免重复执行导致的 Duplicate 错误
  • assignments 增加可选外键 step_idchapter_steps.id(索引:ix_assignments_step_idON DELETE SET NULL

external_api_keys

  • id: int pk
  • provider: varchar(32) not null, index(取值:new_api / ai_intent
  • name: varchar(128) not null, 用于检索显示
  • remote_token_id: varchar(64) null,上游 token id(可选)
  • key_encrypted: text not null,加密存储的密钥明文
  • key_masked: varchar(128) not null,脱敏展示(如 sk-xxxx...abcd
  • status: varchar(16) not null default activeactive / disabled / revoked
  • meta: jsonb null(额度、分组等元信息)
  • created_by_user_id: int null(记录创建人,当前未强制)
  • created_at: timestamptz not null default now()
  • deleted: boolean not null default false(软删除)

索引:

  • ix_external_api_keys_provider(provider)
  • ix_external_api_keys_status(status)
  • ix_external_api_keys_deleted(deleted)

备注:

  • 运行中库若存在 metadata 列,会在迁移中自动重命名为 meta

external_api_key_assignments

  • id: int pk
  • provider: varchar(32) not null(new_api / ai_intent
  • api_key_id: int not null → fk external_api_keys.id
  • scope_type: varchar(16) not null(school / user
  • scope_id: int not null(school → schools.id;user → users.id)
  • is_default: boolean not null default false(同一学校+provider 仅允许 0/1 个默认,迁移不做约束,由业务写操作保证)
  • created_by_user_id: int null
  • created_at: timestamptz not null default now()

索引:

  • ix_external_api_key_assignments_provider(provider)
  • ix_external_api_key_assignments_scope(scope_type, scope_id)
  • ix_external_api_key_assignments_is_default(is_default)

assignments 与步骤绑定(新增)

  • 表:assignments
  • 新增列:step_id INT NULL → 外键 chapter_steps.id
  • 索引:ix_assignments_step_id(step_id)
  • 级联:ON DELETE SET NULL
  • 业务校验:当请求体提供 step_id 时,需验证该 chapter_steps.id 通过其 chapter_id 归属于 courses.id = assignments.course_id

迁移(示意 SQL):

sql
ALTER TABLE assignments ADD COLUMN step_id INT NULL;
CREATE INDEX IF NOT EXISTS ix_assignments_step_id ON assignments(step_id);
ALTER TABLE assignments
  ADD CONSTRAINT fk_assignments_step_id_chapter_steps
  FOREIGN KEY (step_id) REFERENCES chapter_steps(id) ON DELETE SET NULL;

解析与使用

  • 解析优先级:用户级 > 学校默认 > 全局默认(settings.NEW_API_KEY / settings.AI_INTENT_KEY)
  • new_api 的 Bearer Token 需要 sk- 前缀;后端在请求前会自动补齐(若存储为裸 key)
  • 学校管理员可只读查看本校被分配的 Key,并按 token / api_key_id 查询日志(仅透传,不落库)