2019-01-05 22:44:33 +00:00
package cmd
import (
"crypto/tls"
"io/ioutil"
"log"
"net"
"net/http"
"os"
2019-01-06 13:01:42 +00:00
"path/filepath"
2019-01-05 22:44:33 +00:00
"strconv"
2019-01-06 05:11:15 +00:00
"strings"
2019-01-05 22:44:33 +00:00
"github.com/asdine/storm"
"github.com/filebrowser/filebrowser/v2/auth"
2019-01-06 13:20:17 +00:00
fbhttp "github.com/filebrowser/filebrowser/v2/http"
2019-01-05 22:44:33 +00:00
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users"
2019-01-06 13:20:17 +00:00
"github.com/mitchellh/go-homedir"
2019-01-05 22:44:33 +00:00
"github.com/spf13/cobra"
2019-01-06 05:11:15 +00:00
v "github.com/spf13/viper"
2019-01-05 22:44:33 +00:00
lumberjack "gopkg.in/natefinch/lumberjack.v2"
)
2019-01-06 05:11:15 +00:00
var (
cfgFile string
)
func init ( ) {
f := rootCmd . Flags ( )
pf := rootCmd . PersistentFlags ( )
2019-01-06 13:20:17 +00:00
f . StringVarP ( & cfgFile , "config" , "c" , "" , "config file (defaults are './.filebrowser[ext]', '$HOME/.filebrowser[ext]' or '/etc/filebrowser/.filebrowser[ext]')" )
2019-01-06 05:11:15 +00:00
vaddP ( pf , "database" , "d" , "./filebrowser.db" , "path to the database" )
2019-01-06 13:20:17 +00:00
vaddP ( f , "address" , "a" , "127.0.0.1" , "address to listen on" )
vaddP ( f , "log" , "l" , "stdout" , "log output" )
vaddP ( f , "port" , "p" , 8080 , "port to listen on" )
vaddP ( f , "cert" , "t" , "" , "tls certificate" )
vaddP ( f , "key" , "k" , "" , "tls key" )
vaddP ( f , "scope" , "s" , "." , "scope to prepend to a user's scope when it is relative" )
2019-01-06 05:11:15 +00:00
if err := v . BindPFlags ( f ) ; err != nil {
panic ( err )
}
2019-01-06 13:20:17 +00:00
2019-01-06 05:11:15 +00:00
if err := v . BindPFlags ( pf ) ; err != nil {
panic ( err )
}
}
2019-01-05 22:44:33 +00:00
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 user and all the configurations without accessing the
web interface .
2019-01-06 05:11:15 +00:00
2019-01-05 22:44:33 +00:00
If you ' ve never run File Browser , you will need to create the database .
2019-01-06 12:26:48 +00:00
See ' filebrowser help config init ' for more information . ` ,
Run : serveAndListen ,
2019-01-05 22:44:33 +00:00
}
2019-01-06 05:11:15 +00:00
2019-01-06 12:26:48 +00:00
func serveAndListen ( cmd * cobra . Command , args [ ] string ) {
2019-01-06 13:20:17 +00:00
initConfig ( )
2019-01-06 05:11:15 +00:00
2019-01-06 13:20:17 +00:00
switch logMethod := v . GetString ( "log" ) ; logMethod {
2019-01-05 22:44:33 +00:00
case "stdout" :
log . SetOutput ( os . Stdout )
case "stderr" :
log . SetOutput ( os . Stderr )
case "" :
log . SetOutput ( ioutil . Discard )
default :
log . SetOutput ( & lumberjack . Logger {
2019-01-06 12:26:48 +00:00
Filename : logMethod ,
2019-01-05 22:44:33 +00:00
MaxSize : 100 ,
MaxAge : 14 ,
MaxBackups : 10 ,
} )
}
2019-01-06 05:11:15 +00:00
2019-01-06 13:20:17 +00:00
if _ , err := os . Stat ( v . GetString ( "database" ) ) ; os . IsNotExist ( err ) {
2019-01-06 12:26:48 +00:00
quickSetup ( cmd )
}
2019-01-06 05:11:15 +00:00
2019-01-06 12:26:48 +00:00
db := getDB ( )
defer db . Close ( )
st := getStorage ( db )
2019-01-06 05:11:15 +00:00
2019-01-06 13:20:17 +00:00
port := v . GetInt ( "port" )
address := v . GetString ( "address" )
cert := v . GetString ( "cert" )
key := v . GetString ( "key" )
scope := v . GetString ( "scope" )
2019-01-06 05:11:15 +00:00
2019-01-06 13:01:42 +00:00
scope , err := filepath . Abs ( scope )
checkErr ( err )
settings , err := st . Settings . Get ( )
checkErr ( err )
settings . Scope = scope
err = st . Settings . Save ( settings )
checkErr ( err )
2019-01-06 05:11:15 +00:00
2019-01-06 12:26:48 +00:00
handler , err := fbhttp . NewHandler ( st )
checkErr ( err )
2019-01-06 05:11:15 +00:00
2019-01-06 12:26:48 +00:00
var listener net . Listener
2019-01-06 05:11:15 +00:00
2019-01-06 12:26:48 +00:00
if key != "" && cert != "" {
cer , err := tls . LoadX509KeyPair ( cert , key )
checkErr ( err )
config := & tls . Config { Certificates : [ ] tls . Certificate { cer } }
listener , err = tls . Listen ( "tcp" , address + ":" + strconv . Itoa ( port ) , config )
checkErr ( err )
} else {
listener , err = net . Listen ( "tcp" , address + ":" + strconv . Itoa ( port ) )
checkErr ( err )
2019-01-06 05:11:15 +00:00
}
2019-01-06 12:26:48 +00:00
log . Println ( "Listening on" , listener . Addr ( ) . String ( ) )
if err := http . Serve ( listener , handler ) ; err != nil {
log . Fatal ( err )
2019-01-05 22:44:33 +00:00
}
}
func quickSetup ( cmd * cobra . Command ) {
2019-01-06 05:11:15 +00:00
db , err := storm . Open ( v . GetString ( "database" ) )
2019-01-05 22:44:33 +00:00
checkErr ( err )
defer db . Close ( )
set := & settings . Settings {
Key : generateRandomBytes ( 64 ) , // 256 bit
BaseURL : "" ,
Signup : false ,
AuthMethod : auth . MethodJSONAuth ,
Defaults : settings . UserDefaults {
2019-01-06 13:01:42 +00:00
Scope : "." ,
2019-01-05 22:44:33 +00:00
Locale : "en" ,
Perm : users . Permissions {
Admin : false ,
Execute : true ,
Create : true ,
Rename : true ,
Modify : true ,
Delete : true ,
Share : true ,
Download : true ,
} ,
} ,
}
st := getStorage ( db )
err = st . Settings . Save ( set )
checkErr ( err )
err = st . Auth . Save ( & auth . JSONAuth { } )
checkErr ( err )
password , err := users . HashPwd ( "admin" )
checkErr ( err )
user := & users . User {
Username : "admin" ,
Password : password ,
LockPassword : false ,
}
set . Defaults . Apply ( user )
user . Perm . Admin = true
err = st . Users . Save ( user )
checkErr ( err )
}
2019-01-06 13:20:17 +00:00
// initConfig reads in config file and ENV variables if set.
func initConfig ( ) {
if cfgFile == "" {
home , err := homedir . Dir ( )
2019-01-05 22:44:33 +00:00
checkErr ( err )
2019-01-06 13:20:17 +00:00
v . AddConfigPath ( "." )
v . AddConfigPath ( home )
v . AddConfigPath ( "/etc/filebrowser/" )
v . SetConfigName ( ".filebrowser" )
2019-01-05 22:44:33 +00:00
} else {
2019-01-06 13:20:17 +00:00
v . SetConfigFile ( cfgFile )
2019-01-05 22:44:33 +00:00
}
2019-01-06 13:20:17 +00:00
v . SetEnvPrefix ( "FB" )
v . AutomaticEnv ( )
v . SetEnvKeyReplacer ( strings . NewReplacer ( "." , "_" ) )
2019-01-05 22:44:33 +00:00
2019-01-06 13:20:17 +00:00
if err := v . ReadInConfig ( ) ; err != nil {
if _ , ok := err . ( v . ConfigParseError ) ; ok {
panic ( err )
}
log . Println ( "No config file provided" )
} else {
log . Println ( "Using config file:" , v . ConfigFileUsed ( ) )
}
2019-01-05 22:44:33 +00:00
}