package handler import ( "strings" "github.com/gofiber/fiber/v3" "github.com/peterqiu0516/sub-store/internal/middleware" ) // --- Recycle bin handlers --- func (d *Deps) HandleListRecycleBin(c fiber.Ctx) error { entries, err := d.RecycleRepo.List() if err != nil { return failed(c, "Failed to list recycle bin", 500) } return success(c, entries) } func (d *Deps) HandleDeleteRecycleBinEntry(c fiber.Ctx) error { id := c.Params("id") entry, err := d.RecycleRepo.Get(id) if err != nil || entry == nil { return failed(c, "Recycle entry not found", 404) } if err := d.RecycleRepo.Delete(id); err != nil { return failed(c, "Failed to delete", 500) } return success(c, fiber.Map{"deleted": true}) } func (d *Deps) HandleRestoreRecycleBinEntry(c fiber.Ctx) error { id := c.Params("id") entry, err := d.RecycleRepo.Get(id) if err != nil || entry == nil { return failed(c, "Recycle entry not found", 404) } resourceType := getStringValue(entry["resourceType"]) resourceId := getStringValue(entry["resourceId"]) snapshot := getMapValue(entry["snapshot"]) switch resourceType { case "source": existing, _ := d.SourceRepo.Get(resourceId) if existing != nil { return failed(c, "Source id already exists", 409) } d.SourceRepo.Upsert(mapToSourceRecord(snapshot)) case "collection": existing, _ := d.CollectionRepo.Get(resourceId) if existing != nil { return failed(c, "Collection id already exists", 409) } d.CollectionRepo.Upsert(mapToCollectionRecord(snapshot)) case "template": existing, _ := d.TemplateRepo.Get(resourceId) if existing != nil { return failed(c, "Template id already exists", 409) } d.TemplateRepo.Upsert(mapToTemplateRecord(snapshot)) } d.RecycleRepo.Delete(id) return success(c, fiber.Map{ "restored": true, "resourceType": resourceType, "resourceId": resourceId, }) } // getPublicBaseUrl returns the public base URL for download links. // Per review-resolution #11: PUBLIC_DOWNLOAD_HOSTS config, fallback to request origin. func getPublicBaseUrl(c fiber.Ctx) string { // This is set by the handler using deps config publicHosts := c.Locals("publicDownloadHosts") if hosts, ok := publicHosts.(string); ok && hosts != "" { parts := strings.Split(hosts, ",") for _, p := range parts { p = strings.TrimSpace(p) if p != "" { return "https://" + p } } } // Use X-Forwarded-Proto or default to http proto := c.Get("X-Forwarded-Proto") if proto == "" { proto = "http" } return proto + "://" + c.Host() } // SetSafeResponseHeader wraps middleware.SetSafeResponseHeader for handler use. var SetSafeResponseHeader = middleware.SetSafeResponseHeader