@@ -31,6 +31,15 @@ import (
3131// It can load policy from file or save policy to file.
3232type Adapter struct {
3333 filePath string
34+ filtered bool
35+ }
36+
37+ // Filter defines filter options for Adater.
38+ type Filter struct {
39+ // P is the filter option for "p" policies.
40+ P []string
41+ // G is the filter option for "g" policies.
42+ G []string
3443}
3544
3645// NewAdapter is the constructor for Adapter.
@@ -40,18 +49,46 @@ func NewAdapter(filePath string) *Adapter {
4049 return & a
4150}
4251
52+ // NewFilteredAdapter is the constructor for FilteredAdapter.
53+ func NewFilteredAdapter (filePath string ) * Adapter {
54+ return NewAdapter (filePath )
55+ }
56+
4357// LoadPolicy loads all policy rules from the storage.
4458func (a * Adapter ) LoadPolicy (model model.Model ) error {
59+ return a .LoadFilteredPolicy (model , nil )
60+ }
61+
62+ // LoadFilteredPolicy loads matching policy rules from the storage.
63+ func (a * Adapter ) LoadFilteredPolicy (model model.Model , filter interface {}) error {
64+ var filterValue * Filter
65+ if filter == nil {
66+ a .filtered = false
67+ } else {
68+ var ok bool
69+ filterValue , ok = filter .(* Filter )
70+ if ! ok {
71+ return errors .New ("invalid filter type, expected *Filter" )
72+ }
73+ a .filtered = true
74+ }
4575 if a .filePath == "" {
4676 return errors .New ("invalid file path, file path cannot be empty" )
4777 }
4878
49- err := a .loadPolicyFile (model , persist .LoadPolicyLine )
50- return err
79+ return a .loadPolicyFile (model , filterValue , persist .LoadPolicyLine )
80+ }
81+
82+ // IsFiltered returns true if the loaded policy is filtered.
83+ func (a * Adapter ) IsFiltered () bool {
84+ return a .filtered
5185}
5286
5387// SavePolicy saves all policy rules to the storage.
5488func (a * Adapter ) SavePolicy (model model.Model ) error {
89+ if a .filtered == true {
90+ return errors .New ("cannot save a filtered policy" )
91+ }
5592 if a .filePath == "" {
5693 return errors .New ("invalid file path, file path cannot be empty" )
5794 }
@@ -78,7 +115,7 @@ func (a *Adapter) SavePolicy(model model.Model) error {
78115 return err
79116}
80117
81- func (a * Adapter ) loadPolicyFile (model model.Model , handler func (string , model.Model )) error {
118+ func (a * Adapter ) loadPolicyFile (model model.Model , filter * Filter , handler func (string , model.Model )) error {
82119 f , err := os .Open (a .filePath )
83120 if err != nil {
84121 return err
@@ -89,6 +126,14 @@ func (a *Adapter) loadPolicyFile(model model.Model, handler func(string, model.M
89126 for {
90127 line , err := buf .ReadString ('\n' )
91128 line = strings .TrimSpace (line )
129+
130+ // If a filter is defined, apply it to the policy
131+ if filter != nil {
132+ if filterLine (line , filter ) {
133+ continue
134+ }
135+ }
136+
92137 handler (line , model )
93138 if err != nil {
94139 if err == io .EOF {
@@ -99,6 +144,28 @@ func (a *Adapter) loadPolicyFile(model model.Model, handler func(string, model.M
99144 }
100145}
101146
147+ func filterLine (line string , filter * Filter ) bool {
148+ p := strings .Split (line , "," )
149+ if len (p ) == 0 {
150+ return true
151+ }
152+ var filterSet []string
153+ if strings .TrimSpace (p [0 ]) == "p" {
154+ filterSet = filter .P
155+ }
156+ if strings .TrimSpace (p [0 ]) == "g" {
157+ filterSet = filter .G
158+ }
159+ var skip bool
160+ for i , v := range filterSet {
161+ if len (p ) < i + 2 || len (v ) > 0 && strings .TrimSpace (v ) != strings .TrimSpace (p [i + 1 ]) {
162+ skip = true
163+ break
164+ }
165+ }
166+ return skip
167+ }
168+
102169func (a * Adapter ) savePolicyFile (text string ) error {
103170 f , err := os .Create (a .filePath )
104171 if err != nil {
0 commit comments