From 71803ab1af6294a9d5b6381487654cfc8417aa94 Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Sat, 14 Mar 2020 21:07:14 +0530 Subject: [PATCH] Add support for loading custom static files with `--static-dir` - Removed duplicate copies of static files in `static/public/` --- README.md | 3 + go.mod | 2 +- go.sum | 2 + init.go | 66 ++++++++----- install.go | 2 +- main.go | 13 +-- static/public/base.html | 98 -------------------- static/public/campaign-status.html | 25 ----- static/public/default.tpl | 84 ----------------- static/public/import-status.html | 19 ---- static/public/subscriber-data.html | 9 -- static/public/subscriber-optin-campaign.html | 17 ---- static/public/subscriber-optin.html | 21 ----- 13 files changed, 55 insertions(+), 306 deletions(-) delete mode 100644 static/public/base.html delete mode 100644 static/public/campaign-status.html delete mode 100644 static/public/default.tpl delete mode 100644 static/public/import-status.html delete mode 100644 static/public/subscriber-data.html delete mode 100644 static/public/subscriber-optin-campaign.html delete mode 100644 static/public/subscriber-optin.html diff --git a/README.md b/README.md index 48d1ee4..b0dde79 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ listmonk is a standalone, self-hosted, newsletter and mailing list manager. It i - Run `./listmonk` and visit `http://localhost:9000`. - Since there is no user auth yet, it's best to put listmonk behind a proxy like Nginx and setup basicauth on all endpoints except for the few endpoints that need to be public. Here is a [sample nginx config](https://github.com/knadh/listmonk/wiki/Production-Nginx-config) for production use. +### Configuration and customization +See the [configuration Wiki page](https://github.com/knadh/listmonk/wiki/Configuration). + ### Running on Docker You can pull the official Docker Image from [Docker Hub](https://hub.docker.com/r/listmonk/listmonk). diff --git a/go.mod b/go.mod index c4c9875..aa84956 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/jordan-wright/email v0.0.0-20200307200233-de844847de93 github.com/knadh/goyesql/v2 v2.1.1 github.com/knadh/koanf v0.8.1 - github.com/knadh/stuffbin v1.0.0 + github.com/knadh/stuffbin v1.1.0 github.com/labstack/echo v3.3.10+incompatible github.com/labstack/gommon v0.3.0 // indirect github.com/lib/pq v1.3.0 diff --git a/go.sum b/go.sum index 1d232c4..73f8715 100644 --- a/go.sum +++ b/go.sum @@ -29,6 +29,8 @@ github.com/knadh/koanf v0.8.1 h1:4VLACWqrkWRQIup3ooq6lOnaSbOJSNO+YVXnJn/NPZ8= github.com/knadh/koanf v0.8.1/go.mod h1:kVvmDbXnBtW49Czi4c1M+nnOWF0YSNZ8BaKvE/bCO1w= github.com/knadh/stuffbin v1.0.0 h1:NQon6PTpLXies4bRFhS3VpLCf6y+jn6YVXU3i2wPQ+M= github.com/knadh/stuffbin v1.0.0/go.mod h1:yVCFaWaKPubSNibBsTAJ939q2ABHudJQxRWZWV5yh+4= +github.com/knadh/stuffbin v1.1.0 h1:f5S5BHzZALjuJEgTIOMC9NidEnBJM7Ze6Lu1GHR/lwU= +github.com/knadh/stuffbin v1.1.0/go.mod h1:yVCFaWaKPubSNibBsTAJ939q2ABHudJQxRWZWV5yh+4= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= diff --git a/init.go b/init.go index af86c8c..9c4754a 100644 --- a/init.go +++ b/init.go @@ -29,41 +29,57 @@ const ( // initFileSystem initializes the stuffbin FileSystem to provide // access to bunded static assets to the app. -func initFS() stuffbin.FileSystem { +func initFS(staticDir string) stuffbin.FileSystem { // Get the executable's path. path, err := os.Executable() if err != nil { log.Fatalf("error getting executable path: %v", err) } + // Load the static files stuffed in the binary. fs, err := stuffbin.UnStuff(path) - if err == nil { - return fs - } - - // Running in local mode. Load the required static assets into - // the in-memory stuffbin.FileSystem. - lo.Printf("unable to initialize embedded filesystem: %v", err) - lo.Printf("using local filesystem for static assets") - files := []string{ - "config.toml.sample", - "queries.sql", - "schema.sql", - "static/email-templates", - - // Alias /static/public to /public for the HTTP fileserver. - "static/public:/public", - - // The frontend app's static assets are aliased to /frontend - // so that they are accessible at localhost:port/frontend/static/ ... - "frontend/build:/frontend", - } - - fs, err = stuffbin.NewLocalFS("/", files...) if err != nil { - lo.Fatalf("failed to initialize local file for assets: %v", err) + // Running in local mode. Load local assets into + // the in-memory stuffbin.FileSystem. + lo.Printf("unable to initialize embedded filesystem: %v", err) + lo.Printf("using local filesystem for static assets") + files := []string{ + "config.toml.sample", + "queries.sql", + "schema.sql", + "static/email-templates", + + // Alias /static/public to /public for the HTTP fileserver. + "static/public:/public", + + // The frontend app's static assets are aliased to /frontend + // so that they are accessible at localhost:port/frontend/static/ ... + "frontend/build:/frontend", + } + + fs, err = stuffbin.NewLocalFS("/", files...) + if err != nil { + lo.Fatalf("failed to initialize local file for assets: %v", err) + } } + // Optional static directory to override files. + if staticDir != "" { + lo.Printf("loading static files from: %v", staticDir) + fStatic, err := stuffbin.NewLocalFS("/", []string{ + filepath.Join(staticDir, "/email-templates") + ":/static/email-templates", + + // Alias /static/public to /public for the HTTP fileserver. + filepath.Join(staticDir, "/public") + ":/public", + }...) + if err != nil { + lo.Fatalf("failed reading static directory: %s: %v", staticDir, err) + } + + if err := fs.Merge(fStatic); err != nil { + lo.Fatalf("error merging static directory: %s: %v", staticDir, err) + } + } return fs } diff --git a/install.go b/install.go index b5731e2..7ce85f9 100644 --- a/install.go +++ b/install.go @@ -157,7 +157,7 @@ func newConfigFile() error { // Initialize the static file system into which all // required static assets (.sql, .js files etc.) are loaded. - fs := initFS() + fs := initFS("") b, err := fs.Read("config.toml.sample") if err != nil { return fmt.Errorf("error reading sample config (is binary stuffed?): %v", err) diff --git a/main.go b/main.go index e8a1d7c..5d86fcd 100644 --- a/main.go +++ b/main.go @@ -57,11 +57,12 @@ func init() { // Register the commandline flags. f.StringSlice("config", []string{"config.toml"}, - "Path to one or more config files (will be merged in order)") - f.Bool("install", false, "Run first time installation") - f.Bool("version", false, "Current version of the build") - f.Bool("new-config", false, "Generate sample config file") - f.Bool("yes", false, "Assume 'yes' to prompts, eg: during --install") + "path to one or more config files (will be merged in order)") + f.Bool("install", false, "run first time installation") + f.Bool("version", false, "current version of the build") + f.Bool("new-config", false, "generate sample config file") + f.String("static-dir", "", "(optional) path to directory with static files") + f.Bool("yes", false, "assume 'yes' to prompts, eg: during --install") if err := f.Parse(os.Args[1:]); err != nil { lo.Fatalf("error loading flags: %v", err) @@ -111,7 +112,7 @@ func main() { // Initialize the DB and the filesystem that are required by the installer // and the app. var ( - fs = initFS() + fs = initFS(ko.String("static-dir")) db = initDB() ) defer db.Close() diff --git a/static/public/base.html b/static/public/base.html deleted file mode 100644 index 0f47897..0000000 --- a/static/public/base.html +++ /dev/null @@ -1,98 +0,0 @@ -{{ define "header" }} - - - - - - - - - - -
 
-
-
- {{ if ne LogoURL "" }} - listmonk - {{ end }} -
-{{ end }} - -{{ define "footer" }} -
- - -
 
- - -{{ end }} diff --git a/static/public/campaign-status.html b/static/public/campaign-status.html deleted file mode 100644 index d174c02..0000000 --- a/static/public/campaign-status.html +++ /dev/null @@ -1,25 +0,0 @@ -{{ define "campaign-status" }} -{{ template "header" . }} -

Campaign update

- - - - - - - - - - - - - - {{ if ne (index . "Reason") "" }} - - - - - {{ end }} -
Campaign{{ index . "Name" }}
Status{{ index . "Status" }}
Sent{{ index . "Sent" }} / {{ index . "ToSend" }}
Reason{{ index . "Reason" }}
-{{ template "footer" }} -{{ end }} \ No newline at end of file diff --git a/static/public/default.tpl b/static/public/default.tpl deleted file mode 100644 index 810a42b..0000000 --- a/static/public/default.tpl +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - -
 
-
- {{ template "content" . }} -
- - -
 {{ TrackView }}
- - diff --git a/static/public/import-status.html b/static/public/import-status.html deleted file mode 100644 index 3fa6e08..0000000 --- a/static/public/import-status.html +++ /dev/null @@ -1,19 +0,0 @@ -{{ define "import-status" }} -{{ template "header" . }} -

Import update

- - - - - - - - - - - - - -
File{{ .Name }}
Status{{ .Status }}
Records{{ .Imported }} / {{ .Total }}
-{{ template "footer" }} -{{ end }} \ No newline at end of file diff --git a/static/public/subscriber-data.html b/static/public/subscriber-data.html deleted file mode 100644 index afd8fec..0000000 --- a/static/public/subscriber-data.html +++ /dev/null @@ -1,9 +0,0 @@ -{{ define "subscriber-data" }} -{{ template "header" . }} -

Your data

-

- A copy of all data recorded on you is attached as a file in JSON format. - It can be viewed in a text editor. -

-{{ template "footer" }} -{{ end }} diff --git a/static/public/subscriber-optin-campaign.html b/static/public/subscriber-optin-campaign.html deleted file mode 100644 index fbdaab6..0000000 --- a/static/public/subscriber-optin-campaign.html +++ /dev/null @@ -1,17 +0,0 @@ -{{ define "optin-campaign" }} - -

Hi {{`{{ .Subscriber.FirstName }}`}},

-

You have been added to the following mailing lists:

- -

- Confirm subscription(s) -

-{{ end }} diff --git a/static/public/subscriber-optin.html b/static/public/subscriber-optin.html deleted file mode 100644 index f81bff3..0000000 --- a/static/public/subscriber-optin.html +++ /dev/null @@ -1,21 +0,0 @@ -{{ define "subscriber-optin" }} -{{ template "header" . }} -

Confirm subscription

-

Hi {{ .Subscriber.FirstName }},

-

You have been added to the following mailing lists:

- -

Confirm your subscription by clicking the below button.

-

- Confirm subscription -

- -{{ template "footer" }} -{{ end }}