package backend import ( "flag" "fmt" "io/fs" "os" "path/filepath" "strings" "github.com/BurntSushi/toml" ) type Config struct { ArticleDir string ConfigFile string DBName string Description string Domain string FirebaseKey string KeyFile string Link string LogFile string PDFDir string PicsDir string Port string RSSFile string Title string WebDir string } func newConfig() *Config { return &Config{ ArticleDir: "/var/www/cpolis/articles", ConfigFile: "/etc/cpolis/config.toml", DBName: "cpolis", FirebaseKey: "/var/www/cpolis/serviceAccountKey.json", KeyFile: "/var/www/cpolis/cpolis.key", LogFile: "/var/log/cpolis.log", PDFDir: "/var/www/cpolis/pdfs", PicsDir: "/var/www/cpolis/pics", Port: ":8080", RSSFile: "/var/www/cpolis/cpolis.rss", 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.ArticleDir, "articles", c.ArticleDir, "articles directory") 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.KeyFile, "key", c.KeyFile, "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.RSSFile, "rss", c.RSSFile, "RSS file") flag.StringVar(&c.Title, "title", c.Title, "channel title") flag.StringVar(&c.WebDir, "web", c.WebDir, "web directory") flag.IntVar(&port, "port", port, "port") flag.Parse() 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.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 } 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.KeyFile != defaultConfig.KeyFile { c.KeyFile = cliConfig.KeyFile } c.KeyFile, err = mkFile(c.KeyFile, 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.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.RSSFile != defaultConfig.RSSFile { c.RSSFile = cliConfig.RSSFile } c.RSSFile, err = mkFile(c.RSSFile, 0600, 0700) if err != nil { return fmt.Errorf("error setting up file: %v", err) } 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 }