diff --git a/internal/handler/chunk.go b/internal/handler/chunk.go index 463bdbb10..f12c56537 100644 --- a/internal/handler/chunk.go +++ b/internal/handler/chunk.go @@ -33,6 +33,7 @@ func (h *ChunkHandler) GetChunkByIDOnly(c *gin.Context) { c.Error(errors.NewBadRequestError("Chunk ID cannot be empty")) return } + safeChunkID := secutils.SanitizeForLog(chunkID) // Get tenant ID from context tenantID, exists := c.Get(types.TenantIDContextKey.String()) @@ -42,13 +43,13 @@ func (h *ChunkHandler) GetChunkByIDOnly(c *gin.Context) { return } - logger.Infof(ctx, "Retrieving chunk by ID, chunk ID: %s, tenant ID: %d", secutils.SanitizeForLog(chunkID), tenantID) + logger.Infof(ctx, "Retrieving chunk by ID, chunk ID: %s, tenant ID: %d", safeChunkID, tenantID) // Get chunk by ID chunk, err := h.service.GetChunkByID(ctx, chunkID) if err != nil { if err == service.ErrChunkNotFound { - logger.Warnf(ctx, "Chunk not found, chunk ID: %s", chunkID) + logger.Warnf(ctx, "Chunk not found, chunk ID: %s", safeChunkID) c.Error(errors.NewNotFoundError("Chunk not found")) return } @@ -62,7 +63,7 @@ func (h *ChunkHandler) GetChunkByIDOnly(c *gin.Context) { logger.Warnf( ctx, "Tenant has no permission to access chunk, chunk ID: %s, req tenant: %d, chunk tenant: %d", - chunkID, tenantID.(uint), chunk.TenantID, + safeChunkID, tenantID.(uint64), chunk.TenantID, ) c.Error(errors.NewForbiddenError("No permission to access this chunk")) return @@ -147,6 +148,7 @@ func (h *ChunkHandler) validateAndGetChunk(c *gin.Context) (*types.Chunk, string logger.Error(ctx, "Knowledge ID is empty") return nil, "", errors.NewBadRequestError("Knowledge ID cannot be empty") } + safeKnowledgeID := secutils.SanitizeForLog(knowledgeID) // Validate chunk ID id := c.Param("id") @@ -154,6 +156,7 @@ func (h *ChunkHandler) validateAndGetChunk(c *gin.Context) (*types.Chunk, string logger.Error(ctx, "Chunk ID is empty") return nil, knowledgeID, errors.NewBadRequestError("Chunk ID cannot be empty") } + safeChunkID := secutils.SanitizeForLog(id) // Get tenant ID from context tenantID, exists := c.Get(types.TenantIDContextKey.String()) @@ -162,13 +165,13 @@ func (h *ChunkHandler) validateAndGetChunk(c *gin.Context) (*types.Chunk, string return nil, knowledgeID, errors.NewUnauthorizedError("Unauthorized") } - logger.Infof(ctx, "Retrieving knowledge chunk information, knowledge ID: %s, chunk ID: %s", knowledgeID, id) + logger.Infof(ctx, "Retrieving knowledge chunk information, knowledge ID: %s, chunk ID: %s", safeKnowledgeID, safeChunkID) // Get existing chunk chunk, err := h.service.GetChunkByID(ctx, id) if err != nil { if err == service.ErrChunkNotFound { - logger.Warnf(ctx, "Chunk not found, knowledge ID: %s, chunk ID: %s", knowledgeID, id) + logger.Warnf(ctx, "Chunk not found, knowledge ID: %s, chunk ID: %s", safeKnowledgeID, safeChunkID) return nil, knowledgeID, errors.NewNotFoundError("Chunk not found") } logger.ErrorWithFields(ctx, err, nil) @@ -180,7 +183,7 @@ func (h *ChunkHandler) validateAndGetChunk(c *gin.Context) (*types.Chunk, string logger.Warnf( ctx, "Tenant has no permission to access chunk, knowledge ID: %s, chunk ID: %s, req tenant: %d, chunk tenant: %d", - knowledgeID, id, tenantID, chunk.TenantID, + safeKnowledgeID, safeChunkID, tenantID, chunk.TenantID, ) return nil, knowledgeID, errors.NewForbiddenError("No permission to access this chunk") } @@ -219,7 +222,8 @@ func (h *ChunkHandler) UpdateChunk(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge chunk updated successfully, knowledge ID: %s, chunk ID: %s", knowledgeID, chunk.ID) + logger.Infof(ctx, "Knowledge chunk updated successfully, knowledge ID: %s, chunk ID: %s", + secutils.SanitizeForLog(knowledgeID), secutils.SanitizeForLog(chunk.ID)) c.JSON(http.StatusOK, gin.H{ "success": true, "data": chunk, diff --git a/internal/handler/evaluation.go b/internal/handler/evaluation.go index 324fda765..661417bdb 100644 --- a/internal/handler/evaluation.go +++ b/internal/handler/evaluation.go @@ -7,6 +7,7 @@ import ( "github.com/Tencent/WeKnora/internal/logger" "github.com/Tencent/WeKnora/internal/types" "github.com/Tencent/WeKnora/internal/types/interfaces" + secutils "github.com/Tencent/WeKnora/internal/utils" "github.com/gin-gonic/gin" ) @@ -34,7 +35,7 @@ func (e *EvaluationHandler) Evaluation(c *gin.Context) { logger.Info(ctx, "Start processing evaluation request") - var request *EvaluationRequest + var request EvaluationRequest if err := c.ShouldBind(&request); err != nil { logger.Error(ctx, "Failed to parse request parameters", err) c.Error(errors.NewBadRequestError("Invalid request parameters").WithDetails(err.Error())) @@ -49,13 +50,12 @@ func (e *EvaluationHandler) Evaluation(c *gin.Context) { } logger.Infof(ctx, "Executing evaluation, tenant: %v, dataset: %s, knowledge_base: %s, chat: %s, rerank: %s", - tenantID, request.DatasetID, request.KnowledgeBaseID, request.ChatModelID, request.RerankModelID) - - if request == nil { - logger.Error(ctx, "Request is nil") - c.Error(errors.NewBadRequestError("Invalid request parameters")) - return - } + tenantID, + secutils.SanitizeForLog(request.DatasetID), + secutils.SanitizeForLog(request.KnowledgeBaseID), + secutils.SanitizeForLog(request.ChatModelID), + secutils.SanitizeForLog(request.RerankModelID), + ) task, err := e.evaluationService.Evaluation(ctx, request.DatasetID, diff --git a/internal/handler/initialization.go b/internal/handler/initialization.go index 8171eaf28..3dccda5b6 100644 --- a/internal/handler/initialization.go +++ b/internal/handler/initialization.go @@ -1589,18 +1589,28 @@ func (h *InitializationHandler) TestMultimodalFunction(c *gin.Context) { c.Error(errors.NewBadRequestError("图片文件大小不能超过10MB")) return } - logger.Infof(ctx, "Processing image: %s, size: %d bytes", header.Filename, header.Size) + logger.Infof(ctx, "Processing image: %s, size: %d bytes", secutils.SanitizeForLog(header.Filename), header.Size) // 解析文档分割配置 - chunkSizeInt64, err := strconv.ParseInt(req.ChunkSize, 10, 0) - chunkSize := int(chunkSizeInt64) - if err != nil || chunkSize < 100 || chunkSize > 10000 { + chunkSizeInt32, err := strconv.ParseInt(req.ChunkSize, 10, 32) + if err != nil { + logger.Error(ctx, "Failed to parse chunk size", err) + c.Error(errors.NewBadRequestError("Failed to parse chunk size")) + return + } + chunkSize := int32(chunkSizeInt32) + if chunkSize < 100 || chunkSize > 10000 { chunkSize = 1000 } - chunkOverlapInt64, err := strconv.ParseInt(req.ChunkOverlap, 10, 0) - chunkOverlap := int(chunkOverlapInt64) - if err != nil || chunkOverlap < 0 || chunkOverlap >= chunkSize { + chunkOverlapInt32, err := strconv.ParseInt(req.ChunkOverlap, 10, 32) + if err != nil { + logger.Error(ctx, "Failed to parse chunk overlap", err) + c.Error(errors.NewBadRequestError("Failed to parse chunk overlap")) + return + } + chunkOverlap := int32(chunkOverlapInt32) + if chunkOverlap < 0 || chunkOverlap >= chunkSize { chunkOverlap = 200 } @@ -1660,7 +1670,7 @@ func (h *InitializationHandler) TestMultimodalFunction(c *gin.Context) { func (h *InitializationHandler) testMultimodalWithDocReader( ctx context.Context, imageContent []byte, filename string, - chunkSize, chunkOverlap int, separators []string, + chunkSize, chunkOverlap int32, separators []string, req *testMultimodalForm, ) (map[string]string, error) { // 获取文件扩展名 @@ -1680,8 +1690,8 @@ func (h *InitializationHandler) testMultimodalWithDocReader( FileName: filename, FileType: fileExt, ReadConfig: &proto.ReadConfig{ - ChunkSize: int32(chunkSize), - ChunkOverlap: int32(chunkOverlap), + ChunkSize: chunkSize, + ChunkOverlap: chunkOverlap, Separators: separators, EnableMultimodal: true, // 启用多模态处理 VlmConfig: &proto.VLMConfig{ diff --git a/internal/handler/knowledge.go b/internal/handler/knowledge.go index 8241989cb..a9a3659ff 100644 --- a/internal/handler/knowledge.go +++ b/internal/handler/knowledge.go @@ -70,7 +70,7 @@ func (h *KnowledgeHandler) handleDuplicateKnowledgeError(c *gin.Context, ) bool { if dupErr, ok := err.(*types.DuplicateKnowledgeError); ok { ctx := c.Request.Context() - logger.Warnf(ctx, "Detected duplicate %s: %s", duplicateType, dupErr.Error()) + logger.Warnf(ctx, "Detected duplicate %s: %s", duplicateType, secutils.SanitizeForLog(dupErr.Error())) c.JSON(http.StatusConflict, gin.H{ "success": false, "message": dupErr.Error(), @@ -107,11 +107,11 @@ func (h *KnowledgeHandler) CreateKnowledgeFromFile(c *gin.Context) { displayFileName := file.Filename if customFileName != "" { displayFileName = customFileName - logger.Infof(ctx, "Using custom filename: %s (original: %s)", customFileName, file.Filename) + logger.Infof(ctx, "Using custom filename: %s (original: %s)", secutils.SanitizeForLog(customFileName), secutils.SanitizeForLog(file.Filename)) } - logger.Infof(ctx, "File upload successful, filename: %s, size: %.2f KB", displayFileName, float64(file.Size)/1024) - logger.Infof(ctx, "Creating knowledge, knowledge base ID: %s, filename: %s", kbID, displayFileName) + logger.Infof(ctx, "File upload successful, filename: %s, size: %.2f KB", secutils.SanitizeForLog(displayFileName), float64(file.Size)/1024) + logger.Infof(ctx, "Creating knowledge, knowledge base ID: %s, filename: %s", secutils.SanitizeForLog(kbID), secutils.SanitizeForLog(displayFileName)) // Parse metadata if provided var metadata map[string]string @@ -122,7 +122,7 @@ func (h *KnowledgeHandler) CreateKnowledgeFromFile(c *gin.Context) { c.Error(errors.NewBadRequestError("Invalid metadata format").WithDetails(err.Error())) return } - logger.Infof(ctx, "Received file metadata: %v", metadata) + logger.Infof(ctx, "Received file metadata: %s", secutils.SanitizeForLog(fmt.Sprintf("%v", metadata))) } enableMultimodelForm := c.PostForm("enable_multimodel") @@ -153,7 +153,7 @@ func (h *KnowledgeHandler) CreateKnowledgeFromFile(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge created successfully, ID: %s, title: %s", knowledge.ID, knowledge.Title) + logger.Infof(ctx, "Knowledge created successfully, ID: %s, title: %s", secutils.SanitizeForLog(knowledge.ID), secutils.SanitizeForLog(knowledge.Title)) c.JSON(http.StatusOK, gin.H{ "success": true, "data": knowledge, @@ -198,7 +198,7 @@ func (h *KnowledgeHandler) CreateKnowledgeFromURL(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge created successfully from URL, ID: %s, title: %s", knowledge.ID, knowledge.Title) + logger.Infof(ctx, "Knowledge created successfully from URL, ID: %s, title: %s", secutils.SanitizeForLog(knowledge.ID), secutils.SanitizeForLog(knowledge.Title)) c.JSON(http.StatusCreated, gin.H{ "success": true, "data": knowledge, @@ -236,7 +236,7 @@ func (h *KnowledgeHandler) CreateManualKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Manual knowledge created successfully, knowledge ID: %s", knowledge.ID) + logger.Infof(ctx, "Manual knowledge created successfully, knowledge ID: %s", secutils.SanitizeForLog(knowledge.ID)) c.JSON(http.StatusOK, gin.H{ "success": true, "data": knowledge, @@ -257,7 +257,7 @@ func (h *KnowledgeHandler) GetKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Retrieving knowledge, ID: %s", id) + logger.Infof(ctx, "Retrieving knowledge, ID: %s", secutils.SanitizeForLog(id)) knowledge, err := h.kgService.GetKnowledgeByID(ctx, id) if err != nil { logger.ErrorWithFields(ctx, err, nil) @@ -265,7 +265,7 @@ func (h *KnowledgeHandler) GetKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge retrieved successfully, ID: %s, title: %s", knowledge.ID, knowledge.Title) + logger.Infof(ctx, "Knowledge retrieved successfully, ID: %s, title: %s", secutils.SanitizeForLog(knowledge.ID), secutils.SanitizeForLog(knowledge.Title)) c.JSON(http.StatusOK, gin.H{ "success": true, "data": knowledge, @@ -297,7 +297,7 @@ func (h *KnowledgeHandler) ListKnowledge(c *gin.Context) { tagID := c.Query("tag_id") logger.Infof(ctx, "Retrieving knowledge list under knowledge base, knowledge base ID: %s, tag_id: %s, page: %d, page size: %d", - kbID, tagID, pagination.Page, pagination.PageSize) + secutils.SanitizeForLog(kbID), secutils.SanitizeForLog(tagID), pagination.Page, pagination.PageSize) // Retrieve paginated knowledge entries result, err := h.kgService.ListPagedKnowledgeByKnowledgeBaseID(ctx, kbID, &pagination, tagID) @@ -307,7 +307,7 @@ func (h *KnowledgeHandler) ListKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge list retrieved successfully, knowledge base ID: %s, total: %d", kbID, result.Total) + logger.Infof(ctx, "Knowledge list retrieved successfully, knowledge base ID: %s, total: %d", secutils.SanitizeForLog(kbID), result.Total) c.JSON(http.StatusOK, gin.H{ "success": true, "data": result.Data, @@ -331,7 +331,7 @@ func (h *KnowledgeHandler) DeleteKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Deleting knowledge, ID: %s", id) + logger.Infof(ctx, "Deleting knowledge, ID: %s", secutils.SanitizeForLog(id)) err := h.kgService.DeleteKnowledge(ctx, id) if err != nil { logger.ErrorWithFields(ctx, err, nil) @@ -339,7 +339,7 @@ func (h *KnowledgeHandler) DeleteKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge deleted successfully, ID: %s", id) + logger.Infof(ctx, "Knowledge deleted successfully, ID: %s", secutils.SanitizeForLog(id)) c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Deleted successfully", @@ -360,7 +360,7 @@ func (h *KnowledgeHandler) DownloadKnowledgeFile(c *gin.Context) { return } - logger.Infof(ctx, "Retrieving knowledge file, ID: %s", id) + logger.Infof(ctx, "Retrieving knowledge file, ID: %s", secutils.SanitizeForLog(id)) // Get file content and filename file, filename, err := h.kgService.GetKnowledgeFile(ctx, id) @@ -371,7 +371,7 @@ func (h *KnowledgeHandler) DownloadKnowledgeFile(c *gin.Context) { } defer file.Close() - logger.Infof(ctx, "Knowledge file retrieved successfully, ID: %s, filename: %s", id, filename) + logger.Infof(ctx, "Knowledge file retrieved successfully, ID: %s, filename: %s", secutils.SanitizeForLog(id), secutils.SanitizeForLog(filename)) // Set response headers for file download c.Header("Content-Description", "File Transfer") @@ -472,7 +472,7 @@ func (h *KnowledgeHandler) UpdateKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge updated successfully, knowledge ID: %s", knowledge.ID) + logger.Infof(ctx, "Knowledge updated successfully, knowledge ID: %s", secutils.SanitizeForLog(knowledge.ID)) c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Knowledge chunk updated successfully", @@ -511,7 +511,7 @@ func (h *KnowledgeHandler) UpdateManualKnowledge(c *gin.Context) { return } - logger.Infof(ctx, "Manual knowledge updated successfully, knowledge ID: %s", knowledge.ID) + logger.Infof(ctx, "Manual knowledge updated successfully, knowledge ID: %s", secutils.SanitizeForLog(knowledge.ID)) c.JSON(http.StatusOK, gin.H{ "success": true, "data": knowledge, @@ -571,7 +571,7 @@ func (h *KnowledgeHandler) UpdateImageInfo(c *gin.Context) { } // Update chunk properties - logger.Infof(ctx, "Updating knowledge chunk, knowledge ID: %s, chunk ID: %s", id, chunkID) + logger.Infof(ctx, "Updating knowledge chunk, knowledge ID: %s, chunk ID: %s", secutils.SanitizeForLog(id), secutils.SanitizeForLog(chunkID)) err := h.kgService.UpdateImageInfo(ctx, id, chunkID, request.ImageInfo) if err != nil { logger.ErrorWithFields(ctx, err, nil) @@ -579,7 +579,7 @@ func (h *KnowledgeHandler) UpdateImageInfo(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge chunk updated successfully, knowledge ID: %s, chunk ID: %s", id, chunkID) + logger.Infof(ctx, "Knowledge chunk updated successfully, knowledge ID: %s, chunk ID: %s", secutils.SanitizeForLog(id), secutils.SanitizeForLog(chunkID)) c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Knowledge chunk image updated successfully", diff --git a/internal/handler/knowledgebase.go b/internal/handler/knowledgebase.go index 885879f2e..4b573aca1 100644 --- a/internal/handler/knowledgebase.go +++ b/internal/handler/knowledgebase.go @@ -126,7 +126,7 @@ func (h *KnowledgeBaseHandler) validateAndGetKnowledgeBase(c *gin.Context) (*typ ctx, "Tenant has no permission to access this knowledge base, knowledge base ID: %s, "+ "request tenant ID: %d, knowledge base tenant ID: %d", - id, tenantID.(uint), kb.TenantID, + id, tenantID.(uint64), kb.TenantID, ) return nil, id, errors.NewForbiddenError("No permission to operate") } diff --git a/internal/handler/mcp_service.go b/internal/handler/mcp_service.go index ebd5f38df..d3bf089b1 100644 --- a/internal/handler/mcp_service.go +++ b/internal/handler/mcp_service.go @@ -44,7 +44,7 @@ func (h *MCPServiceHandler) CreateMCPService(c *gin.Context) { service.TenantID = tenantID if err := h.mcpServiceService.CreateMCPService(ctx, &service); err != nil { - logger.ErrorWithFields(ctx, err, map[string]interface{}{"service_name": service.Name}) + logger.ErrorWithFields(ctx, err, map[string]interface{}{"service_name": secutils.SanitizeForLog(service.Name)}) c.Error(errors.NewInternalServerError("Failed to create MCP service: " + err.Error())) return } diff --git a/internal/handler/model.go b/internal/handler/model.go index 1a7840848..8d2aaba58 100644 --- a/internal/handler/model.go +++ b/internal/handler/model.go @@ -110,7 +110,7 @@ func (h *ModelHandler) CreateModel(c *gin.Context) { return } - logger.Infof(ctx, "Model created successfully, ID: %s, Name: %s", model.ID, model.Name) + logger.Infof(ctx, "Model created successfully, ID: %s, Name: %s", secutils.SanitizeForLog(model.ID), secutils.SanitizeForLog(model.Name)) // Hide sensitive information for builtin models (though newly created models are unlikely to be builtin) responseModel := hideSensitiveInfo(model) @@ -138,11 +138,11 @@ func (h *ModelHandler) GetModel(c *gin.Context) { return } - logger.Infof(ctx, "Retrieving model, ID: %s", id) + logger.Infof(ctx, "Retrieving model, ID: %s", secutils.SanitizeForLog(id)) model, err := h.service.GetModelByID(ctx, id) if err != nil { if err == service.ErrModelNotFound { - logger.Warnf(ctx, "Model not found, ID: %s", id) + logger.Warnf(ctx, "Model not found, ID: %s", secutils.SanitizeForLog(id)) c.Error(errors.NewNotFoundError("Model not found")) return } @@ -151,12 +151,12 @@ func (h *ModelHandler) GetModel(c *gin.Context) { return } - logger.Infof(ctx, "Retrieved model successfully, ID: %s, Name: %s", model.ID, model.Name) + logger.Infof(ctx, "Retrieved model successfully, ID: %s, Name: %s", secutils.SanitizeForLog(model.ID), secutils.SanitizeForLog(model.Name)) // Hide sensitive information for builtin models responseModel := hideSensitiveInfo(model) if model.IsBuiltin { - logger.Infof(ctx, "Builtin model detected, hiding sensitive information for model: %s", model.ID) + logger.Infof(ctx, "Builtin model detected, hiding sensitive information for model: %s", secutils.SanitizeForLog(model.ID)) } c.JSON(http.StatusOK, gin.H{ @@ -196,7 +196,7 @@ func (h *ModelHandler) ListModels(c *gin.Context) { for i, model := range models { responseModels[i] = hideSensitiveInfo(model) if model.IsBuiltin { - logger.Infof(ctx, "Builtin model detected in list, hiding sensitive information for model: %s", model.ID) + logger.Infof(ctx, "Builtin model detected in list, hiding sensitive information for model: %s", secutils.SanitizeForLog(model.ID)) } } @@ -240,11 +240,11 @@ func (h *ModelHandler) UpdateModel(c *gin.Context) { return } - logger.Infof(ctx, "Retrieving model information, ID: %s", id) + logger.Infof(ctx, "Retrieving model information, ID: %s", secutils.SanitizeForLog(id)) model, err := h.service.GetModelByID(ctx, id) if err != nil { if err == service.ErrModelNotFound { - logger.Warnf(ctx, "Model not found, ID: %s", id) + logger.Warnf(ctx, "Model not found, ID: %s", secutils.SanitizeForLog(id)) c.Error(errors.NewNotFoundError("Model not found")) return } @@ -264,14 +264,14 @@ func (h *ModelHandler) UpdateModel(c *gin.Context) { model.Source = req.Source model.Type = req.Type - logger.Infof(ctx, "Updating model, ID: %s, Name: %s", id, model.Name) + logger.Infof(ctx, "Updating model, ID: %s, Name: %s", secutils.SanitizeForLog(id), secutils.SanitizeForLog(model.Name)) if err := h.service.UpdateModel(ctx, model); err != nil { logger.ErrorWithFields(ctx, err, nil) c.Error(errors.NewInternalServerError(err.Error())) return } - logger.Infof(ctx, "Model updated successfully, ID: %s", id) + logger.Infof(ctx, "Model updated successfully, ID: %s", secutils.SanitizeForLog(id)) // Hide sensitive information for builtin models (though builtin models cannot be updated) responseModel := hideSensitiveInfo(model) @@ -299,10 +299,10 @@ func (h *ModelHandler) DeleteModel(c *gin.Context) { return } - logger.Infof(ctx, "Deleting model, ID: %s", id) + logger.Infof(ctx, "Deleting model, ID: %s", secutils.SanitizeForLog(id)) if err := h.service.DeleteModel(ctx, id); err != nil { if err == service.ErrModelNotFound { - logger.Warnf(ctx, "Model not found, ID: %s", id) + logger.Warnf(ctx, "Model not found, ID: %s", secutils.SanitizeForLog(id)) c.Error(errors.NewNotFoundError("Model not found")) return } @@ -311,7 +311,7 @@ func (h *ModelHandler) DeleteModel(c *gin.Context) { return } - logger.Infof(ctx, "Model deleted successfully, ID: %s", id) + logger.Infof(ctx, "Model deleted successfully, ID: %s", secutils.SanitizeForLog(id)) c.JSON(http.StatusOK, gin.H{ "success": true, "message": "Model deleted", diff --git a/internal/handler/session/qa.go b/internal/handler/session/qa.go index 5c087c619..ca2392057 100644 --- a/internal/handler/session/qa.go +++ b/internal/handler/session/qa.go @@ -46,8 +46,8 @@ func (h *Handler) SearchKnowledge(c *gin.Context) { logger.Infof( ctx, "Knowledge search request, knowledge base ID: %s, query: %s", - request.KnowledgeBaseID, - request.Query, + secutils.SanitizeForLog(request.KnowledgeBaseID), + secutils.SanitizeForLog(request.Query), ) // Directly call knowledge retrieval service without LLM summarization @@ -80,6 +80,7 @@ func (h *Handler) KnowledgeQA(c *gin.Context) { c.Error(errors.NewBadRequestError(errors.ErrInvalidSessionID.Error())) return } + safeSessionID := secutils.SanitizeForLog(sessionID) // Parse request body var request CreateKnowledgeQARequest @@ -104,12 +105,12 @@ func (h *Handler) KnowledgeQA(c *gin.Context) { return } - logger.Infof(ctx, "Knowledge QA request, session ID: %s, query: %s", secutils.SanitizeForLog(sessionID), secutils.SanitizeForLog(request.Query)) + logger.Infof(ctx, "Knowledge QA request, session ID: %s, query: %s", safeSessionID, secutils.SanitizeForLog(request.Query)) // Get session to prepare knowledge base IDs session, err := h.sessionService.GetSession(ctx, sessionID) if err != nil { - logger.Errorf(ctx, "Failed to get session, session ID: %s, error: %v", secutils.SanitizeForLog(sessionID), err) + logger.Errorf(ctx, "Failed to get session, session ID: %s, error: %v", safeSessionID, err) c.Error(errors.NewInternalServerError(err.Error())) return } @@ -137,6 +138,7 @@ func (h *Handler) AgentQA(c *gin.Context) { c.Error(errors.NewBadRequestError(errors.ErrInvalidSessionID.Error())) return } + safeSessionID := secutils.SanitizeForLog(sessionID) // Parse request body var request CreateKnowledgeQARequest @@ -145,7 +147,11 @@ func (h *Handler) AgentQA(c *gin.Context) { c.Error(errors.NewBadRequestError(err.Error())) return } - logger.Infof(ctx, "Agent QA request, request: %+v", request) + if requestJSON, err := json.Marshal(request); err == nil { + logger.Infof(ctx, "Agent QA request, request: %s", secutils.SanitizeForLog(string(requestJSON))) + } else { + logger.Warnf(ctx, "Agent QA request received but failed to marshal for logging: %s", secutils.SanitizeForLog(err.Error())) + } // Validate query content if request.Query == "" { @@ -169,7 +175,7 @@ func (h *Handler) AgentQA(c *gin.Context) { c.Error(errors.NewInternalServerError(err.Error())) return } - logger.Infof(ctx, "Before AgentQA, Session: %s", string(sessionJSON)) + logger.Infof(ctx, "Before AgentQA, Session: %s", secutils.SanitizeForLog(string(sessionJSON))) // Create assistant message assistantMessage := &types.Message{ @@ -210,7 +216,10 @@ func (h *Handler) AgentQA(c *gin.Context) { } } if knowledgeBasesChanged { - logger.Infof(ctx, "Knowledge bases changed from %v to %v", session.AgentConfig.KnowledgeBases, request.KnowledgeBaseIDs) + logger.Infof(ctx, "Knowledge bases changed from %s to %s", + secutils.SanitizeForLog(fmt.Sprintf("%v", session.AgentConfig.KnowledgeBases)), + secutils.SanitizeForLog(fmt.Sprintf("%v", request.KnowledgeBaseIDs)), + ) } } @@ -239,14 +248,14 @@ func (h *Handler) AgentQA(c *gin.Context) { // If configuration changed, clear context and update session if configChanged { - logger.Warnf(ctx, "Configuration changed, clearing context for session: %s", sessionID) + logger.Warnf(ctx, "Configuration changed, clearing context for session: %s", safeSessionID) // Clear the LLM context to prevent contamination if err := h.sessionService.ClearContext(ctx, sessionID); err != nil { - logger.Errorf(ctx, "Failed to clear context for session %s: %v", sessionID, err) + logger.Errorf(ctx, "Failed to clear context for session %s: %v", safeSessionID, err) // Continue anyway - this is not a fatal error } if err := h.sessionService.DeleteWebSearchTempKBState(ctx, sessionID); err != nil { - logger.Errorf(ctx, "Failed to delete temp knowledge base for session %s: %v", sessionID, err) + logger.Errorf(ctx, "Failed to delete temp knowledge base for session %s: %v", safeSessionID, err) // Continue anyway - this is not a fatal error } session.AgentConfig.KnowledgeBases = request.KnowledgeBaseIDs @@ -255,16 +264,16 @@ func (h *Handler) AgentQA(c *gin.Context) { session.SummaryModelID = summaryModelID // Persist the session changes if err := h.sessionService.UpdateSession(ctx, session); err != nil { - logger.Errorf(ctx, "Failed to update session %s: %v", sessionID, err) + logger.Errorf(ctx, "Failed to update session %s: %v", safeSessionID, err) c.Error(errors.NewInternalServerError("Failed to update session configuration")) return } - logger.Infof(ctx, "Session configuration updated successfully for session: %s", sessionID) + logger.Infof(ctx, "Session configuration updated successfully for session: %s", safeSessionID) } // If Agent mode is disabled, delegate to KnowledgeQA if !request.AgentEnabled { - logger.Infof(ctx, "Agent mode disabled, delegating to KnowledgeQA for session: %s", sessionID) + logger.Infof(ctx, "Agent mode disabled, delegating to KnowledgeQA for session: %s", safeSessionID) // Use knowledge bases from request or session config knowledgeBaseIDs := request.KnowledgeBaseIDs @@ -285,7 +294,7 @@ func (h *Handler) AgentQA(c *gin.Context) { return } - logger.Infof(ctx, "Delegating to KnowledgeQA with knowledge bases: %v", knowledgeBaseIDs) + logger.Infof(ctx, "Delegating to KnowledgeQA with knowledge bases: %s", secutils.SanitizeForLog(fmt.Sprintf("%v", knowledgeBaseIDs))) // Use shared function to handle KnowledgeQA request (no title generation for AgentQA fallback) h.handleKnowledgeQARequest(ctx, c, session, request.Query, knowledgeBaseIDs, assistantMessage, false, request.SummaryModelID, request.WebSearchEnabled) @@ -325,7 +334,7 @@ func (h *Handler) AgentQA(c *gin.Context) { } assistantMessage = assistantMessagePtr - logger.Infof(ctx, "Calling agent QA service, session ID: %s", sessionID) + logger.Infof(ctx, "Calling agent QA service, session ID: %s", safeSessionID) // Write initial agent_query event to StreamManager h.writeAgentQueryEvent(ctx, sessionID, assistantMessage.ID) @@ -338,7 +347,7 @@ func (h *Handler) AgentQA(c *gin.Context) { // Start async title generation if session has no title if session.Title == "" { - logger.Infof(ctx, "Session has no title, starting async title generation, session ID: %s", sessionID) + logger.Infof(ctx, "Session has no title, starting async title generation, session ID: %s", safeSessionID) h.sessionService.GenerateTitleAsync(asyncCtx, session, request.Query, eventBus) } @@ -353,11 +362,11 @@ func (h *Handler) AgentQA(c *gin.Context) { logger.ErrorWithFields(asyncCtx, errors.NewInternalServerError(fmt.Sprintf("Agent QA service panicked: %v\n%s", r, string(buf))), map[string]interface{}{ - "session_id": sessionID, + "session_id": safeSessionID, }) } h.completeAssistantMessage(asyncCtx, assistantMessage) - logger.Infof(asyncCtx, "Agent QA service completed for session: %s", sessionID) + logger.Infof(asyncCtx, "Agent QA service completed for session: %s", safeSessionID) }() err := h.sessionService.AgentQA(asyncCtx, session, request.Query, assistantMessage.ID, eventBus) if err != nil { @@ -394,6 +403,7 @@ func (h *Handler) handleKnowledgeQARequest( webSearchEnabled bool, // Whether web search is enabled ) { sessionID := session.ID + safeSessionID := secutils.SanitizeForLog(sessionID) requestID := getRequestID(c) // Create user message @@ -415,7 +425,7 @@ func (h *Handler) handleKnowledgeQARequest( return } - logger.Infof(ctx, "Using knowledge bases: %v", knowledgeBaseIDs) + logger.Infof(ctx, "Using knowledge bases: %s", secutils.SanitizeForLog(fmt.Sprintf("%v", knowledgeBaseIDs))) // Set headers for SSE setSSEHeaders(c) @@ -434,7 +444,7 @@ func (h *Handler) handleKnowledgeQARequest( // Generate title if needed if generateTitle && session.Title == "" { - logger.Infof(ctx, "Session has no title, starting async title generation, session ID: %s", sessionID) + logger.Infof(ctx, "Session has no title, starting async title generation, session ID: %s", safeSessionID) h.sessionService.GenerateTitleAsync(asyncCtx, session, query, eventBus) } @@ -445,7 +455,7 @@ func (h *Handler) handleKnowledgeQARequest( } assistantMessage.Content += data.Content if data.Done { - logger.Infof(asyncCtx, "Knowledge QA service completed for session: %s", sessionID) + logger.Infof(asyncCtx, "Knowledge QA service completed for session: %s", safeSessionID) h.completeAssistantMessage(asyncCtx, assistantMessage) // Emit completion event when stream finishes if err := eventBus.Emit(asyncCtx, event.Event{ diff --git a/internal/handler/tenant.go b/internal/handler/tenant.go index 3b5bc3392..bfbbcf824 100644 --- a/internal/handler/tenant.go +++ b/internal/handler/tenant.go @@ -13,6 +13,7 @@ import ( "github.com/Tencent/WeKnora/internal/logger" "github.com/Tencent/WeKnora/internal/types" "github.com/Tencent/WeKnora/internal/types/interfaces" + secutils "github.com/Tencent/WeKnora/internal/utils" ) // TenantHandler implements HTTP request handlers for tenant management @@ -54,7 +55,7 @@ func (h *TenantHandler) CreateTenant(c *gin.Context) { return } - logger.Infof(ctx, "Creating tenant, name: %s", tenantData.Name) + logger.Infof(ctx, "Creating tenant, name: %s", secutils.SanitizeForLog(tenantData.Name)) createdTenant, err := h.service.CreateTenant(ctx, &tenantData) if err != nil { @@ -69,7 +70,7 @@ func (h *TenantHandler) CreateTenant(c *gin.Context) { return } - logger.Infof(ctx, "Tenant created successfully, ID: %d, name: %s", createdTenant.ID, createdTenant.Name) + logger.Infof(ctx, "Tenant created successfully, ID: %d, name: %s", createdTenant.ID, secutils.SanitizeForLog(createdTenant.Name)) c.JSON(http.StatusCreated, gin.H{ "success": true, "data": createdTenant, @@ -86,7 +87,7 @@ func (h *TenantHandler) GetTenant(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { - logger.Errorf(ctx, "Invalid tenant ID: %s", c.Param("id")) + logger.Errorf(ctx, "Invalid tenant ID: %s", secutils.SanitizeForLog(c.Param("id"))) c.Error(errors.NewBadRequestError("Invalid tenant ID")) return } @@ -122,7 +123,7 @@ func (h *TenantHandler) UpdateTenant(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { - logger.Errorf(ctx, "Invalid tenant ID: %s", c.Param("id")) + logger.Errorf(ctx, "Invalid tenant ID: %s", secutils.SanitizeForLog(c.Param("id"))) c.Error(errors.NewBadRequestError("Invalid tenant ID")) return } @@ -134,7 +135,7 @@ func (h *TenantHandler) UpdateTenant(c *gin.Context) { return } - logger.Infof(ctx, "Updating tenant, ID: %d, Name: %s", id, tenantData.Name) + logger.Infof(ctx, "Updating tenant, ID: %d, Name: %s", id, secutils.SanitizeForLog(tenantData.Name)) tenantData.ID = id updatedTenant, err := h.service.UpdateTenant(ctx, &tenantData) @@ -150,7 +151,7 @@ func (h *TenantHandler) UpdateTenant(c *gin.Context) { return } - logger.Infof(ctx, "Tenant updated successfully, ID: %d, Name: %s", updatedTenant.ID, updatedTenant.Name) + logger.Infof(ctx, "Tenant updated successfully, ID: %d, Name: %s", updatedTenant.ID, secutils.SanitizeForLog(updatedTenant.Name)) c.JSON(http.StatusOK, gin.H{ "success": true, "data": updatedTenant, @@ -169,7 +170,7 @@ func (h *TenantHandler) DeleteTenant(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { - logger.Errorf(ctx, "Invalid tenant ID: %s", c.Param("id")) + logger.Errorf(ctx, "Invalid tenant ID: %s", secutils.SanitizeForLog(c.Param("id"))) c.Error(errors.NewBadRequestError("Invalid tenant ID")) return } diff --git a/internal/middleware/auth.go b/internal/middleware/auth.go index 9e0bbf06a..d09efa905 100644 --- a/internal/middleware/auth.go +++ b/internal/middleware/auth.go @@ -140,8 +140,8 @@ func Auth(tenantService interfaces.TenantService, userService interfaces.UserSer } // GetTenantIDFromContext helper function to get tenant ID from context -func GetTenantIDFromContext(ctx context.Context) (uint, error) { - tenantID, ok := ctx.Value("tenantID").(uint) +func GetTenantIDFromContext(ctx context.Context) (uint64, error) { + tenantID, ok := ctx.Value("tenantID").(uint64) if !ok { return 0, errors.New("tenant ID not found in context") } diff --git a/internal/middleware/logger.go b/internal/middleware/logger.go index 2381934eb..5e84d7632 100644 --- a/internal/middleware/logger.go +++ b/internal/middleware/logger.go @@ -105,6 +105,7 @@ func RequestID() gin.HandlerFunc { if requestID == "" { requestID = uuid.New().String() } + safeRequestID := secutils.SanitizeForLog(requestID) // Set request ID in header c.Header("X-Request-ID", requestID) @@ -113,7 +114,7 @@ func RequestID() gin.HandlerFunc { // Set logger in context requestLogger := logger.GetLogger(c) - requestLogger = requestLogger.WithField("request_id", requestID) + requestLogger = requestLogger.WithField("request_id", safeRequestID) c.Set(types.LoggerContextKey.String(), requestLogger) // Set request ID in the global context for logging @@ -154,9 +155,13 @@ func Logger() gin.HandlerFunc { // Get request ID from context requestID, exists := c.Get(types.RequestIDContextKey.String()) - if !exists { - requestID = "unknown" + requestIDStr := "unknown" + if exists { + if idStr, ok := requestID.(string); ok && idStr != "" { + requestIDStr = idStr + } } + safeRequestID := secutils.SanitizeForLog(requestIDStr) // Calculate latency latency := time.Since(start) @@ -189,26 +194,26 @@ func Logger() gin.HandlerFunc { } } - // 构建日志消息 - logMsg := logger.GetLogger(c) - logMsg = logMsg.WithFields(map[string]interface{}{ - "request_id": requestID, - "method": method, - "path": secutils.SanitizeForLog(path), - "status_code": statusCode, - "size": c.Writer.Size(), - "latency": latency.String(), - "client_ip": secutils.SanitizeForLog(clientIP), - }) + // 构建日志消息 + logMsg := logger.GetLogger(c) + logMsg = logMsg.WithFields(map[string]interface{}{ + "request_id": safeRequestID, + "method": method, + "path": secutils.SanitizeForLog(path), + "status_code": statusCode, + "size": c.Writer.Size(), + "latency": latency.String(), + "client_ip": secutils.SanitizeForLog(clientIP), + }) // 添加请求体(如果有) if requestBody != "" { - logMsg = logMsg.WithField("request_body", requestBody) + logMsg = logMsg.WithField("request_body", secutils.SanitizeForLog(requestBody)) } // 添加响应体(如果有) if responseBodyStr != "" { - logMsg = logMsg.WithField("response_body", responseBodyStr) + logMsg = logMsg.WithField("response_body", secutils.SanitizeForLog(responseBodyStr)) } logMsg.Info() }