Add sync conflict detection and resolution system
Implement conflict detection for concurrent reading progress updates from different devices. Adds conflict management endpoints for listing, viewing, and resolving conflicts. - Add ConflictHandler with CRUD endpoints for conflict management - Implement automatic conflict detection in KOReader progress updates - Add WebSocket broadcast for real-time conflict notifications - Add database query for listing user conflicts by status - Add integration tests and Bruno API test collection
This commit is contained in:
+21
-2
@@ -59,6 +59,7 @@ func main() {
|
||||
|
||||
koreaderHandler := handlers.NewKOReaderHandler(queries, connManager)
|
||||
wsHandler := handlers.NewWSHandler(queries, connManager, cfg.JWTSecret, deviceAuthMiddleware)
|
||||
conflictHandler := handlers.NewConflictHandler(queries, connManager)
|
||||
|
||||
e := echo.New()
|
||||
|
||||
@@ -128,10 +129,20 @@ func main() {
|
||||
// Public library types endpoint (no authentication required)
|
||||
e.GET("/api/libraries/types", libraryHandler.GetLibraryTypes)
|
||||
|
||||
// Refresh token endpoint (no authentication required - uses refresh token from body)
|
||||
e.POST("/api/auth/refresh", authHandler.RefreshAccessToken)
|
||||
|
||||
// Logout endpoint (optional authentication - can revoke tokens if provided)
|
||||
e.POST("/api/auth/logout", authHandler.Logout)
|
||||
|
||||
// Protected routes
|
||||
protected = e.Group("/api", jwtMiddleware)
|
||||
|
||||
// Setup ebook handler routes first (so we can use it for library scan)
|
||||
h = handlers.SetupRoutes(protected, queries, connManager)
|
||||
|
||||
protected.GET("/auth/profile", authHandler.GetProfile)
|
||||
protected.PUT("/auth/profile", authHandler.UpdateProfile)
|
||||
protected.POST("/auth/refresh", authHandler.RefreshAccessToken)
|
||||
protected.POST("/auth/logout", authHandler.Logout)
|
||||
|
||||
// Admin-only routes for user and folder management
|
||||
admin := protected.Group("/auth", handlers.AdminMiddleware)
|
||||
@@ -219,6 +230,14 @@ func main() {
|
||||
devices.GET("/approve/:registration_id", deviceHandler.ApproveDevice)
|
||||
devices.POST("/reject/:registration_id", deviceHandler.RejectDevice)
|
||||
|
||||
// Conflict resolution routes (protected - require user auth)
|
||||
conflicts := protected.Group("/conflicts")
|
||||
conflicts.GET("", conflictHandler.ListConflicts)
|
||||
conflicts.GET("/:id", conflictHandler.GetConflict)
|
||||
conflicts.POST("/:id/resolve", conflictHandler.ResolveConflict)
|
||||
conflicts.DELETE("/:id", conflictHandler.DeleteConflict)
|
||||
conflicts.POST("/dismiss-all", conflictHandler.DismissAllResolved)
|
||||
|
||||
// WebSocket endpoint for real-time sync
|
||||
e.GET("/ws/sync", wsHandler.HandleWebSocket)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user