Commit aa6d2cf7 authored by 陈曦's avatar 陈曦
Browse files

关闭capture_requests标识位nfs和db持续写入的问题排查

parent d8563adc
Pipeline #82297 passed with stage
in 3 minutes and 1 second
......@@ -565,6 +565,17 @@ func (s *stubAdminService) AdminUpdateAPIKeyGroupID(ctx context.Context, keyID i
return nil, service.ErrAPIKeyNotFound
}
func (s *stubAdminService) AdminSetCaptureRequests(ctx context.Context, keyID int64, enabled bool) (*service.APIKey, error) {
for i := range s.apiKeys {
if s.apiKeys[i].ID == keyID {
s.apiKeys[i].CaptureRequests = enabled
k := s.apiKeys[i]
return &k, nil
}
}
return nil, service.ErrAPIKeyNotFound
}
func (s *stubAdminService) ResetAccountQuota(ctx context.Context, id int64) error {
return nil
}
......
......@@ -10,6 +10,11 @@ import (
"github.com/gin-gonic/gin"
)
// AdminSetCaptureRequestsRequest 请求体:设置/清除 capture_requests
type AdminSetCaptureRequestsRequest struct {
Enabled bool `json:"enabled"`
}
// AdminAPIKeyHandler handles admin API key management
type AdminAPIKeyHandler struct {
adminService service.AdminService
......@@ -27,6 +32,33 @@ type AdminUpdateAPIKeyGroupRequest struct {
GroupID *int64 `json:"group_id"` // nil=不修改, 0=解绑, >0=绑定到目标分组
}
// SetCaptureRequests 开启或关闭指定 API Key 的请求体捕获,并立即失效认证缓存。
// PUT /api/v1/admin/api-keys/:id/capture-requests
func (h *AdminAPIKeyHandler) SetCaptureRequests(c *gin.Context) {
keyID, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
response.BadRequest(c, "Invalid API key ID")
return
}
var req AdminSetCaptureRequestsRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Invalid request: "+err.Error())
return
}
apiKey, err := h.adminService.AdminSetCaptureRequests(c.Request.Context(), keyID, req.Enabled)
if err != nil {
response.ErrorFrom(c, err)
return
}
response.Success(c, gin.H{
"id": apiKey.ID,
"capture_requests": apiKey.CaptureRequests,
})
}
// UpdateGroup handles updating an API key's group binding
// PUT /api/v1/admin/api-keys/:id
func (h *AdminAPIKeyHandler) UpdateGroup(c *gin.Context) {
......
......@@ -256,6 +256,8 @@ func (r *apiKeyRepository) Update(ctx context.Context, key *service.APIKey) erro
builder.ClearIPBlacklist()
}
builder.SetCaptureRequests(key.CaptureRequests)
affected, err := builder.Save(ctx)
if err != nil {
return err
......
......@@ -101,6 +101,7 @@ func registerAdminAPIKeyRoutes(admin *gin.RouterGroup, h *handler.Handlers) {
apiKeys := admin.Group("/api-keys")
{
apiKeys.PUT("/:id", h.Admin.APIKey.UpdateGroup)
apiKeys.PUT("/:id/capture-requests", h.Admin.APIKey.SetCaptureRequests)
}
}
......
......@@ -58,6 +58,7 @@ type AdminService interface {
// API Key management (admin)
AdminUpdateAPIKeyGroupID(ctx context.Context, keyID int64, groupID *int64) (*AdminUpdateAPIKeyGroupIDResult, error)
AdminSetCaptureRequests(ctx context.Context, keyID int64, enabled bool) (*APIKey, error)
// ReplaceUserGroup 替换用户的专属分组:授予新分组权限、迁移 Key、移除旧分组权限
ReplaceUserGroup(ctx context.Context, userID, oldGroupID, newGroupID int64) (*ReplaceUserGroupResult, error)
......@@ -1961,6 +1962,22 @@ func (s *adminServiceImpl) AdminUpdateAPIKeyGroupID(ctx context.Context, keyID i
return result, nil
}
// AdminSetCaptureRequests 设置或清除指定 API Key 的请求捕获开关,并立即失效认证缓存。
func (s *adminServiceImpl) AdminSetCaptureRequests(ctx context.Context, keyID int64, enabled bool) (*APIKey, error) {
apiKey, err := s.apiKeyRepo.GetByID(ctx, keyID)
if err != nil {
return nil, err
}
apiKey.CaptureRequests = enabled
if err := s.apiKeyRepo.Update(ctx, apiKey); err != nil {
return nil, err
}
if s.authCacheInvalidator != nil {
s.authCacheInvalidator.InvalidateAuthCacheByKey(ctx, apiKey.Key)
}
return apiKey, nil
}
// ReplaceUserGroup 替换用户的专属分组
func (s *adminServiceImpl) ReplaceUserGroup(ctx context.Context, userID, oldGroupID, newGroupID int64) (*ReplaceUserGroupResult, error) {
if oldGroupID == newGroupID {
......
......@@ -184,6 +184,9 @@ type UpdateAPIKeyRequest struct {
RateLimit1d *float64 `json:"rate_limit_1d"`
RateLimit7d *float64 `json:"rate_limit_7d"`
ResetRateLimitUsage *bool `json:"reset_rate_limit_usage"` // Reset all usage counters to 0
// Request capture
CaptureRequests *bool `json:"capture_requests"` // nil = no change
}
// APIKeyService API Key服务
......@@ -601,6 +604,10 @@ func (s *APIKeyService) Update(ctx context.Context, id int64, userID int64, req
apiKey.IPWhitelist = req.IPWhitelist
apiKey.IPBlacklist = req.IPBlacklist
if req.CaptureRequests != nil {
apiKey.CaptureRequests = *req.CaptureRequests
}
// Update rate limit configuration
if req.RateLimit5h != nil {
apiKey.RateLimit5h = *req.RateLimit5h
......
#!/bin/bash
# =============================================================================
# capture_requests.sh — 控制指定 API Key 的请求体捕获开关
# =============================================================================
# 用法:
# ./capture_requests.sh <key_id> <on|off>
#
# 环境变量(优先级高于脚本内默认值):
# BASE_URL API 服务地址,例如 https://s2a-st.appbym.com
# ADMIN_KEY Admin API Key
#
# 示例:
# BASE_URL=https://example.com ADMIN_KEY=sk-xxx ./capture_requests.sh 123 on
# ./capture_requests.sh 456 off
# =============================================================================
set -euo pipefail
# ---------- 默认配置(可通过环境变量覆盖)----------
DEFAULT_BASE_URL="https://s2a-st.appbym.com"
DEFAULT_ADMIN_KEY="admin-bccab2aa363738a3f8140f014a8bab2b4e23f4bb8be15c72d1d79299981d38a0"
BASE_URL="${BASE_URL:-$DEFAULT_BASE_URL}"
ADMIN_KEY="${ADMIN_KEY:-$DEFAULT_ADMIN_KEY}"
# ---------- 颜色输出 ----------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
usage() {
echo "用法: $0 <key_id> <on|off>"
echo ""
echo " key_id API Key 的数字 ID"
echo " on 开启请求体捕获"
echo " off 关闭请求体捕获(同时立即清除认证缓存)"
echo ""
echo "环境变量:"
echo " BASE_URL API 服务地址(默认: $DEFAULT_BASE_URL)"
echo " ADMIN_KEY Admin API Key(必填)"
exit 1
}
# ---------- 参数检查 ----------
if [[ $# -ne 2 ]]; then
echo -e "${RED}错误: 需要 2 个参数${NC}"
usage
fi
KEY_ID="$1"
ACTION="$2"
# 验证 key_id 是正整数
if ! [[ "$KEY_ID" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${RED}错误: key_id 必须是正整数,收到: '$KEY_ID'${NC}"
usage
fi
# 解析 on/off → true/false
case "$ACTION" in
on|true|1|yes)
ENABLED="true"
ACTION_LABEL="开启"
;;
off|false|0|no)
ENABLED="false"
ACTION_LABEL="关闭"
;;
*)
echo -e "${RED}错误: 第二个参数必须是 on 或 off,收到: '$ACTION'${NC}"
usage
;;
esac
# 检查 ADMIN_KEY
if [[ -z "$ADMIN_KEY" ]]; then
echo -e "${RED}错误: 未设置 ADMIN_KEY${NC}"
echo "请通过环境变量传入: ADMIN_KEY=sk-xxx $0 $KEY_ID $ACTION"
exit 1
fi
# ---------- 发送请求 ----------
ENDPOINT="${BASE_URL}/api/v1/admin/api-keys/${KEY_ID}/capture-requests"
echo -e "${YELLOW}${ACTION_LABEL} API Key #${KEY_ID} 的请求体捕获...${NC}"
echo " 接口: PUT $ENDPOINT"
echo " 参数: enabled=$ENABLED"
echo ""
HTTP_RESPONSE=$(curl -s -w "\n%{http_code}" \
-X PUT "$ENDPOINT" \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d "{\"enabled\": $ENABLED}")
# 分离响应体和状态码
HTTP_BODY=$(echo "$HTTP_RESPONSE" | sed '$d')
HTTP_CODE=$(echo "$HTTP_RESPONSE" | tail -n 1)
# ---------- 结果输出 ----------
echo "HTTP 状态码: $HTTP_CODE"
echo "响应内容:"
# 尝试格式化 JSON(有 jq 就用,没有就原样输出)
if command -v jq &>/dev/null; then
echo "$HTTP_BODY" | jq .
else
echo "$HTTP_BODY"
fi
echo ""
if [[ "$HTTP_CODE" == "200" ]]; then
echo -e "${GREEN}✓ 操作成功:API Key #${KEY_ID} 请求体捕获已${ACTION_LABEL}${NC}"
if [[ "$ENABLED" == "false" ]]; then
echo -e "${GREEN} 认证缓存已同步清除,下一条请求立即生效${NC}"
fi
else
echo -e "${RED}✗ 操作失败(HTTP $HTTP_CODE${NC}"
exit 1
fi
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment