From 22bc049eb78e21ff919c5f5f6c006cd9f40744ba Mon Sep 17 00:00:00 2001 From: basakest Date: Fri, 27 Aug 2021 19:11:18 +0800 Subject: [PATCH] feat: support Casbin UpdatableAdapter interface --- src/Adapter.php | 58 ++++++++++++++++++++++++++++++++++++++++--- tests/AdapterTest.php | 57 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/src/Adapter.php b/src/Adapter.php index 13f801d..5fbe68a 100644 --- a/src/Adapter.php +++ b/src/Adapter.php @@ -5,6 +5,7 @@ use Casbin\Persist\Adapter as AdapterContract; use Casbin\Persist\BatchAdapter as BatchAdapterContract; use Casbin\Persist\FilteredAdapter as FilteredAdapterContract; +use Casbin\Persist\UpdatableAdapter as UpdatableAdapterContract; use Casbin\Persist\AdapterHelper; use Laminas\Db\Adapter\AdapterInterface as LaminasDbAdapterInterface; use Laminas\Db\Adapter\Adapter as LaminasDbAdapter; @@ -20,7 +21,7 @@ * * @author techlee@qq.com */ -class Adapter implements AdapterContract, BatchAdapterContract, FilteredAdapterContract +class Adapter implements AdapterContract, BatchAdapterContract, FilteredAdapterContract, UpdatableAdapterContract { use AdapterHelper; @@ -214,11 +215,16 @@ public function removePolicy($sec, $ptype, $rule): void */ public function removePolicies(string $sec, string $ptype, array $rules): void { - $this->tableGateway->adapter->getDriver()->getConnection()->beginTransaction(function () use ($sec, $ptype, $rules) { + try { + $connection = $this->tableGateway->adapter->getDriver()->getConnection(); + $connection->beginTransaction(); foreach ($rules as $rule) { $this->removePolicy($sec, $ptype, $rule); } - }); + $connection->commit(); + } catch (\Exception $e) { + $connection->rollback(); + } } /** @@ -296,4 +302,50 @@ public function setFiltered(bool $filtered): void { $this->filtered = $filtered; } + + /** + * Updates a policy rule from storage. + * This is part of the Auto-Save feature. + * + * @param string $sec + * @param string $ptype + * @param string[] $oldRule + * @param string[] $newPolicy + */ + public function updatePolicy(string $sec, string $ptype, array $oldRule, array $newPolicy): void + { + $where['ptype'] = $ptype; + foreach ($oldRule as $k => $v) { + $where['v' . $k] = $v; + } + + $data = []; + foreach ($newPolicy as $k => $v) { + $data['v' . $k] = $v; + } + $this->tableGateway->update($data, $where); + } + + /** + * UpdatePolicies updates some policy rules to storage, like db, redis. + * + * @param string $sec + * @param string $ptype + * @param string[][] $oldRules + * @param string[][] $newRules + * @return void + */ + public function updatePolicies(string $sec, string $ptype, array $oldRules, array $newRules): void + { + try { + $connection = $this->tableGateway->adapter->getDriver()->getConnection(); + $connection->beginTransaction(); + foreach ($oldRules as $i => $oldRule) { + $this->updatePolicy($sec, $ptype, $oldRule, $newRules[$i]); + } + $connection->commit(); + } catch (\Exception $e) { + $connection->rollback(); + } + } } diff --git a/tests/AdapterTest.php b/tests/AdapterTest.php index af4d680..80cb800 100644 --- a/tests/AdapterTest.php +++ b/tests/AdapterTest.php @@ -263,6 +263,63 @@ public function testLoadFilteredPolicy() ], $e->getPolicy()); } + public function testUpdatePolicy() + { + $e = $this->getEnforcer(); + $this->assertEquals([ + ['alice', 'data1', 'read'], + ['bob', 'data2', 'write'], + ['data2_admin', 'data2', 'read'], + ['data2_admin', 'data2', 'write'], + ], $e->getPolicy()); + + $e->updatePolicy( + ['alice', 'data1', 'read'], + ['alice', 'data1', 'write'] + ); + + $e->updatePolicy( + ['bob', 'data2', 'write'], + ['bob', 'data2', 'read'] + ); + + $this->assertEquals([ + ['alice', 'data1', 'write'], + ['bob', 'data2', 'read'], + ['data2_admin', 'data2', 'read'], + ['data2_admin', 'data2', 'write'], + ], $e->getPolicy()); + } + + public function testUpdatePolicies() + { + $e = $this->getEnforcer(); + $this->assertEquals([ + ['alice', 'data1', 'read'], + ['bob', 'data2', 'write'], + ['data2_admin', 'data2', 'read'], + ['data2_admin', 'data2', 'write'], + ], $e->getPolicy()); + + $oldPolicies = [ + ['alice', 'data1', 'read'], + ['bob', 'data2', 'write'] + ]; + $newPolicies = [ + ['alice', 'data1', 'write'], + ['bob', 'data2', 'read'] + ]; + + $e->updatePolicies($oldPolicies, $newPolicies); + + $this->assertEquals([ + ['alice', 'data1', 'write'], + ['bob', 'data2', 'read'], + ['data2_admin', 'data2', 'read'], + ['data2_admin', 'data2', 'write'], + ], $e->getPolicy()); + } + protected function env($key, $default = null) { $value = getenv($key);