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