filebrowser/cli/cmd/server.go

151 lines
4.0 KiB
Go

package cmd
import (
"io/ioutil"
"log"
"net"
"net/http"
"os"
"path/filepath"
"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"
"github.com/spf13/viper"
"gopkg.in/natefinch/lumberjack.v2"
)
func Serve() {
// Set up process log before anything bad happens.
switch l := viper.GetString("log"); l {
case "stdout":
log.SetOutput(os.Stdout)
case "stderr":
log.SetOutput(os.Stderr)
case "":
log.SetOutput(ioutil.Discard)
default:
log.SetOutput(&lumberjack.Logger{
Filename: l,
MaxSize: 100,
MaxAge: 14,
MaxBackups: 10,
})
}
// Validate the provided config before moving forward
{
// Map of valid authentication methods, containing a boolean value to indicate the need of Auth.Header
validMethods := make(map[string]bool)
validMethods["none"] = false
validMethods["default"] = false
validMethods["proxy"] = true
m := viper.GetString("auth.method")
b, ok := validMethods[m]
if !ok {
log.Fatal("The property 'auth.method' needs to be set to 'none', 'default' or 'proxy'.")
}
if b {
if viper.GetString("auth.header") == "" {
log.Fatal("The 'auth.header' needs to be specified when '", m, "' authentication is used.")
}
log.Println("[WARN] Filebrowser authentication is configured to '", m, "' 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.
log.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)
}
fb := &filebrowser.FileBrowser{
Auth: &filebrowser.Auth{
Method: viper.GetString("auth.method"),
Header: viper.GetString("auth.header"),
},
ReCaptcha: &filebrowser.ReCaptcha{
Host: viper.GetString("recaptcha.host"),
Key: viper.GetString("recaptcha.key"),
Secret: viper.GetString("recaptcha.secret"),
},
DefaultUser: &filebrowser.User{
AllowCommands: viper.GetBool("defaults.allowCommands"),
AllowEdit: viper.GetBool("defaults.allowEdit"),
AllowNew: viper.GetBool("defaults.allowNew"),
AllowPublish: viper.GetBool("defaults.allowPublish"),
Commands: viper.GetStringSlice("defaults.commands"),
Rules: []*filebrowser.Rule{},
Locale: viper.GetString("defaults.locale"),
CSS: "",
Scope: viper.GetString("defaults.scope"),
FileSystem: fileutils.Dir(viper.GetString("defaults.scope")),
ViewMode: viper.GetString("defaults.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)
},
}
fb.SetBaseURL(viper.GetString("baseurl"))
fb.SetPrefixURL(viper.GetString("prefixurl"))
err = fb.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 = fb.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 = fb.Attach(jekyll); err != nil {
log.Fatal(err)
}
}
return h.Handler(fb)
}