From 1e163bce84c83a1901ad25016604f3c0d9de57a3 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sat, 29 Dec 2018 10:13:04 +0000 Subject: [PATCH] feat: custom branding License: MIT Signed-off-by: Henrique Dias --- cmd/config.go | 8 ++++++++ cmd/config_set.go | 13 +++++++++--- frontend | 2 +- http/static.go | 52 ++++++++++++++++++++++++++++++++++++++++------- types/settings.go | 8 ++++++++ 5 files changed, 72 insertions(+), 11 deletions(-) diff --git a/cmd/config.go b/cmd/config.go index cd2a1d85..e1f973ae 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -38,6 +38,10 @@ func addConfigFlags(cmd *cobra.Command) { cmd.Flags().String("recaptcha.host", "https://www.google.com", "Use another host for ReCAPTCHA. recaptcha.net might be useful in China") cmd.Flags().String("recaptcha.key", "", "ReCaptcha site key") cmd.Flags().String("recaptcha.secret", "", "ReCaptcha secret") + + cmd.Flags().String("branding.name", "", "Replace 'File Browser' by this name") + cmd.Flags().String("branding.files", "", "Path to directory with images and custom styles") + cmd.Flags().Bool("branding.disableExternal", false, "Disable external links such as GitHub links") } func getAuthentication(cmd *cobra.Command) (types.AuthMethod, types.Auther) { @@ -87,6 +91,10 @@ func printSettings(s *types.Settings, auther types.Auther) { fmt.Fprintf(w, "\nBase URL:\t%s\n", s.BaseURL) fmt.Fprintf(w, "Sign up:\t%t\n", s.Signup) fmt.Fprintf(w, "Auth method:\t%s\n", s.AuthMethod) + fmt.Fprintln(w, "\nBranding:") + fmt.Fprintf(w, "\tName:\t%s\n", s.Branding.Name) + fmt.Fprintf(w, "\tFiles override:\t%s\n", s.Branding.Files) + fmt.Fprintf(w, "\tDisable external links:\t%t\n", s.Branding.DisableExternal) fmt.Fprintln(w, "\nDefaults:") fmt.Fprintf(w, "\tScope:\t%s\n", s.Defaults.Scope) fmt.Fprintf(w, "\tLocale:\t%s\n", s.Defaults.Locale) diff --git a/cmd/config_set.go b/cmd/config_set.go index 66448ba6..099fd56b 100644 --- a/cmd/config_set.go +++ b/cmd/config_set.go @@ -28,12 +28,19 @@ you want to change.`, auth := false cmd.Flags().Visit(func(flag *pflag.Flag) { - if flag.Name == "baseURL" { + switch flag.Name { + case "baseURL": s.BaseURL = mustGetString(cmd, "baseURL") - } else if flag.Name == "signup" { + case "signup": s.Signup = mustGetBool(cmd, "signup") - } else if flag.Name == "auth.method" { + case "auth.method": auth = true + case "branding.name": + s.Branding.Name = mustGetString(cmd, "branding.name") + case "branding.disableExternal": + s.Branding.DisableExternal = mustGetBool(cmd, "branding.disableExternal") + case "branding.files": + s.Branding.Files = mustGetString(cmd, "branding.files") } }) diff --git a/frontend b/frontend index b9dc7e02..82abdaf3 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit b9dc7e02e718b39c6b12e6946c7ce01b1b08890f +Subproject commit 82abdaf3900aae349f172cc1f5494fa5b6e72a02 diff --git a/http/static.go b/http/static.go index 211057dc..69eda896 100644 --- a/http/static.go +++ b/http/static.go @@ -1,7 +1,11 @@ package http import ( + "encoding/json" + "log" "net/http" + "os" + "path/filepath" "strings" "text/template" @@ -16,14 +20,32 @@ func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { baseURL := strings.TrimSuffix(e.Settings.BaseURL, "/") staticURL := strings.TrimPrefix(baseURL+"/static", "/") + cssFile := "" // TODO: baseurl must always not have the trailing slash data := map[string]interface{}{ - "BaseURL": baseURL, - "Version": types.Version, - "StaticURL": staticURL, - "Signup": e.Settings.Signup, - "ReCaptcha": false, + "Name": e.Settings.Branding.Name, + "DisableExternal": e.Settings.Branding.DisableExternal, + "BaseURL": baseURL, + "Version": types.Version, + "StaticURL": staticURL, + "Signup": e.Settings.Signup, + "CSS": false, + "ReCaptcha": false, + } + + if e.Settings.Branding.Files != "" { + path := filepath.Join(e.Settings.Branding.Files, "custom.css") + _, err := os.Stat(path) + + if err != nil && !os.IsNotExist(err) { + log.Printf("couldn't load custom styles: %v", err) + } + + if err == nil { + cssFile = path + data["CSS"] = true + } } if e.Settings.AuthMethod == auth.MethodJSONAuth { @@ -36,6 +58,9 @@ func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { } } + b, _ := json.MarshalIndent(data, "", " ") + data["Json"] = string(b) + handleWithData := func(w http.ResponseWriter, r *http.Request, file string, contentType string) { w.Header().Set("Content-Type", contentType) index := template.Must(template.New("index").Delims("[{[", "]}]").Parse(box.MustString(file))) @@ -58,13 +83,26 @@ func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { handleWithData(w, r, "index.html", "text/html; charset=utf-8") }) - static := http.StripPrefix("/static", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + static := http.StripPrefix("/static/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if e.Settings.Branding.Files != "" { + if strings.HasPrefix(r.URL.Path, "img/") { + path := filepath.Join(e.Settings.Branding.Files, r.URL.Path) + if _, err := os.Stat(path); err == nil { + http.ServeFile(w, r, path) + return + } + } else if r.URL.Path == "custom.css" && cssFile != "" { + http.ServeFile(w, r, cssFile) + return + } + } + if !strings.HasSuffix(r.URL.Path, ".js") { handler.ServeHTTP(w, r) return } - handleWithData(w, r, strings.TrimPrefix(r.URL.Path, "/"), "application/javascript; charset=utf-8") + handleWithData(w, r, r.URL.Path, "application/javascript; charset=utf-8") })) return index, static diff --git a/types/settings.go b/types/settings.go index 66fd178d..9d8488e2 100644 --- a/types/settings.go +++ b/types/settings.go @@ -10,6 +10,14 @@ type Settings struct { Signup bool `json:"signup"` Defaults UserDefaults `json:"defaults"` AuthMethod AuthMethod `json:"authMethod"` + Branding Branding `json:"Branding"` +} + +// Branding contains the branding settings of the app. +type Branding struct { + Name string `json:"name"` + DisableExternal bool `json:"disableExternal"` + Files string `json:"string"` } // UserDefaults is a type that holds the default values