-
Notifications
You must be signed in to change notification settings - Fork 0
/
enforcer.go
137 lines (106 loc) · 2.79 KB
/
enforcer.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
137
package casbin
import (
"fmt"
"github.com/sdcxtech/casbin/core"
"github.com/sdcxtech/casbin/core/graph"
)
// Enforcer check if a user has requested permission.
//
// Default to use matcher with name 'm', can be changed by option.
type Enforcer struct {
model *core.Model
policies core.Policies
roleMappings core.RoleMappings
}
type enforceConfig struct {
withRoleGraphs map[string][]*graph.Graph
matcher string
policies core.Policies
rawPolicies [][]string
onlyInjectedPolicies bool
}
// Enforce check if the requested permissions assertion is allowed.
func (e *Enforcer) Enforce(requestValues []string, options ...EnforceOption) (allow bool, err error) {
conf, err := newEnforceConfig(options...)
if err != nil {
return
}
matcher, err := e.model.Matchers().Get(conf.matcher)
if err != nil {
return
}
rVar, err := e.model.Request().CreateAssertion(requestValues)
if err != nil {
err = fmt.Errorf("convert request vals: %w", err)
return
}
prg, err := matcher.Program(
map[string]interface{}{
"r": rVar,
},
e.roleMappings,
conf.withRoleGraphs,
)
if err != nil {
err = fmt.Errorf("new program: %w", err)
return
}
vars := make(map[string]interface{}, 1)
policyEval := func(policy core.Assertion) (allow bool, err error) {
vars["p"] = policy
result, _ /*details*/, _err := prg.Eval(vars)
if _err != nil {
err = _err
return
}
allow, ok := result.Value().(bool)
if !ok {
err = fmt.Errorf(
"%w: eval result should be bool type, but got %s",
core.ErrUnexpectedEvalResult,
result.Type().TypeName(),
)
return
}
return
}
// merge injected policies and glabol policies - start
policies := make([]core.Assertion, 0, len(e.policies)+len(conf.policies)+len(conf.rawPolicies))
// add injected policies first
policies = append(policies, conf.policies...)
if len(conf.rawPolicies) > 0 {
morePolicies, err1 := e.model.Policy().CreateAssertions(conf.rawPolicies)
if err1 != nil {
err = fmt.Errorf("invalid injected raw polices: %w", err1)
return
}
policies = append(policies, morePolicies...)
}
if !conf.onlyInjectedPolicies {
policies = append(policies, e.policies...)
}
// merge injected policies and glabol policies - end
allow, err = e.model.Effector().Execute(policyEval, policies)
if err != nil {
err = fmt.Errorf("effector execute: %w", err)
return
}
return allow, err
}
// NewEnforcer new an enforcer by a model and a policy iterator.
func NewEnforcer(
model *core.Model,
policyItr core.LoadIterator,
) (enforcer *Enforcer, err error) {
policies, roles, err := model.Load(policyItr)
if err != nil {
err = fmt.Errorf("new enforcer: %w", err)
return
}
enforcer = &Enforcer{
model: model,
policies: policies,
roleMappings: roles,
}
return
}