feat: add Kobo device sync support and fix device route protection

- Add Kobo sync handler with markup, bookmark, analytics, and initialization endpoints
- Add Kobo integration tests and Bruno API test collection
- Move device approve/reject routes from public to protected routes
- Enhance test infrastructure with DATABASE_URL support and helper functions
- Fix device GetDevice handler nil pointer handling
- Clean up test reports and session files
This commit is contained in:
2026-01-30 23:58:34 -05:00
parent b49ba7909f
commit a3aa9f67ac
11 changed files with 839 additions and 676 deletions
+10 -2
View File
@@ -184,8 +184,6 @@ func main() {
// Device management routes (public - for registration)
e.POST("/api/devices/register", deviceHandler.InitiateRegistration)
e.POST("/api/devices/register/status", deviceHandler.CheckRegistrationStatus)
e.GET("/devices/approve/:registration_id", deviceHandler.ApproveDevice)
e.POST("/devices/reject/:registration_id", deviceHandler.RejectDevice)
// KOReader sync routes (device authentication required)
koreaderSync := e.Group("/api/sync/koreader")
@@ -194,6 +192,14 @@ func main() {
koreaderSync.GET("/library", deviceAuthMiddleware.Authenticate(koreaderHandler.GetLibrary))
koreaderSync.POST("/bookmarks", deviceAuthMiddleware.Authenticate(koreaderHandler.SyncBookmarks))
// Kobo sync routes (device authentication required)
koboHandler := handlers.NewKoboHandler(queries, connManager)
koboSync := e.Group("/api/sync/kobo")
koboSync.POST("/markup", deviceAuthMiddleware.Authenticate(koboHandler.Markup))
koboSync.POST("/bookmark", deviceAuthMiddleware.Authenticate(koboHandler.Bookmark))
koboSync.POST("/v1/analytics/gettests", deviceAuthMiddleware.Authenticate(koboHandler.AnalyticsGettests))
koboSync.GET("/v1/initialization", deviceAuthMiddleware.Authenticate(koboHandler.Initialization))
// Device management routes (protected - require user auth)
devices := protected.Group("/devices")
devices.GET("", deviceHandler.ListDevices)
@@ -201,6 +207,8 @@ func main() {
devices.PUT("/:id", deviceHandler.UpdateDevice)
devices.DELETE("/:id", deviceHandler.DeleteDevice)
devices.GET("/pending", deviceHandler.ListPendingRegistrations)
devices.GET("/approve/:registration_id", deviceHandler.ApproveDevice)
devices.POST("/reject/:registration_id", deviceHandler.RejectDevice)
// WebSocket endpoint for real-time sync
e.GET("/ws/sync", wsHandler.HandleWebSocket)