package api import ( "net/http" "github.com/gin-gonic/gin" ) // getPublicGarden serves the read-only /full payload for a garden addressed by a // public share token. It sits OUTSIDE requireAuth — the token itself is the // capability — so a logged-out visitor can open a shared link without ever being // bounced to /login or the OIDC flow. An unknown or disabled token is a 404. func (h *handlers) getPublicGarden(c *gin.Context) { full, err := h.svc.PublicGarden(c.Request.Context(), c.Param("token")) if err != nil { writeServiceError(c, err) return } c.JSON(http.StatusOK, full) } // getShareLink reports the garden's public-link state (and, to the owner, the // current token) so the share dialog can show/copy the URL. Owner only. func (h *handlers) getShareLink(c *gin.Context) { id, ok := parseIDParam(c, "id") if !ok { return } link, err := h.svc.GetPublicShareLink(c.Request.Context(), mustActor(c).ID, id) if err != nil { writeServiceError(c, err) return } c.JSON(http.StatusOK, link) } // createShareLink enables the public link (idempotent) or, with {"rotate":true}, // issues a fresh token that invalidates the previous URL. Owner only. The body is // optional — a missing/malformed one just means enable-without-rotate. func (h *handlers) createShareLink(c *gin.Context) { id, ok := parseIDParam(c, "id") if !ok { return } var req struct { Rotate bool `json:"rotate"` } _ = c.ShouldBindJSON(&req) link, err := h.svc.EnablePublicShareLink(c.Request.Context(), mustActor(c).ID, id, req.Rotate) if err != nil { writeServiceError(c, err) return } c.JSON(http.StatusOK, link) } // deleteShareLink disables the public link. Owner only; idempotent. func (h *handlers) deleteShareLink(c *gin.Context) { id, ok := parseIDParam(c, "id") if !ok { return } if err := h.svc.DisablePublicShareLink(c.Request.Context(), mustActor(c).ID, id); err != nil { writeServiceError(c, err) return } c.JSON(http.StatusOK, gin.H{"enabled": false}) }