Files
xk-hy-transit-go/internal/logweb/configview.go
2026-05-28 17:03:08 +08:00

333 lines
6.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package logweb
import (
"strings"
"time"
"xk-hy-transit-go/internal/config"
syncer "xk-hy-transit-go/internal/sync"
"xk-hy-transit-go/internal/xkapi"
)
// ConfigViewResponse Web 配置页 API 响应(敏感字段已脱敏)。
type ConfigViewResponse struct {
FetchedAt string `json:"fetchedAt"`
XkAPIBaseURL string `json:"xkApiBaseUrl"`
Cloud cloudConfigView `json:"cloud"`
LocalEnv localEnvView `json:"localEnv"`
Effective effectiveConfigView `json:"effective"`
Diagnostics []string `json:"diagnostics"`
CloudRaw map[string]any `json:"cloudRaw,omitempty"`
}
type cloudConfigView struct {
OrganID string `json:"organID"`
UnitID string `json:"unitID"`
OrganName string `json:"organName"`
HosCode string `json:"hosCode"`
HosName string `json:"hosName"`
FileBucket string `json:"fileBucket"`
FileUploadURL string `json:"fileUploadUrl"`
AppKeyPreview string `json:"appKeyPreview"`
AppSecretSet bool `json:"appSecretSet"`
AesKeySet bool `json:"aesKeySet"`
UploadTokenSet bool `json:"uploadTokenSet"`
UploadTokenPreview string `json:"uploadTokenPreview"`
RawError string `json:"rawError"`
}
type localEnvView struct {
HyAppKeyPreview string `json:"hyAppKeyPreview"`
HyAppSecretSet bool `json:"hyAppSecretSet"`
HyAesKeySet bool `json:"hyAesKeySet"`
HyFileBucket string `json:"hyFileBucket"`
FileUploadViaForward bool `json:"fileUploadViaForward"`
ForwardBaseURL string `json:"forwardBaseUrl"`
ForwardSharedSecretSet bool `json:"forwardSharedSecretSet"`
XkAPITokenSet bool `json:"xkApiTokenSet"`
}
type effectiveConfigView struct {
OrganID string `json:"organID"`
UnitID string `json:"unitID"`
OrganName string `json:"organName"`
AppKeyPreview string `json:"appKeyPreview"`
AppSecretSet bool `json:"appSecretSet"`
AesKeySet bool `json:"aesKeySet"`
FileBucket string `json:"fileBucket"`
UploadTokenSet bool `json:"uploadTokenSet"`
UploadTokenPreview string `json:"uploadTokenPreview"`
UploadTokenSource string `json:"uploadTokenSource"`
FileUploadURL string `json:"fileUploadURL"`
SourceNote string `json:"sourceNote"`
ConfigRefreshed string `json:"configRefreshedAt"`
}
func maskPreview(s string) string {
s = strings.TrimSpace(s)
if s == "" {
return ""
}
if len(s) <= 12 {
return s
}
return s[:8] + "****" + s[len(s)-4:]
}
func BuildConfigView(snap syncer.ConfigSnapshot, cfg config.Config) ConfigViewResponse {
cloud := snap.Cloud
localToken := strings.TrimSpace(snap.UploadToken)
cloudToken := strings.TrimSpace(snap.CloudUploadToken)
if cloudToken == "" {
cloudToken = strings.TrimSpace(cloud.UploadToken)
}
effectiveBucket := strings.TrimSpace(snap.EffectiveFileBucket)
view := ConfigViewResponse{
FetchedAt: time.Now().Format(time.RFC3339),
XkAPIBaseURL: cfg.XkAPIBaseURL,
Cloud: cloudConfigView{
OrganID: cloud.OrganID,
UnitID: cloud.UnitID,
OrganName: cloud.OrganName,
HosCode: cloud.HosCode,
HosName: cloud.HosName,
FileBucket: cloud.FileBucket,
FileUploadURL: cloud.FileUploadURL,
AppKeyPreview: maskPreview(cloud.AppKey),
AppSecretSet: strings.TrimSpace(cloud.AppSecret) != "",
AesKeySet: strings.TrimSpace(cloud.AesKey) != "",
UploadTokenSet: cloudToken != "",
UploadTokenPreview: maskPreview(cloudToken),
RawError: snap.CloudFetchError,
},
LocalEnv: localEnvView{
HyAppKeyPreview: maskPreview(cfg.HyAppKey),
HyAppSecretSet: strings.TrimSpace(cfg.HyAppSecret) != "",
HyAesKeySet: strings.TrimSpace(cfg.HyAesKey) != "",
HyFileBucket: cfg.HyFileBucket,
FileUploadViaForward: cfg.FileUploadViaForward,
ForwardBaseURL: cfg.ForwardBaseURL,
ForwardSharedSecretSet: strings.TrimSpace(cfg.ForwardSharedSecret) != "",
XkAPITokenSet: strings.TrimSpace(cfg.XkAPIToken) != "",
},
Effective: effectiveConfigView{
OrganID: snap.EffectiveOrgan.OrganID,
UnitID: snap.EffectiveOrgan.UnitID,
OrganName: snap.EffectiveOrgan.OrganName,
AppKeyPreview: maskPreview(snap.EffectiveAppKey),
AppSecretSet: strings.TrimSpace(snap.EffectiveSecret) != "",
AesKeySet: strings.TrimSpace(snap.EffectiveAesKey) != "",
FileBucket: effectiveBucket,
UploadTokenSet: localToken != "",
UploadTokenPreview: maskPreview(localToken),
UploadTokenSource: snap.UploadTokenSource,
FileUploadURL: snap.FileUploadURL,
SourceNote: "uploadTokenRunner 按 FileAuth.java 本地生成appKey/secret/bucket 云端非空优先",
ConfigRefreshed: formatTime(snap.RefreshedAt),
},
}
if !snap.CloudOK {
view.Diagnostics = append(view.Diagnostics, "无法连接 xk-api /supervise/config"+snap.CloudFetchError)
}
if effectiveBucket == "" {
view.Diagnostics = append(view.Diagnostics, "fileBucket 为空:请在 xk-api 配置 HY_FILE_BUCKET或 transit .env HY_FILE_BUCKET")
}
if !view.Effective.UploadTokenSet {
view.Diagnostics = append(view.Diagnostics, "本地 uploadToken 未生成:检查 HY_APP_KEY、HY_APP_SECRET、HY_FILE_BUCKET 后点「重新拉取」")
}
if cloudToken != "" && localToken != "" && cloudToken != localToken {
view.Diagnostics = append(view.Diagnostics, "云端预生成 uploadToken 与 Runner 本地 token 不一致(已使用本地 FileAuth.java以 Runner 为准)")
}
if cloud.AppKey != "" && cfg.HyAppKey != "" && cloud.AppKey != cfg.HyAppKey {
view.Diagnostics = append(view.Diagnostics, "云端 appKey 与 transit 本地 HY_APP_KEY 不一致,生效值以云端为准,请点「重新拉取」")
}
if view.Effective.AppKeyPreview == "" {
view.Diagnostics = append(view.Diagnostics, "生效 appKey 为空:请在 xk-api 或 transit .env 配置 HY_APP_KEY")
}
if cfg.FileUploadViaForward {
if view.LocalEnv.ForwardSharedSecretSet {
view.Diagnostics = append(view.Diagnostics, "PDF 经 forward 上传:请确认 forward .env 的 FORWARD_SHARED_SECRET 与 transit 一致")
}
view.Diagnostics = append(view.Diagnostics, "PDF 经 forward 上传:请确认 forward ALLOW_IPS 包含中转机 IP否则 HTTP 403 body=forbidden")
}
view.CloudRaw = redactCloudRaw(cloud)
return view
}
func formatTime(t time.Time) string {
if t.IsZero() {
return "-"
}
return t.Format(time.RFC3339)
}
func redactCloudRaw(c xkapi.ConfigResponse) map[string]any {
return map[string]any{
"organID": c.OrganID,
"unitID": c.UnitID,
"organName": c.OrganName,
"hosCode": c.HosCode,
"hosName": c.HosName,
"fileUploadUrl": c.FileUploadURL,
"fileBucket": c.FileBucket,
"appKey": maskPreview(c.AppKey),
"appSecret": boolLabel(c.AppSecret != ""),
"aesKey": boolLabel(c.AesKey != ""),
"uploadToken": maskPreview(c.UploadToken),
}
}
func boolLabel(set bool) string {
if set {
return "(已配置)"
}
return "(未配置)"
}