Changed `src/` code and templates to use the new user model

This commit is contained in:
Igor Scheller 2018-10-08 19:30:37 +02:00 committed by msquare
parent 8e62c4c52c
commit d15946df2d
20 changed files with 329 additions and 36 deletions

View File

@ -20,6 +20,7 @@ return [
\Engelsystem\Helpers\TranslationServiceProvider::class,
\Engelsystem\Http\ResponseServiceProvider::class,
\Engelsystem\Http\Psr7ServiceProvider::class,
\Engelsystem\Helpers\AuthenticatorServiceProvider::class,
\Engelsystem\Renderer\TwigServiceProvider::class,
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
@ -30,7 +31,6 @@ return [
// Application middleware
'middleware' => [
// Basic initialization
\Engelsystem\Middleware\SendResponseHandler::class,
\Engelsystem\Middleware\ExceptionHandler::class,
@ -41,6 +41,8 @@ return [
// The application code
\Engelsystem\Middleware\ErrorHandler::class,
\Engelsystem\Middleware\RouteDispatcher::class,
// Handle request
\Engelsystem\Middleware\RequestHandler::class,
],
];

View File

@ -28,7 +28,7 @@ function engelsystem_email_to_user($recipient_user, $title, $message, $not_if_it
$recipient_user['email'],
$title,
'emails/mail',
['user' => $recipient_user['Nick'], 'message' => $message]
['username' => $recipient_user['Nick'], 'message' => $message]
);
$translator->setLocale($locale);

View File

@ -1,6 +1,7 @@
<?php
use Carbon\Carbon;
use Engelsystem\Models\User\User;
/**
* Renders user settings page
@ -279,6 +280,14 @@ function Users_table_header_link($column, $label, $order_by)
*/
function User_shift_state_render($user)
{
if ($user instanceof User) {
$userModel = $user;
$user = [
'Gekommen' => $userModel->state->arrived,
'UID' => $user->id,
];
}
if (!$user['Gekommen']) {
return '';
}

View File

@ -1,4 +1,4 @@
{{ __('Hi %s,', [user]) }}
{{ __('Hi %s,', [username]) }}
{{ __('here is a message for you from the %s:', [config('app_name')]) }}
{{ message|raw }}

View File

@ -1,4 +1,4 @@
{% set theme = user.color|default(config('theme')) %}
{% set theme = user.settings.theme|default(config('theme')) %}
<!DOCTYPE html>
<html lang="{{ session_get('locale')|split('_')[0]|escape('html_attr') }}">
<head>

View File

@ -21,7 +21,8 @@
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{ url('/') }}">
<span class="icon-icon_angel"></span> <strong class="visible-lg-inline">{{ config('app_name')|upper }}</strong>
<span class="icon-icon_angel"></span>
<strong class="visible-lg-inline">{{ config('app_name')|upper }}</strong>
</a>
</div>
@ -51,7 +52,7 @@
{{ menuUserHints() }}
{% if has_permission_to('user_myshifts') %}
{{ elements.toolbar_item(user.Nick, url('users', {'action': 'view'}), 'users', 'icon icon-icon_angel') }}
{{ elements.toolbar_item(user.name, url('users', {'action': 'view'}), 'users', 'icon icon-icon_angel') }}
{% endif %}
{% if has_permission_to('user_settings') or has_permission_to('logout') %}

View File

@ -4,6 +4,7 @@ namespace Engelsystem\Exceptions\Handlers;
use Engelsystem\Application;
use Engelsystem\Container\Container;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Http\Request;
use Throwable;
use Whoops\Handler\JsonResponseHandler;
@ -81,9 +82,15 @@ class Whoops extends Legacy implements HandlerInterface
*/
protected function getData()
{
global $user;
$data = [];
$user = null;
if ($this->app->has('authenticator')) {
/** @var Authenticator $authenticator */
$authenticator = $this->app->get('authenticator');
$user = $authenticator->user();
}
$data['user'] = $user;
$data['Booted'] = $this->app->isBooted();

View File

@ -0,0 +1,56 @@
<?php
namespace Engelsystem\Helpers;
use Engelsystem\Models\BaseModel;
use Engelsystem\Models\User\User;
use Engelsystem\Models\User\User as UserRepository;
use Symfony\Component\HttpFoundation\Session\Session;
class Authenticator
{
/** @var UserRepository */
protected $user = null;
/** @var Session */
protected $session;
/** @var BaseModel */
protected $userRepository;
/**
* @param Session $session
* @param UserRepository $userRepository
*/
public function __construct(Session $session, UserRepository $userRepository)
{
$this->session = $session;
$this->userRepository = $userRepository;
}
/**
* @return User|null
*/
public function user()
{
if ($this->user) {
return $this->user;
}
$userId = $this->session->get('uid');
if (!$userId) {
return null;
}
$user = $this
->userRepository
->find($userId);
if (!$user) {
return null;
}
$this->user = $user;
return $user;
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Engelsystem\Helpers;
use Engelsystem\Container\ServiceProvider;
class AuthenticatorServiceProvider extends ServiceProvider
{
public function register()
{
/** @var Authenticator $authenticator */
$authenticator = $this->app->make(Authenticator::class);
$this->app->instance(Authenticator::class, $authenticator);
$this->app->instance('authenticator', $authenticator);
}
}

View File

@ -2,6 +2,7 @@
namespace Engelsystem\Middleware;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Helpers\Translator;
use Engelsystem\Http\Request;
use Engelsystem\Http\Response;
@ -35,12 +36,17 @@ class LegacyMiddleware implements MiddlewareInterface
/** @var ContainerInterface */
protected $container;
/** @var Authenticator */
protected $auth;
/**
* @param ContainerInterface $container
* @param Authenticator $auth
*/
public function __construct(ContainerInterface $container)
public function __construct(ContainerInterface $container, Authenticator $auth)
{
$this->container = $container;
$this->auth = $auth;
}
/**
@ -56,7 +62,6 @@ class LegacyMiddleware implements MiddlewareInterface
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface {
global $user;
global $privileges;
global $page;
@ -68,7 +73,7 @@ class LegacyMiddleware implements MiddlewareInterface
$page = str_replace('-', '_', $page);
}
if ($page == '/') {
$page = isset($user) ? 'news' : 'login';
$page = $this->auth->user() ? 'news' : 'login';
}
$title = $content = '';

View File

@ -30,7 +30,7 @@ abstract class BaseModel extends Model
*
* @param mixed $id
* @param array $columns
* @return Builder|Builder[]|Collection|Model|null
* @return Builder|Builder[]|Collection|static|null
*/
public static function find($id, $columns = ['*'])
{

View File

@ -2,11 +2,23 @@
namespace Engelsystem\Renderer\Twig\Extensions;
use Engelsystem\Helpers\Authenticator;
use Twig_Extension as TwigExtension;
use Twig_Function as TwigFunction;
class Authentication extends TwigExtension
{
/** @var Authenticator */
protected $auth;
/**
* @param Authenticator $auth
*/
public function __construct(Authenticator $auth)
{
$this->auth = $auth;
}
/**
* @return TwigFunction[]
*/
@ -19,18 +31,26 @@ class Authentication extends TwigExtension
];
}
/**
* @return bool
*/
public function isAuthenticated()
{
global $user;
return !empty($user);
return (bool)$this->auth->user();
}
/**
* @return bool
*/
public function isGuest()
{
return !$this->isAuthenticated();
}
/**
* @param $privilege
* @return bool
*/
public function checkAuth($privilege)
{
global $privileges;

View File

@ -2,11 +2,23 @@
namespace Engelsystem\Renderer\Twig\Extensions;
use Engelsystem\Helpers\Authenticator;
use Twig_Extension as TwigExtension;
use Twig_Extension_GlobalsInterface as GlobalsInterface;
class Globals extends TwigExtension implements GlobalsInterface
{
/** @var Authenticator */
protected $auth;
/**
* @param Authenticator $auth
*/
public function __construct(Authenticator $auth)
{
$this->auth = $auth;
}
/**
* Returns a list of global variables to add to the existing list.
*
@ -14,10 +26,10 @@ class Globals extends TwigExtension implements GlobalsInterface
*/
public function getGlobals()
{
global $user;
$user = $this->auth->user();
return [
'user' => isset($user) ? $user : [],
'user' => $user ? $user : [],
];
}
}

View File

@ -5,6 +5,7 @@ namespace Engelsystem\Test\Unit\Exceptions\handlers;
use Engelsystem\Application;
use Engelsystem\Exceptions\Handlers\Whoops;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Http\Request;
use Exception;
use PHPUnit\Framework\TestCase;
@ -23,15 +24,23 @@ class WhoopsTest extends TestCase
{
/** @var Application|Mock $app */
$app = $this->createMock(Application::class);
/** @var Authenticator|Mock $auth */
$auth = $this->createMock(Authenticator::class);
/** @var Request|Mock $request */
$request = $this->createMock(Request::class);
$request->expects($this->once())
->method('isXmlHttpRequest')
->willReturn(true);
/** @var WhoopsRunnerInterface|Mock $whoopsRunner */
$whoopsRunner = $this->getMockForAbstractClass(WhoopsRunnerInterface::class);
/** @var PrettyPageHandler|Mock $prettyPageHandler */
$prettyPageHandler = $this->createMock(PrettyPageHandler::class);
/** @var JsonResponseHandler|Mock $jsonResponseHandler */
$jsonResponseHandler = $this->createMock(JsonResponseHandler::class);
/** @var Exception|Mock $exception */
$exception = $this->createMock(Exception::class);
$request->expects($this->once())
->method('isXmlHttpRequest')
->willReturn(true);
$prettyPageHandler
->expects($this->atLeastOnce())
->method('setApplicationPaths');
@ -41,16 +50,13 @@ class WhoopsTest extends TestCase
$prettyPageHandler
->expects($this->once())
->method('addDataTable');
/** @var JsonResponseHandler|Mock $jsonResponseHandler */
$jsonResponseHandler = $this->createMock(JsonResponseHandler::class);
$jsonResponseHandler->expects($this->once())
->method('setJsonApi')
->with(true);
$jsonResponseHandler->expects($this->once())
->method('addTraceToOutput')
->with(true);
/** @var Exception|Mock $exception */
$exception = $this->createMock(Exception::class);
$app->expects($this->exactly(3))
->method('make')
@ -64,6 +70,18 @@ class WhoopsTest extends TestCase
$prettyPageHandler,
$jsonResponseHandler
);
$app->expects($this->once())
->method('has')
->with('authenticator')
->willReturn(true);
$app->expects($this->once())
->method('get')
->with('authenticator')
->willReturn($auth);
$auth->expects($this->once())
->method('user')
->willReturn(null);
$whoopsRunner
->expects($this->exactly(2))

View File

@ -0,0 +1,25 @@
<?php
namespace Engelsystem\Test\Unit\Helpers;
use Engelsystem\Application;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Helpers\AuthenticatorServiceProvider;
use Engelsystem\Test\Unit\ServiceProviderTest;
class AuthenticatorServiceProviderTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Helpers\AuthenticatorServiceProvider::register()
*/
public function testRegister()
{
$app = new Application();
$serviceProvider = new AuthenticatorServiceProvider($app);
$serviceProvider->register();
$this->assertInstanceOf(Authenticator::class, $app->get(Authenticator::class));
$this->assertInstanceOf(Authenticator::class, $app->get('authenticator'));
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace Engelsystem\Test\Unit\Helpers;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
use Engelsystem\Test\Unit\Helpers\Stub\UserModelImplementation;
use Engelsystem\Test\Unit\ServiceProviderTest;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\HttpFoundation\Session\Session;
class AuthenticatorTest extends ServiceProviderTest
{
/**
* @covers \Engelsystem\Helpers\Authenticator::__construct(
* @covers \Engelsystem\Helpers\Authenticator::user
*/
public function testUser()
{
/** @var Session|MockObject $session */
$session = $this->createMock(Session::class);
/** @var UserModelImplementation|MockObject $userRepository */
$userRepository = new UserModelImplementation();
/** @var User|MockObject $user */
$user = $this->createMock(User::class);
$session->expects($this->exactly(3))
->method('get')
->with('uid')
->willReturnOnConsecutiveCalls(
null,
42,
1337
);
$auth = new Authenticator($session, $userRepository);
// Not in session
$this->assertEquals(null, $auth->user());
// Unknown user
UserModelImplementation::$id = 42;
$this->assertEquals(null, $auth->user());
// User found
UserModelImplementation::$id = 1337;
UserModelImplementation::$user = $user;
$this->assertEquals($user, $auth->user());
// User cached
UserModelImplementation::$id = null;
UserModelImplementation::$user = null;
$this->assertEquals($user, $auth->user());
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace Engelsystem\Test\Unit\Helpers\Stub;
use Engelsystem\Models\User\User;
use InvalidArgumentException;
class UserModelImplementation extends User
{
/** @var User */
public static $user = null;
/** @var int */
public static $id = null;
/**
* @param mixed $id
* @param array $columns
* @return User|null
*/
public static function find($id, $columns = ['*'])
{
if ($id != static::$id) {
throw new InvalidArgumentException('Wrong user ID searched');
}
return self::$user;
}
}

View File

@ -2,6 +2,7 @@
namespace Engelsystem\Test\Unit\Middleware;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Helpers\Translator;
use Engelsystem\Http\Request;
use Engelsystem\Middleware\LegacyMiddleware;
@ -23,9 +24,11 @@ class LegacyMiddlewareTest extends TestCase
{
/** @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])
->setConstructorArgs([$container, $auth])
->setMethods(['loadPage', 'renderPage'])
->getMock();
/** @var Request|MockObject $defaultRequest */
@ -70,6 +73,10 @@ class LegacyMiddlewareTest extends TestCase
$defaultRequest
);
$auth->expects($this->atLeastOnce())
->method('user')
->willReturn(false);
$translator->expects($this->exactly(2))
->method('translate')
->willReturnOnConsecutiveCalls(

View File

@ -2,16 +2,23 @@
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
use Engelsystem\Renderer\Twig\Extensions\Authentication;
use PHPUnit\Framework\MockObject\MockObject;
class AuthenticationTest extends ExtensionTest
{
/**
* @covers \Engelsystem\Renderer\Twig\Extensions\Authentication::__construct
* @covers \Engelsystem\Renderer\Twig\Extensions\Authentication::getFunctions
*/
public function testGetFunctions()
{
$extension = new Authentication();
/** @var Authenticator|MockObject $auth */
$auth = $this->createMock(Authenticator::class);
$extension = new Authentication($auth);
$functions = $extension->getFunctions();
$this->assertExtensionExists('is_user', [$extension, 'isAuthenticated'], $functions);
@ -25,15 +32,24 @@ class AuthenticationTest extends ExtensionTest
*/
public function testIsAuthenticated()
{
global $user;
$user = [];
/** @var Authenticator|MockObject $auth */
$auth = $this->createMock(Authenticator::class);
$user = new User();
$extension = new Authentication();
$auth->expects($this->exactly(4))
->method('user')
->willReturnOnConsecutiveCalls(
null,
null,
$user,
$user
);
$extension = new Authentication($auth);
$this->assertFalse($extension->isAuthenticated());
$this->assertTrue($extension->isGuest());
$user = ['lorem' => 'ipsum'];
$this->assertTrue($extension->isAuthenticated());
$this->assertFalse($extension->isGuest());
}
@ -46,7 +62,10 @@ class AuthenticationTest extends ExtensionTest
global $privileges;
$privileges = [];
$extension = new Authentication();
/** @var Authenticator|MockObject $auth */
$auth = $this->createMock(Authenticator::class);
$extension = new Authentication($auth);
$this->assertFalse($extension->checkAuth('foo.bar'));

View File

@ -2,25 +2,36 @@
namespace Engelsystem\Test\Unit\Renderer\Twig\Extensions;
use Engelsystem\Helpers\Authenticator;
use Engelsystem\Models\User\User;
use Engelsystem\Renderer\Twig\Extensions\Globals;
use PHPUnit\Framework\MockObject\MockObject;
class GlobalsTest extends ExtensionTest
{
/**
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::__construct
* @covers \Engelsystem\Renderer\Twig\Extensions\Globals::getGlobals
*/
public function testGetGlobals()
{
global $user;
$user = [];
/** @var Authenticator|MockObject $auth */
$auth = $this->createMock(Authenticator::class);
$user = new User();
$extension = new Globals();
$auth->expects($this->exactly(2))
->method('user')
->willReturnOnConsecutiveCalls(
null,
$user
);
$extension = new Globals($auth);
$globals = $extension->getGlobals();
$this->assertGlobalsExists('user', [], $globals);
$user['foo'] = 'bar';
$globals = $extension->getGlobals();
$this->assertGlobalsExists('user', ['foo' => 'bar'], $globals);
$this->assertGlobalsExists('user', $user, $globals);
}
}