From bcce2625a8cb0b630d945c6849014049869e10ce Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 27 Nov 2018 12:01:36 +0100 Subject: Implemented AuthController for login * Moved /login functionality to AuthController * Refactored password handling logic to use the Authenticator --- tests/Unit/Controllers/AuthControllerTest.php | 132 ++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 9 deletions(-) (limited to 'tests/Unit/Controllers/AuthControllerTest.php') diff --git a/tests/Unit/Controllers/AuthControllerTest.php b/tests/Unit/Controllers/AuthControllerTest.php index c5349cda..0fad3b6d 100644 --- a/tests/Unit/Controllers/AuthControllerTest.php +++ b/tests/Unit/Controllers/AuthControllerTest.php @@ -3,40 +3,154 @@ namespace Engelsystem\Test\Unit\Controllers; use Engelsystem\Controllers\AuthController; +use Engelsystem\Helpers\Authenticator; +use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Http\UrlGeneratorInterface; +use Engelsystem\Models\User\Settings; +use Engelsystem\Models\User\User; +use Engelsystem\Test\Unit\HasDatabase; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Session\SessionInterface; class AuthControllerTest extends TestCase { + use HasDatabase; + /** * @covers \Engelsystem\Controllers\AuthController::__construct - * @covers \Engelsystem\Controllers\AuthController::logout + * @covers \Engelsystem\Controllers\AuthController::login */ - public function testLogout() + public function testLogin() { /** @var Response|MockObject $response */ $response = $this->createMock(Response::class); /** @var SessionInterface|MockObject $session */ - $session = $this->getMockForAbstractClass(SessionInterface::class); /** @var UrlGeneratorInterface|MockObject $url */ - $url = $this->getMockForAbstractClass(UrlGeneratorInterface::class); + /** @var Authenticator|MockObject $auth */ + list(, $session, $url, $auth) = $this->getMocks(); - $session->expects($this->once()) - ->method('invalidate'); + $response->expects($this->once()) + ->method('withView') + ->with('pages/login') + ->willReturn($response); + + $controller = new AuthController($response, $session, $url, $auth); + $controller->login(); + } + + /** + * @covers \Engelsystem\Controllers\AuthController::postLogin + * @covers \Engelsystem\Controllers\AuthController::authenticateUser + */ + public function testPostLogin() + { + $this->initDatabase(); + $request = new Request(); + /** @var Response|MockObject $response */ + $response = $this->createMock(Response::class); + /** @var SessionInterface|MockObject $session */ + /** @var UrlGeneratorInterface|MockObject $url */ + /** @var Authenticator|MockObject $auth */ + list(, $session, $url, $auth) = $this->getMocks(); + + $user = new User([ + 'name' => 'foo', + 'password' => '', + 'email' => '', + 'api_key' => '', + 'last_login_at' => null, + ]); + $user->forceFill(['id' => 42,]); + $user->save(); + + $settings = new Settings(['language' => 'de_DE', 'theme' => '']); + $settings->user() + ->associate($user) + ->save(); + + $auth->expects($this->exactly(2)) + ->method('authenticate') + ->with('foo', 'bar') + ->willReturnOnConsecutiveCalls(null, $user); + + $response->expects($this->exactly(3)) + ->method('withView') + ->withConsecutive( + ['pages/login', ['errors' => ['auth.no-nickname'], 'show_password_recovery' => true]], + ['pages/login', ['errors' => ['auth.no-password'], 'show_password_recovery' => true]], + ['pages/login', ['errors' => ['auth.not-found'], 'show_password_recovery' => true]]) + ->willReturn($response); $response->expects($this->once()) ->method('redirectTo') - ->with('https://foo.bar/'); + ->with('news') + ->willReturn($response); + + $session->expects($this->once()) + ->method('invalidate'); + + $session->expects($this->exactly(2)) + ->method('set') + ->withConsecutive( + ['user_id', 42], + ['locale', 'de_DE'] + ); + + $controller = new AuthController($response, $session, $url, $auth); + $controller->postLogin($request); + + $request = new Request(['login' => 'foo']); + $controller->postLogin($request); + + $request = new Request(['login' => 'foo', 'password' => 'bar']); + // No user found + $controller->postLogin($request); + // Authenticated user + $controller->postLogin($request); + + $this->assertNotNull($user->last_login_at); + } + + /** + * @covers \Engelsystem\Controllers\AuthController::logout + */ + public function testLogout() + { + /** @var Response $response */ + /** @var SessionInterface|MockObject $session */ + /** @var UrlGeneratorInterface|MockObject $url */ + /** @var Authenticator|MockObject $auth */ + list($response, $session, $url, $auth) = $this->getMocks(); + + $session->expects($this->once()) + ->method('invalidate'); $url->expects($this->once()) ->method('to') ->with('/') ->willReturn('https://foo.bar/'); - $controller = new AuthController($response, $session, $url); - $controller->logout(); + $controller = new AuthController($response, $session, $url, $auth); + $return = $controller->logout(); + + $this->assertEquals(['https://foo.bar/'], $return->getHeader('location')); + } + + /** + * @return array + */ + protected function getMocks() + { + $response = new Response(); + /** @var SessionInterface|MockObject $session */ + $session = $this->getMockForAbstractClass(SessionInterface::class); + /** @var UrlGeneratorInterface|MockObject $url */ + $url = $this->getMockForAbstractClass(UrlGeneratorInterface::class); + /** @var Authenticator|MockObject $auth */ + $auth = $this->createMock(Authenticator::class); + + return [$response, $session, $url, $auth]; } } -- cgit v1.2.3-54-g00ecf From 6d5ada252202bfb29eba884cf9567e969d798607 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 9 Jul 2019 22:02:07 +0200 Subject: Added validation to AuthController --- resources/lang/de_DE/default.mo | Bin 46271 -> 46206 bytes resources/lang/de_DE/default.po | 18 +++++--- resources/lang/en_US/default.mo | Bin 745 -> 770 bytes resources/lang/en_US/default.po | 16 ++++--- src/Controllers/AuthController.php | 62 ++++++++++++-------------- tests/Unit/Controllers/AuthControllerTest.php | 61 +++++++++++++++---------- 6 files changed, 88 insertions(+), 69 deletions(-) (limited to 'tests/Unit/Controllers/AuthControllerTest.php') diff --git a/resources/lang/de_DE/default.mo b/resources/lang/de_DE/default.mo index 35ad80b7..fb93d590 100644 Binary files a/resources/lang/de_DE/default.mo and b/resources/lang/de_DE/default.mo differ diff --git a/resources/lang/de_DE/default.po b/resources/lang/de_DE/default.po index cd696610..1f0372af 100644 --- a/resources/lang/de_DE/default.po +++ b/resources/lang/de_DE/default.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Engelsystem\n" "POT-Creation-Date: 2019-04-28 15:23+0200\n" -"PO-Revision-Date: 2019-06-12 16:07+0200\n" +"PO-Revision-Date: 2019-06-13 11:54+0200\n" "Last-Translator: msquare \n" "Language-Team: \n" "Language: de_DE\n" @@ -1529,9 +1529,8 @@ msgstr "Nachname" msgid "Entry required!" msgstr "Pflichtfeld!" -#: includes/pages/guest_login.php:414 -msgid "auth.no-password" -msgstr "Gib bitte ein Passwort ein." +#~ msgid "auth.no-password" +#~ msgstr "Gib bitte ein Passwort ein." #: includes/pages/guest_login.php:418 msgid "auth.not-found" @@ -1539,9 +1538,8 @@ msgstr "" "Es wurde kein Engel gefunden. Probiere es bitte noch einmal. Wenn das Problem " "weiterhin besteht, melde dich im Himmel." -#: includes/pages/guest_login.php:451 includes/view/User_view.php:130 -msgid "auth.no-nickname" -msgstr "Gib bitte einen Nick an." +#~ msgid "auth.no-nickname" +#~ msgstr "Gib bitte einen Nick an." #: includes/pages/guest_login.php:481 #: includes/view/User_view.php:122 @@ -2765,3 +2763,9 @@ msgid "" msgstr "" "Diese Seite existiert nicht oder Du hast keinen Zugriff. Melde Dich an um " "Zugriff zu erhalten!" + +msgid "validation.password.required" +msgstr "Bitte gib ein Passwort an." + +msgid "validation.login.required" +msgstr "Bitte gib einen Loginnamen an." diff --git a/resources/lang/en_US/default.mo b/resources/lang/en_US/default.mo index e95ae703..7ef9c3b2 100644 Binary files a/resources/lang/en_US/default.mo and b/resources/lang/en_US/default.mo differ diff --git a/resources/lang/en_US/default.po b/resources/lang/en_US/default.po index 22566e52..54847e61 100644 --- a/resources/lang/en_US/default.po +++ b/resources/lang/en_US/default.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Engelsystem 2.0\n" "POT-Creation-Date: 2017-12-29 19:01+0100\n" -"PO-Revision-Date: 2018-11-27 00:28+0100\n" +"PO-Revision-Date: 2019-06-04 23:41+0200\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -16,11 +16,17 @@ msgstr "" "Language: en_US\n" "X-Poedit-SearchPath-0: .\n" -msgid "auth.no-nickname" -msgstr "Please enter a nickname." +#~ msgid "auth.no-nickname" +#~ msgstr "Please enter a nickname." -msgid "auth.no-password" -msgstr "Please enter a password." +#~ msgid "auth.no-password" +#~ msgstr "Please enter a password." msgid "auth.not-found" msgstr "No user was found. Please try again. If you are still having problems, ask Heaven." + +msgid "validation.password.required" +msgstr "The password is required." + +msgid "validation.login.required" +msgstr "The login name is required." diff --git a/src/Controllers/AuthController.php b/src/Controllers/AuthController.php index e5fc40e3..a8cc1ace 100644 --- a/src/Controllers/AuthController.php +++ b/src/Controllers/AuthController.php @@ -8,6 +8,8 @@ use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Http\UrlGeneratorInterface; use Engelsystem\Models\User\User; +use Illuminate\Support\Arr; +use Illuminate\Support\Collection; use Symfony\Component\HttpFoundation\Session\SessionInterface; class AuthController extends BaseController @@ -53,7 +55,22 @@ class AuthController extends BaseController */ public function login() { - return $this->response->withView('pages/login'); + return $this->showLogin(); + } + + /** + * @param bool $showRecovery + * @return Response + */ + protected function showLogin($showRecovery = false) + { + $errors = Collection::make(Arr::flatten($this->session->get('errors', []))); + $this->session->remove('errors'); + + return $this->response->withView( + 'pages/login', + ['errors' => $errors, 'show_password_recovery' => $showRecovery] + ); } /** @@ -64,15 +81,18 @@ class AuthController extends BaseController */ public function postLogin(Request $request): Response { - $return = $this->authenticateUser($request->get('login', ''), $request->get('password', '')); - if (!$return instanceof User) { - return $this->response->withView( - 'pages/login', - ['errors' => [$return], 'show_password_recovery' => true] - ); - } + $data = $this->validate($request, [ + 'login' => 'required', + 'password' => 'required', + ]); + + $user = $this->auth->authenticate($data['login'], $data['password']); - $user = $return; + if (!$user instanceof User) { + $this->session->set('errors', $this->session->get('errors', []) + ['auth.not-found']); + + return $this->showLogin(true); + } $this->session->invalidate(); $this->session->set('user_id', $user->id); @@ -93,28 +113,4 @@ class AuthController extends BaseController return $this->response->redirectTo($this->url->to('/')); } - - /** - * Verify the user and password - * - * @param $login - * @param $password - * @return User|string - */ - protected function authenticateUser(string $login, string $password) - { - if (!$login) { - return 'auth.no-nickname'; - } - - if (!$password) { - return 'auth.no-password'; - } - - if (!$user = $this->auth->authenticate($login, $password)) { - return 'auth.not-found'; - } - - return $user; - } } diff --git a/tests/Unit/Controllers/AuthControllerTest.php b/tests/Unit/Controllers/AuthControllerTest.php index 0fad3b6d..d3dbfa4b 100644 --- a/tests/Unit/Controllers/AuthControllerTest.php +++ b/tests/Unit/Controllers/AuthControllerTest.php @@ -4,15 +4,21 @@ namespace Engelsystem\Test\Unit\Controllers; use Engelsystem\Controllers\AuthController; use Engelsystem\Helpers\Authenticator; +use Engelsystem\Http\Exceptions\ValidationException; use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Http\UrlGeneratorInterface; +use Engelsystem\Http\Validation\Validates; +use Engelsystem\Http\Validation\Validator; use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\User; use Engelsystem\Test\Unit\HasDatabase; +use Illuminate\Support\Collection; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; class AuthControllerTest extends TestCase { @@ -21,6 +27,7 @@ class AuthControllerTest extends TestCase /** * @covers \Engelsystem\Controllers\AuthController::__construct * @covers \Engelsystem\Controllers\AuthController::login + * @covers \Engelsystem\Controllers\AuthController::showLogin */ public function testLogin() { @@ -31,6 +38,10 @@ class AuthControllerTest extends TestCase /** @var Authenticator|MockObject $auth */ list(, $session, $url, $auth) = $this->getMocks(); + $session->expects($this->once()) + ->method('get') + ->with('errors', []) + ->willReturn(['foo' => 'bar']); $response->expects($this->once()) ->method('withView') ->with('pages/login') @@ -42,7 +53,6 @@ class AuthControllerTest extends TestCase /** * @covers \Engelsystem\Controllers\AuthController::postLogin - * @covers \Engelsystem\Controllers\AuthController::authenticateUser */ public function testPostLogin() { @@ -51,10 +61,12 @@ class AuthControllerTest extends TestCase $request = new Request(); /** @var Response|MockObject $response */ $response = $this->createMock(Response::class); - /** @var SessionInterface|MockObject $session */ /** @var UrlGeneratorInterface|MockObject $url */ /** @var Authenticator|MockObject $auth */ - list(, $session, $url, $auth) = $this->getMocks(); + list(, , $url, $auth) = $this->getMocks(); + $session = new Session(new MockArraySessionStorage()); + /** @var Validator|MockObject $validator */ + $validator = new Validator(new Validates()); $user = new User([ 'name' => 'foo', @@ -63,7 +75,7 @@ class AuthControllerTest extends TestCase 'api_key' => '', 'last_login_at' => null, ]); - $user->forceFill(['id' => 42,]); + $user->forceFill(['id' => 42]); $user->save(); $settings = new Settings(['language' => 'de_DE', 'theme' => '']); @@ -76,41 +88,42 @@ class AuthControllerTest extends TestCase ->with('foo', 'bar') ->willReturnOnConsecutiveCalls(null, $user); - $response->expects($this->exactly(3)) + $response->expects($this->once()) ->method('withView') - ->withConsecutive( - ['pages/login', ['errors' => ['auth.no-nickname'], 'show_password_recovery' => true]], - ['pages/login', ['errors' => ['auth.no-password'], 'show_password_recovery' => true]], - ['pages/login', ['errors' => ['auth.not-found'], 'show_password_recovery' => true]]) + ->with('pages/login', ['errors' => Collection::make(['auth.not-found']), 'show_password_recovery' => true]) ->willReturn($response); $response->expects($this->once()) ->method('redirectTo') ->with('news') ->willReturn($response); - $session->expects($this->once()) - ->method('invalidate'); - - $session->expects($this->exactly(2)) - ->method('set') - ->withConsecutive( - ['user_id', 42], - ['locale', 'de_DE'] - ); - + // No credentials $controller = new AuthController($response, $session, $url, $auth); - $controller->postLogin($request); + $controller->setValidator($validator); + try { + $controller->postLogin($request); + $this->fail('Login without credentials possible'); + } catch (ValidationException $e) { + } + + // Missing password + $request = new Request([], ['login' => 'foo']); + try { + $controller->postLogin($request); + $this->fail('Login without password possible'); + } catch (ValidationException $e) { + } - $request = new Request(['login' => 'foo']); - $controller->postLogin($request); - - $request = new Request(['login' => 'foo', 'password' => 'bar']); // No user found + $request = new Request([], ['login' => 'foo', 'password' => 'bar']); $controller->postLogin($request); + $this->assertEquals([], $session->all()); + // Authenticated user $controller->postLogin($request); $this->assertNotNull($user->last_login_at); + $this->assertEquals(['user_id' => 42, 'locale' => 'de_DE'], $session->all()); } /** -- cgit v1.2.3-54-g00ecf From 6743106d9a8c760580690aab704f908766731801 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Wed, 10 Jul 2019 13:34:15 +0200 Subject: Replaced validation with `respect/validation` --- composer.json | 1 + src/Http/Validation/Rules/In.php | 21 ++ src/Http/Validation/Rules/NotIn.php | 15 ++ src/Http/Validation/Validates.php | 154 ----------- src/Http/Validation/ValidationServiceProvider.php | 3 - src/Http/Validation/Validator.php | 61 +++-- tests/Unit/Controllers/AuthControllerTest.php | 3 +- tests/Unit/Http/Validation/Rules/InTest.php | 19 ++ tests/Unit/Http/Validation/Rules/NotInTest.php | 20 ++ tests/Unit/Http/Validation/ValidatesTest.php | 308 ---------------------- tests/Unit/Http/Validation/ValidatorTest.php | 42 ++- 11 files changed, 155 insertions(+), 492 deletions(-) create mode 100644 src/Http/Validation/Rules/In.php create mode 100644 src/Http/Validation/Rules/NotIn.php delete mode 100644 src/Http/Validation/Validates.php create mode 100644 tests/Unit/Http/Validation/Rules/InTest.php create mode 100644 tests/Unit/Http/Validation/Rules/NotInTest.php delete mode 100644 tests/Unit/Http/Validation/ValidatesTest.php (limited to 'tests/Unit/Controllers/AuthControllerTest.php') diff --git a/composer.json b/composer.json index b2b70789..a1f2101b 100644 --- a/composer.json +++ b/composer.json @@ -32,6 +32,7 @@ "psr/container": "^1.0", "psr/http-server-middleware": "^1.0", "psr/log": "^1.1", + "respect/validation": "^1.1", "swiftmailer/swiftmailer": "^6.2", "symfony/http-foundation": "^4.3", "symfony/psr-http-message-bridge": "^1.2", diff --git a/src/Http/Validation/Rules/In.php b/src/Http/Validation/Rules/In.php new file mode 100644 index 00000000..d585cc3d --- /dev/null +++ b/src/Http/Validation/Rules/In.php @@ -0,0 +1,21 @@ +validateParameterCount(2, $parameters, __FUNCTION__); - $size = $this->getSize($value); - - return $size >= $parameters[0] && $size <= $parameters[1]; - } - - /** - * @param mixed $value - * @return bool - */ - public function bool($value): bool - { - return in_array($value, ['1', 1, true, '0', 0, false], true); - } - - /** - * @param mixed $value - * @param array $parameters ['1,2,3,56,7'] - * @return bool - */ - public function in($value, $parameters): bool - { - $this->validateParameterCount(1, $parameters, __FUNCTION__); - - return in_array($value, explode(',', $parameters[0])); - } - - /** - * @param mixed $value - * @return bool - */ - public function int($value): bool - { - return filter_var($value, FILTER_VALIDATE_INT) !== false; - } - - /** - * @param string $value - * @param array $parameters ['max'] - * @return bool - */ - public function max($value, $parameters): bool - { - $this->validateParameterCount(1, $parameters, __FUNCTION__); - $size = $this->getSize($value); - - return $size <= $parameters[0]; - } - - /** - * @param string $value - * @param array $parameters ['min'] - * @return bool - */ - public function min($value, $parameters) - { - $this->validateParameterCount(1, $parameters, __FUNCTION__); - $size = $this->getSize($value); - - return $size >= $parameters[0]; - } - - /** - * @param mixed $value - * @param array $parameters ['1,2,3,56,7'] - * @return bool - */ - public function notIn($value, $parameters): bool - { - $this->validateParameterCount(1, $parameters, __FUNCTION__); - - return !$this->in($value, $parameters); - } - - /** - * @param mixed $value - * @return bool - */ - public function numeric($value): bool - { - return is_numeric($value); - } - - /** - * @param mixed $value - * @return bool - */ - public function required($value): bool - { - if ( - is_null($value) - || (is_string($value) && trim($value) === '') - ) { - return false; - } - - return true; - } - - /** - * @param mixed $value - * @return int|float - */ - protected function getSize($value) - { - if (is_numeric($value)) { - return $value; - } - - return mb_strlen($value); - } - - /** - * @param int $count - * @param array $parameters - * @param string $rule - * - * @throws InvalidArgumentException - */ - protected function validateParameterCount(int $count, array $parameters, string $rule) - { - if (count($parameters) < $count) { - throw new InvalidArgumentException(sprintf( - 'The rule "%s" requires at least %d parameters', - $rule, - $count - )); - } - } -} diff --git a/src/Http/Validation/ValidationServiceProvider.php b/src/Http/Validation/ValidationServiceProvider.php index 2f1c6359..14530ae6 100644 --- a/src/Http/Validation/ValidationServiceProvider.php +++ b/src/Http/Validation/ValidationServiceProvider.php @@ -10,9 +10,6 @@ class ValidationServiceProvider extends ServiceProvider { public function register() { - $validates = $this->app->make(Validates::class); - $this->app->instance(Validates::class, $validates); - $validator = $this->app->make(Validator::class); $this->app->instance(Validator::class, $validator); $this->app->instance('validator', $validator); diff --git a/src/Http/Validation/Validator.php b/src/Http/Validation/Validator.php index a9235a5f..0bd846bd 100644 --- a/src/Http/Validation/Validator.php +++ b/src/Http/Validation/Validator.php @@ -4,25 +4,23 @@ namespace Engelsystem\Http\Validation; use Illuminate\Support\Str; use InvalidArgumentException; +use Respect\Validation\Exceptions\ComponentException; +use Respect\Validation\Validator as RespectValidator; class Validator { - /** @var Validates */ - protected $validate; - /** @var string[] */ protected $errors = []; /** @var array */ protected $data = []; - /** - * @param Validates $validate - */ - public function __construct(Validates $validate) - { - $this->validate = $validate; - } + /** @var array */ + protected $mapping = [ + 'accepted' => 'TrueVal', + 'int' => 'IntVal', + 'required' => 'NotEmpty', + ]; /** * @param array $data @@ -35,29 +33,56 @@ class Validator $this->data = []; foreach ($rules as $key => $values) { + $v = new RespectValidator(); + $v->with('\\Engelsystem\\Http\\Validation\\Rules', true); + + $value = isset($data[$key]) ? $data[$key] : null; + foreach (explode('|', $values) as $parameters) { $parameters = explode(':', $parameters); $rule = array_shift($parameters); $rule = Str::camel($rule); + $rule = $this->map($rule); - if (!method_exists($this->validate, $rule)) { - throw new InvalidArgumentException('Unknown validation rule: ' . $rule); + try { + call_user_func_array([$v, $rule], $parameters); + } catch (ComponentException $e) { + throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } - $value = isset($data[$key]) ? $data[$key] : null; - if (!$this->validate->{$rule}($value, $parameters, $data)) { - $this->errors[$key][] = implode('.', ['validation', $key, $rule]); - - continue; + if ($v->validate($value)) { + $this->data[$key] = $value; + } else { + $this->errors[$key][] = implode('.', ['validation', $key, $this->mapBack($rule)]); } - $this->data[$key] = $value; + $v->removeRules(); } } return empty($this->errors); } + /** + * @param string $rule + * @return string + */ + protected function map($rule) + { + return $this->mapping[$rule] ?? $rule; + } + + /** + * @param string $rule + * @return string + */ + protected function mapBack($rule) + { + $mapping = array_flip($this->mapping); + + return $mapping[$rule] ?? $rule; + } + /** * @return array */ diff --git a/tests/Unit/Controllers/AuthControllerTest.php b/tests/Unit/Controllers/AuthControllerTest.php index d3dbfa4b..c3d9659c 100644 --- a/tests/Unit/Controllers/AuthControllerTest.php +++ b/tests/Unit/Controllers/AuthControllerTest.php @@ -8,7 +8,6 @@ use Engelsystem\Http\Exceptions\ValidationException; use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Http\UrlGeneratorInterface; -use Engelsystem\Http\Validation\Validates; use Engelsystem\Http\Validation\Validator; use Engelsystem\Models\User\Settings; use Engelsystem\Models\User\User; @@ -66,7 +65,7 @@ class AuthControllerTest extends TestCase list(, , $url, $auth) = $this->getMocks(); $session = new Session(new MockArraySessionStorage()); /** @var Validator|MockObject $validator */ - $validator = new Validator(new Validates()); + $validator = new Validator(); $user = new User([ 'name' => 'foo', diff --git a/tests/Unit/Http/Validation/Rules/InTest.php b/tests/Unit/Http/Validation/Rules/InTest.php new file mode 100644 index 00000000..e5688d90 --- /dev/null +++ b/tests/Unit/Http/Validation/Rules/InTest.php @@ -0,0 +1,19 @@ +assertEquals(['foo', 'bar'], $rule->haystack); + } +} diff --git a/tests/Unit/Http/Validation/Rules/NotInTest.php b/tests/Unit/Http/Validation/Rules/NotInTest.php new file mode 100644 index 00000000..9be12336 --- /dev/null +++ b/tests/Unit/Http/Validation/Rules/NotInTest.php @@ -0,0 +1,20 @@ +assertTrue($rule->validate('lorem')); + $this->assertFalse($rule->validate('foo')); + } +} diff --git a/tests/Unit/Http/Validation/ValidatesTest.php b/tests/Unit/Http/Validation/ValidatesTest.php deleted file mode 100644 index 5cf0447a..00000000 --- a/tests/Unit/Http/Validation/ValidatesTest.php +++ /dev/null @@ -1,308 +0,0 @@ -assertTrue($val->accepted($value) === $result); - } - - /** - * @return array - */ - public function provideBetween() - { - return [ - ['42', [10, 100]], - [42.5, [42, 43]], - [42, [42, 1000]], - [1337, [0, 99], false], - [-17, [32, 45], false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::between - * @param mixed $value - * @param array $parameters - * @param bool $result - * @dataProvider provideBetween - */ - public function testBetween($value, array $parameters, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->between($value, $parameters) === $result); - } - - /** - * @return array - */ - public function provideBool() - { - return [ - ['1'], - [1], - [true], - ['0'], - [0], - [false], - ['true', false], - ['false', false], - ['yes', false], - ['no', false], - ['bool', false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::bool - * @param mixed $value - * @param bool $result - * @dataProvider provideBool - */ - public function testBool($value, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->bool($value) === $result); - } - - /** - * @return array - */ - public function provideIn() - { - return [ - ['lorem', ['lorem,ipsum,dolor']], - [99, ['66,77,88,99,111']], - [4, ['1,3,5,7'], false], - ['toggle', ['on,off'], false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::in - * @param mixed $value - * @param array $parameters - * @param bool $result - * @dataProvider provideIn - */ - public function testIn($value, array $parameters, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->in($value, $parameters) === $result); - } - - /** - * @return array - */ - public function provideInt() - { - return [ - ['1337'], - [42], - ['0'], - [false, false], - ['12asd1', false], - ['one', false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::int - * @param mixed $value - * @param bool $result - * @dataProvider provideInt - */ - public function testInt($value, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->int($value) === $result); - } - - /** - * @return array - */ - public function provideMax() - { - return [ - ['99', [100]], - [-42, [1024]], - [99, [99]], - [100, [10], false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::max - * @param mixed $value - * @param array $parameters - * @param bool $result - * @dataProvider provideMax - */ - public function testMax($value, array $parameters, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->max($value, $parameters) === $result); - } - - /** - * @return array - */ - public function provideMin() - { - return [ - [32, [0]], - [7, [7]], - ['99', [10]], - [3, [42], false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::min - * @param mixed $value - * @param array $parameters - * @param bool $result - * @dataProvider provideMin - */ - public function testMin($value, array $parameters, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->min($value, $parameters) === $result); - } - - /** - * @return array - */ - public function provideNotIn() - { - return [ - [77, ['50,60,70']], - ['test', ['coding,deployment']], - ['PHP', ['Java,PHP,bash'], false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::notIn - * @param mixed $value - * @param array $parameters - * @param bool $result - * @dataProvider provideNotIn - */ - public function testNotIn($value, array $parameters, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->notIn($value, $parameters) === $result); - } - - /** - * @return array - */ - public function provideNumeric() - { - return [ - [77], - ['42'], - ['1337e0'], - ['123f00', false], - [null, false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::numeric - * @param mixed $value - * @param bool $result - * @dataProvider provideNumeric - */ - public function testNumeric($value, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->numeric($value) === $result); - } - - /** - * @return array - */ - public function provideRequired() - { - return [ - ['Lorem ipsum'], - ['1234'], - [1234], - ['0'], - [0], - ['', false], - [' ', false], - [null, false], - ]; - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::required - * @param mixed $value - * @param bool $result - * @dataProvider provideRequired - */ - public function testRequired($value, bool $result = true) - { - $val = new Validates; - $this->assertTrue($val->required($value) === $result); - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::getSize - */ - public function testGetSize() - { - $val = new Validates; - $this->assertTrue($val->max(42, [999])); - $this->assertTrue($val->max('99', [100])); - $this->assertFalse($val->max('101', [100])); - $this->assertTrue($val->max('lorem', [5])); - $this->assertFalse($val->max('Lorem Ipsum', [5])); - } - - /** - * @covers \Engelsystem\Http\Validation\Validates::validateParameterCount - */ - public function testValidateParameterCount() - { - $val = new Validates; - $this->assertTrue($val->between(42, [1, 100])); - - $this->expectException(InvalidArgumentException::class); - $val->between(42, [1]); - } -} diff --git a/tests/Unit/Http/Validation/ValidatorTest.php b/tests/Unit/Http/Validation/ValidatorTest.php index 799265ec..0790b7a8 100644 --- a/tests/Unit/Http/Validation/ValidatorTest.php +++ b/tests/Unit/Http/Validation/ValidatorTest.php @@ -2,7 +2,6 @@ namespace Engelsystem\Test\Unit\Http\Validation; -use Engelsystem\Http\Validation\Validates; use Engelsystem\Http\Validation\Validator; use InvalidArgumentException; use PHPUnit\Framework\TestCase; @@ -10,19 +9,18 @@ use PHPUnit\Framework\TestCase; class ValidatorTest extends TestCase { /** - * @covers \Engelsystem\Http\Validation\Validator::__construct * @covers \Engelsystem\Http\Validation\Validator::validate * @covers \Engelsystem\Http\Validation\Validator::getData * @covers \Engelsystem\Http\Validation\Validator::getErrors */ public function testValidate() { - $val = new Validator(new Validates); + $val = new Validator(); $this->assertTrue($val->validate( - ['foo' => 'bar', 'lorem' => 'on'], - ['foo' => 'required|not_in:lorem,ipsum,dolor', 'lorem' => 'accepted'] + ['foo' => 'bar', 'lorem' => 'on', 'dolor' => 'bla'], + ['lorem' => 'accepted'] )); - $this->assertEquals(['foo' => 'bar', 'lorem' => 'on'], $val->getData()); + $this->assertEquals(['lorem' => 'on'], $val->getData()); $this->assertFalse($val->validate( [], @@ -39,7 +37,7 @@ class ValidatorTest extends TestCase */ public function testValidateNotImplemented() { - $val = new Validator(new Validates); + $val = new Validator(); $this->expectException(InvalidArgumentException::class); $val->validate( @@ -47,4 +45,34 @@ class ValidatorTest extends TestCase ['foo' => 'never_implemented'] ); } + + /** + * @covers \Engelsystem\Http\Validation\Validator::map + * @covers \Engelsystem\Http\Validation\Validator::mapBack + */ + public function testValidateMapping() + { + $val = new Validator(); + $this->assertTrue($val->validate( + ['foo' => 'bar'], + ['foo' => 'required'] + )); + $this->assertTrue($val->validate( + ['foo' => '0'], + ['foo' => 'int'] + )); + $this->assertTrue($val->validate( + ['foo' => 'on'], + ['foo' => 'accepted'] + )); + + $this->assertFalse($val->validate( + [], + ['lorem' => 'required'] + )); + $this->assertEquals( + ['lorem' => ['validation.lorem.required']], + $val->getErrors() + ); + } } -- cgit v1.2.3-54-g00ecf