package server import ( "net/http" "github.com/gorilla/mux" ) // setupRoutes configures all HTTP routes and their handlers func (s *Server) setupRoutes() *mux.Router { router := mux.NewRouter() // Health endpoint (always available) router.HandleFunc("/health", s.healthHandler).Methods("GET") // KV endpoints (with conditional authentication based on anonymous access settings) // GET endpoint - require auth if anonymous read is disabled if s.config.AuthEnabled && !s.config.AllowAnonymousRead { router.Handle("/kv/{path:.+}", s.authService.Middleware( []string{"read"}, nil, "", )(s.getKVHandler)).Methods("GET") } else { router.HandleFunc("/kv/{path:.+}", s.getKVHandler).Methods("GET") } // PUT endpoint - require auth if anonymous write is disabled if s.config.AuthEnabled && !s.config.AllowAnonymousWrite { router.Handle("/kv/{path:.+}", s.authService.Middleware( []string{"write"}, nil, "", )(s.putKVHandler)).Methods("PUT") } else { router.HandleFunc("/kv/{path:.+}", s.putKVHandler).Methods("PUT") } // DELETE endpoint - always require authentication (no anonymous delete) if s.config.AuthEnabled { router.Handle("/kv/{path:.+}", s.authService.Middleware( []string{"delete"}, nil, "", )(s.deleteKVHandler)).Methods("DELETE") } else { router.HandleFunc("/kv/{path:.+}", s.deleteKVHandler).Methods("DELETE") } // Member endpoints (available when clustering is enabled) if s.config.ClusteringEnabled { // Apply cluster authentication middleware if cluster secret is configured if s.clusterAuthService != nil { router.Handle("/members/", s.clusterAuthService.Middleware(http.HandlerFunc(s.getMembersHandler))).Methods("GET") router.Handle("/members/join", s.clusterAuthService.Middleware(http.HandlerFunc(s.joinMemberHandler))).Methods("POST") router.Handle("/members/leave", s.clusterAuthService.Middleware(http.HandlerFunc(s.leaveMemberHandler))).Methods("DELETE") router.Handle("/members/gossip", s.clusterAuthService.Middleware(http.HandlerFunc(s.gossipHandler))).Methods("POST") router.Handle("/members/pairs_by_time", s.clusterAuthService.Middleware(http.HandlerFunc(s.pairsByTimeHandler))).Methods("POST") // Merkle Tree endpoints (clustering feature) router.Handle("/merkle_tree/root", s.clusterAuthService.Middleware(http.HandlerFunc(s.getMerkleRootHandler))).Methods("GET") router.Handle("/merkle_tree/diff", s.clusterAuthService.Middleware(http.HandlerFunc(s.getMerkleDiffHandler))).Methods("POST") router.Handle("/kv_range", s.clusterAuthService.Middleware(http.HandlerFunc(s.getKVRangeHandler))).Methods("POST") } else { // Fallback to unprotected endpoints (for backwards compatibility) router.HandleFunc("/members/", s.getMembersHandler).Methods("GET") router.HandleFunc("/members/join", s.joinMemberHandler).Methods("POST") router.HandleFunc("/members/leave", s.leaveMemberHandler).Methods("DELETE") router.HandleFunc("/members/gossip", s.gossipHandler).Methods("POST") router.HandleFunc("/members/pairs_by_time", s.pairsByTimeHandler).Methods("POST") // Merkle Tree endpoints (clustering feature) router.HandleFunc("/merkle_tree/root", s.getMerkleRootHandler).Methods("GET") router.HandleFunc("/merkle_tree/diff", s.getMerkleDiffHandler).Methods("POST") router.HandleFunc("/kv_range", s.getKVRangeHandler).Methods("POST") } } // Authentication and user management endpoints (available when auth is enabled) if s.config.AuthEnabled { // User Management endpoints (with authentication middleware) router.Handle("/api/users", s.authService.Middleware( []string{"admin:users:create"}, nil, "", )(s.createUserHandler)).Methods("POST") router.Handle("/api/users/{uuid}", s.authService.Middleware( []string{"admin:users:read"}, nil, "", )(s.getUserHandler)).Methods("GET") router.Handle("/api/users/{uuid}", s.authService.Middleware( []string{"admin:users:update"}, nil, "", )(s.updateUserHandler)).Methods("PUT") router.Handle("/api/users/{uuid}", s.authService.Middleware( []string{"admin:users:delete"}, nil, "", )(s.deleteUserHandler)).Methods("DELETE") // Group Management endpoints (with authentication middleware) router.Handle("/api/groups", s.authService.Middleware( []string{"admin:groups:create"}, nil, "", )(s.createGroupHandler)).Methods("POST") router.Handle("/api/groups/{uuid}", s.authService.Middleware( []string{"admin:groups:read"}, nil, "", )(s.getGroupHandler)).Methods("GET") router.Handle("/api/groups/{uuid}", s.authService.Middleware( []string{"admin:groups:update"}, nil, "", )(s.updateGroupHandler)).Methods("PUT") router.Handle("/api/groups/{uuid}", s.authService.Middleware( []string{"admin:groups:delete"}, nil, "", )(s.deleteGroupHandler)).Methods("DELETE") // Token Management endpoints (with authentication middleware) router.Handle("/api/tokens", s.authService.Middleware( []string{"admin:tokens:create"}, nil, "", )(s.createTokenHandler)).Methods("POST") // Cluster Bootstrap endpoint (Issue #13) - Protected by JWT authentication // Allows authenticated administrators to retrieve the cluster secret for new nodes router.Handle("/auth/cluster-bootstrap", s.authService.Middleware( []string{"admin:tokens:create"}, nil, "", )(s.clusterBootstrapHandler)).Methods("GET") } // Revision History endpoints (available when revision history is enabled) if s.config.RevisionHistoryEnabled { router.HandleFunc("/api/data/{key}/history", s.getRevisionHistoryHandler).Methods("GET") router.HandleFunc("/api/data/{key}/history/{revision}", s.getSpecificRevisionHandler).Methods("GET") } // Backup Status endpoint (always available if backup is enabled) router.HandleFunc("/api/backup/status", s.getBackupStatusHandler).Methods("GET") return router }