package shares import ( "net/http" "github.com/atlasos/calypso/internal/common/database" "github.com/atlasos/calypso/internal/common/logger" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" ) // Handler handles Shares-related API requests type Handler struct { service *Service logger *logger.Logger } // NewHandler creates a new Shares handler func NewHandler(db *database.DB, log *logger.Logger) *Handler { return &Handler{ service: NewService(db, log), logger: log, } } // ListShares lists all shares func (h *Handler) ListShares(c *gin.Context) { shares, err := h.service.ListShares(c.Request.Context()) if err != nil { h.logger.Error("Failed to list shares", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list shares"}) return } // Ensure we return an empty array instead of null if shares == nil { shares = []*Share{} } c.JSON(http.StatusOK, gin.H{"shares": shares}) } // GetShare retrieves a share by ID func (h *Handler) GetShare(c *gin.Context) { shareID := c.Param("id") share, err := h.service.GetShare(c.Request.Context(), shareID) if err != nil { if err.Error() == "share not found" { c.JSON(http.StatusNotFound, gin.H{"error": "share not found"}) return } h.logger.Error("Failed to get share", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get share"}) return } c.JSON(http.StatusOK, share) } // CreateShare creates a new share func (h *Handler) CreateShare(c *gin.Context) { var req CreateShareRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Error("Invalid create share request", "error", err) c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request: " + err.Error()}) return } // Validate request validate := validator.New() if err := validate.Struct(req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "validation failed: " + err.Error()}) return } // Get user ID from context (set by auth middleware) userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } share, err := h.service.CreateShare(c.Request.Context(), &req, userID.(string)) if err != nil { if err.Error() == "dataset not found" { c.JSON(http.StatusNotFound, gin.H{"error": "dataset not found"}) return } if err.Error() == "only filesystem datasets can be shared (not volumes)" { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err.Error() == "at least one protocol (NFS or SMB) must be enabled" { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } h.logger.Error("Failed to create share", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, share) } // UpdateShare updates an existing share func (h *Handler) UpdateShare(c *gin.Context) { shareID := c.Param("id") var req UpdateShareRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Error("Invalid update share request", "error", err) c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request: " + err.Error()}) return } share, err := h.service.UpdateShare(c.Request.Context(), shareID, &req) if err != nil { if err.Error() == "share not found" { c.JSON(http.StatusNotFound, gin.H{"error": "share not found"}) return } h.logger.Error("Failed to update share", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, share) } // DeleteShare deletes a share func (h *Handler) DeleteShare(c *gin.Context) { shareID := c.Param("id") err := h.service.DeleteShare(c.Request.Context(), shareID) if err != nil { if err.Error() == "share not found" { c.JSON(http.StatusNotFound, gin.H{"error": "share not found"}) return } h.logger.Error("Failed to delete share", "error", err) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "share deleted successfully"}) }