]> BookStack Code Mirror - bookstack/commitdiff
Implemented database structure and inital interfaces for entity restrictions
authorDan Brown <redacted>
Sun, 28 Feb 2016 10:49:41 +0000 (10:49 +0000)
committerDan Brown <redacted>
Sun, 28 Feb 2016 10:49:41 +0000 (10:49 +0000)
22 files changed:
app/Entity.php
app/Http/Controllers/BookController.php
app/Http/Controllers/ChapterController.php
app/Http/Controllers/PageController.php
app/Http/routes.php
app/Repos/BookRepo.php
app/Repos/ChapterRepo.php
app/Repos/PageRepo.php
app/Repos/UserRepo.php
app/Restriction.php [new file with mode: 0644]
database/migrations/2016_02_27_120329_update_permissions_and_roles.php
database/migrations/2016_02_28_084200_add_entity_access_controls.php [new file with mode: 0644]
resources/views/books/restrictions.blade.php [new file with mode: 0644]
resources/views/books/show.blade.php
resources/views/chapters/restrictions.blade.php [new file with mode: 0644]
resources/views/chapters/show.blade.php
resources/views/form/checkbox.blade.php [new file with mode: 0644]
resources/views/form/restriction-checkbox.blade.php [new file with mode: 0644]
resources/views/form/restriction-form.blade.php [new file with mode: 0644]
resources/views/pages/restrictions.blade.php [new file with mode: 0644]
resources/views/pages/show.blade.php
resources/views/settings/roles/form.blade.php

index 08aa14638a4bdbe9272584ca6ca2e4fa37ac6097..97500917419cd82bd730b0f9859bfc309bb99be6 100644 (file)
@@ -48,13 +48,31 @@ abstract class Entity extends Ownable
 
     /**
      * Get View objects for this entity.
-     * @return mixed
      */
     public function views()
     {
         return $this->morphMany('BookStack\View', 'viewable');
     }
 
+    /**
+     * Get this entities restrictions.
+     */
+    public function restrictions()
+    {
+        return $this->morphMany('BookStack\Restriction', 'restrictable');
+    }
+
+    /**
+     * Check if this entity has a specific restriction set against it.
+     * @param $role_id
+     * @param $action
+     * @return bool
+     */
+    public function hasRestriction($role_id, $action)
+    {
+        return $this->restrictions->where('role_id', $role_id)->where('action', $action)->count() > 0;
+    }
+
     /**
      * Allows checking of the exact class, Used to check entity type.
      * Cleaner method for is_a.
index c1320088dc68efa9e57ad4f8bb41da907f4b7fdb..5b2b510c9ce279ba80728c8584b0ffbf97a6907a 100644 (file)
@@ -3,6 +3,7 @@
 namespace BookStack\Http\Controllers;
 
 use Activity;
+use BookStack\Repos\UserRepo;
 use Illuminate\Http\Request;
 
 use Illuminate\Support\Facades\Auth;
@@ -19,18 +20,21 @@ class BookController extends Controller
     protected $bookRepo;
     protected $pageRepo;
     protected $chapterRepo;
+    protected $userRepo;
 
     /**
      * BookController constructor.
      * @param BookRepo $bookRepo
      * @param PageRepo $pageRepo
      * @param ChapterRepo $chapterRepo
+     * @param UserRepo $userRepo
      */
-    public function __construct(BookRepo $bookRepo, PageRepo $pageRepo, ChapterRepo $chapterRepo)
+    public function __construct(BookRepo $bookRepo, PageRepo $pageRepo, ChapterRepo $chapterRepo, UserRepo $userRepo)
     {
         $this->bookRepo = $bookRepo;
         $this->pageRepo = $pageRepo;
         $this->chapterRepo = $chapterRepo;
+        $this->userRepo = $userRepo;
         parent::__construct();
     }
 
@@ -177,7 +181,6 @@ class BookController extends Controller
 
     /**
      * Saves an array of sort mapping to pages and chapters.
-     *
      * @param  string $bookSlug
      * @param Request $request
      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
@@ -223,7 +226,6 @@ class BookController extends Controller
 
     /**
      * Remove the specified book from storage.
-     *
      * @param $bookSlug
      * @return Response
      */
@@ -236,4 +238,36 @@ class BookController extends Controller
         $this->bookRepo->destroyBySlug($bookSlug);
         return redirect('/books');
     }
+
+    /**
+     * Show the Restrictions view.
+     * @param $bookSlug
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function showRestrict($bookSlug)
+    {
+        $book = $this->bookRepo->getBySlug($bookSlug);
+        $this->checkOwnablePermission('restrictions-manage', $book);
+        $roles = $this->userRepo->getRestrictableRoles();
+        return view('books/restrictions', [
+            'book' => $book,
+            'roles' => $roles
+        ]);
+    }
+
+    /**
+     * Set the restrictions for this book.
+     * @param $bookSlug
+     * @param $bookSlug
+     * @param Request $request
+     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     */
+    public function restrict($bookSlug, Request $request)
+    {
+        $book = $this->bookRepo->getBySlug($bookSlug);
+        $this->checkOwnablePermission('restrictions-manage', $book);
+        $this->bookRepo->updateRestrictionsFromRequest($request, $book);
+        session()->flash('success', 'Page Restrictions Updated');
+        return redirect($book->getUrl());
+    }
 }
index 3b4780f8dfa1204fdb4178f2204b81cf8e1fee64..2ad08c7da6b979332fc7260640fccc6cf337b54f 100644 (file)
@@ -1,6 +1,7 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Activity;
+use BookStack\Repos\UserRepo;
 use Illuminate\Http\Request;
 use BookStack\Http\Requests;
 use BookStack\Repos\BookRepo;
@@ -12,16 +13,19 @@ class ChapterController extends Controller
 
     protected $bookRepo;
     protected $chapterRepo;
+    protected $userRepo;
 
     /**
      * ChapterController constructor.
-     * @param $bookRepo
-     * @param $chapterRepo
+     * @param BookRepo $bookRepo
+     * @param ChapterRepo $chapterRepo
+     * @param UserRepo $userRepo
      */
-    public function __construct(BookRepo $bookRepo, ChapterRepo $chapterRepo)
+    public function __construct(BookRepo $bookRepo, ChapterRepo $chapterRepo, UserRepo $userRepo)
     {
         $this->bookRepo = $bookRepo;
         $this->chapterRepo = $chapterRepo;
+        $this->userRepo = $userRepo;
         parent::__construct();
     }
 
@@ -144,4 +148,39 @@ class ChapterController extends Controller
         $this->chapterRepo->destroy($chapter);
         return redirect($book->getUrl());
     }
+
+    /**
+     * Show the Restrictions view.
+     * @param $bookSlug
+     * @param $chapterSlug
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function showRestrict($bookSlug, $chapterSlug)
+    {
+        $book = $this->bookRepo->getBySlug($bookSlug);
+        $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
+        $this->checkOwnablePermission('restrictions-manage', $chapter);
+        $roles = $this->userRepo->getRestrictableRoles();
+        return view('chapters/restrictions', [
+            'chapter' => $chapter,
+            'roles' => $roles
+        ]);
+    }
+
+    /**
+     * Set the restrictions for this chapter.
+     * @param $bookSlug
+     * @param $chapterSlug
+     * @param Request $request
+     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     */
+    public function restrict($bookSlug, $chapterSlug, Request $request)
+    {
+        $book = $this->bookRepo->getBySlug($bookSlug);
+        $chapter = $this->chapterRepo->getBySlug($chapterSlug, $book->id);
+        $this->checkOwnablePermission('restrictions-manage', $chapter);
+        $this->chapterRepo->updateRestrictionsFromRequest($request, $chapter);
+        session()->flash('success', 'Page Restrictions Updated');
+        return redirect($chapter->getUrl());
+    }
 }
index ac968159bd780280aaf882e11e58487cb860728d..b469f51ddccfce7d2f61d51cbe4aae006509cc09 100644 (file)
@@ -1,6 +1,7 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Activity;
+use BookStack\Repos\UserRepo;
 use BookStack\Services\ExportService;
 use Illuminate\Http\Request;
 use BookStack\Http\Requests;
@@ -17,20 +18,23 @@ class PageController extends Controller
     protected $bookRepo;
     protected $chapterRepo;
     protected $exportService;
+    protected $userRepo;
 
     /**
      * PageController constructor.
-     * @param PageRepo      $pageRepo
-     * @param BookRepo      $bookRepo
-     * @param ChapterRepo   $chapterRepo
+     * @param PageRepo $pageRepo
+     * @param BookRepo $bookRepo
+     * @param ChapterRepo $chapterRepo
      * @param ExportService $exportService
+     * @param UserRepo $userRepo
      */
-    public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ExportService $exportService)
+    public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ExportService $exportService, UserRepo $userRepo)
     {
         $this->pageRepo = $pageRepo;
         $this->bookRepo = $bookRepo;
         $this->chapterRepo = $chapterRepo;
         $this->exportService = $exportService;
+        $this->userRepo = $userRepo;
         parent::__construct();
     }
 
@@ -308,4 +312,39 @@ class PageController extends Controller
         ]);
     }
 
+    /**
+     * Show the Restrictions view.
+     * @param $bookSlug
+     * @param $pageSlug
+     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
+     */
+    public function showRestrict($bookSlug, $pageSlug)
+    {
+        $book = $this->bookRepo->getBySlug($bookSlug);
+        $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
+        $this->checkOwnablePermission('restrictions-manage', $page);
+        $roles = $this->userRepo->getRestrictableRoles();
+        return view('pages/restrictions', [
+            'page' => $page,
+            'roles' => $roles
+        ]);
+    }
+
+    /**
+     * Set the restrictions for this page.
+     * @param $bookSlug
+     * @param $pageSlug
+     * @param Request $request
+     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     */
+    public function restrict($bookSlug, $pageSlug, Request $request)
+    {
+        $book = $this->bookRepo->getBySlug($bookSlug);
+        $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
+        $this->checkOwnablePermission('restrictions-manage', $page);
+        $this->pageRepo->updateRestrictionsFromRequest($request, $page);
+        session()->flash('success', 'Page Restrictions Updated');
+        return redirect($page->getUrl());
+    }
+
 }
index a1c73764246373be546f0af0c40625a495727de9..81bbb16bc0f2bfad7f4c8a402d7773b2b2d88525 100644 (file)
@@ -19,6 +19,8 @@ Route::group(['middleware' => 'auth'], function () {
         Route::delete('/{id}', 'BookController@destroy');
         Route::get('/{slug}/sort-item', 'BookController@getSortItem');
         Route::get('/{slug}', 'BookController@show');
+        Route::get('/{bookSlug}/restrict', 'BookController@showRestrict');
+        Route::put('/{bookSlug}/restrict', 'BookController@restrict');
         Route::get('/{slug}/delete', 'BookController@showDelete');
         Route::get('/{bookSlug}/sort', 'BookController@sort');
         Route::put('/{bookSlug}/sort', 'BookController@saveSort');
@@ -32,6 +34,8 @@ Route::group(['middleware' => 'auth'], function () {
         Route::get('/{bookSlug}/page/{pageSlug}/export/plaintext', 'PageController@exportPlainText');
         Route::get('/{bookSlug}/page/{pageSlug}/edit', 'PageController@edit');
         Route::get('/{bookSlug}/page/{pageSlug}/delete', 'PageController@showDelete');
+        Route::get('/{bookSlug}/page/{pageSlug}/restrict', 'PageController@showRestrict');
+        Route::put('/{bookSlug}/page/{pageSlug}/restrict', 'PageController@restrict');
         Route::put('/{bookSlug}/page/{pageSlug}', 'PageController@update');
         Route::delete('/{bookSlug}/page/{pageSlug}', 'PageController@destroy');
 
@@ -47,6 +51,8 @@ Route::group(['middleware' => 'auth'], function () {
         Route::get('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@show');
         Route::put('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@update');
         Route::get('/{bookSlug}/chapter/{chapterSlug}/edit', 'ChapterController@edit');
+        Route::get('/{bookSlug}/chapter/{chapterSlug}/restrict', 'ChapterController@showRestrict');
+        Route::put('/{bookSlug}/chapter/{chapterSlug}/restrict', 'ChapterController@restrict');
         Route::get('/{bookSlug}/chapter/{chapterSlug}/delete', 'ChapterController@showDelete');
         Route::delete('/{bookSlug}/chapter/{chapterSlug}', 'ChapterController@destroy');
 
index d8a24c099734d6a24a757130d842fc14e7445c05..dbf95623edc0016968b3fd34d04b2851b6b0a17b 100644 (file)
@@ -238,4 +238,27 @@ class BookRepo
         return $books;
     }
 
+    /**
+     * Updates books restrictions from a request
+     * @param $request
+     * @param $book
+     */
+    public function updateRestrictionsFromRequest($request, $book)
+    {
+        // TODO - extract into shared repo
+        $book->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
+        $book->restrictions()->delete();
+        if ($request->has('restrictions')) {
+            foreach($request->get('restrictions') as $roleId => $restrictions) {
+                foreach ($restrictions as $action => $value) {
+                    $book->restrictions()->create([
+                        'role_id' => $roleId,
+                        'action'  => strtolower($action)
+                    ]);
+                }
+            }
+        }
+        $book->save();
+    }
+
 }
\ No newline at end of file
index bba6cbe7a134c6ac66843376bda7f279f89b46c6..7e3560f2b2a6090386761b71e26c8ee39eb8419d 100644 (file)
@@ -161,4 +161,27 @@ class ChapterRepo
         return $chapter;
     }
 
+    /**
+     * Updates pages restrictions from a request
+     * @param $request
+     * @param $chapter
+     */
+    public function updateRestrictionsFromRequest($request, $chapter)
+    {
+        // TODO - extract into shared repo
+        $chapter->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
+        $chapter->restrictions()->delete();
+        if ($request->has('restrictions')) {
+            foreach($request->get('restrictions') as $roleId => $restrictions) {
+                foreach ($restrictions as $action => $value) {
+                    $chapter->restrictions()->create([
+                        'role_id' => $roleId,
+                        'action'  => strtolower($action)
+                    ]);
+                }
+            }
+        }
+        $chapter->save();
+    }
+
 }
\ No newline at end of file
index f028a1fccfa642890a9fc1f9aa4e8aec73cdd0c6..1a98255abe934d50940c34153ec9973cf1a71220 100644 (file)
@@ -407,4 +407,27 @@ class PageRepo
         return $this->page->orderBy('updated_at', 'desc')->paginate($count);
     }
 
+    /**
+     * Updates pages restrictions from a request
+     * @param $request
+     * @param $page
+     */
+    public function updateRestrictionsFromRequest($request, $page)
+    {
+        // TODO - extract into shared repo
+        $page->restricted = $request->has('restricted') && $request->get('restricted') === 'true';
+        $page->restrictions()->delete();
+        if ($request->has('restrictions')) {
+            foreach($request->get('restrictions') as $roleId => $restrictions) {
+                foreach ($restrictions as $action => $value) {
+                    $page->restrictions()->create([
+                        'role_id' => $roleId,
+                        'action'  => strtolower($action)
+                    ]);
+                }
+            }
+        }
+        $page->save();
+    }
+
 }
index 15813b3e18b4e204d4a6e45e84cab56477754f7b..01cf80d29fcf0322f7847516130d2d9d87798bbe 100644 (file)
@@ -164,4 +164,14 @@ class UserRepo
         ];
     }
 
+    /**
+     * Get all the roles which can be given restricted access to
+     * other entities in the system.
+     * @return mixed
+     */
+    public function getRestrictableRoles()
+    {
+        return $this->role->where('name', '!=', 'admin')->get();
+    }
+
 }
\ No newline at end of file
diff --git a/app/Restriction.php b/app/Restriction.php
new file mode 100644 (file)
index 0000000..58d1179
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+
+namespace BookStack;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Restriction extends Model
+{
+
+    protected $fillable = ['role_id', 'action'];
+    public $timestamps = false;
+
+    /**
+     * Get all this restriction's attached entity.
+     * @return \Illuminate\Database\Eloquent\Relations\MorphTo
+     */
+    public function restrictable()
+    {
+        return $this->morphTo();
+    }
+}
index 9fb2e98f25ceac6d23629490ebadb485c7749ad6..ea3735d9eb6e767fa1cf8858ed53bbff15cd1852 100644 (file)
@@ -26,7 +26,9 @@ class UpdatePermissionsAndRoles extends Migration
         $permissionsToCreate = [
             'settings-manage' => 'Manage Settings',
             'users-manage' => 'Manage Users',
-            'user-roles-manage' => 'Manage Roles & Permissions'
+            'user-roles-manage' => 'Manage Roles & Permissions',
+            'restrictions-manage-all' => 'Manage All Entity Restrictions',
+            'restrictions-manage-own' => 'Manage Entity Restrictions On Own Content'
         ];
         foreach ($permissionsToCreate as $name => $displayName) {
             $newPermission = new \BookStack\Permission();
diff --git a/database/migrations/2016_02_28_084200_add_entity_access_controls.php b/database/migrations/2016_02_28_084200_add_entity_access_controls.php
new file mode 100644 (file)
index 0000000..5df2353
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddEntityAccessControls extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('images', function (Blueprint $table) {
+            $table->integer('uploaded_to')->default(0);
+            $table->index('uploaded_to');
+        });
+
+        Schema::table('books', function (Blueprint $table) {
+            $table->boolean('restricted')->default(false);
+            $table->index('restricted');
+        });
+
+        Schema::table('chapters', function (Blueprint $table) {
+            $table->boolean('restricted')->default(false);
+            $table->index('restricted');
+        });
+
+        Schema::table('pages', function (Blueprint $table) {
+            $table->boolean('restricted')->default(false);
+            $table->index('restricted');
+        });
+
+        Schema::create('restrictions', function(Blueprint $table) {
+            $table->increments('id');
+            $table->integer('restrictable_id');
+            $table->string('restrictable_type');
+            $table->integer('role_id');
+            $table->string('action');
+            $table->index('role_id');
+            $table->index('action');
+            $table->index(['restrictable_id', 'restrictable_type']);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('images', function (Blueprint $table) {
+            $table->dropColumn('uploaded_to');
+        });
+
+        Schema::table('books', function (Blueprint $table) {
+            $table->dropColumn('restricted');
+        });
+
+        Schema::table('chapters', function (Blueprint $table) {
+            $table->dropColumn('restricted');
+        });
+
+
+        Schema::table('pages', function (Blueprint $table) {
+            $table->dropColumn('restricted');
+        });
+
+        Schema::drop('restrictions');
+    }
+}
diff --git a/resources/views/books/restrictions.blade.php b/resources/views/books/restrictions.blade.php
new file mode 100644 (file)
index 0000000..826f218
--- /dev/null
@@ -0,0 +1,10 @@
+@extends('base')
+
+@section('content')
+
+    <div class="container" ng-non-bindable>
+        <h1>Book Restrictions</h1>
+        @include('form/restriction-form', ['model' => $book])
+    </div>
+
+@stop
index 12ebae0d6b820484805c081101ac746698454fca..f8a22ada846f343a77440839d76480347e66e7f5 100644 (file)
@@ -17,6 +17,9 @@
                             <a href="{{$book->getEditUrl()}}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>Edit</a>
                             <a href="{{ $book->getUrl() }}/sort" class="text-primary text-button"><i class="zmdi zmdi-sort"></i>Sort</a>
                         @endif
+                        @if(userCan('restrictions-manage', $book))
+                            <a href="{{$book->getUrl()}}/restrict" class="text-primary text-button"><i class="zmdi zmdi-lock-outline"></i>Restrict</a>
+                        @endif
                         @if(userCan('book-delete', $book))
                             <a href="{{ $book->getUrl() }}/delete" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a>
                         @endif
diff --git a/resources/views/chapters/restrictions.blade.php b/resources/views/chapters/restrictions.blade.php
new file mode 100644 (file)
index 0000000..3b19b55
--- /dev/null
@@ -0,0 +1,10 @@
+@extends('base')
+
+@section('content')
+
+    <div class="container" ng-non-bindable>
+        <h1>Chapter Restrictions</h1>
+        @include('form/restriction-form', ['model' => $chapter])
+    </div>
+
+@stop
index 18a115ea5c3c03755304049aa1bee0bbf6ae3901..ac36a6b3ee6d3a04d5b3faa34b15df61d6974e53 100644 (file)
@@ -18,6 +18,9 @@
                         @if(userCan('chapter-update', $chapter))
                             <a href="{{$chapter->getUrl() . '/edit'}}" class="text-primary text-button"><i class="zmdi zmdi-edit"></i>Edit</a>
                         @endif
+                        @if(userCan('restrictions-manage', $chapter))
+                            <a href="{{$chapter->getUrl()}}/restrict" class="text-primary text-button"><i class="zmdi zmdi-lock-outline"></i>Restrict</a>
+                        @endif
                         @if(userCan('chapter-delete', $chapter))
                             <a href="{{$chapter->getUrl() . '/delete'}}" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a>
                         @endif
diff --git a/resources/views/form/checkbox.blade.php b/resources/views/form/checkbox.blade.php
new file mode 100644 (file)
index 0000000..2558969
--- /dev/null
@@ -0,0 +1,12 @@
+
+<label>
+    <input value="true" id="{{$name}}" type="checkbox" name="{{$name}}"
+           @if($errors->has($name)) class="neg" @endif
+           @if(old($name) || (!old() && isset($model) && $model->$name)) checked="checked" @endif
+    >
+    {{ $label }}
+</label>
+
+@if($errors->has($name))
+    <div class="text-neg text-small">{{ $errors->first($name) }}</div>
+@endif
\ No newline at end of file
diff --git a/resources/views/form/restriction-checkbox.blade.php b/resources/views/form/restriction-checkbox.blade.php
new file mode 100644 (file)
index 0000000..a4449cc
--- /dev/null
@@ -0,0 +1,7 @@
+
+<label>
+    <input value="true" id="{{$name}}[{{$role->id}}][{{$action}}]" type="checkbox" name="{{$name}}[{{$role->id}}][{{$action}}]"
+           @if(old($name .'.'.$role->id.'.'.$action) || (!old() && isset($model) && $model->hasRestriction($role->id, $action))) checked="checked" @endif
+    >
+    {{ $label }}
+</label>
\ No newline at end of file
diff --git a/resources/views/form/restriction-form.blade.php b/resources/views/form/restriction-form.blade.php
new file mode 100644 (file)
index 0000000..cb42497
--- /dev/null
@@ -0,0 +1,28 @@
+<form action="{{ $model->getUrl() }}/restrict" method="POST">
+    {!! csrf_field() !!}
+    <input type="hidden" name="_method" value="PUT">
+
+    <div class="form-group">
+        @include('form/checkbox', ['name' => 'restricted', 'label' => 'Restrict this page?'])
+    </div>
+
+    <table class="table">
+        <tr>
+            <th>Role</th>
+            <th @if($model->isA('page')) colspan="3" @else colspan="4" @endif>Actions</th>
+        </tr>
+        @foreach($roles as $role)
+            <tr>
+                <td>{{ $role->display_name }}</td>
+                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'View', 'action' => 'view'])</td>
+                @if(!$model->isA('page'))
+                    <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'Create', 'action' => 'create'])</td>
+                @endif
+                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'Update', 'action' => 'update'])</td>
+                <td>@include('form/restriction-checkbox', ['name'=>'restrictions', 'label' => 'Delete', 'action' => 'delete'])</td>
+            </tr>
+        @endforeach
+    </table>
+
+    <button type="submit" class="button pos">Save Restrictions</button>
+</form>
\ No newline at end of file
diff --git a/resources/views/pages/restrictions.blade.php b/resources/views/pages/restrictions.blade.php
new file mode 100644 (file)
index 0000000..63ad1fa
--- /dev/null
@@ -0,0 +1,10 @@
+@extends('base')
+
+@section('content')
+
+    <div class="container" ng-non-bindable>
+        <h1>Page Restrictions</h1>
+        @include('form/restriction-form', ['model' => $page])
+    </div>
+
+@stop
index 52b9daee67e974821da43fd4ae63f0279fbf42eb..f84d1963dd561474dc567d7c500aab2a47bbf136 100644 (file)
                         <span dropdown class="dropdown-container">
                             <div dropdown-toggle class="text-button text-primary"><i class="zmdi zmdi-open-in-new"></i>Export</div>
                             <ul class="wide">
-                                <li><a href="{{$page->getUrl() . '/export/html'}}" target="_blank">Contained Web File <span class="text-muted float right">.html</span></a></li>
-                                <li><a href="{{$page->getUrl() . '/export/pdf'}}" target="_blank">PDF File <span class="text-muted float right">.pdf</span></a></li>
-                                <li><a href="{{$page->getUrl() . '/export/plaintext'}}" target="_blank">Plain Text File <span class="text-muted float right">.txt</span></a></li>
+                                <li><a href="{{$page->getUrl()}}/export/html" target="_blank">Contained Web File <span class="text-muted float right">.html</span></a></li>
+                                <li><a href="{{$page->getUrl()}}/export/pdf" target="_blank">PDF File <span class="text-muted float right">.pdf</span></a></li>
+                                <li><a href="{{$page->getUrl()}}/export/plaintext" target="_blank">Plain Text File <span class="text-muted float right">.txt</span></a></li>
                             </ul>
                         </span>
                         @if(userCan('page-update', $page))
-                            <a href="{{$page->getUrl() . '/revisions'}}" class="text-primary text-button"><i class="zmdi zmdi-replay"></i>Revisions</a>
-                            <a href="{{$page->getUrl() . '/edit'}}" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a>
+                            <a href="{{$page->getUrl()}}/revisions" class="text-primary text-button"><i class="zmdi zmdi-replay"></i>Revisions</a>
+                            <a href="{{$page->getUrl()}}/edit" class="text-primary text-button" ><i class="zmdi zmdi-edit"></i>Edit</a>
+                        @endif
+                        @if(userCan('restrictions-manage', $page))
+                            <a href="{{$page->getUrl()}}/restrict" class="text-primary text-button"><i class="zmdi zmdi-lock-outline"></i>Restrict</a>
                         @endif
                         @if(userCan('page-delete', $page))
-                            <a href="{{$page->getUrl() . '/delete'}}" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a>
+                            <a href="{{$page->getUrl()}}/delete" class="text-neg text-button"><i class="zmdi zmdi-delete"></i>Delete</a>
                         @endif
                     </div>
                 </div>
index 3069896b98e4faf691ef39af5d26280eed91948e..0758f317a608d1de383ba902c485118a56468666 100644 (file)
             @include('form/text', ['name' => 'description'])
         </div>
         <hr class="even">
+        <div class="row">
+            <div class="col-md-6">
+                <label> @include('settings/roles/checkbox', ['permission' => 'users-manage']) Manage users</label>
+            </div>
+            <div class="col-md-6">
+                <label>@include('settings/roles/checkbox', ['permission' => 'user-roles-manage']) Manage user roles & Permissions</label>
+            </div>
+        </div>
+        <hr class="even">
+        <div class="row">
+            <div class="col-md-6">
+                <label>@include('settings/roles/checkbox', ['permission' => 'restrictions-manage-all']) Manage all restrictions</label>
+            </div>
+            <div class="col-md-6">
+                <label>@include('settings/roles/checkbox', ['permission' => 'restrictions-manage-own']) Manage restrictions on own content</label>
+            </div>
+        </div>
+        <hr class="even">
         <div class="form-group">
-            <label>Manage users @include('settings/roles/checkbox', ['permission' => 'users-manage'])</label>
-            <hr class="even">
-            <label>Manage user roles & Permissions @include('settings/roles/checkbox', ['permission' => 'user-roles-manage'])</label>
-            <hr class="even">
-            <label>Manage app settings @include('settings/roles/checkbox', ['permission' => 'settings-manage'])</label>
+            <label>@include('settings/roles/checkbox', ['permission' => 'settings-manage']) Manage app settings</label>
         </div>
+
     </div>
 
     <div class="col-md-6">