Skip to content

Commit

Permalink
Scope admin items/collections by user frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
rastislav-chynoransky committed Aug 19, 2024
1 parent 7b95aa7 commit f0e8455
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 132 deletions.
10 changes: 9 additions & 1 deletion app/Http/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Http;

use App\Http\Middleware\ApplyFrontendScope;
use App\Http\Middleware\ConfigureFrontendFromUser;
use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
Expand Down Expand Up @@ -44,9 +46,15 @@ class Kernel extends HttpKernel
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\AcceptLanguage::class,
\App\Http\Middleware\ConfigureFrontendFromRequest::class,
\App\Http\Middleware\ConfigureFrontendFromHeader::class,
\App\Http\Middleware\ApplyFrontendScope::class,
],

'admin' => [
'auth',
ConfigureFrontendFromUser::class,
ApplyFrontendScope::class,
],
];

/**
Expand Down
8 changes: 6 additions & 2 deletions app/Http/Middleware/ApplyFrontendScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ class ApplyFrontendScope
{
public function handle(Request $request, \Closure $next): Response
{
Collection::addGlobalScope('frontend', fn ($query) => $query->whereJsonContains('collections.frontends', Frontend::get()));
Item::addGlobalScope('frontend', fn ($query) => $query->whereJsonContains('items.frontends', Frontend::get()));
$frontend = Frontend::get();

if ($frontend) {
Collection::addGlobalScope('frontend', fn($query) => $query->whereJsonContains('collections.frontends', $frontend));
Item::addGlobalScope('frontend', fn($query) => $query->whereJsonContains('items.frontends', $frontend));
}

return $next($request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ConfigureFrontendFromRequest
class ConfigureFrontendFromHeader
{
public function handle(Request $request, Closure $next): Response
{
Expand Down
23 changes: 23 additions & 0 deletions app/Http/Middleware/ConfigureFrontendFromUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Http\Middleware;

use App\Enums\FrontendEnum;
use App\Facades\Frontend;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class ConfigureFrontendFromUser
{
public function handle(Request $request, Closure $next): Response
{
$frontend = !$request->user()->can_administer
? FrontendEnum::from($request->user()->frontend)
: null;

Frontend::set($frontend);

return $next($request);
}
}
6 changes: 5 additions & 1 deletion app/Providers/RouteServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ public function boot()
->prefix('api')
->group(base_path('routes/api.php'));

Route::middleware('web')->group(base_path('routes/web.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));

Route::middleware(['web', 'admin'])
->group(base_path('routes/admin.php'));
});
}

Expand Down
6 changes: 3 additions & 3 deletions app/Services/Frontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@

class Frontend
{
public function __construct(private FrontendEnum $current)
public function __construct(private ?FrontendEnum $current)
{
}

public function set(FrontendEnum $frontend): void
public function set(?FrontendEnum $frontend): void
{
$this->current = $frontend;
}

public function get(): FrontendEnum
public function get(): ?FrontendEnum
{
return $this->current;
}
Expand Down
3 changes: 3 additions & 0 deletions database/factories/UserFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Database\Factories;

use App\Enums\FrontendEnum;
use App\Services\Frontend;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

Expand All @@ -23,6 +25,7 @@ public function definition()
'email' => fake()->safeEmail(),
'password' => bcrypt(Str::random(10)),
'remember_token' => Str::random(10),
'frontend' => FrontendEnum::WEBUMENIA->value,
];
}
}
99 changes: 99 additions & 0 deletions routes/admin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

use App\Http\Controllers\Admin\Authority\RoleTranslationsController;
use App\Http\Controllers\Admin\FeaturedArtworkController;
use App\Http\Controllers\Admin\FeaturedPieceController;
use App\Http\Controllers\Admin\ItemTagsController;
use App\Http\Controllers\Admin\ShuffledItemController;
use App\Http\Controllers\AdminController;
use App\Http\Controllers\ArticleController;
use App\Http\Controllers\AuthController;
use App\Http\Controllers\AuthorityController;
use App\Http\Controllers\CollectionController;
use App\Http\Controllers\ImportController;
use App\Http\Controllers\ItemController;
use App\Http\Controllers\NoticeController;
use App\Http\Controllers\RedirectController;
use App\Http\Controllers\SketchbookController;
use App\Http\Controllers\SpiceHarvesterController;
use App\Http\Controllers\UserController;
use App\Item;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Session;
use Rap2hpoutre\LaravelLogViewer\LogViewerController;
use UniSharp\LaravelFilemanager\Lfm;

Route::get('admin', [AdminController::class, 'index']);
Route::get('logout', [AuthController::class, 'logout']);
Route::resource('imports', ImportController::class);
Route::get('imports/{import}/launch', [ImportController::class, 'launch']);

Route::group(['middleware' => ['can:edit']], function () {
Route::get('item/search', [ItemController::class, 'search'])->name('item.search');
Route::get('item', [ItemController::class, 'index'])->name('item.index');
Route::resource('item/tags', ItemTagsController::class)->names('item-tags');
Route::get('item/{id}/show', [ItemController::class, 'show'])->name('item.show');
Route::match(['get', 'post'], 'item/create', [ItemController::class, 'create'])->name('item.create');
Route::match(['get', 'post'], 'item/{id}/edit', [ItemController::class, 'edit'])->name('item.edit');
Route::post('item/destroySelected', [ItemController::class, 'destroySelected']);
Route::post('dielo/{id}/addTags', function($id) {
$item = Item::find($id);
$newTags = Request::input('tags');

if (empty($newTags)) {
Session::flash('message', trans('Neboli zadadné žiadne nové tagy.') );
return Redirect::to($item->getUrl());
}

// @TODO take back captcha if opened for all users
foreach ($newTags as $newTag) {
$item->tag($newTag);
}

Session::flash( 'message', trans('Bolo pridaných ' . count($newTags) . ' tagov. Ďakujeme!') );

return Redirect::to($item->getUrl());
});

Route::resource('article', ArticleController::class);
Route::get('collection/{collection_id}/detach/{item_id}', [CollectionController::class, 'detach']);
Route::post('collection/fill', [CollectionController::class, 'fill']);
Route::post('collection/sort', [CollectionController::class, 'sort']);
Route::resource('collection', CollectionController::class);
Route::resource('user', UserController::class);

Route::group(['prefix' => 'laravel-filemanager'], function () {
Lfm::routes();
});
});

Route::group(['middleware' => ['can:administer']], function () {
Route::resource('featured-pieces', FeaturedPieceController::class);
Route::resource('featured-artworks', FeaturedArtworkController::class);
Route::resource('shuffled-items', ShuffledItemController::class);
Route::get('harvests/launch/{id}', [SpiceHarvesterController::class, 'launch']);
Route::get('harvests/harvestFailed/{id}', [SpiceHarvesterController::class, 'harvestFailed']);
Route::get('harvests/orphaned/{id}', [SpiceHarvesterController::class, 'orphaned']);
Route::get('harvests/{record_id}/refreshRecord/', [SpiceHarvesterController::class, 'refreshRecord']);
Route::resource('harvests', SpiceHarvesterController::class);
Route::get('item/backup', [ItemController::class, 'backup']);
Route::get('item/geodata', [ItemController::class, 'geodata']);
Route::post('item/refreshSelected', [ItemController::class, 'refreshSelected']);
Route::get('item/reindex', [ItemController::class, 'reindex']);
Route::get('authority/reindex', [AuthorityController::class, 'reindex']);
Route::post('authority/destroySelected', [AuthorityController::class, 'destroySelected']);
Route::get('authority/search', [AuthorityController::class, 'search']);
Route::get('authority/role-translations', [RoleTranslationsController::class, 'index'])->name(
'authority.role-translations.index'
);
Route::get('authority/role-translations/download', [RoleTranslationsController::class, 'download'])->name(
'authority.role-translations.download'
);
Route::resource('authority', AuthorityController::class);
Route::resource('sketchbook', SketchbookController::class);
Route::resource('notices', NoticeController::class);
Route::resource('redirects', RedirectController::class);
Route::get('logs', [LogViewerController::class, 'index']);
});
124 changes: 0 additions & 124 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,19 @@
use App\Elasticsearch\Repositories\ItemRepository;
use App\Facades\Experiment;
use App\Filter\ItemFilter;
use App\Http\Controllers\Admin\Authority\RoleTranslationsController;
use App\Http\Controllers\Admin\FeaturedArtworkController;
use App\Http\Controllers\Admin\FeaturedPieceController;
use App\Http\Controllers\Admin\ItemTagsController;
use App\Http\Controllers\Admin\ShuffledItemController;
use App\Http\Controllers\AdminController;
use App\Http\Controllers\ArticleController;
use App\Http\Controllers\AuthController;
use App\Http\Controllers\AuthorController;
use App\Http\Controllers\AuthorityController;
use App\Http\Controllers\CatalogController;
use App\Http\Controllers\ClanokController;
use App\Http\Controllers\CollectionController;
use App\Http\Controllers\EducationalArticleController;
use App\Http\Controllers\HomeController;
use App\Http\Controllers\ImageController;
use App\Http\Controllers\ImportController;
use App\Http\Controllers\ItemController;
use App\Http\Controllers\KolekciaController;
use App\Http\Controllers\NoticeController;
use App\Http\Controllers\PatternlibController;
use App\Http\Controllers\RedirectController;
use App\Http\Controllers\SharedUserCollectionController;
use App\Http\Controllers\SketchbookController;
use App\Http\Controllers\SkicareController;
use App\Http\Controllers\SpiceHarvesterController;
use App\Http\Controllers\UserCollectionController;
use App\Http\Controllers\NewCatalogController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\ZoomController;
use App\Http\Middleware\ApplyFrontendScope;
use App\Http\Middleware\RedirectLegacyCatalogRequest;
Expand All @@ -59,19 +43,6 @@
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use Rap2hpoutre\LaravelLogViewer\LogViewerController;

Route::group(['domain' => 'media.webumenia.{tld}'], function () {
Route::get('/', function ($tld) {
return "webumenia media server";
});
Route::get('{id}', function ($tld, $id) {
$item = Item::find($id);
if ($item) {
return config('app.url') . $item->getImagePath();
}
});
});

Route::group([
'prefix' => LaravelLocalization::setLocale(),
Expand Down Expand Up @@ -405,98 +376,3 @@ function()
Route::get('login', [AuthController::class, 'getLogin']);
Route::post('login', [AuthController::class, 'postLogin']);
});

Route::group(['middleware' => ['auth']], function () {
Route::get('admin', [AdminController::class, 'index']);
Route::get('logout', [AuthController::class, 'logout']);
Route::resource('imports', ImportController::class);
Route::get('imports/{import}/launch', [ImportController::class, 'launch']);
});

Route::group(['middleware' => ['auth', 'can:edit']], function () {
Route::get('item/search', [ItemController::class, 'search'])->name('item.search');
Route::get('item', [ItemController::class, 'index'])->name('item.index');
Route::resource('item/tags', ItemTagsController::class)->names('item-tags');
Route::get('item/{id}/show', [ItemController::class, 'show'])->name('item.show');
Route::match(['get', 'post'], 'item/create', [ItemController::class, 'create'])->name('item.create');
Route::match(['get', 'post'], 'item/{id}/edit', [ItemController::class, 'edit'])->name('item.edit');

Route::post('item/destroySelected', [ItemController::class, 'destroySelected']);

Route::post('dielo/{id}/addTags', function($id)
{
$item = Item::find($id);
$newTags = Request::input('tags');

if (empty($newTags)) {
Session::flash( 'message', trans('Neboli zadadné žiadne nové tagy.') );
return Redirect::to($item->getUrl());
}

// @TODO take back captcha if opened for all users
foreach ($newTags as $newTag) {
$item->tag($newTag);
}

Session::flash( 'message', trans('Bolo pridaných ' . count($newTags) . ' tagov. Ďakujeme!') );

// validate that user is human with recaptcha
// till it's for authorised users only, temporary disable
/*
$secret = config('app.google_recaptcha_secret');
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->verify($_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR']);
if ($resp->isSuccess()) {
// add new tags
foreach ($newTags as $newTag) {
$item->tag($newTag);
}
} else {
// validation unsuccessful
return Redirect::to($item->getUrl());
}
*/

return Redirect::to($item->getUrl());
});

Route::resource('article', ArticleController::class);
Route::get('collection/{collection_id}/detach/{item_id}', [CollectionController::class, 'detach']);
Route::post('collection/fill', [CollectionController::class, 'fill']);
Route::post('collection/sort', [CollectionController::class, 'sort']);
Route::resource('collection', CollectionController::class);
Route::resource('user', UserController::class);

Route::group(['prefix' => 'laravel-filemanager'], function () {
\UniSharp\LaravelFilemanager\Lfm::routes();
});
});

Route::group(['middleware' => ['auth', 'can:administer']], function () {
Route::resource('featured-pieces', FeaturedPieceController::class);
Route::resource('featured-artworks', FeaturedArtworkController::class);
Route::resource('shuffled-items', ShuffledItemController::class);
Route::get('harvests/launch/{id}', [SpiceHarvesterController::class, 'launch']);
Route::get('harvests/harvestFailed/{id}', [SpiceHarvesterController::class, 'harvestFailed']);
Route::get('harvests/orphaned/{id}', [SpiceHarvesterController::class, 'orphaned']);
Route::get('harvests/{record_id}/refreshRecord/', [SpiceHarvesterController::class, 'refreshRecord']);
Route::resource('harvests', SpiceHarvesterController::class);
Route::get('item/backup', [ItemController::class, 'backup']);
Route::get('item/geodata', [ItemController::class, 'geodata']);
Route::post('item/refreshSelected', [ItemController::class, 'refreshSelected']);
Route::get('item/reindex', [ItemController::class, 'reindex']);
Route::get('authority/reindex', [AuthorityController::class, 'reindex']);
Route::post('authority/destroySelected', [AuthorityController::class, 'destroySelected']);
Route::get('authority/search', [AuthorityController::class, 'search']);
Route::get('authority/role-translations', [RoleTranslationsController::class, 'index'])->name(
'authority.role-translations.index'
);
Route::get('authority/role-translations/download', [RoleTranslationsController::class, 'download'])->name(
'authority.role-translations.download'
);
Route::resource('authority', AuthorityController::class);
Route::resource('sketchbook', SketchbookController::class);
Route::resource('notices', NoticeController::class);
Route::resource('redirects', RedirectController::class);
Route::get('logs', [LogViewerController::class, 'index']);
});

0 comments on commit f0e8455

Please sign in to comment.