diff --git a/.travis.yml b/.travis.yml
index dd8d548c..14cf1c41 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,14 +1,14 @@
-language: php
-
-php:
- - 5.4
- - 5.5
- - 5.6
- - hhvm
-
-before_script:
- - travis_retry composer self-update
- - travis_retry composer install --no-interaction --prefer-source --dev
-
-script:
- - vendor/bin/phpunit --verbose
+language: php
+
+php:
+ - 5.4
+ - 5.5
+ - 5.6
+ - hhvm
+
+before_script:
+ - travis_retry composer self-update
+ - travis_retry composer install --no-interaction --prefer-source --dev
+
+script:
+ - vendor/bin/phpunit --verbose
diff --git a/composer.json b/composer.json
index 6579795d..38429a01 100644
--- a/composer.json
+++ b/composer.json
@@ -1,62 +1,62 @@
-{
- "name": "zizaco/entrust",
- "description": "This package provides a flexible way to add Role-based Permissions to Laravel 4",
- "keywords": ["laravel","illuminate","auth","roles"],
- "license": "MIT",
- "authors": [
- {
- "name": "Zizaco Zizuini",
- "email": "zizaco@gmail.com"
- },
- {
- "name": "Andrew Elkins",
- "homepage": "http://www.andrewelkins.com"
- }
- ],
- "require": {
- "php": ">=5.4.0",
- "illuminate/support": "~4.0",
- "laravelbook/ardent": "~2.4"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.0",
- "mockery/mockery": "~0.8",
- "illuminate/database": "~4.0",
- "league/factory-muffin": "~1.5"
- },
- "repositories": [
- {
- "type": "package",
- "package": {
- "name": "laravelbook/ardent",
- "version": "2.4.2",
- "source": {
- "type": "git",
- "url": "https://github.com/bexarcreativeinc/ardent.git",
- "reference": "master"
- },
- "autoload": {
- "psr-0": {
- "LaravelBook\\Ardent": "src/"
- }
- }
- }
- }
- ],
- "suggest": {
- "zizaco/confide":"Confide is an authentication solution for Laravel 4 that couples very well with Entrust"
- },
- "autoload": {
- "classmap": [
- "src/commands"
- ],
- "psr-0": {
- "Zizaco\\Entrust": "src/"
- }
- },
- "extra": {
- "branch-alias": {
- "dev-master": "1.2-dev"
- }
- }
-}
+{
+ "name": "zizaco/entrust",
+ "description": "This package provides a flexible way to add Role-based Permissions to Laravel 4",
+ "keywords": ["laravel","illuminate","auth","roles"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Zizaco Zizuini",
+ "email": "zizaco@gmail.com"
+ },
+ {
+ "name": "Andrew Elkins",
+ "homepage": "http://www.andrewelkins.com"
+ }
+ ],
+ "require": {
+ "php": ">=5.4.0",
+ "illuminate/support": "~4.0",
+ "laravelbook/ardent": "~2.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0",
+ "mockery/mockery": "~0.8",
+ "illuminate/database": "~4.0",
+ "league/factory-muffin": "~1.5"
+ },
+ "repositories": [
+ {
+ "type": "package",
+ "package": {
+ "name": "laravelbook/ardent",
+ "version": "2.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/bexarcreativeinc/ardent.git",
+ "reference": "master"
+ },
+ "autoload": {
+ "psr-0": {
+ "LaravelBook\\Ardent": "src/"
+ }
+ }
+ }
+ }
+ ],
+ "suggest": {
+ "zizaco/confide":"Confide is an authentication solution for Laravel 4 that couples very well with Entrust"
+ },
+ "autoload": {
+ "classmap": [
+ "src/commands"
+ ],
+ "psr-4": {
+ "Zizaco\\Entrust\\": "src/Entrust/"
+ }
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.2-dev"
+ }
+ }
+}
diff --git a/phpunit.xml b/phpunit.xml
index 71adedca..3347b75b 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -1,18 +1,18 @@
-
-
-
-
- ./tests/
-
-
-
+
+
+
+
+ ./tests/
+
+
+
diff --git a/src/Zizaco/Entrust/Entrust.php b/src/Entrust/Entrust.php
similarity index 93%
rename from src/Zizaco/Entrust/Entrust.php
rename to src/Entrust/Entrust.php
index d0973265..1ec49724 100644
--- a/src/Zizaco/Entrust/Entrust.php
+++ b/src/Entrust/Entrust.php
@@ -10,7 +10,7 @@ class Entrust
*
* @var Illuminate\Foundation\Application
*/
- public $_app;
+ public $app;
/**
* Create a new confide instance.
@@ -20,7 +20,7 @@ class Entrust
*/
public function __construct($app)
{
- $this->_app = $app;
+ $this->app = $app;
}
/**
@@ -80,7 +80,7 @@ public function can( $permission )
*/
public function user()
{
- return $this->_app['auth']->user();
+ return $this->app->auth->user();
}
/**
@@ -126,11 +126,11 @@ public function routeNeedsRole( $route, $roles, $result = null, $cumulative=true
}
// Same as Route::filter, registers a new filter
- $this->_app['router']->filter($filter_name, $result);
+ $this->app->router->filter($filter_name, $result);
// Same as Route::when, assigns a route pattern to the
// previously created filter.
- $this->_app['router']->when( $route, $filter_name );
+ $this->app->router->when( $route, $filter_name );
}
/**
@@ -178,11 +178,11 @@ public function routeNeedsPermission( $route, $permissions, $result = null, $cum
}
// Same as Route::filter, registers a new filter
- $this->_app['router']->filter($filter_name, $result);
+ $this->app->router->filter($filter_name, $result);
// Same as Route::when, assigns a route pattern to the
// previously created filter.
- $this->_app['router']->when( $route, $filter_name );
+ $this->app->router->when( $route, $filter_name );
}
/**
@@ -242,10 +242,10 @@ public function routeNeedsRoleOrPermission( $route, $roles, $permissions, $resul
}
// Same as Route::filter, registers a new filter
- $this->_app['router']->filter($filter_name, $result);
+ $this->app->router->filter($filter_name, $result);
// Same as Route::when, assigns a route pattern to the
// previously created filter.
- $this->_app['router']->when( $route, $filter_name );
+ $this->app->router->when( $route, $filter_name );
}
}
diff --git a/src/Zizaco/Entrust/EntrustFacade.php b/src/Entrust/EntrustFacade.php
similarity index 100%
rename from src/Zizaco/Entrust/EntrustFacade.php
rename to src/Entrust/EntrustFacade.php
diff --git a/src/Zizaco/Entrust/EntrustPermission.php b/src/Entrust/EntrustPermission.php
similarity index 100%
rename from src/Zizaco/Entrust/EntrustPermission.php
rename to src/Entrust/EntrustPermission.php
diff --git a/src/Zizaco/Entrust/EntrustRole.php b/src/Entrust/EntrustRole.php
similarity index 100%
rename from src/Zizaco/Entrust/EntrustRole.php
rename to src/Entrust/EntrustRole.php
diff --git a/src/Zizaco/Entrust/EntrustServiceProvider.php b/src/Entrust/EntrustServiceProvider.php
similarity index 94%
rename from src/Zizaco/Entrust/EntrustServiceProvider.php
rename to src/Entrust/EntrustServiceProvider.php
index 9d2c9d83..014985e8 100644
--- a/src/Zizaco/Entrust/EntrustServiceProvider.php
+++ b/src/Entrust/EntrustServiceProvider.php
@@ -1,65 +1,65 @@
-package('zizaco/entrust');
- }
-
- /**
- * Register the service provider.
- *
- * @return void
- */
- public function register()
- {
- $this->registerEntrust();
-
- $this->registerCommands();
- }
-
- /**
- * Register the application bindings.
- *
- * @return void
- */
- private function registerEntrust()
- {
- $this->app->bind('entrust', function($app)
- {
- return new Entrust($app);
- });
- }
-
- /**
- * Register the artisan commands.
- *
- * @return void
- */
- private function registerCommands()
- {
- $this->app['command.entrust.migration'] = $this->app->share(function($app)
- {
- return new MigrationCommand($app);
- });
-
- $this->commands(
- 'command.entrust.migration'
- );
- }
-}
+package('zizaco/entrust');
+ }
+
+ /**
+ * Register the service provider.
+ *
+ * @return void
+ */
+ public function register()
+ {
+ $this->registerEntrust();
+
+ $this->registerCommands();
+ }
+
+ /**
+ * Register the application bindings.
+ *
+ * @return void
+ */
+ private function registerEntrust()
+ {
+ $this->app->bind('entrust', function($app)
+ {
+ return new Entrust($app);
+ });
+ }
+
+ /**
+ * Register the artisan commands.
+ *
+ * @return void
+ */
+ private function registerCommands()
+ {
+ $this->app['command.entrust.migration'] = $this->app->share(function($app)
+ {
+ return new MigrationCommand($app);
+ });
+
+ $this->commands(
+ 'command.entrust.migration'
+ );
+ }
+}
diff --git a/src/Zizaco/Entrust/HasRole.php b/src/Entrust/HasRole.php
similarity index 100%
rename from src/Zizaco/Entrust/HasRole.php
rename to src/Entrust/HasRole.php
diff --git a/tests/EntrustTest.php b/tests/EntrustTest.php
index 4528767a..b71759d8 100644
--- a/tests/EntrustTest.php
+++ b/tests/EntrustTest.php
@@ -1,114 +1,710 @@
shouldReceive('user')
+ ->andReturn($user)
+ ->twice()->ordered();
+
+ $entrust->shouldReceive('user')
+ ->andReturn(false)
+ ->once()->ordered();
+
+ $user->shouldReceive('hasRole')
+ ->with('UserRole')
+ ->andReturn(true)
+ ->once();
+
+ $user->shouldReceive('hasRole')
+ ->with('NonUserRole')
+ ->andReturn(false)
+ ->once();
+
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ $this->assertTrue($entrust->hasRole('UserRole'));
+ $this->assertFalse($entrust->hasRole('NonUserRole'));
+ $this->assertFalse($entrust->hasRole('AnyRole'));
+ }
+
+ public function testCan()
+ {
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $entrust = m::mock('Zizaco\Entrust\Entrust[user]', [$app]);
+ $user = m::mock('_mockedUser');
+
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $entrust->shouldReceive('user')
+ ->andReturn($user)
+ ->twice()->ordered();
+
+ $entrust->shouldReceive('user')
+ ->andReturn(false)
+ ->once()->ordered();
+
$user->shouldReceive('can')
- ->with( 'manage_a' )
- ->once()
- ->andReturn( true );
-
- // Permission manage b as false
+ ->with('user_can')
+ ->andReturn(true)
+ ->once();
+
$user->shouldReceive('can')
- ->with( 'manage_b' )
- ->once()
- ->andReturn( false );
-
- $entrust = new Entrust( $this->mockAppWithCurrentUser( $user ) );
+ ->with('user_cannot')
+ ->andReturn(false)
+ ->once();
+
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ $this->assertTrue($entrust->can('user_can'));
+ $this->assertFalse($entrust->can('user_cannot'));
+ $this->assertFalse($entrust->can('any_permission'));
+ }
- // Check if user 'can'
- $this->assertTrue( $entrust->can('manage_a') );
- $this->assertFalse( $entrust->can('manage_b') );
+ public function testShouldGetUser()
+ {
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $app->auth = m::mock('Auth');
+ $entrust = new Entrust($app);
+ $user = m::mock('_mockedUser');
+
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $app->auth->shouldReceive('user')
+ ->andReturn($user)
+ ->once();
+
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ $this->assertSame($user, $entrust->user());
}
+
+ public function testRouteNeedsRole()
+ {
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $app->router = m::mock('Route');
+ $entrust = new Entrust($app);
+
+ $route = 'route';
+ $oneRole = 'RoleA';
+ $manyRole = ['RoleA', 'RoleB', 'RoleC'];
+ $emptyClosure = function () {};
+
+ $oneRoleFilterName = $this->makeFilterName($route, [$oneRole]);
+ $manyRoleFilterName = $this->makeFilterName($route, $manyRole);
- public function testEntrustHasRole()
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $app->router->shouldReceive('filter')
+ ->with(m::anyOf($oneRoleFilterName, $manyRoleFilterName), m::type('Closure'))
+ ->twice()->ordered();
+ $app->router->shouldReceive('filter')
+ ->with(m::anyOf($oneRoleFilterName, $manyRoleFilterName), m::mustBe($emptyClosure))
+ ->twice()->ordered();
+
+ $app->router->shouldReceive('when')
+ ->with($route, m::anyOf($oneRoleFilterName, $manyRoleFilterName))
+ ->times(4);
+
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ $entrust->routeNeedsRole($route, $oneRole);
+ $entrust->routeNeedsRole($route, $manyRole);
+ $entrust->routeNeedsRole($route, $oneRole, $emptyClosure);
+ $entrust->routeNeedsRole($route, $manyRole, $emptyClosure);
+ }
+
+ public function testFilterGeneratedByRouteNeedsRole()
{
- // Current user
- $user = m::mock( 'User' );
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $app->router = m::mock('Route');
+ $entrust = m::mock('Zizaco\Entrust\Entrust[hasRole]', [$app]);
+ $facadeApp = m::mock('_mockedApplication');
+ Facade::setFacadeApplication($facadeApp);
+
+ $route = 'route';
+ $userRoleA = 'UserRoleA';
+ $userRoleB = 'UserRoleB';
+ $nonUserRoleA = 'NonUserRoleA';
+ $nonUserRoleB = 'NonUserRoleB';
+ $nonUserRoles = [$nonUserRoleA, $nonUserRoleB];
+ $customResponse = new stdClass();
+
+ $roles = [];
+ $isPassedCustomResponse = false;
+ $isCumulative = false;
- // Permission manage a as true
- $user->shouldReceive('hasRole')
- ->with( 'AdminA' )
- ->once()
- ->andReturn( true );
+ $callFilterAndAssert = function ($filter) use (
+ $nonUserRoles,
+ $customResponse,
+ &$roles,
+ &$isPassedCustomResponse,
+ &$isCumulative
+ ) {
+ if (!($filter instanceof Closure)) {
+ return false;
+ }
+
+ $result = null;
+ $numAgainst = count(array_intersect($nonUserRoles, $roles));
+ $numTotal = count($roles);
+ $isUserAuthorized = !($numAgainst > 0 && ($isCumulative || $numAgainst === $numTotal));
- // Permission manage b as false
- $user->shouldReceive('hasRole')
- ->with( 'AdminB' )
- ->once()
- ->andReturn( false );
+ try {
+ $result = $filter();
+ } catch(Exception $e) {
+ $this->assertSame('abort', $e->getMessage());
+ $this->assertFalse($isPassedCustomResponse);
+ $this->assertFalse($isUserAuthorized);
+ return true;
+ }
+
+ if ($isUserAuthorized) {
+ $this->assertNull($result);
+ } else {
+ $this->assertSame($customResponse, $result);
+ }
- $entrust = new Entrust( $this->mockAppWithCurrentUser( $user ) );
+ return true;
+ };
+
+ $runTestCase = function (
+ array $caseRoles,
+ $result = null,
+ $cumulative = true
+ ) use (
+ $entrust,
+ $route,
+ &$roles,
+ &$isPassedCustomResponse,
+ &$isCumulative
+ ) {
+ list($roles, $isPassedCustomResponse, $isCumulative)
+ = [$caseRoles, !is_null($result), $cumulative];
+ $entrust->routeNeedsRole(
+ $route,
+ $caseRoles,
+ $result,
+ $cumulative
+ );
+ };
+
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $app->router->shouldReceive('filter')
+ ->with(m::type('string'), m::on($callFilterAndAssert));
+ $app->router->shouldReceive('when')
+ ->with($route, m::type('string'));
+
+ $facadeApp->shouldReceive('abort')
+ ->with(403)->andThrow('Exception', 'abort');
- // Check if user 'can'
- $this->assertTrue( $entrust->hasRole('AdminA') );
- $this->assertFalse( $entrust->hasRole('AdminB') );
+ $entrust->shouldReceive('hasRole')
+ ->with(m::anyOf($userRoleA, $userRoleB))
+ ->andReturn(true);
+ $entrust->shouldReceive('hasRole')
+ ->with(m::anyOf($nonUserRoleA, $nonUserRoleB))
+ ->andReturn(false);
+
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ // Case: User has both roles.
+ $runTestCase([$userRoleA, $userRoleB]);
+ $runTestCase([$userRoleA, $userRoleB], null, false);
+ $runTestCase([$userRoleA, $userRoleB], $customResponse);
+ $runTestCase([$userRoleA, $userRoleB], $customResponse, false);
+
+ // Case: User lacks a role.
+ $runTestCase([$nonUserRoleA, $userRoleB]);
+ $runTestCase([$nonUserRoleA, $userRoleB], null, false);
+ $runTestCase([$nonUserRoleA, $userRoleB], $customResponse);
+ $runTestCase([$nonUserRoleA, $userRoleB], $customResponse, false);
+
+ // Case: User lacks both roles.
+ $runTestCase([$nonUserRoleA, $nonUserRoleB]);
+ $runTestCase([$nonUserRoleA, $nonUserRoleB], null, false);
+ $runTestCase([$nonUserRoleA, $nonUserRoleB], $customResponse);
+ $runTestCase([$nonUserRoleA, $nonUserRoleB], $customResponse, false);
}
- public function testGetUser()
+ public function testRouteNeedsPermission()
{
- // Current user
- $user = m::mock( 'User' );
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $app->router = m::mock('Route');
+ $entrust = new Entrust($app);
+
+ $route = 'route';
+ $onePerm = 'can_a';
+ $manyPerm = ['can_a', 'can_b', 'can_c'];
+ $emptyClosure = function () {};
- $entrust = new Entrust( $this->mockAppWithCurrentUser( $user ) );
+ $onePermFilterName = $this->makeFilterName($route, [$onePerm]);
+ $manyPermFilterName = $this->makeFilterName($route, $manyPerm);
- // Check the returned user
- $this->assertEquals( $entrust->user(), $user );
- }
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $app->router->shouldReceive('filter')
+ ->with(m::anyOf($onePermFilterName, $manyPermFilterName), m::type('Closure'))
+ ->twice()->ordered();
+ $app->router->shouldReceive('filter')
+ ->with(m::anyOf($onePermFilterName, $manyPermFilterName), m::mustBe($emptyClosure))
+ ->twice()->ordered();
+
+ $app->router->shouldReceive('when')
+ ->with($route, m::anyOf($onePermFilterName, $manyPermFilterName))
+ ->times(4);
- public function testFilterRoutesNeedRole()
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ $entrust->routeNeedsPermission($route, $onePerm);
+ $entrust->routeNeedsPermission($route, $manyPerm);
+ $entrust->routeNeedsPermission($route, $onePerm, $emptyClosure);
+ $entrust->routeNeedsPermission($route, $manyPerm, $emptyClosure);
+ }
+
+ public function testFilterGeneratedByRouteNeedsPermission()
{
- $router = m::mock( 'Router' );
- $router->shouldReceive('filter')
- ->once();
- $router->shouldReceive('when')
- ->once();
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $app->router = m::mock('Route');
+ $entrust = m::mock('Zizaco\Entrust\Entrust[can]', [$app]);
+ $facadeApp = m::mock('_mockedApplication');
+ Facade::setFacadeApplication($facadeApp);
+
+ $route = 'route';
+ $userPermA = 'user_can_a';
+ $userPermB = 'user_can_b';
+ $nonUserPermA = 'user_cannot_a';
+ $nonUserPermB = 'user_cannot_b';
+ $nonUserPerms = [$nonUserPermA, $nonUserPermB];
+ $customResponse = new stdClass();
+
+ $perms = [];
+ $isPassedCustomResponse = false;
+ $isCumulative = false;
- $app = array('router'=>$router);
+ $callFilterAndAssert = function ($filter) use (
+ $nonUserPerms,
+ $customResponse,
+ &$perms,
+ &$isPassedCustomResponse,
+ &$isCumulative
+ ) {
+ if (!($filter instanceof Closure)) {
+ return false;
+ }
+
+ $result = null;
+ $numAgainst = count(array_intersect($nonUserPerms, $perms));
+ $numTotal = count($perms);
+ $isUserAuthorized = !($numAgainst > 0 && ($isCumulative || $numAgainst === $numTotal));
- $entrust = new Entrust( $app );
+ try {
+ $result = $filter();
+ } catch(Exception $e) {
+ $this->assertSame('abort', $e->getMessage());
+ $this->assertFalse($isPassedCustomResponse);
+ $this->assertFalse($isUserAuthorized);
+ return true;
+ }
- $entrust->routeNeedsRole('admin','Admin');
- }
+ if ($isUserAuthorized) {
+ $this->assertNull($result);
+ } else {
+ $this->assertSame($customResponse, $result);
+ }
- public function testFilterRoutesNeedPermission()
+ return true;
+ };
+
+ $runTestCase = function (
+ array $casePerms,
+ $result = null,
+ $cumulative = true
+ ) use (
+ $entrust,
+ $route,
+ &$perms,
+ &$isPassedCustomResponse,
+ &$isCumulative
+ ) {
+ list($perms, $isPassedCustomResponse, $isCumulative)
+ = [$casePerms, !is_null($result), $cumulative];
+ $entrust->routeNeedsPermission(
+ $route,
+ $casePerms,
+ $result,
+ $cumulative
+ );
+ };
+
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $app->router->shouldReceive('filter')
+ ->with(m::type('string'), m::on($callFilterAndAssert));
+ $app->router->shouldReceive('when')
+ ->with($route, m::type('string'));
+
+ $facadeApp->shouldReceive('abort')
+ ->with(403)->andThrow('Exception', 'abort');
+
+ $entrust->shouldReceive('can')
+ ->with(m::anyOf($userPermA, $userPermB))
+ ->andReturn(true);
+ $entrust->shouldReceive('can')
+ ->with(m::anyOf($nonUserPermA, $nonUserPermB))
+ ->andReturn(false);
+
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ // Case: User has both permissions.
+ $runTestCase([$userPermA, $userPermB]);
+ $runTestCase([$userPermA, $userPermB], null, false);
+ $runTestCase([$userPermA, $userPermB], $customResponse);
+ $runTestCase([$userPermA, $userPermB], $customResponse, false);
+
+
+ // Case: User lacks a permission.
+ $runTestCase([$nonUserPermA, $userPermB]);
+ $runTestCase([$nonUserPermA, $userPermB], null, false);
+ $runTestCase([$nonUserPermA, $userPermB], $customResponse, false);
+ $runTestCase([$nonUserPermA, $userPermB], $customResponse);
+
+ // Case: User lacks both permissions.
+ $runTestCase([$nonUserPermA, $nonUserPermB]);
+ $runTestCase([$nonUserPermA, $nonUserPermB], null, false);
+ $runTestCase([$nonUserPermA, $nonUserPermB], $customResponse, false);
+ $runTestCase([$nonUserPermA, $nonUserPermB], $customResponse);
+ }
+
+ public function testRouteNeedsRoleOrPermission()
{
- $router = m::mock( 'Router' );
- $router->shouldReceive('filter')
- ->once();
- $router->shouldReceive('when')
- ->once();
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $app->router = m::mock('Route');
+ $entrust = new Entrust($app);
+
+ $route = 'route';
+ $oneRole = 'RoleA';
+ $manyRole = ['RoleA', 'RoleB', 'RoleC'];
+ $onePerm = 'can_a';
+ $manyPerm = ['can_a', 'can_b', 'can_c'];
+ $emptyClosure = function () {};
- $app = array('router'=>$router);
+ $oneRoleOnePermFilterName = $this->makeFilterName($route, [$oneRole], [$onePerm]);
+ $oneRoleManyPermFilterName = $this->makeFilterName($route, [$oneRole], $manyPerm);
+ $manyRoleOnePermFilterName = $this->makeFilterName($route, $manyRole, [$onePerm]);
+ $manyRoleManyPermFilterName = $this->makeFilterName($route, $manyRole, $manyPerm);
- $entrust = new Entrust( $app );
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $app->router->shouldReceive('filter')
+ ->with(
+ m::anyOf(
+ $oneRoleOnePermFilterName,
+ $oneRoleManyPermFilterName,
+ $manyRoleOnePermFilterName,
+ $manyRoleManyPermFilterName
+ ),
+ m::type('Closure')
+ )
+ ->times(4)->ordered();
+ $app->router->shouldReceive('filter')
+ ->with(
+ m::anyOf(
+ $oneRoleOnePermFilterName,
+ $oneRoleManyPermFilterName,
+ $manyRoleOnePermFilterName,
+ $manyRoleManyPermFilterName
+ ),
+ m::mustBe($emptyClosure)
+ )
+ ->times(4)->ordered();
- $entrust->routeNeedsPermission('admin','manage_users');
- }
+ $app->router->shouldReceive('when')
+ ->with(
+ $route,
+ m::anyOf(
+ $oneRoleOnePermFilterName,
+ $oneRoleManyPermFilterName,
+ $manyRoleOnePermFilterName,
+ $manyRoleManyPermFilterName
+ )
+ )
+ ->times(8);
- private function mockAppWithCurrentUser( $user )
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ $entrust->routeNeedsRoleOrPermission($route, $oneRole, $onePerm);
+ $entrust->routeNeedsRoleOrPermission($route, $oneRole, $manyPerm);
+ $entrust->routeNeedsRoleOrPermission($route, $manyRole, $onePerm);
+ $entrust->routeNeedsRoleOrPermission($route, $manyRole, $manyPerm);
+
+ $entrust->routeNeedsRoleOrPermission($route, $oneRole, $onePerm, $emptyClosure);
+ $entrust->routeNeedsRoleOrPermission($route, $oneRole, $manyPerm, $emptyClosure);
+ $entrust->routeNeedsRoleOrPermission($route, $manyRole, $onePerm, $emptyClosure);
+ $entrust->routeNeedsRoleOrPermission($route, $manyRole, $manyPerm, $emptyClosure);
+ }
+
+ public function testFilterGeneratedByRouteNeedsRoleOrPermission()
{
- // Mock app
- $app = array( 'auth' => m::mock( 'Auth' ) );
+ /*
+ |------------------------------------------------------------
+ | Set
+ |------------------------------------------------------------
+ */
+ $app = new stdClass();
+ $app->router = m::mock('Route');
+ $entrust = m::mock('Zizaco\Entrust\Entrust[hasRole,can]', [$app]);
+ $facadeApp = m::mock('_mockedApplication');
+ Facade::setFacadeApplication($facadeApp);
+
+ $route = 'route';
+ $userRoleA = 'UserRoleA';
+ $userRoleB = 'UserRoleB';
+ $userPermA = 'user_can_a';
+ $userPermB = 'user_can_b';
+ $nonUserRoleA = 'NonUserRoleA';
+ $nonUserRoleB = 'NonUserRoleB';
+ $nonUserPermA = 'user_cannot_a';
+ $nonUserPermB = 'user_cannot_b';
+ $nonUserRolesPerms = [$nonUserRoleA, $nonUserRoleB, $nonUserPermA, $nonUserPermB];
+ $customResponse = new stdClass();
+
+ $roles = [];
+ $perms = [];
+ $isPassedCustomResponse = false;
+ $isCumulative = false;
+
+ $callFilterAndAssert = function ($filter) use (
+ $nonUserRolesPerms,
+ $customResponse,
+ &$roles,
+ &$perms,
+ &$isPassedCustomResponse,
+ &$isCumulative
+ ) {
+ if (!($filter instanceof Closure)) {
+ return false;
+ }
+
+ $result = null;
+ $numAgainst = count(array_intersect($nonUserRolesPerms, array_merge($roles, $perms)));
+ $numTotal = count(array_merge($roles, $perms));
+ $isUserAuthorized = !($numAgainst > 0 && ($isCumulative || $numAgainst === $numTotal));
+
+ try {
+ $result = $filter();
+ } catch(Exception $e) {
+ $this->assertSame('abort', $e->getMessage());
+ $this->assertFalse($isPassedCustomResponse);
+ $this->assertFalse($isUserAuthorized);
+ return true;
+ }
- // Return current user within Auth mock
- $app['auth']->shouldReceive('user')
- ->andReturn( $user );
+ if ($isUserAuthorized) {
+ $this->assertNull($result);
+ } else {
+ $this->assertSame($customResponse, $result);
+ }
- return $app;
+ return true;
+ };
+
+ $runTestCase = function (
+ array $caseRoles,
+ array $casePerms,
+ $result = null,
+ $cumulative = false
+ ) use (
+ $entrust,
+ $route,
+ &$roles,
+ &$perms,
+ &$isPassedCustomResponse,
+ &$isCumulative
+ ) {
+ list($roles, $perms, $isPassedCustomResponse, $isCumulative)
+ = [$caseRoles, $casePerms, !is_null($result), $cumulative];
+ $entrust->routeNeedsRoleOrPermission(
+ $route,
+ $caseRoles,
+ $casePerms,
+ $result,
+ $cumulative
+ );
+ };
+
+ /*
+ |------------------------------------------------------------
+ | Expectation
+ |------------------------------------------------------------
+ */
+ $app->router->shouldReceive('filter')
+ ->with(m::type('string'), m::on($callFilterAndAssert));
+ $app->router->shouldReceive('when')
+ ->with($route, m::type('string'));
+
+ $facadeApp->shouldReceive('abort')
+ ->with(403)->andThrow('Exception', 'abort');
+
+ $entrust->shouldReceive('hasRole')
+ ->with(m::anyOf($userRoleA, $userRoleB))
+ ->andReturn(true);
+ $entrust->shouldReceive('hasRole')
+ ->with(m::anyOf($nonUserRoleA, $nonUserRoleB))
+ ->andReturn(false);
+ $entrust->shouldReceive('can')
+ ->with(m::anyOf($userPermA, $userPermB))
+ ->andReturn(true);
+ $entrust->shouldReceive('can')
+ ->with(m::anyOf($nonUserPermA, $nonUserPermB))
+ ->andReturn(false);
+
+ /*
+ |------------------------------------------------------------
+ | Assertion
+ |------------------------------------------------------------
+ */
+ // Case: User has everything.
+ $runTestCase([$userRoleA, $userRoleB], [$userPermA, $userPermB]);
+ $runTestCase([$userRoleA, $userRoleB], [$userPermA, $userPermB], null, true);
+ $runTestCase([$userRoleA, $userRoleB], [$userPermA, $userPermB], $customResponse, true);
+ $runTestCase([$userRoleA, $userRoleB], [$userPermA, $userPermB], $customResponse);
+
+ // Case: User lacks a role.
+ $runTestCase([$nonUserRoleA, $userRoleB], [$userPermA, $userPermB]);
+ $runTestCase([$nonUserRoleA, $userRoleB], [$userPermA, $userPermB], null, true);
+ $runTestCase([$nonUserRoleA, $userRoleB], [$userPermA, $userPermB], $customResponse, true);
+ $runTestCase([$nonUserRoleA, $userRoleB], [$userPermA, $userPermB], $customResponse);
+
+ // Case: User lacks a permission.
+ $runTestCase([$userRoleA, $userRoleB], [$nonUserPermA, $userPermB]);
+ $runTestCase([$userRoleA, $userRoleB], [$nonUserPermA, $userPermB], null, true);
+ $runTestCase([$userRoleA, $userRoleB], [$nonUserPermA, $userPermB], $customResponse, true);
+ $runTestCase([$userRoleA, $userRoleB], [$nonUserPermA, $userPermB], $customResponse);
+
+ // Case: User lacks a role and a permission.
+ $runTestCase([$nonUserRoleA, $userRoleB], [$nonUserPermA, $userPermB]);
+ $runTestCase([$nonUserRoleA, $userRoleB], [$nonUserPermA, $userPermB], null, true);
+ $runTestCase([$nonUserRoleA, $userRoleB], [$nonUserPermA, $userPermB], $customResponse, true);
+ $runTestCase([$nonUserRoleA, $userRoleB], [$nonUserPermA, $userPermB], $customResponse);
+
+ // Case: User lacks everything.
+ $runTestCase([$nonUserRoleA, $nonUserRoleB], [$nonUserPermA, $nonUserPermB]);
+ $runTestCase([$nonUserRoleA, $nonUserRoleB], [$nonUserPermA, $nonUserPermB], null, true);
+ $runTestCase([$nonUserRoleA, $nonUserRoleB], [$nonUserPermA, $nonUserPermB], $customResponse, true);
+ $runTestCase([$nonUserRoleA, $nonUserRoleB], [$nonUserPermA, $nonUserPermB], $customResponse);
+ }
+
+ protected function makeFilterName($route, array $roles, array $permissions = null)
+ {
+ if (is_null($permissions)) {
+ return implode('_', $roles) . '_' . substr(md5($route), 0, 6);
+ } else {
+ return implode('_', $roles) . '_' . implode('_', $permissions) . '_' . substr(md5($route), 0, 6);
+ }
}
}