Skip to content

Commit

Permalink
add unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
basakest committed Jan 9, 2021
1 parent dc1fc93 commit e14c507
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 50 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Expand Up @@ -18,10 +18,13 @@ before_install:
install:
- travis_retry composer install --no-suggest --no-interaction

before_script:
- export XDEBUG_MODE=coverage

script:
- vendor/bin/phpunit --version
- mkdir -p build/logs
- XDEBUG_MODE=coverage vendor/bin/phpunit
- vendor/bin/phpunit

after_script:
- travis_retry vendor/bin/php-coveralls -v
119 changes: 70 additions & 49 deletions src/Adapter.php
Expand Up @@ -9,6 +9,7 @@
use Casbin\Persist\FilteredAdapter;
use Casbin\Persist\Adapters\Filter;
use Casbin\Exceptions\InvalidFilterTypeException;
use Closure;

/**
* DatabaseAdapter.
Expand All @@ -27,6 +28,8 @@ class Adapter implements AdapterContract, FilteredAdapter

public $casbinRuleTableName = 'casbin_rule';

public $rows = [];

public function __construct(array $config)
{
$this->config = $config;
Expand All @@ -45,6 +48,16 @@ public function isFiltered(): bool
return $this->filtered;
}

/**
* Sets filtered parameter.
*
* @param bool $filtered
*/
public function setFiltered(bool $filtered): void
{
$this->filtered = $filtered;
}

public static function newAdapter(array $config)
{
return new static($config);
Expand Down Expand Up @@ -90,55 +103,6 @@ public function loadPolicy(Model $model): void
}
}

/**
* Loads only policy rules that match the filter from storage.
*
* @param Model $model
* @param mixed $filter
*
* @throws CasbinException
*/
public function loadFilteredPolicy(Model $model, $filter): void
{
// if $filter is empty, load all policies
if (is_null($filter)) {
$this->loadPolicy($model);
return;
}
// validate $filter is a instance of Filter
if (!$filter instanceof Filter) {
throw new InvalidFilterTypeException('invalid filter type');
}
$type = '';
$filter = (array) $filter;
// choose which ptype to use
foreach($filter as $i => $v) {
if (!empty($v)) {
array_unshift($filter[$i], $i);
$type = $i;
break;
}
}
$sql = 'SELECT ptype, v0, v1, v2, v3, v4, v5 FROM '.$this->casbinRuleTableName . ' WHERE ';
$items = ['ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'];
$temp = [];
$values = [];
foreach($items as $i => $item) {
if (isset($filter[$type][$i]) && !empty($filter[$type][$i])) {
array_push($temp, $item . '=:' . $item);
$values[$item] = $filter[$type][$i];
}
}
$sql .= implode(' and ', $temp);
$rows = $this->connection->query($sql, $values);
foreach($rows as $row) {
$line = implode(', ', $row);
$this->loadPolicyLine($line, $model);
}

$this->filtered = true;
}

/**
* saves all policy rules to the storage.
*
Expand Down Expand Up @@ -219,4 +183,61 @@ public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex

$this->connection->execute($sql, $where);
}

/**
* Loads only policy rules that match the filter from storage.
*
* @param Model $model
* @param mixed $filter
*
* @throws CasbinException
*/
public function loadFilteredPolicy(Model $model, $filter): void
{
// if $filter is empty, load all policies
if (is_null($filter)) {
$this->loadPolicy($model);
return;
}
// the basic sql
$sql = 'SELECT ptype, v0, v1, v2, v3, v4, v5 FROM '.$this->casbinRuleTableName . ' WHERE ';

if ($filter instanceof Filter) {
$type = '';
$filter = (array) $filter;
// choose which ptype to use
foreach($filter as $i => $v) {
if (!empty($v)) {
array_unshift($filter[$i], $i);
$type = $i;
break;
}
}
$items = ['ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'];
$temp = [];
$values = [];
foreach($items as $i => $item) {
if (isset($filter[$type][$i]) && !empty($filter[$type][$i])) {
array_push($temp, $item . '=:' . $item);
$values[$item] = $filter[$type][$i];
}
}
$sql .= implode(' and ', $temp);
$rows = $this->connection->query($sql, $values);
} elseif (is_string($filter)) {
$sql .= $filter;
$rows = $this->connection->query($sql);
} else if ($filter instanceof Closure) {
$filter($this->connection, $sql, $this->rows);
} else {
throw new InvalidFilterTypeException('invalid filter type');
}

$rows = $rows ?? $this->rows;
foreach($rows as $row) {
$line = implode(', ', $row);
$this->loadPolicyLine($line, $model);
}
$this->filtered = true;
}
}
62 changes: 62 additions & 0 deletions tests/AdapterTest.php
Expand Up @@ -3,9 +3,12 @@
namespace Tests;

use Casbin\Enforcer;
use Casbin\Model\Model;
use Casbin\Persist\Adapter;
use CasbinAdapter\Database\Adapter as DatabaseAdapter;
use PHPUnit\Framework\TestCase;
use TechOne\Database\Manager;
use Casbin\Persist\Adapters\Filter;

class AdapterTest extends TestCase
{
Expand Down Expand Up @@ -44,6 +47,31 @@ protected function getEnforcer()
return new Enforcer(__DIR__.'/rbac_model.conf', $adapter);
}

protected function getEnforcerWithAdapter(Adapter $adapter): Enforcer
{
$this->adapter = $adapter;
$this->initDb($this->adapter);
$model = Model::newModelFromString(
<<<'EOT'
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
EOT
);
return new Enforcer($model, $this->adapter);
}

public function testLoadPolicy()
{
$e = $this->getEnforcer();
Expand All @@ -54,6 +82,40 @@ public function testLoadPolicy()
$this->assertTrue($e->enforce('alice', 'data2', 'write'));
}

public function testLoadFilteredPolicy()
{
$this->initConfig();
$adapter = DatabaseAdapter::newAdapter($this->config);
$adapter->setFiltered(true);
$e = $this->getEnforcerWithAdapter($adapter);
$this->assertEquals([], $e->getPolicy());

// string
$filter = "v0 = 'bob'";
$e->loadFilteredPolicy($filter);
$this->assertEquals([
//
['bob', 'data2', 'write', '', '', '']
], $e->getPolicy());

// Filter
$filter = new Filter(['', '', 'read']);
$e->loadFilteredPolicy($filter);
$this->assertEquals([
['alice', 'data1', 'read', '', '', ''],
['data2_admin', 'data2', 'read', '', '', ''],
], $e->getPolicy());

// Closure
$e->loadFilteredPolicy(function ($connection, $sql, &$rows) {
$rows = $connection->query($sql . "v0 = 'alice'");
});

$this->assertEquals([
['alice', 'data1', 'read', '', '', ''],
], $e->getPolicy());
}

public function testAddPolicy()
{
$e = $this->getEnforcer();
Expand Down

0 comments on commit e14c507

Please sign in to comment.