8d838d9cb4
build / build (push) Successful in 1m45s
执行时真实时钟与持久授权回读(撤销/过期即停并保留预备份)、写集合写前落盘、 租约与 attempt 身份、恢复队列与原发送身份分离、成功收尾必须释放维护后再登记终态。
49 lines
1.8 KiB
Go
49 lines
1.8 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"knowledge-governance/internal/governance"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type libraryLegacySourceBinder interface {
|
|
BindLegacyLibrarySource(context.Context, string, string, governance.LibrarySourceIdentity, string, time.Time) error
|
|
}
|
|
|
|
func libraryLegacySourceBind(w http.ResponseWriter, r *http.Request, config Config) {
|
|
identity, ok := sessionFrom(r.Context())
|
|
if !ok || identity.Role != roleAdmin || identity.Username == "" {
|
|
writeJSON(w, http.StatusForbidden, map[string]string{"error": "administrator session required"})
|
|
return
|
|
}
|
|
var input struct {
|
|
Scope string `json:"scope"`
|
|
SnapshotID string `json:"snapshot_id"`
|
|
}
|
|
decoder := json.NewDecoder(http.MaxBytesReader(w, r.Body, 4096))
|
|
decoder.DisallowUnknownFields()
|
|
if decoder.Decode(&input) != nil || decoder.Decode(new(any)) != io.EOF || (input.Scope != "internal" && input.Scope != "external") || input.SnapshotID == "" {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "exact snapshot and scope required"})
|
|
return
|
|
}
|
|
source := configuredLibrarySource(config, input.Scope)
|
|
sourceID, err := source.ID()
|
|
if err != nil {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
store, ok := config.Store.(libraryLegacySourceBinder)
|
|
if !ok {
|
|
writeJSON(w, http.StatusServiceUnavailable, map[string]string{"error": "source association store unavailable"})
|
|
return
|
|
}
|
|
if err = store.BindLegacyLibrarySource(r.Context(), input.SnapshotID, config.LibraryArchiveRoot, source, identity.Username, time.Now().UTC()); err != nil {
|
|
writeJSON(w, http.StatusConflict, map[string]string{"error": err.Error()})
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, map[string]any{"snapshot_id": input.SnapshotID, "source_id": sourceID, "source_identity": source, "associated": true, "published": false})
|
|
}
|