Go: add delete search (#14014)

### What problem does this PR solve?

As title.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
Jin Hai
2026-04-10 09:42:37 +08:00
committed by GitHub
parent 56810ec5a3
commit cd04467b9b
4 changed files with 91 additions and 0 deletions

View File

@@ -145,3 +145,18 @@ func (dao *SearchDAO) QueryByTenantIDAndID(tenantID string, searchID string) ([]
err := DB.Where("tenant_id = ? AND id = ? AND status = ?", tenantID, searchID, "1").Find(&searches).Error
return searches, err
}
// DeleteByID deletes a search by ID (soft delete by setting status to "0")
// Reference: Python common_service.py::delete_by_id
func (dao *SearchDAO) DeleteByID(id string) error {
return DB.Model(&entity.Search{}).Where("id = ?", id).Update("status", "0").Error
}
// Accessible4Deletion checks if a search can be deleted by a specific user
// Reference: Python search_service.py::accessible4deletion
// Returns true if the search exists, is valid, and was created by the user
func (dao *SearchDAO) Accessible4Deletion(searchID string, userID string) bool {
var search entity.Search
err := DB.Where("id = ? AND created_by = ? AND status = ?", searchID, userID, "1").First(&search).Error
return err == nil
}

View File

@@ -251,3 +251,61 @@ func (h *SearchHandler) GetSearch(c *gin.Context) {
"message": "success",
})
}
// DeleteSearch delete a search app
// @Summary Delete Search App
// @Description Delete a search app by ID
// @Tags search
// @Accept json
// @Produce json
// @Param search_id path string true "search app ID"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/searches/{search_id} [delete]
func (h *SearchHandler) DeleteSearch(c *gin.Context) {
// Get current user from context (same as Python current_user)
user, errorCode, errorMessage := GetUser(c)
if errorCode != common.CodeSuccess {
jsonError(c, errorCode, errorMessage)
return
}
userID := user.ID
// Get search_id from path parameter (same as Python <search_id>)
searchID := c.Param("search_id")
if searchID == "" {
c.JSON(http.StatusBadRequest, gin.H{
"code": common.CodeBadRequest,
"data": nil,
"message": "search_id is required",
})
return
}
// Delete search with permission check
err := h.searchService.DeleteSearch(userID, searchID)
if err != nil {
// Check if it's an authorization error
if err.Error() == "no authorization" {
c.JSON(http.StatusOK, gin.H{
"code": common.CodeAuthenticationError,
"data": false,
"message": "No authorization.",
})
return
}
// Delete failed error
c.JSON(http.StatusOK, gin.H{
"code": common.CodeDataError,
"data": nil,
"message": err.Error(),
})
return
}
// Return success response (same as Python get_json_result(data=True))
c.JSON(http.StatusOK, gin.H{
"code": common.CodeSuccess,
"data": true,
"message": "success",
})
}

View File

@@ -197,6 +197,7 @@ func (r *Router) Setup(engine *gin.Engine) {
searches.GET("", r.searchHandler.ListSearches)
searches.POST("", r.searchHandler.CreateSearch)
searches.GET("/:search_id", r.searchHandler.GetSearch)
searches.DELETE("/:search_id", r.searchHandler.DeleteSearch)
}
file := v1.Group("/files")

View File

@@ -233,3 +233,20 @@ func (s *SearchService) GetSearchDetail(userID string, searchID string) (*entity
return search, nil
}
// DeleteSearch deletes a search app by ID
func (s *SearchService) DeleteSearch(userID string, searchID string) error {
// Step 1: Check deletion permission (same as Python SearchService.accessible4deletion)
// Python: cls.model.select().where(cls.model.id == search_id, cls.model.created_by == user_id, cls.model.status == StatusEnum.VALID.value).first()
if !s.searchDAO.Accessible4Deletion(searchID, userID) {
return fmt.Errorf("no authorization")
}
// Step 2: Execute delete (same as Python SearchService.delete_by_id)
// Python: cls.model.delete().where(cls.model.id == pid).execute()
if err := s.searchDAO.DeleteByID(searchID); err != nil {
return fmt.Errorf("failed to delete search App %s: %w", searchID, err)
}
return nil
}