Dan Brown

Updated permission bookChildrenQuery to use QueryBuilder

...@@ -318,15 +318,15 @@ class EntityRepo ...@@ -318,15 +318,15 @@ class EntityRepo
318 */ 318 */
319 public function getBookChildren(Book $book, $filterDrafts = false) 319 public function getBookChildren(Book $book, $filterDrafts = false)
320 { 320 {
321 - $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts); 321 + $q = $this->permissionService->bookChildrenQuery($book->id, $filterDrafts)->get();
322 $entities = []; 322 $entities = [];
323 $parents = []; 323 $parents = [];
324 $tree = []; 324 $tree = [];
325 325
326 foreach ($q as $index => $rawEntity) { 326 foreach ($q as $index => $rawEntity) {
327 - if ($rawEntity->entity_type === 'Bookstack\\Page') { 327 + if ($rawEntity->entity_type === 'BookStack\\Page') {
328 $entities[$index] = $this->page->newFromBuilder($rawEntity); 328 $entities[$index] = $this->page->newFromBuilder($rawEntity);
329 - } else if ($rawEntity->entity_type === 'Bookstack\\Chapter') { 329 + } else if ($rawEntity->entity_type === 'BookStack\\Chapter') {
330 $entities[$index] = $this->chapter->newFromBuilder($rawEntity); 330 $entities[$index] = $this->chapter->newFromBuilder($rawEntity);
331 $key = $entities[$index]->entity_type . ':' . $entities[$index]->id; 331 $key = $entities[$index]->entity_type . ':' . $entities[$index]->id;
332 $parents[$key] = $entities[$index]; 332 $parents[$key] = $entities[$index];
...@@ -338,7 +338,7 @@ class EntityRepo ...@@ -338,7 +338,7 @@ class EntityRepo
338 338
339 foreach ($entities as $entity) { 339 foreach ($entities as $entity) {
340 if ($entity->chapter_id === 0) continue; 340 if ($entity->chapter_id === 0) continue;
341 - $parentKey = 'Bookstack\\Chapter:' . $entity->chapter_id; 341 + $parentKey = 'BookStack\\Chapter:' . $entity->chapter_id;
342 $chapter = $parents[$parentKey]; 342 $chapter = $parents[$parentKey];
343 $chapter->pages->push($entity); 343 $chapter->pages->push($entity);
344 } 344 }
......
...@@ -470,49 +470,35 @@ class PermissionService ...@@ -470,49 +470,35 @@ class PermissionService
470 return $q; 470 return $q;
471 } 471 }
472 472
473 + /**
474 + * Get the children of a book in an efficient single query, Filtered by the permission system.
475 + * @param integer $book_id
476 + * @param bool $filterDrafts
477 + * @return \Illuminate\Database\Query\Builder
478 + */
473 public function bookChildrenQuery($book_id, $filterDrafts = false) { 479 public function bookChildrenQuery($book_id, $filterDrafts = false) {
474 - 480 + $pageSelect = $this->db->table('pages')->selectRaw("'BookStack\\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft")->where('book_id', '=', $book_id)->where(function($query) use ($filterDrafts) {
475 - // Draft setup 481 + $query->where('draft', '=', 0);
476 - $params = [ 482 + if (!$filterDrafts) {
477 - 'userId' => $this->currentUser()->id, 483 + $query->orWhere(function($query) {
478 - 'bookIdPage' => $book_id, 484 + $query->where('draft', '=', 1)->where('created_by', '=', $this->currentUser()->id);
479 - 'bookIdChapter' => $book_id 485 + });
480 - ]; 486 + }
481 - if (!$filterDrafts) { 487 + });
482 - $params['userIdDrafts'] = $this->currentUser()->id; 488 + $chapterSelect = $this->db->table('chapters')->selectRaw("'BookStack\\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft")->where('book_id', '=', $book_id);
483 - } 489 + $whereQuery = $this->db->table('joint_permissions as jp')->selectRaw('COUNT(*)')
484 - // Role setup 490 + ->whereRaw('jp.entity_id=U.id')->whereRaw('jp.entity_type=U.entity_type')
485 - $userRoles = $this->getRoles(); 491 + ->where('jp.action', '=', 'view')->whereIn('jp.role_id', $this->getRoles())
486 - $roleBindings = []; 492 + ->where(function($query) {
487 - $roleValues = []; 493 + $query->where('jp.has_permission', '=', 1)->orWhere(function($query) {
488 - foreach ($userRoles as $index => $roleId) { 494 + $query->where('jp.has_permission_own', '=', 1)->where('jp.created_by', '=', $this->currentUser()->id);
489 - $roleBindings[':role'.$index] = $roleId; 495 + });
490 - $roleValues['role'.$index] = $roleId; 496 + });
491 - } 497 + $query = $this->db->query()->select('*')->from($this->db->raw("({$pageSelect->toSql()} UNION {$chapterSelect->toSql()}) AS U"))
492 - // TODO - Clean this up, Maybe extract into a nice class for doing these kind of manual things 498 + ->mergeBindings($pageSelect)->mergeBindings($chapterSelect)
493 - // Something which will handle the above role crap in a nice clean way 499 + ->whereRaw("({$whereQuery->toSql()}) > 0")->mergeBindings($whereQuery)->orderBy('draft', 'desc')->orderBy('priority', 'asc');
494 - $roleBindingString = implode(',', array_keys($roleBindings));
495 - $query = "SELECT * from (
496 -(SELECT 'Bookstack\\\Page' as entity_type, id, slug, name, text, '' as description, book_id, priority, chapter_id, draft FROM {$this->page->getTable()}
497 - where book_id = :bookIdPage AND ". ($filterDrafts ? '(draft = 0)' : '(draft = 0 OR (draft = 1 AND created_by = :userIdDrafts))') .")
498 -UNION
499 -(SELECT 'Bookstack\\\Chapter' as entity_type, id, slug, name, '' as text, description, book_id, priority, 0 as chapter_id, 0 as draft FROM {$this->chapter->getTable()} WHERE book_id = :bookIdChapter)
500 -) as U WHERE (
501 - SELECT COUNT(*) FROM {$this->jointPermission->getTable()} jp
502 - WHERE
503 - jp.entity_id=U.id AND
504 - jp.entity_type=U.entity_type AND
505 - jp.action = 'view' AND
506 - jp.role_id IN ({$roleBindingString}) AND
507 - (
508 - jp.has_permission = 1 OR
509 - (jp.has_permission_own = 1 AND jp.created_by = :userId)
510 - )
511 -) > 0
512 -ORDER BY draft desc, priority asc";
513 -
514 $this->clean(); 500 $this->clean();
515 - return $this->db->select($query, array_replace($roleValues, $params)); 501 + return $query;
516 } 502 }
517 503
518 /** 504 /**
......