Skip to content

Commit

Permalink
Merge pull request #1 from ARCANEDEV/develop
Browse files Browse the repository at this point in the history
Adding Impersonation policies & facade
  • Loading branch information
arcanedev-maroc authored May 10, 2017
2 parents b475371 + 6541dc5 commit 37aec82
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/Facades/Impersonator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php namespace Arcanedev\LaravelImpersonator\Facades;

use Arcanedev\LaravelImpersonator\Contracts\Impersonator as ImpersonatorContract;
use Illuminate\Support\Facades\Facade;

/**
* Class Impersonator
*
* @package Arcanedev\LaravelImpersonator\Facades
* @author ARCANEDEV <[email protected]>
*/
class Impersonator extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor() { return ImpersonatorContract::class; }
}
2 changes: 2 additions & 0 deletions src/ImpersonatorServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public function register()

$this->registerConfig();

$this->registerProvider(Providers\AuthorizationServiceProvider::class);

$this->singleton(Contracts\Impersonator::class, Impersonator::class);
$this->extendAuthDriver();
}
Expand Down
51 changes: 51 additions & 0 deletions src/Policies/ImpersonationPolicy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php namespace Arcanedev\LaravelImpersonator\Policies;

use Arcanedev\LaravelImpersonator\Contracts\Impersonatable;
use Arcanedev\Support\Bases\Policy;

/**
* Class ImpersonationPolicy
*
* @package Arcanedev\LaravelImpersonator\Policies
* @author ARCANEDEV <[email protected]>
*/
class ImpersonationPolicy extends Policy
{
/* -----------------------------------------------------------------
| Constants
| -----------------------------------------------------------------
*/

const CAN_IMPERSONATE = 'auth.impersonator.can-impersonate';
const CAN_BE_IMPERSONATED = 'auth.impersonator.can-be-impersonated';

/* -----------------------------------------------------------------
| Main Methods
| -----------------------------------------------------------------
*/

/**
* Check if the current user has the `can impersonate` ability.
*
* @param \Arcanedev\LaravelImpersonator\Contracts\Impersonatable $impersonator
*
* @return bool
*/
public function canImpersonatePolicy(Impersonatable $impersonator)
{
return $impersonator->canImpersonate();
}

/**
* Check if the given user can be impersonated.
*
* @param \Arcanedev\LaravelImpersonator\Contracts\Impersonatable $impersonator
* @param \Arcanedev\LaravelImpersonator\Contracts\Impersonatable $impersonated
*
* @return bool
*/
public function canBeImpersonatedPolicy(Impersonatable $impersonator, Impersonatable $impersonated)
{
return $this->canImpersonatePolicy($impersonator) && $impersonated->canBeImpersonated();
}
}
28 changes: 28 additions & 0 deletions src/Providers/AuthorizationServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php namespace Arcanedev\LaravelImpersonator\Providers;

use Arcanedev\LaravelImpersonator\Policies\ImpersonationPolicy;
use Arcanedev\Support\Providers\AuthorizationServiceProvider as ServiceProvider;

/**
* Class AuthorizationServiceProvider
*
* @package Arcanedev\LaravelImpersonator\Providers
* @author ARCANEDEV <[email protected]>
*/
class AuthorizationServiceProvider extends ServiceProvider
{
/* -----------------------------------------------------------------
| Main Methods
| -----------------------------------------------------------------
*/

/**
* Register any application authentication / authorization services.
*/
public function boot()
{
parent::registerPolicies();

$this->defineMany(ImpersonationPolicy::class, ImpersonationPolicy::policies());
}
}
75 changes: 75 additions & 0 deletions tests/ImpersonationPoliciesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php namespace Arcanedev\LaravelImpersonator\Tests;

/**
* Class ImpersonationPoliciesTest
*
* @package Arcanedev\LaravelImpersonator\Tests
* @author ARCANEDEV <[email protected]>
*/
class ImpersonationPoliciesTest extends TestCase
{
/* -----------------------------------------------------------------
| Tests
| -----------------------------------------------------------------
*/

/** @test */
public function it_can_allow_access_to_impersonator()
{
$this->loginWithId(1);

$response = $this->get(route('auth::impersonator.start', [2]));

$response->assertSuccessful();
$response->assertSessionHas('impersonator_id');
$response->assertSeeText('Impersonation started');
}

/** @test */
public function it_can_deny_access_to_impersonator()
{
$this->loginWithId(2);

$response = $this->get(route('auth::impersonator.start', [3]));

$response->assertStatus(403);
}

/** @test */
public function it_can_deny_access_if_impersonated_can_not_be_impersonated()
{
$this->loginWithId(1);

$response = $this->get(route('auth::impersonator.start', [4]));

$response->assertStatus(403);
}

/** @test */
public function it_can_stop_ongoing_impersonation()
{
$this->loginWithId(1);

$response = $this->get(route('auth::impersonator.start', [2]));

$response->assertSuccessful();
$response->assertSessionHas('impersonator_id');
$response->assertSeeText('Impersonation started');

$response = $this->get(route('auth::impersonator.stop'));

$response->assertSuccessful();
$response->assertSessionMissing('impersonator_id');
$response->assertSeeText('Impersonation stopped');
}

/** @test */
public function it_can_redirect_if_impersonation_not_started()
{
$this->loginWithId(1);

$response = $this->get(route('auth::impersonator.stop'));

$response->assertStatus(302);
}
}
77 changes: 77 additions & 0 deletions tests/Stubs/Controllers/ImpersonatorController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php namespace Arcanedev\LaravelImpersonator\Tests\Stubs\Controllers;

use Arcanedev\LaravelImpersonator\Contracts\Impersonator;
use Arcanedev\LaravelImpersonator\Policies\ImpersonationPolicy;
use Arcanedev\LaravelImpersonator\Tests\Stubs\Models\User;
use Arcanedev\Support\Http\Controller;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;

/**
* Class ImpersonatorController
*
* @package Arcanedev\LaravelImpersonator\Tests\Stubs\Controllers
* @author ARCANEDEV <[email protected]>
*/
class ImpersonatorController extends Controller
{
/* -----------------------------------------------------------------
| Traits
| -----------------------------------------------------------------
*/

use AuthorizesRequests;

/* -----------------------------------------------------------------
| Properties
| -----------------------------------------------------------------
*/

/** @var \Arcanedev\LaravelImpersonator\Contracts\Impersonator */
private $impersonator;

/* -----------------------------------------------------------------
| Constructor
| -----------------------------------------------------------------
*/

/**
* ImpersonatorController constructor.
*
* @param \Arcanedev\LaravelImpersonator\Contracts\Impersonator $impersonator
*/
public function __construct(Impersonator $impersonator)
{
parent::__construct();

$this->middleware('auth');

$this->impersonator = $impersonator;
}

/* -----------------------------------------------------------------
| Main Methods
| -----------------------------------------------------------------
*/

public function start($id)
{
$impersonated = User::findOrFail($id);

$this->authorize(ImpersonationPolicy::CAN_BE_IMPERSONATED, [$impersonated]);

return $this->impersonator->start(auth()->user(), $impersonated)
? 'Impersonation started'
: 'Impersonation failed';
}

public function stop()
{
if ( ! $this->impersonator->isImpersonating()) {
return redirect()->back();
}

return $this->impersonator->stop()
? 'Impersonation stopped'
: 'Impersonation failed';
}
}
26 changes: 26 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ protected function getPackageAliases($app)
*/
protected function getEnvironmentSetUp($app)
{
$app['config']->set('app.debug', true);

$app['config']->set('database.default', 'testbench');
$app['config']->set('database.connections.testbench', [
'driver' => 'sqlite',
Expand All @@ -76,6 +78,8 @@ protected function getEnvironmentSetUp($app)
]);

$app['config']->set('auth.providers.users.model', Stubs\Models\User::class);

$this->setUpRoutes($app['router']);
}

/* -----------------------------------------------------------------
Expand Down Expand Up @@ -122,4 +126,26 @@ protected function assertIsLoggedIn()
{
$this->assertTrue($this->app['auth']->check());
}

/**
* @param \Illuminate\Routing\Router $router
*/
private function setUpRoutes($router)
{
$router->group([
'namespace' => 'Arcanedev\LaravelImpersonator\Tests\Stubs\Controllers',
'as' => 'auth::impersonator.',
'middleware' => 'web',
], function () use ($router) {
$router->get('start/{id}', [
'uses' => 'ImpersonatorController@start',
'as' => 'start', // auth::impersonator.start
]);

$router->get('stop', [
'uses' => 'ImpersonatorController@stop',
'as' => 'stop', // auth::impersonator.stop
]);
});
}
}

0 comments on commit 37aec82

Please sign in to comment.