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 AtomFeed string FirebaseKey string KeyFile string Link string LogFile string PDFDir string PicsDir string Port string RSSFile string Title string WebDir string MaxImgHeight int MaxImgWidth int } func newConfig() *Config { return &Config{ ArticleDir: "/var/www/cpolis/articles", ConfigFile: "/etc/cpolis/config.toml", DBName: "cpolis", AtomFeed: "/var/www/cpolis/cpolis.atom", FirebaseKey: "/var/www/cpolis/serviceAccountKey.json", KeyFile: "/var/www/cpolis/cpolis.key", LogFile: "/var/log/cpolis.log", MaxImgHeight: 1080, MaxImgWidth: 1920, 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.AtomFeed, "feed", c.AtomFeed, "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.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(&c.MaxImgHeight, "height", c.MaxImgHeight, "maximum image height") flag.IntVar(&c.MaxImgWidth, "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.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.AtomFeed != defaultConfig.AtomFeed { c.AtomFeed = cliConfig.AtomFeed } c.AtomFeed, err = mkFile(c.AtomFeed, 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.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.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.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 }