* some stuff moved to UtilityModule(old DoctrineExpressiveModule)

* api auth in place
This commit is contained in:
Danyi Dávid 2018-05-12 00:14:34 +02:00
parent 68bf4735ad
commit 8cd607b063
48 changed files with 766 additions and 29 deletions

18
bin/cli Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/php
<?php
chdir(__DIR__ . '/..');
require __DIR__ . '/../vendor/autoload.php';
use Symfony\Component\Console\Application;
/** @var \Interop\Container\ContainerInterface $container */
$container = require __DIR__ . '/../config/container.php';
$application = new Application('Application console');
$commands = $container->get('config')['console']['commands'];
foreach ($commands as $command) {
$application->add($container->get($command));
}
$application->run();

View File

@ -46,8 +46,11 @@
"los/loslog": "^3.1",
"roave/security-advisories": "dev-master",
"tuupola/cors-middleware": "^0.7.0",
"tuupola/slim-jwt-auth": "^3.0",
"zendframework/zend-component-installer": "^2.1.1",
"zendframework/zend-config": "^3.2",
"zendframework/zend-config-aggregator": "^1.0",
"zendframework/zend-crypt": "^3.3",
"zendframework/zend-diactoros": "^1.7.1",
"zendframework/zend-expressive": "^3.0.1",
"zendframework/zend-expressive-fastroute": "^3.0",
@ -55,6 +58,7 @@
"zendframework/zend-expressive-platesrenderer": "^2.0",
"zendframework/zend-hydrator": "^2.4",
"zendframework/zend-json": "^3.1",
"zendframework/zend-permissions-rbac": "^3.0",
"zendframework/zend-servicemanager": "^3.3",
"zendframework/zend-stdlib": "^3.1"
},
@ -68,7 +72,7 @@
"autoload": {
"psr-4": {
"App\\": "src/App/",
"DoctrineExpressiveModule\\": "src/DoctrineExpressiveModule/"
"UtilityModule\\": "src/UtilityModule/"
}
},
"autoload-dev": {

373
composer.lock generated
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": "d431f9aedef0713895d247778391bea1",
"content-hash": "c16dbd46a5e34757c69f0fdb32bf7680",
"packages": [
{
"name": "behat/transliterator",
@ -784,6 +784,52 @@
],
"time": "2017-02-09T16:10:21+00:00"
},
{
"name": "firebase/php-jwt",
"version": "v5.0.0",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
"reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e",
"reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": " 4.8.35"
},
"type": "library",
"autoload": {
"psr-4": {
"Firebase\\JWT\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Neuman Vong",
"email": "neuman+pear@twilio.com",
"role": "Developer"
},
{
"name": "Anant Narayanan",
"email": "anant@php.net",
"role": "Developer"
}
],
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
"homepage": "https://github.com/firebase/php-jwt",
"time": "2017-06-27T22:17:23+00:00"
},
{
"name": "gedmo/doctrine-extensions",
"version": "v2.4.34",
@ -1274,6 +1320,54 @@
],
"time": "2018-02-13T20:26:39+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v2.0.12",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"type": "library",
"autoload": {
"files": [
"lib/random.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"pseudorandom",
"random"
],
"time": "2018-04-04T21:24:14+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
@ -1976,6 +2070,73 @@
],
"time": "2017-07-15T22:03:15+00:00"
},
{
"name": "tuupola/slim-jwt-auth",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/tuupola/slim-jwt-auth.git",
"reference": "b195031f3732bc2e050bbb203329825377b9f8cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tuupola/slim-jwt-auth/zipball/b195031f3732bc2e050bbb203329825377b9f8cb",
"reference": "b195031f3732bc2e050bbb203329825377b9f8cb",
"shasum": ""
},
"require": {
"firebase/php-jwt": "^3.0 || ^4.0 || ^5.0",
"php": "^7.1",
"psr/http-message": "^1.0",
"psr/http-server-middleware": "^1.0",
"psr/log": "^1.0",
"tuupola/callable-handler": "^0.3.0",
"tuupola/http-factory": "^0.3.0"
},
"require-dev": {
"codedungeon/phpunit-result-printer": "^0.5.4",
"equip/dispatch": "^2.0",
"overtrue/phplint": "^0.2.4",
"phpstan/phpstan": "^0.9.1",
"phpunit/phpunit": "^6.5",
"squizlabs/php_codesniffer": "^2.3",
"zendframework/zend-diactoros": "^1.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-3.x": "3.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Tuupola\\Middleware\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mika Tuupola",
"email": "tuupola@appelsiini.net",
"homepage": "http://www.appelsiini.net/",
"role": "Developer"
}
],
"description": "PSR-7 and PSR-15 JWT Authentication Middleware",
"homepage": "https://github.com/tuupola/slim-jwt-auth",
"keywords": [
"auth",
"json",
"jwt",
"middleware",
"psr-15",
"psr-7"
],
"time": "2018-03-02T06:33:46+00:00"
},
{
"name": "zendframework/zend-component-installer",
"version": "2.1.1",
@ -2028,6 +2189,66 @@
],
"time": "2018-03-21T16:53:56+00:00"
},
{
"name": "zendframework/zend-config",
"version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-config.git",
"reference": "6796f5dcba52c84ef2501d7313618989b5ef3023"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-config/zipball/6796f5dcba52c84ef2501d7313618989b5ef3023",
"reference": "6796f5dcba52c84ef2501d7313618989b5ef3023",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^5.6 || ^7.0",
"psr/container": "^1.0",
"zendframework/zend-stdlib": "^2.7.7 || ^3.1"
},
"conflict": {
"container-interop/container-interop": "<1.2.0"
},
"require-dev": {
"malukenho/docheader": "^0.1.6",
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2",
"zendframework/zend-coding-standard": "~1.0.0",
"zendframework/zend-filter": "^2.7.2",
"zendframework/zend-i18n": "^2.7.4",
"zendframework/zend-servicemanager": "^2.7.8 || ^3.3"
},
"suggest": {
"zendframework/zend-filter": "^2.7.2; install if you want to use the Filter processor",
"zendframework/zend-i18n": "^2.7.4; install if you want to use the Translator processor",
"zendframework/zend-servicemanager": "^2.7.8 || ^3.3; if you need an extensible plugin manager for use with the Config Factory"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.2.x-dev",
"dev-develop": "3.3.x-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Config\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "provides a nested object property based user interface for accessing this configuration data within application code",
"keywords": [
"ZendFramework",
"config",
"zf"
],
"time": "2018-04-24T19:26:44+00:00"
},
{
"name": "zendframework/zend-config-aggregator",
"version": "1.1.1",
@ -2083,6 +2304,58 @@
],
"time": "2018-04-04T20:37:31+00:00"
},
{
"name": "zendframework/zend-crypt",
"version": "3.3.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-crypt.git",
"reference": "9c2916faa9b2132a0f91cdca8e95b025c352f065"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-crypt/zipball/9c2916faa9b2132a0f91cdca8e95b025c352f065",
"reference": "9c2916faa9b2132a0f91cdca8e95b025c352f065",
"shasum": ""
},
"require": {
"container-interop/container-interop": "^1.2",
"ext-mbstring": "*",
"php": "^5.6 || ^7.0",
"zendframework/zend-math": "^3.0",
"zendframework/zend-stdlib": "^2.7.7 || ^3.1"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2",
"zendframework/zend-coding-standard": "~1.0.0"
},
"suggest": {
"ext-openssl": "Required for most features of Zend\\Crypt"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.3.x-dev",
"dev-develop": "3.4.x-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Crypt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Strong cryptography tools and password hashing",
"keywords": [
"ZendFramework",
"crypt",
"zf"
],
"time": "2018-04-24T22:01:58+00:00"
},
{
"name": "zendframework/zend-diactoros",
"version": "1.7.1",
@ -2817,6 +3090,104 @@
],
"time": "2018-04-09T21:59:51+00:00"
},
{
"name": "zendframework/zend-math",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-math.git",
"reference": "558806e338ee68575fbe69489c9dcb6d57a1dae0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-math/zipball/558806e338ee68575fbe69489c9dcb6d57a1dae0",
"reference": "558806e338ee68575fbe69489c9dcb6d57a1dae0",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"paragonie/random_compat": "^2.0.11",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2",
"zendframework/zend-coding-standard": "~1.0.0"
},
"suggest": {
"ext-bcmath": "If using the bcmath functionality",
"ext-gmp": "If using the gmp functionality"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1.x-dev",
"dev-develop": "3.2.x-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Math\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Create cryptographically secure pseudo-random numbers, and manage big integers",
"keywords": [
"ZendFramework",
"math",
"zf"
],
"time": "2018-04-26T21:37:02+00:00"
},
{
"name": "zendframework/zend-permissions-rbac",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/zendframework/zend-permissions-rbac.git",
"reference": "850eda612474d93f49b484604529bcd8ac810d8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/zendframework/zend-permissions-rbac/zipball/850eda612474d93f49b484604529bcd8ac810d8c",
"reference": "850eda612474d93f49b484604529bcd8ac810d8c",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.0.1",
"zendframework/zend-coding-standard": "~1.0.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev",
"dev-develop": "3.1.x-dev"
}
},
"autoload": {
"psr-4": {
"Zend\\Permissions\\Rbac\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Provides a role-based access control management",
"homepage": "https://github.com/zendframework/zend-permissions-rbac",
"keywords": [
"ZendFramework",
"authorization",
"rbac",
"zend-permssions-rbac"
],
"time": "2018-03-22T13:18:45+00:00"
},
{
"name": "zendframework/zend-servicemanager",
"version": "3.3.2",

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
return [
'acl_config' => [
'unguarded_routes' => [
'api.auth.login',
'api.ping',
],
],
];

View File

@ -21,7 +21,6 @@ return [
// Use 'factories' for services provided by callbacks/factory classes.
'factories' => [
// Fully\Qualified\ClassName::class => Fully\Qualified\FactoryName::class,
Tuupola\Middleware\CorsMiddleware::class => DoctrineExpressiveModule\Middleware\CorsMiddlewareFactory::class,
],
],
];

View File

@ -9,4 +9,7 @@
declare(strict_types=1);
return [
'acl_config' => [
'hmac_key' => '',
],
];

View File

@ -26,7 +26,7 @@ $aggregator = new ConfigAggregator([
\Zend\Expressive\Router\ConfigProvider::class,
// Default App module config
DoctrineExpressiveModule\ConfigProvider::class,
UtilityModule\ConfigProvider::class,
App\ConfigProvider::class,
// Load application config in a pre-defined order in such a way that local settings

View File

@ -11,7 +11,6 @@ use Zend\Expressive\Helper\UrlHelperMiddleware;
use Zend\Expressive\MiddlewareFactory;
use Zend\Expressive\Router\Middleware\DispatchMiddleware;
use Zend\Expressive\Router\Middleware\ImplicitHeadMiddleware;
use Zend\Expressive\Router\Middleware\ImplicitOptionsMiddleware;
use Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware;
use Zend\Expressive\Router\Middleware\RouteMiddleware;
use Zend\Stratigility\Middleware\ErrorHandler;
@ -54,7 +53,6 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
// Order here matters; the MethodNotAllowedMiddleware should be placed
// after the Implicit*Middleware.
$app->pipe(ImplicitHeadMiddleware::class);
// $app->pipe(ImplicitOptionsMiddleware::class);
$app->pipe(CorsMiddleware::class);
$app->pipe(MethodNotAllowedMiddleware::class);
@ -67,6 +65,7 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
// - route-based authentication
// - route-based validation
// - etc.
$app->pipe(Tuupola\Middleware\JwtAuthentication::class);
// Register the dispatch middleware in the middleware pipeline
$app->pipe(DispatchMiddleware::class);

View File

@ -61,4 +61,7 @@ return function (Application $app, MiddlewareFactory $factory, ContainerInterfac
$app->get('/awards', App\Handler\AwardeeRedirectHandler::class, 'awardees');
$app->get('/awards/{year:\d+}', App\Handler\AwardeeHandler::class, 'awardees-by-year');
$app->get('/awardee/{slug}', App\Handler\ProfileHandler::class, 'awardee');
$app->post('/api/auth/login', UtilityModule\Handler\AuthHandler::class, 'api.auth.login');
$app->get('/api/auth/renew', UtilityModule\Handler\AuthHandler::class, 'api.auth.renew');
};

View File

@ -7,6 +7,7 @@ namespace App\Handler\Api;
use App\Service\AwardeeManager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use UtilityModule\Handler\AbstractCrudHandler;
use Zend\Diactoros\Response\JsonResponse;
class AwardeeHandler extends AbstractCrudHandler

View File

@ -7,6 +7,7 @@ namespace App\Handler\Api;
use App\Service\JudgeManager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use UtilityModule\Handler\AbstractCrudHandler;
use Zend\Diactoros\Response\JsonResponse;
class JudgesHandler extends AbstractCrudHandler

View File

@ -7,6 +7,7 @@ namespace App\Handler\Api;
use App\Service\YearManager;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use UtilityModule\Handler\AbstractCrudHandler;
use Zend\Diactoros\Response\JsonResponse;
class YearsHandler extends AbstractCrudHandler

View File

@ -6,7 +6,7 @@ namespace App\Service;
use App\Entity\Awardee;
use Doctrine\ORM\EntityManager;
use DoctrineExpressiveModule\Hydrator\DoctrineObject;
use UtilityModule\Hydrator\DoctrineObject;
class AwardeeManager
{

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace App\Service;
use Doctrine\ORM\EntityManager;
use DoctrineExpressiveModule\Hydrator\DoctrineObject;
use UtilityModule\Hydrator\DoctrineObject;
use Psr\Container\ContainerInterface;
class AwardeeManagerFactory

View File

@ -6,7 +6,7 @@ namespace App\Service;
use App\Entity\Judge;
use Doctrine\ORM\EntityManager;
use DoctrineExpressiveModule\Hydrator\DoctrineObject;
use UtilityModule\Hydrator\DoctrineObject;
class JudgeManager
{

View File

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace App\Service;
use Doctrine\ORM\EntityManager;
use DoctrineExpressiveModule\Hydrator\DoctrineObject;
use UtilityModule\Hydrator\DoctrineObject;
use Psr\Container\ContainerInterface;
class JudgeManagerFactory

View File

@ -0,0 +1,34 @@
<?php
namespace UtilityModule\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use UtilityModule\Service\AuthService;
class GeneratePasswordHash extends Command
{
/** @var AuthService */
private $authService;
public function __construct(AuthService $authService)
{
$this->authService = $authService;
parent::__construct();
}
protected function configure()
{
$this->setName('password:generate')
->setDescription('Generate a password hash')
->addArgument('password', InputArgument::REQUIRED, 'Password to hash');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$pass = $input->getArgument('password');
$output->writeln($this->authService->createPasswordHash($pass));
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace UtilityModule\Command;
use Psr\Container\ContainerInterface;
use UtilityModule\Service\AuthService;
class GeneratePasswordHashFactory
{
/**
* @param ContainerInterface $container
* @return GeneratePasswordHash
*/
public function __invoke(ContainerInterface $container)
{
$authService = $container->get(AuthService::class);
return new GeneratePasswordHash($authService);
}
}

View File

@ -2,8 +2,10 @@
declare(strict_types=1);
namespace DoctrineExpressiveModule;
namespace UtilityModule;
use Tuupola\Middleware\CorsMiddleware;
use Tuupola\Middleware\JwtAuthentication;
use Zend\EventManager\EventManager;
/**
@ -25,6 +27,7 @@ class ConfigProvider
return [
'dependencies' => $this->getDependencies(),
'form_elements' => $this->getFormElements(),
'console' => $this->getConsoleCommands(),
];
}
@ -42,7 +45,15 @@ class ConfigProvider
EventManager::class => EventManager::class,
],
'factories' => [
Command\GeneratePasswordHash::class => Command\GeneratePasswordHashFactory::class,
Hydrator\DoctrineObject::class => Hydrator\DoctrineObjectFactory::class,
CorsMiddleware::class => Middleware\CorsMiddlewareFactory::class,
JwtAuthentication::class => Middleware\JwtMiddlewareFactory::class,
Handler\AuthHandler::class => Handler\AuthHandlerFactory::class,
Service\AuthService::class => Service\AuthServiceFactory::class,
],
];
}
@ -61,4 +72,13 @@ class ConfigProvider
],
];
}
public function getConsoleCommands(): array
{
return [
'commands' => [
Command\GeneratePasswordHash::class,
]
];
}
}

View File

@ -1,6 +1,6 @@
<?php
namespace DoctrineExpressiveModule\Form\Element;
namespace UtilityModule\Form\Element;
use Interop\Container\ContainerInterface;

View File

@ -1,6 +1,6 @@
<?php
namespace DoctrineExpressiveModule\Form\Element\Exception;
namespace UtilityModule\Form\Element\Exception;
use InvalidArgumentException;

View File

@ -1,6 +1,6 @@
<?php
namespace DoctrineExpressiveModule\Form\Element;
namespace UtilityModule\Form\Element;
use DoctrineModule\Form\Element\Proxy;
use Zend\Form\Element\MultiCheckbox;

View File

@ -1,8 +1,8 @@
<?php
namespace DoctrineExpressiveModule\Form\Element;
namespace UtilityModule\Form\Element;
use DoctrineExpressiveModule\Form\Element\Proxy;
use UtilityModule\Form\Element\Proxy;
use Zend\Form\Element\Radio as RadioElement;
use Zend\Form\Form;

View File

@ -1,8 +1,8 @@
<?php
namespace DoctrineExpressiveModule\Form\Element;
namespace UtilityModule\Form\Element;
use DoctrineExpressiveModule\Form\Element\Proxy;
use UtilityModule\Form\Element\Proxy;
use Zend\Form\Element\Select as SelectElement;
use Zend\Form\Form;
use Zend\Stdlib\ArrayUtils;

View File

@ -1,6 +1,6 @@
<?php
namespace DoctrineExpressiveModule\Form\Element;
namespace UtilityModule\Form\Element;
use Traversable;
use ReflectionMethod;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Handler\Api;
namespace UtilityModule\Handler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace UtilityModule\Handler;
use Doctrine\ORM\NoResultException;
use Psr\Http\Message\ServerRequestInterface;
use UtilityModule\Service\AuthService;
use Zend\Diactoros\Response\JsonResponse;
class AuthHandler extends AbstractCrudHandler
{
/** @var AuthService */
private $authService;
public function __construct(AuthService $authService) {
$this->authService = $authService;
}
/**
* Respond to POST (login) requests
* @param ServerRequestInterface $request
* @return \Zend\Diactoros\Response\JsonResponse
*/
public function create(ServerRequestInterface $request)
{
$data = $this->getRequestData($request);
try {
return new JsonResponse($this->authService->authenticate(
$data['user'],
$data['pass']
));
} catch (NoResultException $e) {
return new JsonResponse("Access denied", 401);
}
}
/**
* Respond to GET (renew-token) requests
* @param ServerRequestInterface $request
* @return \Zend\Diactoros\Response\JsonResponse
*/
public function get(ServerRequestInterface $request)
{
$token = $request->getAttribute('token');
return new JsonResponse($this->authService->renewToken($token));
}
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace UtilityModule\Handler;
use Psr\Container\ContainerInterface;
use Psr\Http\Server\RequestHandlerInterface;
use UtilityModule\Service\AuthService;
class AuthHandlerFactory
{
public function __invoke(ContainerInterface $container) : RequestHandlerInterface
{
$authService = $container->get(AuthService::class);
return new AuthHandler($authService);
}
}

View File

@ -17,7 +17,7 @@
* <http://www.doctrine-project.org>.
*/
namespace DoctrineExpressiveModule\Hydrator;
namespace UtilityModule\Hydrator;
use DateTime;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;

View File

@ -1,6 +1,6 @@
<?php
namespace DoctrineExpressiveModule\Hydrator;
namespace UtilityModule\Hydrator;
use Interop\Container\ContainerInterface;

View File

@ -17,7 +17,7 @@
* <http://www.doctrine-project.org>.
*/
namespace DoctrineExpressiveModule\Hydrator\Filter;
namespace UtilityModule\Hydrator\Filter;
use Zend\Hydrator\Filter\FilterInterface;

View File

@ -17,7 +17,7 @@
* <http://www.doctrine-project.org>.
*/
namespace DoctrineExpressiveModule\Hydrator\Strategy;
namespace UtilityModule\Hydrator\Strategy;
use InvalidArgumentException;
use Doctrine\Common\Collections\Collection;

View File

@ -17,7 +17,7 @@
* <http://www.doctrine-project.org>.
*/
namespace DoctrineExpressiveModule\Hydrator\Strategy;
namespace UtilityModule\Hydrator\Strategy;
/**
* When this strategy is used for Collections, if the new collection does not contain elements that are present in

View File

@ -17,7 +17,7 @@
* <http://www.doctrine-project.org>.
*/
namespace DoctrineExpressiveModule\Hydrator\Strategy;
namespace UtilityModule\Hydrator\Strategy;
use Doctrine\Common\Collections\Collection;
use LogicException;

View File

@ -17,7 +17,7 @@
* <http://www.doctrine-project.org>.
*/
namespace DoctrineExpressiveModule\Hydrator\Strategy;
namespace UtilityModule\Hydrator\Strategy;
/**
* When this strategy is used for Collections, if the new collection does not contain elements that are present in

View File

@ -17,7 +17,7 @@
* <http://www.doctrine-project.org>.
*/
namespace DoctrineExpressiveModule\Hydrator\Strategy;
namespace UtilityModule\Hydrator\Strategy;
use Doctrine\Common\Collections\Collection;
use LogicException;

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace DoctrineExpressiveModule\Middleware;
namespace UtilityModule\Middleware;
use Psr\Container\ContainerInterface;
use Tuupola\Middleware\CorsMiddleware;

View File

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
namespace UtilityModule\Middleware;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Tuupola\Middleware\JwtAuthentication;
use Zend\Config\Config;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Expressive\Application;
use Zend\Expressive\Router\Route;
class JwtMiddlewareFactory
{
/** @var Config */
private $aclConfig;
/**
* @param ContainerInterface $container
* @return JwtAuthentication
*/
public function __invoke(ContainerInterface $container): JwtAuthentication
{
$configArray = $container->get('config');
/** @var Config $config */
$config = new Config($configArray);
$this->aclConfig = $config->get('acl_config');
return new JwtAuthentication([
"secret" => $this->aclConfig->get('hmac_key'),
"path" => "/api",
"ignore" => $this->getIgnoredRoutes($container),
"secure" => true,
"relaxed" => [
"localhost",
"granprize.dev.yvan.hu",
],
"error" => function (ResponseInterface $response, $arguments) {
$data["status"] = "error";
$data["message"] = $arguments["message"];
return new JsonResponse($data, 401);
}
]);
}
/**
* @param ContainerInterface $container
* @return array
*/
private function getIgnoredRoutes(ContainerInterface $container): array
{
$passThroughRoutes = [];
/** @var Application $app */
$app = $container->get(Application::class);
$appRoutes = $app->getRoutes();
$unguardedRoutes = $this->aclConfig->get('unguarded_routes', new Config([]))->toArray();
/** @var Route $route */
foreach ($appRoutes as $route) {
if (in_array($route->getName(), $unguardedRoutes)) {
$passThroughRoutes[] = $route->getPath();
}
}
return $passThroughRoutes;
}
}

View File

@ -0,0 +1,97 @@
<?php
namespace UtilityModule\Service;
use Doctrine\ORM\NoResultException;
use Firebase\JWT\JWT;
use Zend\Config\Config;
use Zend\Crypt\Password\Bcrypt;
class AuthService
{
const CONFIG_KEY_NAME = 'hmac_key';
const PASSWORD_COST = 14;
/**
* @var Config
*/
private $config;
public function __construct(
Config $config
) {
$this->config = $config;
}
/**
* @param string $user
* @param string $pass
* @return string
* @throws NoResultException
*/
public function authenticate(string $user, string $pass): string
{
$cfgUser = $this->config->get('user');
$cfgPass = $this->config->get('pass');
$crypt = new Bcrypt();
$crypt->setCost(self::PASSWORD_COST);
if ($cfgUser===$user && $crypt->verify($pass, $cfgPass)) {
return $this->generateJwt();
}
throw new NoResultException();
}
/**
* @param $token
* @return string
*/
public function renewToken($token): string
{
return $this->renewJWT($token);
}
/**
* @return string
*/
private function generateJwt(): string
{
/** @var string $hmacKey */
$hmacKey = $this->config->get('hmac_key');
return JWT::encode([
"iat" => time(),
"nbf" => time(),
"exp" => time() + 3600,
], $hmacKey);
}
/**
* @param $token
* @return string
*/
private function renewJWT($token): string
{
/** @var string $hmacKey */
$hmacKey = $this->config->get('hmac_key');
return JWT::encode([
"jti" => $token->jti,
"iat" => time(),
"nbf" => time(),
"exp" => time() + 3600,
], $hmacKey);
}
/**
* @param string $password
* @return string
*/
public function createPasswordHash(string $password): string
{
$crypt = new Bcrypt();
$crypt->setCost(self::PASSWORD_COST);
return $crypt->create($password);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace UtilityModule\Service;
use Interop\Container\ContainerInterface;
use Zend\Config\Config;
class AuthServiceFactory
{
/**
* @param ContainerInterface $container
* @return AuthService
*/
public function __invoke(ContainerInterface $container): AuthService
{
$configArr = $container->get('config')['acl_config'];
return new AuthService(new Config($configArr));
}
}