FEATURE: add form for setting default permissions and fix few bugs

This commit is contained in:
Michal Kváček
2017-08-23 21:34:56 +02:00
parent 0aaa626124
commit e0f5cba9a4
31 changed files with 150 additions and 482 deletions
+1
View File
@@ -126,6 +126,7 @@ abstract class BaseHandler implements BaseModuleHandler
if ($user->can('manage', Settings::class)) { if ($user->can('manage', Settings::class)) {
$sub->route('settings.overview', trans('admin/mainMenu.settings'), [], 80, ['icon' => 'fa fa-fw fa-gear']); $sub->route('settings.overview', trans('admin/mainMenu.settings'), [], 80, ['icon' => 'fa fa-fw fa-gear']);
$sub->route('permissions.index', trans('admin/mainMenu.permissions'), [], 90, ['icon' => 'fa fa-fw fa-gear']);
} }
}, 10000, ['icon' => 'fa fa-fw fa-gears']); }, 10000, ['icon' => 'fa fa-fw fa-gears']);
}); });
@@ -2,10 +2,10 @@
namespace Modules\$ModuleNamespace$\Handlers; namespace Modules\$ModuleNamespace$\Handlers;
use App\CMS\Handlers\Handler; use App\CMS\Handlers\BaseHandler;
use App\Models\User; use App\Models\User;
class $Module$Handler extends Handler class $Module$Handler extends BaseHandler
{ {
/** /**
* Register admin menu * Register admin menu
@@ -38,6 +38,9 @@ class CreateNew extends Command
return; return;
} }
if (!is_dir($path))
mkdir($path);
// copy stub files // copy stub files
\File::copyDirectory(config('modules.paths.stubs'), $path); \File::copyDirectory(config('modules.paths.stubs'), $path);
+2 -2
View File
@@ -2,9 +2,9 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\CMS\ModuleManager\Installer;
use App\CMS\ModuleManager\Uninstaller;
use App\Models\Module; use App\Models\Module;
use App\ModuleManager\Installer;
use App\ModuleManager\Uninstaller;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -2,19 +2,19 @@
namespace App\Http\Controllers\Admin\Dashboard; namespace App\Http\Controllers\Admin\Dashboard;
use App\CMS\Repositories\Module; use App\CMS\Contracts\Repositories\Module;
use App\Http\Controllers\Admin\Controller; use App\Http\Controllers\Admin\Controller;
use App\Models\Content\Content; use App\Models\Content\Content;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
class Dashboard extends Controller class Dashboard extends Controller
{ {
public function index(Request $request) public function index()
{ {
$contentModules = app(Module::class)->getContentModules(); $contentModules = app(Module::class)->getContentModules();
if (\Auth::user()->can('manage', Content::class) && !$contentModules->isEmpty()) { if (\Auth::user()
->can('manage', Content::class) && !$contentModules->isEmpty()) {
return redirect()->route('content.overview'); return redirect()->route('content.overview');
} else { } else {
return redirect()->route('users.detail', ['user' => Auth::user()]); return redirect()->route('users.detail', ['user' => Auth::user()]);
+24 -22
View File
@@ -3,39 +3,41 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\Request;
use App\Models\Permissions\Permission; use App\Models\Permissions\Permission;
use App\Models\User;
use Illuminate\Http\Request;
class Permissions extends Controller class Permissions extends Controller
{ {
/** /**
* Update the specified resource in storage. * Display all permissions
* * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @param \Illuminate\Http\Request $request
* @param int $id
*
* @return \Illuminate\Http\Response
*/ */
public function update(Request $request, User $user) public function index()
{ {
$permissionIds = $request->get('permissions', []); $permissions = Permission::whereNull('parent_id')->get();
$permissions = Permission::whereIn('string_id', array_keys($permissionIds))
->get();
\DB::transaction(function () use ($user, $permissions) { return view('admin/permissions.index', compact('permissions'));
// remove all permissions }
$user->permissions()
->detach();
foreach ($permissions as $permission) { /**
$user->permissions() * Setup default permissions
->attach($permission->id); *
} * @param Request $request
}); *
* @return \Illuminate\Http\RedirectResponse
*/
public function setDefault(Request $request)
{
Permission::where('default', true)
->update(['default' => false]);
$permissions = $request->permissions;
Permission::whereIn('string_id', array_keys($permissions))
->update(['default' => true]);
return redirect() return redirect()
->back() ->back()
->with('success', trans('admin/permissions.successfullySet')); ->with('success', trans('admin/permissions.defaultSuccessfullySet'));
} }
} }
@@ -8,8 +8,11 @@ use App\CMS\Repositories\Users\User as UserRepository;
use App\Events\EditUser as EditUserEvent; use App\Events\EditUser as EditUserEvent;
use App\Http\Controllers\Admin\Controller; use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\EditUserRequest; use App\Http\Requests\EditUserRequest;
use App\Http\Requests\Request;
use App\Models\Permissions\Permission;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
class EditUser extends Controller class EditUser extends Controller
@@ -82,4 +85,34 @@ class EditUser extends Controller
->back() ->back()
->with('success', trans('admin/userManagement.userSuccessfullyEdited')); ->with('success', trans('admin/userManagement.userSuccessfullyEdited'));
} }
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
*
* @return \Illuminate\Http\Response
*/
public function setPermissions(Request $request, User $user)
{
$permissionIds = $request->get('permissions', []);
$permissions = Permission::whereIn('string_id', array_keys($permissionIds))
->get();
DB::transaction(function () use ($user, $permissions) {
// remove all permissions
$user->permissions()
->detach();
foreach ($permissions as $permission) {
$user->permissions()
->attach($permission->id);
}
});
return redirect()
->back()
->with('success', trans('admin/permissions.successfullySet'));
}
} }
+6
View File
@@ -2,6 +2,7 @@
namespace App\Models\Content; namespace App\Models\Content;
use App\Models\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/** /**
@@ -22,4 +23,9 @@ class ContentHistory extends Model
'old_value' 'old_value'
]; ];
protected $guarded = []; protected $guarded = [];
public function author()
{
return $this->belongsTo(User::class, 'user_id');
}
} }
+13 -11
View File
@@ -9,15 +9,23 @@ use Illuminate\Database\Eloquent\Model;
abstract class BasicPolicy abstract class BasicPolicy
{ {
use HandlesAuthorization; use HandlesAuthorization;
protected $entity; protected $entity;
/**
* Check if user has ability to manage entity before evaluating any other policy method
* @param User $user
* @param $ability
*
* @return bool|null
*/
public function before(User $user, $ability) public function before(User $user, $ability)
{ {
// check if user can operate on given entity // check if user can operate on given entity
if (!$this->manage($user)) { if (!$this->manage($user)) {
return false; return false;
} }
return null;
} }
/** /**
@@ -27,15 +35,9 @@ abstract class BasicPolicy
* *
* @return bool * @return bool
*/ */
public function manage(User $user) { public function manage(User $user)
if (!$user->hasAbility($this->entity.'-management')) { {
// echo "<pre>"; return $user->hasAbility($this->entity . '-management');
// debug_print_backtrace();
// echo "</pre>";
// die();
}
return $user->hasAbility($this->entity.'-management');
} }
/** /**
@@ -48,6 +50,6 @@ abstract class BasicPolicy
*/ */
public function delete(User $user, Model $model) public function delete(User $user, Model $model)
{ {
return $user->hasAbility('delete-'.$this->entity); return $user->hasAbility('delete-' . $this->entity);
} }
} }
+1 -1
View File
@@ -5,6 +5,6 @@ return [
'paths' => [ 'paths' => [
'modules' => base_path('modules'), 'modules' => base_path('modules'),
'assets' => public_path('modules'), 'assets' => public_path('modules'),
'stubs' => base_path('app/CMS/ModuleManager/Stubs'), 'stubs' => base_path('app/CMS/Modules/Stubs'),
] ]
]; ];
-3
View File
@@ -22,9 +22,6 @@ a:focus {
padding-bottom: 20px !important; padding-bottom: 20px !important;
} }
/*.form-control {*/
/*margin: .3em 0;*/
/*}*/
.text-center { .text-center {
text-align: center; text-align: center;
+1
View File
@@ -27,4 +27,5 @@ return [
"widgetAreas" => "Plochy pro widgety", "widgetAreas" => "Plochy pro widgety",
"widgets" => "Widgety", "widgets" => "Widgety",
"widgetsOverview" => "Všechny widgety", "widgetsOverview" => "Všechny widgety",
'permissions' => 'Přístupová práva'
]; ];
+5 -1
View File
@@ -1,5 +1,8 @@
<?php <?php
return [ return [
'defaultSuccessfullySet' => 'Výchozí oprávnění úspěšně nastavena.',
'pageTitle' => 'Nastavení výchozích oprávnění',
'description' => 'Nastavte výchozí oprávnění, která budou přidělena nově vytvořeným uživatelům.',
'successfullySet' => 'Oprávnění úspěšně nastavena.', 'successfullySet' => 'Oprávnění úspěšně nastavena.',
'contents' => [ 'contents' => [
'management' => 'Správa obsahu', 'management' => 'Správa obsahu',
@@ -61,5 +64,6 @@ return [
], ],
'settings' => [ 'settings' => [
'management' => 'Správa nastavení', 'management' => 'Správa nastavení',
] ],
'save' => 'Uložit výchozí nastavení'
]; ];
@@ -36,7 +36,7 @@
@if (!$directory->is_root) @if (!$directory->is_root)
@can('update', \App\Models\FileManager\Directory::class) @can('update', $directory)
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading" role="tab" id="edit-dir-title"> <div class="panel-heading" role="tab" id="edit-dir-title">
<h5 class="panel-title"> <h5 class="panel-title">
@@ -0,0 +1,41 @@
@extends('admin.layoutWithNavigation')
@section('pageHeading', trans('admin/permissions.pageTitle'))
@section('pageDescription', trans('admin/permissions.description'))
@section('content')
<form action="{{route('permissions.setDefault')}}" method="post">
{!! csrf_field() !!}
@foreach($permissions as $permission)
<div>
<label>
<input class="checkbox" data-id="{{$permission->id}}" value="1"
@if($permission->default)
checked
@endif name="permissions[{{$permission->string_id}}]" type="checkbox">
<span>{{trans($permission->name)}}</span>
</label>
</div>
@if($permission->subpermissions->count() > 0)
@foreach($permission->subpermissions as $subpermission)
<div>
<label>
<i class="fa fa-fw"></i>
<input class="checkbox child-{{$subpermission->parent_id}}" value="1"
@if($permission->default && $subpermission->default)
checked
@endif name="permissions[{{$subpermission->string_id}}]" type="checkbox">
<span>{{trans($subpermission->name)}}</span>
</label>
</div>
@endforeach
@endif
@endforeach
<button class="btn btn-primary">@lang('admin/permissions.save')</button>
</form>
@endsection
@@ -1,4 +1,4 @@
<form action="{{route('permissions.update', ['user' => $user])}}" method="post"> a<form action="{{route('users.setPermissions', ['user' => $user])}}" method="post">
{!! csrf_field() !!} {!! csrf_field() !!}
@foreach($permissions as $permission) @foreach($permissions as $permission)
-19
View File
@@ -1,19 +0,0 @@
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<a href="{{ $url }}" class="button button-{{ $color or 'blue' }}" target="_blank">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
-11
View File
@@ -1,11 +0,0 @@
<tr>
<td>
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0">
<tr>
<td class="content-cell" align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>
-7
View File
@@ -1,7 +0,0 @@
<tr>
<td class="header">
<a href="{{ $url }}">
{{ $slot }}
</a>
</td>
</tr>
-51
View File
@@ -1,51 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<style>
@media only screen and (max-width: 600px) {
.inner-body {
width: 100% !important;
}
.footer {
width: 100% !important;
}
}
@media only screen and (max-width: 500px) {
.button {
width: 100% !important;
}
}
</style>
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table class="content" width="100%" cellpadding="0" cellspacing="0">
{!! $header or '' !!}
<!-- Email Body -->
<tr>
<td class="body" width="100%" cellpadding="0" cellspacing="0">
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0">
<!-- Body content -->
<tr>
<td class="content-cell">
{!! $slot !!}
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
-11
View File
@@ -1,11 +0,0 @@
@component('mail::layout')
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
{{ config('app.name') }}
@endcomponent
@endslot
{{-- Body --}}
{!! $slot !!}
@endcomponent
-13
View File
@@ -1,13 +0,0 @@
<table class="panel" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="panel-content">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="panel-item">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
</td>
</tr>
</table>
-7
View File
@@ -1,7 +0,0 @@
<table class="promotion" align="center" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
@@ -1,13 +0,0 @@
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<a href="{{ $url }}" class="button button-green" target="_blank">{{ $slot }}</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
-7
View File
@@ -1,7 +0,0 @@
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td>
{{ Illuminate\Mail\Markdown::parse($slot) }}
</td>
</tr>
</table>
-3
View File
@@ -1,3 +0,0 @@
<div class="table">
{{ Illuminate\Mail\Markdown::parse($slot) }}
</div>
-285
View File
@@ -1,285 +0,0 @@
/* Base */
body, body *:not(html):not(style):not(br):not(tr):not(code) {
font-family: Avenir, Helvetica, sans-serif;
box-sizing: border-box;
}
body {
background-color: #f5f8fa;
color: #74787E;
height: 100%;
hyphens: auto;
line-height: 1.4;
margin: 0;
-moz-hyphens: auto;
-ms-word-break: break-all;
width: 100% !important;
-webkit-hyphens: auto;
-webkit-text-size-adjust: none;
word-break: break-all;
word-break: break-word;
}
p,
ul,
ol,
blockquote {
line-height: 1.4;
text-align: left;
}
a {
color: #3869D4;
}
a img {
border: none;
}
/* Typography */
h1 {
color: #2F3133;
font-size: 19px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h2 {
color: #2F3133;
font-size: 16px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
h3 {
color: #2F3133;
font-size: 14px;
font-weight: bold;
margin-top: 0;
text-align: left;
}
p {
color: #74787E;
font-size: 16px;
line-height: 1.5em;
margin-top: 0;
text-align: left;
}
p.sub {
font-size: 12px;
}
img {
max-width: 100%;
}
/* Layout */
.wrapper {
background-color: #f5f8fa;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.content {
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
/* Header */
.header {
padding: 25px 0;
text-align: center;
}
.header a {
color: #bbbfc3;
font-size: 19px;
font-weight: bold;
text-decoration: none;
text-shadow: 0 1px 0 white;
}
/* Body */
.body {
background-color: #FFFFFF;
border-bottom: 1px solid #EDEFF2;
border-top: 1px solid #EDEFF2;
margin: 0;
padding: 0;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.inner-body {
background-color: #FFFFFF;
margin: 0 auto;
padding: 0;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
/* Subcopy */
.subcopy {
border-top: 1px solid #EDEFF2;
margin-top: 25px;
padding-top: 25px;
}
.subcopy p {
font-size: 12px;
}
/* Footer */
.footer {
margin: 0 auto;
padding: 0;
text-align: center;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
}
.footer p {
color: #AEAEAE;
font-size: 12px;
text-align: center;
}
/* Tables */
.table table {
margin: 30px auto;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.table th {
border-bottom: 1px solid #EDEFF2;
padding-bottom: 8px;
}
.table td {
color: #74787E;
font-size: 15px;
line-height: 18px;
padding: 10px 0;
}
.content-cell {
padding: 35px;
}
/* Buttons */
.action {
margin: 30px auto;
padding: 0;
text-align: center;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.button {
border-radius: 3px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16);
color: #FFF;
display: inline-block;
text-decoration: none;
-webkit-text-size-adjust: none;
}
.button-blue {
background-color: #3097D1;
border-top: 10px solid #3097D1;
border-right: 18px solid #3097D1;
border-bottom: 10px solid #3097D1;
border-left: 18px solid #3097D1;
}
.button-green {
background-color: #2ab27b;
border-top: 10px solid #2ab27b;
border-right: 18px solid #2ab27b;
border-bottom: 10px solid #2ab27b;
border-left: 18px solid #2ab27b;
}
.button-red {
background-color: #bf5329;
border-top: 10px solid #bf5329;
border-right: 18px solid #bf5329;
border-bottom: 10px solid #bf5329;
border-left: 18px solid #bf5329;
}
/* Panels */
.panel {
margin: 0 0 21px;
}
.panel-content {
background-color: #EDEFF2;
padding: 16px;
}
.panel-item {
padding: 0;
}
.panel-item p:last-of-type {
margin-bottom: 0;
padding-bottom: 0;
}
/* Promotions */
.promotion {
background-color: #FFFFFF;
border: 2px dashed #9BA2AB;
margin: 0;
margin-bottom: 25px;
margin-top: 25px;
padding: 24px;
width: 100%;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 100%;
}
.promotion h1 {
text-align: center;
}
.promotion p {
font-size: 15px;
text-align: center;
}
-5
View File
@@ -1,5 +0,0 @@
<?php
Route::post('permissions/{user}', 'Permissions@update')
->middleware('can:set-permissions,user')
->name('permissions.update');
+8
View File
@@ -6,4 +6,12 @@ Route::get('settings', 'Settings@getOverview')
Route::post('settings', 'Settings@saveSettings') Route::post('settings', 'Settings@saveSettings')
->name('settings.save') ->name('settings.save')
->middleware('can:manage,' . \App\Models\Settings::class);
Route::get('permissions', 'Permissions@index')
->name('permissions.index')
->middleware('can:manage,' . \App\Models\Settings::class);
Route::post('permissions', 'Permissions@setDefault')
->name('permissions.setDefault')
->middleware('can:manage,' . \App\Models\Settings::class); ->middleware('can:manage,' . \App\Models\Settings::class);
+4
View File
@@ -30,4 +30,8 @@ Route::group(['namespace' => 'Users'], function () {
Route::get('users/overview/{state?}/{perPage?}', 'UsersOverview@getOverview') Route::get('users/overview/{state?}/{perPage?}', 'UsersOverview@getOverview')
->name('users.overview') ->name('users.overview')
->middleware('can:manage,' . \App\Models\User::class); ->middleware('can:manage,' . \App\Models\User::class);
Route::post('users/{user}/permissions', 'EditUser@setPermissions')
->middleware('can:set-permissions,user')
->name('users.setPermissions');
}); });
-2
View File
@@ -255,8 +255,6 @@ if [ ! -e $THEME_SET_FILE ]; then
chmod 0777 resources/views/visitor -R chmod 0777 resources/views/visitor -R
chmod 0777 resources/views/modules -R chmod 0777 resources/views/modules -R
chmod 0777 modules/*/module.json
echo $THEME_NAME > $THEME_SET_FILE echo $THEME_NAME > $THEME_SET_FILE
fi fi