mirror of
https://github.com/Tencent/WeKnora.git
synced 2026-09-21 13:52:09 +08:00
refactor: Sanitize log inputs across various handlers to enhance security
- Implemented input sanitization for logging in chunk, evaluation, initialization, knowledge, knowledgebase, mcp_service, model, tenant, and session handlers. - Updated logging statements to use sanitized values for sensitive information, preventing potential injection attacks.
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+13
-13
@@ -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",
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user