github.com/RevenueMonster/sqlike@v1.0.6/plugin/casbin/casbin.go (about) 1 package casbin 2 3 import ( 4 "context" 5 "errors" 6 "strings" 7 8 "github.com/RevenueMonster/sqlike/sql/expr" 9 "github.com/RevenueMonster/sqlike/sqlike" 10 "github.com/RevenueMonster/sqlike/sqlike/actions" 11 "github.com/RevenueMonster/sqlike/sqlike/indexes" 12 "github.com/RevenueMonster/sqlike/sqlike/options" 13 "github.com/RevenueMonster/sqlike/sqlike/primitive" 14 "github.com/casbin/casbin/v2/model" 15 "github.com/casbin/casbin/v2/persist" 16 ) 17 18 // Adapter : 19 type Adapter struct { 20 ctx context.Context 21 table *sqlike.Table 22 filtered bool 23 } 24 25 var _ persist.FilteredAdapter = new(Adapter) 26 27 // MustNew : 28 func MustNew(ctx context.Context, table *sqlike.Table) persist.FilteredAdapter { 29 a, err := New(ctx, table) 30 if err != nil { 31 panic(err) 32 } 33 return a 34 } 35 36 // New : 37 func New(ctx context.Context, table *sqlike.Table) (persist.FilteredAdapter, error) { 38 if table == nil { 39 return nil, errors.New("invalid <nil> table") 40 } 41 a := &Adapter{ 42 ctx: ctx, 43 table: table, 44 } 45 if err := a.createTable(); err != nil { 46 return nil, err 47 } 48 if err := a.table.Indexes(). 49 CreateOneIfNotExists( 50 a.ctx, 51 indexes.Index{ 52 Type: indexes.Primary, 53 Columns: indexes.Columns( 54 "PType", 55 "V0", "V1", "V2", 56 "V3", "V4", "V5", 57 ), 58 }); err != nil { 59 return nil, err 60 } 61 return a, nil 62 } 63 64 // LoadPolicy : 65 func (a *Adapter) LoadPolicy(model model.Model) error { 66 result, err := a.table.Find(a.ctx, nil) 67 if err != nil { 68 return err 69 } 70 71 policies := []*Policy{} 72 if err := result.All(&policies); err != nil { 73 return err 74 } 75 76 for _, r := range policies { 77 loadPolicy(r, model) 78 } 79 return nil 80 } 81 82 // LoadFilteredPolicy : 83 func (a *Adapter) LoadFilteredPolicy(model model.Model, filter interface{}) error { 84 var policies []*Policy 85 x, ok := filter.(primitive.Group) 86 if !ok { 87 return errors.New("invalid filter data type, expected []interface{}") 88 } 89 90 act := new(actions.FindActions) 91 act.Conditions = x 92 result, err := a.table.Find( 93 a.ctx, 94 act, 95 options.Find(). 96 SetNoLimit(true). 97 SetDebug(true), 98 ) 99 if err != nil { 100 return err 101 } 102 103 if err := result.All(&policies); err != nil { 104 return err 105 } 106 107 for _, policy := range policies { 108 loadPolicy(policy, model) 109 } 110 a.filtered = true 111 return nil 112 } 113 114 // SavePolicy : saves all policy rules to the storage. 115 func (a *Adapter) SavePolicy(model model.Model) error { 116 var policies []*Policy 117 for ptype, ast := range model["p"] { 118 for _, r := range ast.Policy { 119 policies = append(policies, toPolicy(ptype, r)) 120 } 121 } 122 123 for ptype, ast := range model["g"] { 124 for _, r := range ast.Policy { 125 policies = append(policies, toPolicy(ptype, r)) 126 } 127 } 128 129 if len(policies) > 0 { 130 if _, err := a.table.Insert( 131 a.ctx, 132 &policies, 133 options.Insert(). 134 SetMode(options.InsertOnDuplicate), 135 ); err != nil { 136 return err 137 } 138 } 139 return nil 140 } 141 142 // AddPolicy : adds a policy policy to the storage. This is part of the Auto-Save feature. 143 func (a *Adapter) AddPolicy(sec string, ptype string, rules []string) error { 144 if _, err := a.table.InsertOne( 145 a.ctx, 146 toPolicy(ptype, rules), 147 options.InsertOne(). 148 SetMode(options.InsertIgnore), 149 ); err != nil { 150 return err 151 } 152 return nil 153 } 154 155 // RemovePolicy : removes a policy policy from the storage. This is part of the Auto-Save feature. 156 func (a *Adapter) RemovePolicy(sec string, ptype string, rules []string) error { 157 policy := toPolicy(ptype, rules) 158 if _, err := a.table.DeleteOne( 159 a.ctx, 160 actions.DeleteOne(). 161 Where( 162 expr.Equal("PType", policy.PType), 163 expr.Equal("V0", policy.V0), 164 expr.Equal("V1", policy.V1), 165 expr.Equal("V2", policy.V2), 166 expr.Equal("V3", policy.V3), 167 expr.Equal("V4", policy.V4), 168 expr.Equal("V5", policy.V5), 169 ), 170 ); err != nil { 171 return err 172 } 173 return nil 174 } 175 176 // RemoveFilteredPolicy : removes policy rules that match the filter from the storage. This is part of the Auto-Save feature. 177 func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, idx int, values ...string) error { 178 policy := new(Policy) 179 policy.PType = ptype 180 length := len(values) 181 if idx <= 0 && 0 < idx+length { 182 policy.V0 = values[0-idx] 183 } 184 if idx <= 1 && 1 < idx+length { 185 policy.V1 = values[1-idx] 186 } 187 if idx <= 2 && 2 < idx+length { 188 policy.V2 = values[2-idx] 189 } 190 if idx <= 3 && 3 < idx+length { 191 policy.V3 = values[3-idx] 192 } 193 if idx <= 4 && 4 < idx+length { 194 policy.V4 = values[4-idx] 195 } 196 if idx <= 5 && 5 < idx+length { 197 policy.V5 = values[5-idx] 198 } 199 return nil 200 } 201 202 // IsFiltered : 203 func (a *Adapter) IsFiltered() bool { 204 return a.filtered 205 } 206 207 func loadPolicy(policy *Policy, m model.Model) { 208 tokens := append([]string{}, policy.PType) 209 210 if len(policy.V0) > 0 { 211 tokens = append(tokens, policy.V0) 212 } 213 if len(policy.V1) > 0 { 214 tokens = append(tokens, policy.V1) 215 } 216 if len(policy.V2) > 0 { 217 tokens = append(tokens, policy.V2) 218 } 219 if len(policy.V3) > 0 { 220 tokens = append(tokens, policy.V3) 221 } 222 if len(policy.V4) > 0 { 223 tokens = append(tokens, policy.V4) 224 } 225 if len(policy.V5) > 0 { 226 tokens = append(tokens, policy.V5) 227 } 228 229 key := tokens[0] 230 sec := key[:1] 231 m[sec][key].Policy = append(m[sec][key].Policy, tokens[1:]) 232 m[sec][key].PolicyMap[strings.Join(tokens[1:], model.DefaultSep)] = len(m[sec][key].Policy) - 1 233 } 234 235 func toPolicy(ptype string, rules []string) *Policy { 236 policy := new(Policy) 237 policy.PType = ptype 238 length := len(rules) 239 if length > 0 { 240 policy.V0 = rules[0] 241 } 242 if length > 1 { 243 policy.V1 = rules[1] 244 } 245 if length > 2 { 246 policy.V2 = rules[2] 247 } 248 if length > 3 { 249 policy.V3 = rules[3] 250 } 251 if length > 4 { 252 policy.V4 = rules[4] 253 } 254 if length > 5 { 255 policy.V5 = rules[5] 256 } 257 return policy 258 } 259 260 func (a *Adapter) createTable() error { 261 return a.table.UnsafeMigrate(a.ctx, Policy{}) 262 }