package externaladmin import ( "bytes" "encoding/json" "errors" "fmt" "strconv" "strings" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/modules/shared" "hyapp-admin-server/internal/response" "github.com/gin-gonic/gin" ) // optionalPermissionSelection preserves the JSON distinction required by account // creation: omitted keeps the legacy full snapshot, while an explicit [] creates a // valid account with no business permissions. JSON null is rejected as ambiguous. type optionalPermissionSelection struct { Value []string Set bool } func (selection *optionalPermissionSelection) UnmarshalJSON(body []byte) error { selection.Set = true body = bytes.TrimSpace(body) if bytes.Equal(body, []byte("null")) { return errors.New("permissions must be an array") } var permissions []string if err := json.Unmarshal(body, &permissions); err != nil { return err } selection.Value = permissions return nil } type updatePermissionsRequest struct { Permissions optionalPermissionSelection `json:"permissions"` ExpectedRevision uint64 `json:"expectedRevision"` } func (h *Handler) ListPermissionCatalog(c *gin.Context) { items := PermissionCatalog() response.OK(c, gin.H{"items": items, "total": len(items)}) } func (h *Handler) GetAccountPermissions(c *gin.Context) { id, ok := parseUint64Param(c, "id") if !ok { return } permissions, err := h.service.GetAccountPermissions(c.Request.Context(), appctx.FromContext(c.Request.Context()), id) if errors.Is(err, ErrAccountNotFound) { response.NotFound(c, "外管用户不存在") return } if errors.Is(err, ErrInvalidInput) { response.BadRequest(c, "外管用户参数不正确") return } if err != nil { response.ServerError(c, "获取外管用户权限失败") return } response.OK(c, permissions) } func (h *Handler) UpdateAccountPermissions(c *gin.Context) { id, ok := parseUint64Param(c, "id") if !ok { return } var request updatePermissionsRequest if err := c.ShouldBindJSON(&request); err != nil || !request.Permissions.Set || request.ExpectedRevision == 0 { response.BadRequest(c, "权限参数不正确") return } result, err := h.service.UpdateAccountPermissions(c.Request.Context(), appctx.FromContext(c.Request.Context()), id, UpdatePermissionsInput{ Permissions: request.Permissions.Value, ExpectedRevision: request.ExpectedRevision, }) if errors.Is(err, ErrInvalidPermissions) { response.BadRequest(c, permissionValidationMessage(err)) return } if errors.Is(err, ErrInvalidInput) { response.BadRequest(c, "外管用户参数不正确") return } if errors.Is(err, ErrAccountNotFound) { response.NotFound(c, "外管用户不存在") return } if errors.Is(err, ErrPermissionConflict) { response.Conflict(c, "外管用户权限已被其他管理员修改,请刷新后重试") return } if err != nil { response.ServerError(c, "更新外管用户权限失败") return } shared.OperationLogWithResourceID( c, h.audit, "update-external-admin-user-permissions", "external_admin_accounts", strconv.FormatUint(id, 10), "success", fmt.Sprintf( "app_code=%s previous_permissions=%s permissions=%s revision=%d changed=%t sessions_revoked=%t", result.Account.AppCode, strings.Join(result.PreviousPermissions, ","), strings.Join(result.Account.Permissions, ","), result.Account.PermissionRevision, result.Changed, result.SessionsRevoked, ), ) response.OK(c, result.Account) }