feat: harden loose-offline sync for user JWT, schema, and console ops
Enable Binding-scoped agent push/pull, empty-table schema ensure, SyncPage inspect/drop-table, default module import, and agent-bound publish docs from the 宇恒联调意见. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -218,6 +218,33 @@ func RequirePermission(perm string) func(http.HandlerFunc) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// RequireSyncPushAccess 放行「数据同步」权限,或已登录人类成员(用户自助 sync)。
|
||||
// 智能体无「数据同步」仍 403;无 sync 权的人类由 handler 再按 Binding 收窄范围。
|
||||
func RequireSyncPushAccess() func(http.HandlerFunc) http.HandlerFunc {
|
||||
return func(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if HasPermissionCtx(r.Context(), Perm数据同步) {
|
||||
next(w, r)
|
||||
return
|
||||
}
|
||||
if IsAgent(Role(r.Context())) {
|
||||
WriteError(w, http.StatusForbidden, "permission denied: 数据同步 (role=智能体)")
|
||||
return
|
||||
}
|
||||
if UserID(r.Context()) <= 0 {
|
||||
WriteError(w, http.StatusForbidden, "permission denied: need user login or 数据同步")
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SyncTenantWide 是否租户级同步权(管理员/智能体带「数据同步」);否则须按 Binding 自助范围。
|
||||
func SyncTenantWide(ctx context.Context) bool {
|
||||
return HasPermissionCtx(ctx, Perm数据同步)
|
||||
}
|
||||
|
||||
// RequireTenant 要求已加入租户;pending / 无 tenant 不可访问业务数据。
|
||||
// 超级管理员可在「进入某公司」后携带 tenant_id 访问公司内接口(可看可改,前端会多重确认)。
|
||||
func RequireTenant() func(http.HandlerFunc) http.HandlerFunc {
|
||||
@@ -394,3 +421,12 @@ func WriteError(w http.ResponseWriter, code int, msg string) {
|
||||
"message": msg,
|
||||
})
|
||||
}
|
||||
|
||||
// WriteRetryableError 供 agent 识别可稍后重试(不换 UUID)。
|
||||
func WriteRetryableError(w http.ResponseWriter, code int, msg string) {
|
||||
httpx.WriteJson(w, code, map[string]any{
|
||||
"code": code,
|
||||
"message": msg,
|
||||
"retryable": true,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user