diff --git a/internal/handlers/ebook.go b/internal/handlers/ebook.go index 8c729d4..3f866aa 100644 --- a/internal/handlers/ebook.go +++ b/internal/handlers/ebook.go @@ -47,25 +47,29 @@ func parseDate(dateStr string) time.Time { func SetupRoutes(g *echo.Group, db *database.Queries) { h := NewHandler(db) + // Public routes (all authenticated users) g.GET("/ebooks", h.ListEbooks) g.GET("/ebooks/:id", h.GetEbook) - g.POST("/ebooks", h.CreateEbook) - g.PUT("/ebooks/:id", h.UpdateEbook) - g.DELETE("/ebooks/:id", h.DeleteEbook) + // User-specific routes g.GET("/ebooks/:id/progress", h.GetReadingProgress) g.PUT("/ebooks/:id/progress", h.UpdateReadingProgress) - g.GET("/ebooks/:id/rating", h.GetEbookRating) g.POST("/ebooks/:id/rating", h.CreateOrUpdateEbookRating) g.PUT("/ebooks/:id/rating", h.CreateOrUpdateEbookRating) g.DELETE("/ebooks/:id/rating", h.DeleteEbookRating) g.GET("/ebooks/:id/ratings", h.GetEbookRatings) - // Scanner routes - g.POST("/scanner/scan", h.ScanEbooks) - g.POST("/scanner/start", h.StartScanner) - g.POST("/scanner/stop", h.StopScanner) + // Admin-only routes + admin := g.Group("", AdminMiddleware) + admin.POST("/ebooks", h.CreateEbook) + admin.PUT("/ebooks/:id", h.UpdateEbook) + admin.DELETE("/ebooks/:id", h.DeleteEbook) + + // Scanner routes (admin only) + admin.POST("/scanner/scan", h.ScanEbooks) + admin.POST("/scanner/start", h.StartScanner) + admin.POST("/scanner/stop", h.StopScanner) } // ListEbooks handles GET /api/ebooks @@ -147,6 +151,13 @@ func (h *Handler) CreateEbook(c echo.Context) error { return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) } + // Get admin ID from JWT token + userID := c.Get("user_id").(string) + userUUID, err := uuid.Parse(userID) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"}) + } + ebook, err := h.db.CreateEbook(c.Request().Context(), database.CreateEbookParams{ Title: req.Title, Author: pgtype.Text{String: req.Author, Valid: req.Author != ""}, @@ -163,6 +174,7 @@ func (h *Handler) CreateEbook(c echo.Context) error { DatePublished: pgtype.Date{Time: parseDate(req.DatePublished), Valid: req.DatePublished != ""}, Publisher: pgtype.Text{String: req.Publisher, Valid: req.Publisher != ""}, Contributors: pgtype.Text{String: req.Contributors, Valid: req.Contributors != ""}, + AddedByAdminID: pgtype.UUID{Bytes: userUUID, Valid: true}, }) if err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()}) @@ -486,6 +498,9 @@ func (h *Handler) ScanEbooks(c echo.Context) error { return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid folder paths: " + err.Error()}) } + // Set the admin ID for ebook association + h.scanner.SetAdminID(pgtype.UUID{Bytes: userUUID, Valid: true}) + // Perform the scan if err := h.scanner.ScanFolders(h.ctx); err != nil { return c.JSON(http.StatusInternalServerError, map[string]string{"error": "scan failed: " + err.Error()}) @@ -504,11 +519,21 @@ func (h *Handler) StartScanner(c echo.Context) error { return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request"}) } + // Get admin ID from JWT token + userID := c.Get("user_id").(string) + userUUID, err := uuid.Parse(userID) + if err != nil { + return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid user id"}) + } + // Set the folder paths if err := h.scanner.SetFolders(req.FolderPaths); err != nil { return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid folder paths: " + err.Error()}) } + // Set the admin ID for ebook association + h.scanner.SetAdminID(pgtype.UUID{Bytes: userUUID, Valid: true}) + // Start watching for changes h.scanner.WatchChanges(h.ctx) diff --git a/internal/services/ebook_scanner.go b/internal/services/ebook_scanner.go index a5441f3..a6f87f0 100644 --- a/internal/services/ebook_scanner.go +++ b/internal/services/ebook_scanner.go @@ -36,6 +36,7 @@ type EbookScanner struct { db *database.Queries watcher *fsnotify.Watcher folders []string + adminID pgtype.UUID } func NewEbookScanner(db *database.Queries) *EbookScanner { @@ -50,6 +51,10 @@ func NewEbookScanner(db *database.Queries) *EbookScanner { } } +func (s *EbookScanner) SetAdminID(adminID pgtype.UUID) { + s.adminID = adminID +} + func (s *EbookScanner) SetFolders(folders []string) error { s.folders = folders @@ -291,6 +296,7 @@ func (s *EbookScanner) processEbookFile(ctx context.Context, path string) error DatePublished: pgtype.Date{Time: metadata.PublishDate, Valid: !metadata.PublishDate.IsZero()}, Contributors: pgtype.Text{String: metadata.Contributors, Valid: metadata.Contributors != ""}, Tags: pgtype.Text{String: metadata.Tags, Valid: metadata.Tags != ""}, + AddedByAdminID: s.adminID, }) return err