Add users.arrive.list permission & refactored LegacyMiddleware test

This commit is contained in:
Xu 2024-04-21 21:09:54 +02:00 committed by Igor Scheller
parent b2951b7337
commit f1f5cd7c01
5 changed files with 179 additions and 118 deletions

View File

@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
namespace Engelsystem\Migrations;
use Engelsystem\Database\Migration\Migration;
use Illuminate\Database\Connection;
use Illuminate\Database\Schema\Builder as SchemaBuilder;
class AddUsersArriveListPermission extends Migration
{
protected int $voucher = 35;
protected int $arrive;
protected Connection $db;
public function __construct(SchemaBuilder $schema)
{
parent::__construct($schema);
$this->db = $this->schema->getConnection();
$this->arrive = $this->db->table('privileges')
->where('name', 'admin_arrive')
->get(['id'])
->first()->id;
}
/**
* Run the migration
*/
public function up(): void
{
$this->db->table('privileges')
->insert([
'name' => 'users.arrive.list', 'description' => 'View arrive angels list',
]);
$arriveList = $this->db->table('privileges')
->where('name', 'users.arrive.list')
->get(['id'])
->first()->id;
// Goodie Manager, Shift Coordinator, Voucher Angel, Welcome Angel
$groups = [50, 60, 35, 30];
foreach ($groups as $group) {
$this->db->table('group_privileges')
->insertOrIgnore([
['group_id' => $group, 'privilege_id' => $arriveList],
]);
}
$this->db->table('group_privileges')
->where(['group_id' => $this->voucher, 'privilege_id' => $this->arrive])
->delete();
}
/**
* Reverse the migration
*/
public function down(): void
{
$this->db->table('privileges')
->where('name', 'users.arrive.list')
->delete();
$this->db->table('group_privileges')
->insertOrIgnore([
['group_id' => $this->voucher, 'privilege_id' => $this->arrive],
]);
}
}

View File

@ -8,7 +8,7 @@ use Engelsystem\Models\User\User;
*/ */
function admin_arrive_title() function admin_arrive_title()
{ {
return __('Arrive angels'); return auth()->can('admin_arrive') ? __('Arrive angels') : __('Angels');
} }
/** /**
@ -19,48 +19,51 @@ function admin_arrive()
$msg = ''; $msg = '';
$search = ''; $search = '';
$request = request(); $request = request();
$admin_arrive = auth()->can('admin_arrive');
if ($request->has('search')) { if ($request->has('search')) {
$search = strip_request_item('search'); $search = strip_request_item('search');
$search = trim($search); $search = trim($search);
} }
$action = $request->get('action'); if ($admin_arrive) {
if ( $action = $request->get('action');
$action == 'reset' if (
&& preg_match('/^\d+$/', $request->input('user')) $action == 'reset'
&& $request->hasPostData('submit') && preg_match('/^\d+$/', $request->input('user'))
) { && $request->hasPostData('submit')
$user_id = $request->input('user'); ) {
$user_source = User::find($user_id); $user_id = $request->input('user');
if ($user_source) { $user_source = User::find($user_id);
$user_source->state->arrived = false; if ($user_source) {
$user_source->state->arrival_date = null; $user_source->state->arrived = false;
$user_source->state->save(); $user_source->state->arrival_date = null;
$user_source->state->save();
engelsystem_log('User set to not arrived: ' . User_Nick_render($user_source, true)); engelsystem_log('User set to not arrived: ' . User_Nick_render($user_source, true));
success(__('Reset done. Angel has not arrived.')); success(__('Reset done. Angel has not arrived.'));
throw_redirect(user_link($user_source->id)); throw_redirect(user_link($user_source->id));
} else { } else {
$msg = error(__('Angel not found.'), true); $msg = error(__('Angel not found.'), true);
} }
} elseif ( } elseif (
$action == 'arrived' $action == 'arrived'
&& preg_match('/^\d+$/', $request->input('user')) && preg_match('/^\d+$/', $request->input('user'))
&& $request->hasPostData('submit') && $request->hasPostData('submit')
) { ) {
$user_id = $request->input('user'); $user_id = $request->input('user');
$user_source = User::find($user_id); $user_source = User::find($user_id);
if ($user_source) { if ($user_source) {
$user_source->state->arrived = true; $user_source->state->arrived = true;
$user_source->state->arrival_date = new Carbon\Carbon(); $user_source->state->arrival_date = new Carbon\Carbon();
$user_source->state->save(); $user_source->state->save();
engelsystem_log('User set has arrived: ' . User_Nick_render($user_source, true)); engelsystem_log('User set has arrived: ' . User_Nick_render($user_source, true));
success(__('Angel has been marked as arrived.')); success(__('Angel has been marked as arrived.'));
throw_redirect(user_link($user_source->id)); throw_redirect(user_link($user_source->id));
} else { } else {
$msg = error(__('Angel not found.'), true); $msg = error(__('Angel not found.'), true);
}
} }
} }
@ -206,15 +209,17 @@ function admin_arrive()
form_text('search', __('form.search'), $search), form_text('search', __('form.search'), $search),
form_submit('submit', icon('search') . __('form.search')), form_submit('submit', icon('search') . __('form.search')),
], url('/admin-arrive')), ], url('/admin-arrive')),
table([ table(array_merge(
'name' => __('general.name'), ['name' => __('general.name'),],
'rendered_planned_arrival_date' => __('Planned arrival'), ($admin_arrive ? ['rendered_planned_arrival_date' => __('Planned arrival')] : []),
'arrived' => __('Arrived?'), ['arrived' => __('Arrived?')],
'rendered_arrival_date' => __('Arrival date'), ($admin_arrive ? [
'rendered_planned_departure_date' => __('Planned departure'), 'rendered_arrival_date' => __('Arrival date'),
'actions' => __('general.actions'), 'rendered_planned_departure_date' => __('Planned departure'),
], $users_matched), 'actions' => __('general.actions'),
div('row', [ ] : [])
), $users_matched),
div('row', $admin_arrive ? [
div('col-md-4', [ div('col-md-4', [
heading(__('Planned arrival statistics'), 3), heading(__('Planned arrival statistics'), 3),
BarChart::render([ BarChart::render([
@ -260,6 +265,6 @@ function admin_arrive()
'sum' => __('Sum'), 'sum' => __('Sum'),
], $planned_departure_at_day), ], $planned_departure_at_day),
]), ]),
]), ] : []),
]); ]);
} }

View File

@ -85,7 +85,7 @@ function make_navigation()
// path => name, // path => name,
// path => [name, permission], // path => [name, permission],
'admin_arrive' => 'Arrive angels', 'admin_arrive' => [admin_arrive_title(), 'users.arrive.list'],
'admin_active' => 'Active angels', 'admin_active' => 'Active angels',
'users' => ['All Angels', 'admin_user'], 'users' => ['All Angels', 'admin_user'],
'admin_free' => 'Free angels', 'admin_free' => 'Free angels',

View File

@ -45,16 +45,21 @@ class LegacyMiddleware implements MiddlewareInterface
/** @var Request $appRequest */ /** @var Request $appRequest */
$appRequest = $this->container->get('request'); $appRequest = $this->container->get('request');
$page = $appRequest->query->get('p'); $page = $appRequest->query->get('p');
// Support old URL scheme // Support old URL/permission scheme
if (empty($page)) { if (empty($page)) {
$page = $appRequest->path(); $page = $appRequest->path();
$page = str_replace('-', '_', $page); $page = str_replace('-', '_', $page);
} }
$allowPage = false;
if ($page === 'admin_arrive') {
$allowPage = $this->auth->can('users.arrive.list');
}
$title = $content = ''; $title = $content = '';
if ( if (
preg_match('~^\w+$~i', $page) preg_match('~^\w+$~i', $page)
&& (in_array($page, $this->free_pages) || $this->auth->can($page)) && (in_array($page, $this->free_pages) || $this->auth->can($page) || $allowPage)
) { ) {
list($title, $content) = $this->loadPage($page); list($title, $content) = $this->loadPage($page);
} }

View File

@ -5,16 +5,12 @@ declare(strict_types=1);
namespace Engelsystem\Test\Unit\Middleware; namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Helpers\Authenticator; use Engelsystem\Helpers\Authenticator;
use Engelsystem\Helpers\Translation\Translator;
use Engelsystem\Http\Request; use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
use Engelsystem\Middleware\LegacyMiddleware; use Engelsystem\Middleware\LegacyMiddleware;
use Engelsystem\Test\Unit\TestCase;
use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Symfony\Component\HttpFoundation\ParameterBag;
class LegacyMiddlewareTest extends TestCase class LegacyMiddlewareTest extends TestCase
{ {
@ -22,79 +18,61 @@ class LegacyMiddlewareTest extends TestCase
* @covers \Engelsystem\Middleware\LegacyMiddleware::__construct * @covers \Engelsystem\Middleware\LegacyMiddleware::__construct
* @covers \Engelsystem\Middleware\LegacyMiddleware::process * @covers \Engelsystem\Middleware\LegacyMiddleware::process
*/ */
public function testRegister(): void public function testRegisterNotFound(): void
{ {
/** @var ContainerInterface|MockObject $container */
$container = $this->getMockForAbstractClass(ContainerInterface::class);
/** @var Authenticator|MockObject $auth */
$auth = $this->createMock(Authenticator::class);
/** @var LegacyMiddleware|MockObject $middleware */
$middleware = $this->getMockBuilder(LegacyMiddleware::class)
->setConstructorArgs([$container, $auth])
->onlyMethods(['loadPage', 'renderPage'])
->getMock();
/** @var Request|MockObject $defaultRequest */
$defaultRequest = $this->createMock(Request::class);
/** @var ParameterBag|MockObject $parameters */
$parameters = $this->createMock(ParameterBag::class);
/** @var ResponseInterface|MockObject $response */
$response = $this->getMockForAbstractClass(ResponseInterface::class);
/** @var RequestHandlerInterface|MockObject $handler */ /** @var RequestHandlerInterface|MockObject $handler */
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class); $handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
/** @var ServerRequestInterface|MockObject $request */ /** @var Authenticator|MockObject $auth */
$request = $this->getMockForAbstractClass(ServerRequestInterface::class); $auth = $this->createMock(Authenticator::class);
/** @var Translator|MockObject $translator */ $response = new Response();
$translator = $this->getMockBuilder(Translator::class) $request = new Request(['p' => 'foo']);
->disableOriginalConstructor() $this->app->instance('request', $request);
$this->mockTranslator();
/** @var LegacyMiddleware|MockObject $middleware */
$middleware = $this->getMockBuilder(LegacyMiddleware::class)
->setConstructorArgs([$this->app, $auth])
->onlyMethods(['renderPage'])
->getMock(); ->getMock();
$middleware->expects($this->once()) $middleware->expects($this->once())
->method('loadPage')
->with('users')
->willReturn(['title', 'content']);
$middleware->expects($this->exactly(2))
->method('renderPage') ->method('renderPage')
->withConsecutive( ->with(404, 'page.404.title', 'page.404.text')
['users', 'title', 'content'],
[404, 'Page not found', 'It\'s not available!']
)
->willReturn($response); ->willReturn($response);
$container->expects($this->exactly(3))
->method('get')
->withConsecutive(['request'], ['request'], ['translator'])
->willReturnOnConsecutiveCalls(
$defaultRequest,
$defaultRequest,
$translator
);
$auth->expects($this->atLeastOnce())
->method('can')
->willReturn(false);
$translator->expects($this->exactly(2))
->method('translate')
->willReturnOnConsecutiveCalls(
'Page not found',
'It\'s not available!'
);
$defaultRequest->query = $parameters;
$defaultRequest->expects($this->once())
->method('path')
->willReturn('users');
$parameters->expects($this->exactly(2))
->method('get')
->with('p')
->willReturnOnConsecutiveCalls(
null,
'foo'
);
$middleware->process($request, $handler); $middleware->process($request, $handler);
}
/**
* @covers \Engelsystem\Middleware\LegacyMiddleware::process
*/
public function testRegisterHasPermission(): void
{
/** @var RequestHandlerInterface|MockObject $handler */
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
/** @var Authenticator|MockObject $auth */
$auth = $this->createMock(Authenticator::class);
$auth->expects($this->exactly(2))
->method('can')
->withConsecutive(['users.arrive.list'], ['admin_arrive'])
->willReturnOnConsecutiveCalls(true, false);
$response = new Response();
$request = new Request([], [], [], [], [], ['REQUEST_URI' => 'admin-arrive']);
$this->app->instance('request', $request);
/** @var LegacyMiddleware|MockObject $middleware */
$middleware = $this->getMockBuilder(LegacyMiddleware::class)
->setConstructorArgs([$this->app, $auth])
->onlyMethods(['loadPage', 'renderPage'])
->getMock();
$middleware->expects($this->once())
->method('loadPage')
->with('admin_arrive')
->willReturn(['title', 'content']);
$middleware->expects($this->once())
->method('renderPage')
->with('admin_arrive', 'title', 'content')
->willReturn($response);
$middleware->process($request, $handler); $middleware->process($request, $handler);
} }
} }