Gitfed
bastien-mrq/gitfed / internal / config / config.go
// Package config holds the on-disk instance configuration shared by
// cmd/gitfed-server and cmd/gitfed-tui.
package config

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"

	"git.neuromancer.ovh/bastien-mrq/gitfed/internal/store"
)

type Config struct {
	Domain       string            `json:"domain"`
	DataDir      string            `json:"data_dir"`
	ReposDir     string            `json:"repos_dir"`
	ListenSSH    string            `json:"listen_ssh"`
	ListenHTTP   string            `json:"listen_http"` // empty disables the well-known HTTP server
	Contact      string            `json:"contact"`
	TrustPolicy  store.TrustPolicy `json:"trust_policy"`
	CertTTLHours int               `json:"cert_ttl_hours"`

	// InsecureFederation fetches remote .well-known documents over plain
	// HTTP instead of HTTPS. Dev/testing only (e.g. federating two local
	// instances with no real domain or TLS cert) — never enable this
	// against real remote instances.
	InsecureFederation bool `json:"insecure_federation"`
}

func Default(domain, dataDir string) Config {
	return Config{
		Domain:       domain,
		DataDir:      dataDir,
		ReposDir:     filepath.Join(dataDir, "repos"),
		ListenSSH:    ":2222",
		ListenHTTP:   ":8443",
		TrustPolicy:  store.TrustPolicyWhitelist,
		CertTTLHours: 24,
	}
}

func (c Config) DBPath() string          { return filepath.Join(c.DataDir, "gitfed.db") }
func (c Config) CADir() string           { return filepath.Join(c.DataDir, "ca") }
func (c Config) HostKeyPath() string     { return filepath.Join(c.DataDir, "host_key") }
func (c Config) AdminSocketPath() string { return filepath.Join(c.DataDir, "admin.sock") }

func Load(path string) (Config, error) {
	var c Config
	data, err := os.ReadFile(path)
	if err != nil {
		return c, fmt.Errorf("config: read %s: %w", path, err)
	}
	if err := json.Unmarshal(data, &c); err != nil {
		return c, fmt.Errorf("config: parse %s: %w", path, err)
	}
	return c, nil
}

func Save(path string, c Config) error {
	data, err := json.MarshalIndent(c, "", "  ")
	if err != nil {
		return err
	}
	if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
		return err
	}
	return os.WriteFile(path, data, 0644)
}