filebrowser/config/config.go

255 lines
5.7 KiB
Go
Raw Normal View History

2016-06-25 20:57:10 +00:00
package config
import (
"fmt"
"io/ioutil"
2016-12-18 12:34:31 +00:00
"net/http"
2016-08-20 20:48:04 +00:00
"regexp"
2016-08-20 19:34:08 +00:00
"strconv"
2016-06-25 20:57:10 +00:00
"strings"
2016-10-17 20:05:52 +00:00
"golang.org/x/net/webdav"
2016-06-25 20:57:10 +00:00
"github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/httpserver"
2016-06-25 20:57:10 +00:00
)
2016-10-31 21:25:14 +00:00
// Config is a configuration for browsing in a particular path.
2016-06-25 20:57:10 +00:00
type Config struct {
2016-08-22 10:37:56 +00:00
*User
2016-11-14 20:09:30 +00:00
PrefixURL string
2016-10-18 20:06:31 +00:00
BaseURL string
WebDavURL string
2016-10-18 20:06:31 +00:00
Token string // Anti CSRF token
HugoEnabled bool // Enables the Hugo plugin for File Manager
Users map[string]*User
2016-12-18 12:36:36 +00:00
BeforeSave CommandFunc
AfterSave CommandFunc
2016-08-20 20:48:04 +00:00
}
2016-08-20 19:34:08 +00:00
2016-12-18 12:34:31 +00:00
// AbsoluteURL ...
2016-11-14 20:09:30 +00:00
func (c Config) AbsoluteURL() string {
return c.PrefixURL + c.BaseURL
2016-11-06 13:17:07 +00:00
}
2016-08-21 17:44:22 +00:00
// Rule is a dissalow/allow rule
type Rule struct {
Regex bool
Allow bool
Path string
2016-08-22 10:37:56 +00:00
Regexp *regexp.Regexp
2016-06-25 20:57:10 +00:00
}
// Parse parses the configuration set by the user so it can
// be used by the middleware
func Parse(c *caddy.Controller) ([]Config, error) {
var (
configs []Config
err error
user *User
)
2016-06-25 20:57:10 +00:00
appendConfig := func(cfg Config) error {
for _, c := range configs {
2016-10-18 20:06:31 +00:00
if c.Scope == cfg.Scope {
return fmt.Errorf("duplicate file managing config for %s", c.Scope)
2016-06-25 20:57:10 +00:00
}
}
configs = append(configs, cfg)
return nil
}
for c.Next() {
// Initialize the configuration with the default settings
cfg := Config{User: &User{}}
2016-10-18 20:06:31 +00:00
cfg.Scope = "."
cfg.FileSystem = webdav.Dir(cfg.Scope)
2016-08-21 18:44:09 +00:00
cfg.BaseURL = ""
2016-08-20 20:48:04 +00:00
cfg.HugoEnabled = false
2016-08-22 10:37:56 +00:00
cfg.Users = map[string]*User{}
2016-08-21 18:07:33 +00:00
cfg.AllowCommands = true
cfg.AllowEdit = true
cfg.AllowNew = true
cfg.Commands = []string{"git", "svn", "hg"}
2016-12-18 12:34:31 +00:00
cfg.BeforeSave = func(r *http.Request, c *Config, u *User) error { return nil }
cfg.AfterSave = func(r *http.Request, c *Config, u *User) error { return nil }
2016-10-31 21:25:14 +00:00
cfg.Rules = []*Rule{{
2016-08-22 10:37:56 +00:00
Regex: true,
Allow: false,
Regexp: regexp.MustCompile("\\/\\..+"),
}}
2016-08-20 21:15:29 +00:00
2016-08-22 11:24:26 +00:00
// Get the baseURL
args := c.RemainingArgs()
if len(args) > 0 {
cfg.BaseURL = args[0]
}
2016-10-17 20:05:52 +00:00
cfg.BaseURL = strings.TrimPrefix(cfg.BaseURL, "/")
cfg.BaseURL = strings.TrimSuffix(cfg.BaseURL, "/")
cfg.BaseURL = "/" + cfg.BaseURL
2016-11-06 13:17:07 +00:00
cfg.WebDavURL = "webdav"
2016-10-17 20:05:52 +00:00
if cfg.BaseURL == "/" {
cfg.BaseURL = ""
}
// Set the first user, the global user
user = cfg.User
2016-08-20 20:48:04 +00:00
2016-06-25 20:57:10 +00:00
for c.NextBlock() {
switch c.Val() {
2016-12-18 12:34:31 +00:00
case "before_save":
if cfg.BeforeSave, err = CommandRunner(c); err != nil {
return configs, err
}
case "after_save":
if cfg.AfterSave, err = CommandRunner(c); err != nil {
return configs, err
}
2016-10-17 20:05:52 +00:00
case "webdav":
2016-10-18 15:42:48 +00:00
if !c.NextArg() {
return configs, c.ArgErr()
2016-10-17 20:05:52 +00:00
}
2016-10-18 15:42:48 +00:00
prefix := c.Val()
2016-10-17 20:05:52 +00:00
prefix = strings.TrimPrefix(prefix, "/")
prefix = strings.TrimSuffix(prefix, "/")
prefix = cfg.BaseURL + "/" + prefix
cfg.WebDavURL = prefix
2016-08-20 21:15:29 +00:00
case "show":
2016-06-25 20:57:10 +00:00
if !c.NextArg() {
return configs, c.ArgErr()
}
2016-10-18 20:06:31 +00:00
user.Scope = c.Val()
user.Scope = strings.TrimSuffix(user.Scope, "/")
user.FileSystem = webdav.Dir(user.Scope)
2016-06-25 20:57:10 +00:00
case "styles":
if !c.NextArg() {
return configs, c.ArgErr()
}
2016-08-20 19:34:08 +00:00
var tplBytes []byte
tplBytes, err = ioutil.ReadFile(c.Val())
2016-06-25 20:57:10 +00:00
if err != nil {
return configs, err
}
user.StyleSheet = string(tplBytes)
2016-08-20 19:34:08 +00:00
case "allow_new":
if !c.NextArg() {
return configs, c.ArgErr()
}
user.AllowNew, err = strconv.ParseBool(c.Val())
2016-08-20 19:34:08 +00:00
if err != nil {
return configs, err
}
case "allow_edit":
if !c.NextArg() {
return configs, c.ArgErr()
}
user.AllowEdit, err = strconv.ParseBool(c.Val())
2016-08-20 19:34:08 +00:00
if err != nil {
return configs, err
}
2016-08-21 18:07:33 +00:00
case "allow_commands":
2016-08-20 19:34:08 +00:00
if !c.NextArg() {
return configs, c.ArgErr()
}
user.AllowCommands, err = strconv.ParseBool(c.Val())
2016-08-20 19:34:08 +00:00
if err != nil {
return configs, err
}
2016-08-21 18:07:33 +00:00
case "allow_command":
if !c.NextArg() {
return configs, c.ArgErr()
}
user.Commands = append(user.Commands, c.Val())
2016-08-21 18:07:33 +00:00
case "block_command":
if !c.NextArg() {
return configs, c.ArgErr()
}
index := 0
for i, val := range user.Commands {
2016-08-21 18:07:33 +00:00
if val == c.Val() {
index = i
}
}
user.Commands = append(user.Commands[:index], user.Commands[index+1:]...)
case "allow", "allow_r", "block", "block_r":
ruleType := c.Val()
2016-08-21 18:07:33 +00:00
if !c.NextArg() {
return configs, c.ArgErr()
}
if c.Val() == "dotfiles" && !strings.HasSuffix(ruleType, "_r") {
ruleType += "_r"
2016-08-21 18:07:33 +00:00
}
rule := &Rule{
Allow: ruleType == "allow" || ruleType == "allow_r",
Regex: ruleType == "allow_r" || ruleType == "block_r",
2016-08-21 18:07:33 +00:00
}
if rule.Regex && c.Val() == "dotfiles" {
rule.Regexp = regexp.MustCompile("\\/\\..+")
} else if rule.Regex {
rule.Regexp = regexp.MustCompile(c.Val())
} else {
rule.Path = c.Val()
2016-08-21 18:07:33 +00:00
}
user.Rules = append(user.Rules, rule)
2016-08-20 21:15:29 +00:00
// NEW USER BLOCK?
default:
val := c.Val()
2016-08-20 21:15:29 +00:00
// Checks if it's a new user
if !strings.HasSuffix(val, ":") {
fmt.Println("Unknown option " + val)
}
// Get the username, sets the current user, and initializes it
val = strings.TrimSuffix(val, ":")
2016-08-22 10:37:56 +00:00
cfg.Users[val] = &User{}
2016-08-21 18:07:33 +00:00
// Initialize the new user
user = cfg.Users[val]
user.AllowCommands = cfg.AllowCommands
user.AllowEdit = cfg.AllowEdit
user.AllowNew = cfg.AllowEdit
user.Commands = cfg.Commands
2016-10-18 20:06:31 +00:00
user.Scope = cfg.Scope
user.FileSystem = cfg.FileSystem
user.Rules = cfg.Rules
user.StyleSheet = cfg.StyleSheet
2016-06-25 20:57:10 +00:00
}
}
2016-11-06 13:17:07 +00:00
caddyConf := httpserver.GetConfig(c)
2016-11-14 20:09:30 +00:00
cfg.PrefixURL = strings.TrimSuffix(caddyConf.Addr.Path, "/")
2016-11-06 13:17:07 +00:00
cfg.WebDavURL = "/" + strings.TrimPrefix(cfg.WebDavURL, "/")
2016-10-18 20:06:31 +00:00
cfg.Handler = &webdav.Handler{
2016-11-14 20:09:30 +00:00
Prefix: cfg.BaseURL + cfg.WebDavURL,
2016-10-18 20:06:31 +00:00
FileSystem: cfg.FileSystem,
2016-10-18 15:42:48 +00:00
LockSystem: webdav.NewMemLS(),
}
2016-06-25 20:57:10 +00:00
if err := appendConfig(cfg); err != nil {
return configs, err
}
}
return configs, nil
}