From 7d7e6e412a97f6e7a5303b2daf0be632063e0999 Mon Sep 17 00:00:00 2001 From: ryyst Date: Thu, 18 Sep 2025 18:17:01 +0300 Subject: [PATCH] Add configuration options to disable optional functionalities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented feature toggles for: - Authentication system (auth_enabled) - Tamper-evident logging (tamper_logging_enabled) - Clustering/gossip (clustering_enabled) - Rate limiting (rate_limiting_enabled) - Revision history (revision_history_enabled) All features are enabled by default to maintain backward compatibility. When disabled, features are gracefully skipped to reduce overhead. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- main.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/main.go b/main.go index a4d417d..b2fcaf8 100644 --- a/main.go +++ b/main.go @@ -294,6 +294,13 @@ type Config struct { BackupSchedule string `yaml:"backup_schedule"` // Cron schedule format BackupPath string `yaml:"backup_path"` // Directory to store backups BackupRetention int `yaml:"backup_retention"` // Days to keep backups + + // Feature toggles for optional functionalities + AuthEnabled bool `yaml:"auth_enabled"` // Enable/disable authentication system + TamperLoggingEnabled bool `yaml:"tamper_logging_enabled"` // Enable/disable tamper-evident logging + ClusteringEnabled bool `yaml:"clustering_enabled"` // Enable/disable clustering/gossip + RateLimitingEnabled bool `yaml:"rate_limiting_enabled"` // Enable/disable rate limiting + RevisionHistoryEnabled bool `yaml:"revision_history_enabled"` // Enable/disable revision history } // Server represents the KVS node @@ -652,6 +659,12 @@ func (s *Server) checkResourcePermission(authCtx *AuthContext, resourceKey strin func (s *Server) authMiddleware(requiredScopes []string, resourceKeyExtractor func(*http.Request) string, operation string) func(http.HandlerFunc) http.HandlerFunc { return func(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + // Skip authentication if disabled + if !s.config.AuthEnabled { + next(w, r) + return + } + // Authenticate request authCtx, err := s.authenticateRequest(r) if err != nil { @@ -1082,6 +1095,12 @@ func (s *Server) checkRateLimit(userUUID string) (bool, error) { // rateLimitMiddleware is the HTTP middleware that enforces rate limiting func (s *Server) rateLimitMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + // Skip rate limiting if disabled + if !s.config.RateLimitingEnabled { + next(w, r) + return + } + // Extract auth context to get user UUID authCtx, ok := r.Context().Value("auth").(*AuthContext) if !ok || authCtx == nil { @@ -1148,8 +1167,8 @@ func (s *Server) isActionLogged(action string) bool { // createTamperLogEntry creates a new tamper-evident log entry func (s *Server) createTamperLogEntry(action, userUUID, resource string) *TamperLogEntry { - if !s.isActionLogged(action) { - return nil // Action not configured for logging + if !s.config.TamperLoggingEnabled || !s.isActionLogged(action) { + return nil // Tamper logging disabled or action not configured for logging } timestamp := time.Now().UTC().Format(time.RFC3339) @@ -1486,6 +1505,13 @@ func defaultConfig() *Config { BackupSchedule: "0 0 * * *", // Daily at midnight BackupPath: "./backups", BackupRetention: 7, // Keep backups for 7 days + + // Default feature toggle settings (all enabled by default) + AuthEnabled: true, + TamperLoggingEnabled: true, + ClusteringEnabled: true, + RateLimitingEnabled: true, + RevisionHistoryEnabled: true, } } @@ -2100,8 +2126,8 @@ func (s *Server) Start() error { // Start gossip and sync routines s.startBackgroundTasks() - // Try to join cluster if seed nodes are configured - if len(s.config.SeedNodes) > 0 { + // Try to join cluster if seed nodes are configured and clustering is enabled + if s.config.ClusteringEnabled && len(s.config.SeedNodes) > 0 { go s.bootstrap() } @@ -2131,15 +2157,18 @@ func (s *Server) Stop() error { // Background tasks (gossip, sync, Merkle tree rebuild, etc.) func (s *Server) startBackgroundTasks() { - // Start gossip routine - s.wg.Add(1) - go s.gossipRoutine() + // Start clustering-related routines only if clustering is enabled + if s.config.ClusteringEnabled { + // Start gossip routine + s.wg.Add(1) + go s.gossipRoutine() - // Start sync routine (now Merkle-based) - s.wg.Add(1) - go s.syncRoutine() + // Start sync routine (now Merkle-based) + s.wg.Add(1) + go s.syncRoutine() + } - // Start Merkle tree rebuild routine + // Start Merkle tree rebuild routine (always needed for data integrity) s.wg.Add(1) go s.merkleTreeRebuildRoutine() } @@ -3194,6 +3223,12 @@ func (s *Server) createTokenHandler(w http.ResponseWriter, r *http.Request) { // getRevisionHistoryHandler handles GET /api/data/{key}/history func (s *Server) getRevisionHistoryHandler(w http.ResponseWriter, r *http.Request) { + // Check if revision history is enabled + if !s.config.RevisionHistoryEnabled { + http.Error(w, "Revision history is disabled", http.StatusServiceUnavailable) + return + } + vars := mux.Vars(r) key := vars["key"] @@ -3224,6 +3259,12 @@ func (s *Server) getRevisionHistoryHandler(w http.ResponseWriter, r *http.Reques // getSpecificRevisionHandler handles GET /api/data/{key}/history/{revision} func (s *Server) getSpecificRevisionHandler(w http.ResponseWriter, r *http.Request) { + // Check if revision history is enabled + if !s.config.RevisionHistoryEnabled { + http.Error(w, "Revision history is disabled", http.StatusServiceUnavailable) + return + } + vars := mux.Vars(r) key := vars["key"] revisionStr := vars["revision"]