mirror of
https://github.com/hacdias/webdav.git
synced 2026-09-22 03:20:41 +08:00
Directory makes it more clear of what it is. In addition, this will make it easier when allowing for multiple directories in the future, since we can just name it 'directories', which is more clear than 'scopes'.
88 lines
1.6 KiB
Go
88 lines
1.6 KiB
Go
package lib
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var readMethods = []string{
|
|
http.MethodGet,
|
|
http.MethodHead,
|
|
http.MethodOptions,
|
|
"PROPFIND",
|
|
}
|
|
|
|
type Rule struct {
|
|
Allow bool
|
|
Modify bool
|
|
Path string
|
|
Regex *regexp.Regexp
|
|
}
|
|
|
|
func (r *Rule) Validate() error {
|
|
if r.Regex != nil && r.Path != "" {
|
|
return errors.New("invalid rule: cannot define both regex and path")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Matches checks if [Rule] matches the given path.
|
|
func (r *Rule) Matches(path string) bool {
|
|
if r.Regex != nil {
|
|
return r.Regex.MatchString(path)
|
|
}
|
|
|
|
return strings.HasPrefix(path, r.Path)
|
|
}
|
|
|
|
type Permissions struct {
|
|
Directory string
|
|
Modify bool
|
|
Rules []*Rule
|
|
}
|
|
|
|
// Allowed checks if the user has permission to access a directory/file
|
|
func (p Permissions) Allowed(r *http.Request) bool {
|
|
// Determine whether or not it is a read or write request.
|
|
readRequest := false
|
|
for _, method := range readMethods {
|
|
if r.Method == method {
|
|
readRequest = true
|
|
break
|
|
}
|
|
}
|
|
|
|
// Go through rules beginning from the last one.
|
|
for i := len(p.Rules) - 1; i >= 0; i-- {
|
|
rule := p.Rules[i]
|
|
|
|
if rule.Matches(r.URL.Path) {
|
|
return rule.Allow && (readRequest || rule.Modify)
|
|
}
|
|
}
|
|
|
|
return readRequest || p.Modify
|
|
}
|
|
|
|
func (p *Permissions) Validate() error {
|
|
var err error
|
|
|
|
p.Directory, err = filepath.Abs(p.Directory)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid permissions: %w", err)
|
|
}
|
|
|
|
for _, r := range p.Rules {
|
|
if err := r.Validate(); err != nil {
|
|
return fmt.Errorf("invalid permissions: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|