Dan Brown

Improved permission regen performance by factor of 4

Worked around slower eloquent access to speed up permission generation.
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
2 2
3 namespace BookStack; 3 namespace BookStack;
4 4
5 -use Illuminate\Database\Eloquent\Model;
6 -
7 /** 5 /**
8 * @property string key 6 * @property string key
9 * @property \User user 7 * @property \User user
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
2 2
3 namespace BookStack; 3 namespace BookStack;
4 4
5 -use Illuminate\Database\Eloquent\Model;
6 -
7 class EmailConfirmation extends Model 5 class EmailConfirmation extends Model
8 { 6 {
9 protected $fillable = ['user_id', 'token']; 7 protected $fillable = ['user_id', 'token'];
......
...@@ -82,8 +82,7 @@ abstract class Entity extends Ownable ...@@ -82,8 +82,7 @@ abstract class Entity extends Ownable
82 */ 82 */
83 public function hasActiveRestriction($role_id, $action) 83 public function hasActiveRestriction($role_id, $action)
84 { 84 {
85 - return $this->restricted && $this->restrictions() 85 + return $this->getRawAttribute('restricted') && $this->hasRestriction($role_id, $action);
86 - ->where('role_id', '=', $role_id)->where('action', '=', $action)->count() > 0;
87 } 86 }
88 87
89 /** 88 /**
......
1 -<?php 1 +<?php namespace BookStack;
2 -
3 -namespace BookStack;
4 -
5 -use Illuminate\Database\Eloquent\Model;
6 2
7 class EntityPermission extends Model 3 class EntityPermission extends Model
8 { 4 {
......
1 +<?php namespace BookStack;
2 +
3 +use Illuminate\Database\Eloquent\Model as EloquentModel;
4 +
5 +class Model extends EloquentModel
6 +{
7 +
8 + /**
9 + * Provides public access to get the raw attribute value from the model.
10 + * Used in areas where no mutations are required but performance is critical.
11 + * @param $key
12 + * @return mixed
13 + */
14 + public function getRawAttribute($key)
15 + {
16 + return parent::getAttributeFromArray($key);
17 + }
18 +
19 +}
...\ No newline at end of file ...\ No newline at end of file
1 <?php namespace BookStack; 1 <?php namespace BookStack;
2 2
3 -use Illuminate\Database\Eloquent\Model;
4 3
5 abstract class Ownable extends Model 4 abstract class Ownable extends Model
6 { 5 {
......
1 -<?php 1 +<?php namespace BookStack;
2 2
3 -namespace BookStack;
4 -
5 -use Illuminate\Database\Eloquent\Model;
6 3
7 class Page extends Entity 4 class Page extends Entity
8 { 5 {
......
1 <?php namespace BookStack; 1 <?php namespace BookStack;
2 2
3 -use Illuminate\Database\Eloquent\Model;
4 3
5 class PageRevision extends Model 4 class PageRevision extends Model
6 { 5 {
......
1 <?php namespace BookStack; 1 <?php namespace BookStack;
2 2
3 -use Illuminate\Database\Eloquent\Model;
4 3
5 class Permission extends Model 4 class Permission extends Model
6 { 5 {
......
1 -<?php 1 +<?php namespace BookStack;
2 2
3 -namespace BookStack;
4 -
5 -use Illuminate\Database\Eloquent\Model;
6 3
7 class Restriction extends Model 4 class Restriction extends Model
8 { 5 {
......
1 -<?php 1 +<?php namespace BookStack;
2 2
3 -namespace BookStack;
4 -
5 -use Illuminate\Database\Eloquent\Model;
6 3
7 class Role extends Model 4 class Role extends Model
8 { 5 {
...@@ -36,11 +33,16 @@ class Role extends Model ...@@ -36,11 +33,16 @@ class Role extends Model
36 33
37 /** 34 /**
38 * Check if this role has a permission. 35 * Check if this role has a permission.
39 - * @param $permission 36 + * @param $permissionName
37 + * @return bool
40 */ 38 */
41 - public function hasPermission($permission) 39 + public function hasPermission($permissionName)
42 { 40 {
43 - return $this->permissions->pluck('name')->contains($permission); 41 + $permissions = $this->getRelationValue('permissions');
42 + foreach ($permissions as $permission) {
43 + if ($permission->getRawAttribute('name') === $permissionName) return true;
44 + }
45 + return false;
44 } 46 }
45 47
46 /** 48 /**
......
...@@ -54,21 +54,21 @@ class RestrictionService ...@@ -54,21 +54,21 @@ class RestrictionService
54 $this->entityPermission->truncate(); 54 $this->entityPermission->truncate();
55 55
56 // Get all roles (Should be the most limited dimension) 56 // Get all roles (Should be the most limited dimension)
57 - $roles = $this->role->load('permissions')->all(); 57 + $roles = $this->role->with('permissions')->get();
58 58
59 // Chunk through all books 59 // Chunk through all books
60 - $this->book->chunk(500, function ($books) use ($roles) { 60 + $this->book->with('restrictions')->chunk(500, function ($books) use ($roles) {
61 $this->createManyEntityPermissions($books, $roles); 61 $this->createManyEntityPermissions($books, $roles);
62 }); 62 });
63 63
64 // Chunk through all chapters 64 // Chunk through all chapters
65 - $this->chapter->with('book')->chunk(500, function ($books) use ($roles) { 65 + $this->chapter->with('book', 'restrictions')->chunk(500, function ($chapters) use ($roles) {
66 - $this->createManyEntityPermissions($books, $roles); 66 + $this->createManyEntityPermissions($chapters, $roles);
67 }); 67 });
68 68
69 // Chunk through all pages 69 // Chunk through all pages
70 - $this->page->with('book', 'chapter')->chunk(500, function ($books) use ($roles) { 70 + $this->page->with('book', 'chapter', 'restrictions')->chunk(500, function ($pages) use ($roles) {
71 - $this->createManyEntityPermissions($books, $roles); 71 + $this->createManyEntityPermissions($pages, $roles);
72 }); 72 });
73 } 73 }
74 74
...@@ -78,7 +78,7 @@ class RestrictionService ...@@ -78,7 +78,7 @@ class RestrictionService
78 */ 78 */
79 public function buildEntityPermissionsForEntity(Entity $entity) 79 public function buildEntityPermissionsForEntity(Entity $entity)
80 { 80 {
81 - $roles = $this->role->load('permissions')->all(); 81 + $roles = $this->role->with('permissions')->get();
82 $entities = collect([$entity]); 82 $entities = collect([$entity]);
83 83
84 if ($entity->isA('book')) { 84 if ($entity->isA('book')) {
...@@ -103,17 +103,17 @@ class RestrictionService ...@@ -103,17 +103,17 @@ class RestrictionService
103 $this->deleteManyEntityPermissionsForRoles($roles); 103 $this->deleteManyEntityPermissionsForRoles($roles);
104 104
105 // Chunk through all books 105 // Chunk through all books
106 - $this->book->chunk(500, function ($books) use ($roles) { 106 + $this->book->with('restrictions')->chunk(500, function ($books) use ($roles) {
107 $this->createManyEntityPermissions($books, $roles); 107 $this->createManyEntityPermissions($books, $roles);
108 }); 108 });
109 109
110 // Chunk through all chapters 110 // Chunk through all chapters
111 - $this->chapter->with('book')->chunk(500, function ($books) use ($roles) { 111 + $this->chapter->with('book', 'restrictions')->chunk(500, function ($books) use ($roles) {
112 $this->createManyEntityPermissions($books, $roles); 112 $this->createManyEntityPermissions($books, $roles);
113 }); 113 });
114 114
115 // Chunk through all pages 115 // Chunk through all pages
116 - $this->page->with('book', 'chapter')->chunk(500, function ($books) use ($roles) { 116 + $this->page->with('book', 'chapter', 'restrictions')->chunk(500, function ($books) use ($roles) {
117 $this->createManyEntityPermissions($books, $roles); 117 $this->createManyEntityPermissions($books, $roles);
118 }); 118 });
119 } 119 }
...@@ -272,13 +272,13 @@ class RestrictionService ...@@ -272,13 +272,13 @@ class RestrictionService
272 { 272 {
273 $entityClass = get_class($entity); 273 $entityClass = get_class($entity);
274 return [ 274 return [
275 - 'role_id' => $role->id, 275 + 'role_id' => $role->getRawAttribute('id'),
276 - 'entity_id' => $entity->id, 276 + 'entity_id' => $entity->getRawAttribute('id'),
277 'entity_type' => $entityClass, 277 'entity_type' => $entityClass,
278 'action' => $action, 278 'action' => $action,
279 'has_permission' => $permissionAll, 279 'has_permission' => $permissionAll,
280 'has_permission_own' => $permissionOwn, 280 'has_permission_own' => $permissionOwn,
281 - 'created_by' => $entity->created_by 281 + 'created_by' => $entity->getRawAttribute('created_by')
282 ]; 282 ];
283 } 283 }
284 284
......
1 -<?php 1 +<?php namespace BookStack;
2 -
3 -namespace BookStack;
4 -
5 -use Illuminate\Database\Eloquent\Model;
6 2
7 class Setting extends Model 3 class Setting extends Model
8 { 4 {
......
1 -<?php 1 +<?php namespace BookStack;
2 2
3 -namespace BookStack;
4 -
5 -use Illuminate\Database\Eloquent\Model;
6 3
7 class SocialAccount extends Model 4 class SocialAccount extends Model
8 { 5 {
......
1 -<?php 1 +<?php namespace BookStack;
2 -
3 -namespace BookStack;
4 2
5 use Illuminate\Auth\Authenticatable; 3 use Illuminate\Auth\Authenticatable;
6 -use Illuminate\Database\Eloquent\Model;
7 use Illuminate\Auth\Passwords\CanResetPassword; 4 use Illuminate\Auth\Passwords\CanResetPassword;
8 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; 5 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
9 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; 6 use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
......
1 -<?php 1 +<?php namespace BookStack;
2 -
3 -namespace BookStack;
4 -
5 -use Illuminate\Database\Eloquent\Model;
6 2
7 class View extends Model 3 class View extends Model
8 { 4 {
......