Commit d413a3f8 authored by khoipham's avatar khoipham

Fix RemoveFilteredPolicy

parent 5fa96e3d
...@@ -45,6 +45,14 @@ func main() { ...@@ -45,6 +45,14 @@ func main() {
} }
``` ```
## Run all tests
docker-compose run --rm go
## Debug tests
docker-compose run --rm go dlv test github.com/pckhoi/casbin-pg-adapter
## Getting Help ## Getting Help
- [Casbin](https://github.com/casbin/casbin) - [Casbin](https://github.com/casbin/casbin)
......
...@@ -32,9 +32,6 @@ type Adapter struct { ...@@ -32,9 +32,6 @@ type Adapter struct {
db *pg.DB db *pg.DB
} }
// finalizer is the destructor for Adapter.
func finalizer(a *Adapter) {}
// NewAdapter is the constructor for Adapter. // NewAdapter is the constructor for Adapter.
// arg should be a PostgreS URL string or of type *pg.Options // arg should be a PostgreS URL string or of type *pg.Options
// The adapter will create a DB named "casbin" if it doesn't exist // The adapter will create a DB named "casbin" if it doesn't exist
...@@ -149,6 +146,13 @@ func (a *Adapter) LoadPolicy(model model.Model) error { ...@@ -149,6 +146,13 @@ func (a *Adapter) LoadPolicy(model model.Model) error {
return nil return nil
} }
func policyID(ptype string, rule []string) string {
data := strings.Join(append([]string{ptype}, rule...), ",")
sum := make([]byte, 64)
sha3.ShakeSum128(sum, []byte(data))
return fmt.Sprintf("%x", sum)
}
func savePolicyLine(ptype string, rule []string) *CasbinRule { func savePolicyLine(ptype string, rule []string) *CasbinRule {
line := &CasbinRule{PType: ptype} line := &CasbinRule{PType: ptype}
...@@ -172,10 +176,7 @@ func savePolicyLine(ptype string, rule []string) *CasbinRule { ...@@ -172,10 +176,7 @@ func savePolicyLine(ptype string, rule []string) *CasbinRule {
line.V5 = rule[5] line.V5 = rule[5]
} }
data := strings.Join(append([]string{ptype}, rule...), ",") line.ID = policyID(ptype, rule)
sum := make([]byte, 64)
sha3.ShakeSum128(sum, []byte(data))
line.ID = fmt.Sprintf("%x", sum)
return line return line
} }
...@@ -222,28 +223,28 @@ func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error { ...@@ -222,28 +223,28 @@ func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error {
// RemoveFilteredPolicy removes policy rules that match the filter from the storage. // RemoveFilteredPolicy removes policy rules that match the filter from the storage.
func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error { func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
line := &CasbinRule{PType: ptype} query := a.db.Model((*CasbinRule)(nil)).Where("p_type = ?", ptype)
idx := fieldIndex + len(fieldValues) idx := fieldIndex + len(fieldValues)
if fieldIndex <= 0 && idx > 0 { if fieldIndex <= 0 && idx > 0 && fieldValues[0-fieldIndex] != "" {
line.V0 = fieldValues[0-fieldIndex] query = query.Where("v0 = ?", fieldValues[0-fieldIndex])
} }
if fieldIndex <= 1 && idx > 1 { if fieldIndex <= 1 && idx > 1 && fieldValues[1-fieldIndex] != "" {
line.V1 = fieldValues[1-fieldIndex] query = query.Where("v1 = ?", fieldValues[1-fieldIndex])
} }
if fieldIndex <= 2 && idx > 2 { if fieldIndex <= 2 && idx > 2 && fieldValues[2-fieldIndex] != "" {
line.V2 = fieldValues[2-fieldIndex] query = query.Where("v2 = ?", fieldValues[2-fieldIndex])
} }
if fieldIndex <= 3 && idx > 3 { if fieldIndex <= 3 && idx > 3 && fieldValues[3-fieldIndex] != "" {
line.V3 = fieldValues[3-fieldIndex] query = query.Where("v3 = ?", fieldValues[3-fieldIndex])
} }
if fieldIndex <= 4 && idx > 4 { if fieldIndex <= 4 && idx > 4 && fieldValues[4-fieldIndex] != "" {
line.V4 = fieldValues[4-fieldIndex] query = query.Where("v4 = ?", fieldValues[4-fieldIndex])
} }
if fieldIndex <= 5 && idx > 5 { if fieldIndex <= 5 && idx > 5 && fieldValues[5-fieldIndex] != "" {
line.V5 = fieldValues[5-fieldIndex] query = query.Where("v5 = ?", fieldValues[5-fieldIndex])
} }
err := a.db.Delete(line) _, err := query.Delete()
return err return err
} }
...@@ -18,6 +18,7 @@ type AdapterTestSuite struct { ...@@ -18,6 +18,7 @@ type AdapterTestSuite struct {
} }
func (s *AdapterTestSuite) testGetPolicy(res [][]string) { func (s *AdapterTestSuite) testGetPolicy(res [][]string) {
s.T().Helper()
myRes := s.e.GetPolicy() myRes := s.e.GetPolicy()
s.Assert().True(util.Array2DEquals(res, myRes), "Policy Got: %v, supposed to be %v", myRes, res) s.Assert().True(util.Array2DEquals(res, myRes), "Policy Got: %v, supposed to be %v", myRes, res)
} }
...@@ -27,8 +28,7 @@ func (s *AdapterTestSuite) dropCasbinDB() { ...@@ -27,8 +28,7 @@ func (s *AdapterTestSuite) dropCasbinDB() {
s.Require().NoError(err) s.Require().NoError(err)
db := pg.Connect(opts) db := pg.Connect(opts)
defer db.Close() defer db.Close()
_, err = db.Exec("DROP DATABASE casbin") db.Exec("DROP DATABASE casbin")
s.Require().NoError(err)
} }
func (s *AdapterTestSuite) SetupTest() { func (s *AdapterTestSuite) SetupTest() {
...@@ -41,9 +41,9 @@ func (s *AdapterTestSuite) SetupTest() { ...@@ -41,9 +41,9 @@ func (s *AdapterTestSuite) SetupTest() {
// This is a trick to save the current policy to the DB. // This is a trick to save the current policy to the DB.
// We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter. // We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter.
// The current policy means the policy in the Casbin enforcer (aka in memory). // The current policy means the policy in the Casbin enforcer (aka in memory).
s.e, err = casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv") e, err := casbin.NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
s.Require().NoError(err) s.Require().NoError(err)
err = s.a.SavePolicy(s.e.GetModel()) err = s.a.SavePolicy(e.GetModel())
s.Require().NoError(err) s.Require().NoError(err)
s.e, err = casbin.NewEnforcer("examples/rbac_model.conf", s.a) s.e, err = casbin.NewEnforcer("examples/rbac_model.conf", s.a)
...@@ -79,11 +79,59 @@ func (s *AdapterTestSuite) TestAutoSave() { ...@@ -79,11 +79,59 @@ func (s *AdapterTestSuite) TestAutoSave() {
// Because AutoSave is enabled, the policy change not only affects the policy in Casbin enforcer, // Because AutoSave is enabled, the policy change not only affects the policy in Casbin enforcer,
// but also affects the policy in the storage. // but also affects the policy in the storage.
s.e.AddPolicy("alice", "data1", "write") _, err = s.e.AddPolicy("alice", "data1", "write")
s.Require().NoError(err)
// Reload the policy from the storage to see the effect. // Reload the policy from the storage to see the effect.
s.e.LoadPolicy() err = s.e.LoadPolicy()
s.Require().NoError(err)
// The policy has a new rule: {"alice", "data1", "write"}. // The policy has a new rule: {"alice", "data1", "write"}.
s.testGetPolicy([][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}, {"alice", "data1", "write"}}) s.testGetPolicy([][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}, {"alice", "data1", "write"}})
// Aditional AddPolicy have no effect
_, err = s.e.AddPolicy("alice", "data1", "write")
s.Require().NoError(err)
err = s.e.LoadPolicy()
s.Require().NoError(err)
s.testGetPolicy([][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}, {"alice", "data1", "write"}})
s.Require().NoError(err)
}
func (s *AdapterTestSuite) TestConstructorOptions() {
opts, err := pg.ParseURL(os.Getenv("PG_CONN"))
s.Require().NoError(err)
a, err := NewAdapter(opts)
s.Require().NoError(err)
defer a.Close()
s.e, err = casbin.NewEnforcer("examples/rbac_model.conf", a)
s.Require().NoError(err)
s.testGetPolicy([][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}
func (s *AdapterTestSuite) TestRemovePolicy() {
_, err := s.e.RemovePolicy("alice", "data1", "read")
s.Require().NoError(err)
s.testGetPolicy([][]string{{"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
err = s.e.LoadPolicy()
s.Require().NoError(err)
s.testGetPolicy([][]string{{"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}
func (s *AdapterTestSuite) TestRemoveFilteredPolicy() {
_, err := s.e.RemoveFilteredPolicy(0, "", "data2")
s.Require().NoError(err)
s.testGetPolicy([][]string{{"alice", "data1", "read"}})
err = s.e.LoadPolicy()
s.Require().NoError(err)
s.testGetPolicy([][]string{{"alice", "data1", "read"}})
} }
func TestAdapterTestSuite(t *testing.T) { func TestAdapterTestSuite(t *testing.T) {
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
version: "3.4" version: "3.4"
services: services:
postgres: postgres:
image: postgres:12 build:
context: ./postgres
ports: ports:
- 5432:5432 - 5432:5432
environment: environment:
......
FROM postgres:12-alpine
ADD . /docker-entrypoint-initdb.d
#!/bin/sh
set -x
PGCONF=/var/lib/postgresql/data/postgresql.conf
sed -i "s/#log_statement = 'none'.*/log_statement = 'all'/g" $PGCONF
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment