-
Notifications
You must be signed in to change notification settings - Fork 35
/
permission.go
136 lines (115 loc) · 3.51 KB
/
permission.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package roles
import (
"errors"
"fmt"
)
// PermissionMode permission mode
type PermissionMode string
const (
// Create predefined permission mode, create permission
Create PermissionMode = "create"
// Read predefined permission mode, read permission
Read PermissionMode = "read"
// Update predefined permission mode, update permission
Update PermissionMode = "update"
// Delete predefined permission mode, deleted permission
Delete PermissionMode = "delete"
// CRUD predefined permission mode, create+read+update+delete permission
CRUD PermissionMode = "crud"
)
// ErrPermissionDenied no permission error
var ErrPermissionDenied = errors.New("permission denied")
// Permission a struct contains permission definitions
type Permission struct {
Role *Role
AllowedRoles map[PermissionMode][]string
DeniedRoles map[PermissionMode][]string
}
func includeRoles(roles []string, values []string) bool {
for _, role := range roles {
if role == Anyone {
return true
}
for _, value := range values {
if value == role {
return true
}
}
}
return false
}
// Concat concat two permissions into a new one
func (permission *Permission) Concat(newPermission *Permission) *Permission {
var result = Permission{
Role: Global,
AllowedRoles: map[PermissionMode][]string{},
DeniedRoles: map[PermissionMode][]string{},
}
var appendRoles = func(p *Permission) {
if p != nil {
result.Role = p.Role
for mode, roles := range p.DeniedRoles {
result.DeniedRoles[mode] = append(result.DeniedRoles[mode], roles...)
}
for mode, roles := range p.AllowedRoles {
result.AllowedRoles[mode] = append(result.AllowedRoles[mode], roles...)
}
}
}
appendRoles(newPermission)
appendRoles(permission)
return &result
}
// Allow allows permission mode for roles
func (permission *Permission) Allow(mode PermissionMode, roles ...string) *Permission {
if mode == CRUD {
return permission.Allow(Create, roles...).Allow(Update, roles...).Allow(Read, roles...).Allow(Delete, roles...)
}
if permission.AllowedRoles[mode] == nil {
permission.AllowedRoles[mode] = []string{}
}
permission.AllowedRoles[mode] = append(permission.AllowedRoles[mode], roles...)
return permission
}
// Deny deny permission mode for roles
func (permission *Permission) Deny(mode PermissionMode, roles ...string) *Permission {
if mode == CRUD {
return permission.Deny(Create, roles...).Deny(Update, roles...).Deny(Read, roles...).Deny(Delete, roles...)
}
if permission.DeniedRoles[mode] == nil {
permission.DeniedRoles[mode] = []string{}
}
permission.DeniedRoles[mode] = append(permission.DeniedRoles[mode], roles...)
return permission
}
// HasPermission check roles has permission for mode or not
func (permission Permission) HasPermission(mode PermissionMode, roles ...interface{}) bool {
var roleNames []string
for _, role := range roles {
if r, ok := role.(string); ok {
roleNames = append(roleNames, r)
} else if roler, ok := role.(Roler); ok {
roleNames = append(roleNames, roler.GetRoles()...)
} else {
fmt.Printf("invalid role %#v\n", role)
return false
}
}
if len(permission.DeniedRoles) != 0 {
if DeniedRoles := permission.DeniedRoles[mode]; DeniedRoles != nil {
if includeRoles(DeniedRoles, roleNames) {
return false
}
}
}
// return true if haven't define allowed roles
if len(permission.AllowedRoles) == 0 {
return true
}
if AllowedRoles := permission.AllowedRoles[mode]; AllowedRoles != nil {
if includeRoles(AllowedRoles, roleNames) {
return true
}
}
return false
}