Skip to content

Commit 69ad23b

Browse files
authored
feat: support UpdatableWatcher interface (#35)
1 parent 06fcda7 commit 69ad23b

File tree

4 files changed

+138
-48
lines changed

4 files changed

+138
-48
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/casbin/redis-watcher/v2
33
go 1.18
44

55
require (
6-
github.com/casbin/casbin/v2 v2.53.1
6+
github.com/casbin/casbin/v2 v2.54.0
77
github.com/go-redis/redis/v8 v8.11.5
88
github.com/google/uuid v1.3.0
99
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
22
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
3-
github.com/casbin/casbin/v2 v2.53.1 h1:uD/1LMHEPOkn1Xw5UmLnOJxdBPI7Zz85VbdPLJhivxo=
4-
github.com/casbin/casbin/v2 v2.53.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
3+
github.com/casbin/casbin/v2 v2.54.0 h1:NFQ3Xkw6rfbD/rwEHMVRHVP5gUxhNQKdcZCb53pwSrA=
4+
github.com/casbin/casbin/v2 v2.54.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
55
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
66
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
77
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=

watcher.go

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,19 @@ func DefaultUpdateCallback(e casbin.IEnforcer) func(string) {
4141
err = e.LoadPolicy()
4242
res = true
4343
case UpdateForAddPolicy:
44-
res, err = e.SelfAddPolicy(msgStruct.Sec, msgStruct.Ptype, msgStruct.Rule)
44+
res, err = e.SelfAddPolicy(msgStruct.Sec, msgStruct.Ptype, msgStruct.NewRule)
4545
case UpdateForAddPolicies:
46-
res, err = e.SelfAddPolicies(msgStruct.Sec, msgStruct.Ptype, msgStruct.Rules)
46+
res, err = e.SelfAddPolicies(msgStruct.Sec, msgStruct.Ptype, msgStruct.NewRules)
4747
case UpdateForRemovePolicy:
48-
res, err = e.SelfRemovePolicy(msgStruct.Sec, msgStruct.Ptype, msgStruct.Rule)
48+
res, err = e.SelfRemovePolicy(msgStruct.Sec, msgStruct.Ptype, msgStruct.NewRule)
4949
case UpdateForRemoveFilteredPolicy:
5050
res, err = e.SelfRemoveFilteredPolicy(msgStruct.Sec, msgStruct.Ptype, msgStruct.FieldIndex, msgStruct.FieldValues...)
5151
case UpdateForRemovePolicies:
52-
res, err = e.SelfRemovePolicies(msgStruct.Sec, msgStruct.Ptype, msgStruct.Rules)
52+
res, err = e.SelfRemovePolicies(msgStruct.Sec, msgStruct.Ptype, msgStruct.NewRules)
53+
case UpdateForUpdatePolicy:
54+
res, err = e.SelfUpdatePolicy(msgStruct.Sec, msgStruct.Ptype, msgStruct.OldRule, msgStruct.NewRule)
55+
case UpdateForUpdatePolicies:
56+
res, err = e.SelfUpdatePolicies(msgStruct.Sec, msgStruct.Ptype, msgStruct.OldRules, msgStruct.NewRules)
5357
default:
5458
err = errors.New("unknown update type")
5559
}
@@ -67,8 +71,10 @@ type MSG struct {
6771
ID string
6872
Sec string
6973
Ptype string
70-
Rule []string
71-
Rules [][]string
74+
OldRule []string
75+
OldRules [][]string
76+
NewRule []string
77+
NewRules [][]string
7278
FieldIndex int
7379
FieldValues []string
7480
}
@@ -83,6 +89,8 @@ const (
8389
UpdateForSavePolicy UpdateType = "UpdateForSavePolicy"
8490
UpdateForAddPolicies UpdateType = "UpdateForAddPolicies"
8591
UpdateForRemovePolicies UpdateType = "UpdateForRemovePolicies"
92+
UpdateForUpdatePolicy UpdateType = "UpdateForUpdatePolicy"
93+
UpdateForUpdatePolicies UpdateType = "UpdateForUpdatePolicies"
8694
)
8795

8896
func (m *MSG) MarshalBinary() ([]byte, error) {
@@ -262,11 +270,11 @@ func (w *Watcher) UpdateForAddPolicy(sec, ptype string, params ...string) error
262270
context.Background(),
263271
w.options.Channel,
264272
&MSG{
265-
Method: UpdateForAddPolicy,
266-
ID: w.options.LocalID,
267-
Sec: sec,
268-
Ptype: ptype,
269-
Rule: params,
273+
Method: UpdateForAddPolicy,
274+
ID: w.options.LocalID,
275+
Sec: sec,
276+
Ptype: ptype,
277+
NewRule: params,
270278
}).Err()
271279
})
272280
}
@@ -281,11 +289,11 @@ func (w *Watcher) UpdateForRemovePolicy(sec, ptype string, params ...string) err
281289
context.Background(),
282290
w.options.Channel,
283291
&MSG{
284-
Method: UpdateForRemovePolicy,
285-
ID: w.options.LocalID,
286-
Sec: sec,
287-
Ptype: ptype,
288-
Rule: params,
292+
Method: UpdateForRemovePolicy,
293+
ID: w.options.LocalID,
294+
Sec: sec,
295+
Ptype: ptype,
296+
NewRule: params,
289297
},
290298
).Err()
291299
})
@@ -339,11 +347,11 @@ func (w *Watcher) UpdateForAddPolicies(sec string, ptype string, rules ...[]stri
339347
context.Background(),
340348
w.options.Channel,
341349
&MSG{
342-
Method: UpdateForAddPolicies,
343-
ID: w.options.LocalID,
344-
Sec: sec,
345-
Ptype: ptype,
346-
Rules: rules,
350+
Method: UpdateForAddPolicies,
351+
ID: w.options.LocalID,
352+
Sec: sec,
353+
Ptype: ptype,
354+
NewRules: rules,
347355
},
348356
).Err()
349357
})
@@ -359,11 +367,53 @@ func (w *Watcher) UpdateForRemovePolicies(sec string, ptype string, rules ...[]s
359367
context.Background(),
360368
w.options.Channel,
361369
&MSG{
362-
Method: UpdateForRemovePolicies,
363-
ID: w.options.LocalID,
364-
Sec: sec,
365-
Ptype: ptype,
366-
Rules: rules,
370+
Method: UpdateForRemovePolicies,
371+
ID: w.options.LocalID,
372+
Sec: sec,
373+
Ptype: ptype,
374+
NewRules: rules,
375+
},
376+
).Err()
377+
})
378+
}
379+
380+
// UpdateForUpdatePolicy calls the update callback of other instances to synchronize their policy.
381+
// It is called after Enforcer.UpdatePolicy()
382+
func (w *Watcher) UpdateForUpdatePolicy(sec string, ptype string, oldRule, newRule []string) error {
383+
return w.logRecord(func() error {
384+
w.l.Lock()
385+
defer w.l.Unlock()
386+
return w.pubClient.Publish(
387+
context.Background(),
388+
w.options.Channel,
389+
&MSG{
390+
Method: UpdateForUpdatePolicy,
391+
ID: w.options.LocalID,
392+
Sec: sec,
393+
Ptype: ptype,
394+
OldRule: oldRule,
395+
NewRule: newRule,
396+
},
397+
).Err()
398+
})
399+
}
400+
401+
// UpdateForUpdatePolicies calls the update callback of other instances to synchronize their policy.
402+
// It is called after Enforcer.UpdatePolicies()
403+
func (w *Watcher) UpdateForUpdatePolicies(sec string, ptype string, oldRules, newRules [][]string) error {
404+
return w.logRecord(func() error {
405+
w.l.Lock()
406+
defer w.l.Unlock()
407+
return w.pubClient.Publish(
408+
context.Background(),
409+
w.options.Channel,
410+
&MSG{
411+
Method: UpdateForUpdatePolicies,
412+
ID: w.options.LocalID,
413+
Sec: sec,
414+
Ptype: ptype,
415+
OldRules: oldRules,
416+
NewRules: newRules,
367417
},
368418
).Err()
369419
})

watcher_test.go

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,27 +89,21 @@ func TestWatcherWithIgnoreSelfTrue(t *testing.T) {
8989
}
9090

9191
func TestUpdate(t *testing.T) {
92-
wo := rediswatcher.WatcherOptions{
93-
IgnoreSelf: true,
94-
}
95-
e, w := initWatcherWithOptions(t, wo)
96-
e2, w2 := initWatcherWithOptions(t, wo)
97-
98-
time.Sleep(time.Millisecond * 500)
99-
_, _ = e.UpdatePolicy([]string{"alice", "data1", "read"}, []string{"alice", "data1", "write"})
100-
_ = e.LoadPolicy()
101-
102-
time.Sleep(time.Millisecond * 500)
103-
if !reflect.DeepEqual(e2.GetPolicy(), e.GetPolicy()) {
104-
t.Log("Method", "Update")
105-
t.Log("e.policy", e.GetPolicy())
106-
t.Log("e2.policy", e2.GetPolicy())
107-
t.Error("These two enforcers' policies should be equal")
108-
}
92+
_, w := initWatcher(t)
93+
_ = w.SetUpdateCallback(func(s string) {
94+
msgStruct := &rediswatcher.MSG{}
10995

96+
err := msgStruct.UnmarshalBinary([]byte(s))
97+
if err != nil {
98+
t.Error(err)
99+
return
100+
}
101+
if msgStruct.Method != "Update" {
102+
t.Errorf("Method should be Update instead of %s", msgStruct.Method)
103+
}
104+
})
105+
_ = w.Update()
110106
w.Close()
111-
w2.Close()
112-
time.Sleep(time.Millisecond * 500)
113107
time.Sleep(time.Millisecond * 500)
114108
}
115109

@@ -258,3 +252,49 @@ func TestUpdateForRemovePolicies(t *testing.T) {
258252
w2.Close()
259253
time.Sleep(time.Millisecond * 500)
260254
}
255+
256+
func TestUpdateForUpdatePolicy(t *testing.T) {
257+
wo := rediswatcher.WatcherOptions{
258+
IgnoreSelf: true,
259+
}
260+
e, w := initWatcherWithOptions(t, wo)
261+
e2, w2 := initWatcherWithOptions(t, wo)
262+
263+
time.Sleep(time.Millisecond * 500)
264+
_, _ = e.UpdatePolicy([]string{"alice", "data1", "read"}, []string{"alice", "data1", "write"})
265+
266+
time.Sleep(time.Millisecond * 500)
267+
if !reflect.DeepEqual(e2.GetPolicy(), e.GetPolicy()) {
268+
t.Log("Method", "UpdatePolicy")
269+
t.Log("e.policy", e.GetPolicy())
270+
t.Log("e2.policy", e2.GetPolicy())
271+
t.Error("These two enforcers' policies should be equal")
272+
}
273+
274+
w.Close()
275+
w2.Close()
276+
time.Sleep(time.Millisecond * 500)
277+
}
278+
279+
func TestUpdateForUpdatePolicies(t *testing.T) {
280+
wo := rediswatcher.WatcherOptions{
281+
IgnoreSelf: true,
282+
}
283+
e, w := initWatcherWithOptions(t, wo)
284+
e2, w2 := initWatcherWithOptions(t, wo)
285+
286+
time.Sleep(time.Millisecond * 500)
287+
_, _ = e.UpdatePolicies([][]string{{"alice", "data1", "read"}}, [][]string{{"alice", "data1", "write"}})
288+
289+
time.Sleep(time.Millisecond * 500)
290+
if !reflect.DeepEqual(e2.GetPolicy(), e.GetPolicy()) {
291+
t.Log("Method", "UpdatePolicies")
292+
t.Log("e.policy", e.GetPolicy())
293+
t.Log("e2.policy", e2.GetPolicy())
294+
t.Error("These two enforcers' policies should be equal")
295+
}
296+
297+
w.Close()
298+
w2.Close()
299+
time.Sleep(time.Millisecond * 500)
300+
}

0 commit comments

Comments
 (0)