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_templates5 种内置模板
  5. 用户布局覆盖config_user_layout_override):用户自定义
  6. Outboxconfig_outboxv2.1 ADR-032Debezium 监听 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_outboxDebezium 监听 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 端点