-
Notifications
You must be signed in to change notification settings - Fork 1
/
casbin_gorose_adapter.go
195 lines (172 loc) · 5.74 KB
/
casbin_gorose_adapter.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package casbin_gorose_adapter
import (
"errors"
"fmt"
"github.com/casbin/casbin/v2/model"
"github.com/casbin/casbin/v2/persist"
"github.com/gohouse/gorose/v2"
)
// Adapter is the file adapter for Casbin.
// It can load policy from file or save policy to file.
type CasbinGoroseAdapter struct {
*gorose.Engin
}
// CasbinRule casbin_rule table
type CasbinRule struct {
Id string `gorose:"id"`
PType string `gorose:"p_type"`
V0 string `gorose:"v0"`
V1 string `gorose:"v1"`
V2 string `gorose:"v2"`
V3 string `gorose:"v3"`
V4 string `gorose:"v4"`
V5 string `gorose:"v5"`
}
// TableName return table's true name
func (CasbinRule) TableName() string {
return "casbin_rule"
}
// NewCasbinGoroseAdapter is the constructor for Adapter.
func NewAdapter(ge *gorose.Engin) *CasbinGoroseAdapter {
cga := &CasbinGoroseAdapter{ge}
// 建表,如果是mysql驱动的话
if err := cga.createTable(); err != nil {
panic(err.Error())
}
return cga
}
func (a *CasbinGoroseAdapter) createTable() (err error) {
// 如果传入的驱动是mysql,则执行此操作
if a.Engin.GetDriver() == gorose.DriverMysql {
sqlStr := fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s%s (
id int(11) NOT NULL AUTO_INCREMENT,
p_type varchar(32) NOT NULL DEFAULT '' COMMENT 'perm类型:p,g......',
v0 varchar(64) NOT NULL DEFAULT '' COMMENT '角色名字(rbac),其他角色类型则依次存放v0-v5...',
v1 varchar(64) NOT NULL DEFAULT '' COMMENT '对象资源(rbac),其他角色类型则依次存放v0-v5...',
v2 varchar(64) NOT NULL DEFAULT '' COMMENT '权限值(rbac),其他角色类型则依次存放v0-v5...',
v3 varchar(64) NOT NULL DEFAULT '' COMMENT 'ext',
v4 varchar(64) NOT NULL DEFAULT '' COMMENT 'ext',
v5 varchar(64) NOT NULL DEFAULT '' COMMENT 'ext',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='casbin权限规则表';`, a.GetPrefix(),"casbin_rule")
_, err = a.Engin.NewSession().Execute(sqlStr)
}
return
}
// LoadPolicy loads all policy rules from the storage.
func (a *CasbinGoroseAdapter) LoadPolicy(model model.Model) error {
if a.Engin == nil {
return errors.New("invalid gorose.Engin, gorose.Engin cannot be empty")
}
return a.loadPolicyData(model, persist.LoadPolicyLine)
}
// SavePolicy saves all policy rules to the storage.
func (a *CasbinGoroseAdapter) SavePolicy(model model.Model) error {
if a.Engin == nil {
return errors.New("db error")
}
var cr []CasbinRule
for ptype, ast := range model["p"] {
for _, rule := range ast.Policy {
var crrow = a.builCasbinRule(ptype,rule)
cr = append(cr, crrow)
}
}
for ptype, ast := range model["g"] {
for _, rule := range ast.Policy {
var crrow = a.builCasbinRule(ptype,rule)
cr = append(cr, crrow)
}
}
aff, e := a.Engin.NewOrm().Insert(&cr)
if e!=nil {
return e
}
if aff==0 {
return errors.New("insert db fail")
}
return nil
}
func (a *CasbinGoroseAdapter) loadPolicyData(model model.Model, handler func(string, model.Model)) error {
// get rules
var cr []CasbinRule
if e := a.Engin.NewOrm().Table(&cr).Select(); e!=nil {
return e
}
for _, item := range cr {
var line = item.PType
if item.V0 != "" { line = fmt.Sprintf("%s, %s", line, item.V0) }
if item.V1 != "" { line = fmt.Sprintf("%s, %s", line, item.V1) }
if item.V2 != "" { line = fmt.Sprintf("%s, %s", line, item.V2) }
if item.V3 != "" { line = fmt.Sprintf("%s, %s", line, item.V3) }
if item.V4 != "" { line = fmt.Sprintf("%s, %s", line, item.V4) }
if item.V5 != "" { line = fmt.Sprintf("%s, %s", line, item.V5) }
handler(line, model)
}
return nil
}
func (a *CasbinGoroseAdapter) builCasbinRule(ptype string, rule []string) (cr CasbinRule) {
var length = len(rule)
if length == 0 {
return
}
cr.PType = ptype
if length>0 {cr.V0 = rule[0]}
if length>1 {cr.V1 = rule[1]}
if length>2 {cr.V2 = rule[2]}
if length>3 {cr.V3 = rule[3]}
if length>4 {cr.V4 = rule[4]}
if length>5 {cr.V5 = rule[5]}
return
}
// AddPolicy adds a policy rule to the storage.
func (a *CasbinGoroseAdapter) AddPolicy(sec string, ptype string, rule []string) error {
var cr = a.builCasbinRule(ptype, rule)
// insert to db
var db = a.Engin.NewOrm()
aff,err := db.Insert(&cr)
if err!=nil {
return err
}
if aff==0 {
return errors.New("insert db error")
}
return nil
}
// RemovePolicy removes a policy rule from the storage.
func (a *CasbinGoroseAdapter) RemovePolicy(sec string, ptype string, rule []string) error {
var cr = a.builCasbinRule(ptype, rule)
return a.rawDelete(&cr)
}
// RemoveFilteredPolicy removes policy rules that match the filter from the storage.
func (a *CasbinGoroseAdapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
var line CasbinRule
line.PType = ptype
idx := fieldIndex+len(fieldValues)
if fieldIndex <= 0 && 0 < idx { line.V0 = fieldValues[0-fieldIndex] }
if fieldIndex <= 1 && 1 < idx { line.V1 = fieldValues[1-fieldIndex] }
if fieldIndex <= 2 && 2 < idx { line.V2 = fieldValues[2-fieldIndex] }
if fieldIndex <= 3 && 3 < idx { line.V3 = fieldValues[3-fieldIndex] }
if fieldIndex <= 4 && 4 < idx { line.V4 = fieldValues[4-fieldIndex] }
if fieldIndex <= 5 && 5 < idx { line.V5 = fieldValues[5-fieldIndex] }
return a.rawDelete(&line)
}
func (a *CasbinGoroseAdapter) rawDelete(line *CasbinRule) error {
var where = gorose.Data{}
where["p_type"] = line.PType
if line.V0 != "" { where["v0"] = line.V0 }
if line.V1 != "" { where["v1"] = line.V1 }
if line.V2 != "" { where["v2"] = line.V2 }
if line.V3 != "" { where["v3"] = line.V3 }
if line.V4 != "" { where["v4"] = line.V4 }
if line.V5 != "" { where["v5"] = line.V5 }
var db = a.Engin.NewOrm()
aff,err := db.Table(line).Where(where).Delete()
if err!=nil {
return err
}
if aff==0 {
return errors.New("delete fail")
}
return nil
}