diff --git a/.air.toml b/.air.toml index 2157d00..612e376 100644 --- a/.air.toml +++ b/.air.toml @@ -5,8 +5,10 @@ tmp_dir = "tmp" [build] args_bin = [ "-articles tmp/articles", + "-config tmp/config.toml", "-desc 'Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität'", "-domain localhost", + "-firebase tmp/firebase.json", "-key tmp/key.gob", "-link https://distrikt-ni-st.de", "-log tmp/cpolis.log", diff --git a/cmd/backend/config.go b/cmd/backend/config.go index 416b325..ae39ce8 100644 --- a/cmd/backend/config.go +++ b/cmd/backend/config.go @@ -3,6 +3,7 @@ package backend import ( "flag" "fmt" + "io/fs" "os" "path/filepath" "strings" @@ -12,6 +13,7 @@ import ( type Config struct { ArticleDir string + ConfigFile string DBName string Description string Domain string @@ -30,56 +32,72 @@ type Config struct { 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", + Port: ":8080", PicsDir: "/var/www/cpolis/pics", RSSFile: "/var/www/cpolis/cpolis.rss", WebDir: "/var/www/cpolis/web", } } -func (c *Config) readFile() error { - cfgFile, err := filepath.Abs(os.Getenv("HOME") + "/.config/cpolis/config.toml") +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 getting absolute path for config file: %v", err) + 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) } - _, err = os.Stat(cfgFile) - if os.IsNotExist(err) { - fileStrings := strings.Split(cfgFile, "/") + return path, nil +} - dir := strings.Join(fileStrings[0:len(fileStrings)-1], "/") - if err = os.MkdirAll(dir, 0755); err != nil { - return fmt.Errorf("error creating config directory: %v", err) +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 := fileStrings[len(fileStrings)-1] + fileName := stringSlice[len(stringSlice)-1] file, err := os.Create(dir + "/" + fileName) if err != nil { - return fmt.Errorf("error creating config file: %v", err) + return "", fmt.Errorf("error creating %v: %v", fileName, err) } defer file.Close() - if err = file.Chmod(0644); err != nil { - return fmt.Errorf("error setting permissions for config file: %v", err) - } - } else { - _, err = toml.DecodeFile(cfgFile, c) - if err != nil { - return fmt.Errorf("error reading config file: %v", err) + if err = file.Chmod(filePerm); err != nil { + return "", fmt.Errorf("error setting permissions for %v: %v", fileName, err) } } - return nil + return path, nil } func (c *Config) handleCliArgs() error { + var port int var err error - port := 8080 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") @@ -95,58 +113,114 @@ func (c *Config) handleCliArgs() error { flag.IntVar(&port, "port", port, "port") flag.Parse() - c.ArticleDir, err = filepath.Abs(c.ArticleDir) - if err != nil { - return fmt.Errorf("error finding absolute path for articles directory: %v", err) - } - if err = os.MkdirAll(c.ArticleDir, 0755); err != nil { - return fmt.Errorf("error creating articles directory: %v", err) - } - - c.FirebaseKey, err = filepath.Abs(c.FirebaseKey) - if err != nil { - return fmt.Errorf("error finding absolute path for Firebase service account key file: %v", err) - } - - c.KeyFile, err = filepath.Abs(c.KeyFile) - if err != nil { - return fmt.Errorf("error finding absolute path for key file: %v", err) - } - - c.LogFile, err = filepath.Abs(c.LogFile) - if err != nil { - return fmt.Errorf("error finding absolute path for log file: %v", err) - } - - c.PDFDir, err = filepath.Abs(c.PDFDir) - if err != nil { - return fmt.Errorf("error finding absolute path for pdfs directory: %v", err) - } - if err = os.MkdirAll(c.PDFDir, 0755); err != nil { - return fmt.Errorf("error creating pdfs directory: %v", err) - } - - c.PicsDir, err = filepath.Abs(c.PicsDir) - if err != nil { - return fmt.Errorf("error finding absolute path for pics directory: %v", err) - } - if err = os.MkdirAll(c.PicsDir, 0755); err != nil { - return fmt.Errorf("error creating pics directory: %v", err) - } - c.Port = fmt.Sprint(":", port) - - c.RSSFile, err = filepath.Abs(c.RSSFile) + c.ConfigFile, err = mkFile(c.ConfigFile, 0600, 0700) if err != nil { - return fmt.Errorf("error finding absolute path for RSS file: %v", err) + return fmt.Errorf("error setting up file: %v", err) } - c.WebDir, err = filepath.Abs(c.WebDir) + return nil +} + +func (c *Config) handleFile(configFile string) error { + _, err := toml.DecodeFile(configFile, c) if err != nil { - return fmt.Errorf("error finding absolute path for web directory: %v", err) + return fmt.Errorf("error reading config file: %v", err) } - if err = os.MkdirAll(c.WebDir, 0755); err != nil { - return fmt.Errorf("error creating web directory: %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 @@ -154,13 +228,19 @@ func (c *Config) handleCliArgs() error { func HandleConfig() (*Config, error) { config := newConfig() + cliConfig := newConfig() - if err := config.readFile(); err != nil { - return nil, fmt.Errorf("error reading config file: %v", err) + if err := cliConfig.handleCliArgs(); err != nil { + return nil, fmt.Errorf("error handling cli arguments: %v", err) } - if err := config.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 diff --git a/tailwind.config.js b/tailwind.config.js index 9e17d63..8e50921 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -7,4 +7,5 @@ module.exports = { plugins: [ require('@tailwindcss/typography') ], + darkMode: 'selector', } diff --git a/web/static/css/input.css b/web/static/css/input.css index 0f50437..462eb57 100644 --- a/web/static/css/input.css +++ b/web/static/css/input.css @@ -2,30 +2,21 @@ @tailwind components; @tailwind utilities; -body { - width: 800px; - @apply mx-auto text-slate-900; -} - h2 { @apply font-bold mb-2 text-2xl; } -form { - @apply flex flex-col gap-y-3; -} - -input[type="file"] { - @apply border rounded-md w-full; +h3 { + @apply font-bold mb-2 text-xl; } input[type="password"], input[type="text"] { - @apply border h-8 rounded-md; + @apply bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 h-8 rounded-md; } textarea { - @apply border h-32 rounded-md; + @apply bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 h-32 rounded-md; } .btn-area { @@ -33,9 +24,41 @@ textarea { } .btn { - @apply bg-slate-200 border my-2 px-3 py-2 rounded-md w-full hover:bg-slate-100; + @apply bg-slate-200 dark:bg-slate-800 hover:bg-slate-100 dark:hover:bg-slate-900 border border-slate-200 dark:border-slate-800 my-2 px-3 py-2 rounded-md w-full; } .action-btn { - @apply bg-slate-800 border my-2 px-3 py-2 rounded-md text-slate-50 w-full hover:bg-slate-700; + @apply bg-slate-800 dark:bg-slate-200 hover:bg-slate-700 dark:hover:bg-slate-300 my-2 px-3 py-2 rounded-md text-slate-50 dark:text-slate-950 w-full; +} + +.EasyMDEContainer .CodeMirror { + @apply bg-slate-50 dark:bg-slate-950 border-slate-200 dark:border-slate-800 text-slate-900 dark:text-slate-100 +} + +.EasyMDEContainer .cm-s-easymde .CodeMirror-cursor { + @apply border-slate-900 dark:border-slate-100 +} + +.EasyMDEContainer .editor-toolbar > * { + @apply text-slate-900 dark:text-slate-100 +} + +.EasyMDEContainer .editor-toolbar > .active, .editor-toolbar > button:hover, .editor-preview pre, .cm-s-easymde .cm-comment { + @apply bg-slate-100 dark:bg-slate-900 +} + +.EasyMDEContainer .CodeMirror-fullscreen { + @apply bg-slate-50 dark:bg-slate-950 +} + +.editor-toolbar { + @apply border border-slate-200 +} + +.editor-toolbar.fullscreen { + @apply bg-slate-50 dark:bg-slate-950 +} + +.editor-preview { + @apply bg-slate-50 dark:bg-slate-950 } diff --git a/web/templates/hub.html b/web/templates/hub.html index 19dbf06..451d645 100644 --- a/web/templates/hub.html +++ b/web/templates/hub.html @@ -4,49 +4,49 @@ {{if lt . 4}}