Skip to content

Commit

Permalink
Merge d0562d0 into 05fc39f
Browse files Browse the repository at this point in the history
  • Loading branch information
Vendin committed Jul 25, 2019
2 parents 05fc39f + d0562d0 commit 6b91f45
Show file tree
Hide file tree
Showing 11 changed files with 310 additions and 35 deletions.
15 changes: 15 additions & 0 deletions config/laravel-impersonate.php
Expand Up @@ -7,6 +7,21 @@
*/
'session_key' => 'impersonated_by',

/**
* The session key used to stored the original user guard.
*/
'session_guard' => 'impersonator_guard',

/**
* The session key used to stored what guard is impersonator using.
*/
'session_guard_using' => 'impersonator_guard_using',

/**
* The default impersonator guard used.
*/
'default_impersonator_guard' => 'web',

/**
* The URI to redirect after taking an impersonation.
*
Expand Down
43 changes: 43 additions & 0 deletions migrations/2018_10_27_000000_create_absolute_admins_table.php
@@ -0,0 +1,43 @@
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class CreateAbsoluteAdminsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('absolute_admins', function (Blueprint $table)
{
$table->increments('id');
$table->string('username')->unique();
$table->string('password');
$table->timestamps();
});

DB::table('absolute_admins')->insert([
[
'username' => 'absolute_admin',
'password' => bcrypt('password'),
],
]);
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('absolute_admins');
}
}
14 changes: 9 additions & 5 deletions src/Controllers/ImpersonateController.php
Expand Up @@ -24,12 +24,16 @@ public function __construct()

/**
* @param int $id
* @param string|null $guardName
* @throws \Exception
* @return RedirectResponse
*/
public function take(Request $request, $id)
public function take(Request $request, $id, $guardName = null)
{
$guardName = $guardName ?? $this->manager->getDefaultSessionGuard();

// Cannot impersonate yourself
if ($id == $request->user()->getKey()) {
if ($id == $request->user()->getKey() && ($this->manager->getCurrentAuthGuardName() == $guardName)) {
abort(403);
}

Expand All @@ -42,10 +46,10 @@ public function take(Request $request, $id)
abort(403);
}

$user_to_impersonate = $this->manager->findUserById($id);
$userToImpersonate = $this->manager->findUserById($id, $guardName);

if ($user_to_impersonate->canBeImpersonated()) {
if ($this->manager->take($request->user(), $user_to_impersonate)) {
if ($userToImpersonate->canBeImpersonated()) {
if ($this->manager->take($request->user(), $userToImpersonate, $guardName)) {
$takeRedirect = $this->manager->getTakeRedirectTo();
if ($takeRedirect !== 'back') {
return redirect()->to($takeRedirect);
Expand Down
24 changes: 20 additions & 4 deletions src/ImpersonateServiceProvider.php
Expand Up @@ -3,11 +3,14 @@
namespace Lab404\Impersonate;

use Illuminate\Auth\AuthManager;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Foundation\Application;
use Illuminate\View\Compilers\BladeCompiler;
use Lab404\Impersonate\Guard\SessionGuard;
use Lab404\Impersonate\Middleware\ProtectFromImpersonation;
use Lab404\Impersonate\Services\ImpersonateManager;
use Illuminate\Support\Facades\Event;

/**
* Class ServiceProvider
Expand Down Expand Up @@ -57,6 +60,14 @@ public function register()
public function boot()
{
$this->publishConfig();

//We want to remove data from storage on real login and logout
Event::listen(Login::class, function ($event) {
app('impersonate')->clear();
});
Event::listen(Logout::class, function ($event) {
app('impersonate')->clear();
});
}

/**
Expand All @@ -69,15 +80,18 @@ protected function registerBladeDirectives()
{
$this->app->afterResolving('blade.compiler', function (BladeCompiler $bladeCompiler) {
$bladeCompiler->directive('impersonating', function () {
return '<?php if (app()["auth"]->check() && app()["auth"]->user()->isImpersonated()): ?>';
$guard = $this->app['impersonate']->getCurrentAuthGuardName();
return "<?php if (app()['auth']->guard('$guard')->check() && app()['auth']->guard('$guard')->user()->isImpersonated()): ?>";
});

$bladeCompiler->directive('endImpersonating', function () {
return '<?php endif; ?>';
});

$bladeCompiler->directive('canImpersonate', function () {
return '<?php if (app()["auth"]->check() && app()["auth"]->user()->canImpersonate()): ?>';
$guard = $this->app['impersonate']->getCurrentAuthGuardName();
return "<?php if (app()['auth']->guard('$guard')->check()
&& app()['auth']->guard('$guard')->user()->canImpersonate()): ?>";
});

$bladeCompiler->directive('endCanImpersonate', function () {
Expand All @@ -86,8 +100,10 @@ protected function registerBladeDirectives()

$bladeCompiler->directive('canBeImpersonated', function ($expression) {
$user = trim($expression);
$guard = $this->app['impersonate']->getCurrentAuthGuardName();

return "<?php if (app()['auth']->check() && app()['auth']->user()->id != {$user}->id && {$user}->canBeImpersonated()): ?>";
return "<?php if (app()['auth']->guard('$guard')->check()
&& app()['auth']->guard('$guard')->user()->id != {$user}->id && {$user}->canBeImpersonated()): ?>";
});

$bladeCompiler->directive('endCanBeImpersonated', function () {
Expand All @@ -107,7 +123,7 @@ protected function registerRoutesMacro()
$router = $this->app['router'];

$router->macro('impersonate', function () use ($router) {
$router->get('/impersonate/take/{id}',
$router->get('/impersonate/take/{id}/{guardName?}',
'\Lab404\Impersonate\Controllers\ImpersonateController@take')->name('impersonate');
$router->get('/impersonate/leave',
'\Lab404\Impersonate\Controllers\ImpersonateController@leave')->name('impersonate.leave');
Expand Down
5 changes: 3 additions & 2 deletions src/Models/Impersonate.php
Expand Up @@ -33,11 +33,12 @@ public function canBeImpersonated()
* Impersonate the given user.
*
* @param Model $user
* @param string|null $guardName
* @return bool
*/
public function impersonate(Model $user)
public function impersonate(Model $user, $guardName = null)
{
return app(ImpersonateManager::class)->take($this, $user);
return app(ImpersonateManager::class)->take($this, $user, $guardName);
}

/**
Expand Down
90 changes: 79 additions & 11 deletions src/Services/ImpersonateManager.php
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Foundation\Application;
use Lab404\Impersonate\Events\LeaveImpersonation;
use Lab404\Impersonate\Events\TakeImpersonation;
use Exception;

class ImpersonateManager
{
Expand All @@ -27,17 +28,24 @@ public function __construct(Application $app)
/**
* @param int $id
* @return Model
* @throws Exception
*/
public function findUserById($id)
public function findUserById($id, $guardName = null)
{
$model = $this->app['config']->get('auth.providers.users.model');
$userProvider = $this->app['config']->get("auth.guards.$guardName.provider");
$model = $this->app['config']->get("auth.providers.$userProvider.model");

$user = call_user_func([
if(!$model) {
throw new Exception("Auth guard doesn not exist.", 1);
}

/** @var Model $modelInstance */
$modelInstance = call_user_func([
$model,
'findOrFail'
], $id);

return $user;
return $modelInstance;
}

/**
Expand All @@ -57,18 +65,38 @@ public function getImpersonatorId()
return session($this->getSessionKey(), null);
}

/**
* @return string|null
*/
public function getImpersonatorGuardName()
{
return session($this->getSessionGuard(), null);
}

/**
* @return string|null
*/
public function getImpersonatorGuardUsingName()
{
return session($this->getSessionGuardUsing(), null);
}

/**
* @param Model $from
* @param Model $to
* @param string|null $guardName
* @return bool
*/
public function take($from, $to)
public function take($from, $to, $guardName = null)
{
try {
$currentGuard = $this->getCurrentAuthGuardName();
session()->put($this->getSessionKey(), $from->getKey());
session()->put($this->getSessionGuard(), $currentGuard);
session()->put($this->getSessionGuardUsing(), $guardName);

$this->app['auth']->quietLogout();
$this->app['auth']->quietLogin($to);
$this->app['auth']->guard($currentGuard)->quietLogout();
$this->app['auth']->guard($guardName)->quietLogin($to);

} catch (\Exception $e) {
unset($e);
Expand All @@ -86,11 +114,11 @@ public function take($from, $to)
public function leave()
{
try {
$impersonated = $this->app['auth']->user();
$impersonator = $this->findUserById($this->getImpersonatorId());
$impersonated = $this->app['auth']->guard($this->getImpersonatorGuardUsingName())->user();
$impersonator = $this->findUserById($this->getImpersonatorId(), $this->getImpersonatorGuardName());

$this->app['auth']->quietLogout();
$this->app['auth']->quietLogin($impersonator);
$this->app['auth']->guard($this->getCurrentAuthGuardName())->quietLogout();
$this->app['auth']->guard($this->getImpersonatorGuardName())->quietLogin($impersonator);

$this->clear();

Expand All @@ -110,6 +138,8 @@ public function leave()
public function clear()
{
session()->forget($this->getSessionKey());
session()->forget($this->getSessionGuard());
session()->forget($this->getSessionGuardUsing());
}

/**
Expand All @@ -120,6 +150,30 @@ public function getSessionKey()
return config('laravel-impersonate.session_key');
}

/**
* @return string
*/
public function getSessionGuard()
{
return config('laravel-impersonate.session_guard');
}

/**
* @return string
*/
public function getSessionGuardUsing()
{
return config('laravel-impersonate.session_guard_using');
}

/**
* @return string
*/
public function getDefaultSessionGuard()
{
return config('laravel-impersonate.default_impersonator_guard');
}

/**
* @return string
*/
Expand Down Expand Up @@ -147,4 +201,18 @@ public function getLeaveRedirectTo()

return $uri;
}

/**
* @return array
*/
public function getCurrentAuthGuardName()
{
$guards = array_keys(config('auth.guards'));
foreach ($guards as $guard) {
if ($this->app['auth']->guard($guard)->check()) {
return $guard;
}
}
return null;
}
}

0 comments on commit 6b91f45

Please sign in to comment.