From 455bc750443812229457389fb321d466b102a091 Mon Sep 17 00:00:00 2001 From: Fimeg Date: Mon, 10 Nov 2025 22:32:22 -0500 Subject: [PATCH] fix: ConfigService now reads subsystems from database Critical regression fix - subsystems were hardcoded instead of reading user settings. Added CreateDefaultSubsystems to queries/subsystems.go. ConfigService now queries agent_subsystems table for actual user configuration. AgentLifecycleService creates default subsystems when creating new agents. Respects user-configured enabled/auto_run settings from UI. --- .../internal/database/queries/subsystems.go | 17 ++++++++ .../internal/services/agent_lifecycle.go | 39 +++++++++++------ .../internal/services/config_service.go | 43 +++++++++++++------ 3 files changed, 74 insertions(+), 25 deletions(-) diff --git a/aggregator-server/internal/database/queries/subsystems.go b/aggregator-server/internal/database/queries/subsystems.go index c328ffb..52f1153 100644 --- a/aggregator-server/internal/database/queries/subsystems.go +++ b/aggregator-server/internal/database/queries/subsystems.go @@ -280,6 +280,23 @@ func (q *SubsystemQueries) DeleteSubsystem(agentID uuid.UUID, subsystem string) return nil } +// CreateDefaultSubsystems creates default subsystems for a new agent +func (q *SubsystemQueries) CreateDefaultSubsystems(agentID uuid.UUID) error { + defaults := []models.AgentSubsystem{ + {AgentID: agentID, Subsystem: "updates", Enabled: true, AutoRun: true, IntervalMinutes: 60}, + {AgentID: agentID, Subsystem: "storage", Enabled: true, AutoRun: true, IntervalMinutes: 5}, + {AgentID: agentID, Subsystem: "system", Enabled: true, AutoRun: true, IntervalMinutes: 5}, + {AgentID: agentID, Subsystem: "docker", Enabled: true, AutoRun: true, IntervalMinutes: 15}, + } + + for _, sub := range defaults { + if err := q.CreateSubsystem(&sub); err != nil { + return fmt.Errorf("failed to create subsystem %s: %w", sub.Subsystem, err) + } + } + return nil +} + // Helper function to join update statements func joinUpdates(updates []string) string { result := "" diff --git a/aggregator-server/internal/services/agent_lifecycle.go b/aggregator-server/internal/services/agent_lifecycle.go index fb0bd46..6319ccb 100644 --- a/aggregator-server/internal/services/agent_lifecycle.go +++ b/aggregator-server/internal/services/agent_lifecycle.go @@ -7,6 +7,7 @@ import ( "time" "github.com/Fimeg/RedFlag/aggregator-server/internal/config" + "github.com/Fimeg/RedFlag/aggregator-server/internal/database/queries" "github.com/Fimeg/RedFlag/aggregator-server/internal/models" "github.com/google/uuid" "github.com/jmoiron/sqlx" @@ -35,12 +36,13 @@ type AgentConfig struct { // AgentLifecycleService manages all agent lifecycle operations type AgentLifecycleService struct { - db *sqlx.DB - config *config.Config - buildService *BuildService - configService *ConfigService - artifactService *ArtifactService - logger *log.Logger + db *sqlx.DB + config *config.Config + buildService *BuildService + configService *ConfigService + artifactService *ArtifactService + subsystemQueries *queries.SubsystemQueries + logger *log.Logger } // NewAgentLifecycleService creates a new lifecycle service @@ -50,12 +52,13 @@ func NewAgentLifecycleService( logger *log.Logger, ) *AgentLifecycleService { return &AgentLifecycleService{ - db: db, - config: cfg, - buildService: NewBuildService(db, cfg, logger), - configService: NewConfigService(db, cfg, logger), - artifactService: NewArtifactService(db, cfg, logger), - logger: logger, + db: db, + config: cfg, + buildService: NewBuildService(db, cfg, logger), + configService: NewConfigService(db, cfg, logger), + artifactService: NewArtifactService(db, cfg, logger), + subsystemQueries: queries.NewSubsystemQueries(db), + logger: logger, } } @@ -190,7 +193,17 @@ func (s *AgentLifecycleService) createAgent( VALUES (:id, :hostname, :os_type, :agent_version, :machine_id, :created_at, :updated_at) ` _, err := s.db.NamedExecContext(ctx, query, agent) - return err + if err != nil { + return fmt.Errorf("agent record creation failed: %w", err) + } + + // Create default subsystems for new agent + if err := s.subsystemQueries.CreateDefaultSubsystems(agent.ID); err != nil { + s.logger.Printf("Warning: failed to create default subsystems: %v", err) + // Non-fatal error - agent still created + } + + return nil } // updateAgent updates existing agent record diff --git a/aggregator-server/internal/services/config_service.go b/aggregator-server/internal/services/config_service.go index 25b48e1..eb104c9 100644 --- a/aggregator-server/internal/services/config_service.go +++ b/aggregator-server/internal/services/config_service.go @@ -8,6 +8,7 @@ import ( "time" "github.com/Fimeg/RedFlag/aggregator-server/internal/config" + "github.com/Fimeg/RedFlag/aggregator-server/internal/database/queries" "github.com/Fimeg/RedFlag/aggregator-server/internal/models" "github.com/google/uuid" "github.com/jmoiron/sqlx" @@ -15,17 +16,19 @@ import ( // ConfigService manages agent configuration generation and validation type ConfigService struct { - db *sqlx.DB - config *config.Config - logger *log.Logger + db *sqlx.DB + config *config.Config + logger *log.Logger + subsystemQueries *queries.SubsystemQueries } // NewConfigService creates a new configuration service func NewConfigService(db *sqlx.DB, cfg *config.Config, logger *log.Logger) *ConfigService { return &ConfigService{ - db: db, - config: cfg, - logger: logger, + db: db, + config: cfg, + logger: logger, + subsystemQueries: queries.NewSubsystemQueries(db), } } @@ -58,6 +61,27 @@ func (s *ConfigService) GenerateNewConfig(agentCfg *AgentConfig) ([]byte, error) serverURL = s.config.Server.PublicURL } + // Get subsystems from database (not hardcoded!) + agentID := uuid.MustParse(agentCfg.AgentID) + subsystems, err := s.subsystemQueries.GetSubsystems(agentID) + if err != nil || len(subsystems) == 0 { + // If not found, create defaults + if err := s.subsystemQueries.CreateDefaultSubsystems(agentID); err != nil { + return nil, fmt.Errorf("failed to create default subsystems: %w", err) + } + subsystems, _ = s.subsystemQueries.GetSubsystems(agentID) + } + + // Convert to map format for JSON + subsystemMap := make(map[string]interface{}) + for _, sub := range subsystems { + subsystemMap[sub.Subsystem] = map[string]interface{}{ + "enabled": sub.Enabled, + "auto_run": sub.AutoRun, + "interval": sub.IntervalMinutes, + } + } + cfg := &AgentConfigData{ AgentID: agentCfg.AgentID, Version: agentCfg.Version, @@ -69,12 +93,7 @@ func (s *ConfigService) GenerateNewConfig(agentCfg *AgentConfig) ([]byte, error) "updates": 3600, // 1 hour "commands": 30, // 30 seconds }, - Subsystems: map[string]interface{}{ - "updates": map[string]interface{}{"enabled": true, "auto_run": true, "timeout": 300}, - "storage": map[string]interface{}{"enabled": true, "auto_run": true, "timeout": 60}, - "system": map[string]interface{}{"enabled": true, "auto_run": true, "timeout": 60}, - "docker": map[string]interface{}{"enabled": true, "auto_run": true, "timeout": 120}, - }, + Subsystems: subsystemMap, // ← USE DATABASE VALUES! MaxRetries: 3, TimeoutSeconds: 30, MachineID: agentCfg.MachineID,