mirror of
https://github.com/hacdias/webdav.git
synced 2026-09-26 13:11:54 +08:00
fix: check permissions at copy/move source and destination (#181)
This commit is contained in:
+51
-15
@@ -39,17 +39,38 @@ type UserPermissions struct {
|
||||
}
|
||||
|
||||
// Allowed checks if the user has permission to access a directory/file
|
||||
func (p UserPermissions) Allowed(r *http.Request, destinationExists func(string) bool) bool {
|
||||
// Go through rules beginning from the last one.
|
||||
for i := len(p.Rules) - 1; i >= 0; i-- {
|
||||
rule := p.Rules[i]
|
||||
func (p UserPermissions) Allowed(r *http.Request, fileExists func(string) bool) bool {
|
||||
// For COPY and MOVE requests, we first check the permissions for the destination
|
||||
// path. As soon as a rule matches and does not allow the operation at the destination,
|
||||
// we fail immediately. If no rule matches, we check the global permissions.
|
||||
if r.Method == "COPY" || r.Method == "MOVE" {
|
||||
dst := r.Header.Get("Destination")
|
||||
|
||||
if rule.Matches(r.URL.Path) {
|
||||
return rule.Permissions.Allowed(r, destinationExists)
|
||||
for i := len(p.Rules) - 1; i >= 0; i-- {
|
||||
if p.Rules[i].Matches(dst) {
|
||||
if !p.Rules[i].Permissions.AllowedDestination(r, fileExists) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Only check the first rule that matches, similarly to the source rules.
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !p.Permissions.AllowedDestination(r, fileExists) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return p.Permissions.Allowed(r, destinationExists)
|
||||
// Go through rules beginning from the last one, and check the permissions at
|
||||
// the source. The first matched rule returns.
|
||||
for i := len(p.Rules) - 1; i >= 0; i-- {
|
||||
if p.Rules[i].Matches(r.URL.Path) {
|
||||
return p.Rules[i].Permissions.Allowed(r, fileExists)
|
||||
}
|
||||
}
|
||||
|
||||
return p.Permissions.Allowed(r, fileExists)
|
||||
}
|
||||
|
||||
func (p *UserPermissions) Validate() error {
|
||||
@@ -100,7 +121,9 @@ func (p *Permissions) UnmarshalText(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p Permissions) Allowed(r *http.Request, destinationExists func(string) bool) bool {
|
||||
// Allowed returns whether this permission set has permissions to execute this
|
||||
// request in the source directory. This applies to all requests with all methods.
|
||||
func (p Permissions) Allowed(r *http.Request, fileExists func(string) bool) bool {
|
||||
switch r.Method {
|
||||
case "GET", "HEAD", "OPTIONS", "POST", "PROPFIND":
|
||||
// Note: POST backend implementation just returns the same thing as GET.
|
||||
@@ -110,17 +133,15 @@ func (p Permissions) Allowed(r *http.Request, destinationExists func(string) boo
|
||||
case "PROPPATCH":
|
||||
return p.Update
|
||||
case "PUT":
|
||||
if destinationExists(r.URL.Path) {
|
||||
return p.Update
|
||||
} else {
|
||||
return p.Create
|
||||
}
|
||||
case "COPY", "MOVE":
|
||||
if destinationExists(r.Header.Get("Destination")) {
|
||||
if fileExists(r.URL.Path) {
|
||||
return p.Update
|
||||
} else {
|
||||
return p.Create
|
||||
}
|
||||
case "COPY":
|
||||
return p.Read
|
||||
case "MOVE":
|
||||
return p.Read && p.Delete
|
||||
case "DELETE":
|
||||
return p.Delete
|
||||
case "LOCK", "UNLOCK":
|
||||
@@ -129,3 +150,18 @@ func (p Permissions) Allowed(r *http.Request, destinationExists func(string) boo
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// AllowedDestination returns whether this permissions set has permissions to execute this
|
||||
// request in the destination directory. This only applies for COPY and MOVE requests.
|
||||
func (p Permissions) AllowedDestination(r *http.Request, fileExists func(string) bool) bool {
|
||||
switch r.Method {
|
||||
case "COPY", "MOVE":
|
||||
if fileExists(r.Header.Get("Destination")) {
|
||||
return p.Update
|
||||
} else {
|
||||
return p.Create
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user