Skip to content

Commit

Permalink
feat: per path modify permissions (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikitsu authored Jan 14, 2021
1 parent fca4e54 commit 8cd6d0a
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 17 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ users:
- regex: false
allow: false
path: /some/file
- path: /public/access/
modify: true
```
There are more ways to customize how you run WebDAV through flags and environment variables. Please run `webdav --help` for more information on that.
Expand Down
14 changes: 11 additions & 3 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import (
"golang.org/x/net/webdav"
)

func parseRules(raw []interface{}) []*lib.Rule {
func parseRules(raw []interface{}, defaultModify bool) []*lib.Rule {
rules := []*lib.Rule{}

for _, v := range raw {
if r, ok := v.(map[interface{}]interface{}); ok {
rule := &lib.Rule{
Regex: false,
Allow: false,
Modify: defaultModify,
Path: "",
}

Expand All @@ -33,6 +34,13 @@ func parseRules(raw []interface{}) []*lib.Rule {
rule.Allow = allow
}

if modify, ok := r["modify"].(bool); ok {
rule.Modify = modify
if modify {
rule.Allow = true
}
}

path, ok := r["path"].(string)
if !ok {
continue
Expand Down Expand Up @@ -110,7 +118,7 @@ func parseUsers(raw []interface{}, c *lib.Config) {
}

if rules, ok := u["rules"].([]interface{}); ok {
user.Rules = parseRules(rules)
user.Rules = append(c.User.Rules, parseRules(rules, user.Modify)...)
}

user.Handler = &webdav.Handler{
Expand Down Expand Up @@ -186,7 +194,7 @@ func readConfig(flags *pflag.FlagSet) *lib.Config {

rawRules := v.Get("rules")
if rules, ok := rawRules.([]interface{}); ok {
cfg.User.Rules = parseRules(rules)
cfg.User.Rules = parseRules(rules, cfg.User.Modify)
}

rawUsers := v.Get("users")
Expand Down
10 changes: 6 additions & 4 deletions lib/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
type Rule struct {
Regex bool
Allow bool
Modify bool
Path string
Regexp *regexp.Regexp
}
Expand All @@ -26,23 +27,24 @@ type User struct {
}

// Allowed checks if the user has permission to access a directory/file
func (u User) Allowed(url string) bool {
func (u User) Allowed(url string, noModification bool) bool {
var rule *Rule
i := len(u.Rules) - 1

for i >= 0 {
rule = u.Rules[i]

isAllowed := rule.Allow && (noModification || rule.Modify)
if rule.Regex {
if rule.Regexp.MatchString(url) {
return rule.Allow
return isAllowed
}
} else if strings.HasPrefix(url, rule.Path) {
return rule.Allow
return isAllowed
}

i--
}

return true
return noModification || u.Modify
}
13 changes: 3 additions & 10 deletions lib/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

// Checks for user permissions relatively to this PATH.
if !u.Allowed(r.URL.Path) {
noModification := r.Method == "GET" || r.Method == "HEAD" ||
r.Method == "OPTIONS" || r.Method == "PROPFIND"
if !u.Allowed(r.URL.Path, noModification) {
w.WriteHeader(http.StatusForbidden)
return
}
Expand All @@ -111,15 +113,6 @@ func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w = newResponseWriterNoBody(w)
}

// If this request modified the files and the user doesn't have permission
// to do so, return forbidden.
if (r.Method == "PUT" || r.Method == "POST" || r.Method == "MKCOL" ||
r.Method == "DELETE" || r.Method == "COPY" || r.Method == "MOVE") &&
!u.Modify {
w.WriteHeader(http.StatusForbidden)
return
}

// Excerpt from RFC4918, section 9.4:
//
// GET, when applied to a collection, may return the contents of an
Expand Down

0 comments on commit 8cd6d0a

Please sign in to comment.