-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e65352f
commit 90ca3e2
Showing
2 changed files
with
190 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// this implementation refers to the following link: | ||
// https://github.com/casbin/gorm-adapter/blob/master/context_adapter.go | ||
|
||
package casbinbunadapter | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/casbin/casbin/v2/model" | ||
"github.com/casbin/casbin/v2/persist" | ||
) | ||
|
||
var ( | ||
// check if the ctxBunAdapter implements the ContextAdapter interface | ||
_ persist.ContextAdapter = (*ctxBunAdapter)(nil) // Ensure ctxBunAdapter | ||
) | ||
|
||
type ctxBunAdapter struct { | ||
*bunAdapter | ||
} | ||
|
||
func NewCtxAdapter(driverName string, dataSourceName string, opts ...adapterOption) (*ctxBunAdapter, error) { | ||
adapter, err := NewAdapter(driverName, dataSourceName, opts...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &ctxBunAdapter{adapter}, nil | ||
} | ||
|
||
// executeWithContext is a helper function to execute a function with context and return the result or error. | ||
func executeWithContext(ctx context.Context, fn func() error) error { | ||
done := make(chan error) | ||
go func() { | ||
done <- fn() | ||
}() | ||
|
||
select { | ||
case <-ctx.Done(): | ||
return ctx.Err() | ||
case err := <-done: | ||
return err | ||
} | ||
} | ||
|
||
// LoadPolicyCtx loads all policy rules from the storage with context. | ||
func (a *ctxBunAdapter) LoadPolicyCtx(ctx context.Context, model model.Model) error { | ||
return executeWithContext(ctx, func() error { | ||
return a.LoadPolicy(model) | ||
}) | ||
} | ||
|
||
// SavePolicyCtx saves all policy rules to the storage with context. | ||
func (a *ctxBunAdapter) SavePolicyCtx(ctx context.Context, model model.Model) error { | ||
return executeWithContext(ctx, func() error { | ||
return a.SavePolicy(model) | ||
}) | ||
} | ||
|
||
// AddPolicyCtx adds a policy rule to the storage with context. | ||
// This is part of the Auto-Save feature. | ||
func (a *ctxBunAdapter) AddPolicyCtx(ctx context.Context, sec string, ptype string, rule []string) error { | ||
return executeWithContext(ctx, func() error { | ||
return a.AddPolicy(sec, ptype, rule) | ||
}) | ||
} | ||
|
||
// RemovePolicyCtx removes a policy rule from the storage with context. | ||
// This is part of the Auto-Save feature. | ||
func (a *ctxBunAdapter) RemovePolicyCtx(ctx context.Context, sec string, ptype string, rule []string) error { | ||
return executeWithContext(ctx, func() error { | ||
return a.RemovePolicy(sec, ptype, rule) | ||
}) | ||
} | ||
|
||
// RemoveFilteredPolicyCtx removes policy rules that match the filter from the storage with context. | ||
// This is part of the Auto-Save feature. | ||
func (a *ctxBunAdapter) RemoveFilteredPolicyCtx(ctx context.Context, sec string, ptype string, fieldIndex int, fieldValues ...string) error { | ||
return executeWithContext(ctx, func() error { | ||
return a.RemoveFilteredPolicy(sec, ptype, fieldIndex, fieldValues...) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package casbinbunadapter | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
"github.com/agiledragon/gomonkey/v2" | ||
"github.com/casbin/casbin/v2" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func mockExecuteWithContextTimeOut(ctx context.Context, fn func() error) error { | ||
done := make(chan error) | ||
go func() { | ||
time.Sleep(500 * time.Microsecond) | ||
done <- fn() | ||
}() | ||
|
||
select { | ||
case <-ctx.Done(): | ||
return ctx.Err() | ||
case err := <-done: | ||
return err | ||
} | ||
} | ||
|
||
func clearDBPolicy() (*casbin.Enforcer, *ctxBunAdapter) { | ||
ca, err := NewCtxAdapter("mysql", "root:root@tcp(127.0.0.1:3306)/test", WithDebugMode()) | ||
if err != nil { | ||
panic(err) | ||
} | ||
e, err := casbin.NewEnforcer("examples/rbac_model.conf", ca) | ||
if err != nil { | ||
panic(err) | ||
} | ||
e.ClearPolicy() | ||
if err := e.SavePolicy(); err != nil { | ||
panic(err) | ||
} | ||
return e, ca | ||
} | ||
|
||
func TestCtxBunAdapter_AddPolicyCtx(t *testing.T) { | ||
e, ca := clearDBPolicy() | ||
|
||
if err := ca.AddPolicyCtx(context.Background(), "p", "p", []string{"alice", "data1", "read"}); err != nil { | ||
t.Fatalf("failed to add policy: %v", err) | ||
} | ||
_ = e.LoadPolicy() | ||
testGetPolicy( | ||
t, | ||
e, | ||
[][]string{ | ||
{"alice", "data1", "read"}, | ||
}, | ||
) | ||
|
||
var p = gomonkey.ApplyFunc(executeWithContext, mockExecuteWithContextTimeOut) | ||
defer p.Reset() | ||
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Microsecond) | ||
defer cancel() | ||
assert.EqualError(t, ca.AddPolicyCtx(ctx, "p", "p", []string{"alice", "data2", "read"}), "context deadline exceeded") | ||
} | ||
|
||
func TestCtxBunAdapter_RemovePolicyCtx(t *testing.T) { | ||
e, ca := clearDBPolicy() | ||
|
||
_ = ca.AddPolicyCtx(context.Background(), "p", "p", []string{"alice", "data1", "read"}) | ||
_ = ca.AddPolicyCtx(context.Background(), "p", "p", []string{"alice", "data2", "read"}) | ||
_ = ca.RemovePolicyCtx(context.Background(), "p", "p", []string{"alice", "data1", "read"}) | ||
_ = e.LoadPolicy() | ||
testGetPolicy( | ||
t, | ||
e, | ||
[][]string{ | ||
{"alice", "data2", "read"}, | ||
}, | ||
) | ||
|
||
var p = gomonkey.ApplyFunc(executeWithContext, mockExecuteWithContextTimeOut) | ||
defer p.Reset() | ||
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Microsecond) | ||
defer cancel() | ||
assert.EqualError(t, ca.RemovePolicyCtx(ctx, "p", "p", []string{"alice", "data2", "read"}), "context deadline exceeded") | ||
} | ||
|
||
func TestCtxBunAdapter_RemoveFilteredPolicyCtx(t *testing.T) { | ||
e, ca := clearDBPolicy() | ||
|
||
_ = ca.AddPolicyCtx(context.Background(), "p", "p", []string{"alice", "data1", "read"}) | ||
_ = ca.AddPolicyCtx(context.Background(), "p", "p", []string{"alice", "data2", "read"}) | ||
_ = ca.AddPolicyCtx(context.Background(), "p", "p", []string{"bob", "data1", "read"}) | ||
_ = ca.RemoveFilteredPolicyCtx(context.Background(), "p", "p", 0, "alice") | ||
_ = e.LoadPolicy() | ||
testGetPolicy( | ||
t, | ||
e, | ||
[][]string{ | ||
{"bob", "data1", "read"}, | ||
}, | ||
) | ||
|
||
var p = gomonkey.ApplyFunc(executeWithContext, mockExecuteWithContextTimeOut) | ||
defer p.Reset() | ||
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Microsecond) | ||
defer cancel() | ||
assert.EqualError(t, ca.RemoveFilteredPolicyCtx(ctx, "p", "p", 0, "alice"), "context deadline exceeded") | ||
} |