From dd1354eed1433194baef83e72e0b4a8a4f92f5bd Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Thu, 9 Aug 2018 04:53:08 +0100 Subject: [PATCH] feat: use cobra to provide subcommands, move sources to lib --- cli/cmd/db.go | 36 +++ cli/cmd/root.go | 92 +++++++ cli/cmd/serve.go | 121 +++++++++ cli/cmd/server.go | 142 +++++++++++ cli/main.go | 7 + cmd/filebrowser/main.go | 284 ---------------------- {bolt => lib/bolt}/config.go | 2 +- {bolt => lib/bolt}/share.go | 2 +- {bolt => lib/bolt}/users.go | 26 +- doc.go => lib/doc.go | 2 +- file.go => lib/file.go | 2 +- filebrowser.go => lib/filebrowser.go | 2 +- {http => lib/http}/auth.go | 2 +- {http => lib/http}/download.go | 2 +- {http => lib/http}/http.go | 2 +- {http => lib/http}/resource.go | 2 +- {http => lib/http}/settings.go | 2 +- {http => lib/http}/share.go | 2 +- {http => lib/http}/subtitle.go | 2 +- {http => lib/http}/users.go | 2 +- {http => lib/http}/websockets.go | 2 +- {staticgen => lib/staticgen}/hugo.go | 2 +- {staticgen => lib/staticgen}/jekyll.go | 2 +- {staticgen => lib/staticgen}/staticgen.go | 0 24 files changed, 427 insertions(+), 313 deletions(-) create mode 100644 cli/cmd/db.go create mode 100644 cli/cmd/root.go create mode 100644 cli/cmd/serve.go create mode 100644 cli/cmd/server.go create mode 100644 cli/main.go delete mode 100644 cmd/filebrowser/main.go rename {bolt => lib/bolt}/config.go (92%) rename {bolt => lib/bolt}/share.go (97%) rename {bolt => lib/bolt}/users.go (70%) rename doc.go => lib/doc.go (99%) rename file.go => lib/file.go (99%) rename filebrowser.go => lib/filebrowser.go (99%) rename {http => lib/http}/auth.go (99%) rename {http => lib/http}/download.go (98%) rename {http => lib/http}/http.go (99%) rename {http => lib/http}/resource.go (99%) rename {http => lib/http}/settings.go (98%) rename {http => lib/http}/share.go (98%) rename {http => lib/http}/subtitle.go (97%) rename {http => lib/http}/users.go (99%) rename {http => lib/http}/websockets.go (99%) rename {staticgen => lib/staticgen}/hugo.go (99%) rename {staticgen => lib/staticgen}/jekyll.go (98%) rename {staticgen => lib/staticgen}/staticgen.go (100%) diff --git a/cli/cmd/db.go b/cli/cmd/db.go new file mode 100644 index 00000000..e458a848 --- /dev/null +++ b/cli/cmd/db.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// dbCmd represents the db command +var dbCmd = &cobra.Command{ + Use: "db", + Short: "A brief description of your command", + Long: `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("db called") + }, +} + +func init() { + rootCmd.AddCommand(dbCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // dbCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // dbCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cli/cmd/root.go b/cli/cmd/root.go new file mode 100644 index 00000000..a8fddc5b --- /dev/null +++ b/cli/cmd/root.go @@ -0,0 +1,92 @@ +package cmd + +import ( + "fmt" + "os" + + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var cfgFile string + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "filebrowser", + Version: "someversion", + Short: "A stylish web-based file manager", + Long: `File Browser is static binary composed of a golang backend +and a Vue.js frontend to create, edit, copy, move, download your files +easily, everywhere, every time.`, +/* + Run: func(cmd *cobra.Command, args []string) { + serveCmd.Run(cmd, args) + }, +*/ +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initConfig) + + rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.cli.yaml)") + + // Cobra also supports local flags, which will only run + // when this action is called directly. + //rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + viper.AddConfigPath(".") + viper.AddConfigPath(home) + viper.AddConfigPath("/etc/filebrowser/") + viper.SetConfigName(".filebrowser") + } + + viper.SetEnvPrefix("FB") + viper.AutomaticEnv() + + if err := viper.ReadInConfig(); err != nil { + if _, ok := err.(viper.ConfigParseError); ok { + panic(err) + } + } else { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +} + +/* + // Add a configuration file if set. + if config != "" { + ext := filepath.Ext(config) + dir := filepath.Dir(config) + config = strings.TrimSuffix(config, ext) + + if dir != "" { + viper.AddConfigPath(dir) + config = strings.TrimPrefix(config, dir) + } + + viper.SetConfigName(config) + } +*/ \ No newline at end of file diff --git a/cli/cmd/serve.go b/cli/cmd/serve.go new file mode 100644 index 00000000..f0998342 --- /dev/null +++ b/cli/cmd/serve.go @@ -0,0 +1,121 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "github.com/spf13/viper" + filebrowser "github.com/filebrowser/filebrowser/lib" +) + +// serveCmd represents the serve command +var serveCmd = &cobra.Command{ + Use: "serve", + Aliases: []string{"serve","server"}, + Short: "A brief description of your command", + Long: `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + Run: func(cmd *cobra.Command, args []string) { + Serve() + }, +} + +var ( + addr string + database string + scope string + commands string + logfile string + staticg string + locale string + baseurl string + prefixurl string + viewMode string + recaptchakey string + recaptchasecret string + port int + auth struct { + method string + loginHeader string + } + noAuth bool + allowCommands bool + allowEdit bool + allowNew bool + allowPublish bool + showVer bool + alterRecaptcha bool +) + +func init() { + rootCmd.AddCommand(serveCmd) + + serveCmd.PersistentFlags().IntVarP(&port, "port", "p", 0, "HTTP Port (default is random)") + serveCmd.PersistentFlags().StringVarP(&addr, "address", "a", "", "Address to listen to (default is all of them)") + serveCmd.PersistentFlags().StringVarP(&database, "database", "d", "./filebrowser.db", "Database file") + serveCmd.PersistentFlags().StringVarP(&logfile, "log", "l", "stdout", "Errors logger; can use 'stdout', 'stderr' or file") + serveCmd.PersistentFlags().StringVarP(&scope, "scope", "s", ".", "Default scope option for new users") + serveCmd.PersistentFlags().StringVarP(&baseurl, "baseurl", "b", "", "Base URL") + serveCmd.PersistentFlags().StringVar(&commands, "commands", "git svn hg", "Default commands option for new users") + serveCmd.PersistentFlags().StringVar(&prefixurl, "prefixurl", "", "Prefix URL") + serveCmd.PersistentFlags().StringVar(&viewMode, "view-mode", "mosaic", "Default view mode for new users") + serveCmd.PersistentFlags().StringVar(&recaptchakey, "recaptcha-key", "", "ReCaptcha site key") + serveCmd.PersistentFlags().StringVar(&recaptchasecret, "recaptcha-secret", "", "ReCaptcha secret") + serveCmd.PersistentFlags().BoolVar(&allowCommands, "allow-commands", true, "Default allow commands option for new users") + serveCmd.PersistentFlags().BoolVar(&allowEdit, "allow-edit", true, "Default allow edit option for new users") + serveCmd.PersistentFlags().BoolVar(&allowPublish, "allow-publish", true, "Default allow publish option for new users") + serveCmd.PersistentFlags().StringVar(&auth.method, "auth.method", "default", "Switch between 'none', 'default' and 'proxy' authentication.") + serveCmd.PersistentFlags().StringVar(&auth.loginHeader, "auth.loginHeader", "X-Forwarded-User", "The header name used for proxy authentication.") + serveCmd.PersistentFlags().BoolVar(&allowNew, "allow-new", true, "Default allow new option for new users") + serveCmd.PersistentFlags().BoolVar(&noAuth, "no-auth", false, "Disables authentication") + serveCmd.PersistentFlags().BoolVar(&alterRecaptcha, "alternative-recaptcha", false, "Use recaptcha.net for serving and handling, useful in China") + serveCmd.PersistentFlags().StringVar(&locale, "locale", "", "Default locale for new users, set it empty to enable auto detect from browser") + serveCmd.PersistentFlags().StringVar(&staticg, "staticgen", "", "Static Generator you want to enable") + serveCmd.PersistentFlags().BoolVarP(&showVer, "version", "v", false, "Show version") + + viper.SetDefault("Address", "") + viper.SetDefault("Port", "0") + viper.SetDefault("Database", "./filebrowser.db") + viper.SetDefault("Scope", ".") + viper.SetDefault("Logger", "stdout") + viper.SetDefault("Commands", []string{"git", "svn", "hg"}) + viper.SetDefault("AllowCommmands", true) + viper.SetDefault("AllowEdit", true) + viper.SetDefault("AllowNew", true) + viper.SetDefault("AllowPublish", true) + viper.SetDefault("StaticGen", "") + viper.SetDefault("Locale", "") + viper.SetDefault("AuthMethod", "default") + viper.SetDefault("LoginHeader", "X-Fowarded-User") + viper.SetDefault("NoAuth", false) + viper.SetDefault("BaseURL", "") + viper.SetDefault("PrefixURL", "") + viper.SetDefault("ViewMode", filebrowser.MosaicViewMode) + viper.SetDefault("AlternativeRecaptcha", false) + viper.SetDefault("ReCaptchaKey", "") + viper.SetDefault("ReCaptchaSecret", "") + + viper.BindPFlag("Port", serveCmd.PersistentFlags().Lookup("port")) + viper.BindPFlag("Address", serveCmd.PersistentFlags().Lookup("address")) + viper.BindPFlag("Database", serveCmd.PersistentFlags().Lookup("database")) + viper.BindPFlag("Scope", serveCmd.PersistentFlags().Lookup("scope")) + viper.BindPFlag("Logger", serveCmd.PersistentFlags().Lookup("log")) + viper.BindPFlag("Commands", serveCmd.PersistentFlags().Lookup("commands")) + viper.BindPFlag("AllowCommands", serveCmd.PersistentFlags().Lookup("allow-commands")) + viper.BindPFlag("AllowEdit", serveCmd.PersistentFlags().Lookup("allow-edit")) + viper.BindPFlag("AllowNew", serveCmd.PersistentFlags().Lookup("allow-new")) + viper.BindPFlag("AllowPublish", serveCmd.PersistentFlags().Lookup("allow-publish")) + viper.BindPFlag("Locale", serveCmd.PersistentFlags().Lookup("locale")) + viper.BindPFlag("StaticGen", serveCmd.PersistentFlags().Lookup("staticgen")) + viper.BindPFlag("AuthMethod", serveCmd.PersistentFlags().Lookup("auth.method")) + viper.BindPFlag("LoginHeader", serveCmd.PersistentFlags().Lookup("auth.loginHeader")) + viper.BindPFlag("NoAuth", serveCmd.PersistentFlags().Lookup("no-auth")) + viper.BindPFlag("BaseURL", serveCmd.PersistentFlags().Lookup("baseurl")) + viper.BindPFlag("PrefixURL", serveCmd.PersistentFlags().Lookup("prefixurl")) + viper.BindPFlag("ViewMode", serveCmd.PersistentFlags().Lookup("view-mode")) + viper.BindPFlag("AlternativeRecaptcha", serveCmd.PersistentFlags().Lookup("alternative-recaptcha")) + viper.BindPFlag("ReCaptchaKey", serveCmd.PersistentFlags().Lookup("recaptcha-key")) + viper.BindPFlag("ReCaptchaSecret", serveCmd.PersistentFlags().Lookup("recaptcha-secret")) +} diff --git a/cli/cmd/server.go b/cli/cmd/server.go new file mode 100644 index 00000000..004afc6b --- /dev/null +++ b/cli/cmd/server.go @@ -0,0 +1,142 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/viper" + "github.com/asdine/storm" + filebrowser "github.com/filebrowser/filebrowser/lib" + "github.com/filebrowser/filebrowser/lib/bolt" + h "github.com/filebrowser/filebrowser/lib/http" + "github.com/filebrowser/filebrowser/lib/staticgen" + "github.com/hacdias/fileutils" + "gopkg.in/natefinch/lumberjack.v2" + "io/ioutil" + "log" + "net" + "net/http" + "os" + "path/filepath" +) + +func Serve() { + // Set up process log before anything bad happens. + switch viper.GetString("Logger") { + case "stdout": + log.SetOutput(os.Stdout) + case "stderr": + log.SetOutput(os.Stderr) + case "": + log.SetOutput(ioutil.Discard) + default: + log.SetOutput(&lumberjack.Logger{ + Filename: logfile, + MaxSize: 100, + MaxAge: 14, + MaxBackups: 10, + }) + } + + // Validate the provided config before moving forward + if viper.GetString("AuthMethod") != "none" && viper.GetString("AuthMethod") != "default" && viper.GetString("AuthMethod") != "proxy" { + log.Fatal("The property 'auth.method' needs to be set to 'default' or 'proxy'.") + } + + if viper.GetString("AuthMethod") == "proxy" { + if viper.GetString("LoginHeader") == "" { + log.Fatal("The 'loginHeader' needs to be specified when 'proxy' authentication is used.") + } + log.Println("[WARN] Filebrowser authentication is configured to 'proxy' authentication. This can cause a huge security issue if the infrastructure is not configured correctly.") + } + + // Builds the address and a listener. + laddr := viper.GetString("Address") + ":" + viper.GetString("Port") + listener, err := net.Listen("tcp", laddr) + if err != nil { + log.Fatal(err) + } + + // Tell the user the port in which is listening. + fmt.Println("Listening on", listener.Addr().String()) + + // Starts the server. + if err := http.Serve(listener, handler()); err != nil { + log.Fatal(err) + } +} + +func handler() http.Handler { + db, err := storm.Open(viper.GetString("Database")) + if err != nil { + log.Fatal(err) + } + + recaptchaHost := "https://www.google.com" + if viper.GetBool("AlternativeRecaptcha") { + recaptchaHost = "https://recaptcha.net" + } + + fm := &filebrowser.FileBrowser{ + AuthMethod: viper.GetString("AuthMethod"), + LoginHeader: viper.GetString("LoginHeader"), + NoAuth: viper.GetBool("NoAuth"), + BaseURL: viper.GetString("BaseURL"), + PrefixURL: viper.GetString("PrefixURL"), + ReCaptchaHost: recaptchaHost, + ReCaptchaKey: viper.GetString("ReCaptchaKey"), + ReCaptchaSecret: viper.GetString("ReCaptchaSecret"), + DefaultUser: &filebrowser.User{ + AllowCommands: viper.GetBool("AllowCommands"), + AllowEdit: viper.GetBool("AllowEdit"), + AllowNew: viper.GetBool("AllowNew"), + AllowPublish: viper.GetBool("AllowPublish"), + Commands: viper.GetStringSlice("Commands"), + Rules: []*filebrowser.Rule{}, + Locale: viper.GetString("Locale"), + CSS: "", + Scope: viper.GetString("Scope"), + FileSystem: fileutils.Dir(viper.GetString("Scope")), + ViewMode: viper.GetString("ViewMode"), + }, + Store: &filebrowser.Store{ + Config: bolt.ConfigStore{DB: db}, + Users: bolt.UsersStore{DB: db}, + Share: bolt.ShareStore{DB: db}, + }, + NewFS: func(scope string) filebrowser.FileSystem { + return fileutils.Dir(scope) + }, + } + + err = fm.Setup() + if err != nil { + log.Fatal(err) + } + + switch viper.GetString("StaticGen") { + case "hugo": + hugo := &staticgen.Hugo{ + Root: viper.GetString("Scope"), + Public: filepath.Join(viper.GetString("Scope"), "public"), + Args: []string{}, + CleanPublic: true, + } + + if err = fm.Attach(hugo); err != nil { + log.Fatal(err) + } + case "jekyll": + jekyll := &staticgen.Jekyll{ + Root: viper.GetString("Scope"), + Public: filepath.Join(viper.GetString("Scope"), "_site"), + Args: []string{"build"}, + CleanPublic: true, + } + + if err = fm.Attach(jekyll); err != nil { + log.Fatal(err) + } + } + + return h.Handler(fm) +} \ No newline at end of file diff --git a/cli/main.go b/cli/main.go new file mode 100644 index 00000000..38b21602 --- /dev/null +++ b/cli/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/filebrowser/filebrowser/cli/cmd" + +func main() { + cmd.Execute() +} diff --git a/cmd/filebrowser/main.go b/cmd/filebrowser/main.go deleted file mode 100644 index 968d0fd7..00000000 --- a/cmd/filebrowser/main.go +++ /dev/null @@ -1,284 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "log" - "net" - "net/http" - "os" - "path/filepath" - "strings" - - "github.com/asdine/storm" - "github.com/filebrowser/filebrowser" - "github.com/filebrowser/filebrowser/bolt" - h "github.com/filebrowser/filebrowser/http" - "github.com/filebrowser/filebrowser/staticgen" - "github.com/hacdias/fileutils" - flag "github.com/spf13/pflag" - "github.com/spf13/viper" -) - -var ( - addr string - config string - database string - scope string - commands string - logfile string - staticg string - locale string - baseurl string - prefixurl string - viewMode string - recaptchakey string - recaptchasecret string - port int - auth struct { - method string - loginHeader string - } - noAuth bool - allowCommands bool - allowEdit bool - allowNew bool - allowPublish bool - showVer bool - alterRecaptcha bool -) - -func init() { - flag.StringVarP(&config, "config", "c", "", "Configuration file") - flag.IntVarP(&port, "port", "p", 0, "HTTP Port (default is random)") - flag.StringVarP(&addr, "address", "a", "", "Address to listen to (default is all of them)") - flag.StringVarP(&database, "database", "d", "./filebrowser.db", "Database file") - flag.StringVarP(&logfile, "log", "l", "stdout", "Errors logger; can use 'stdout', 'stderr' or file") - flag.StringVarP(&scope, "scope", "s", ".", "Default scope option for new users") - flag.StringVarP(&baseurl, "baseurl", "b", "", "Base URL") - flag.StringVar(&commands, "commands", "git svn hg", "Default commands option for new users") - flag.StringVar(&prefixurl, "prefixurl", "", "Prefix URL") - flag.StringVar(&viewMode, "view-mode", "mosaic", "Default view mode for new users") - flag.StringVar(&recaptchakey, "recaptcha-key", "", "ReCaptcha site key") - flag.StringVar(&recaptchasecret, "recaptcha-secret", "", "ReCaptcha secret") - flag.BoolVar(&allowCommands, "allow-commands", true, "Default allow commands option for new users") - flag.BoolVar(&allowEdit, "allow-edit", true, "Default allow edit option for new users") - flag.BoolVar(&allowPublish, "allow-publish", true, "Default allow publish option for new users") - flag.StringVar(&auth.method, "auth.method", "default", "Switch between 'none', 'default' and 'proxy' authentication.") - flag.StringVar(&auth.loginHeader, "auth.loginHeader", "X-Forwarded-User", "The header name used for proxy authentication.") - flag.BoolVar(&allowNew, "allow-new", true, "Default allow new option for new users") - flag.BoolVar(&noAuth, "no-auth", false, "Disables authentication") - flag.BoolVar(&alterRecaptcha, "alternative-recaptcha", false, "Use recaptcha.net for serving and handling, useful in China") - flag.StringVar(&locale, "locale", "", "Default locale for new users, set it empty to enable auto detect from browser") - flag.StringVar(&staticg, "staticgen", "", "Static Generator you want to enable") - flag.BoolVarP(&showVer, "version", "v", false, "Show version") -} - -func setupViper() { - viper.SetDefault("Address", "") - viper.SetDefault("Port", "0") - viper.SetDefault("Database", "./filebrowser.db") - viper.SetDefault("Scope", ".") - viper.SetDefault("Logger", "stdout") - viper.SetDefault("Commands", []string{"git", "svn", "hg"}) - viper.SetDefault("AllowCommmands", true) - viper.SetDefault("AllowEdit", true) - viper.SetDefault("AllowNew", true) - viper.SetDefault("AllowPublish", true) - viper.SetDefault("StaticGen", "") - viper.SetDefault("Locale", "") - viper.SetDefault("AuthMethod", "default") - viper.SetDefault("LoginHeader", "X-Fowarded-User") - viper.SetDefault("NoAuth", false) - viper.SetDefault("BaseURL", "") - viper.SetDefault("PrefixURL", "") - viper.SetDefault("ViewMode", filebrowser.MosaicViewMode) - viper.SetDefault("AlternativeRecaptcha", false) - viper.SetDefault("ReCaptchaKey", "") - viper.SetDefault("ReCaptchaSecret", "") - - viper.BindPFlag("Port", flag.Lookup("port")) - viper.BindPFlag("Address", flag.Lookup("address")) - viper.BindPFlag("Database", flag.Lookup("database")) - viper.BindPFlag("Scope", flag.Lookup("scope")) - viper.BindPFlag("Logger", flag.Lookup("log")) - viper.BindPFlag("Commands", flag.Lookup("commands")) - viper.BindPFlag("AllowCommands", flag.Lookup("allow-commands")) - viper.BindPFlag("AllowEdit", flag.Lookup("allow-edit")) - viper.BindPFlag("AllowNew", flag.Lookup("allow-new")) - viper.BindPFlag("AllowPublish", flag.Lookup("allow-publish")) - viper.BindPFlag("Locale", flag.Lookup("locale")) - viper.BindPFlag("StaticGen", flag.Lookup("staticgen")) - viper.BindPFlag("AuthMethod", flag.Lookup("auth.method")) - viper.BindPFlag("LoginHeader", flag.Lookup("auth.loginHeader")) - viper.BindPFlag("NoAuth", flag.Lookup("no-auth")) - viper.BindPFlag("BaseURL", flag.Lookup("baseurl")) - viper.BindPFlag("PrefixURL", flag.Lookup("prefixurl")) - viper.BindPFlag("ViewMode", flag.Lookup("view-mode")) - viper.BindPFlag("AlternativeRecaptcha", flag.Lookup("alternative-recaptcha")) - viper.BindPFlag("ReCaptchaKey", flag.Lookup("recaptcha-key")) - viper.BindPFlag("ReCaptchaSecret", flag.Lookup("recaptcha-secret")) - - viper.SetEnvPrefix("FB") - viper.AutomaticEnv() - -} - -func printVersion() { - fmt.Println("filebrowser version", filebrowser.Version) - os.Exit(0) -} - -func initConfig() { - // Add a configuration file if set. - if config != "" { - cfg := strings.TrimSuffix(config, filepath.Ext(config)) - if dir := filepath.Dir(cfg); dir != "" { - viper.AddConfigPath(dir) - cfg = strings.TrimPrefix(cfg, dir) - } - viper.SetConfigName(cfg) - } else { - viper.SetConfigName("filebrowser") - viper.AddConfigPath(".") - } - - // Read configuration from a file if exists. - err := viper.ReadInConfig() - if err != nil { - if _, ok := err.(viper.ConfigParseError); ok { - panic(err) - } - } -} - -func main() { - setupViper() - flag.Parse() - - if showVer { - printVersion() - } - - initConfig() - - // Set up process log before anything bad happens. - switch viper.GetString("Logger") { - case "stdout": - log.SetOutput(os.Stdout) - case "stderr": - log.SetOutput(os.Stderr) - case "": - log.SetOutput(ioutil.Discard) - default: - log.SetOutput(&lumberjack.Logger{ - Filename: logfile, - MaxSize: 100, - MaxAge: 14, - MaxBackups: 10, - }) - } - - // Validate the provided config before moving forward - if viper.GetString("AuthMethod") != "none" && viper.GetString("AuthMethod") != "default" && viper.GetString("AuthMethod") != "proxy" { - log.Fatal("The property 'auth.method' needs to be set to 'default' or 'proxy'.") - } - - if viper.GetString("AuthMethod") == "proxy" { - if viper.GetString("LoginHeader") == "" { - log.Fatal("The 'loginHeader' needs to be specified when 'proxy' authentication is used.") - } - log.Println("[WARN] Filebrowser authentication is configured to 'proxy' authentication. This can cause a huge security issue if the infrastructure is not configured correctly.") - } - - // Builds the address and a listener. - laddr := viper.GetString("Address") + ":" + viper.GetString("Port") - listener, err := net.Listen("tcp", laddr) - if err != nil { - log.Fatal(err) - } - - // Tell the user the port in which is listening. - fmt.Println("Listening on", listener.Addr().String()) - - // Starts the server. - if err := http.Serve(listener, handler()); err != nil { - log.Fatal(err) - } -} - -func handler() http.Handler { - db, err := storm.Open(viper.GetString("Database")) - if err != nil { - log.Fatal(err) - } - - recaptchaHost := "https://www.google.com" - if viper.GetBool("AlternativeRecaptcha") { - recaptchaHost = "https://recaptcha.net" - } - - fm := &filebrowser.FileBrowser{ - AuthMethod: viper.GetString("AuthMethod"), - LoginHeader: viper.GetString("LoginHeader"), - NoAuth: viper.GetBool("NoAuth"), - BaseURL: viper.GetString("BaseURL"), - PrefixURL: viper.GetString("PrefixURL"), - ReCaptchaHost: recaptchaHost, - ReCaptchaKey: viper.GetString("ReCaptchaKey"), - ReCaptchaSecret: viper.GetString("ReCaptchaSecret"), - DefaultUser: &filebrowser.User{ - AllowCommands: viper.GetBool("AllowCommands"), - AllowEdit: viper.GetBool("AllowEdit"), - AllowNew: viper.GetBool("AllowNew"), - AllowPublish: viper.GetBool("AllowPublish"), - Commands: viper.GetStringSlice("Commands"), - Rules: []*filebrowser.Rule{}, - Locale: viper.GetString("Locale"), - CSS: "", - Scope: viper.GetString("Scope"), - FileSystem: fileutils.Dir(viper.GetString("Scope")), - ViewMode: viper.GetString("ViewMode"), - }, - Store: &filebrowser.Store{ - Config: bolt.ConfigStore{DB: db}, - Users: bolt.UsersStore{DB: db}, - Share: bolt.ShareStore{DB: db}, - }, - NewFS: func(scope string) filebrowser.FileSystem { - return fileutils.Dir(scope) - }, - } - - err = fm.Setup() - if err != nil { - log.Fatal(err) - } - - switch viper.GetString("StaticGen") { - case "hugo": - hugo := &staticgen.Hugo{ - Root: viper.GetString("Scope"), - Public: filepath.Join(viper.GetString("Scope"), "public"), - Args: []string{}, - CleanPublic: true, - } - - if err = fm.Attach(hugo); err != nil { - log.Fatal(err) - } - case "jekyll": - jekyll := &staticgen.Jekyll{ - Root: viper.GetString("Scope"), - Public: filepath.Join(viper.GetString("Scope"), "_site"), - Args: []string{"build"}, - CleanPublic: true, - } - - if err = fm.Attach(jekyll); err != nil { - log.Fatal(err) - } - } - - return h.Handler(fm) -} diff --git a/bolt/config.go b/lib/bolt/config.go similarity index 92% rename from bolt/config.go rename to lib/bolt/config.go index aeb646b9..59c44a56 100644 --- a/bolt/config.go +++ b/lib/bolt/config.go @@ -2,7 +2,7 @@ package bolt import ( "github.com/asdine/storm" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) // ConfigStore is a configuration store. diff --git a/bolt/share.go b/lib/bolt/share.go similarity index 97% rename from bolt/share.go rename to lib/bolt/share.go index c908bd36..629ecca8 100644 --- a/bolt/share.go +++ b/lib/bolt/share.go @@ -3,7 +3,7 @@ package bolt import ( "github.com/asdine/storm" "github.com/asdine/storm/q" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) // ShareStore is a shareable links store. diff --git a/bolt/users.go b/lib/bolt/users.go similarity index 70% rename from bolt/users.go rename to lib/bolt/users.go index 58976306..43c33fcc 100644 --- a/bolt/users.go +++ b/lib/bolt/users.go @@ -4,7 +4,7 @@ import ( "reflect" "github.com/asdine/storm" - fm "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) // UsersStore is a users store. @@ -13,11 +13,11 @@ type UsersStore struct { } // Get gets a user with a certain id from the database. -func (u UsersStore) Get(id int, builder fm.FSBuilder) (*fm.User, error) { - var us fm.User +func (u UsersStore) Get(id int, builder fb.FSBuilder) (*fb.User, error) { + var us fb.User err := u.DB.One("ID", id, &us) if err == storm.ErrNotFound { - return nil, fm.ErrNotExist + return nil, fb.ErrNotExist } if err != nil { @@ -29,11 +29,11 @@ func (u UsersStore) Get(id int, builder fm.FSBuilder) (*fm.User, error) { } // GetByUsername gets a user with a certain username from the database. -func (u UsersStore) GetByUsername(username string, builder fm.FSBuilder) (*fm.User, error) { - var us fm.User +func (u UsersStore) GetByUsername(username string, builder fb.FSBuilder) (*fb.User, error) { + var us fb.User err := u.DB.One("Username", username, &us) if err == storm.ErrNotFound { - return nil, fm.ErrNotExist + return nil, fb.ErrNotExist } if err != nil { @@ -45,11 +45,11 @@ func (u UsersStore) GetByUsername(username string, builder fm.FSBuilder) (*fm.Us } // Gets gets all the users from the database. -func (u UsersStore) Gets(builder fm.FSBuilder) ([]*fm.User, error) { - var us []*fm.User +func (u UsersStore) Gets(builder fb.FSBuilder) ([]*fb.User, error) { + var us []*fb.User err := u.DB.All(&us) if err == storm.ErrNotFound { - return nil, fm.ErrNotExist + return nil, fb.ErrNotExist } if err != nil { @@ -64,7 +64,7 @@ func (u UsersStore) Gets(builder fm.FSBuilder) ([]*fm.User, error) { } // Update updates the whole user object or only certain fields. -func (u UsersStore) Update(us *fm.User, fields ...string) error { +func (u UsersStore) Update(us *fb.User, fields ...string) error { if len(fields) == 0 { return u.Save(us) } @@ -80,11 +80,11 @@ func (u UsersStore) Update(us *fm.User, fields ...string) error { } // Save saves a user to the database. -func (u UsersStore) Save(us *fm.User) error { +func (u UsersStore) Save(us *fb.User) error { return u.DB.Save(us) } // Delete deletes a user from the database. func (u UsersStore) Delete(id int) error { - return u.DB.DeleteStruct(&fm.User{ID: id}) + return u.DB.DeleteStruct(&fb.User{ID: id}) } diff --git a/doc.go b/lib/doc.go similarity index 99% rename from doc.go rename to lib/doc.go index 23fabeec..91907439 100644 --- a/doc.go +++ b/lib/doc.go @@ -74,4 +74,4 @@ One simple implementation for this, at port 80, in the root of the domain, would http.ListenAndServe(":80", h.Handler(m)) */ -package filebrowser +package lib diff --git a/file.go b/lib/file.go similarity index 99% rename from file.go rename to lib/file.go index 1aa3ebd4..2fb19425 100644 --- a/file.go +++ b/lib/file.go @@ -1,4 +1,4 @@ -package filebrowser +package lib import ( "bytes" diff --git a/filebrowser.go b/lib/filebrowser.go similarity index 99% rename from filebrowser.go rename to lib/filebrowser.go index ed1ac681..9c7f8a78 100644 --- a/filebrowser.go +++ b/lib/filebrowser.go @@ -1,4 +1,4 @@ -package filebrowser +package lib import ( "crypto/rand" diff --git a/http/auth.go b/lib/http/auth.go similarity index 99% rename from http/auth.go rename to lib/http/auth.go index 58d12212..e593e46b 100644 --- a/http/auth.go +++ b/lib/http/auth.go @@ -9,7 +9,7 @@ import ( "github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go/request" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) const reCaptchaAPI = "/recaptcha/api/siteverify" diff --git a/http/download.go b/lib/http/download.go similarity index 98% rename from http/download.go rename to lib/http/download.go index a1a1d08e..d2143646 100644 --- a/http/download.go +++ b/lib/http/download.go @@ -7,7 +7,7 @@ import ( "path/filepath" "strings" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" "github.com/hacdias/fileutils" "github.com/mholt/archiver" ) diff --git a/http/http.go b/lib/http/http.go similarity index 99% rename from http/http.go rename to lib/http/http.go index a5e93311..fd82074a 100644 --- a/http/http.go +++ b/lib/http/http.go @@ -10,7 +10,7 @@ import ( "strings" "time" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) // Handler returns a function compatible with http.HandleFunc. diff --git a/http/resource.go b/lib/http/resource.go similarity index 99% rename from http/resource.go rename to lib/http/resource.go index df776dcc..af39962d 100644 --- a/http/resource.go +++ b/lib/http/resource.go @@ -13,7 +13,7 @@ import ( "strings" "time" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" "github.com/hacdias/fileutils" ) diff --git a/http/settings.go b/lib/http/settings.go similarity index 98% rename from http/settings.go rename to lib/http/settings.go index 1663f5e4..5008bea7 100644 --- a/http/settings.go +++ b/lib/http/settings.go @@ -6,7 +6,7 @@ import ( "net/http" "reflect" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" "github.com/mitchellh/mapstructure" ) diff --git a/http/share.go b/lib/http/share.go similarity index 98% rename from http/share.go rename to lib/http/share.go index df78d24d..79f5236b 100644 --- a/http/share.go +++ b/lib/http/share.go @@ -8,7 +8,7 @@ import ( "strings" "time" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) func shareHandler(c *fb.Context, w http.ResponseWriter, r *http.Request) (int, error) { diff --git a/http/subtitle.go b/lib/http/subtitle.go similarity index 97% rename from http/subtitle.go rename to lib/http/subtitle.go index e83f295b..38436162 100644 --- a/http/subtitle.go +++ b/lib/http/subtitle.go @@ -8,7 +8,7 @@ import ( "path/filepath" "regexp" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) func subtitlesHandler(c *fb.Context, w http.ResponseWriter, r *http.Request) (int, error) { diff --git a/http/users.go b/lib/http/users.go similarity index 99% rename from http/users.go rename to lib/http/users.go index f924e304..e4b24be9 100644 --- a/http/users.go +++ b/lib/http/users.go @@ -9,7 +9,7 @@ import ( "strconv" "strings" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) type modifyRequest struct { diff --git a/http/websockets.go b/lib/http/websockets.go similarity index 99% rename from http/websockets.go rename to lib/http/websockets.go index e135d110..54178e5b 100644 --- a/http/websockets.go +++ b/lib/http/websockets.go @@ -12,7 +12,7 @@ import ( "strings" "time" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" "github.com/gorilla/websocket" ) diff --git a/staticgen/hugo.go b/lib/staticgen/hugo.go similarity index 99% rename from staticgen/hugo.go rename to lib/staticgen/hugo.go index d9e989a6..f8c6d7a5 100644 --- a/staticgen/hugo.go +++ b/lib/staticgen/hugo.go @@ -10,7 +10,7 @@ import ( "path/filepath" "strings" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" "github.com/hacdias/varutils" ) diff --git a/staticgen/jekyll.go b/lib/staticgen/jekyll.go similarity index 98% rename from staticgen/jekyll.go rename to lib/staticgen/jekyll.go index c8902798..ba119fcc 100644 --- a/staticgen/jekyll.go +++ b/lib/staticgen/jekyll.go @@ -9,7 +9,7 @@ import ( "path/filepath" "strings" - fb "github.com/filebrowser/filebrowser" + fb "github.com/filebrowser/filebrowser/lib" ) // Jekyll is the Jekyll static website generator. diff --git a/staticgen/staticgen.go b/lib/staticgen/staticgen.go similarity index 100% rename from staticgen/staticgen.go rename to lib/staticgen/staticgen.go