diff --git a/server/composer.json b/server/composer.json index bb0af29e..960dd0ce 100644 --- a/server/composer.json +++ b/server/composer.json @@ -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.*" diff --git a/server/controllers/ticket/create.php b/server/controllers/ticket/create.php index 845b415c..a0e86e1f 100644 --- a/server/controllers/ticket/create.php +++ b/server/controllers/ticket/create.php @@ -1,5 +1,7 @@ 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' => '', diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php index 396f5acf..54357d80 100644 --- a/server/controllers/user/login.php +++ b/server/controllers/user/login.php @@ -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()) { diff --git a/server/controllers/user/logout.php b/server/controllers/user/logout.php index cab4cccd..60e51c80 100644 --- a/server/controllers/user/logout.php +++ b/server/controllers/user/logout.php @@ -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(); diff --git a/server/controllers/user/signup.php b/server/controllers/user/signup.php index a38559d3..aa3828e8 100644 --- a/server/controllers/user/signup.php +++ b/server/controllers/user/signup.php @@ -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'); diff --git a/server/index.php b/server/index.php index d4617e88..850db116 100644 --- a/server/index.php +++ b/server/index.php @@ -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(); diff --git a/server/libs/Controller.php b/server/libs/Controller.php index 11770fc7..6f809351 100644 --- a/server/libs/Controller.php +++ b/server/libs/Controller.php @@ -1,4 +1,5 @@ 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(); } diff --git a/server/libs/Validator.php b/server/libs/Validator.php new file mode 100644 index 00000000..3ab52485 --- /dev/null +++ b/server/libs/Validator.php @@ -0,0 +1,61 @@ +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); + } + +} \ No newline at end of file diff --git a/server/models/ERRORS.php b/server/models/ERRORS.php index 76d29f3c..a8dbe39c 100644 --- a/server/models/ERRORS.php +++ b/server/models/ERRORS.php @@ -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'; } diff --git a/server/models/Session.php b/server/models/Session.php index 3ca9dedd..3c9d4f5e 100644 --- a/server/models/Session.php +++ b/server/models/Session.php @@ -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) { diff --git a/tests/ticket/create.rb b/tests/ticket/create.rb index 8742c287..c8b717f6 100644 --- a/tests/ticket/create.rb +++ b/tests/ticket/create.rb @@ -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