Merged in validations-architecture-backend (pull request #17)
Validations architecture backend
This commit is contained in:
commit
48d5cf9226
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"require": {
|
||||
"slim/slim": "~2.0",
|
||||
"gabordemooij/redbean": "~4.2"
|
||||
"gabordemooij/redbean": "~4.2",
|
||||
"respect/validation": "^1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "5.0.*"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
|
||||
class CreateController extends Controller {
|
||||
const PATH = '/create';
|
||||
|
||||
|
@ -8,44 +10,36 @@ class CreateController extends Controller {
|
|||
private $departmentId;
|
||||
private $language;
|
||||
|
||||
public function handler() {
|
||||
$this->requestTicketData();
|
||||
|
||||
$validateResult = $this->validateData();
|
||||
|
||||
if ($validateResult !== true) {
|
||||
Response::respondError($validateResult);
|
||||
} else {
|
||||
$this->storeTicket();
|
||||
|
||||
Response::respondSuccess();
|
||||
}
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'any',
|
||||
'requestData' => [
|
||||
'title' => [
|
||||
'validation' => DataValidator::length(3, 30),
|
||||
'error' => ERRORS::INVALID_TITLE
|
||||
],
|
||||
'content' => [
|
||||
'validation' => DataValidator::length(10, 500),
|
||||
'error' => ERRORS::INVALID_CONTENT
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
private function requestTicketData() {
|
||||
public function handler() {
|
||||
$this->storeRequestData();
|
||||
$this->storeTicket();
|
||||
|
||||
Response::respondSuccess();
|
||||
}
|
||||
|
||||
private function storeRequestData() {
|
||||
$this->title = Controller::request('title');
|
||||
$this->content = Controller::request('content');
|
||||
$this->departmentId = Controller::request('departmentId');
|
||||
$this->language = Controller::request('language');
|
||||
}
|
||||
|
||||
private function validateData() {
|
||||
if (strlen($this->title) < 3) {
|
||||
return ERRORS::SHORT_TITLE;
|
||||
}
|
||||
if (strlen($this->title) > 30) {
|
||||
return ERRORS::LONG_TITLE;
|
||||
}
|
||||
if (strlen($this->content) < 5) {
|
||||
return ERRORS::SHORT_CONTENT;
|
||||
}
|
||||
if (strlen($this->content) > 500) {
|
||||
return ERRORS::LONG_CONTENT;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function storeTicket() {
|
||||
$ticket = new Ticket();
|
||||
$ticket->setProperties(array(
|
||||
|
@ -55,7 +49,7 @@ class CreateController extends Controller {
|
|||
'language' => $this->language,
|
||||
'department' => $this->departmentId,
|
||||
'file' => '',
|
||||
'date' => date("F j, Y, g:i a"),
|
||||
'date' => date('F j, Y, g:i a'),
|
||||
'unread' => false,
|
||||
'closed' => false,
|
||||
'author' => '',
|
||||
|
|
|
@ -5,6 +5,13 @@ class LoginController extends Controller {
|
|||
|
||||
private $userInstance;
|
||||
private $session;
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'any',
|
||||
'requestData' => []
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
if ($this->isAlreadyLoggedIn()) {
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
class LogoutController extends Controller {
|
||||
const PATH = '/logout';
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'any',
|
||||
'requestData' => []
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
$session = Session::getInstance();
|
||||
$session->closeSession();
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
class SignUpController extends Controller {
|
||||
const PATH = '/signup';
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'any',
|
||||
'requestData' => []
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
$email = Controller::request('email');
|
||||
$password = Controller::request('password');
|
||||
|
|
|
@ -20,13 +20,13 @@ spl_autoload_register(function ($class) {
|
|||
$classPath = "models/{$class}.php";
|
||||
|
||||
if(file_exists($classPath)) {
|
||||
include $classPath;
|
||||
include_once $classPath;
|
||||
}
|
||||
});
|
||||
|
||||
// LOAD CONTROLLERS
|
||||
foreach (glob('controllers/*.php') as $controller) {
|
||||
include $controller;
|
||||
include_once $controller;
|
||||
}
|
||||
|
||||
$app->run();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
require_once 'libs/Validator.php';
|
||||
|
||||
abstract class Controller {
|
||||
|
||||
|
@ -6,40 +7,37 @@ abstract class Controller {
|
|||
* Instance-related stuff
|
||||
*/
|
||||
abstract public function handler();
|
||||
abstract public function validations();
|
||||
|
||||
public function getHandler() {
|
||||
return function () {
|
||||
try {
|
||||
$this->validate();
|
||||
} catch (ValidationException $exception) {
|
||||
Response::respondError($exception->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
$this->handler();
|
||||
};
|
||||
}
|
||||
|
||||
public function validate() {
|
||||
$validator = new Validator();
|
||||
|
||||
$validator->validate($this->validations());
|
||||
}
|
||||
|
||||
public static function request($key) {
|
||||
$app = self::getAppInstance();
|
||||
|
||||
return $app->request()->post($key);
|
||||
}
|
||||
|
||||
public static function checkUserLogged() {
|
||||
$session = Session::getInstance();
|
||||
|
||||
return $session->checkAuthentication(array(
|
||||
'user_id' => self::request('csrf_userid'),
|
||||
'token' => self::request('csrf_token')
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
public static function getLoggedUser() {
|
||||
return User::getUser((int)self::request('csrf_userid'));
|
||||
}
|
||||
|
||||
public static function checkStaffLogged() {
|
||||
return self::checkUserLogged() && (self::getLoggedUser()->admin === 1);
|
||||
}
|
||||
|
||||
public static function checkAdminLogged() {
|
||||
return self::checkUserLogged() && (self::getLoggedUser()->admin === 2);
|
||||
}
|
||||
|
||||
public static function getAppInstance() {
|
||||
return \Slim\Slim::getInstance();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
require_once 'libs/Controller.php';
|
||||
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
|
||||
class ValidationException extends Exception {}
|
||||
|
||||
class Validator {
|
||||
|
||||
public function validate($config) {
|
||||
$this->validatePermissions($config['permission']);
|
||||
$this->validateAllRequestData($config['requestData']);
|
||||
}
|
||||
|
||||
private function validatePermissions($permission) {
|
||||
$permissions = [
|
||||
'any' => true,
|
||||
'user' => $this->isUserLogged(),
|
||||
'staff' => $this->isStaffLogged(),
|
||||
'admin' => $this->isAdminLogged()
|
||||
];
|
||||
|
||||
if (!$permissions[$permission]) {
|
||||
throw new ValidationException(ERRORS::NO_PERMISSION);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateAllRequestData($requestDataValidations) {
|
||||
foreach ($requestDataValidations as $requestDataKey => $requestDataValidationConfig) {
|
||||
$requestDataValue = Controller::request($requestDataKey);
|
||||
$requestDataValidator = $requestDataValidationConfig['validation'];
|
||||
$requestDataValidationErrorMessage = $requestDataValidationConfig['error'];
|
||||
|
||||
$this->validateData($requestDataValue, $requestDataValidator, $requestDataValidationErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateData($value, DataValidator $dataValidator, $error) {
|
||||
if (!$dataValidator->validate($value)) {
|
||||
throw new ValidationException($error);
|
||||
}
|
||||
}
|
||||
|
||||
private function isUserLogged() {
|
||||
$session = Session::getInstance();
|
||||
|
||||
return $session->checkAuthentication(array(
|
||||
'userId' => Controller::request('csrf_userid'),
|
||||
'token' => Controller::request('csrf_token')
|
||||
));
|
||||
}
|
||||
|
||||
private function isStaffLogged() {
|
||||
return $this->isUserLogged() && (Controller::getLoggedUser()->admin === 1);
|
||||
}
|
||||
|
||||
private function isAdminLogged() {
|
||||
return $this->isUserLogged() && (Controller::getLoggedUser()->admin === 2);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,8 +2,7 @@
|
|||
class ERRORS {
|
||||
const INVALID_CREDENTIALS = 'User or password is not defined';
|
||||
const SESSION_EXISTS = 'User is already logged in';
|
||||
const SHORT_TITLE = 'Title is too short';
|
||||
const LONG_TITLE = 'Title is very long';
|
||||
const SHORT_CONTENT = 'Content is too short';
|
||||
const LONG_CONTENT = 'Content is very long';
|
||||
const NO_PERMISSION = 'You have no permission to access';
|
||||
const INVALID_TITLE = 'Invalid title';
|
||||
const INVALID_CONTENT = 'Invalid content';
|
||||
}
|
||||
|
|
|
@ -38,8 +38,12 @@ class Session {
|
|||
}
|
||||
|
||||
public function checkAuthentication($data) {
|
||||
return $this->getStoredData('userId') === $data['userId'] &&
|
||||
$this->getStoredData('token') === $data['token'];
|
||||
$userId = $this->getStoredData('userId');
|
||||
$token = $this->getStoredData('token');
|
||||
|
||||
return $userId && $token &&
|
||||
$userId === $data['userId'] &&
|
||||
$token === $data['token'];
|
||||
}
|
||||
|
||||
public function isLoggedWithId($userId) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
describe '/user/login' do
|
||||
describe '/ticket/create' do
|
||||
it 'should fail if title is too short' do
|
||||
result = request('/ticket/create',{
|
||||
result = request('/ticket/create', {
|
||||
title: 'GG'
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('Title is too short')
|
||||
(result['message']).should.equal('Invalid title')
|
||||
|
||||
end
|
||||
|
||||
|
@ -15,7 +15,7 @@ describe '/user/login' do
|
|||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('Title is very long')
|
||||
(result['message']).should.equal('Invalid title')
|
||||
|
||||
end
|
||||
|
||||
|
@ -26,7 +26,7 @@ describe '/user/login' do
|
|||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('Content is too short')
|
||||
(result['message']).should.equal('Invalid content')
|
||||
end
|
||||
|
||||
it 'should fail if content is very long' do
|
||||
|
@ -39,7 +39,7 @@ describe '/user/login' do
|
|||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('Content is very long')
|
||||
(result['message']).should.equal('Invalid content')
|
||||
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue