From bc768ea12fcd230bbbce4b2110b0227bbcfc51fe Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Thu, 31 Aug 2023 17:15:44 -0500 Subject: [PATCH 01/14] updated --- backend/version/version.go | 2 +- frontend/index.html | 192 ++++++ frontend/public/themes/dark.css | 4 + frontend/src/components/Search.vue | 2 +- frontend/src/components/header/HeaderBar.vue | 14 +- frontend/src/views/Layout.vue | 78 +-- frontend/src/views/files/Default.vue | 631 +++++++++++++++++++ 7 files changed, 871 insertions(+), 52 deletions(-) create mode 100644 frontend/index.html create mode 100644 frontend/src/views/files/Default.vue diff --git a/backend/version/version.go b/backend/version/version.go index 03dbd250..99e9b441 100644 --- a/backend/version/version.go +++ b/backend/version/version.go @@ -2,7 +2,7 @@ package version var ( // Version is the current File Browser version. - Version = "(0.1.4)" + Version = "(0.2.0)" // CommitSHA is the commmit sha. CommitSHA = "(unknown)" ) diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 00000000..7d0b8bc9 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,192 @@ + + + + + + + + File Browser + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+
+
+ + + + diff --git a/frontend/public/themes/dark.css b/frontend/public/themes/dark.css index 86ac857c..b76520b0 100644 --- a/frontend/public/themes/dark.css +++ b/frontend/public/themes/dark.css @@ -213,3 +213,7 @@ nav { background: var(--background); color: white } +#result-desktop #result-list { + background: #2a3137; + +} \ No newline at end of file diff --git a/frontend/src/components/Search.vue b/frontend/src/components/Search.vue index 84b18c4b..e67c4e86 100644 --- a/frontend/src/components/Search.vue +++ b/frontend/src/components/Search.vue @@ -211,7 +211,7 @@ border-top: none; border-top-left-radius: 0px; border-top-right-radius: 0px; - background-color: white; + background: white; max-height: 80vh; left: 50%; -webkit-transform: translateX(-50%); diff --git a/frontend/src/components/header/HeaderBar.vue b/frontend/src/components/header/HeaderBar.vue index 8995be9f..f7f8db15 100644 --- a/frontend/src/components/header/HeaderBar.vue +++ b/frontend/src/components/header/HeaderBar.vue @@ -1,24 +1,12 @@ diff --git a/frontend/src/views/files/Default.vue b/frontend/src/views/files/Default.vue new file mode 100644 index 00000000..5993665e --- /dev/null +++ b/frontend/src/views/files/Default.vue @@ -0,0 +1,631 @@ + + + + + From 7aeb2ee4742a01284250623028fcb10d0754879a Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Thu, 31 Aug 2023 17:17:05 -0500 Subject: [PATCH 02/14] updated --- frontend/index.html | 192 -------------------------------------------- 1 file changed, 192 deletions(-) delete mode 100644 frontend/index.html diff --git a/frontend/index.html b/frontend/index.html deleted file mode 100644 index 7d0b8bc9..00000000 --- a/frontend/index.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - - File Browser - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
-
-
-
-
- - - - From 4cda1d1c63dfafb4ed5b8289f11978fdf7fb5912 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Thu, 31 Aug 2023 17:32:57 -0500 Subject: [PATCH 03/14] updated --- frontend/src/views/Layout.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/Layout.vue b/frontend/src/views/Layout.vue index 9dd1270d..3a4e7cb4 100644 --- a/frontend/src/views/Layout.vue +++ b/frontend/src/views/Layout.vue @@ -80,4 +80,4 @@ export default { }, }, }; - + \ No newline at end of file From 736489b577e31e24684900cce65d7f2742c5a854 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Thu, 31 Aug 2023 18:28:34 -0500 Subject: [PATCH 04/14] updated --- CHANGELOG.md | 4 +- backend/.filebrowser.json | 10 --- backend/filebrowser.yml | 35 ++++++++ backend/render.yml | 0 frontend/src/components/Shell.vue | 125 --------------------------- frontend/src/css/styles.css | 1 - frontend/src/views/Layout.vue | 9 +- frontend/src/views/files/Default.vue | 1 - frontend/src/views/files/Listing.vue | 1 - 9 files changed, 41 insertions(+), 145 deletions(-) delete mode 100644 backend/.filebrowser.json create mode 100644 backend/filebrowser.yml delete mode 100644 backend/render.yml delete mode 100644 frontend/src/components/Shell.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index 903a3ff7..f40eb49e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ All notable changes to this project will be documented in this file. See [standa - Works with new more advanced filebrowser.json - improved GUI - more unified coehisive look - - + - The shell is dead. + - If you need to use the shell, exec into the docker container. + - All configuration is done via filebrowser.yml # v0.1.4 - various UI fixes diff --git a/backend/.filebrowser.json b/backend/.filebrowser.json deleted file mode 100644 index 33b9a3dd..00000000 --- a/backend/.filebrowser.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - - "port": 8080, - "baseURL": "", - "address": "", - "log": "stdout", - "database": "./database.db", - "root": "/srv" - -} \ No newline at end of file diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml new file mode 100644 index 00000000..efd76980 --- /dev/null +++ b/backend/filebrowser.yml @@ -0,0 +1,35 @@ +server: + port: 8080 + baseURL: /files + address: '' + log: stdout + database: ./database.db + root: /srv + disable-thumbnails: false + disable-preview-resize: false + disable-exec: false + disable-type-detection-by-header: false +auth: + header: '' + method: '' + command: '' + signup: false + shell: '' +branding: + name: '' + color: '' + files: '' + disableExternal: '' + disableUsedPercentage: '' +permissions: + Admin: false + Execute: true + Create: true + Rename: true + Modify: true + Delete: true + Share: true + Download: true +commands: +shell: +rules: diff --git a/backend/render.yml b/backend/render.yml deleted file mode 100644 index e69de29b..00000000 diff --git a/frontend/src/components/Shell.vue b/frontend/src/components/Shell.vue deleted file mode 100644 index 47c3d67c..00000000 --- a/frontend/src/components/Shell.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - diff --git a/frontend/src/css/styles.css b/frontend/src/css/styles.css index 723bbf4e..14059978 100644 --- a/frontend/src/css/styles.css +++ b/frontend/src/css/styles.css @@ -4,7 +4,6 @@ @import "./_variables.css"; @import "./_buttons.css"; @import "./_inputs.css"; -@import "./_shell.css"; @import "./_share.css"; @import "./fonts.css"; @import "./base.css"; diff --git a/frontend/src/views/Layout.vue b/frontend/src/views/Layout.vue index 3a4e7cb4..81b0e825 100644 --- a/frontend/src/views/Layout.vue +++ b/frontend/src/views/Layout.vue @@ -10,7 +10,6 @@
-
@@ -22,12 +21,11 @@ import editorBar from "./files/Editor.vue" import defaultBar from "./files/Default.vue" import listingBar from"./files/Listing.vue" import previewBar from "./files/Preview.vue" -import Action from "@/components/header/Action.vue"; +import Prompts from "@/components/prompts/Prompts"; +import Action from "@/components/header/Action"; import { mapState, mapGetters } from "vuex"; import Sidebar from "@/components/Sidebar.vue"; -import Prompts from "@/components/header/Action.vue"; -import Shell from "@/components/Shell.vue"; -import UploadFiles from "../components/prompts/UploadFiles.vue"; +import UploadFiles from "../components/prompts/UploadFiles"; import { enableExec } from "@/utils/constants"; export default { @@ -40,7 +38,6 @@ export default { Action, Sidebar, Prompts, - Shell, UploadFiles, }, data: function () { diff --git a/frontend/src/views/files/Default.vue b/frontend/src/views/files/Default.vue index 5993665e..61736c37 100644 --- a/frontend/src/views/files/Default.vue +++ b/frontend/src/views/files/Default.vue @@ -128,7 +128,6 @@ export default { select: this.selectedCount > 0, upload: this.user.perm.create && this.selectedCount > 0, download: this.user.perm.download && this.selectedCount > 0, - shell: this.user.perm.execute && enableExec, delete: this.selectedCount > 0 && this.user.perm.delete, rename: this.selectedCount === 1 && this.user.perm.rename, share: this.selectedCount === 1 && this.user.perm.share, diff --git a/frontend/src/views/files/Listing.vue b/frontend/src/views/files/Listing.vue index 4b635654..932c6daa 100644 --- a/frontend/src/views/files/Listing.vue +++ b/frontend/src/views/files/Listing.vue @@ -301,7 +301,6 @@ export default { select: this.selectedCount > 0, upload: this.user.perm.create && this.selectedCount > 0, download: this.user.perm.download && this.selectedCount > 0, - shell: this.user.perm.execute && enableExec, delete: this.selectedCount > 0 && this.user.perm.delete, rename: this.selectedCount === 1 && this.user.perm.rename, share: this.selectedCount === 1 && this.user.perm.share, From d0cca8f285e635631b07b890480d3b501c673a0a Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 09:00:02 -0500 Subject: [PATCH 05/14] updated auth method --- backend/.filebrowser.json | 8 ++ backend/cmd/config.go | 57 +++----- backend/cmd/config_cat.go | 2 +- backend/cmd/config_export.go | 2 +- backend/cmd/config_import.go | 3 +- backend/cmd/config_init.go | 32 +---- backend/cmd/config_set.go | 32 ++--- backend/cmd/root.go | 162 ++++------------------ backend/filebrowser.yml | 12 +- backend/go.mod | 5 + backend/go.sum | 19 +++ backend/http/auth.go | 2 +- backend/http/settings.go | 6 +- backend/http/static.go | 32 ++--- backend/settings/config.go | 50 +++++++ backend/settings/settings.go | 4 + backend/settings/structs.go | 32 +++-- backend/storage/bolt/config.go | 6 +- backend/storage/bolt/importer/conf.go | 10 +- backend/storage/bolt/importer/importer.go | 2 + 20 files changed, 206 insertions(+), 272 deletions(-) create mode 100644 backend/.filebrowser.json create mode 100644 backend/settings/config.go diff --git a/backend/.filebrowser.json b/backend/.filebrowser.json new file mode 100644 index 00000000..40e89fbb --- /dev/null +++ b/backend/.filebrowser.json @@ -0,0 +1,8 @@ +{ + "port": 5555, + "baseURL": "", + "address": "", + "log": "stdout", + "database": "./database.db", + "root": "/srv" +} \ No newline at end of file diff --git a/backend/cmd/config.go b/backend/cmd/config.go index b93563b9..a8d9211d 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -28,7 +28,6 @@ var configCmd = &cobra.Command{ } func addConfigFlags(flags *pflag.FlagSet) { - addServerFlags(flags) addUserFlags(flags) flags.BoolP("signup", "s", false, "allow users to signup") flags.String("shell", "", "shell command to which other commands should be appended") @@ -41,38 +40,20 @@ func addConfigFlags(flags *pflag.FlagSet) { flags.String("recaptcha.key", "", "ReCaptcha site key") flags.String("recaptcha.secret", "", "ReCaptcha secret") - flags.String("branding.name", "", "replace 'File Browser' by this name") - flags.String("branding.color", "", "set the theme color") - flags.String("branding.files", "", "path to directory with images and custom styles") - flags.Bool("branding.disableExternal", false, "disable external links such as GitHub links") - flags.Bool("branding.disableUsedPercentage", false, "disable used disk percentage graph") + flags.String("frontend.name", "", "replace 'File Browser' by this name") + flags.String("frontend.color", "", "set the theme color") + flags.String("frontend.files", "", "path to directory with images and custom styles") + flags.Bool("frontend.disableExternal", false, "disable external links such as GitHub links") + flags.Bool("frontend.disableUsedPercentage", false, "disable used disk percentage graph") } //nolint:gocyclo -func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (string, auth.Auther) { - method := mustGetString(flags, "auth.method") - +func getAuthentication() (string, auth.Auther) { + method := settings.GlobalConfiguration.Auth.Method var defaultAuther map[string]interface{} - if len(defaults) > 0 { - if hasAuth := defaults[0]; hasAuth != true { - for _, arg := range defaults { - switch def := arg.(type) { - case *settings.Settings: - method = def.AuthMethod - case auth.Auther: - ms, err := json.Marshal(def) - checkErr(err) - err = json.Unmarshal(ms, &defaultAuther) - checkErr(err) - } - } - } - } - var auther auth.Auther if method == auth.MethodProxyAuth { - header := mustGetString(flags, "auth.header") - + header := settings.GlobalConfiguration.Auth.Header if header == "" { header = defaultAuther["header"].(string) } @@ -90,9 +71,9 @@ func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (string, a if method == auth.MethodJSONAuth { jsonAuth := &auth.JSONAuth{} - host := mustGetString(flags, "recaptcha.host") - key := mustGetString(flags, "recaptcha.key") - secret := mustGetString(flags, "recaptcha.secret") + host := settings.GlobalConfiguration.Auth.Recaptcha.Host + key := settings.GlobalConfiguration.Auth.Recaptcha.Key + secret := settings.GlobalConfiguration.Auth.Recaptcha.Secret if key == "" { if kmap, ok := defaultAuther["recaptcha"].(map[string]interface{}); ok { @@ -117,7 +98,7 @@ func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (string, a } if method == auth.MethodHookAuth { - command := mustGetString(flags, "auth.command") + command := settings.GlobalConfiguration.Auth.Command if command == "" { command = defaultAuther["command"].(string) @@ -142,14 +123,14 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup) fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir) - fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod) + fmt.Fprintf(w, "Auth method:\t%s\n", set.Auth.Method) fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " ")) - fmt.Fprintln(w, "\nBranding:") - fmt.Fprintf(w, "\tName:\t%s\n", set.Branding.Name) - fmt.Fprintf(w, "\tFiles override:\t%s\n", set.Branding.Files) - fmt.Fprintf(w, "\tDisable external links:\t%t\n", set.Branding.DisableExternal) - fmt.Fprintf(w, "\tDisable used disk percentage graph:\t%t\n", set.Branding.DisableUsedPercentage) - fmt.Fprintf(w, "\tColor:\t%s\n", set.Branding.Color) + fmt.Fprintln(w, "\nFrontend:") + fmt.Fprintf(w, "\tName:\t%s\n", set.Frontend.Name) + fmt.Fprintf(w, "\tFiles override:\t%s\n", set.Frontend.Files) + fmt.Fprintf(w, "\tDisable external links:\t%t\n", set.Frontend.DisableExternal) + fmt.Fprintf(w, "\tDisable used disk percentage graph:\t%t\n", set.Frontend.DisableUsedPercentage) + fmt.Fprintf(w, "\tColor:\t%s\n", set.Frontend.Color) fmt.Fprintln(w, "\nServer:") fmt.Fprintf(w, "\tLog:\t%s\n", ser.Log) fmt.Fprintf(w, "\tPort:\t%s\n", ser.Port) diff --git a/backend/cmd/config_cat.go b/backend/cmd/config_cat.go index eca56dd1..3f06eb9f 100644 --- a/backend/cmd/config_cat.go +++ b/backend/cmd/config_cat.go @@ -18,7 +18,7 @@ var configCatCmd = &cobra.Command{ checkErr(err) ser, err := d.store.Settings.GetServer() checkErr(err) - auther, err := d.store.Auth.Get(set.AuthMethod) + auther, err := d.store.Auth.Get(set.Auth.Method) checkErr(err) printSettings(ser, set, auther) }, pythonConfig{}), diff --git a/backend/cmd/config_export.go b/backend/cmd/config_export.go index 9d6450f9..a4d8ecff 100644 --- a/backend/cmd/config_export.go +++ b/backend/cmd/config_export.go @@ -22,7 +22,7 @@ and imported again with 'config import' command.`, server, err := d.store.Settings.GetServer() checkErr(err) - auther, err := d.store.Auth.Get(settings.AuthMethod) + auther, err := d.store.Auth.Get(settings.Auth.Method) checkErr(err) data := &settingsFile{ diff --git a/backend/cmd/config_import.go b/backend/cmd/config_import.go index 98309612..800b0512 100644 --- a/backend/cmd/config_import.go +++ b/backend/cmd/config_import.go @@ -43,7 +43,6 @@ The path must be for a json or yaml file.`, } else { key = generateKey() } - file := settingsFile{} err := unmarshal(args[0], &file) checkErr(err) @@ -63,7 +62,7 @@ The path must be for a json or yaml file.`, } var auther auth.Auther - switch file.Settings.AuthMethod { + switch file.Settings.Auth.Method { case auth.MethodJSONAuth: auther = getAuther(auth.JSONAuth{}, rawAuther).(*auth.JSONAuth) case auth.MethodNoAuth: diff --git a/backend/cmd/config_init.go b/backend/cmd/config_init.go index 4f3b4050..47bf8df7 100644 --- a/backend/cmd/config_init.go +++ b/backend/cmd/config_init.go @@ -26,33 +26,9 @@ override the options.`, defaults := settings.UserDefaults{} flags := cmd.Flags() getUserDefaults(flags, &defaults, true) - authMethod, auther := getAuthentication(flags) - - s := &settings.Settings{ - Key: generateKey(), - Signup: mustGetBool(flags, "signup"), - Shell: convertCmdStrToCmdArray(mustGetString(flags, "shell")), - AuthMethod: authMethod, - Defaults: defaults, - Branding: settings.Branding{ - Name: mustGetString(flags, "branding.name"), - DisableExternal: mustGetBool(flags, "branding.disableExternal"), - DisableUsedPercentage: mustGetBool(flags, "branding.DisableUsedPercentage"), - Files: mustGetString(flags, "branding.files"), - }, - } - - ser := &settings.Server{ - Address: mustGetString(flags, "address"), - Socket: mustGetString(flags, "socket"), - Root: mustGetString(flags, "root"), - BaseURL: mustGetString(flags, "baseurl"), - TLSKey: mustGetString(flags, "key"), - TLSCert: mustGetString(flags, "cert"), - Port: mustGetString(flags, "port"), - Log: mustGetString(flags, "log"), - } - err := d.store.Settings.Save(s) + _, auther := getAuthentication() + ser := &settings.GlobalConfiguration.Server + err := d.store.Settings.Save(&settings.GlobalConfiguration) checkErr(err) err = d.store.Settings.SaveServer(ser) checkErr(err) @@ -64,6 +40,6 @@ Congratulations! You've set up your database to use with File Browser. Now add your first user via 'filebrowser users add' and then you just need to call the main command to boot up the server. `) - printSettings(ser, s, auther) + printSettings(ser, &settings.GlobalConfiguration, auther) }, pythonConfig{noDB: true}), } diff --git a/backend/cmd/config_set.go b/backend/cmd/config_set.go index 5a02288f..d7bb80d9 100644 --- a/backend/cmd/config_set.go +++ b/backend/cmd/config_set.go @@ -24,7 +24,6 @@ you want to change. Other options will remain unchanged.`, ser, err := d.store.Settings.GetServer() checkErr(err) - hasAuth := false flags.Visit(func(flag *pflag.Flag) { switch flag.Name { case "baseurl": @@ -40,37 +39,30 @@ you want to change. Other options will remain unchanged.`, case "address": ser.Address = mustGetString(flags, flag.Name) case "port": - ser.Port = mustGetString(flags, flag.Name) + ser.Port = 8080 case "log": ser.Log = mustGetString(flags, flag.Name) case "signup": set.Signup = mustGetBool(flags, flag.Name) - case "auth.method": - hasAuth = true case "shell": set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name)) - case "branding.name": - set.Branding.Name = mustGetString(flags, flag.Name) - case "branding.color": - set.Branding.Color = mustGetString(flags, flag.Name) - case "branding.disableExternal": - set.Branding.DisableExternal = mustGetBool(flags, flag.Name) - case "branding.disableUsedPercentage": - set.Branding.DisableUsedPercentage = mustGetBool(flags, flag.Name) - case "branding.files": - set.Branding.Files = mustGetString(flags, flag.Name) + case "frontend.name": + set.Frontend.Name = mustGetString(flags, flag.Name) + case "frontend.color": + set.Frontend.Color = mustGetString(flags, flag.Name) + case "frontend.disableExternal": + set.Frontend.DisableExternal = mustGetBool(flags, flag.Name) + case "frontend.disableUsedPercentage": + set.Frontend.DisableUsedPercentage = mustGetBool(flags, flag.Name) + case "frontend.files": + set.Frontend.Files = mustGetString(flags, flag.Name) } }) getUserDefaults(flags, &set.Defaults, false) // read the defaults - auther, err := d.store.Auth.Get(set.AuthMethod) - checkErr(err) - - // check if there are new flags for existing auth method - set.AuthMethod, auther = getAuthentication(flags, hasAuth, set, auther) - + _, auther := getAuthentication() err = d.store.Auth.Save(auther) checkErr(err) err = d.store.Settings.Save(set) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index 9191df22..ca31422d 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -2,7 +2,6 @@ package cmd import ( "crypto/tls" - "errors" "io" "io/fs" "log" @@ -10,7 +9,6 @@ import ( "net/http" "os" "os/signal" - "path/filepath" "strconv" "strings" "syscall" @@ -57,55 +55,19 @@ func init() { flags.Bool("noauth", false, "use the noauth auther when using quick setup") flags.String("username", "admin", "username for the first user when using quick config") flags.String("password", "", "hashed password for the first user when using quick config (default \"admin\")") - - addServerFlags(flags) -} - -func getEnvVariableAsUint32(key string) uint32 { - valueStr := os.Getenv(key) - value, err := strconv.ParseUint(valueStr, 10, 32) - if err != nil { - return 5 // default value every 5 minutes - } - return uint32(value) -} - -func addServerFlags(flags *pflag.FlagSet) { - flags.StringP("address", "a", "127.0.0.1", "address to listen on") - flags.StringP("log", "l", "stdout", "log output") - flags.StringP("port", "p", "8080", "port to listen on") - flags.StringP("cert", "t", "", "tls certificate") - flags.StringP("key", "k", "", "tls key") - flags.StringP("root", "r", ".", "root to prepend to relative paths") - flags.String("socket", "", "socket to listen to (cannot be used with address, port, cert nor key flags)") - flags.Uint32("socket-perm", 0666, "unix socket file permissions") //nolint:gomnd - flags.StringP("baseurl", "b", "", "base url") - flags.String("cache-dir", "", "file cache directory (disabled if empty)") - flags.Int("img-processors", 4, "image processors count") //nolint:gomnd - flags.Bool("disable-thumbnails", false, "disable image thumbnails") - flags.Bool("disable-preview-resize", true, "disable resize of image previews") - flags.Bool("disable-exec", false, "disables Command Runner feature") - flags.Bool("disable-type-detection-by-header", false, "disables type detection by reading file headers") } var rootCmd = &cobra.Command{ Use: "filebrowser", Short: "A stylish web-based file browser", - Long: `File Browser CLI lets you create the database to use with File Browser, -manage your users and all the configurations without acessing the -web interface. - + Long: ` If you've never run File Browser, you'll need to have a database for it. Don't worry: you don't need to setup a separate database server. We're using Bolt DB which is a single file database and all managed by ourselves. -For this specific command, all the flags you have available (except -"config" for the configuration file), can be given either through -environment variables or configuration files. - If you don't set "config", it will look for a configuration file called -.filebrowser.{json, toml, yaml, yml} in the following directories: +filebrowser.{json, toml, yaml, yml} in the following directories: - ./ - $HOME/ @@ -119,70 +81,60 @@ The precedence of the configuration values are as follows: - database values - defaults -The environment variables are prefixed by "FB_" followed by the option -name in caps. So to set "database" via an env variable, you should -set FB_DATABASE. - Also, if the database path doesn't exist, File Browser will enter into the quick setup mode and a new database will be bootstraped and a new user created with the credentials from options "username" and "password".`, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + settings.Initialize() + serverConfig := settings.GlobalConfiguration.Server log.Println(cfgFile) if !d.hadDB { quickSetup(cmd.Flags(), d) } - // build img service - workersCount, err := cmd.Flags().GetInt("img-processors") - checkErr(err) + workersCount := serverConfig.NumImageProcessors if workersCount < 1 { log.Fatal("Image resize workers count could not be < 1") } imgSvc := img.New(workersCount) var fileCache diskcache.Interface = diskcache.NewNoOp() - cacheDir, err := cmd.Flags().GetString("cache-dir") - checkErr(err) + cacheDir := "/tmp" if cacheDir != "" { if err := os.MkdirAll(cacheDir, 0700); err != nil { //nolint:govet,gomnd log.Fatalf("can't make directory %s: %s", cacheDir, err) } fileCache = diskcache.New(afero.NewOsFs(), cacheDir) } + // initialize indexing and schedule indexing ever n minutes (default 5) - indexingInterval := getEnvVariableAsUint32("INDEXING_INTERVAL") - go search.InitializeIndex(indexingInterval) + go search.InitializeIndex(serverConfig.IndexingInterval) - server := getRunParams(cmd.Flags(), d.store) - setupLog(server.Log) - - root, err := filepath.Abs(server.Root) + _, err := os.Stat(serverConfig.Root) checkErr(err) - server.Root = root - - adr := server.Address + ":" + server.Port var listener net.Listener + address := serverConfig.Address+":"+strconv.Itoa(serverConfig.Port) switch { - case server.Socket != "": - listener, err = net.Listen("unix", server.Socket) + case serverConfig.Socket != "": + listener, err = net.Listen("unix", serverConfig.Socket) checkErr(err) socketPerm, err := cmd.Flags().GetUint32("socket-perm") //nolint:govet checkErr(err) - err = os.Chmod(server.Socket, os.FileMode(socketPerm)) + err = os.Chmod(serverConfig.Socket, os.FileMode(socketPerm)) checkErr(err) - case server.TLSKey != "" && server.TLSCert != "": - cer, err := tls.LoadX509KeyPair(server.TLSCert, server.TLSKey) //nolint:govet + case serverConfig.TLSKey != "" && serverConfig.TLSCert != "": + cer, err := tls.LoadX509KeyPair(serverConfig.TLSCert, serverConfig.TLSKey) //nolint:govet checkErr(err) - listener, err = tls.Listen("tcp", adr, &tls.Config{ + listener, err = tls.Listen("tcp", address, &tls.Config{ MinVersion: tls.VersionTLS12, Certificates: []tls.Certificate{cer}}, ) checkErr(err) default: - listener, err = net.Listen("tcp", adr) + listener, err = net.Listen("tcp", address) checkErr(err) } @@ -191,7 +143,7 @@ user created with the credentials from options "username" and "password".`, go cleanupHandler(listener, sigc) assetsFs := dirFS{Dir: http.Dir("frontend/dist")} - handler, err := fbhttp.NewHandler(imgSvc, fileCache, d.store, server, assetsFs) + handler, err := fbhttp.NewHandler(imgSvc, fileCache, d.store, &serverConfig, assetsFs) checkErr(err) defer listener.Close() @@ -215,68 +167,6 @@ func cleanupHandler(listener net.Listener, c chan os.Signal) { //nolint:interfac func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server { server, err := st.Settings.GetServer() checkErr(err) - - if val, set := getParamB(flags, "root"); set { - server.Root = val - } - - if val, set := getParamB(flags, "baseurl"); set { - server.BaseURL = val - } - - if val, set := getParamB(flags, "log"); set { - server.Log = val - } - - isSocketSet := false - isAddrSet := false - - if val, set := getParamB(flags, "address"); set { - server.Address = val - isAddrSet = isAddrSet || set - } - - if val, set := getParamB(flags, "port"); set { - server.Port = val - isAddrSet = isAddrSet || set - } - - if val, set := getParamB(flags, "key"); set { - server.TLSKey = val - isAddrSet = isAddrSet || set - } - - if val, set := getParamB(flags, "cert"); set { - server.TLSCert = val - isAddrSet = isAddrSet || set - } - - if val, set := getParamB(flags, "socket"); set { - server.Socket = val - isSocketSet = isSocketSet || set - } - - if isAddrSet && isSocketSet { - checkErr(errors.New("--socket flag cannot be used with --address, --port, --key nor --cert")) - } - - // Do not use saved Socket if address was manually set. - if isAddrSet && server.Socket != "" { - server.Socket = "" - } - - _, disableThumbnails := getParamB(flags, "disable-thumbnails") - server.EnableThumbnails = !disableThumbnails - - _, disablePreviewResize := getParamB(flags, "disable-preview-resize") - server.ResizePreview = !disablePreviewResize - - _, disableTypeDetectionByHeader := getParamB(flags, "disable-type-detection-by-header") - server.TypeDetectionByHeader = !disableTypeDetectionByHeader - - _, disableExec := getParamB(flags, "disable-exec") - server.EnableExec = !disableExec - return server } @@ -348,32 +238,28 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { Download: true, }, }, - AuthMethod: "", - Branding: settings.Branding{}, + Frontend: settings.Frontend{}, Commands: nil, Shell: nil, Rules: nil, } var err error - if _, noauth := getParamB(flags, "noauth"); noauth { - set.AuthMethod = auth.MethodNoAuth + if settings.GlobalConfiguration.Auth.Method == "noAuth" { + set.Auth.Method = "noAuth" err = d.store.Auth.Save(&auth.NoAuth{}) - } else { - set.AuthMethod = auth.MethodJSONAuth + }else{ + set.Auth.Method = auth.MethodJSONAuth err = d.store.Auth.Save(&auth.JSONAuth{}) } - err = d.store.Settings.Save(set) checkErr(err) ser := &settings.Server{ BaseURL: getParam(flags, "baseurl"), - Port: getParam(flags, "port"), Log: getParam(flags, "log"), TLSKey: getParam(flags, "key"), TLSCert: getParam(flags, "cert"), - Address: getParam(flags, "address"), Root: getParam(flags, "root"), } err = d.store.Settings.SaveServer(ser) @@ -408,7 +294,7 @@ func initConfig() { if cfgFile == "" { v.AddConfigPath(".") v.AddConfigPath("/etc/filebrowser/") - v.SetConfigName(".filebrowser") + v.SetConfigName("filebrowser") } else { v.SetConfigFile(cfgFile) } diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index efd76980..ba1f1d57 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -1,26 +1,27 @@ server: - port: 8080 + port: 8050 baseURL: /files address: '' log: stdout database: ./database.db root: /srv +general: disable-thumbnails: false disable-preview-resize: false disable-exec: false disable-type-detection-by-header: false auth: header: '' - method: '' + method: 'noauth' command: '' signup: false shell: '' -branding: +frontend: name: '' color: '' files: '' - disableExternal: '' - disableUsedPercentage: '' + disableExternal: false + disableUsedPercentage: false permissions: Admin: false Execute: true @@ -31,5 +32,4 @@ permissions: Share: true Download: true commands: -shell: rules: diff --git a/backend/go.mod b/backend/go.mod index 8ad814af..f2ab4898 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -7,6 +7,7 @@ require ( github.com/disintegration/imaging v1.6.2 github.com/dsoprea/go-exif/v3 v3.0.1 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 + github.com/goccy/go-yaml v1.11.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.5.0 @@ -35,6 +36,7 @@ require ( github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect + github.com/fatih/color v1.13.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect @@ -45,6 +47,8 @@ require ( github.com/klauspost/compress v1.11.4 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/nwaples/rardecode v1.1.0 // indirect github.com/pierrec/lz4/v4 v4.1.2 // indirect @@ -58,6 +62,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.3 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.11.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 2c3368f4..ebb50138 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -86,6 +86,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= @@ -101,6 +103,11 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/goccy/go-yaml v1.11.0 h1:n7Z+zx8S9f9KgzG6KtQKf+kwqXZlLNR2F6018Dgau54= +github.com/goccy/go-yaml v1.11.0/go.mod h1:H+mJrWtjPTJAHvRbV09MCK9xYwODM+wRTVFFTWckfng= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= @@ -198,6 +205,7 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= @@ -205,6 +213,12 @@ github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ= github.com/maruel/natural v1.1.0/go.mod h1:eFVhYCcUOfZFxXoDZam8Ktya72wa79fNC3lc/leA0DQ= github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tpx6DJGM= github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -403,6 +417,7 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -427,6 +442,8 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -507,6 +524,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= diff --git a/backend/http/auth.go b/backend/http/auth.go index e5cb2a7e..a47baec5 100644 --- a/backend/http/auth.go +++ b/backend/http/auth.go @@ -102,7 +102,7 @@ func withAdmin(fn handleFunc) handleFunc { } var loginHandler = func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { - auther, err := d.store.Auth.Get(d.settings.AuthMethod) + auther, err := d.store.Auth.Get(d.settings.Auth.Method) if err != nil { return http.StatusInternalServerError, err } diff --git a/backend/http/settings.go b/backend/http/settings.go index c412148b..ee2ab9e1 100644 --- a/backend/http/settings.go +++ b/backend/http/settings.go @@ -14,7 +14,7 @@ type settingsData struct { UserHomeBasePath string `json:"userHomeBasePath"` Defaults settings.UserDefaults `json:"defaults"` Rules []rules.Rule `json:"rules"` - Branding settings.Branding `json:"branding"` + Frontend settings.Frontend `json:"frontend"` Shell []string `json:"shell"` Commands map[string][]string `json:"commands"` } @@ -26,7 +26,7 @@ var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, UserHomeBasePath: d.settings.UserHomeBasePath, Defaults: d.settings.Defaults, Rules: d.settings.Rules, - Branding: d.settings.Branding, + Frontend: d.settings.Frontend, Shell: d.settings.Shell, Commands: d.settings.Commands, } @@ -46,7 +46,7 @@ var settingsPutHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d.settings.UserHomeBasePath = req.UserHomeBasePath d.settings.Defaults = req.Defaults d.settings.Rules = req.Rules - d.settings.Branding = req.Branding + d.settings.Frontend = req.Frontend d.settings.Shell = req.Shell d.settings.Commands = req.Commands diff --git a/backend/http/static.go b/backend/http/static.go index 500bef8b..8b7ac8c8 100644 --- a/backend/http/static.go +++ b/backend/http/static.go @@ -21,33 +21,33 @@ import ( func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys fs.FS, file, contentType string) (int, error) { w.Header().Set("Content-Type", contentType) - auther, err := d.store.Auth.Get(d.settings.AuthMethod) + auther, err := d.store.Auth.Get(d.settings.Auth.Method) if err != nil { return http.StatusInternalServerError, err } data := map[string]interface{}{ - "Name": d.settings.Branding.Name, - "DisableExternal": d.settings.Branding.DisableExternal, - "DisableUsedPercentage": d.settings.Branding.DisableUsedPercentage, - "Color": d.settings.Branding.Color, + "Name": d.settings.Frontend.Name, + "DisableExternal": d.settings.Frontend.DisableExternal, + "DisableUsedPercentage": d.settings.Frontend.DisableUsedPercentage, + "Color": d.settings.Frontend.Color, "BaseURL": d.server.BaseURL, "Version": version.Version, "StaticURL": path.Join(d.server.BaseURL, "/static"), "Signup": d.settings.Signup, - "NoAuth": d.settings.AuthMethod == auth.MethodNoAuth, - "AuthMethod": d.settings.AuthMethod, + "NoAuth": d.settings.Auth.Method == auth.MethodNoAuth, + "AuthMethod": d.settings.Auth.Method, "LoginPage": auther.LoginPage(), "CSS": false, "ReCaptcha": false, - "Theme": d.settings.Branding.Theme, + "Theme": d.settings.Frontend.Theme, "EnableThumbs": d.server.EnableThumbnails, "ResizePreview": d.server.ResizePreview, "EnableExec": d.server.EnableExec, } - if d.settings.Branding.Files != "" { - fPath := filepath.Join(d.settings.Branding.Files, "custom.css") + if d.settings.Frontend.Files != "" { + fPath := filepath.Join(d.settings.Frontend.Files, "custom.css") _, err := os.Stat(fPath) //nolint:govet if err != nil && !os.IsNotExist(err) { @@ -59,8 +59,8 @@ func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys } } - if d.settings.AuthMethod == auth.MethodJSONAuth { - raw, err := d.store.Auth.Get(d.settings.AuthMethod) //nolint:govet + if d.settings.Auth.Method == auth.MethodJSONAuth { + raw, err := d.store.Auth.Get(d.settings.Auth.Method) //nolint:govet if err != nil { return http.StatusInternalServerError, err } @@ -115,15 +115,15 @@ func getStaticHandlers(store *storage.Storage, server *settings.Server, assetsFs const maxAge = 86400 // 1 day w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%v", maxAge)) - if d.settings.Branding.Files != "" { + if d.settings.Frontend.Files != "" { if strings.HasPrefix(r.URL.Path, "img/") { - fPath := filepath.Join(d.settings.Branding.Files, r.URL.Path) + fPath := filepath.Join(d.settings.Frontend.Files, r.URL.Path) if _, err := os.Stat(fPath); err == nil { http.ServeFile(w, r, fPath) return 0, nil } - } else if r.URL.Path == "custom.css" && d.settings.Branding.Files != "" { - http.ServeFile(w, r, filepath.Join(d.settings.Branding.Files, "custom.css")) + } else if r.URL.Path == "custom.css" && d.settings.Frontend.Files != "" { + http.ServeFile(w, r, filepath.Join(d.settings.Frontend.Files, "custom.css")) return 0, nil } } diff --git a/backend/settings/config.go b/backend/settings/config.go new file mode 100644 index 00000000..4f093c05 --- /dev/null +++ b/backend/settings/config.go @@ -0,0 +1,50 @@ +package settings + +import ( + "io/ioutil" + "log" + "os" + + "github.com/goccy/go-yaml" +) + +var GlobalConfiguration Settings + +func Initialize() { + // Open and read the YAML file + yamlFile, err := os.Open("filebrowser.yml") + if err != nil { + log.Fatalf("Error opening YAML file: %v", err) + } + defer yamlFile.Close() + + yamlData, err := ioutil.ReadAll(yamlFile) + if err != nil { + log.Fatalf("Error reading YAML data: %v", err) + } + setDefaults() + // Unmarshal the YAML data into the Settings struct + err = yaml.Unmarshal(yamlData, &GlobalConfiguration) + if err != nil { + log.Fatalf("Error unmarshaling YAML data: %v", err) + } + // Now you have the Settings struct with values from the YAML file + // You can access the values like: defaultSettings.Key, defaultSettings.Server.Port, etc. +} + +func setDefaults() { + GlobalConfiguration = Settings{ + Signup: true, + Server: Server{ + IndexingInterval: 5, + Port: 8080, + NumImageProcessors: 1, + BaseURL: "/files", + }, + Auth: Auth{ + Recaptcha: Recaptcha{ + Host: "", + }, + }, + } +} \ No newline at end of file diff --git a/backend/settings/settings.go b/backend/settings/settings.go index dde86d73..6b5d0dd8 100644 --- a/backend/settings/settings.go +++ b/backend/settings/settings.go @@ -35,3 +35,7 @@ func GenerateKey() ([]byte, error) { return b, nil } + +func GetSettingsConfig(nameType string,Value string) string { + return nameType + Value +} \ No newline at end of file diff --git a/backend/settings/structs.go b/backend/settings/structs.go index 5669684a..a4317ba4 100644 --- a/backend/settings/structs.go +++ b/backend/settings/structs.go @@ -29,21 +29,31 @@ type Settings struct { Shell []string `json:"shell"` Rules []rules.Rule `json:"rules"` Server Server `json:"server"` - AuthMethod string `json:"authMethod"` - Auth struct { - Header string `json:"header"` - Method string `json:"method"` - Command string `json:"command"` - Signup bool `json:"signup"` - Shell string `json:"shell"` - } `json:"auth"` + Auth Auth `json:"auth"` - Branding Branding `json:"branding"` + Frontend Frontend `json:"frontend"` UserDefaults UserDefaults `json:"userDefaults"` } +type Auth struct { + Recaptcha Recaptcha + Header string `json:"header"` + Method string `json:"method"` + Command string `json:"command"` + Signup bool `json:"signup"` + Shell string `json:"shell"` +} + +type Recaptcha struct { + Host string + Key string + Secret string +} + type Server struct { + IndexingInterval uint32 + NumImageProcessors int Socket string `json:"socket"` TLSKey string `json:"tlsKey"` TLSCert string `json:"tlsCert"` @@ -52,7 +62,7 @@ type Server struct { EnableExec bool `json:"enableExec"` TypeDetectionByHeader bool `json:"typeDetectionByHeader"` AuthHook string `json:"authHook"` - Port string `json:"port"` + Port int `json:"port"` BaseURL string `json:"baseURL"` Address string `json:"address"` Log string `json:"log"` @@ -61,7 +71,7 @@ type Server struct { EnablePreviewResize bool `json:"disable-preview-resize"` } -type Branding struct { +type Frontend struct { Name string `json:"name"` DisableExternal bool `json:"disableExternal"` DisableUsedPercentage bool `json:"disableUsedPercentage"` diff --git a/backend/storage/bolt/config.go b/backend/storage/bolt/config.go index 67f9eed9..cb4914c6 100644 --- a/backend/storage/bolt/config.go +++ b/backend/storage/bolt/config.go @@ -2,7 +2,6 @@ package bolt import ( "github.com/asdine/storm/v3" - "github.com/gtsteffaniak/filebrowser/settings" ) @@ -20,7 +19,10 @@ func (s settingsBackend) Save(set *settings.Settings) error { } func (s settingsBackend) GetServer() (*settings.Server, error) { - server := &settings.Server{} + server := &settings.Server{ + Port: 8080, + NumImageProcessors: 1, + } return server, get(s.db, "server", server) } diff --git a/backend/storage/bolt/importer/conf.go b/backend/storage/bolt/importer/conf.go index 939559c2..b40e155c 100644 --- a/backend/storage/bolt/importer/conf.go +++ b/backend/storage/bolt/importer/conf.go @@ -140,7 +140,7 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { server := &settings.Server{ BaseURL: cfg.BaseURL, - Port: cfg.Port, + Port: 8080, Address: cfg.Address, Log: cfg.Log, } @@ -149,13 +149,13 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { switch cfg.Auth.Method { case "proxy": auther = &auth.ProxyAuth{Header: cfg.Auth.Header} - s.AuthMethod = string(auth.MethodProxyAuth) + s.Auth.Method = string(auth.MethodProxyAuth) case "hook": auther = &auth.HookAuth{Command: cfg.Auth.Command} - s.AuthMethod = string(auth.MethodHookAuth) + s.Auth.Method = string(auth.MethodHookAuth) case "none": auther = &auth.NoAuth{} - s.AuthMethod = string(auth.MethodNoAuth) + s.Auth.Method = string(auth.MethodNoAuth) default: auther = &auth.JSONAuth{ ReCaptcha: &auth.ReCaptcha{ @@ -164,7 +164,7 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { Secret: cfg.ReCaptcha.Secret, }, } - s.AuthMethod = string(auth.MethodJSONAuth) + s.Auth.Method = string(auth.MethodJSONAuth) } err = sto.Auth.Save(auther) diff --git a/backend/storage/bolt/importer/importer.go b/backend/storage/bolt/importer/importer.go index 1ecc70eb..36b60283 100644 --- a/backend/storage/bolt/importer/importer.go +++ b/backend/storage/bolt/importer/importer.go @@ -2,12 +2,14 @@ package importer import ( "github.com/asdine/storm/v3" + "log" "github.com/gtsteffaniak/filebrowser/storage/bolt" ) // Import imports an old configuration to a newer database. func Import(oldDBPath, oldConf, newDBPath string) error { + log.Println(oldDBPath, oldConf, newDBPath) oldDB, err := storm.Open(oldDBPath) if err != nil { return err From 3fb940ba5b88f9bc2f4e7d9b7aefce5173ec3f79 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 17:35:54 -0500 Subject: [PATCH 06/14] new --- backend/.filebrowser.json | 8 -------- backend/auth/hook.go | 3 --- backend/auth/json.go | 3 --- backend/cmd/config.go | 12 ++++-------- backend/cmd/config_import.go | 13 +++++++------ backend/cmd/root.go | 21 ++++++--------------- backend/filebrowser.yml | 4 ++-- backend/http/static.go | 4 ++-- backend/settings/config.go | 20 +++++++++++++------- backend/storage/bolt/auth.go | 13 +++++++------ backend/storage/bolt/importer/conf.go | 10 +++++----- 11 files changed, 46 insertions(+), 65 deletions(-) delete mode 100644 backend/.filebrowser.json diff --git a/backend/.filebrowser.json b/backend/.filebrowser.json deleted file mode 100644 index 40e89fbb..00000000 --- a/backend/.filebrowser.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "port": 5555, - "baseURL": "", - "address": "", - "log": "stdout", - "database": "./database.db", - "root": "/srv" -} \ No newline at end of file diff --git a/backend/auth/hook.go b/backend/auth/hook.go index 7e165f07..00b2a625 100644 --- a/backend/auth/hook.go +++ b/backend/auth/hook.go @@ -15,9 +15,6 @@ import ( "github.com/gtsteffaniak/filebrowser/users" ) -// MethodHookAuth is used to identify hook auth. -const MethodHookAuth = "hook" - type hookCred struct { Password string `json:"password"` Username string `json:"username"` diff --git a/backend/auth/json.go b/backend/auth/json.go index bcd8af52..ce7143de 100644 --- a/backend/auth/json.go +++ b/backend/auth/json.go @@ -11,9 +11,6 @@ import ( "github.com/gtsteffaniak/filebrowser/users" ) -// MethodJSONAuth is used to identify json auth. -const MethodJSONAuth = "json" - type jsonCred struct { Password string `json:"password"` Username string `json:"username"` diff --git a/backend/cmd/config.go b/backend/cmd/config.go index a8d9211d..21d69d2a 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -32,10 +32,6 @@ func addConfigFlags(flags *pflag.FlagSet) { flags.BoolP("signup", "s", false, "allow users to signup") flags.String("shell", "", "shell command to which other commands should be appended") - flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type") - flags.String("auth.header", "", "HTTP header for auth.method=proxy") - flags.String("auth.command", "", "command for auth.method=hook") - flags.String("recaptcha.host", "https://www.google.com", "use another host for ReCAPTCHA. recaptcha.net might be useful in China") flags.String("recaptcha.key", "", "ReCaptcha site key") flags.String("recaptcha.secret", "", "ReCaptcha secret") @@ -52,7 +48,7 @@ func getAuthentication() (string, auth.Auther) { method := settings.GlobalConfiguration.Auth.Method var defaultAuther map[string]interface{} var auther auth.Auther - if method == auth.MethodProxyAuth { + if method == "proxy" { header := settings.GlobalConfiguration.Auth.Header if header == "" { header = defaultAuther["header"].(string) @@ -65,11 +61,11 @@ func getAuthentication() (string, auth.Auther) { auther = &auth.ProxyAuth{Header: header} } - if method == auth.MethodNoAuth { + if method == "noauth" { auther = &auth.NoAuth{} } - if method == auth.MethodJSONAuth { + if method == "password" { jsonAuth := &auth.JSONAuth{} host := settings.GlobalConfiguration.Auth.Recaptcha.Host key := settings.GlobalConfiguration.Auth.Recaptcha.Key @@ -97,7 +93,7 @@ func getAuthentication() (string, auth.Auther) { auther = jsonAuth } - if method == auth.MethodHookAuth { + if method == "hook" { command := settings.GlobalConfiguration.Auth.Command if command == "" { diff --git a/backend/cmd/config_import.go b/backend/cmd/config_import.go index 800b0512..08ff806d 100644 --- a/backend/cmd/config_import.go +++ b/backend/cmd/config_import.go @@ -5,6 +5,7 @@ import ( "errors" "path/filepath" "reflect" + "log" "github.com/spf13/cobra" @@ -46,7 +47,7 @@ The path must be for a json or yaml file.`, file := settingsFile{} err := unmarshal(args[0], &file) checkErr(err) - + log.Println(file.Settings) file.Settings.Key = key err = d.store.Settings.Save(file.Settings) checkErr(err) @@ -60,16 +61,16 @@ The path must be for a json or yaml file.`, } else { rawAuther = file.Auther } - + log.Println("config_import",file.Settings.Auth) var auther auth.Auther switch file.Settings.Auth.Method { - case auth.MethodJSONAuth: + case "password": auther = getAuther(auth.JSONAuth{}, rawAuther).(*auth.JSONAuth) - case auth.MethodNoAuth: + case "noauth": auther = getAuther(auth.NoAuth{}, rawAuther).(*auth.NoAuth) - case auth.MethodProxyAuth: + case "proxy": auther = getAuther(auth.ProxyAuth{}, rawAuther).(*auth.ProxyAuth) - case auth.MethodHookAuth: + case "hook": auther = getAuther(&auth.HookAuth{}, rawAuther).(*auth.HookAuth) default: checkErr(errors.New("invalid auth method")) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index ca31422d..79e16d8e 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -19,7 +19,6 @@ import ( v "github.com/spf13/viper" lumberjack "gopkg.in/natefinch/lumberjack.v2" - "github.com/gtsteffaniak/filebrowser/auth" "github.com/gtsteffaniak/filebrowser/diskcache" fbhttp "github.com/gtsteffaniak/filebrowser/http" "github.com/gtsteffaniak/filebrowser/img" @@ -51,8 +50,6 @@ func init() { persistent := rootCmd.PersistentFlags() persistent.StringVarP(&cfgFile, "config", "c", "", "config file path") - persistent.StringP("database", "d", "./filebrowser.db", "database path") - flags.Bool("noauth", false, "use the noauth auther when using quick setup") flags.String("username", "admin", "username for the first user when using quick config") flags.String("password", "", "hashed password for the first user when using quick config (default \"admin\")") } @@ -115,7 +112,7 @@ user created with the credentials from options "username" and "password".`, checkErr(err) var listener net.Listener - address := serverConfig.Address+":"+strconv.Itoa(serverConfig.Port) + address := serverConfig.Address + ":" + strconv.Itoa(serverConfig.Port) switch { case serverConfig.Socket != "": @@ -238,20 +235,14 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { Download: true, }, }, - Frontend: settings.Frontend{}, - Commands: nil, - Shell: nil, - Rules: nil, + Frontend: settings.Frontend{}, + Commands: nil, + Shell: nil, + Rules: nil, } var err error - if settings.GlobalConfiguration.Auth.Method == "noAuth" { - set.Auth.Method = "noAuth" - err = d.store.Auth.Save(&auth.NoAuth{}) - }else{ - set.Auth.Method = auth.MethodJSONAuth - err = d.store.Auth.Save(&auth.JSONAuth{}) - } + set.Auth.Method = settings.GlobalConfiguration.Auth.Method err = d.store.Settings.Save(set) checkErr(err) diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index ba1f1d57..4c1631f7 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -1,6 +1,6 @@ server: port: 8050 - baseURL: /files + baseURL: / address: '' log: stdout database: ./database.db @@ -12,7 +12,7 @@ general: disable-type-detection-by-header: false auth: header: '' - method: 'noauth' + method: noauth command: '' signup: false shell: '' diff --git a/backend/http/static.go b/backend/http/static.go index 8b7ac8c8..b0e1685e 100644 --- a/backend/http/static.go +++ b/backend/http/static.go @@ -35,7 +35,7 @@ func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys "Version": version.Version, "StaticURL": path.Join(d.server.BaseURL, "/static"), "Signup": d.settings.Signup, - "NoAuth": d.settings.Auth.Method == auth.MethodNoAuth, + "NoAuth": d.settings.Auth.Method == "noauth", "AuthMethod": d.settings.Auth.Method, "LoginPage": auther.LoginPage(), "CSS": false, @@ -59,7 +59,7 @@ func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys } } - if d.settings.Auth.Method == auth.MethodJSONAuth { + if d.settings.Auth.Method == "password" { raw, err := d.store.Auth.Get(d.settings.Auth.Method) //nolint:govet if err != nil { return http.StatusInternalServerError, err diff --git a/backend/settings/config.go b/backend/settings/config.go index 4f093c05..ac46b743 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -22,12 +22,17 @@ func Initialize() { if err != nil { log.Fatalf("Error reading YAML data: %v", err) } + log.Println(GlobalConfiguration) setDefaults() + log.Println(GlobalConfiguration) + // Unmarshal the YAML data into the Settings struct err = yaml.Unmarshal(yamlData, &GlobalConfiguration) if err != nil { log.Fatalf("Error unmarshaling YAML data: %v", err) } + log.Println(GlobalConfiguration) + // Now you have the Settings struct with values from the YAML file // You can access the values like: defaultSettings.Key, defaultSettings.Server.Port, etc. } @@ -35,16 +40,17 @@ func Initialize() { func setDefaults() { GlobalConfiguration = Settings{ Signup: true, - Server: Server{ - IndexingInterval: 5, - Port: 8080, + Server: Server{ + IndexingInterval: 5, + Port: 8080, NumImageProcessors: 1, - BaseURL: "/files", - }, + BaseURL: "/", + }, Auth: Auth{ + Method: "noauth", Recaptcha: Recaptcha{ Host: "", }, }, - } -} \ No newline at end of file + } +} diff --git a/backend/storage/bolt/auth.go b/backend/storage/bolt/auth.go index abba4e1d..79fa9133 100644 --- a/backend/storage/bolt/auth.go +++ b/backend/storage/bolt/auth.go @@ -1,8 +1,9 @@ package bolt import ( - "github.com/asdine/storm/v3" + "fmt" + "github.com/asdine/storm/v3" "github.com/gtsteffaniak/filebrowser/auth" "github.com/gtsteffaniak/filebrowser/errors" ) @@ -13,15 +14,15 @@ type authBackend struct { func (s authBackend) Get(t string) (auth.Auther, error) { var auther auth.Auther - + fmt.Println("auth.go", t) switch t { - case auth.MethodJSONAuth: + case "password": auther = &auth.JSONAuth{} - case auth.MethodProxyAuth: + case "proxy": auther = &auth.ProxyAuth{} - case auth.MethodHookAuth: + case "hook": auther = &auth.HookAuth{} - case auth.MethodNoAuth: + case "noauth": auther = &auth.NoAuth{} default: return nil, errors.ErrInvalidAuthMethod diff --git a/backend/storage/bolt/importer/conf.go b/backend/storage/bolt/importer/conf.go index b40e155c..a6d84a21 100644 --- a/backend/storage/bolt/importer/conf.go +++ b/backend/storage/bolt/importer/conf.go @@ -144,18 +144,18 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { Address: cfg.Address, Log: cfg.Log, } - + fmt.Println("config.go", server) var auther auth.Auther switch cfg.Auth.Method { case "proxy": auther = &auth.ProxyAuth{Header: cfg.Auth.Header} - s.Auth.Method = string(auth.MethodProxyAuth) + s.Auth.Method = "proxy" case "hook": auther = &auth.HookAuth{Command: cfg.Auth.Command} - s.Auth.Method = string(auth.MethodHookAuth) + s.Auth.Method = "hoook" case "none": auther = &auth.NoAuth{} - s.Auth.Method = string(auth.MethodNoAuth) + s.Auth.Method = "noauth" default: auther = &auth.JSONAuth{ ReCaptcha: &auth.ReCaptcha{ @@ -164,7 +164,7 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { Secret: cfg.ReCaptcha.Secret, }, } - s.Auth.Method = string(auth.MethodJSONAuth) + s.Auth.Method = "password" } err = sto.Auth.Save(auther) From 5c860a45e11ff16518bab16058aab04d96e79437 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 17:53:22 -0500 Subject: [PATCH 07/14] new --- backend/cmd/root.go | 2 -- backend/cmd/utils.go | 4 ++-- backend/filebrowser.yml | 4 ++-- backend/settings/config.go | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index 79e16d8e..a59d0318 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -82,10 +82,8 @@ Also, if the database path doesn't exist, File Browser will enter into the quick setup mode and a new database will be bootstraped and a new user created with the credentials from options "username" and "password".`, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - settings.Initialize() serverConfig := settings.GlobalConfiguration.Server log.Println(cfgFile) - if !d.hadDB { quickSetup(cmd.Flags(), d) } diff --git a/backend/cmd/utils.go b/backend/cmd/utils.go index ef0b9a7c..0ae50265 100644 --- a/backend/cmd/utils.go +++ b/backend/cmd/utils.go @@ -85,8 +85,7 @@ func dbExists(path string) (bool, error) { func python(fn pythonFunc, cfg pythonConfig) cobraFunc { return func(cmd *cobra.Command, args []string) { data := pythonData{hadDB: true} - - path := getParam(cmd.Flags(), "database") + path := settings.GlobalConfiguration.Server.Database exists, err := dbExists(path) if err != nil { @@ -100,6 +99,7 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc { data.hadDB = exists db, err := storm.Open(path) checkErr(err) + defer db.Close() data.store, err = bolt.NewStorage(db) checkErr(err) diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index 4c1631f7..58b2636f 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -1,9 +1,9 @@ server: port: 8050 - baseURL: / + #baseURL: / address: '' log: stdout - database: ./database.db + database: database.db root: /srv general: disable-thumbnails: false diff --git a/backend/settings/config.go b/backend/settings/config.go index ac46b743..130ac7d0 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -10,7 +10,7 @@ import ( var GlobalConfiguration Settings -func Initialize() { +func init() { // Open and read the YAML file yamlFile, err := os.Open("filebrowser.yml") if err != nil { From 014b999ed77b85b1a80df4bc3599e2a3b77afb84 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 17:57:24 -0500 Subject: [PATCH 08/14] test --- backend/filebrowser.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index 58b2636f..07503bbb 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -1,6 +1,6 @@ server: port: 8050 - #baseURL: / + baseURL: "" address: '' log: stdout database: database.db @@ -12,7 +12,7 @@ general: disable-type-detection-by-header: false auth: header: '' - method: noauth + method: password command: '' signup: false shell: '' From 99bcec49c3f1183aea4dddab58c3037464412157 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 17:59:23 -0500 Subject: [PATCH 09/14] updated --- backend/cmd/root.go | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index a59d0318..bb7b4c56 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -84,6 +84,7 @@ user created with the credentials from options "username" and "password".`, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { serverConfig := settings.GlobalConfiguration.Server log.Println(cfgFile) + if !d.hadDB { quickSetup(cmd.Flags(), d) } From adbf5b21fe01e77035608e2327c3171d271ea73b Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 18:30:51 -0500 Subject: [PATCH 10/14] updated --- backend/cmd/root.go | 6 +++++- backend/filebrowser.yml | 6 +++--- backend/settings/config.go | 5 +---- backend/storage/bolt/auth.go | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index bb7b4c56..7121c93e 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -111,7 +111,11 @@ user created with the credentials from options "username" and "password".`, checkErr(err) var listener net.Listener - address := serverConfig.Address + ":" + strconv.Itoa(serverConfig.Port) + listenAddress := serverConfig.Address + if listenAddress == "" { + listenAddress = "[::]" // default an + } + address := listenAddress + ":" + strconv.Itoa(serverConfig.Port) switch { case serverConfig.Socket != "": diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index 07503bbb..2edb6a8d 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -1,6 +1,6 @@ server: - port: 8050 - baseURL: "" + port: 8080 + baseURL: "/" address: '' log: stdout database: database.db @@ -12,7 +12,7 @@ general: disable-type-detection-by-header: false auth: header: '' - method: password + method: noauth command: '' signup: false shell: '' diff --git a/backend/settings/config.go b/backend/settings/config.go index 130ac7d0..d9648274 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -22,16 +22,13 @@ func init() { if err != nil { log.Fatalf("Error reading YAML data: %v", err) } - log.Println(GlobalConfiguration) setDefaults() - log.Println(GlobalConfiguration) - // Unmarshal the YAML data into the Settings struct err = yaml.Unmarshal(yamlData, &GlobalConfiguration) if err != nil { log.Fatalf("Error unmarshaling YAML data: %v", err) } - log.Println(GlobalConfiguration) + log.Printf("GlobalConfiguration: \n%#v\n", GlobalConfiguration) // Now you have the Settings struct with values from the YAML file // You can access the values like: defaultSettings.Key, defaultSettings.Server.Port, etc. diff --git a/backend/storage/bolt/auth.go b/backend/storage/bolt/auth.go index 79fa9133..4e05f611 100644 --- a/backend/storage/bolt/auth.go +++ b/backend/storage/bolt/auth.go @@ -14,7 +14,6 @@ type authBackend struct { func (s authBackend) Get(t string) (auth.Auther, error) { var auther auth.Auther - fmt.Println("auth.go", t) switch t { case "password": auther = &auth.JSONAuth{} @@ -27,6 +26,7 @@ func (s authBackend) Get(t string) (auth.Auther, error) { default: return nil, errors.ErrInvalidAuthMethod } + fmt.Println("auth.go", t) return auther, get(s.db, "auther", auther) } From 87da81310d5b0cb50306e16ad0a95feaa012fb51 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 18:47:48 -0500 Subject: [PATCH 11/14] updated --- backend/cmd/root.go | 6 +-- backend/filebrowser.yml | 96 +++++++++++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index 7121c93e..df59dfa0 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -112,9 +112,6 @@ user created with the credentials from options "username" and "password".`, var listener net.Listener listenAddress := serverConfig.Address - if listenAddress == "" { - listenAddress = "[::]" // default an - } address := listenAddress + ":" + strconv.Itoa(serverConfig.Port) switch { @@ -141,7 +138,8 @@ user created with the credentials from options "username" and "password".`, sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, syscall.SIGTERM) go cleanupHandler(listener, sigc) - + _, err = os.Stat("frontend/dist") + checkErr(err) assetsFs := dirFS{Dir: http.Dir("frontend/dist")} handler, err := fbhttp.NewHandler(imgSvc, fileCache, d.store, &serverConfig, assetsFs) checkErr(err) diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index 2edb6a8d..a352b0d6 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -1,35 +1,77 @@ +general: + key: [] + signup: true + createUserDir: false + userHomeBasePath: "" + scope: "" + locale: "" + viewMode: "" + singleClick: false + hideDotfiles: true + dateFormat: false + defaultSortBy: "" +perm: + admin: true + execute: true + create: true + rename: true + modify: true + delete: true + share: true + download: true +shell: [] +rules: [] server: + indexingInterval: 5 + numImageProcessors: 1 + socket: "" + tlsKey: "" + tlsCert: "" + enableThumbnails: true + resizePreview: false + enableExec: false + typeDetectionByHeader: true + authHook: "" port: 8080 baseURL: "/" - address: '' - log: stdout - database: database.db - root: /srv -general: - disable-thumbnails: false - disable-preview-resize: false - disable-exec: false - disable-type-detection-by-header: false + address: "" + log: "stdout" + database: "database.db" + root: "/srv" auth: - header: '' - method: noauth - command: '' + recaptcha: + host: "" + key: "" + secret: "" + header: "" + method: "noauth" + command: "" signup: false - shell: '' + shell: "" frontend: - name: '' - color: '' - files: '' + name: "" disableExternal: false disableUsedPercentage: false -permissions: - Admin: false - Execute: true - Create: true - Rename: true - Modify: true - Delete: true - Share: true - Download: true -commands: -rules: + files: "" + theme: "" + color: "" +userDefaults: + scope: "" + locale: "" + viewMode: "" + singleClick: false + sorting: + by: "" + asc: false + perm: + admin: false + execute: false + create: false + rename: false + modify: false + delete: false + share: false + download: false + commands: [] + hideDotfiles: false + dateFormat: false From 1cd055d768d18899a315532e9475d90e353989d0 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 19:22:38 -0500 Subject: [PATCH 12/14] test --- backend/cmd/root.go | 20 ++++++++++++++------ backend/settings/config.go | 19 ++++++++----------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index df59dfa0..27da4658 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -19,6 +19,7 @@ import ( v "github.com/spf13/viper" lumberjack "gopkg.in/natefinch/lumberjack.v2" + "github.com/gtsteffaniak/filebrowser/auth" "github.com/gtsteffaniak/filebrowser/diskcache" fbhttp "github.com/gtsteffaniak/filebrowser/http" "github.com/gtsteffaniak/filebrowser/img" @@ -44,12 +45,16 @@ func init() { cobra.OnInitialize(initConfig) cobra.MousetrapHelpText = "" rootCmd.SetVersionTemplate("File Browser version {{printf \"%s\" .Version}}\n") + settings.Initialize() + log.Println(settings.GlobalConfiguration) flags := rootCmd.Flags() persistent := rootCmd.PersistentFlags() persistent.StringVarP(&cfgFile, "config", "c", "", "config file path") + persistent.StringP("database", "d", "./filebrowser.db", "database path") + flags.Bool("noauth", false, "use the noauth auther when using quick setup") flags.String("username", "admin", "username for the first user when using quick config") flags.String("password", "", "hashed password for the first user when using quick config (default \"admin\")") } @@ -83,7 +88,6 @@ the quick setup mode and a new database will be bootstraped and a new user created with the credentials from options "username" and "password".`, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { serverConfig := settings.GlobalConfiguration.Server - log.Println(cfgFile) if !d.hadDB { quickSetup(cmd.Flags(), d) @@ -111,8 +115,7 @@ user created with the credentials from options "username" and "password".`, checkErr(err) var listener net.Listener - listenAddress := serverConfig.Address - address := listenAddress + ":" + strconv.Itoa(serverConfig.Port) + address := serverConfig.Address + ":" + strconv.Itoa(serverConfig.Port) switch { case serverConfig.Socket != "": @@ -138,8 +141,7 @@ user created with the credentials from options "username" and "password".`, sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, syscall.SIGTERM) go cleanupHandler(listener, sigc) - _, err = os.Stat("frontend/dist") - checkErr(err) + assetsFs := dirFS{Dir: http.Dir("frontend/dist")} handler, err := fbhttp.NewHandler(imgSvc, fileCache, d.store, &serverConfig, assetsFs) checkErr(err) @@ -243,7 +245,13 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { } var err error - set.Auth.Method = settings.GlobalConfiguration.Auth.Method + if settings.GlobalConfiguration.Auth.Method == "noAuth" { + set.Auth.Method = "noAuth" + err = d.store.Auth.Save(&auth.NoAuth{}) + } else { + set.Auth.Method = "json" + err = d.store.Auth.Save(&auth.JSONAuth{}) + } err = d.store.Settings.Save(set) checkErr(err) diff --git a/backend/settings/config.go b/backend/settings/config.go index d9648274..4f093c05 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -10,7 +10,7 @@ import ( var GlobalConfiguration Settings -func init() { +func Initialize() { // Open and read the YAML file yamlFile, err := os.Open("filebrowser.yml") if err != nil { @@ -28,8 +28,6 @@ func init() { if err != nil { log.Fatalf("Error unmarshaling YAML data: %v", err) } - log.Printf("GlobalConfiguration: \n%#v\n", GlobalConfiguration) - // Now you have the Settings struct with values from the YAML file // You can access the values like: defaultSettings.Key, defaultSettings.Server.Port, etc. } @@ -37,17 +35,16 @@ func init() { func setDefaults() { GlobalConfiguration = Settings{ Signup: true, - Server: Server{ - IndexingInterval: 5, - Port: 8080, + Server: Server{ + IndexingInterval: 5, + Port: 8080, NumImageProcessors: 1, - BaseURL: "/", - }, + BaseURL: "/files", + }, Auth: Auth{ - Method: "noauth", Recaptcha: Recaptcha{ Host: "", }, }, - } -} + } +} \ No newline at end of file From 91f4a299c424f776c58629dfb2de739375d4011f Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 19:51:13 -0500 Subject: [PATCH 13/14] updated --- backend/cmd/root.go | 4 +--- backend/cmd/utils.go | 4 ++-- backend/settings/config.go | 17 +++++++++-------- backend/settings/structs.go | 24 ++++++++++++------------ 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index 27da4658..80de79c8 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -45,9 +45,7 @@ func init() { cobra.OnInitialize(initConfig) cobra.MousetrapHelpText = "" rootCmd.SetVersionTemplate("File Browser version {{printf \"%s\" .Version}}\n") - settings.Initialize() - log.Println(settings.GlobalConfiguration) flags := rootCmd.Flags() persistent := rootCmd.PersistentFlags() @@ -88,12 +86,12 @@ the quick setup mode and a new database will be bootstraped and a new user created with the credentials from options "username" and "password".`, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { serverConfig := settings.GlobalConfiguration.Server - if !d.hadDB { quickSetup(cmd.Flags(), d) } workersCount := serverConfig.NumImageProcessors + log.Println(serverConfig) if workersCount < 1 { log.Fatal("Image resize workers count could not be < 1") } diff --git a/backend/cmd/utils.go b/backend/cmd/utils.go index 0ae50265..ef0b9a7c 100644 --- a/backend/cmd/utils.go +++ b/backend/cmd/utils.go @@ -85,7 +85,8 @@ func dbExists(path string) (bool, error) { func python(fn pythonFunc, cfg pythonConfig) cobraFunc { return func(cmd *cobra.Command, args []string) { data := pythonData{hadDB: true} - path := settings.GlobalConfiguration.Server.Database + + path := getParam(cmd.Flags(), "database") exists, err := dbExists(path) if err != nil { @@ -99,7 +100,6 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc { data.hadDB = exists db, err := storm.Open(path) checkErr(err) - defer db.Close() data.store, err = bolt.NewStorage(db) checkErr(err) diff --git a/backend/settings/config.go b/backend/settings/config.go index 4f093c05..e3b41bdd 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -10,7 +10,7 @@ import ( var GlobalConfiguration Settings -func Initialize() { +func init() { // Open and read the YAML file yamlFile, err := os.Open("filebrowser.yml") if err != nil { @@ -35,16 +35,17 @@ func Initialize() { func setDefaults() { GlobalConfiguration = Settings{ Signup: true, - Server: Server{ - IndexingInterval: 5, - Port: 8080, + Server: Server{ + IndexingInterval: 5, + Port: 8080, NumImageProcessors: 1, - BaseURL: "/files", - }, + BaseURL: "/files", + }, Auth: Auth{ + Method: "password", Recaptcha: Recaptcha{ Host: "", }, }, - } -} \ No newline at end of file + } +} diff --git a/backend/settings/structs.go b/backend/settings/structs.go index a4317ba4..fba392e7 100644 --- a/backend/settings/structs.go +++ b/backend/settings/structs.go @@ -29,7 +29,7 @@ type Settings struct { Shell []string `json:"shell"` Rules []rules.Rule `json:"rules"` Server Server `json:"server"` - Auth Auth `json:"auth"` + Auth Auth `json:"auth"` Frontend Frontend `json:"frontend"` @@ -38,22 +38,22 @@ type Settings struct { type Auth struct { Recaptcha Recaptcha - Header string `json:"header"` - Method string `json:"method"` - Command string `json:"command"` - Signup bool `json:"signup"` - Shell string `json:"shell"` + Header string `json:"header"` + Method string `json:"method"` + Command string `json:"command"` + Signup bool `json:"signup"` + Shell string `json:"shell"` } type Recaptcha struct { - Host string - Key string - Secret string + Host string + Key string + Secret string } type Server struct { - IndexingInterval uint32 - NumImageProcessors int + IndexingInterval uint32 `json:"indexingInterval"` + NumImageProcessors int `json:"numImageProcessors"` Socket string `json:"socket"` TLSKey string `json:"tlsKey"` TLSCert string `json:"tlsCert"` @@ -62,7 +62,7 @@ type Server struct { EnableExec bool `json:"enableExec"` TypeDetectionByHeader bool `json:"typeDetectionByHeader"` AuthHook string `json:"authHook"` - Port int `json:"port"` + Port int `json:"port"` BaseURL string `json:"baseURL"` Address string `json:"address"` Log string `json:"log"` From 667786e487aec406d44e1645ebe8a14e7333a5d9 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Fri, 1 Sep 2023 21:03:45 -0500 Subject: [PATCH 14/14] updated --- backend/cmd/root.go | 23 +++++------------------ backend/filebrowser.yml | 29 ++--------------------------- backend/http/settings.go | 1 - backend/settings/config.go | 11 ++++++++--- backend/storage/bolt/auth.go | 4 ---- 5 files changed, 15 insertions(+), 53 deletions(-) diff --git a/backend/cmd/root.go b/backend/cmd/root.go index 80de79c8..774211ed 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -89,14 +89,10 @@ user created with the credentials from options "username" and "password".`, if !d.hadDB { quickSetup(cmd.Flags(), d) } - - workersCount := serverConfig.NumImageProcessors - log.Println(serverConfig) - if workersCount < 1 { + if serverConfig.NumImageProcessors < 1 { log.Fatal("Image resize workers count could not be < 1") } - imgSvc := img.New(workersCount) - + imgSvc := img.New(serverConfig.NumImageProcessors) var fileCache diskcache.Interface = diskcache.NewNoOp() cacheDir := "/tmp" if cacheDir != "" { @@ -105,16 +101,12 @@ user created with the credentials from options "username" and "password".`, } fileCache = diskcache.New(afero.NewOsFs(), cacheDir) } - // initialize indexing and schedule indexing ever n minutes (default 5) go search.InitializeIndex(serverConfig.IndexingInterval) - _, err := os.Stat(serverConfig.Root) checkErr(err) - var listener net.Listener address := serverConfig.Address + ":" + strconv.Itoa(serverConfig.Port) - switch { case serverConfig.Socket != "": listener, err = net.Listen("unix", serverConfig.Socket) @@ -135,17 +127,13 @@ user created with the credentials from options "username" and "password".`, listener, err = net.Listen("tcp", address) checkErr(err) } - sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, syscall.SIGTERM) go cleanupHandler(listener, sigc) - assetsFs := dirFS{Dir: http.Dir("frontend/dist")} handler, err := fbhttp.NewHandler(imgSvc, fileCache, d.store, &serverConfig, assetsFs) checkErr(err) - defer listener.Close() - log.Println("Listening on", listener.Addr().String()) //nolint: gosec if err := http.Serve(listener, handler); err != nil { @@ -241,13 +229,12 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { Shell: nil, Rules: nil, } - var err error - if settings.GlobalConfiguration.Auth.Method == "noAuth" { - set.Auth.Method = "noAuth" + if settings.GlobalConfiguration.Auth.Method == "noauth" { + set.Auth.Method = "noauth" err = d.store.Auth.Save(&auth.NoAuth{}) } else { - set.Auth.Method = "json" + set.Auth.Method = "password" err = d.store.Auth.Save(&auth.JSONAuth{}) } err = d.store.Settings.Save(set) diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index a352b0d6..f68917f4 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -1,37 +1,12 @@ -general: - key: [] - signup: true - createUserDir: false - userHomeBasePath: "" - scope: "" - locale: "" - viewMode: "" - singleClick: false - hideDotfiles: true - dateFormat: false - defaultSortBy: "" -perm: - admin: true - execute: true - create: true - rename: true - modify: true - delete: true - share: true - download: true -shell: [] -rules: [] server: indexingInterval: 5 - numImageProcessors: 1 + numImageProcessors: 2 socket: "" tlsKey: "" tlsCert: "" enableThumbnails: true resizePreview: false - enableExec: false typeDetectionByHeader: true - authHook: "" port: 8080 baseURL: "/" address: "" @@ -44,7 +19,7 @@ auth: key: "" secret: "" header: "" - method: "noauth" + method: noauth command: "" signup: false shell: "" diff --git a/backend/http/settings.go b/backend/http/settings.go index ee2ab9e1..49c77326 100644 --- a/backend/http/settings.go +++ b/backend/http/settings.go @@ -49,7 +49,6 @@ var settingsPutHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d.settings.Frontend = req.Frontend d.settings.Shell = req.Shell d.settings.Commands = req.Commands - err = d.store.Settings.Save(d.settings) return errToStatus(err), err }) diff --git a/backend/settings/config.go b/backend/settings/config.go index e3b41bdd..c0c427dd 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -1,7 +1,6 @@ package settings import ( - "io/ioutil" "log" "os" @@ -18,7 +17,13 @@ func init() { } defer yamlFile.Close() - yamlData, err := ioutil.ReadAll(yamlFile) + stat, err := yamlFile.Stat() + if err != nil { + log.Fatalf("Error getting file information: %v", err) + } + + yamlData := make([]byte, stat.Size()) + _, err = yamlFile.Read(yamlData) if err != nil { log.Fatalf("Error reading YAML data: %v", err) } @@ -39,7 +44,7 @@ func setDefaults() { IndexingInterval: 5, Port: 8080, NumImageProcessors: 1, - BaseURL: "/files", + BaseURL: "", }, Auth: Auth{ Method: "password", diff --git a/backend/storage/bolt/auth.go b/backend/storage/bolt/auth.go index 4e05f611..e3f6977b 100644 --- a/backend/storage/bolt/auth.go +++ b/backend/storage/bolt/auth.go @@ -1,8 +1,6 @@ package bolt import ( - "fmt" - "github.com/asdine/storm/v3" "github.com/gtsteffaniak/filebrowser/auth" "github.com/gtsteffaniak/filebrowser/errors" @@ -26,8 +24,6 @@ func (s authBackend) Get(t string) (auth.Auther, error) { default: return nil, errors.ErrInvalidAuthMethod } - fmt.Println("auth.go", t) - return auther, get(s.db, "auther", auther) }