| package casbin |
| |
| import ( |
| "github.com/casbin/casbin/v2/model" |
| "github.com/casbin/casbin/v2/persist" |
| ) |
| |
| // DistributedEnforcer wraps SyncedEnforcer for dispatcher. |
| type DistributedEnforcer struct { |
| *SyncedEnforcer |
| } |
| |
| func NewDistributedEnforcer(params ...interface{}) (*DistributedEnforcer, error) { |
| e := &DistributedEnforcer{} |
| var err error |
| e.SyncedEnforcer, err = NewSyncedEnforcer(params...) |
| if err != nil { |
| return nil, err |
| } |
| |
| return e, nil |
| } |
| |
| // SetDispatcher sets the current dispatcher. |
| func (d *DistributedEnforcer) SetDispatcher(dispatcher persist.Dispatcher) { |
| d.dispatcher = dispatcher |
| } |
| |
| // AddPoliciesSelf provides a method for dispatcher to add authorization rules to the current policy. |
| // The function returns the rules affected and error. |
| func (d *DistributedEnforcer) AddPoliciesSelf(shouldPersist func() bool, sec string, ptype string, rules [][]string) (affected [][]string, err error) { |
| d.m.Lock() |
| defer d.m.Unlock() |
| if shouldPersist != nil && shouldPersist() { |
| var noExistsPolicy [][]string |
| for _, rule := range rules { |
| var hasPolicy bool |
| hasPolicy, err = d.model.HasPolicy(sec, ptype, rule) |
| if err != nil { |
| return nil, err |
| } |
| if !hasPolicy { |
| noExistsPolicy = append(noExistsPolicy, rule) |
| } |
| } |
| |
| if err = d.adapter.(persist.BatchAdapter).AddPolicies(sec, ptype, noExistsPolicy); err != nil && err.Error() != notImplemented { |
| return nil, err |
| } |
| } |
| |
| affected, err = d.model.AddPoliciesWithAffected(sec, ptype, rules) |
| if err != nil { |
| return affected, err |
| } |
| |
| if sec == "g" { |
| err := d.BuildIncrementalRoleLinks(model.PolicyAdd, ptype, affected) |
| if err != nil { |
| return affected, err |
| } |
| } |
| |
| return affected, nil |
| } |
| |
| // RemovePoliciesSelf provides a method for dispatcher to remove a set of rules from current policy. |
| // The function returns the rules affected and error. |
| func (d *DistributedEnforcer) RemovePoliciesSelf(shouldPersist func() bool, sec string, ptype string, rules [][]string) (affected [][]string, err error) { |
| d.m.Lock() |
| defer d.m.Unlock() |
| if shouldPersist != nil && shouldPersist() { |
| if err = d.adapter.(persist.BatchAdapter).RemovePolicies(sec, ptype, rules); err != nil { |
| if err.Error() != notImplemented { |
| return nil, err |
| } |
| } |
| } |
| |
| affected, err = d.model.RemovePoliciesWithAffected(sec, ptype, rules) |
| if err != nil { |
| return affected, err |
| } |
| |
| if sec == "g" { |
| err = d.BuildIncrementalRoleLinks(model.PolicyRemove, ptype, affected) |
| if err != nil { |
| return affected, err |
| } |
| } |
| |
| return affected, err |
| } |
| |
| // RemoveFilteredPolicySelf provides a method for dispatcher to remove an authorization rule from the current policy, field filters can be specified. |
| // The function returns the rules affected and error. |
| func (d *DistributedEnforcer) RemoveFilteredPolicySelf(shouldPersist func() bool, sec string, ptype string, fieldIndex int, fieldValues ...string) (affected [][]string, err error) { |
| d.m.Lock() |
| defer d.m.Unlock() |
| if shouldPersist != nil && shouldPersist() { |
| if err = d.adapter.RemoveFilteredPolicy(sec, ptype, fieldIndex, fieldValues...); err != nil { |
| if err.Error() != notImplemented { |
| return nil, err |
| } |
| } |
| } |
| |
| _, affected, err = d.model.RemoveFilteredPolicy(sec, ptype, fieldIndex, fieldValues...) |
| if err != nil { |
| return affected, err |
| } |
| |
| if sec == "g" { |
| err := d.BuildIncrementalRoleLinks(model.PolicyRemove, ptype, affected) |
| if err != nil { |
| return affected, err |
| } |
| } |
| |
| return affected, nil |
| } |
| |
| // ClearPolicySelf provides a method for dispatcher to clear all rules from the current policy. |
| func (d *DistributedEnforcer) ClearPolicySelf(shouldPersist func() bool) error { |
| d.m.Lock() |
| defer d.m.Unlock() |
| if shouldPersist != nil && shouldPersist() { |
| err := d.adapter.SavePolicy(nil) |
| if err != nil { |
| return err |
| } |
| } |
| |
| d.model.ClearPolicy() |
| |
| return nil |
| } |
| |
| // UpdatePolicySelf provides a method for dispatcher to update an authorization rule from the current policy. |
| func (d *DistributedEnforcer) UpdatePolicySelf(shouldPersist func() bool, sec string, ptype string, oldRule, newRule []string) (affected bool, err error) { |
| d.m.Lock() |
| defer d.m.Unlock() |
| if shouldPersist != nil && shouldPersist() { |
| err = d.adapter.(persist.UpdatableAdapter).UpdatePolicy(sec, ptype, oldRule, newRule) |
| if err != nil { |
| return false, err |
| } |
| } |
| |
| ruleUpdated, err := d.model.UpdatePolicy(sec, ptype, oldRule, newRule) |
| if !ruleUpdated || err != nil { |
| return ruleUpdated, err |
| } |
| |
| if sec == "g" { |
| err := d.BuildIncrementalRoleLinks(model.PolicyRemove, ptype, [][]string{oldRule}) // remove the old rule |
| if err != nil { |
| return ruleUpdated, err |
| } |
| err = d.BuildIncrementalRoleLinks(model.PolicyAdd, ptype, [][]string{newRule}) // add the new rule |
| if err != nil { |
| return ruleUpdated, err |
| } |
| } |
| |
| return ruleUpdated, nil |
| } |
| |
| // UpdatePoliciesSelf provides a method for dispatcher to update a set of authorization rules from the current policy. |
| func (d *DistributedEnforcer) UpdatePoliciesSelf(shouldPersist func() bool, sec string, ptype string, oldRules, newRules [][]string) (affected bool, err error) { |
| d.m.Lock() |
| defer d.m.Unlock() |
| if shouldPersist != nil && shouldPersist() { |
| err = d.adapter.(persist.UpdatableAdapter).UpdatePolicies(sec, ptype, oldRules, newRules) |
| if err != nil { |
| return false, err |
| } |
| } |
| |
| ruleUpdated, err := d.model.UpdatePolicies(sec, ptype, oldRules, newRules) |
| if !ruleUpdated || err != nil { |
| return ruleUpdated, err |
| } |
| |
| if sec == "g" { |
| err := d.BuildIncrementalRoleLinks(model.PolicyRemove, ptype, oldRules) // remove the old rule |
| if err != nil { |
| return ruleUpdated, err |
| } |
| err = d.BuildIncrementalRoleLinks(model.PolicyAdd, ptype, newRules) // add the new rule |
| if err != nil { |
| return ruleUpdated, err |
| } |
| } |
| |
| return ruleUpdated, nil |
| } |
| |
| // UpdateFilteredPoliciesSelf provides a method for dispatcher to update a set of authorization rules from the current policy. |
| func (d *DistributedEnforcer) UpdateFilteredPoliciesSelf(shouldPersist func() bool, sec string, ptype string, newRules [][]string, fieldIndex int, fieldValues ...string) (bool, error) { |
| d.m.Lock() |
| defer d.m.Unlock() |
| var ( |
| oldRules [][]string |
| err error |
| ) |
| if shouldPersist != nil && shouldPersist() { |
| oldRules, err = d.adapter.(persist.UpdatableAdapter).UpdateFilteredPolicies(sec, ptype, newRules, fieldIndex, fieldValues...) |
| if err != nil { |
| return false, err |
| } |
| } |
| |
| ruleChanged, err := d.model.RemovePolicies(sec, ptype, oldRules) |
| if err != nil { |
| return ruleChanged, err |
| } |
| err = d.model.AddPolicies(sec, ptype, newRules) |
| if err != nil { |
| return ruleChanged, err |
| } |
| ruleChanged = ruleChanged && len(newRules) != 0 |
| if !ruleChanged { |
| return ruleChanged, nil |
| } |
| |
| if sec == "g" { |
| err := d.BuildIncrementalRoleLinks(model.PolicyRemove, ptype, oldRules) // remove the old rule |
| if err != nil { |
| return ruleChanged, err |
| } |
| err = d.BuildIncrementalRoleLinks(model.PolicyAdd, ptype, newRules) // add the new rule |
| if err != nil { |
| return ruleChanged, err |
| } |
| } |
| |
| return true, nil |
| } |