diff --git a/api/config.go b/api/config.go index 596a7ff..7b8c963 100644 --- a/api/config.go +++ b/api/config.go @@ -2,9 +2,17 @@ package main import ( "os" + "strings" + "path/filepath" ) func parseConfig() error { + binPath, err := filepath.Abs(filepath.Dir(os.Args[0])) + if err != nil { + logger.Fatalf("cannot load binary path: %v", err) + return err + } + defaults := map[string]string{ "POSTGRES": "postgres://postgres:postgres@localhost/commento?sslmode=disable", @@ -13,6 +21,8 @@ func parseConfig() error { "CDN_PREFIX": "", + "STATIC": binPath, + "SMTP_USERNAME": "", "SMTP_PASSWORD": "", "SMTP_HOST": "", @@ -42,5 +52,23 @@ func parseConfig() error { os.Setenv("CDN_PREFIX", os.Getenv("ORIGIN")) } + static := os.Getenv("STATIC") + for strings.HasSuffix(static, "/") { + static = static[0:len(static)-1] + } + + file, err := os.Stat(static) + if err != nil { + logger.Errorf("cannot load %s: %v", static, err) + return err + } + + if !file.IsDir() { + logger.Errorf("COMMENTO_STATIC=%s is not a directory", static) + return errorNotADirectory + } + + os.Setenv("STATIC", static) + return nil } diff --git a/api/config_test.go b/api/config_test.go index ae0d477..0bfb378 100644 --- a/api/config_test.go +++ b/api/config_test.go @@ -3,6 +3,7 @@ package main import ( "os" "testing" + "path/filepath" ) func TestParseConfigBasics(t *testing.T) { @@ -31,3 +32,55 @@ func TestParseConfigBasics(t *testing.T) { return } } + +func TestParseConfigStatic(t *testing.T) { + os.Setenv("COMMENTO_ORIGIN", "https://commento.io") + + if err := parseConfig(); err != nil { + t.Errorf("unexpected error when parsing config: %v", err) + return + } + + binPath, err := filepath.Abs(filepath.Dir(os.Args[0])) + if err != nil { + t.Errorf("cannot load binary path: %v", err) + return + } + + if os.Getenv("STATIC") != binPath { + t.Errorf("COMMENTO_STATIC != %s when unset", binPath) + return + } + + os.Setenv("COMMENTO_STATIC", "/usr/") + + if err := parseConfig(); err != nil { + t.Errorf("unexpected error when parsing config: %v", err) + return + } + + if os.Getenv("STATIC") != "/usr" { + t.Errorf("COMMENTO_STATIC != /usr when unset") + return + } +} + +func TestParseConfigStaticDNE(t *testing.T) { + os.Setenv("COMMENTO_ORIGIN", "https://commento.io") + os.Setenv("COMMENTO_STATIC", "/does/not/exist/surely/") + + if err := parseConfig(); err == nil { + t.Errorf("expected error not found when a non-existant directory is used") + return + } +} + +func TestParseConfigStaticNotADirectory(t *testing.T) { + os.Setenv("COMMENTO_ORIGIN", "https://commento.io") + os.Setenv("COMMENTO_STATIC", os.Args[0]) + + if err := parseConfig(); err != errorNotADirectory { + t.Errorf("expected error not found when a file is used") + return + } +} diff --git a/api/database_migrations.go b/api/database_migrations.go index 3d385b9..1d48d49 100644 --- a/api/database_migrations.go +++ b/api/database_migrations.go @@ -7,7 +7,7 @@ import ( ) func performMigrations() error { - return performMigrationsFromDir("db") + return performMigrationsFromDir(os.Getenv("STATIC") + "/db") } func performMigrationsFromDir(dir string) error { diff --git a/api/errors.go b/api/errors.go index b8ba5bc..f53a54f 100644 --- a/api/errors.go +++ b/api/errors.go @@ -43,3 +43,4 @@ var errorUnassociatedSession = errors.New("No user associated with that session. var errorSessionAlreadyInUse = errors.New("Session is already in use.") var errorCannotReadResponse = errors.New("Cannot read response.") var errorNotModerator = errors.New("You need to be a moderator to do that.") +var errorNotADirectory = errors.New("The given path is not a directory.") diff --git a/api/router_static.go b/api/router_static.go index 772a118..45c048f 100644 --- a/api/router_static.go +++ b/api/router_static.go @@ -28,24 +28,26 @@ func initStaticRouter(router *mux.Router) error { asset := make(map[string]string) for _, dir := range []string{"js", "css", "images"} { - files, err := ioutil.ReadDir("./" + dir) + sl := string(os.PathSeparator) + dir = sl + dir + + files, err := ioutil.ReadDir(os.Getenv("STATIC") + dir) if err != nil { - logger.Errorf("cannot read directory ./%s: %v", dir, err) + logger.Errorf("cannot read directory %s%s: %v", os.Getenv("STATIC"), dir, err) return err } for _, file := range files { - sl := string(os.PathSeparator) - p := sl + dir + sl + file.Name() + p := dir + sl + file.Name() - contents, err := ioutil.ReadFile("." + p) + contents, err := ioutil.ReadFile(os.Getenv("STATIC") + p) if err != nil { - logger.Errorf("cannot read file %s: %v", p, err) + logger.Errorf("cannot read file %s%s: %v", os.Getenv("STATIC"), p, err) return err } prefix := "" - if dir == "js" { + if dir == "/js" { prefix = "window.commento_origin='" + os.Getenv("ORIGIN") + "';\n" prefix += "window.commento_cdn='" + os.Getenv("CDN_PREFIX") + "';\n" } @@ -69,22 +71,26 @@ func initStaticRouter(router *mux.Router) error { html := make(map[string]string) for _, page := range pages { - contents, err := ioutil.ReadFile(page + ".html") + sl := string(os.PathSeparator) + page = sl + page + file := page + ".html" + + contents, err := ioutil.ReadFile(os.Getenv("STATIC") + file) if err != nil { - logger.Errorf("cannot read file %s.html: %v", page, err) + logger.Errorf("cannot read file %s%s: %v", os.Getenv("STATIC"), file, err) return err } t, err := template.New(page).Delims("<<<", ">>>").Parse(string(contents)) if err != nil { - logger.Errorf("cannot parse /%s template: %v", page, err) + logger.Errorf("cannot parse %s%s template: %v", os.Getenv("STATIC"), file, err) return err } var buf bytes.Buffer t.Execute(&buf, &staticHtmlPlugs{CdnPrefix: os.Getenv("CDN_PREFIX")}) - html["/" + page] = buf.String() + html[page] = buf.String() } for _, page := range pages { diff --git a/api/smtp_templates.go b/api/smtp_templates.go index 2889121..1f42f15 100644 --- a/api/smtp_templates.go +++ b/api/smtp_templates.go @@ -1,6 +1,7 @@ package main import ( + "os" "fmt" "html/template" ) @@ -38,9 +39,9 @@ Subject: {{.Subject}} for _, name := range names { var err error templates[name] = template.New(name) - templates[name], err = template.ParseFiles(fmt.Sprintf("email/%s.html", name)) + templates[name], err = template.ParseFiles(fmt.Sprintf("%s/templates/%s.html", os.Getenv("COMMENTO_STATIC"), name)) if err != nil { - logger.Fatalf("cannot parse %s.html: %v\n", name, err) + logger.Fatalf("cannot parse %s/templates/%s.html: %v", os.Getenv("STATIC"), name, err) return errorMalformedTemplate } }