Files
Edu/services/config-service
SpecialX 1b5781bf42 fix: add missing @RequirePermission decorators
Adds @RequirePermission to 19 TS GraphQL resolvers across 5
subgraphs (iam, config-service, core-edu, content, msg) per
audit report §6.1. Maps: iam user/role -> IAM_USER_READ;
config-service 5 queries -> CONFIG_USER; core-edu classInfo ->
CLASS_READ, exam -> EXAM_READ, grade -> GRADE_READ, homework
-> HOMEWORK_READ, datascope visibleGrades/visibleExams ->
GRADE_READ/EXAM_READ; content chapter/knowledgePoint/question/
textbook -> CONTENT_*_READ; msg notifications ->
MSG_NOTIFICATION_READ, template -> MSG_NOTIFICATION_MANAGE.
Federation resolveReference left unguarded. Python subgraphs
(data-ana, ai) deferred to follow-up infrastructure work.
2026-07-17 13:26:58 +08:00
..

config-service

v2.1 M3 / ADR-026:从 iam 拆分插件配置 + 布局 + 用户偏好职责

端口

  • HTTP: 3011
  • gRPC: 50059

职责

config-service 负责插件化仪表盘的后端配置管理(portal-shell spec §6):

  1. 插件注册表(config_plugin_registry):系统级插件元数据
  2. 角色-插件映射(config_role_plugin_mapping):角色可用插件集
  3. 角色 Layout 默认(config_role_layout_default):角色默认布局模板
  4. Layout 模板(config_layout_templates):5 种内置模板
  5. 用户布局覆盖(config_user_layout_override):用户自定义
  6. Outbox(config_outbox):v2.1 ADR-032,Debezium 监听 binlog

不涉及

  • DataScope(仍归 iam)
  • 认证 / JWT(仍归 iam)
  • 权限点 DB 查询(简化为角色判断)

架构

HTTP 3011 ─┬─ /v1/config/plugin-config      (用户三层合并)
           ├─ /v1/config/layout-templates    (用户列模板)
           ├─ /v1/config/user-layout         (用户更新布局)
           ├─ /v1/config/admin/*             (admin CRUD)
           ├─ /healthz, /readyz              (健康检查)
           ├─ /metrics                       (Prometheus)
           └─ /graphql                       (Federation 子图)

gRPC 50059 ── ConfigService                  (BFF 聚合调用)

三层合并算法

getPluginConfig(userId, userRole) 的合并逻辑(portal-shell spec §6.4):

  1. 查 config_plugin_registry WHERE is_active=TRUE
  2. 查 config_role_plugin_mapping WHERE role=:userRole
  3. 查 config_user_layout_override WHERE user_id=:userId
  4. 对每个 plugin:
    • finalProps = merge(registry.default_props, roleMapping.widget_props, userPlacement.props)
    • finalSlot = userPlacement.slot ?? roleMapping.slot ?? registry.default_slot
    • isVisible = !hidden.includes(pluginId) && (roleMapping.is_enabled ?? true) && registry.is_active

缓存

Redis 缓存(TTL 5min):

  • config:plugin:{pluginId} — 插件注册表项
  • config:user-layout:{userId} — 用户布局覆盖

失效策略:admin 修改配置或用户更新布局时主动 del。

事件

v2.1 ADR-032:业务写 config_outbox 表,Debezium 监听 binlog 投递到 Kafka。

事件命名:<Aggregate>.<Action>

  • PluginRegistry.updated
  • RolePluginMapping.updated
  • RoleLayoutDefault.updated
  • UserLayoutOverride.upserted / UserLayoutOverride.reset

开发

# 安装依赖
pnpm install

# 类型检查
pnpm --filter @edu/config-service run typecheck

# Lint
pnpm --filter @edu/config-service run lint

# 开发模式
pnpm --filter @edu/config-service run dev

环境变量

变量 默认值 说明
PORT 3011 HTTP 端口
GRPC_PORT 50059 gRPC 端口
DATABASE_URL — MySQL 连接串
REDIS_URL — Redis 连接串
KAFKA_BROKERS — Kafka broker 列表
ROUTER_AUTH_SECRET dev-router-secret Apollo Router 信任凭证
DEV_MODE false 开发模式(放行权限校验)
OTEL_EXPORTER_OTLP_ENDPOINT — OTLP exporter 端点