Improved permission regen performance by factor of 4

Worked around slower eloquent access to speed up permission generation.
This commit is contained in:
Dan Brown 2016-04-30 17:16:06 +01:00
parent 9a31b83b2a
commit 59367b3417
16 changed files with 49 additions and 60 deletions

View File

@ -2,8 +2,6 @@
namespace BookStack; namespace BookStack;
use Illuminate\Database\Eloquent\Model;
/** /**
* @property string key * @property string key
* @property \User user * @property \User user

View File

@ -2,8 +2,6 @@
namespace BookStack; namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class EmailConfirmation extends Model class EmailConfirmation extends Model
{ {
protected $fillable = ['user_id', 'token']; protected $fillable = ['user_id', 'token'];

View File

@ -82,8 +82,7 @@ abstract class Entity extends Ownable
*/ */
public function hasActiveRestriction($role_id, $action) public function hasActiveRestriction($role_id, $action)
{ {
return $this->restricted && $this->restrictions() return $this->getRawAttribute('restricted') && $this->hasRestriction($role_id, $action);
->where('role_id', '=', $role_id)->where('action', '=', $action)->count() > 0;
} }
/** /**

View File

@ -1,8 +1,4 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class EntityPermission extends Model class EntityPermission extends Model
{ {

19
app/Model.php Normal file
View File

@ -0,0 +1,19 @@
<?php namespace BookStack;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Model extends EloquentModel
{
/**
* Provides public access to get the raw attribute value from the model.
* Used in areas where no mutations are required but performance is critical.
* @param $key
* @return mixed
*/
public function getRawAttribute($key)
{
return parent::getAttributeFromArray($key);
}
}

View File

@ -1,6 +1,5 @@
<?php namespace BookStack; <?php namespace BookStack;
use Illuminate\Database\Eloquent\Model;
abstract class Ownable extends Model abstract class Ownable extends Model
{ {

View File

@ -1,8 +1,5 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class Page extends Entity class Page extends Entity
{ {

View File

@ -1,6 +1,5 @@
<?php namespace BookStack; <?php namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class PageRevision extends Model class PageRevision extends Model
{ {

View File

@ -1,6 +1,5 @@
<?php namespace BookStack; <?php namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model class Permission extends Model
{ {

View File

@ -1,8 +1,5 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class Restriction extends Model class Restriction extends Model
{ {

View File

@ -1,8 +1,5 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class Role extends Model class Role extends Model
{ {
@ -36,11 +33,16 @@ class Role extends Model
/** /**
* Check if this role has a permission. * Check if this role has a permission.
* @param $permission * @param $permissionName
* @return bool
*/ */
public function hasPermission($permission) public function hasPermission($permissionName)
{ {
return $this->permissions->pluck('name')->contains($permission); $permissions = $this->getRelationValue('permissions');
foreach ($permissions as $permission) {
if ($permission->getRawAttribute('name') === $permissionName) return true;
}
return false;
} }
/** /**

View File

@ -54,21 +54,21 @@ class RestrictionService
$this->entityPermission->truncate(); $this->entityPermission->truncate();
// Get all roles (Should be the most limited dimension) // Get all roles (Should be the most limited dimension)
$roles = $this->role->load('permissions')->all(); $roles = $this->role->with('permissions')->get();
// Chunk through all books // Chunk through all books
$this->book->chunk(500, function ($books) use ($roles) { $this->book->with('restrictions')->chunk(500, function ($books) use ($roles) {
$this->createManyEntityPermissions($books, $roles); $this->createManyEntityPermissions($books, $roles);
}); });
// Chunk through all chapters // Chunk through all chapters
$this->chapter->with('book')->chunk(500, function ($books) use ($roles) { $this->chapter->with('book', 'restrictions')->chunk(500, function ($chapters) use ($roles) {
$this->createManyEntityPermissions($books, $roles); $this->createManyEntityPermissions($chapters, $roles);
}); });
// Chunk through all pages // Chunk through all pages
$this->page->with('book', 'chapter')->chunk(500, function ($books) use ($roles) { $this->page->with('book', 'chapter', 'restrictions')->chunk(500, function ($pages) use ($roles) {
$this->createManyEntityPermissions($books, $roles); $this->createManyEntityPermissions($pages, $roles);
}); });
} }
@ -78,7 +78,7 @@ class RestrictionService
*/ */
public function buildEntityPermissionsForEntity(Entity $entity) public function buildEntityPermissionsForEntity(Entity $entity)
{ {
$roles = $this->role->load('permissions')->all(); $roles = $this->role->with('permissions')->get();
$entities = collect([$entity]); $entities = collect([$entity]);
if ($entity->isA('book')) { if ($entity->isA('book')) {
@ -103,17 +103,17 @@ class RestrictionService
$this->deleteManyEntityPermissionsForRoles($roles); $this->deleteManyEntityPermissionsForRoles($roles);
// Chunk through all books // Chunk through all books
$this->book->chunk(500, function ($books) use ($roles) { $this->book->with('restrictions')->chunk(500, function ($books) use ($roles) {
$this->createManyEntityPermissions($books, $roles); $this->createManyEntityPermissions($books, $roles);
}); });
// Chunk through all chapters // Chunk through all chapters
$this->chapter->with('book')->chunk(500, function ($books) use ($roles) { $this->chapter->with('book', 'restrictions')->chunk(500, function ($books) use ($roles) {
$this->createManyEntityPermissions($books, $roles); $this->createManyEntityPermissions($books, $roles);
}); });
// Chunk through all pages // Chunk through all pages
$this->page->with('book', 'chapter')->chunk(500, function ($books) use ($roles) { $this->page->with('book', 'chapter', 'restrictions')->chunk(500, function ($books) use ($roles) {
$this->createManyEntityPermissions($books, $roles); $this->createManyEntityPermissions($books, $roles);
}); });
} }
@ -272,13 +272,13 @@ class RestrictionService
{ {
$entityClass = get_class($entity); $entityClass = get_class($entity);
return [ return [
'role_id' => $role->id, 'role_id' => $role->getRawAttribute('id'),
'entity_id' => $entity->id, 'entity_id' => $entity->getRawAttribute('id'),
'entity_type' => $entityClass, 'entity_type' => $entityClass,
'action' => $action, 'action' => $action,
'has_permission' => $permissionAll, 'has_permission' => $permissionAll,
'has_permission_own' => $permissionOwn, 'has_permission_own' => $permissionOwn,
'created_by' => $entity->created_by 'created_by' => $entity->getRawAttribute('created_by')
]; ];
} }

View File

@ -1,8 +1,4 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model class Setting extends Model
{ {

View File

@ -1,8 +1,5 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class SocialAccount extends Model class SocialAccount extends Model
{ {

View File

@ -1,9 +1,6 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

View File

@ -1,8 +1,4 @@
<?php <?php namespace BookStack;
namespace BookStack;
use Illuminate\Database\Eloquent\Model;
class View extends Model class View extends Model
{ {