mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-07 22:06:38 +08:00
fix: add field whitelist to site update, fix HTTP status codes in site handlers
- SiteService.Update: whitelist updatable fields to prevent injection of id, created_at, deleted_at, login_status, upload_bytes, download_bytes - createSiteHandler: return 201 Created (was 200 OK) - siteSearchHandler: return 500 for infra errors (was 400) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -102,7 +102,7 @@ func createSiteHandler(svc *service.Container) gin.HandlerFunc {
|
|||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, site)
|
c.JSON(http.StatusCreated, site)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ func siteSearchHandler(svc *service.Container) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
results, err := svc.Site.Search(c.Request.Context(), keyword)
|
results, err := svc.Site.Search(c.Request.Context(), keyword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{"items": results, "total": len(results)})
|
c.JSON(http.StatusOK, gin.H{"items": results, "total": len(results)})
|
||||||
|
|||||||
@@ -213,20 +213,53 @@ func (s *SiteService) FindByID(ctx context.Context, id string) (*model.Site, err
|
|||||||
return &site, err
|
return &site, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// siteUpdatableFields is the whitelist of columns that may be patched via
|
||||||
|
// the update endpoint. Fields like id, created_at, deleted_at, login_status,
|
||||||
|
// upload_bytes, download_bytes are excluded to prevent injection.
|
||||||
|
var siteUpdatableFields = map[string]bool{
|
||||||
|
"name": true,
|
||||||
|
"url": true,
|
||||||
|
"type": true,
|
||||||
|
"auth_type": true,
|
||||||
|
"api_key": true,
|
||||||
|
"cookie": true,
|
||||||
|
"auth_header": true,
|
||||||
|
"user_agent": true,
|
||||||
|
"rss_url": true,
|
||||||
|
"timeout": true,
|
||||||
|
"priority": true,
|
||||||
|
"use_proxy": true,
|
||||||
|
"rate_limit": true,
|
||||||
|
"browser_emulation": true,
|
||||||
|
"downloader": true,
|
||||||
|
"enabled": true,
|
||||||
|
"is_default": true,
|
||||||
|
"extra": true,
|
||||||
|
}
|
||||||
|
|
||||||
// Update applies a partial patch to an existing site.
|
// Update applies a partial patch to an existing site.
|
||||||
func (s *SiteService) Update(ctx context.Context, id string, updates map[string]any) error {
|
func (s *SiteService) Update(ctx context.Context, id string, updates map[string]any) error {
|
||||||
if id == "" {
|
if id == "" {
|
||||||
return errors.New("site id required")
|
return errors.New("site id required")
|
||||||
}
|
}
|
||||||
if raw, ok := updates["url"].(string); ok {
|
filtered := make(map[string]any, len(updates))
|
||||||
updates["url"] = strings.TrimRight(strings.TrimSpace(raw), "/")
|
for k, v := range updates {
|
||||||
}
|
if siteUpdatableFields[k] {
|
||||||
for _, key := range []string{"api_key", "cookie", "auth_header"} {
|
filtered[k] = v
|
||||||
if raw, ok := updates[key].(string); ok && strings.TrimSpace(raw) == "" {
|
|
||||||
delete(updates, key)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s.repo.DB.WithContext(ctx).Model(&model.Site{}).Where("id = ?", id).Updates(updates).Error
|
if len(filtered) == 0 {
|
||||||
|
return errors.New("no valid fields to update")
|
||||||
|
}
|
||||||
|
if raw, ok := filtered["url"].(string); ok {
|
||||||
|
filtered["url"] = strings.TrimRight(strings.TrimSpace(raw), "/")
|
||||||
|
}
|
||||||
|
for _, key := range []string{"api_key", "cookie", "auth_header"} {
|
||||||
|
if raw, ok := filtered[key].(string); ok && strings.TrimSpace(raw) == "" {
|
||||||
|
delete(filtered, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s.repo.DB.WithContext(ctx).Model(&model.Site{}).Where("id = ?", id).Updates(filtered).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete removes a site.
|
// Delete removes a site.
|
||||||
|
|||||||
Reference in New Issue
Block a user