Author SHA1 Message Date
Michal Kváček 5abd7d9151 FIX: fix content dependency on categories 2017-08-24 02:50:30 +02:00
Michal Kváček ac8e3aeacc FEATURE: do not require template to be set in admin 2017-08-24 02:08:28 +02:00
Michal Kváček 49bd38db50 FEATURE: hopefully last changes about permissions 2017-08-24 02:04:20 +02:00
Michal Kváček b35149ad67 FEATURE: add permissions into widgets and fix few bugs 2017-08-24 01:54:58 +02:00
Michal Kváček e0f5cba9a4 FEATURE: add form for setting default permissions and fix few bugs 2017-08-23 21:34:56 +02:00
Michal Kváček 0aaa626124 FEATURE: add another permissions 2017-08-22 23:27:23 +02:00
Michal Kváček 1050271915 Merge branch 'authorization' into separate_modules 2017-08-22 22:36:00 +02:00
Michal Kváček e0b5559b96 FEATURE: hide menu entry when no content modules are available 2017-08-22 22:35:48 +02:00
Michal Kváček 3955d7290f FEATURE: remove gallery and move it into own repository 2017-08-22 20:19:06 +02:00
Michal Kváček 81ef15b8d6 FEATURE: remove contact form and move it into own repository 2017-08-22 20:18:20 +02:00
Michal Kváček f06d9b35d8 FEATURE: remove static pages and move it into own repository 2017-08-22 20:16:56 +02:00
Michal Kváček c4c328d21d FEATURE: add /modules into .gitignore 2017-08-22 14:11:57 +02:00
Michal Kváček fc8b76960a FEATURE: move categories into own repository 2017-08-22 14:11:48 +02:00
Michal Kváček b2e99bef05 FEATURE: move module blog into own repository 2017-08-22 14:08:28 +02:00
Michal Kváček 7d847cbab9 FIX: fix few bugs in routes 2017-08-11 04:13:33 +02:00
Michal Kváček ef432702b4 FEATURE #2048: add missing policies 2017-08-11 02:57:54 +02:00
Michal Kváček 7f43316602 FEATURE #2048: another work done on permissions 2017-08-11 02:24:44 +02:00
Michal Kváček 335ec4a167 FEATURE #2048: prepare routes for ACL, add some more permissions 2017-08-11 02:07:31 +02:00
Michal Kváček cccdbda543 FEATURE #2048: add basics of permissions management 2017-08-10 23:18:53 +02:00
Michal Kváček f702ba3a29 FEATURE #1854: add widget settings 2017-08-10 21:27:39 +02:00
Michal Kváček 6af0c16a9a FEATURE #1853: move widget areas 'views' into middleware 2017-08-10 19:59:40 +02:00
Michal Kváček c2209538db FEATURE: refactorize code little bit more 2017-08-04 18:43:18 +02:00
Michal Kváček 25d9ded124 FIX: fix bug related to settings cache 2017-08-02 18:35:48 +02:00
Michal Kváček 3a1e4b9c5b FIX #2056: areYouSure now reacts also on changes in CKEditor 2017-08-02 14:10:37 +02:00
Michal Kváček 3d73bffa6e FIX: fix minor bug in user management 2017-08-02 13:52:19 +02:00
Michal Kváček a4c020daa0 FEATURE #2047: use laravel's authorization 2017-08-02 13:33:26 +02:00
Michal Kváček 67fb3c6945 FEATURE #2039 @15m: clean up the code 2017-08-02 10:39:15 +02:00
339 changed files with 10302 additions and 4699 deletions
+5 -4
View File
@@ -1,3 +1,6 @@
/modules
/templates
# published files from modules
/public/modules
/public/assets
@@ -9,9 +12,6 @@
**/views/**/custom/*
!**/views/**/custom/.gitkeep
# module config - generated in ModuleManager service provider
**/module.json
# uploaded files
/public/uploads/*
!/public/uploads/.gitkeep
@@ -32,4 +32,5 @@
/public/js
/public/fonts
/bower_components
.sass-cache
.sass-cache
!/resources/views/vendor/
+1 -1
View File
@@ -9,7 +9,7 @@ class UserRoles extends BaseEnumeration
{
$roles = [
User::ROLE_ADMIN => 'admin/userManagement.role_' . User::ROLE_ADMIN,
User::ROLE_EDITOR => 'admin/userManagement.role_' . User::ROLE_EDITOR,
// User::ROLE_EDITOR => 'admin/userManagement.role_' . User::ROLE_EDITOR,
User::ROLE_VISITOR => 'admin/userManagement.role_' . User::ROLE_VISITOR
];
@@ -1,19 +1,17 @@
<?php
namespace App\CMS\Handlers;
use App\CMS\Contracts\Modules\AppHandler;
use App\Http\Controllers\Controller;
use App\Models\Content\Content;
use App\Models\FileManager\File;
/**
* Class Handler
*
* Handler is a class which handles module-specific behaviour which cannot be done by module itself, resp. cannot be
* done by some abstract magic.
*
* @package App\CMS\Handlers\
*/
abstract class Handler extends BaseHandler implements AppHandler
abstract class AdminHandler extends BaseHandler implements AppHandler
{
public static function getHistoryHandler()
{
@@ -22,26 +20,38 @@ abstract class Handler extends BaseHandler implements AppHandler
public static function getExtendedFormSections()
{
return [
$formParts = [
'basicInfo' => trans('admin/contents.basicInfo'),
'meta' => trans('admin/contents.metaOptions'),
'publication' => trans('admin/contents.publicationOptions'),
'appearance' => trans('admin/contents.appearance'),
'files' => trans('admin/contents.files')
];
if (\Auth::user()->cannot('upload', File::class)) {
unset($formParts['files']);
}
return $formParts;
}
public static function getExtendedFormInputsCreate()
{
return [
$formParts = [
'basicInfo' => 'admin.content.formParts.basicInformation',
'meta' => 'admin.content.formParts.metaInformation',
'publication' => 'admin.content.formParts.publicationSetup',
'appearance' => 'admin.content.formParts.appearance',
'files' => 'admin.content.formParts.files'
];
if (\Auth::user()->cannot('upload', File::class)) {
unset($formParts['files']);
}
return $formParts;
}
public static function getExtendedFormInputsEdit()
{
return self::getExtendedFormInputsCreate();
+75 -43
View File
@@ -1,16 +1,24 @@
<?php
namespace App\CMS\Handlers;
use App\CMS\Contracts\Modules\BaseModuleHandler;
use App\CMS\Enumerations\TemplatePathsHumanReadableRootOnly;
use App\CMS\Enumerations\WidgetTypes;
use App\CMS\Repositories\Module;
use App\Models\ActionLog\ActionLog;
use App\Models\Content\Content;
use App\Models\FileManager\File;
use App\Models\Settings;
use App\Models\Templates\Template;
use App\Models\User;
use App\Models\Widgets\Widget;
use App\Models\Widgets\WidgetArea;
abstract class BaseHandler implements BaseModuleHandler
{
/**
* Register admin menu (or multiple ones)
*
* This cannot be in ServiceProvider because Session is started at middleware. And ServiceProvider is called before
* starting any middleware..
*
@@ -25,84 +33,108 @@ abstract class BaseHandler implements BaseModuleHandler
}
// create instance of main menu
\Menu::create('mainMenu', function ($menu) {
\Menu::create('mainMenu', function ($menu) use ($user) {
// $menu->route('admin.dashboard', trans('admin/mainMenu.dashboard'), [], 10, ['icon' => 'fa fa-fw fa-dashboard']);
/**
* Content pages
*
* Submenus can be registered later
*/
$menu->dropdown(trans('admin/mainMenu.contentPages'), function ($sub) {
$sub->route('content.overview', trans('admin/mainMenu.contentPageOverview'), [], 10000, ['icon' => 'fa fa-fw fa-list']);
}, 20, ['icon' => 'fa fa-fw fa-database']);
$contentModules = app(Module::class)->getContentModules();
if ($user->can('manage', Content::class) && !$contentModules->isEmpty()) {
$menu->dropdown(trans('admin/mainMenu.contentPages'), function ($sub) {
$sub->route('content.overview', trans('admin/mainMenu.contentPageOverview'), [], 10000, ['icon' => 'fa fa-fw fa-list']);
}, 20, ['icon' => 'fa fa-fw fa-database']);
}
/**
* File manager
*/
$menu->route('upload.overview', trans('admin/mainMenu.fileManager'), [], 40, ['icon' => 'fa fa-fw fa-folder']);
if ($user->can('manage', File::class)) {
$menu->route('upload.overview', trans('admin/mainMenu.fileManager'), [], 40, ['icon' => 'fa fa-fw fa-folder']);
}
/**
* Widgets and widget areas
*/
$menu->dropdown(trans('admin/mainMenu.widgets'), function ($sub) {
// create list of all widget types
$widgets = WidgetTypes::getWithTranslations();
if ($user->can('manage', Widget::class) || $user->can('manage', WidgetArea::class)) {
$menu->dropdown(trans('admin/mainMenu.widgets'), function ($sub) use ($user) {
// create list of all widget types
$widgets = WidgetTypes::getWithTranslations();
if (!empty($widgets)) {
$sub->dropdown(trans('admin/mainMenu.newWidget'), function ($sub) use ($widgets) {
$i = 1;
foreach ($widgets as $type => $name) {
$sub->route('widgets.new', $name, ['type' => $type], $i++);
}
}, 10, ['icon' => 'fa fa-fw fa-plus']);
}
if (!empty($widgets) && $user->can('create', Widget::class)) {
$sub->dropdown(trans('admin/mainMenu.newWidget'), function ($sub) use ($widgets) {
$i = 1;
foreach ($widgets as $type => $name) {
$sub->route('widgets.new', $name, ['type' => $type], $i++);
}
}, 10, ['icon' => 'fa fa-fw fa-plus']);
}
if ($user->can('manage', Widget::class)) {
$sub->route('widgets.overview', trans('admin/mainMenu.widgetsOverview'), [], 20, ['icon' => 'fa fa-fw fa-list']);
}
$sub->route('widgets.overview', trans('admin/mainMenu.widgetsOverview'), [], 20, ['icon' => 'fa fa-fw fa-list']);
// menu for widget areas
$sub->dropdown(trans('admin/mainMenu.widgetAreas'), function ($sub) {
$sub->route('widgetareas.new', trans('admin/mainMenu.newWidgetArea'), [], 1, ['icon' => 'fa fa-fw fa-plus']);
$sub->route('widgetareas.overview', trans('admin/mainMenu.widgetAreaOverview'), [], 2, ['icon' => 'fa fa-fw fa-list']);
}, 50, ['icon' => 'fa fa-fw fa-object-group']);
}, 50, ['icon' => 'fa fa-fw fa-puzzle-piece']);
// menu for widget areas
if ($user->can('manage', WidgetArea::class)) {
$sub->dropdown(trans('admin/mainMenu.widgetAreas'), function ($sub) use ($user) {
if ($user->can('create', WidgetArea::class)) {
$sub->route('widgetareas.new', trans('admin/mainMenu.newWidgetArea'), [], 1, ['icon' => 'fa fa-fw fa-plus']);
}
$sub->route('widgetareas.overview', trans('admin/mainMenu.widgetAreaOverview'), [], 2, ['icon' => 'fa fa-fw fa-list']);
}, 50, ['icon' => 'fa fa-fw fa-object-group']);
}
}, 50, ['icon' => 'fa fa-fw fa-puzzle-piece']);
}
/**
* Divide system entries and other links in menu
*/
$menu->addDivider(9999);
$menu->dropdown(trans('admin/mainMenu.system'), function ($sub) {
$menu->dropdown(trans('admin/mainMenu.system'), function ($sub) use ($user) {
/**
* User management
*/
$sub->dropdown(trans('admin/mainMenu.userManagement'), function ($sub) {
$sub->route('users.new', trans('admin/mainMenu.newUser'), [], 10, ['icon' => 'fa fa-fw fa-user-plus']);
$sub->route('users.overview', trans('admin/mainMenu.usersOverview'), [], 30, ['icon' => 'fa fa-fw fa-users']);
}, 20, ['icon' => 'fa fa-fw fa-users']);
if ($user->can('manage', User::class)) {
$sub->dropdown(trans('admin/mainMenu.userManagement'), function ($sub) use ($user) {
if ($user->can('create', User::class)) {
$sub->route('users.new', trans('admin/mainMenu.newUser'), [], 10, ['icon' => 'fa fa-fw fa-user-plus']);
}
$sub->route('users.overview', trans('admin/mainMenu.usersOverview'), [], 30, ['icon' => 'fa fa-fw fa-users']);
}, 20, ['icon' => 'fa fa-fw fa-users']);
}
/**
* Templates
*/
$templatePaths = TemplatePathsHumanReadableRootOnly::getWithTranslations();
if (!empty($templatePaths)) {
$sub->dropdown(trans('admin/mainMenu.templates'), function ($sub) use ($templatePaths) {
$i = 1;
foreach ($templatePaths as $id => $name) {
$sub->route('templates.overview', $name, ['id' => $id], $i++);
}
}, 60, ['icon' => 'fa fa-fw fa-file-code-o']);
if ($user->can('manage', Template::class)) {
$templatePaths = TemplatePathsHumanReadableRootOnly::getWithTranslations();
if (!empty($templatePaths)) {
$sub->dropdown(trans('admin/mainMenu.templates'), function ($sub) use ($templatePaths) {
$i = 1;
foreach ($templatePaths as $id => $name) {
$sub->route('templates.overview', $name, ['id' => $id], $i++);
}
}, 60, ['icon' => 'fa fa-fw fa-file-code-o']);
}
}
$sub->route('log.overview', trans('admin/mainMenu.actionLog'), [], 70, ['icon' => 'fa fa-fw fa-history']);
$sub->route('settings.overview', trans('admin/mainMenu.settings'), [], 80, ['icon' => 'fa fa-fw fa-gear']);
if ($user->can('manage', ActionLog::class)) {
$sub->route('log.overview', trans('admin/mainMenu.actionLog'), [], 70, ['icon' => 'fa fa-fw fa-history']);
}
if ($user->can('manage', Settings::class)) {
$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-key']);
}
}, 10000, ['icon' => 'fa fa-fw fa-gears']);
});
// create menu with user profile
\Menu::create('profileMenu', function ($menu) {
$menu->route('users.detail', trans('admin/userManagement.profile'), [], 10, ['icon' => 'fa fa-fw fa-user icon']);
\Menu::create('profileMenu', function ($menu) use ($user) {
$menu->route('users.detail', trans('admin/userManagement.profile'), ['user' => $user], 10, ['icon' => 'fa fa-fw fa-user icon']);
$menu->addDivider(999);
$menu->route('logout', trans('admin/common.logout'), [], 1000, ['icon' => 'fa fa-fw fa-power-off icon']);
});
+3 -4
View File
@@ -17,8 +17,7 @@ class History implements HistoryHandler
switch ($changeset->column) {
case 'pageContent':
$route = route('history.diff', [
'revision' => $changeset->edit_batch,
'id' => $changeset->id
'revision' => $changeset->id
]);
return "(<a href='" . $route . "'>" . trans('admin/history.diff') . "</a>)";
@@ -48,8 +47,8 @@ class History implements HistoryHandler
break;
default:
return trans('admin/history.changedFromTo', [
'from' => is_null($changeset->old_value) ? trans('admin/history.emptyValue') : $changeset->old_value,
'to' => is_null($changeset->new_value) ? trans('admin/history.emptyValue') : $changeset->new_value,
'from' => empty($changeset->old_value) ? trans('admin/history.emptyValue') : $changeset->old_value,
'to' => empty($changeset->new_value) ? trans('admin/history.emptyValue') : $changeset->new_value,
]);
break;
}
+9 -1
View File
@@ -1,7 +1,10 @@
<?php
namespace App\CMS\Handlers\Search;
use App\Models\Content\Content as ContentModel;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
class Content extends Search
{
@@ -10,10 +13,15 @@ class Content extends Search
*
* @param string $term searched word
*
* @return array list of found objects
* @return array|\Illuminate\Database\Eloquent\Collection|Collection|static[]
*/
public function search($term)
{
if (Auth::user()
->cannot('manage', ContentModel::class)) {
return new Collection();
}
$token = $this->tokenize($term);
return ContentModel::where('pageContent', 'LIKE', $token)
+7
View File
@@ -1,7 +1,9 @@
<?php
namespace App\CMS\Handlers\Search;
use App\Models\FileManager\File;
use Illuminate\Support\Collection;
class Files extends Search
{
@@ -24,6 +26,11 @@ class Files extends Search
*/
public function search($term)
{
if (\Auth::user()
->cannot('manage', File::class)) {
return new Collection();
}
$token = $this->tokenize($term);
return File::where('original_filename', 'LIKE', $token)
@@ -3,11 +3,17 @@ namespace App\CMS\Handlers\Search\Presenters;
use App\CMS\Enumerations\ContentStatuses;
use App\CMS\Handlers\Contracts\SearchPresenterHandler;
use App\Models\Content\Content;
class AdminContent implements SearchPresenterHandler
{
public function render($foundItems)
{
if (\Auth::user()
->cannot('manage', Content::class)) {
return null;
}
return view('admin.search.results.content', [
'pages' => $foundItems,
'statuses' => ContentStatuses::getWithTranslations(),
@@ -2,6 +2,7 @@
namespace App\CMS\Handlers\Search\Presenters;
use App\CMS\Handlers\Contracts\SearchPresenterHandler;
use App\Models\FileManager\File;
class AdminFiles implements SearchPresenterHandler
{
@@ -14,6 +15,11 @@ class AdminFiles implements SearchPresenterHandler
*/
public function render($foundItems)
{
if (\Auth::user()
->cannot('manage', File::class)) {
return null;
}
return view('admin.fileManager.filesTiles', ['files' => $foundItems, 'hideDelete' => true]);
}
}
+1 -1
View File
@@ -79,7 +79,7 @@ class Settings
{
if (!self::$initialized) {
self::$settings = Cache::remember('settings', config('cache.settingCacheLifetime'), function () {
app(SettingsRepository::class)->getAll();
return app(SettingsRepository::class)->getAll();
});
}
}
+10 -6
View File
@@ -3,7 +3,6 @@
namespace App\CMS\Helpers;
use App\CMS\Repositories\Widgets\WidgetArea as WidgetAreaRepository;
use App\Models\Widgets\WidgetArea;
use Illuminate\Support\Facades\Cache;
class WidgetAreas
@@ -27,9 +26,6 @@ class WidgetAreas
protected static function loadWidgetArea($uniqueCode)
{
WidgetArea::where('code', $uniqueCode)
->increment('viewed');
$widgets = Cache::remember('widget-area-' . $uniqueCode, setting('widgetCacheLifetime', 5), function () use ($uniqueCode) {
$widgetArea = app(\App\CMS\Repositories\Widgets\WidgetArea::class);
@@ -69,12 +65,20 @@ class WidgetAreas
self::initWidgetAreas();
}
// dd($uniqueCode);
if (!isset(self::$widgetAreas[$uniqueCode])) {
self::loadWidgetArea($uniqueCode);
}
echo isset(self::$widgetAreas[$uniqueCode]) ? self::$widgetAreas[$uniqueCode] : null;
}
/**
* Get list of loaded widgets and areas
*
* @return array
*/
public static function getLoadedWidgets()
{
return ['areas' => array_keys(self::$widgetAreas)];
}
}
@@ -1,4 +1,5 @@
<?php
namespace App\CMS\MenuPresenters;
use Nwidart\Menus\MenuItem;
@@ -27,6 +28,10 @@ class MetismenuPresenter extends Presenter
*/
public function getMenuWithoutDropdownWrapper($item)
{
if (!is_string($item->getUrl())) {
return null;
}
return '<li' . $this->getActiveState($item) . '><a href="' . $item->getUrl() . '">' . $item->getIcon() . ' ' . $item->title . '</a></li>' . PHP_EOL;
}
@@ -1,6 +1,6 @@
<?php
namespace App\ModuleManager;
namespace App\CMS\ModuleManager;
use App\CMS\Contracts\Modules\AppHandler;
use App\CMS\Contracts\Modules\TemplateHandler;
@@ -1,9 +1,8 @@
<?php
namespace App\ModuleManager\Providers;
namespace App\CMS\ModuleManager\Providers;
use App\Models\Module;
use Illuminate\Support\Facades\Cache;
use App\CMS\Repositories\Module as ModuleRepository;
use Illuminate\Support\ServiceProvider;
class ModuleManager extends ServiceProvider
@@ -15,11 +14,8 @@ class ModuleManager extends ServiceProvider
public function boot()
{
// this service provider needs published config - config is merged right after this service provider
$modules = Cache::rememberForever('enabled-modules', function () {
return Module::where('enabled', true)
->where('is_template', false)
->get();
});
$modules = app(ModuleRepository::class)->getOnlyModules();
// iterate over all modules and enable or disable them
foreach ($modules as $module) {
@@ -1,5 +1,5 @@
<?php
namespace App\ModuleManager;
namespace App\CMS\ModuleManager;
use App\Models\Module;
use App\Models\Templates\TemplatePath;
@@ -2,10 +2,10 @@
namespace Modules\$ModuleNamespace$\Handlers;
use App\CMS\Handlers\Handler;
use App\CMS\Handlers\BaseHandler;
use App\Models\User;
class $Module$Handler extends Handler
class $Module$Handler extends BaseHandler
{
/**
* Register admin menu
+2
View File
@@ -1,4 +1,5 @@
<?php
namespace App\CMS\Repositories\Content;
use App\CMS\Contracts\Repositories\Content as IContent;
@@ -113,6 +114,7 @@ class Content extends Repository implements IContent
->whereNull('contents.deleted_at')
->where('contents.language', LaravelLocalization::getCurrentLocale())
->where('modules.enabled', 1)
->with('module')
->orderBy('contents.created_at', 'DESC');
// filter results using handler
+24 -2
View File
@@ -1,9 +1,11 @@
<?php
namespace App\CMS\Repositories;
use App\CMS\Contracts\Repositories\Module as IModule;
use App\Models\Content\Content;
use App\Models\Module as ModuleModel;
use Illuminate\Support\Facades\Cache;
class Module extends Repository implements IModule
{
@@ -26,6 +28,15 @@ class Module extends Repository implements IModule
}
}
public function getContentModules()
{
return Cache::remember('enabled-content-modules', 3600, function () {
return ModuleModel::where('enabled', true)
->where('manages_content', true)
->get();
});
}
public function getCreateContentTitle(ModuleModel $module)
{
$pageHeading = trans('admin/contents.new', ['name' => trans($module->name)]);
@@ -52,8 +63,19 @@ class Module extends Repository implements IModule
public function all()
{
return ModuleModel::where('enabled', true)
->get();
return Cache::rememberForever('enabled-modules-and-template', function () {
return ModuleModel::where('enabled', true)
->get();
});
}
public function getOnlyModules()
{
return Cache::rememberForever('enabled-modules', function () {
return ModuleModel::where('enabled', true)
->where('is_template', false)
->get();
});
}
public function getByHandler($handler)
@@ -0,0 +1,15 @@
<?php
namespace App\CMS\Repositories\Permissions;
use App\Models\Permissions\Permission as PermissionModel;
class Permission
{
public function getRootPermissions()
{
return PermissionModel::whereNull('parent_id')
->with('subpermissions')
->get();
}
}
@@ -3,6 +3,7 @@
namespace App\CMS\Repositories\Settings;
use App\Models\Settings as SettingsModel;
use Illuminate\Support\Facades\Cache;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
class Settings
@@ -104,5 +105,7 @@ class Settings
$setting->value = $value;
empty($value) ? $setting->delete() : $setting->save();
}
Cache::forget('settings');
}
}
+7 -3
View File
@@ -1,10 +1,12 @@
<?php
namespace App\Cms\Repositories\Templates;
use App\CMS\Contracts\Repositories\Template as ITemplate;
use App\CMS\Repositories\Repository;
use App\Models\Module;
use App\Models\Templates\Template as TemplateModel;
use Illuminate\Support\Facades\Cache;
class Template extends Repository implements ITemplate
{
@@ -68,8 +70,10 @@ class Template extends Repository implements ITemplate
public function getForModule(Module $module)
{
return TemplateModel::where('module_id', $module->id)
->select(['template_name', 'name', 'description'])
->get();
return Cache::rememberForever('templates-for-module', function () use ($module) {
return TemplateModel::where('module_id', $module->id)
->select(['template_name', 'name', 'description'])
->get();
});
}
}
+14 -13
View File
@@ -8,6 +8,7 @@ use App\CMS\Contracts\Widgets\WidgetRenderer;
use App\CMS\Widgets\Exceptions\MissingParameterException;
use App\Http\Requests\Request;
use App\Models\Content\Content;
use Illuminate\Support\Facades\Cache;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Modules\Blog\Article\Handlers\Article;
@@ -15,7 +16,6 @@ class Menu implements PublicWidget
{
/**
* Name getter
*
* @return string
*/
public static function getName()
@@ -25,7 +25,6 @@ class Menu implements PublicWidget
/**
* Getter for description
*
* @return string
*/
public static function getDescription()
@@ -35,7 +34,6 @@ class Menu implements PublicWidget
/**
* Getter for presenter/renderer of this widget
*
* @return WidgetRenderer
*/
public static function getPresenter()
@@ -75,16 +73,19 @@ class Menu implements PublicWidget
$allowedStatuses[] = IContent::STATUS_PROTECTED;
}
$pages = Content::where('language', LaravelLocalization::getCurrentLocale())
->whereIn('id', $ids)
->whereIn('status', $allowedStatuses)
->where('moduleHandler', '!=', Article::class)
->get();
$used = [];
foreach ($pages as $page) {
$used[$page->id] = $page;
}
return Cache::remember('widget-menu-content-pages', 5, function () use ($ids, $allowedStatuses) {
$pages = Content::where('language', LaravelLocalization::getCurrentLocale())
->whereIn('id', $ids)
->whereIn('status', $allowedStatuses)
->where('moduleHandler', '!=', Article::class)
->get();
return $used;
$used = [];
foreach ($pages as $page) {
$used[$page->id] = $page;
}
return $used;
});
}
}
@@ -38,6 +38,9 @@ class CreateNew extends Command
return;
}
if (!is_dir($path))
mkdir($path);
// copy stub files
\File::copyDirectory(config('modules.paths.stubs'), $path);
@@ -39,6 +39,9 @@ class DisableModule extends Command
$module->enabled = false;
$module->save();
\Cache::forget('enabled-modules');
\Cache::forget('enabled-modules-and-template');
$this->line('Module ' . $module->static_name . ' disabled.');
}
}
@@ -43,6 +43,9 @@ class EnableModule extends Command
$module->enabled = true;
$module->save();
\Cache::forget('enabled-modules');
\Cache::forget('enabled-modules-and-template');
$this->line('Module ' . $module->static_name . ' enabled.');
}
}
+11 -12
View File
@@ -2,8 +2,8 @@
namespace App\Console\Commands\Modules;
use App\CMS\ModuleManager\Installer;
use App\Models\Module;
use App\ModuleManager\Installer;
use Illuminate\Console\Command;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Facades\Cache;
@@ -15,13 +15,11 @@ class InstallModule extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'module:install {name} {parentModuleId?}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Custom installation of CMS module. Name given as directory name in /modules.';
@@ -31,7 +29,6 @@ class InstallModule extends Command
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
@@ -56,8 +53,9 @@ class InstallModule extends Command
// get config
$config = $this->loadConfig();
if (empty($config))
if (empty($config)) {
return;
}
// check if it is valid
$this->checkMandatoryFields($config);
@@ -69,14 +67,15 @@ class InstallModule extends Command
Cache::forget('enabled-modules');
Cache::forget('module-handler-to-id-enumeration');
exec('composer dump-autoload');
// inform user
$this->line('Module ' . $name . ' successfuly installed');
$this->line('Module ' . $name . ' successfuly installed.');
}
/**
* Load config from Config/config.php in module files. We cannot use config() because the file have not published
* yet.
*
* @return array
* @throws FileNotFoundException
*/
@@ -85,8 +84,9 @@ class InstallModule extends Command
$basePath = $this->modulesPath . DIRECTORY_SEPARATOR . $this->moduleName . DIRECTORY_SEPARATOR;
$path = $basePath . 'Config' . DIRECTORY_SEPARATOR . 'config.php';
if (basename($basePath) == 'Database')
if (basename($basePath) == 'Database') {
return [];
}
// check if module has Config/config.php file
if (!file_exists($path)) {
@@ -121,7 +121,6 @@ class InstallModule extends Command
/**
* Installs module into database.
*
* This method calls Module::install, which handles specific installation of module. In this way we should be able
* to install any module even with some other database structures.
*
@@ -155,9 +154,9 @@ class InstallModule extends Command
if (is_null($module)) {
// insert module into database
$settings = [
'providers' => $providers,
'order' => isset($config['order']) ? $config['order'] : 0,
'files' => isset($config['files']) ? $config['files'] : []
'providers' => $providers,
'order' => isset($config['order']) ? $config['order'] : 0,
'files' => isset($config['files']) ? $config['files'] : []
];
$module = Installer::install($name, $alias, $this->moduleName, $description, $handler, $this->parentModuleId, $settings);
+3 -3
View File
@@ -2,9 +2,9 @@
namespace App\Console\Commands;
use App\CMS\ModuleManager\Installer;
use App\CMS\ModuleManager\Uninstaller;
use App\Models\Module;
use App\ModuleManager\Installer;
use App\ModuleManager\Uninstaller;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -59,7 +59,7 @@ class SetTemplate extends Command
}
try {
Installer::install($config['name'], $config['alias'], $current->static_name, $config['description'], $config['handler'], false, $config);
Installer::install($config['name'], $config['alias'], $config['staticName'], $config['description'], $config['handler'], false, $config);
} catch (\Exception $e) {
$this->error('Cannot install template ' . $template . '. Message: ' . $e->getMessage());
return;
@@ -46,10 +46,13 @@ class ContentOverview extends Controller
// get homepage - for checking if homepage is set and available
$homepage = $this->content->getHomepage();
$contentModules = app(\App\CMS\Repositories\Module::class)->getContentModules();
return view('admin.content.overview', [
'pages' => $pages,
'homepage' => $homepage,
'pageHeading' => $pageHeading,
'contentModules' => $contentModules,
'statuses' => ContentStatuses::getWithTranslations(),
'module' => isset($module) ? $module : null
]);
@@ -1,4 +1,5 @@
<?php
namespace App\Http\Controllers\Admin\Contents;
use App\CMS\Contracts\Repositories\Content as IContent;
@@ -11,13 +12,12 @@ use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\CreateNewContentRequest;
use App\Http\Requests\Request;
use App\Models\Module;
use Illuminate\Support\Collection;
use Modules\Categories\Contracts\Repositories\Category as ICategory;
/**
* Class CreateNewContent
*
* Controller for creating new content page.
*
* @package App\Http\Controllers\Admin\Contents
*/
class CreateNewContent extends Controller
@@ -30,10 +30,6 @@ class CreateNewContent extends Controller
* @var IModuleRepository
*/
private $module;
/**
* @var ICategory
*/
private $category;
/**
* @var ITemplate
*/
@@ -41,23 +37,20 @@ class CreateNewContent extends Controller
/**
* CreateNewContent constructor.
*
* Sets File and Content models into class variables
*
* @param IContent|Content $content
* @param IModuleRepository $module
* @param ICategory $category
*
* @param ITemplate $template
*
* @internal param File $file
*/
public function __construct(IContent $content, IModuleRepository $module, ICategory $category, ITemplate $template)
public function __construct(IContent $content, IModuleRepository $module, ITemplate $template)
{
parent::__construct();
$this->content = $content;
$this->module = $module;
$this->category = $category;
$this->template = $template;
}
@@ -73,7 +66,11 @@ class CreateNewContent extends Controller
$statuses = ContentStatuses::getWithTranslations();
$pageHeading = $this->module->getCreateContentTitle($module);
$templates = $this->template->getForModule($module);
$categories = $this->category->getForModule($module);
$categories = new Collection();
if (class_exists(ICategory::class)) {
$categories = app(ICategory::class)->getForModule($module);
}
$page = $this->content->getOne();
@@ -1,4 +1,5 @@
<?php
namespace App\Http\Controllers\Admin\Contents;
use App\CMS\Contracts\Repositories\Content as IContent;
@@ -6,19 +7,15 @@ use App\CMS\Contracts\Repositories\Module as IModuleRepository;
use App\CMS\Contracts\Repositories\Template as ITemplate;
use App\CMS\Enumerations\ContentStatuses;
use App\Cms\Handlers\Interactions\Interaction;
use App\CMS\Helpers\CurrentTemplate;
use App\Cms\Interactions\Admin\Content\EditContent as EditContentInteraction;
use App\Events\AttemptToEditInvalidContent;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\EditContentRequest;
use App\Http\Requests\Request;
use App\Models\Content\Content;
use App\Models\Content\ContentHistory;
use App\Models\FileManager\File;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Collection;
use Modules\Categories\Contracts\Repositories\Category as ICategory;
use Modules\Categories\Repositories\Category;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class EditContent extends Controller
{
@@ -38,10 +35,6 @@ class EditContent extends Controller
* @var IModuleRepository
*/
private $module;
/**
* @var ICategory
*/
private $category;
/**
* @var ITemplate
*/
@@ -49,7 +42,6 @@ class EditContent extends Controller
/**
* EditContent constructor.
*
* Load ContentHistory and File into this controller
*
* @param ContentHistory $history
@@ -59,13 +51,12 @@ class EditContent extends Controller
* @param ICategory $category
* @param ITemplate $template
*/
public function __construct(ContentHistory $history, File $file, IContent $content, IModuleRepository $module, Category $category, ITemplate $template)
public function __construct(ContentHistory $history, File $file, IContent $content, IModuleRepository $module, ITemplate $template)
{
$this->history = $history;
$this->file = $file;
$this->content = $content;
$this->module = $module;
$this->category = $category;
$this->template = $template;
}
@@ -84,9 +75,13 @@ class EditContent extends Controller
$module = $this->module->getByHandler($page->moduleHandler);
$pageHeading = $this->module->getUpdateContentTitle($module, $page);
$templates = $this->template->getForModule($module);
$categories = $this->category->getForModule($module);
$history = $this->history->getStructuredHistoryOf($page);
$categories = new Collection();
if (class_exists(ICategory::class)) {
$categories = app(ICategory::class)->getForModule($module);
}
// render view
return view('admin.content.edit', [
'pageHeading' => $pageHeading,
@@ -94,7 +89,8 @@ class EditContent extends Controller
'page' => $page,
'module' => $module,
'categories' => $categories,
'rootPages' => $this->content->getOverview()->get(),
'rootPages' => $this->content->getOverview()
->get(),
'templates' => $templates,
'formSectionNames' => $this->module->call($module, 'getExtendedFormSections'),
'formSections' => $this->module->call($module, 'getExtendedFormInputsEdit'),
@@ -2,13 +2,22 @@
namespace App\Http\Controllers\Admin\Dashboard;
use App\CMS\Contracts\Repositories\Module;
use App\Http\Controllers\Admin\Controller;
use Illuminate\Http\Request;
use App\Models\Content\Content;
use Illuminate\Support\Facades\Auth;
class Dashboard extends Controller
{
public function index(Request $request)
public function index()
{
return redirect()->route('content.overview');
$contentModules = app(Module::class)->getContentModules();
if (\Auth::user()
->can('manage', Content::class) && !$contentModules->isEmpty()) {
return redirect()->route('content.overview');
} else {
return redirect()->route('users.detail', ['user' => Auth::user()]);
}
}
}
@@ -1,8 +1,8 @@
<?php
namespace App\Http\Controllers\Admin\FileManager;
use App\CMS\Helpers\Path;
use App\CMS\Helpers\Template;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\Request;
use App\Models\FileManager\File;
@@ -47,7 +47,7 @@ class UploadFile extends Controller
*/
private function internalUpload(Request $request)
{
// try {
try {
$uploadedFiles = [];
$files = $request->all()['files'];
@@ -62,9 +62,9 @@ class UploadFile extends Controller
return redirect()
->back()
->with('success', trans_choice('admin/fileManager.uploadSuccessfull', $successfullUploads));
// } catch (FileException $e) {
// return $this->invalidUpload('invalidFile');
// }
} catch (FileException $e) {
return $this->invalidUpload('invalidFile');
}
}
/**
@@ -32,8 +32,6 @@ class UploadedFilesOverview extends Controller
*/
public function index(Directory $directory = null)
{
// dd($directory);
// include hidden directories?
$subdirectories = $this->directoryRepository->getAllSubdirectories($directory);
-87
View File
@@ -1,87 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\LoginRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
/**
* Class Login
*
* @package App\Http\Controllers\Admin
*
* @todo use trait ThrottlesLogins for disabling brutal-force password cracking
*/
class Login extends Controller
{
/**
* Display login form
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getLogin()
{
return view('admin.loginForm');
}
/**
* Login handler
*
* @param LoginRequest $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postLogin(LoginRequest $request)
{
$email = $request->email;
// try to find user
$user = User::where('email', $email)
->where('role', '!=', User::ROLE_VISITOR)
->where('status', User::STATE_ACTIVE)
->first();
if (!$user) {
return $this->loginFailed();
}
// try to log in user
if (Hash::check($request->password, $user->password)) {
Auth::login($user);
$redirect = $request->redirectTo ? $request->redirectTo : route('admin.dashboard');
return redirect()->intended($redirect);
}
// login invalid, redirect and inform the user
return $this->loginFailed();
}
/**
* Logs out user
*
* @return \Illuminate\Http\RedirectResponse
*/
public function logout()
{
// remove user information
\Auth::logout();
// redirect to login form with info about successfull logout
return redirect()
->route('login')
->with('success', trans('admin/common.logoutSuccessfull'));
}
private function loginFailed()
{
return redirect()
->route('login')
->with('error', trans('auth.failed'))
->withInput();
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Request;
use App\Models\Permissions\Permission;
class Permissions extends Controller
{
/**
* Display all permissions
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
$permissions = Permission::whereNull('parent_id')->get();
return view('admin/permissions.index', compact('permissions'));
}
/**
* Setup default permissions
*
* @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()
->back()
->with('success', trans('admin/permissions.defaultSuccessfullySet'));
}
}
+7 -3
View File
@@ -13,7 +13,6 @@ class Search extends Controller
{
/**
* Create form for searching
*
* @return $this|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function getSearch()
@@ -37,7 +36,6 @@ class Search extends Controller
/**
* Method used for performing search.
*
* This method iterates over all registered search engines and returns results for each engine apart.
*
* @param string $term search text
@@ -60,10 +58,16 @@ class Search extends Controller
// try to find given term
$results = $search->search($term);
$content = $presenter->render($results);
if (is_null($content)) {
continue;
}
// create result object
$resultsParts[$search->getId()] = [
'name' => $search->getName(),
'content' => $presenter->render($results),
'content' => $content,
'count' => count($results)
];
}
+34 -1
View File
@@ -8,8 +8,11 @@ use App\CMS\Repositories\Users\User as UserRepository;
use App\Events\EditUser as EditUserEvent;
use App\Http\Controllers\Admin\Controller;
use App\Http\Requests\EditUserRequest;
use App\Http\Requests\Request;
use App\Models\Permissions\Permission;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
class EditUser extends Controller
@@ -39,7 +42,7 @@ class EditUser extends Controller
public function getEditUser(User $user = null)
{
// when no user specified, lets assume we want to edit "me"
if (!$user->exists()) {
if (!$user->exists) {
$user = Auth::user();
}
@@ -82,4 +85,34 @@ class EditUser extends Controller
->back()
->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'));
}
}
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin\Users;
use App\CMS\Enumerations\UserRoles;
use App\CMS\Enumerations\UserStates;
use App\Cms\Repositories\ActionLog\Actions;
use App\CMS\Repositories\Permissions\Permission;
use App\Http\Controllers\Admin\Controller;
use App\Models\ActionLog\ActionLog;
use App\Models\User;
@@ -25,19 +26,21 @@ class UserDetail extends Controller
public function getDetail(User $user = null)
{
// when no user specified, lets assume we want to edit "me"
if (!$user->exists()) {
$id = Auth::user();
if (!$user->exists) {
$user = Auth::user();
}
$actions = $this->log->getUserActions($user->id, 10);
$roles = UserRoles::getWithTranslations();
$states = UserStates::getWithTranslations();
$permissions = app(Permission::class)->getRootPermissions();
return view('admin.userManagement.detail', [
'user' => $user,
'statuses' => $states,
'roles' => $roles,
'actions' => $actions
'user' => $user,
'statuses' => $states,
'roles' => $roles,
'actions' => $actions,
'permissions' => $permissions
]);
}
}
@@ -40,7 +40,6 @@ class EditWidgetArea extends Controller
*/
public function edit(WidgetArea $widgetArea)
{
return view("test");
$associatedWidgetIds = WidgetInWidgetArea::getWidgetIdsFromArea($widgetArea->id);
$widgets = Widget::where('language', LaravelLocalization::getCurrentLocale())
->paginate(25);
@@ -1,17 +1,25 @@
<?php
namespace App\Http\Controllers\Admin\Widgets;
use App\Http\Controllers\Admin\Controller;
use App\Models\Widgets\Widget;
use App\Models\Widgets\WidgetType;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
class WidgetsOverview extends Controller
{
/**
* Display list of all widgets
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
$widgets = Widget::where('language', LaravelLocalization::getCurrentLocale())
->paginate(25);
return view('admin.widgets.overview', ['widgets' => $widgets]);
$widgetTypes = WidgetType::all();
return view('admin.widgets.overview', compact('widgetTypes', 'widgets'));
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
}
@@ -0,0 +1,46 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/admin';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function logout() {
Auth::logout();
return redirect()->route('login');
}
}
@@ -0,0 +1,73 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
* @var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'g-recaptcha-response' => 'required|recaptcha',
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
*
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'role' => User::ROLE_VISITOR,
'state' => User::STATE_ACTIVE,
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
}
@@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = '/admin';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
}
+2 -3
View File
@@ -1,9 +1,9 @@
<?php
namespace App\Http\Controllers;
namespace App\Http\Controllers\Visitor;
use App\CMS\Contracts\Repositories\Content;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class Sitemap extends Controller
{
@@ -24,7 +24,6 @@ class Sitemap extends Controller
/**
* Get sitemap for all content pages
*
* @return mixed
*/
public function getMap()
+12 -9
View File
@@ -2,8 +2,9 @@
namespace App\Http;
use App\Http\Middleware\TemplatePathInstaller;
use App\Http\Middleware\WidgetInstaller;
use App\Http\Middleware\TemplateChecker;
use App\Http\Middleware\Web\IncrementWidgetsViews;
use Illuminate\Auth\Middleware\Authorize;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode;
@@ -36,13 +37,15 @@ class Kernel extends HttpKernel
protected $middlewareGroups = [
'web' => [
CheckForMaintenanceMode::class,
TemplateChecker::class,
AddQueuedCookiesToResponse::class,
IncrementWidgetsViews::class,
],
'admin' => [
Middleware\Authenticate::class,
Middleware\AdminMenuRegistrator::class,
TemplatePathInstaller::class,
WidgetInstaller::class,
Middleware\Admin\Authenticate::class,
Middleware\Admin\AdminMenuRegistrator::class,
Middleware\Admin\TemplatePathInstaller::class,
Middleware\Admin\WidgetInstaller::class,
],
'api' => [
'throttle:60,1',
@@ -54,9 +57,9 @@ class Kernel extends HttpKernel
* @var array
*/
protected $routeMiddleware = [
'auth' => Middleware\Authenticate::class,
'onlyAdmin' => Middleware\RequireAdminRole::class,
'adminMenu' => Middleware\AdminMenuRegistrator::class,
'can' => Authorize::class,
'auth' => Middleware\Admin\Authenticate::class,
'adminMenu' => Middleware\Admin\AdminMenuRegistrator::class,
'guest' => Middleware\RedirectIfAuthenticated::class,
'throttle' => ThrottleRequests::class,
'localize' => LaravelLocalizationRoutes::class,
@@ -1,9 +1,9 @@
<?php
namespace App\Http\Middleware;
namespace App\Http\Middleware\Admin;
use App\CMS\Handlers\Handler;
use App\Models\Module;
use App\CMS\Handlers\AdminHandler;
use App\CMS\Repositories\Module as ModuleRepository;
use Closure;
use Illuminate\Support\Facades\Log;
@@ -26,15 +26,15 @@ class AdminMenuRegistrator
// create menu
$user = \Auth::user();
Handler::registerAdminMenu($user);
AdminHandler::registerAdminMenu($user);
$modules = Module::where('enabled', true)
->get();
$modules = app(ModuleRepository::class)->all();
// iterate over all enabled modules
foreach ($modules as $key => $module) {
if (!is_callable([$module->handler, 'registerAdminMenu']))
if (!is_callable([$module->handler, 'registerAdminMenu'])) {
continue;
}
// try to register menus
try {
@@ -0,0 +1,46 @@
<?php
namespace App\Http\Middleware\Admin;
use App\Models\User;
use Closure;
use Illuminate\Support\Facades\Auth;
class Authenticate
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
*
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (!Auth::guard($guard)
->check() || Auth::user()->status != User::STATE_ACTIVE || Auth::user()->role == User::ROLE_VISITOR || 0) {
Auth::logout();
if ($request->ajax()) {
return response('Unauthorized.', 401);
}
// select right message
if (Auth::user() && Auth::user()->status != User::STATE_ACTIVE) {
$message = 'auth.userNotActive';
} elseif (Auth::user() && Auth::user()->role == User::ROLE_VISITOR) {
$message = 'auth.visitorInAdmin';
} else {
$message = 'auth.loginExpired';
}
return redirect()
->route('login')
->with('warning', trans($message));
}
return $next($request);
}
}
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Middleware;
namespace App\Http\Middleware\Admin;
use App\CMS\Handlers\Registrators\TemplateRegistrator;
use Closure;
@@ -1,6 +1,6 @@
<?php
namespace App\Http\Middleware;
namespace App\Http\Middleware\Admin;
use App\CMS\Handlers\Registrators\WidgetRegistrator;
use Closure;
-33
View File
@@ -1,33 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class Authenticate
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
*
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (!Auth::guard($guard)->check()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
}
return redirect()
->route('login')
->with('redirectTo', $request->fullUrl());
}
return $next($request);
}
}
@@ -2,10 +2,10 @@
namespace App\Http\Middleware;
use App\Models\User;
use App\CMS\Helpers\CurrentTemplate;
use Closure;
class RequireAdminRole
class TemplateChecker
{
/**
* Handle an incoming request.
@@ -17,10 +17,10 @@ class RequireAdminRole
*/
public function handle($request, Closure $next)
{
if (\Auth::user()->role != User::ROLE_ADMIN) {
return redirect()
->back()
->with('error', trans('auth.accessDenied'));
$template = CurrentTemplate::get();
if (!$template) {
throw new \ErrorException('Template is not set, cannot continue');
}
return $next($request);
@@ -0,0 +1,36 @@
<?php
namespace App\Http\Middleware\Web;
use App\CMS\Helpers\WidgetAreas;
use App\Models\Widgets\WidgetArea;
use Closure;
class IncrementWidgetsViews
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// if (!setting('useWidgetPreloading', false))
// return;
$widgets = WidgetAreas::getLoadedWidgets();
if (!empty($widgets['areas'])) {
WidgetArea::whereIn('code', $widgets['areas'])
->increment('viewed');
}
}
}
-75
View File
@@ -1,75 +0,0 @@
<?php
/**
* This routing groups is used for routing along public part of website
*/
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
Route::pattern('id', '\d+');
Route::pattern('url', '[0-9\-a-z]+');
/*******************************************************************************/
Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => ['bindings']], function () {
/**
* This route group serves to handle request in admin
*/
Route::group([
'middleware' => ['admin'],
'namespace' => 'Admin',
'prefix' => 'admin'
], function () {
// include all routes in routes/admin subfolder
$files = ['contents', 'fileManager', 'settings', 'templates', 'users', 'widgets'];
foreach ($files as $file) {
require_once __DIR__ . DIRECTORY_SEPARATOR . 'routes' . DIRECTORY_SEPARATOR . 'admin' . DIRECTORY_SEPARATOR . $file . '.php';
}
// display dashboard with some usefull information
Route::get('/', 'Dashboard\Dashboard@index')
->name('admin.dashboard');
// list of all actions
Route::get('actions', 'ActionLog\Overview@index')
->name('log.overview');
// search form with results
Route::get('search', 'Search@getSearch')
->name('search');
// logout method
Route::get('logout', 'Login@logout')
->name('logout');
});
/**************************************************************************************/
/**
* This section must be specified as last one
*/
Route::group(['middleware' => ['web']], function () {
// Homepage
Route::get('/', 'Visitor\Homepage@getIndex')
->name('page.index');
// display login form
Route::get('admin/login', 'Admin\Login@getLogin')
->name('loginForm');
// handle login
Route::post('admin/login', 'Admin\Login@postLogin')
->name('login');
// route for sitemap
Route::get('sitemap.xml', 'Visitor\Sitemap@getMap')
->name('sitemap');
// route for all content pages. This rule must be specified last (because it matches every route)
Route::get('{url}', 'Visitor\ContentPage@getPage')
->name('page.content');
});
});
-42
View File
@@ -1,42 +0,0 @@
<?php
Route::group(['namespace' => 'Contents'], function () {
// list of all static pages
Route::get('content/overview/{module?}', 'ContentOverview@index')
->name('content.overview');
// form for creating new static page
Route::get('content/new/{module}', 'CreateNewContent@create')
->name('content.new');
// form for editing existing static page
Route::get('content/edit/{page}', 'EditContent@edit')
->name('content.edit');
// post method for creating new static page
Route::post('content/new/{module}', 'CreateNewContent@store')
->name('content.newPost');
// post method for creating new static page
Route::post('content/edit/{page}', 'EditContent@update')
->name('content.editPost');
// change status of page (protected, public or draft)
Route::get('content/status/{page}/{status}', 'ContentActions@changeStatus')
->name('content.changeStatus');
// set homepage
Route::get('content/homepage/{page}', 'ContentActions@setHomepage')
->name('content.setHomepage');
// delete page
Route::get('content/delete/{page}', 'ContentActions@delete')
->name('content.delete');
// history of changes for specified page
Route::get('history/{page}', 'History@getOverview')
->name('content.history');
// history of changes for specified page
Route::get('history/{revision}', 'History@getDiff')
->name('history.diff');
});
-29
View File
@@ -1,29 +0,0 @@
<?php
Route::group(['namespace' => 'FileManager'], function () {
Route::get('files/overview/{directory?}', 'UploadedFilesOverview@index')
->name('upload.overview');
// uploader methods
Route::get('directories/edit/{directory}', 'EditDirectory@edit')
->name('upload.editDirectory');
Route::post('directories/edit/{directory}', 'EditDirectory@update')
->name('upload.postEditDirectory');
route::post('directories/new', 'CreateNewDirectory@store')
->name('upload.postNewDirectory');
Route::get('upload/detail/{file}', 'EditUploadedFile@show')
->name('upload.detail');
Route::post('upload/detail/{file}', 'EditUploadedFile@update')
->name('upload.postEdit');
Route::get('upload/delete/{file}', 'EditUploadedFile@delete')
->name('upload.delete');
// uploader methods
Route::post('upload', 'UploadFile@store')
->name('upload.postFile');
});
-7
View File
@@ -1,7 +0,0 @@
<?php
// form with settings
Route::get('settings', 'Settings@getOverview')
->name('settings.overview');
Route::post('settings', 'Settings@saveSettings')
->name('settings.save');
-15
View File
@@ -1,15 +0,0 @@
<?php
// these routes are available only for user with role admin
Route::group(['middleware' => 'onlyAdmin', 'namespace' => 'Templates'], function () {
Route::get('templates/overview/path/{templatePath}', 'TemplateOverview@getPath')
->name('templates.overview');
Route::post('templates/copy', 'CopyTemplate@createCopy')
->name('templates.postCopy');
Route::get('templates/edit/{template}', 'EditTemplate@getEdit')
->name('templates.edit');
Route::post('templates/edit/{template}', 'EditTemplate@postEdit')
->name('templates.postEdit');
});
-27
View File
@@ -1,27 +0,0 @@
<?php
Route::group(['namespace' => 'Users'], function () {
// display form for creating new user
Route::get('users/new', 'CreateNewUser@getNewUser')
->name('users.new');
// POST methods
// display form for creating new user
Route::post('users/new', 'CreateNewUser@postRegistration')
->name('users.newPost');
// display form for edit of existing user
Route::get('users/edit/{user}', 'EditUser@getEditUser')
->name('users.edit');
// display user detail in admin
Route::get('users/detail/{user?}', 'UserDetail@getDetail')
->name('users.detail');
// method for saving edited data of user
Route::post('users/edit/{user}', 'EditUser@postEdit')
->name('users.editPost');
// display list of all users registered into our system
Route::get('users/overview/{state?}/{perPage?}', 'UsersOverview@getOverview')
->name('users.overview');
});
+6 -4
View File
@@ -3,19 +3,22 @@
namespace App\Listeners\Loggers;
use Illuminate\Auth\Events\Logout;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class LogLogout extends Logger
{
/**
* Handle the event.
*
* @param Logout $event
* @param Logout $event
*
* @return void
*/
public function handle(Logout $event)
{
if (is_null($event->user)) {
return;
}
$parameters = [
'id' => $event->user->id,
'name' => $event->user->name,
@@ -27,7 +30,6 @@ class LogLogout extends Logger
/**
* Getter for action name. Used only internally
*
* @return mixed
*/
protected function getName()
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Listeners;
use App\Events\CreateNewUser;
use App\Models\Permissions\Permission;
class SetDefaultPermissions
{
/**
* Handle the event.
*
* @param CreateNewUser $event
*
* @return void
*/
public function handle(CreateNewUser $event)
{
$permissions = Permission::where('default', true)
->get();
foreach ($permissions as $permission) {
$event->user->permissions()
->attach($permission);
}
}
}
+11 -1
View File
@@ -2,6 +2,7 @@
namespace App\Models\Content;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
/**
@@ -21,5 +22,14 @@ class ContentHistory extends Model
'new_value',
'old_value'
];
protected $guarded = [];
/**
* Author of the change
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function author()
{
return $this->belongsTo(User::class, 'user_id');
}
}
@@ -6,6 +6,7 @@ use App\Events\UploadFile;
use App\Models\FileManager\File as FileModel;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Gate;
use Symfony\Component\HttpFoundation\File\File as SymphonyFile;
use Symfony\Component\HttpFoundation\File\UploadedFile;
@@ -36,6 +37,8 @@ trait File
*/
public function upload(UploadedFile $file, $data = [])
{
abort_unless(Auth::user()->can('upload', FileModel::class), 403);
$data = (object)$data;
$destination = config('app.upload_path');
+1 -1
View File
@@ -15,7 +15,7 @@ class Module extends Model
'parent_id',
'name',
'description',
'static_name', // @todo instalace potrebuje naplnit tento sloupec!
'static_name',
'alias',
'module_settings',
'enabled',
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace App\Models\Permissions;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
public $timestamps = false;
protected $fillable = [
'string_id',
'parent_id',
'group',
'name',
'default'
];
protected $casts = [
'default' => 'boolean'
];
/**
* Assign observer for this model for logging
*/
protected static function boot()
{
parent::boot();
self::observe(PermissionObserver::class);
}
public function parent()
{
return $this->hasOne(Permission::class, 'parent_id');
}
public function subpermissions()
{
return $this->hasMany(Permission::class, 'parent_id');
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Models\Permissions;
use App\Models\User;
class PermissionObserver
{
/**
* Sets default permissions when creating new
*
* @param Permission $permission
*/
public function created(Permission $permission)
{
if ($permission->default) {
$users = User::where('role', '!=', User::ROLE_VISITOR)
->get();
foreach ($users as $user) {
$user->permissions()
->attach($permission->id);
}
}
}
}
+55 -9
View File
@@ -2,18 +2,29 @@
namespace App\Models;
use App\Models\Permissions\Permission;
use App\Notifications\ResetPasswordNotification;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticableInterface;
use Illuminate\Contracts\Auth\CanResetPassword;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Notifications\Notifiable;
/**
* Class User
*/
class User extends Model implements AuthenticableInterface
class User extends Model implements AuthenticableInterface, CanResetPassword
{
use SoftDeletes, Authenticatable, Authorizable;
use SoftDeletes, Authenticatable, Authorizable, Notifiable;
const STATE_DELETED = 'deleted';
const STATE_BLOCKED = 'blocked';
const STATE_ACTIVE = 'active';
const ROLE_VISITOR = 'visitor';
const ROLE_EDITOR = 'editor';
const ROLE_ADMIN = 'admin';
protected static $abilities;
public $timestamps = true;
protected $fillable = [
'email',
@@ -24,17 +35,52 @@ class User extends Model implements AuthenticableInterface
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
];
const STATE_DELETED = 'deleted';
const STATE_BLOCKED = 'blocked';
const STATE_ACTIVE = 'active';
const ROLE_VISITOR = 'visitor';
const ROLE_EDITOR = 'editor';
const ROLE_ADMIN = 'admin';
/**
* Get the e-mail address where password reset links are sent.
* @return string
*/
public function getEmailForPasswordReset()
{
return $this->email;
}
/**
* Send the password reset notification.
*
* @param string $token
*
* @return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPasswordNotification($token));
}
public function permissions()
{
return $this->belongsToMany(Permission::class, 'user_has_permissions');
}
/**
* Check if current user has given ability
*
* @param $ability
*
* @return bool
*/
public function hasAbility($ability)
{
if (!isset(self::$abilities[$this->id])) {
self::$abilities[$this->id] = $this->permissions->pluck('string_id')->toArray();
}
return in_array($ability, self::$abilities[$this->id]);
}
}
-10
View File
@@ -1,10 +0,0 @@
<?php
return [
'namespace' => 'Modules',
'paths' => [
'modules' => base_path('modules'),
'assets' => public_path('modules'),
'stubs' => base_path('app/CMS/Modules/Stubs'),
]
];
@@ -0,0 +1,52 @@
<?php
namespace App\Notifications;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class ResetPasswordNotification extends Notification
{
/**
* @var string
*/
private $token;
/**
* Create a new notification instance.
* @return void
*/
public function __construct($token)
{
$this->token = $token;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
*
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$url = route('password.reset', ['token' => $this->token, 'email' => $notifiable->email]);
return (new MailMessage())->subject(trans('notification.forgottenPassword.subject'))
->line(trans('notification.forgottenPassword.firstLine'))
->action(trans('notification.forgottenPassword.button'), $url)
->line(trans('notification.forgottenPassword.lastLine'));
}
}
View File
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App\Policies;
use Illuminate\Auth\Access\HandlesAuthorization;
class ActionLogPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'actions';
}
+54
View File
@@ -0,0 +1,54 @@
<?php
namespace App\Policies;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Database\Eloquent\Model;
abstract class BasicPolicy
{
use HandlesAuthorization;
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)
{
// check if user can operate on given entity
if (!$this->manage($user)) {
return false;
}
}
/**
* Can user manage given entity?
*
* @param User $user
*
* @return bool
*/
public function manage(User $user)
{
return $user->hasAbility($this->entity . '-management');
}
/**
* Determine whether the user can delete the content.
*
* @param \App\Models\User $user
* @param Model $model
*
* @return mixed
*/
public function delete(User $user, Model $model)
{
return $user->hasAbility('delete-' . $this->entity);
}
}
+55
View File
@@ -0,0 +1,55 @@
<?php
namespace App\Policies;
use App\Models\Content\Content;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class ContentPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'contents';
/**
* Determine whether the user can update the content.
*
* @param \App\Models\User $user
* @param \App\Models\Content\Content $content
*
* @return mixed
*/
public function update(User $user, Content $content)
{
if ($user->id != $content->user_id) {
return $user->hasAbility('update-contents') && $user->hasAbility('update-all-contents');
};
return $user->hasAbility('update-contents');
}
/**
* Does given user has permissions to create new content page?
*
* @param User $user
*
* @return bool
*/
public function create(User $user) {
return $user->hasAbility('create-contents');
}
public function publish(User $user)
{
return $user->hasAbility('publish-contents');
}
public function setHomepage(User $user)
{
return $user->hasAbility('set-homepage-contents');
}
public function viewHistory(User $user) {
return $user->hasAbility('view-history-contents');
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace App\Policies;
use App\Models\FileManager\Directory;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class DirectoriesPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'directories';
/**
* Determine whether the user can create directories.
*
* @param \App\Models\User $user
* @return mixed
*/
public function create(User $user)
{
return $user->hasAbility('create-directories');
}
/**
* Determine whether the user can update the directory.
*
* @param \App\Models\User $user
* @param \App\Directory $directory
* @return mixed
*/
public function update(User $user, Directory $directory)
{
return $user->hasAbility('update-directories');
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Policies;
use App\Models\FileManager\File;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class FilesPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'files';
/**
* Determine whether the user can create appModelsFileManagerFiles.
*
* @param User $user
* @param File $file
*
* @return mixed
*/
public function upload(User $user)
{
return $user->hasAbility('upload-files');
}
/**
* Determine whether the user can update the appModelsFileManagerFile.
*
* @param User $user
* @param File $file
*
* @return mixed
*/
public function update(User $user, File $file)
{
return $user->hasAbility('update-files');
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace App\Policies;
use App\Models\Module;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Database\Eloquent\Model;
class ModulePolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'modules';
/**
* Determine whether the user can create modules.
*
* @param \App\Models\User $user
* @param Module $module
*
* @return mixed
*/
public function create(User $user, Model $module)
{
return $user->hasAbility('create-contents-' . $module->alias);
}
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App\Policies;
use Illuminate\Auth\Access\HandlesAuthorization;
class SettingsPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'settings';
}
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace App\Policies;
use App\Models\Templates\Template;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class TemplatePolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'templates';
/**
* Determine whether the user can view the template.
*
* @param \App\Models\User $user
* @param \App\Template $template
*
* @return mixed
*/
public function copy(User $user)
{
return $user->hasAbility('copy-templates');
}
/**
* Determine whether the user can update the template.
*
* @param \App\Models\User $user
* @param \App\Template $template
*
* @return mixed
*/
public function update(User $user, Template $template)
{
return $user->hasAbility('edit-templates');
}
}
+111
View File
@@ -0,0 +1,111 @@
<?php
namespace App\Policies;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class UserPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'users';
public function before(User $user, $ability)
{
if ($ability === 'view')
return null;
return parent::before($user, $ability);
}
/**
* Can user see other users?
*
* @param User $currentUser
* @param User $user
*
* @return bool
*/
public function view(User $currentUser, User $user) {
// user can se himself
if ($currentUser->id == $user->id)
return true;
return $this->manage($currentUser);
}
/**
* Can current user updates other users (or himself?)
*
* @param User $currentUser
* @param User $user
*
* @return bool
*/
public function update(User $currentUser, User $user)
{
return $currentUser->id == $user->id || $currentUser->hasAbility('update-users');
}
/**
* Can user create other users?
*
* @param User $user
*
* @return bool
*/
public function create(User $user) {
return $user->hasAbility('create-users');
}
/**
* Does current user has permissions for setting permissions to other users?
*
* @param User $currentUser
* @param User $user
*
* @return bool
*/
public function setPermissions(User $currentUser, User $user)
{
if ($currentUser->id == $user->id || $user->role == User::ROLE_VISITOR) {
return false;
}
return $currentUser->hasAbility('set-permissions-users');
}
/**
* Can logged user change status of other users?
*
* @param User $currentUser
* @param User $user
*
* @return bool
*/
public function changeStatus(User $currentUser, User $user)
{
if ($currentUser->id == $user->id) {
return false;
}
return $currentUser->hasAbility('change-status-users');
}
/**
* Can current user change role of other users?
*
* @param User $currentUser
* @param User $user
*
* @return bool
*/
public function changeRole(User $currentUser, User $user)
{
if ($currentUser->id == $user->id) {
return false;
}
return $currentUser->hasAbility('change-role-users');
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace App\Policies;
use App\Models\User;
use App\Models\Widgets\WidgetArea;
use Illuminate\Auth\Access\HandlesAuthorization;
class WidgetAreaPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'widgetareas';
/**
* Determine whether the user can create widgetAreas.
*
* @param \App\Models\User $user
* @return mixed
*/
public function create(User $user)
{
return $user->hasAbility('create-widgetareas');
}
/**
* Determine whether the user can update the widgetArea.
*
* @param \App\Models\User $user
* @param \App\WidgetArea $widgetArea
* @return mixed
*/
public function update(User $user, WidgetArea $widgetArea)
{
return $user->id == $widgetArea->user_id || $user->hasAbility('edit-widgetareas');
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php
namespace App\Policies;
use App\Models\User;
use App\Models\Widgets\Widget;
use Illuminate\Auth\Access\HandlesAuthorization;
class WidgetsPolicy extends BasicPolicy
{
use HandlesAuthorization;
protected $entity = 'widgets';
/**
* Determine whether the user can create widgets.
*
* @param \App\Models\User $user
*
* @return mixed
*/
public function create(User $user)
{
return $user->hasAbility('create-widgets');
}
/**
* Determine whether the user can update the widget.
*
* @param \App\Models\User $user
* @param \App\Widget $widget
*
* @return mixed
*/
public function update(User $user, Widget $widget)
{
return $user->id == $widget->user_id || $user->hasAbility('edit-widgets');
}
public function assign(User $user)
{
return $user->hasAbility('assign-widgets');
}
public function unassign(User $user)
{
return $user->hasAbility('unassign-widgets');
}
}
+3
View File
@@ -25,6 +25,7 @@ use App\CMS\Repositories\Module as ModuleRepository;
use App\CMS\Repositories\Templates\Template as TemplateRepository;
use App\CMS\Widgets\HtmlCode\HtmlCode;
use App\CMS\Widgets\Menu\Menu;
use App\CMS\Widgets\SocialButtons\SocialButtons;
use Barryvdh\Debugbar\ServiceProvider as DebugBarServiceProvider;
use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider;
@@ -106,6 +107,7 @@ class AppServiceProvider extends ServiceProvider
// register all available widgets
$registrator->register(HtmlCode::class);
$registrator->register(Menu::class);
$registrator->register(SocialButtons::class);
}
/**
@@ -118,6 +120,7 @@ class AppServiceProvider extends ServiceProvider
$registrator->register('basic', 'admin/settings.basic', 'admin.settings.parts.basic');
$registrator->register('meta', 'admin/settings.meta', 'admin.settings.parts.meta');
$registrator->register('social', 'admin/settings.socialSites', 'admin.settings.parts.social');
$registrator->register('widgets', 'admin/settings.widgets.title', 'admin.settings.parts.widgets');
}
/**
+37 -9
View File
@@ -2,30 +2,58 @@
namespace App\Providers;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Models\ActionLog\ActionLog;
use App\Models\Content\Content;
use App\Models\FileManager\Directory;
use App\Models\FileManager\File;
use App\Models\Module;
use App\Models\Settings;
use App\Models\Templates\Template;
use App\Models\User;
use App\Models\Widgets\Widget;
use App\Models\Widgets\WidgetArea;
use App\Policies\ActionLogPolicy;
use App\Policies\ContentPolicy;
use App\Policies\DirectoriesPolicy;
use App\Policies\FilesPolicy;
use App\Policies\ModulePolicy;
use App\Policies\SettingsPolicy;
use App\Policies\TemplatePolicy;
use App\Policies\UserPolicy;
use App\Policies\WidgetAreaPolicy;
use App\Policies\WidgetsPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as IlluminateAuthServiceProvider;
class AuthServiceProvider extends ServiceProvider
class AuthServiceProvider extends IlluminateAuthServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
Content::class => ContentPolicy::class,
User::class => UserPolicy::class,
Module::class => ModulePolicy::class,
File::class => FilesPolicy::class,
ActionLog::class => ActionLogPolicy::class,
Template::class => TemplatePolicy::class,
Directory::class => DirectoriesPolicy::class,
Settings::class => SettingsPolicy::class,
Widget::class => WidgetsPolicy::class,
WidgetArea::class => WidgetAreaPolicy::class,
ActionLog::class => ActionLogPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @param \Illuminate\Contracts\Auth\Access\Gate $gate
* @param \Illuminate\Contracts\Auth\Access\Gate $gate
*
* @return void
*/
public function boot(GateContract $gate)
public function boot()
{
$this->registerPolicies($gate);
$this->registerPolicies();
//
}
}
+2 -2
View File
@@ -43,21 +43,21 @@ use App\Listeners\Loggers\LogPublishContent;
use App\Listeners\Loggers\LogRemoveWidgetFromArea;
use App\Listeners\Loggers\LogSetHomepage;
use App\Listeners\Loggers\LogUploadFile;
use App\Listeners\SetDefaultPermissions;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
CreateNewUser::class => [
LogCreatedUser::class,
SetDefaultPermissions::class,
],
EditUser::class => [
LogEditUser::class,
+13 -11
View File
@@ -14,24 +14,27 @@ class RouteServiceProvider extends ServiceProvider
*/
protected $namespace = 'App\Http\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
* @return void
*/
public function boot()
{
parent::boot();
}
/**
* Define the routes for the application.
* @return void
*/
public function map()
{
$this->mapAdminRoutes();
$this->mapWebRoutes();
}
/**
* Define the "admin" routes for the application.
* These routes all receive session state, CSRF protection, etc.
* @return void
*/
protected function mapAdminRoutes()
{
Route::namespace($this->namespace.'\\Admin')
->group(base_path('routes/admin.php'));
}
/**
* Define the "web" routes for the application.
* These routes all receive session state, CSRF protection, etc.
@@ -40,7 +43,6 @@ class RouteServiceProvider extends ServiceProvider
protected function mapWebRoutes()
{
Route::namespace($this->namespace)
->middleware('web')
->group(app_path('Http/routes.php'));
->group(base_path('routes/web.php'));
}
}
+14 -14
View File
@@ -5,7 +5,7 @@ namespace App\Providers;
use App\CMS\Contracts\Repositories\Template as TemplateContract;
use App\CMS\Handlers\Registrators\TemplateRegistrator;
use App\CMS\Helpers\CurrentTemplate;
use App\Models\Module;
use App\CMS\Repositories\Module;
use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider;
@@ -13,19 +13,15 @@ class TemplateServiceProvider extends ServiceProvider
{
public function boot()
{
$template = CurrentTemplate::get();
// ignore running from artisan
if (App::runningInConsole() || App::environment('testing')) {
if (App::runningInConsole() || App::environment('testing') || !$template) {
$this->publishViewResources();
return;
}
$template = CurrentTemplate::get();
if (!$template) {
throw new \ErrorException('Template is not set, cannot continue');
}
// include files
$files = isset($template->moduleSettings->files) ? $template->moduleSettings->files : [];
@@ -43,12 +39,17 @@ class TemplateServiceProvider extends ServiceProvider
$this->registerTemplatePaths($publicTemplates);
}
/**
* Register template paths from public templates
*
* @param $publicTemplates
*/
public function registerTemplatePaths($publicTemplates)
{
$modules = Module::where('enabled', true)
->get()
->pluck('id', 'alias')
->toArray();
$modules = app(Module::class)
->all()
->pluck('id', 'alias')
->toArray();
/**
* @var $registrator TemplateRegistrator
@@ -77,7 +78,6 @@ class TemplateServiceProvider extends ServiceProvider
/**
* Register the service provider.
*
* @return void
*/
public function register()
@@ -94,7 +94,7 @@ class TemplateServiceProvider extends ServiceProvider
return;
}
$templateDir = base_path('templates/' . $template->static_name. '/Resources');
$templateDir = base_path('templates/' . $template->static_name . '/Resources');
$assetsDir = $templateDir . '/' . TemplateContract::ASSETS_DIRECTORY;
$viewsDir = $templateDir . '/views';
Executable → Regular
View File
+4 -11
View File
@@ -7,7 +7,7 @@
"license": "MIT",
"type": "project",
"require": {
"php": ">=5.5.9",
"php": ">=7.0.0",
"laravel/framework": "5.4.*",
"watson/sitemap": "^2.0",
"mcamara/laravel-localization": "^1.1",
@@ -37,16 +37,9 @@
}
},
"scripts": {
"post-install-cmd": [
"php artisan clear-compiled",
"php artisan optimize"
],
"pre-update-cmd": [
"php artisan clear-compiled"
],
"post-update-cmd": [
"php artisan optimize"
]
"post-install-cmd": [],
"pre-update-cmd": [],
"post-update-cmd": []
},
"config": {
"preferred-install": "dist",
Generated
+120 -110
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "55d3fc4c8ded52b3b1a3fdb720787538",
"content-hash": "c1d95b3a28c04323c45a7fab876aadb7",
"packages": [
{
"name": "doctrine/inflector",
@@ -223,7 +223,7 @@
"laravel5",
"recaptcha"
],
"time": "2017-04-06 17:10:49"
"time": "2017-04-06T17:10:49+00:00"
},
{
"name": "guzzlehttp/psr7",
@@ -288,7 +288,7 @@
"uri",
"url"
],
"time": "2017-07-17 09:11:21"
"time": "2017-07-17T09:11:21+00:00"
},
{
"name": "intervention/image",
@@ -366,12 +366,12 @@
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "e59981477f0b710dd40708952e10f96fbf1f5361"
"reference": "f0d417bfa7a2e78d70c7382bfc51fe02321f0a3e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/e59981477f0b710dd40708952e10f96fbf1f5361",
"reference": "e59981477f0b710dd40708952e10f96fbf1f5361",
"url": "https://api.github.com/repos/laravel/framework/zipball/f0d417bfa7a2e78d70c7382bfc51fe02321f0a3e",
"reference": "f0d417bfa7a2e78d70c7382bfc51fe02321f0a3e",
"shasum": ""
},
"require": {
@@ -487,7 +487,7 @@
"framework",
"laravel"
],
"time": "2017-08-01T12:58:10+00:00"
"time": "2017-08-08T16:36:51+00:00"
},
{
"name": "laravelcollective/html",
@@ -549,12 +549,12 @@
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "988626314a28f34e682f374162b67deb855af2d1"
"reference": "d3ce2f8f409ac7d01dea0fd03d30f1e466bdd957"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/988626314a28f34e682f374162b67deb855af2d1",
"reference": "988626314a28f34e682f374162b67deb855af2d1",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/d3ce2f8f409ac7d01dea0fd03d30f1e466bdd957",
"reference": "d3ce2f8f409ac7d01dea0fd03d30f1e466bdd957",
"shasum": ""
},
"require": {
@@ -624,24 +624,24 @@
"sftp",
"storage"
],
"time": "2017-07-29T19:03:34+00:00"
"time": "2017-08-08T08:44:14+00:00"
},
{
"name": "mcamara/laravel-localization",
"version": "v1.2.6",
"version": "v1.2.7",
"source": {
"type": "git",
"url": "https://github.com/mcamara/laravel-localization.git",
"reference": "2177e05d5cf35efea3a43c0f1785a3edd816347f"
"reference": "5f7e0e646d5c2374b8adaf1757599e043cd0994d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mcamara/laravel-localization/zipball/2177e05d5cf35efea3a43c0f1785a3edd816347f",
"reference": "2177e05d5cf35efea3a43c0f1785a3edd816347f",
"url": "https://api.github.com/repos/mcamara/laravel-localization/zipball/5f7e0e646d5c2374b8adaf1757599e043cd0994d",
"reference": "5f7e0e646d5c2374b8adaf1757599e043cd0994d",
"shasum": ""
},
"require": {
"laravel/framework": "~5.2",
"laravel/framework": "~5.2, ~5.3, ~5.4",
"php": ">=5.6.0"
},
"require-dev": {
@@ -649,6 +649,16 @@
"phpunit/phpunit": "5.4.*"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Mcamara\\LaravelLocalization\\LaravelLocalizationServiceProvider"
],
"aliases": {
"LaravelLocalization": "Mcamara\\LaravelLocalization\\Facades\\LaravelLocalization"
}
}
},
"autoload": {
"classmap": [],
"psr-0": {
@@ -673,7 +683,7 @@
"localization",
"php"
],
"time": "2017-05-18T10:22:35+00:00"
"time": "2017-08-08T04:41:28+00:00"
},
{
"name": "monolog/monolog",
@@ -856,26 +866,26 @@
"source": {
"type": "git",
"url": "https://github.com/nWidart/laravel-menus.git",
"reference": "4ccc94ea47f0be812488f743f22662e6f446f53b"
"reference": "71a5fb430ab1ae19773f1c47625f854c612afea1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nWidart/laravel-menus/zipball/4ccc94ea47f0be812488f743f22662e6f446f53b",
"reference": "4ccc94ea47f0be812488f743f22662e6f446f53b",
"url": "https://api.github.com/repos/nWidart/laravel-menus/zipball/71a5fb430ab1ae19773f1c47625f854c612afea1",
"reference": "71a5fb430ab1ae19773f1c47625f854c612afea1",
"shasum": ""
},
"require": {
"illuminate/config": "5.2.*|5.3.*|5.4.*",
"illuminate/support": "5.2.*|5.3.*|5.4.*",
"illuminate/view": "5.2.*|5.3.*|5.4.*",
"laravelcollective/html": "5.2.*|5.3.*|5.4.*",
"php": ">=5.5.9"
"illuminate/config": "5.4.*",
"illuminate/support": "5.4.*",
"illuminate/view": "5.4.*",
"laravelcollective/html": "5.4.*",
"php": ">=5.6.4"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^1.11",
"friendsofphp/php-cs-fixer": "^2.4",
"mockery/mockery": "~0.9",
"orchestra/testbench": "3.2.*| 3.3.*|3.4.*",
"phpro/grumphp": "^0.9.1",
"orchestra/testbench": "3.4.*",
"phpro/grumphp": "^0.11",
"phpunit/phpunit": "~5.7"
},
"type": "library",
@@ -916,7 +926,7 @@
"nav",
"navigation"
],
"time": "2017-06-02 09:42:52"
"time": "2017-08-06T15:28:13+00:00"
},
{
"name": "paragonie/random_compat",
@@ -1014,7 +1024,7 @@
"request",
"response"
],
"time": "2016-08-06 14:39:51"
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/log",
@@ -1069,12 +1079,12 @@
"source": {
"type": "git",
"url": "https://github.com/ramsey/uuid.git",
"reference": "c479cdd42f53c98b7f93209131c37b436503f808"
"reference": "0ef23d1b10cf1bc576e9d865a7e9c47982c5715e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/c479cdd42f53c98b7f93209131c37b436503f808",
"reference": "c479cdd42f53c98b7f93209131c37b436503f808",
"url": "https://api.github.com/repos/ramsey/uuid/zipball/0ef23d1b10cf1bc576e9d865a7e9c47982c5715e",
"reference": "0ef23d1b10cf1bc576e9d865a7e9c47982c5715e",
"shasum": ""
},
"require": {
@@ -1143,7 +1153,7 @@
"identifier",
"uuid"
],
"time": "2017-07-31T06:30:25+00:00"
"time": "2017-08-04T13:39:04+00:00"
},
{
"name": "swiftmailer/swiftmailer",
@@ -1151,12 +1161,12 @@
"source": {
"type": "git",
"url": "https://github.com/swiftmailer/swiftmailer.git",
"reference": "4441f8a61006f81138aa4a3e5a6cb8330e5160f2"
"reference": "e8a71970b33410591f664f72dba6bd755fa7bf55"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/4441f8a61006f81138aa4a3e5a6cb8330e5160f2",
"reference": "4441f8a61006f81138aa4a3e5a6cb8330e5160f2",
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/e8a71970b33410591f664f72dba6bd755fa7bf55",
"reference": "e8a71970b33410591f664f72dba6bd755fa7bf55",
"shasum": ""
},
"require": {
@@ -1197,7 +1207,7 @@
"mail",
"mailer"
],
"time": "2017-05-19T18:47:58+00:00"
"time": "2017-08-10T12:25:50+00:00"
},
{
"name": "symfony/console",
@@ -1205,16 +1215,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "e7f890da834c1bdd395df1f39cf3656c5f1f23fa"
"reference": "0e283478c2d68c9bf9cc52592ad1ef1834083a85"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/e7f890da834c1bdd395df1f39cf3656c5f1f23fa",
"reference": "e7f890da834c1bdd395df1f39cf3656c5f1f23fa",
"url": "https://api.github.com/repos/symfony/console/zipball/0e283478c2d68c9bf9cc52592ad1ef1834083a85",
"reference": "0e283478c2d68c9bf9cc52592ad1ef1834083a85",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"php": "^5.5.9|>=7.0.8",
"symfony/debug": "~2.8|~3.0|~4.0",
"symfony/polyfill-mbstring": "~1.0"
},
@@ -1267,7 +1277,7 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2017-07-31T09:53:49+00:00"
"time": "2017-08-10T07:07:17+00:00"
},
{
"name": "symfony/css-selector",
@@ -1328,16 +1338,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
"reference": "97592888b907532a9225f6e84a620e642d7093df"
"reference": "50bda5b4b8641616d45254c6855bcd45f2f64187"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/debug/zipball/97592888b907532a9225f6e84a620e642d7093df",
"reference": "97592888b907532a9225f6e84a620e642d7093df",
"url": "https://api.github.com/repos/symfony/debug/zipball/50bda5b4b8641616d45254c6855bcd45f2f64187",
"reference": "50bda5b4b8641616d45254c6855bcd45f2f64187",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"php": "^5.5.9|>=7.0.8",
"psr/log": "~1.0"
},
"conflict": {
@@ -1376,7 +1386,7 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"time": "2017-07-28T15:30:20+00:00"
"time": "2017-08-10T07:07:17+00:00"
},
{
"name": "symfony/event-dispatcher",
@@ -1447,16 +1457,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "295fa37f13dbc4bba200680d2f4ae2c4a1f77709"
"reference": "bf0450cfe7282c5f06539c4733ba64273e91e918"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/295fa37f13dbc4bba200680d2f4ae2c4a1f77709",
"reference": "295fa37f13dbc4bba200680d2f4ae2c4a1f77709",
"url": "https://api.github.com/repos/symfony/finder/zipball/bf0450cfe7282c5f06539c4733ba64273e91e918",
"reference": "bf0450cfe7282c5f06539c4733ba64273e91e918",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
"php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
@@ -1488,7 +1498,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"time": "2017-06-01T21:02:15+00:00"
"time": "2017-08-03T09:34:20+00:00"
},
{
"name": "symfony/http-foundation",
@@ -1496,16 +1506,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "0c4bf18214f040537c47ff8ecabdf10278bdf689"
"reference": "b7e34ba2eb4d0ac9eb0c2d46b20d9136fde5fa66"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/0c4bf18214f040537c47ff8ecabdf10278bdf689",
"reference": "0c4bf18214f040537c47ff8ecabdf10278bdf689",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/b7e34ba2eb4d0ac9eb0c2d46b20d9136fde5fa66",
"reference": "b7e34ba2eb4d0ac9eb0c2d46b20d9136fde5fa66",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"php": "^5.5.9|>=7.0.8",
"symfony/polyfill-mbstring": "~1.1"
},
"require-dev": {
@@ -1541,7 +1551,7 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"time": "2017-07-21T11:05:08+00:00"
"time": "2017-08-10T07:07:17+00:00"
},
{
"name": "symfony/http-kernel",
@@ -1549,16 +1559,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "8913930a3f122b4b223bc41700fde77a815d87ac"
"reference": "42dab8a691f7d0d00b496ba39202f017f286cec3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/8913930a3f122b4b223bc41700fde77a815d87ac",
"reference": "8913930a3f122b4b223bc41700fde77a815d87ac",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/42dab8a691f7d0d00b496ba39202f017f286cec3",
"reference": "42dab8a691f7d0d00b496ba39202f017f286cec3",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"php": "^5.5.9|>=7.0.8",
"psr/log": "~1.0",
"symfony/debug": "~2.8|~3.0|~4.0",
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
@@ -1566,7 +1576,7 @@
},
"conflict": {
"symfony/config": "<2.8",
"symfony/dependency-injection": "<3.3",
"symfony/dependency-injection": "<3.4",
"symfony/var-dumper": "<3.3",
"twig/twig": "<1.34|<2.4,>=2"
},
@@ -1577,7 +1587,7 @@
"symfony/config": "~2.8|~3.0|~4.0",
"symfony/console": "~2.8|~3.0|~4.0",
"symfony/css-selector": "~2.8|~3.0|~4.0",
"symfony/dependency-injection": "~3.3|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/dom-crawler": "~2.8|~3.0|~4.0",
"symfony/expression-language": "~2.8|~3.0|~4.0",
"symfony/finder": "~2.8|~3.0|~4.0",
@@ -1626,7 +1636,7 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
"time": "2017-07-15T08:52:56+00:00"
"time": "2017-08-09T16:53:01+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@@ -1693,16 +1703,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "aeea12fe8abbf2f6ccb917c0037a7664d0e20b51"
"reference": "9794f948d9af3be0157185051275d78b24d68b92"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/aeea12fe8abbf2f6ccb917c0037a7664d0e20b51",
"reference": "aeea12fe8abbf2f6ccb917c0037a7664d0e20b51",
"url": "https://api.github.com/repos/symfony/process/zipball/9794f948d9af3be0157185051275d78b24d68b92",
"reference": "9794f948d9af3be0157185051275d78b24d68b92",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
"php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
@@ -1734,7 +1744,7 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"time": "2017-07-15T08:52:56+00:00"
"time": "2017-08-03T09:34:20+00:00"
},
{
"name": "symfony/routing",
@@ -1742,16 +1752,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
"reference": "5d8d766e4db7eda52ec886b1584538808f8b718e"
"reference": "1513f0bec2de03bee38a23a262bae9bfae4a5c26"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/5d8d766e4db7eda52ec886b1584538808f8b718e",
"reference": "5d8d766e4db7eda52ec886b1584538808f8b718e",
"url": "https://api.github.com/repos/symfony/routing/zipball/1513f0bec2de03bee38a23a262bae9bfae4a5c26",
"reference": "1513f0bec2de03bee38a23a262bae9bfae4a5c26",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
"php": "^5.5.9|>=7.0.8"
},
"conflict": {
"symfony/config": "<2.8",
@@ -1812,7 +1822,7 @@
"uri",
"url"
],
"time": "2017-07-26T06:46:38+00:00"
"time": "2017-08-03T09:34:20+00:00"
},
{
"name": "symfony/translation",
@@ -1820,16 +1830,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "eca09e9af11fe317f313d2915e1573a01609fcb9"
"reference": "62bb068e004874bbe39624101e1aae70ca7c05cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/eca09e9af11fe317f313d2915e1573a01609fcb9",
"reference": "eca09e9af11fe317f313d2915e1573a01609fcb9",
"url": "https://api.github.com/repos/symfony/translation/zipball/62bb068e004874bbe39624101e1aae70ca7c05cd",
"reference": "62bb068e004874bbe39624101e1aae70ca7c05cd",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"php": "^5.5.9|>=7.0.8",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
@@ -1879,7 +1889,7 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"time": "2017-07-06T06:49:25+00:00"
"time": "2017-08-03T12:04:31+00:00"
},
{
"name": "symfony/var-dumper",
@@ -1887,16 +1897,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "b7e0da3cdcf72a472eeeb3193105cf4902433df1"
"reference": "c83889ce881bc16a4c23d7f5dd42b51deb0333a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/b7e0da3cdcf72a472eeeb3193105cf4902433df1",
"reference": "b7e0da3cdcf72a472eeeb3193105cf4902433df1",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/c83889ce881bc16a4c23d7f5dd42b51deb0333a2",
"reference": "c83889ce881bc16a4c23d7f5dd42b51deb0333a2",
"shasum": ""
},
"require": {
"php": ">=5.5.9",
"php": "^5.5.9|>=7.0.8",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
@@ -1948,7 +1958,7 @@
"debug",
"dump"
],
"time": "2017-07-28T15:30:20+00:00"
"time": "2017-08-09T16:38:43+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@@ -2003,12 +2013,12 @@
"source": {
"type": "git",
"url": "https://github.com/vlucas/phpdotenv.git",
"reference": "7ac2c1cef304f5bd5a8d40750fbcbdd49333b9e5"
"reference": "3dd3d8f90e6604e75cca48ec32b033b50b05135b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/7ac2c1cef304f5bd5a8d40750fbcbdd49333b9e5",
"reference": "7ac2c1cef304f5bd5a8d40750fbcbdd49333b9e5",
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3dd3d8f90e6604e75cca48ec32b033b50b05135b",
"reference": "3dd3d8f90e6604e75cca48ec32b033b50b05135b",
"shasum": ""
},
"require": {
@@ -2045,7 +2055,7 @@
"env",
"environment"
],
"time": "2017-02-03T22:05:04+00:00"
"time": "2017-08-08T20:02:34+00:00"
},
{
"name": "watson/sitemap",
@@ -2275,12 +2285,12 @@
"source": {
"type": "git",
"url": "https://github.com/fzaninotto/Faker.git",
"reference": "ea4244d0354634e020042278478c9842524b0459"
"reference": "e70d9612d9108ec07476f7c304f14b8e583b6494"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fzaninotto/Faker/zipball/ea4244d0354634e020042278478c9842524b0459",
"reference": "ea4244d0354634e020042278478c9842524b0459",
"url": "https://api.github.com/repos/fzaninotto/Faker/zipball/e70d9612d9108ec07476f7c304f14b8e583b6494",
"reference": "e70d9612d9108ec07476f7c304f14b8e583b6494",
"shasum": ""
},
"require": {
@@ -2317,7 +2327,7 @@
"faker",
"fixtures"
],
"time": "2017-07-19T13:05:01+00:00"
"time": "2017-08-10T09:58:44+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@@ -2552,22 +2562,22 @@
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "3.2.0",
"version": "3.2.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "46f7e8bb075036c92695b15a1ddb6971c751e585"
"reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/46f7e8bb075036c92695b15a1ddb6971c751e585",
"reference": "46f7e8bb075036c92695b15a1ddb6971c751e585",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157",
"reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157",
"shasum": ""
},
"require": {
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0@dev",
"phpdocumentor/type-resolver": "^0.4.0",
"phpdocumentor/type-resolver": "^0.3.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
@@ -2593,20 +2603,20 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2017-07-15T11:38:20+00:00"
"time": "2017-08-08T06:39:58+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "0.4.0",
"version": "0.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
"reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773",
"reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773",
"shasum": ""
},
"require": {
@@ -2640,7 +2650,7 @@
"email": "me@mikevanriel.com"
}
],
"time": "2017-07-14T14:27:02+00:00"
"time": "2017-06-03T08:32:36+00:00"
},
{
"name": "phpspec/prophecy",
@@ -3515,16 +3525,16 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "8ccc03269a0e2a248c0daff5ad20050388cc07c4"
"reference": "1395ddba6f65bf46cdf1d80d59223cbab8ff3ccc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/8ccc03269a0e2a248c0daff5ad20050388cc07c4",
"reference": "8ccc03269a0e2a248c0daff5ad20050388cc07c4",
"url": "https://api.github.com/repos/symfony/yaml/zipball/1395ddba6f65bf46cdf1d80d59223cbab8ff3ccc",
"reference": "1395ddba6f65bf46cdf1d80d59223cbab8ff3ccc",
"shasum": ""
},
"require": {
"php": ">=5.5.9"
"php": "^5.5.9|>=7.0.8"
},
"require-dev": {
"symfony/console": "~2.8|~3.0|~4.0"
@@ -3562,7 +3572,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2017-07-26T06:46:38+00:00"
"time": "2017-08-04T13:29:48+00:00"
},
{
"name": "webmozart/assert",
@@ -3624,7 +3634,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.5.9"
"php": ">=7.0.0"
},
"platform-dev": []
}
+3 -4
View File
@@ -153,10 +153,10 @@ return [
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
Illuminate\Notifications\NotificationServiceProvider::class,
Mcamara\LaravelLocalization\LaravelLocalizationServiceProvider::class,
\App\ModuleManager\Providers\ModuleManager::class,
\App\CMS\ModuleManager\Providers\ModuleManager::class,
\Nwidart\Menus\MenusServiceProvider::class,
// Pingpong\Menus\MenusServiceProvider::class,
Franzose\ClosureTable\ClosureTableServiceProvider::class,
\Watson\Sitemap\SitemapServiceProvider::class,
Intervention\Image\ImageServiceProvider::class,
@@ -185,7 +185,6 @@ return [
*/
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
@@ -221,7 +220,7 @@ return [
'View' => Illuminate\Support\Facades\View::class,
'Recaptcha' => Greggilbert\Recaptcha\Facades\Recaptcha::class,
'Shortcode' => Webwizo\Shortcodes\Facades\Shortcode::class,
'Notification' => Illuminate\Support\Facades\Notification::class,
],
];
+18
View File
@@ -111,4 +111,22 @@ return [
'sendmail' => '/usr/sbin/sendmail -bs',
/*
|--------------------------------------------------------------------------
| Markdown Mail Settings
|--------------------------------------------------------------------------
|
| If you are using Markdown based email rendering, you may configure your
| theme and component paths here, allowing you to customize the design
| of the emails. Or, you may simply stick with the Laravel defaults!
|
*/
'markdown' => [
'theme' => 'default',
'paths' => [
resource_path('views/vendor/mail'),
],
]
];
+1 -1
View File
@@ -5,6 +5,6 @@ return [
'paths' => [
'modules' => base_path('modules'),
'assets' => public_path('modules'),
'stubs' => base_path('app/ModuleManager/Stubs'),
'stubs' => base_path('app/CMS/Modules/Stubs'),
]
];
@@ -0,0 +1,65 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePermissionsTable extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up()
{
Schema::create('permissions', function (Blueprint $table) {
$table->increments('id');
$table->integer('parent_id')
->nullable()
->unsigned();
$table->string('string_id')
->unique();
$table->string('name');
$table->string('group')
->nullable(true);
});
Schema::table('permissions', function (Blueprint $table) {
$table->foreign('parent_id')
->references('id')
->on('permissions')
->onDelete('set null')
->onUpdate('cascade');
});
Schema::create('user_has_permissions', function (Blueprint $table) {
$table->integer('user_id');
$table->integer('permission_id')
->unsigned();
});
Schema::table('user_has_permissions', function (Blueprint $table) {
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade')
->onUpdate('cascade');
$table->foreign('permission_id')
->references('id')
->on('permissions')
->onDelete('cascade')
->onUpdate('cascade');
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
Schema::drop('user_has_permissions');
Schema::drop('permissions');
}
}
@@ -0,0 +1,66 @@
<?php
use App\Models\Permissions\Permission;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDefaultPermissions extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up()
{
Schema::table('permissions', function (Blueprint $table) {
$table->boolean('default')
->default(false);
});
Permission::getQuery()
->delete();
$permissions = [
'contents' => ['create', 'update', 'update-all', 'delete', 'set-homepage', 'publish', 'draft', 'protect', 'view-history'],
'users' => ['create', 'update', 'delete', 'set-permissions', 'change-status', 'change-role'],
'files' => ['upload', 'update', 'delete', 'move-to-directories'],
'directories' => ['create', 'edit', 'delete'],
'widgetareas' => ['create', 'edit', 'delete'],
'widgets' => ['create', 'edit', 'delete', 'assign', 'unassign'],
'templates' => ['copy', 'edit'],
'actions' => [],
'settings' => []
];
foreach ($permissions as $entity => $abilities) {
$parent = Permission::create([
'name' => 'admin/permissions.' . $entity . '.management',
'string_id' => $entity . '-management',
'group' => $entity,
'default' => true,
]);
foreach ($abilities as $ability) {
Permission::create([
'name' => 'admin/permissions.' . $entity . '.' . $ability,
'string_id' => $ability . '-' . $entity,
'group' => $entity,
'parent_id' => $parent->id,
'default' => true,
]);
}
}
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
Schema::table('permissions', function (Blueprint $table) {
$table->dropColumn('default');
});
}
}

Some files were not shown because too many files have changed in this diff Show More