]> BookStack Code Mirror - bookstack/commitdiff
Abstracted userCanCreatePage helper to work for any permisison
authorDan Brown <redacted>
Sat, 9 Mar 2019 16:50:22 +0000 (16:50 +0000)
committerDan Brown <redacted>
Sat, 9 Mar 2019 16:50:22 +0000 (16:50 +0000)
- Added test to cover scenario where someone with create-own permission
would want to copy a viewable item into a container entity that they
own.

app/Auth/Permissions/PermissionService.php
app/helpers.php
resources/views/pages/show.blade.php
tests/Entity/SortTest.php

index b28f59cc5018b127eaf15365b20148761de791de..33d2149637b98b40bc568ee67b105af6fe896b20 100644 (file)
@@ -557,19 +557,17 @@ class PermissionService
     }
 
     /**
-     * Checks if a user has a book or chapter available to create a page
-     * @param Ownable $ownable
-     * @param $permission
+     * Checks if a user has the given permission for any items in the system.
+     * @param string $permission
      * @return bool
      */
-    public function checkAvailableCreatePageAccess()
+    public function checkUserHasPermissionOnAnything(string $permission)
     {
-        $userRoleIds = $this->currentUser()->roles()->pluck('id')->toArray();
+        $userRoleIds = $this->currentUser()->roles()->select('id')->pluck('id')->toArray();
         $userId = $this->currentUser()->id;
 
-
         $canCreatePage = $this->db->table('joint_permissions')
-            ->where('action', '=', 'page-create')
+            ->where('action', '=', $permission)
             ->whereIn('role_id', $userRoleIds)
             ->where(function ($query) use ($userId) {
                 $query->where('has_permission', '=', 1)
@@ -580,6 +578,7 @@ class PermissionService
             })
             ->get()->count() > 0;
 
+        $this->clean();
         return $canCreatePage;
     }
 
index 383e25c1594e8eac7e5b1b3f6cb2f8d3c3fa8c6e..0825a2e4aff87fde91afe6eaf0f67e65ffe2f587 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use BookStack\Auth\Permissions\PermissionService;
 use BookStack\Ownable;
 
 /**
@@ -50,30 +51,31 @@ function signedInUser()
  * Check if the current user has a permission.
  * If an ownable element is passed in the jointPermissions are checked against
  * that particular item.
- * @param $permission
+ * @param string $permission
  * @param Ownable $ownable
  * @return mixed
  */
-function userCan($permission, Ownable $ownable = null)
+function userCan(string $permission, Ownable $ownable = null)
 {
     if ($ownable === null) {
         return user() && user()->can($permission);
     }
 
     // Check permission on ownable item
-    $permissionService = app(\BookStack\Auth\Permissions\PermissionService::class);
+    $permissionService = app(PermissionService::class);
     return $permissionService->checkOwnableUserAccess($ownable, $permission);
 }
 
 /**
- * Check if the current user has the ability to create a page for an existing object
+ * Check if the current user has the given permission
+ * on any item in the system.
+ * @param string $permission
  * @return bool
  */
-function userCanCreatePage()
+function userCanOnAny(string $permission)
 {
-    // Check for create page permissions
-    $permissionService = app(\BookStack\Auth\Permissions\PermissionService::class);
-    return $permissionService->checkAvailableCreatePageAccess();
+    $permissionService = app(PermissionService::class);
+    return $permissionService->checkUserHasPermissionOnAnything($permission);
 }
 
 /**
index 6f221edee92b37be1fa361dd582cac883cfb148c..db2f1462e3d05bedbea27fef66c9677c5efc599c 100644 (file)
             @if(userCan('page-update', $page))
                 <a href="{{ $page->getUrl('/edit') }}" class="text-primary text-button" >@icon('edit'){{ trans('common.edit') }}</a>
             @endif
-            @if((userCan('page-view', $page) && userCanCreatePage()) || userCan('page-update', $page) || userCan('restrictions-manage', $page) || userCan('page-delete', $page))
+            @if((userCan('page-view', $page) && userCanOnAny('page-create')) || userCan('page-update', $page) || userCan('restrictions-manage', $page) || userCan('page-delete', $page))
                 <div dropdown class="dropdown-container">
                     <a dropdown-toggle class="text-primary text-button">@icon('more') {{ trans('common.more') }}</a>
                     <ul>
-                        @if(userCanCreatePage())
+                        @if(userCanOnAny('page-create'))
                             <li><a href="{{ $page->getUrl('/copy') }}" class="text-primary" >@icon('copy'){{ trans('common.copy') }}</a></li>
                         @endif
-                        @if(userCan('page-delete', $page) && userCan('page-update, $page))
+                        @if(userCan('page-delete', $page) && userCan('page-update', $page))
                             <li><a href="{{ $page->getUrl('/move') }}" class="text-primary" >@icon('folder'){{ trans('common.move') }}</a></li>
                         @endif
                         @if(userCan('page-update', $page))
index 11294f7dfdcd236dc7b0f6f8508650a09656a5e6..a3c20e84c5b517bede1e3b3488516a299c1e853a 100644 (file)
@@ -1,5 +1,6 @@
 <?php namespace Tests;
 
+use BookStack\Auth\Role;
 use BookStack\Entities\Book;
 use BookStack\Entities\Chapter;
 use BookStack\Entities\Page;
@@ -239,4 +240,35 @@ class SortTest extends TestCase
         $this->assertTrue($pageCopy->id !== $page->id, 'Page copy is not the same instance');
     }
 
+    public function test_page_can_be_copied_without_edit_permission()
+    {
+        $page = Page::first();
+        $currentBook = $page->book;
+        $newBook = Book::where('id', '!=', $currentBook->id)->first();
+        $viewer = $this->getViewer();
+
+        $resp = $this->actingAs($viewer)->get($page->getUrl());
+        $resp->assertDontSee($page->getUrl('/copy'));
+
+        $newBook->created_by = $viewer->id;
+        $newBook->save();
+        $this->giveUserPermissions($viewer, ['page-create-own']);
+        $this->regenEntityPermissions($newBook);
+
+        $resp = $this->actingAs($viewer)->get($page->getUrl());
+        $resp->assertSee($page->getUrl('/copy'));
+
+        $movePageResp = $this->post($page->getUrl('/copy'), [
+            'entity_selection' => 'book:' . $newBook->id,
+            'name' => 'My copied test page'
+        ]);
+        $movePageResp->assertRedirect();
+
+        $this->assertDatabaseHas('pages', [
+            'name' => 'My copied test page',
+            'created_by' => $viewer->id,
+            'book_id' => $newBook->id,
+        ]);
+    }
+
 }
\ No newline at end of file