github.com/kyleu/dbaudit@v0.0.2-0.20240321155047-ff2f2c940496/app/lib/user/permission.go (about) 1 // Package user - Content managed by Project Forge, see [projectforge.md] for details. 2 package user 3 4 import ( 5 "cmp" 6 "fmt" 7 "slices" 8 "strings" 9 10 "github.com/kyleu/dbaudit/app/util" 11 ) 12 13 const permPrefix = "perm: " 14 15 var ( 16 PermissionsLogger util.Logger 17 perms Permissions 18 ) 19 20 func SetPermissions(allowDefault bool, ps ...*Permission) { 21 perms = make(Permissions, 0, len(ps)+4) 22 perms = append(perms, Perm("/auth", "*", true), Perm("/profile", "*", true)) 23 perms = append(perms, ps...) 24 perms = append(perms, Perm("/admin", "*", false), Perm("/about", "*", true), Perm("/", "*", allowDefault)) 25 } 26 27 func GetPermissions() Permissions { 28 ret := make(Permissions, 0, len(perms)) 29 return append(ret, perms...) 30 } 31 32 type Permission struct { 33 Path string `json:"path"` 34 Match string `json:"match"` 35 Allow bool `json:"allow"` 36 } 37 38 func Check(path string, accounts Accounts) (bool, string) { 39 return perms.Check(path, accounts) 40 } 41 42 func IsAdmin(accounts Accounts) bool { 43 ret, _ := perms.Check("/admin", accounts) 44 return ret 45 } 46 47 func Perm(p string, m string, a bool) *Permission { 48 return &Permission{Path: p, Match: m, Allow: a} 49 } 50 51 func (p Permission) Matches(path string) bool { 52 return strings.HasPrefix(path, p.Path) 53 } 54 55 func (p Permission) String() string { 56 return fmt.Sprintf("%s [%s::%t]", p.Path, p.Match, p.Allow) 57 } 58 59 type Permissions []*Permission 60 61 func (p Permissions) Sort() { 62 slices.SortFunc(p, func(l *Permission, r *Permission) int { 63 if l.Path == r.Path { 64 return cmp.Compare(l.Match, r.Match) 65 } 66 return cmp.Compare(l.Path, r.Path) 67 }) 68 } 69 70 func (p Permissions) Check(path string, accounts Accounts) (bool, string) { 71 if PermissionsLogger != nil { 72 PermissionsLogger.Debugf(permPrefix+"checking [%d] permissions for [%s]", len(p), accounts.String()) 73 } 74 if len(p) == 0 { 75 const msg = "no permissions configured" 76 if PermissionsLogger != nil { 77 PermissionsLogger.Debug(permPrefix + msg) 78 } 79 return true, msg 80 } 81 for _, perm := range p { 82 if perm.Matches(path) { 83 if accounts.Matches(perm.Match) { 84 msg := fmt.Sprintf("matched [%s], result [%t]", perm.Match, perm.Allow) 85 if PermissionsLogger != nil { 86 PermissionsLogger.Debug(permPrefix + msg) 87 } 88 return perm.Allow, msg 89 } 90 } 91 } 92 msg := fmt.Sprintf("no matches among [%d] permissions", len(p)) 93 if PermissionsLogger != nil { 94 PermissionsLogger.Debug(permPrefix + msg) 95 } 96 return false, msg 97 }