Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php namespace PrivacyDriver\Providers;
use Cache;
use Config;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Collection;
use Artisan;
use Gate;
use PrivacyDriver\Cache\PDRedisStore;
use Schema;
use PrivacyDriver\Models\Permission\Permission;
use PrivacyDriver\Models\User\User;
use ReflectionClass;
use View;
/**
* Class AuthServiceProvider
* @package PrivacyDriver\Providers
*/
class AuthServiceProvider extends ServiceProvider
{
/**
* Mapping of events to actions
* @var array
*/
protected static $action_events = ["creating" => "create", "updating" => "update", "saving" => "update", "deleting" => "delete"];
/**
* The policy mappings for the application.
* @var array
*/
protected $policies = [];
/**
* Returns action events array
* @return array
*/
public static function actions() {
return array_values(self::$action_events);
}
/**
* Register any application authentication / authorization services.
*
* @param GateContract $gate
* @return void
*/
public function boot(GateContract $gate)
{
$this->policies = Config::get('privacydriver.model_policies');
$this->configure_gate_before($gate);
//Actived cache
$datatabase_permissions = Cache::remember(PDRedisStore::PERMISSION, 60, function() {
return $this->getPermissions();
});
//Disabled cache
//$datatabase_permissions = $this->getPermissions();
$this->define_abilities($gate, $datatabase_permissions);
if (Config::get('privacydriver.create_permissions_on_auth')) {
$this->createAndRegisterPolicies($gate, $this->permissionsToArray($datatabase_permissions));
} else {
parent::registerPolicies($gate);
}
$this->registerAuthorizationEvents();
}
/**
* Configure before method on gate. Superadmin users and Acting As Another role
* @param GateContract|Gate $gate
*/
protected function configure_gate_before($gate) {
$gate->before(function ($user, $ability) {
if ($ability != 'act-as-another') {
/** @var User $user */
if($user->isActing() ){
$permission = Permission::where('name', $ability)->with('roles', 'roles.translations', 'translations')->first();
if ($permission != null) {
if ($user->actAs( $permission->toArray()['roles']) ) {
return true;
}
}
}
}
if ($user->isSuperAdmin()) {
return true;
}
});
}
/**
* Get Permissions from database
* @return array|\Illuminate\Database\Eloquent\Collection|static[]
*/
protected function getPermissions()
{
try {
if (Schema::hasTable(with(new Permission)->getTable())) {
$AllPermissions = Permission::with('roles', 'roles.translations', 'translations')->get();
$rolePermissions = [];
foreach ($AllPermissions as $permission ) {
$rolePermissions[$permission->name] = $permission->roles->pluck('name')->toArray();
}
return $rolePermissions;
} else {
return array();
}
} catch (\PDOException $e) {
return array();
}
}
/**
* Define Laravel 5.1 abilities using and array of permissions
* @param \Gate|GateContract $gate
* @param $permissions
*/
protected function define_abilities($gate, $permissions)
{
foreach ($permissions as $permissionName => $permissionRoleNames) {
$gate->define($permissionName, function ($user) use ($permissionRoleNames) {
/** @var User $user */
return $user->hasRole($permissionRoleNames);
});
}
}
/**
* Return and array of permission names from Collestion
* @param Collectionç/array $permissions
* @return array
*/
protected function permissionsToArray($permissions)
{
$permissions_array = $permissions;
if ($permissions instanceof Collection){
$permissions_array = $permissions->pluck("name")->toArray();
}
return $permissions_array;
}
/**
* Create And Register the application's policies.
*
* @param \Illuminate\Contracts\Auth\Access\Gate $gate
* @param array $permissions existing permissions
* @return void
*/
public function createAndRegisterPolicies(GateContract $gate,$permissions)
{
parent::registerPolicies($gate);
$this->createPolicies($permissions);
}
/**
* Create the application's policies.
* @param $permissions
*/
public function createPolicies($permissions)
{
//Create policy classes dinamically if not exists using custom php artisan make:pd-policy
if ($this->check_connection()) {
foreach ($this->policies as $key => $value) {
Artisan::call('make:pd-policy', ['name' => $value, 'model' => $key, 'permissions' => $permissions]);
}
}
}
/**
* Register Authorization Events
*/
protected function registerAuthorizationEvents()
{
foreach ($this->policies as $model => $policy) {
foreach (self::$action_events as $event => $action) {
$this->registerEventModel($model, $event, $action);
}
}
}
/**
* Register Event Model
* @param $modelName
* @param $eventName
* @param $action
*/
protected function registerEventModel($modelName, $eventName, $action)
{
$modelName::$eventName(function ($model) use ($action,$modelName) {
if (Gate::denies($action, $model)) {
View::share('permission', $this->getPermissionNameSuffix($modelName) . '-' . $action);
abort(403);
}
});
}
/**
* Get undercase model name
* @param $model
* @return string
*/
protected function getPermissionNameSuffix($model) {
return strtolower((new ReflectionClass($model))->getShortName());
}
/**
* Checks connection to database an existance of permissions table
* @return bool
*/
protected function check_connection()
{
try {
if (Schema::hasTable(with(new Permission)->getTable())) {
return true;
} else {
return false;
}
} catch (\PDOException $e) {
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment