c04abd6530
接入格式门禁前先量了一次存量:gofmt -l 在 295 个被跟踪的 .go 文件里报 6 个, 全是字段对齐与缺文件末尾换行这类机械问题。先一次性清干净,门禁接上后 Go 侧一条都不欠。 为什么独立一个提交:格式清理混进功能改动会让 diff 无法 review(正本要求存量清理独立提交)。 验证:gofmt -l 对被跟踪的 .go 文件输出为空;go vet 与 go test 全过。
51 lines
2.0 KiB
Go
51 lines
2.0 KiB
Go
package httpapi
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"net/http"
|
||
"time"
|
||
|
||
"knowledge-governance/internal/dingtalkdiscovery"
|
||
)
|
||
|
||
// dingtalkSourcesLister 是本路由需要的最小能力面:枚举「我账号下能看到」的钉钉知识库与
|
||
// 钉盘空间。真实实现由 cmd/api 注入(用 worker 同一份 dws 状态跑只读列举);
|
||
// 未接线时返回 501,而不是把"没接线"当成空列表。
|
||
type dingtalkSourcesLister interface {
|
||
ListAvailableDingtalkSources(context.Context) (dingtalkdiscovery.Result, error)
|
||
}
|
||
|
||
// listDingtalkSources 处理 GET /api/v1/dingtalk-spaces/available:
|
||
// 「系统设置 → 数据源配置」用它列出可勾选为来源的钉钉知识库与钉盘空间。
|
||
//
|
||
// 走 /api/v1/dingtalk-spaces 前缀是刻意的:该前缀在角色判定里是管理员专用(与扫码会话、
|
||
// 空间登记同级),因为这里用的是平台持有的钉钉凭据读租户目录。
|
||
func listDingtalkSources(w http.ResponseWriter, r *http.Request, config Config) {
|
||
if _, ok := requireSessionIdentity(w, r); !ok {
|
||
return
|
||
}
|
||
lister := config.DingtalkSources
|
||
if lister == nil {
|
||
writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "dingtalk source discovery is not wired"})
|
||
return
|
||
}
|
||
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Second)
|
||
defer cancel()
|
||
result, err := lister.ListAvailableDingtalkSources(ctx)
|
||
if err != nil {
|
||
if errors.Is(err, dingtalkdiscovery.ErrUnavailable) {
|
||
// 环境问题(dws 未登录 / 权限不足 / 二进制缺失):页面显示"暂时列不出来",
|
||
// 不是平台故障,也不该把内部错误细节当 500 抛出去。
|
||
writeJSON(w, http.StatusServiceUnavailable, map[string]string{
|
||
"error": "dingtalk_discovery_unavailable",
|
||
"hint": "dws 未登录或缺少租户目录读权限;请先刷新钉钉会话,或让管理员检查 dws 凭据。",
|
||
})
|
||
return
|
||
}
|
||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "could not list dingtalk sources"})
|
||
return
|
||
}
|
||
writeJSON(w, http.StatusOK, map[string]any{"data": result})
|
||
}
|