OAuth

/app/lib/user/permission.go (2.3 KB)

 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
}