package backend import ( "flag" "fmt" "io/fs" "os" "path/filepath" "strings" "github.com/BurntSushi/toml" ) type Config struct { AESKeyFile string ArticleDir string ConfigFile string DBName string Description string Domain string AtomFile string FirebaseKey string GOBKeyFile string Link string LogFile string PDFDir string PicsDir string Port string Title string Version string WebDir string MaxBannerHeight int MaxBannerWidth int MaxImgHeight int MaxImgWidth int } func newConfig() *Config { return &Config{ AESKeyFile: "/var/www/cpolis/aes.key", ArticleDir: "/var/www/cpolis/articles", AtomFile: "/var/www/cpolis/cpolis.atom", ConfigFile: "/etc/cpolis/config.toml", DBName: "cpolis", FirebaseKey: "/var/www/cpolis/serviceAccountKey.json", GOBKeyFile: "/var/www/cpolis/gob.key", LogFile: "/var/log/cpolis.log", MaxBannerHeight: 1080, MaxBannerWidth: 1920, MaxImgHeight: 1080, MaxImgWidth: 1920, PDFDir: "/var/www/cpolis/pdfs", PicsDir: "/var/www/cpolis/pics", Port: ":8080", Version: "v0.13.2", WebDir: "/var/www/cpolis/web", } } func mkDir(path string, perm fs.FileMode) (string, error) { var err error stringSlice := strings.Split(path, "/") name := stringSlice[len(stringSlice)-1] path, err = filepath.Abs(path) if err != nil { return "", fmt.Errorf("error finding absolute path for %v directory: %v", name, err) } if err = os.MkdirAll(path, perm); err != nil { return "", fmt.Errorf("error creating %v directory: %v", name, err) } return path, nil } func mkFile(path string, filePerm, dirPerm fs.FileMode) (string, error) { var err error path, err = filepath.Abs(path) if err != nil { return "", fmt.Errorf("error finding absolute path for %v: %v", path, err) } stringSlice := strings.Split(path, "/") _, err = os.Stat(path) if os.IsNotExist(err) { dir := strings.Join(stringSlice[:len(stringSlice)-1], "/") if err = os.MkdirAll(dir, dirPerm); err != nil { return "", fmt.Errorf("error creating %v: %v", dir, err) } fileName := stringSlice[len(stringSlice)-1] file, err := os.Create(dir + "/" + fileName) if err != nil { return "", fmt.Errorf("error creating %v: %v", fileName, err) } defer file.Close() if err = file.Chmod(filePerm); err != nil { return "", fmt.Errorf("error setting permissions for %v: %v", fileName, err) } } return path, nil } func (c *Config) handleCliArgs() error { var port int var err error flag.StringVar(&c.AESKeyFile, "aes", c.AESKeyFile, "aes key file") flag.StringVar(&c.ArticleDir, "articles", c.ArticleDir, "articles directory") flag.StringVar(&c.AtomFile, "feed", c.AtomFile, "atom feed file") flag.StringVar(&c.ConfigFile, "config", c.ConfigFile, "config file") flag.StringVar(&c.DBName, "db", c.DBName, "DB name") flag.StringVar(&c.Description, "desc", c.Description, "channel description") flag.StringVar(&c.Domain, "domain", c.Domain, "domain name") flag.StringVar(&c.FirebaseKey, "firebase", c.FirebaseKey, "Firebase service account key file") flag.StringVar(&c.GOBKeyFile, "gob", c.GOBKeyFile, "gob key file") flag.StringVar(&c.Link, "link", c.Link, "channel Link") flag.StringVar(&c.LogFile, "log", c.LogFile, "log file") flag.StringVar(&c.PDFDir, "pdfs", c.PDFDir, "pdf directory") flag.StringVar(&c.PicsDir, "pics", c.PicsDir, "pictures directory") flag.StringVar(&c.Title, "title", c.Title, "channel title") flag.StringVar(&c.WebDir, "web", c.WebDir, "web directory") flag.IntVar(&c.MaxBannerHeight, "banner-height", c.MaxBannerHeight, "maximum banner height") flag.IntVar(&c.MaxBannerWidth, "banner-width", c.MaxBannerWidth, "maximum banner width") flag.IntVar(&c.MaxImgHeight, "img-height", c.MaxImgHeight, "maximum image height") flag.IntVar(&c.MaxImgWidth, "img-width", c.MaxImgWidth, "maximum image width") flag.IntVar(&port, "port", port, "port") flag.Parse() if port != 0 { c.Port = fmt.Sprint(":", port) } c.ConfigFile, err = mkFile(c.ConfigFile, 0600, 0700) if err != nil { return fmt.Errorf("error setting up file: %v", err) } return nil } func (c *Config) handleFile(configFile string) error { _, err := toml.DecodeFile(configFile, c) if err != nil { return fmt.Errorf("error reading config file: %v", err) } return nil } func (c *Config) setupConfig(cliConfig *Config) error { var err error defaultConfig := newConfig() if cliConfig.AESKeyFile != defaultConfig.AESKeyFile { c.AESKeyFile = cliConfig.AESKeyFile } c.AESKeyFile, err = mkFile(c.AESKeyFile, 0600, 0700) if err != nil { return fmt.Errorf("error setting up file: %v", err) } if cliConfig.ArticleDir != defaultConfig.ArticleDir { c.ArticleDir = cliConfig.ArticleDir } c.ArticleDir, err = mkDir(c.ArticleDir, 0700) if err != nil { return fmt.Errorf("error setting up directory: %v", err) } if cliConfig.DBName != defaultConfig.DBName { c.DBName = cliConfig.DBName } if cliConfig.Description != defaultConfig.Description { c.Description = cliConfig.Description } if cliConfig.Domain != defaultConfig.Domain { c.Domain = cliConfig.Domain } domainStrings := strings.Split(c.Domain, "/") if domainStrings[0] != "http:" && domainStrings[0] != "https:" { c.Domain = "https://" + c.Domain } if cliConfig.AtomFile != defaultConfig.AtomFile { c.AtomFile = cliConfig.AtomFile } c.AtomFile, err = mkFile(c.AtomFile, 0644, 0744) if err != nil { return fmt.Errorf("error setting up file: %v", err) } if cliConfig.FirebaseKey != defaultConfig.FirebaseKey { c.FirebaseKey = cliConfig.FirebaseKey } c.FirebaseKey, err = mkFile(c.FirebaseKey, 0600, 0700) if err != nil { return fmt.Errorf("error setting up file: %v", err) } if cliConfig.GOBKeyFile != defaultConfig.GOBKeyFile { c.GOBKeyFile = cliConfig.GOBKeyFile } c.GOBKeyFile, err = mkFile(c.GOBKeyFile, 0600, 0700) if err != nil { return fmt.Errorf("error setting up file: %v", err) } if cliConfig.Link != defaultConfig.Link { c.Link = cliConfig.Link } if cliConfig.LogFile != defaultConfig.LogFile { c.LogFile = cliConfig.LogFile } c.LogFile, err = mkFile(c.LogFile, 0600, 0700) if err != nil { return fmt.Errorf("error setting up file: %v", err) } if cliConfig.MaxBannerHeight != defaultConfig.MaxBannerHeight { c.MaxBannerHeight = cliConfig.MaxBannerHeight } if cliConfig.MaxBannerWidth != defaultConfig.MaxBannerWidth { c.MaxBannerWidth = cliConfig.MaxBannerWidth } if cliConfig.MaxImgHeight != defaultConfig.MaxImgHeight { c.MaxImgHeight = cliConfig.MaxImgHeight } if cliConfig.MaxImgWidth != defaultConfig.MaxImgWidth { c.MaxImgWidth = cliConfig.MaxImgWidth } if cliConfig.PDFDir != defaultConfig.PDFDir { c.PDFDir = cliConfig.PDFDir } c.PDFDir, err = mkDir(c.PDFDir, 0700) if err != nil { return fmt.Errorf("error setting up directory: %v", err) } if cliConfig.PicsDir != defaultConfig.PicsDir { c.PicsDir = cliConfig.PicsDir } c.PicsDir, err = mkDir(c.PicsDir, 0700) if err != nil { return fmt.Errorf("error setting up directory: %v", err) } if cliConfig.Port != defaultConfig.Port { c.Port = cliConfig.Port } if cliConfig.Title != defaultConfig.Title { c.Title = cliConfig.Title } if cliConfig.WebDir != defaultConfig.WebDir { c.WebDir = cliConfig.WebDir } c.WebDir, err = mkDir(c.WebDir, 0700) if err != nil { return fmt.Errorf("error setting up directory: %v", err) } return nil } func HandleConfig() (*Config, error) { config := newConfig() cliConfig := newConfig() if err := cliConfig.handleCliArgs(); err != nil { return nil, fmt.Errorf("error handling cli arguments: %v", err) } err := config.handleFile(cliConfig.ConfigFile) if err != nil { return nil, fmt.Errorf("error reading configuration file: %v", err) } if err = config.setupConfig(cliConfig); err != nil { return nil, fmt.Errorf("error setting up files: %v", err) } return config, nil }