85 lines
1.5 KiB
Go
85 lines
1.5 KiB
Go
package lib
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var readMethods = []string{
|
|
http.MethodGet,
|
|
http.MethodHead,
|
|
http.MethodOptions,
|
|
"PROPFIND",
|
|
}
|
|
|
|
type Rule struct {
|
|
Regex bool
|
|
Allow bool
|
|
Modify bool
|
|
Path string
|
|
// TODO: remove Regex and replace by this. It encodes
|
|
Regexp *regexp.Regexp `mapstructure:"-"`
|
|
}
|
|
|
|
func (r *Rule) Validate() error {
|
|
if r.Regex {
|
|
rp, err := regexp.Compile(r.Path)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid rule: %w", err)
|
|
}
|
|
r.Regexp = rp
|
|
r.Path = ""
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Matches checks if [Rule] matches the given path.
|
|
func (r *Rule) Matches(path string) bool {
|
|
if r.Regex {
|
|
return r.Regexp.MatchString(path)
|
|
}
|
|
|
|
return strings.HasPrefix(path, r.Path)
|
|
}
|
|
|
|
type Permissions struct {
|
|
Scope 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 {
|
|
for _, r := range p.Rules {
|
|
if err := r.Validate(); err != nil {
|
|
return fmt.Errorf("invalid permissions: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|