mirror of
https://github.com/hacdias/webdav.git
synced 2024-04-21 12:32:06 +00:00
feat: per path modify permissions (#57)
This commit is contained in:
@@ -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.
|
||||
|
||||
+11
-3
@@ -14,7 +14,7 @@ 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 {
|
||||
@@ -22,6 +22,7 @@ func parseRules(raw []interface{}) []*lib.Rule {
|
||||
rule := &lib.Rule{
|
||||
Regex: false,
|
||||
Allow: false,
|
||||
Modify: defaultModify,
|
||||
Path: "",
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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{
|
||||
@@ -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")
|
||||
|
||||
+6
-4
@@ -11,6 +11,7 @@ import (
|
||||
type Rule struct {
|
||||
Regex bool
|
||||
Allow bool
|
||||
Modify bool
|
||||
Path string
|
||||
Regexp *regexp.Regexp
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+3
-10
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user