четверг, 14 сентября 2017 г.

Laravel. Блог. Ограничения на действия админов.

Ограничения на действия админов.


Скроем кнопу добавления нового поста для Editor.
Для этого используем gates.

Идем в провайдеры \app\Providers\AuthServiceProvider.php

public function boot()
{
$this->registerPolicies();

Gate::resource('posts', 'App\Policies\PostPolicy');
}

Идем в консоль и создадим policy.
php artisan make:policy PostPolicy --model=Post

В app создается папка Policies. Открываем файл PostPolicy.php
Это создание сообщения! id Post-Create равно 2
<?php

namespace App\Policies;

use App\Model\admin\admin;
use App\Model\user\post;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
use HandlesAuthorization;


public function view(admin $user, post $post)
{
//
}


public function create(admin $user)
{
// пройдемся по всем ролям поьзоваетля
foreach($user->roles as $role) {
// и по всем разрешениям
foreach($role->permissions as $permission) {
// id Post-Create равно 2
if($permission->id == 2) {
return true;
}
}
}
return false;
}


public function update(admin $user, post $post)
{
//
}


public function delete(admin $user, post $post)
{
//
}
}



Открываем вид \resources\views\admin\post\show.blade.php
@extends('admin.layouts.app')

@section('headSection')
<link rel="stylesheet" href="{{ asset('admin/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css') }}" />
@endsection

@section('main-content')
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
@include('admin.layouts.pagehead')
</section>

<!-- Main content -->
<section class="content">

<!-- Default box -->
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Posts</h3>
@can('posts.create', Auth::user())
<a class="col-lg-offset-5 btn btn-success" href="{{ route('post.create') }}">Add New Post</a>
@endcan

<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse" data-toggle="tooltip"
title="Collapse">
<i class="fa fa-minus"></i></button>
<button type="button" class="btn btn-box-tool" data-widget="remove" data-toggle="tooltip" title="Remove">
<i class="fa fa-times"></i></button>
</div>
</div>
<div class="box-body">
<div class="box-body">
<table id="example1" class="table table-bordered table-striped">
<thead>
<tr>
<th>S.No</th>
<th>Title</th>
<th>Sub Title</th>
<th>Slug</th>
<th>Created at</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
@foreach ($posts as $post)
<tr>
<td>{{ $loop->index + 1 }}</td>
<td>{{ $post->title }}</td>
<td>{{ $post->subtitle }}</td>
<td>{{ $post->slug}}</td>
<td>{{ $post->created_at }}</td>
<td><a href="{{ route('post.edit', $post->id) }}"><span class="glyphicon glyphicon-edit"></span></a></td>
<td>
<form id="delete-form-{{ $post->id }}" method="post" action="{{ route('post.destroy', $post->id) }}" style="display:none">
{{ csrf_field() }}
{{ method_field('DELETE') }}
</form>
<a href="" onclick="if(confirm('Are you sure, you want to delete this?'))
{event.preventDefault();
document.getElementById('delete-form-{{ $post->id }}').submit();
}else{
event.preventDefault();
}"><span class="glyphicon glyphicon-trash"></span></a>
</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<th>S.No</th>
<th>Title</th>
<th>Sub Title</th>
<th>Slug</th>
<th>Created at</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</tfoot>
</table>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
Footer
</div>
<!-- /.box-footer-->
</div>
<!-- /.box -->

</section>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
@endsection

@section('footerSection')
<script src="{{ asset('admin/bower_components/datatables.net/js/jquery.dataTables.min.js') }}"></script>
<script src="{{ asset('admin/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js') }}"></script>
<script>
$(function () {
$('#example1').DataTable()
})
</script>
@endsection

Идем в файл \app\Policies\PostPolicy.php
Удалим модель post.

<?php

namespace App\Policies;

use App\Model\admin\admin;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
use HandlesAuthorization;

/**
* Determine whether the user can view the post.
*
* @param \App\Model\user\User $user
* @param \App\Post $post
* @return mixed
*/
public function view(admin $user)
{
//
}

/**
* Determine whether the user can create posts.
*
* @param \App\Model\user\User $user
* @return mixed
*/
public function create(admin $user)
{
// пройдемся по всем ролям поьзоваетля
foreach($user->roles as $role) {
// и по всем разрешениям
foreach($role->permissions as $permission) {
// id Post-Create равно 2
if($permission->id == 2) {
return true;
}
}
}
return false;
}

/**
* Determine whether the user can update the post.
*
* @param \App\Model\user\User $user
* @param \App\Post $post
* @return mixed
*/
public function update(admin $user) {

foreach($user->roles as $role) {
// и по всем разрешениям
foreach($role->permissions as $permission) {
// id Post-Update равно 3
if($permission->id == 3) {
return true;
}
}
}
return false;
}

/**
* Determine whether the user can delete the post.
*
* @param \App\Model\user\User $user
* @param \App\Post $post
* @return mixed
*/
public function delete(admin $user)
{
foreach($user->roles as $role) {
foreach($role->permissions as $permission) {
// id Post-Delete равно 4
if($permission->id == 4) {
return true;
}
}
}
return false;
}
}

У нас много повторений. Сократим код.
<?php

namespace App\Policies;

use App\Model\admin\admin;
use Illuminate\Auth\Access\HandlesAuthorization;

class PostPolicy
{
use HandlesAuthorization;

/**
* Determine whether the user can view the post.
*
* @param \App\Model\user\User $user
* @param \App\Post $post
* @return mixed
*/
public function view(admin $user)
{
//
}

/**
* Determine whether the user can create posts.
*
* @param \App\Model\user\User $user
* @return mixed
*/
public function create(admin $user)
{
// id Post-Create равно 2
return $this->getPermission($user, 2);

}

/**
* Determine whether the user can update the post.
*
* @param \App\Model\user\User $user
* @param \App\Post $post
* @return mixed
*/
public function update(admin $user) {
return $this->getPermission($user, 3);
}

/**
* Determine whether the user can delete the post.
*
* @param \App\Model\user\User $user
* @param \App\Post $post
* @return mixed
*/
public function delete(admin $user)
{
return $this->getPermission($user, 4);
}

protected function getPermission($user, $p_id) {
// пройдемся по всем ролям поьзоваетля
foreach($user->roles as $role) {
// и по всем разрешениям
foreach($role->permissions as $permission) {
// $p_id - permission
if($permission->id == $p_id) {
return true;
}
}
}
return false;
}
}

Открываем вид \resources\views\admin\post\show.blade.php
@extends('admin.layouts.app')

@section('headSection')
<link rel="stylesheet" href="{{ asset('admin/bower_components/datatables.net-bs/css/dataTables.bootstrap.min.css') }}" />
@endsection

@section('main-content')
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
@include('admin.layouts.pagehead')
</section>

<!-- Main content -->
<section class="content">

<!-- Default box -->
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Posts</h3>
@can('posts.create', Auth::user())
<a class="col-lg-offset-5 btn btn-success" href="{{ route('post.create') }}">Add New Post</a>
@endcan

<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse" data-toggle="tooltip"
title="Collapse">
<i class="fa fa-minus"></i></button>
<button type="button" class="btn btn-box-tool" data-widget="remove" data-toggle="tooltip" title="Remove">
<i class="fa fa-times"></i></button>
</div>
</div>
<div class="box-body">
<div class="box-body">
<table id="example1" class="table table-bordered table-striped">
<thead>
<tr>
<th>S.No</th>
<th>Title</th>
<th>Sub Title</th>
<th>Slug</th>
<th>Created at</th>
@can('posts.update', Auth::user())
<th>Edit</th>
@endcan
@can('posts.delete', Auth::user())
<th>Delete</th>
@endcan
</tr>
</thead>
<tbody>
@foreach ($posts as $post)
<tr>
<td>{{ $loop->index + 1 }}</td>
<td>{{ $post->title }}</td>
<td>{{ $post->subtitle }}</td>
<td>{{ $post->slug}}</td>
<td>{{ $post->created_at }}</td>
@can('posts.update', Auth::user())
<td><a href="{{ route('post.edit', $post->id) }}"><span class="glyphicon glyphicon-edit"></span></a></td>
@endcan
@can('posts.delete', Auth::user())
<td>
<form id="delete-form-{{ $post->id }}" method="post" action="{{ route('post.destroy', $post->id) }}" style="display:none">
{{ csrf_field() }}
{{ method_field('DELETE') }}
</form>
<a href="" onclick="if(confirm('Are you sure, you want to delete this?'))
{event.preventDefault();
document.getElementById('delete-form-{{ $post->id }}').submit();
}else{
event.preventDefault();
}"><span class="glyphicon glyphicon-trash"></span></a>
</td>
@endcan
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<th>S.No</th>
<th>Title</th>
<th>Sub Title</th>
<th>Slug</th>
<th>Created at</th>
@can('posts.update', Auth::user())
<th>Edit</th>
@endcan
@can('posts.delete', Auth::user())
<th>Delete</th>
@endcan
</tr>
</tfoot>
</table>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
Footer
</div>
<!-- /.box-footer-->
</div>
<!-- /.box -->

</section>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
@endsection

@section('footerSection')
<script src="{{ asset('admin/bower_components/datatables.net/js/jquery.dataTables.min.js') }}"></script>
<script src="{{ asset('admin/bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js') }}"></script>
<script>
$(function () {
$('#example1').DataTable()
})
</script>
@endsection


Запретим вход по ссылке http://blog.my/admin/post/create
Откроем контроллер app\Http\Controllers\Admin\PostController.php

<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

use App\Model\user\post;
use App\Model\user\category;
use App\Model\user\tag;

use Illuminate\Support\Facades\Auth;

class PostController extends Controller
{

public function __construct()
{
$this->middleware('auth:admin');
}

public function index()
{
$posts = post::all();
return view('admin.post.show', compact('posts'));
}


public function create()
{
if(Auth::user()->can('posts.create')) {
$tags = tag::all();
$categories = category::all();
return view('admin.post.post', compact('tags', 'categories'));
}
return redirect(route('admin.home'));
}



public function store(Request $request)
{
$this->validate($request, [
'title'=>'required',
'subtitle'=>'required',
'slug'=>'required',
'body'=>'required',
'image' =>'required'
]);

if($request->hasFile('image')) {
$imageName = $request->image->store('public'); // сохраняется в \storage\app\public
}

$post = new post;
$post->image = $imageName;
$post->title = $request->title;
$post->subtitle = $request->subtitle;
$post->slug = $request->slug;
$post->body = $request->body;
$post->status= $request->status;
$post->save();
$post->tags()->sync($request->tags);
$post->categories()->sync($request->categories);

return redirect(route('post.index'));
}


public function show($id)
{

}


public function edit($id)
{
if(Auth::user()->can('posts.update')) {
$post = post::with('tags', 'categories')->where('id', $id)->first();
$tags = tag::all();
$categories = category::all();
return view('admin.post.edit', compact('post', 'tags', 'categories'));
}
return redirect(route('admin.home'));
}



public function update(Request $request, $id)
{
$this->validate($request, [
'title'=>'required',
'subtitle'=>'required',
'slug'=>'required',
'body'=>'required',
'image'=>'required'
]);

if($request->hasFile('image')) {
// return $request->image->getClientOriginalName(); // имя файла
$imageName = $request->image->store('public'); // сохраняется в \storage\app\public
}

$post = post::find($id);
$post->image = $imageName;
$post->title = $request->title;
$post->subtitle = $request->subtitle;
$post->slug = $request->slug;
$post->body = $request->body;
$post->status= $request->status;
$post->tags()->sync($request->tags);
$post->categories()->sync($request->categories);
$post->save();

return redirect(route('post.index'));
}


public function destroy($id)
{
post::where('id', $id)->delete();
return redirect()->back();
}
}


Идем в провайдеры \app\Providers\AuthServiceProvider.php
Добавим гейты для тэгов и категорий:

public function boot()
{
$this->registerPolicies();

Gate::resource('posts', 'App\Policies\PostPolicy');
Gate::define('posts.tag', 'App\Policies\PostPolicy@tag');
Gate::define('posts.category', 'App\Policies\PostPolicy@category');

}

Идем в файл \app\Policies\PostPolicy.php

public function tag(admin $user)
{
return $this->getPermission($user, 9);
}

public function category(admin $user)
{
return $this->getPermission($user, 10);
}

Откроем сайдбар \resources\views\admin\layouts\sidebar.blade.php
<aside class="main-sidebar">
<!-- sidebar: style can be found in sidebar.less -->
<section class="sidebar">
<!-- Sidebar user panel -->
<div class="user-panel">
<div class="pull-left image">
<img src="dist/img/user2-160x160.jpg" class="img-circle" alt="User Image">
</div>
<div class="pull-left info">
<p>{{ Auth::user()->name }}</p>
</div>
</div>
<!-- search form -->
<form action="#" method="get" class="sidebar-form">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="Search...">
<span class="input-group-btn">
<button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
<!-- /.search form -->
<!-- sidebar menu: : style can be found in sidebar.less -->
<ul class="sidebar-menu" data-widget="tree">
<li class="header">MAIN NAVIGATION</li>
<li class="active treeview">
<li class=""><a href="{{ route('post.index') }}"><i class="fa fa-circle-o"></i> Posts</a></li>
@can('posts.category', Auth::user())
<li class=""><a href="{{ route('category.index') }}"><i class="fa fa-circle-o"></i> Categories</a></li>
@endcan
@can('posts.tag', Auth::user())
<li class=""><a href="{{ route('tag.index') }}"><i class="fa fa-circle-o"></i> Tags</a></li>
@endcan
<li class=""><a href="{{ route('user.index') }}"><i class="fa fa-circle-o"></i> Users</a></li>
<li class=""><a href="{{ route('role.index') }}"><i class="fa fa-circle-o"></i> Roles</a></li>
<li class=""><a href="{{ route('permission.index') }}"><i class="fa fa-circle-o"></i> Permissions</a></li>
</li>
</ul>
</section>
<!-- /.sidebar -->
</aside>

Закроем доступ по ссылке http://blog.my/admin/category
через middleware.

Откроем контроллер app\Http\Controllers\Admin\CategoryController.php
public function __construct()
{
$this->middleware('auth:admin');
$this->middleware('can:posts.category');
}


Откроем контроллер app\Http\Controllers\Admin\TagController.php

public function __construct()
{
$this->middleware('auth:admin');
$this->middleware('can:posts.tag');
}

Комментариев нет:

Отправить комментарий

Materialize-css. Футер

Сделаем футер и прижмем к низу страницы. Документация: https://materializecss.com/footer.html