-
Notifications
You must be signed in to change notification settings - Fork 1
/
role.go
116 lines (90 loc) · 2.5 KB
/
role.go
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package types
import (
"sort"
"strings"
"github.com/bmatcuk/doublestar/v4"
"github.com/go-playground/validator/v10"
)
// Role holds an role
type (
Role struct {
// Name of role (not changable)
Name string `validate:"required,min=1,max=100"`
// Display name
DisplayName string
// Allowed methods & paths
Permissions `validate:"required"`
// Created at timestamp in epoch milliseconds
CreatedAt int64
// Name of user who created this role
CreatedBy string
// Last modified at timestamp in epoch milliseconds
LastModifiedAt int64
// Name of user who last updated this role
LastModifiedBy string
}
// Roles holds one or more roles
Roles []Role
)
// Permission holds the criteria a role will allow request
type Permission struct {
// Request methods which are allowed
// FIXME these bindings settings do not get used...
Methods []string `validate:"dive,oneof=GET POST PUT PATCH DELETE,required"`
// Request paths (regexp) which are allowed
Paths []string `validate:"dive,startswith=/,required"`
}
// Permissions holds one or more allow
type Permissions []Permission
var (
// NullRole is an empty role type
NullRole = Role{}
// NullRoles is an empty role slice
NullRoles = Roles{}
// NullPermission is an allow type
NullPermission = Permission{}
// NullPermissions is an allows type
NullPermissions = Permissions{}
)
// Validate checks if field values are set correct and are allowed
func (r *Role) Validate() error {
validate := validator.New()
return validate.Struct(r)
}
// IsPathAllowed checks whether role is allowed to access a path
func (r *Role) IsPathAllowed(requestMethod, requestPath string) bool {
for _, allow := range r.Permissions {
if methodMatch(allow.Methods, requestMethod) &&
pathMatch(allow.Paths, requestPath) {
return true
}
}
// by default we do not allow access
return false
}
// methodMatch checks if methods exists in a slice of methods
func methodMatch(methods []string, requestMethod string) bool {
for _, method := range methods {
if requestMethod == strings.ToUpper(method) {
return true
}
}
return false
}
// pathMatch checks if path matches one of the paths
func pathMatch(paths []string, requestPath string) bool {
for _, path := range paths {
matched, err := doublestar.Match(path, requestPath)
if err == nil && matched {
return true
}
}
return false
}
// Sort a slice of users
func (roles Roles) Sort() {
// Sort roles by name
sort.SliceStable(roles, func(i, j int) bool {
return roles[i].Name < roles[j].Name
})
}