Files
ai_site/platform/internal/handler/sync_binding.go
whm 362dcee242 feat: heal dead sync channels and block deleting system default (Z12h)
Ensure default channel and rebind Agent/Binding on list, ticket, agents/me, and ensure-binding so SyncPage does not stay on deleted-channel errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 08:57:30 +08:00

101 lines
2.8 KiB
Go
Raw 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 handler
import (
"encoding/json"
"net/http"
"aijianzhan/platform/internal/authx"
"aijianzhan/platform/internal/dbsync"
"aijianzhan/platform/internal/logic/applogic"
"aijianzhan/platform/internal/svc"
"github.com/zeromicro/go-zero/rest/httpx"
)
func syncBindingsListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !requireDBSync(svcCtx, w) {
return
}
tid := syncTenantID(r)
if _, err := applogic.HealTenantSyncBind(r.Context(), svcCtx, tid); err != nil {
_ = err
}
localID := r.URL.Query().Get("local_database_id")
var (
list []dbsync.Binding
err error
)
if authx.SyncTenantWide(r.Context()) {
list, err = svcCtx.DBSync.Store().ListBindings(tid, localID)
} else {
list, err = svcCtx.DBSync.Store().ListBindingsFiltered(tid, authx.UserID(r.Context()), localID)
if err == nil {
// 附带公司共享库 Binding便于客户端展示
all, e2 := svcCtx.DBSync.Store().ListBindings(tid, localID)
if e2 == nil {
seen := map[string]bool{}
for _, b := range list {
seen[b.ID] = true
}
for _, b := range all {
if b.Shared && !seen[b.ID] {
list = append(list, b)
}
}
}
}
}
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, map[string]any{"items": list})
}
}
func syncBindingsEnsureHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !requireDBSync(svcCtx, w) {
return
}
var body dbsync.Binding
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
body.TenantID = syncTenantID(r)
uid := authx.UserID(r.Context())
if authx.SyncTenantWide(r.Context()) {
if body.UserID == 0 {
body.UserID = uid
}
} else {
// 用户自助:强制绑定到本人,禁止冒用他人 user_id禁止自助标共享库
body.UserID = uid
if body.Shared {
authx.WriteError(w, http.StatusForbidden, "仅公司管理员可将 Binding 标为公司共享库shared")
return
}
}
// Z12h-2通道空/已删 → 静默挂回公司默认同步
needHeal := body.ChannelID == ""
if !needHeal {
if _, e := svcCtx.DBSync.Store().GetChannelForTenant(body.ChannelID, body.TenantID); e != nil {
needHeal = true
}
}
if needHeal {
if healed, hErr := applogic.HealTenantSyncBind(r.Context(), svcCtx, body.TenantID); hErr == nil && healed != nil && healed.ChannelID != "" {
body.ChannelID = healed.ChannelID
}
}
saved, err := svcCtx.DBSync.Store().EnsureBinding(body)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, saved)
}
}