package community import ( "encoding/json" "fmt" "os" "path/filepath" "time" ) // CommunityConfigManager handles loading and saving community configuration type CommunityConfigManager struct { configPath string config *CommunityConfig } // LoadCommunityConfig loads community configuration from file func LoadCommunityConfig(configPath string) (*CommunityConfig, error) { manager := &CommunityConfigManager{ configPath: configPath, } return manager.Load() } // Load loads configuration from file func (ccm *CommunityConfigManager) Load() (*CommunityConfig, error) { // Check if config file exists if _, err := os.Stat(ccm.configPath); os.IsNotExist(err) { // Create default configuration ccm.config = ccm.createDefaultConfig() return ccm.config, ccm.Save() } // Read existing configuration data, err := os.ReadFile(ccm.configPath) if err != nil { return nil, fmt.Errorf("failed to read config file: %w", err) } // Parse configuration ccm.config = &CommunityConfig{} if err := json.Unmarshal(data, ccm.config); err != nil { return nil, fmt.Errorf("failed to parse config file: %w", err) } return ccm.config, nil } // Save saves configuration to file func (ccm *CommunityConfigManager) Save() error { if ccm.config == nil { return fmt.Errorf("no configuration to save") } // Create directory if it doesn't exist configDir := filepath.Dir(ccm.configPath) if err := os.MkdirAll(configDir, 0755); err != nil { return fmt.Errorf("failed to create config directory: %w", err) } // Marshal configuration data, err := json.MarshalIndent(ccm.config, "", " ") if err != nil { return fmt.Errorf("failed to marshal config: %w", err) } // Write to file if err := os.WriteFile(ccm.configPath, data, 0644); err != nil { return fmt.Errorf("failed to write config file: %w", err) } return nil } // UpdateConfig updates configuration and saves to file func (ccm *CommunityConfigManager) UpdateConfig(updates map[string]interface{}) error { if ccm.config == nil { return fmt.Errorf("no configuration loaded") } // Apply updates for key, value := range updates { switch key { case "enabled": if boolVal, ok := value.(bool); ok { ccm.config.Enabled = boolVal } case "community_path": if strVal, ok := value.(string); ok { ccm.config.CommunityPath = strVal } case "forum_enabled": if boolVal, ok := value.(bool); ok { ccm.config.ForumEnabled = boolVal } case "blueprint_sharing": if boolVal, ok := value.(bool); ok { ccm.config.BlueprintSharing = boolVal } case "feedback_enabled": if boolVal, ok := value.(bool); ok { ccm.config.FeedbackEnabled = boolVal } case "contributor_tools": if boolVal, ok := value.(bool); ok { ccm.config.ContributorTools = boolVal } case "metadata": if mapVal, ok := value.(map[string]string); ok { ccm.config.Metadata = mapVal } } } // Save updated configuration return ccm.Save() } // createDefaultConfig creates a default community configuration func (ccm *CommunityConfigManager) createDefaultConfig() *CommunityConfig { return &CommunityConfig{ Enabled: true, CommunityPath: "/var/lib/debian-forge/community", ForumEnabled: true, BlueprintSharing: true, FeedbackEnabled: true, ContributorTools: true, Metadata: map[string]string{ "version": "1.0.0", "created": time.Now().Format(time.RFC3339), "description": "Default community configuration for Debian Forge", }, } } // ValidateConfig validates the configuration func (ccm *CommunityConfigManager) ValidateConfig() error { if ccm.config == nil { return fmt.Errorf("no configuration loaded") } // Validate community path if ccm.config.CommunityPath == "" { return fmt.Errorf("community path is required") } // Validate paths are absolute if !isAbsolutePath(ccm.config.CommunityPath) { return fmt.Errorf("community path must be absolute") } return nil } // isAbsolutePath checks if a path is absolute func isAbsolutePath(path string) bool { return len(path) > 0 && path[0] == '/' } // GetUserCommunityConfig returns user community configuration func (ccm *CommunityConfigManager) GetUserCommunityConfig() *UserCommunityConfig { if ccm.config == nil { return nil } return &UserCommunityConfig{ Enabled: ccm.config.Enabled, ForumEnabled: ccm.config.ForumEnabled, BlueprintSharing: ccm.config.BlueprintSharing, FeedbackEnabled: ccm.config.FeedbackEnabled, ModerationEnabled: true, Metadata: ccm.config.Metadata, } } // GetContributorConfig returns contributor tools configuration func (ccm *CommunityConfigManager) GetContributorConfig() *ContributorConfig { if ccm.config == nil { return nil } return &ContributorConfig{ Enabled: ccm.config.Enabled, DevSetup: ccm.config.ContributorTools, Guidelines: ccm.config.ContributorTools, Workflows: ccm.config.ContributorTools, Testing: ccm.config.ContributorTools, Onboarding: ccm.config.ContributorTools, Metadata: ccm.config.Metadata, } } // GetEcosystemConfig returns ecosystem integration configuration func (ccm *CommunityConfigManager) GetEcosystemConfig() *EcosystemConfig { if ccm.config == nil { return nil } return &EcosystemConfig{ Enabled: ccm.config.Enabled, CICDEnabled: true, CloudEnabled: true, DevToolsEnabled: true, APIEnabled: true, Metadata: ccm.config.Metadata, } }