mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-30 01:05:18 +02:00
Merge branch 'master' into Add-email-sender-class
# Conflicts: # server/composer.json # server/controllers/user/signup.php
This commit is contained in:
commit
948b476c12
@ -1,13 +1,23 @@
|
|||||||
import React from 'react';
|
const React = require('react');
|
||||||
import {Router, Route, IndexRoute, browserHistory} from 'react-router';
|
const {Router, Route, IndexRoute, browserHistory} = require('react-router');
|
||||||
|
|
||||||
import App from 'app/App';
|
const App = require('app/App');
|
||||||
import DemoPage from 'app/demo/components-demo-page';
|
const DemoPage = require('app/demo/components-demo-page');
|
||||||
|
|
||||||
import MainLayout from 'app/main/main-layout';
|
const MainLayout = require('app/main/main-layout');
|
||||||
import MainHomePage from 'app/main/main-home/main-home-page';
|
const MainHomePage = require('app/main/main-home/main-home-page');
|
||||||
import MainSignUpPage from 'app/main/main-signup/main-signup-page';
|
const MainSignUpPage = require('app/main/main-signup/main-signup-page');
|
||||||
|
|
||||||
|
const DashboardLayout = require('app/main/dashboard/dashboard-layout');
|
||||||
|
|
||||||
|
const DashboardListTicketsPage = require('app/main/dashboard/dashboard-list-tickets/dashboard-list-tickets-page');
|
||||||
|
const DashboardListArticlesPage = require('app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page');
|
||||||
|
|
||||||
|
const DashboardCreateTicketPage = require('app/main/dashboard/dashboard-create-ticket/dashboard-create-ticket-page');
|
||||||
|
const DashboardEditProfilePage = require('app/main/dashboard/dashboard-edit-profile/dashboard-edit-profile-page');
|
||||||
|
|
||||||
|
const DashboardArticlePage = require('app/main/dashboard/dashboard-article/dashboard-article-page');
|
||||||
|
const DashboardTicketPage = require('app/main/dashboard/dashboard-ticket/dashboard-ticket-page');
|
||||||
|
|
||||||
export default (
|
export default (
|
||||||
<Router history={browserHistory}>
|
<Router history={browserHistory}>
|
||||||
@ -15,6 +25,16 @@ export default (
|
|||||||
<Route path='/app' component={MainLayout}>
|
<Route path='/app' component={MainLayout}>
|
||||||
<IndexRoute component={MainHomePage} />
|
<IndexRoute component={MainHomePage} />
|
||||||
<Route path='signup' component={MainSignUpPage}/>
|
<Route path='signup' component={MainSignUpPage}/>
|
||||||
|
<Route path='dashboard' component={DashboardLayout}>
|
||||||
|
<IndexRoute component={DashboardListTicketsPage} />
|
||||||
|
<Route path='articles' component={DashboardListArticlesPage}/>
|
||||||
|
|
||||||
|
<Route path='create-ticket' component={DashboardCreateTicketPage}/>
|
||||||
|
<Route path='edit-profile' component={DashboardEditProfilePage}/>
|
||||||
|
|
||||||
|
<Route path='article' component={DashboardArticlePage}/>
|
||||||
|
<Route path='ticket' component={DashboardTicketPage}/>
|
||||||
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route name='Demo' path='demo' component={DemoPage} />
|
<Route name='Demo' path='demo' component={DemoPage} />
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DashboardArticlePage = React.createClass({
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
DASHBOARD ARTICLE
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardArticlePage;
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DashboardCreateTicketPage = React.createClass({
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
DASHBOARD CREATE TICKET
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardCreateTicketPage;
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DashboardEditProfilePage = React.createClass({
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
DASHBOARD EDIT PROFILE
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardEditProfilePage;
|
16
client/src/app/main/dashboard/dashboard-layout.js
Normal file
16
client/src/app/main/dashboard/dashboard-layout.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import DashboardMenu from 'app/main/dashboard/dashboard-menu';
|
||||||
|
|
||||||
|
const DashboardLayout = React.createClass({
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div><DashboardMenu location={this.props.location} /></div>
|
||||||
|
<div>{this.props.children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardLayout;
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DashboardListArticlesPage = React.createClass({
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
DASHBOARD ARTICLES LIST
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardListArticlesPage;
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DashboardListTicketsPage = React.createClass({
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
DASHBOARD TICKET LIST
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardListTicketsPage;
|
57
client/src/app/main/dashboard/dashboard-menu.js
Normal file
57
client/src/app/main/dashboard/dashboard-menu.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import Menu from 'core-components/menu';
|
||||||
|
|
||||||
|
let dashboardRoutes = [
|
||||||
|
{ path: '/app/dashboard', text: 'Ticket List' },
|
||||||
|
{ path: '/app/dashboard/create-ticket', text: 'Create Ticket' },
|
||||||
|
{ path: '/app/dashboard/articles', text: 'View Articles' },
|
||||||
|
{ path: '/app/dashboard/edit-profile', text: 'Edit Profile' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const DashboardMenu = React.createClass({
|
||||||
|
contextTypes: {
|
||||||
|
router: React.PropTypes.object
|
||||||
|
},
|
||||||
|
|
||||||
|
propTypes: {
|
||||||
|
location: React.PropTypes.object
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Menu {...this.getProps()} />
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
getProps() {
|
||||||
|
return {
|
||||||
|
items: this.getMenuItems(),
|
||||||
|
selectedIndex: this.getSelectedIndex(),
|
||||||
|
onItemClick: this.goToPathByIndex
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getMenuItems: function () {
|
||||||
|
return dashboardRoutes.map(this.getMenuItem);
|
||||||
|
},
|
||||||
|
|
||||||
|
getMenuItem(item) {
|
||||||
|
return {
|
||||||
|
content: item.text
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getSelectedIndex() {
|
||||||
|
let pathname = this.props.location.pathname;
|
||||||
|
|
||||||
|
return _.findIndex(dashboardRoutes, {path: pathname});
|
||||||
|
},
|
||||||
|
|
||||||
|
goToPathByIndex(itemIndex) {
|
||||||
|
this.context.router.push(dashboardRoutes[itemIndex].path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardMenu;
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const DashboardTicketPage = React.createClass({
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
DASHBOARD TICKET PAGE
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default DashboardTicketPage;
|
@ -26,7 +26,7 @@ const Icon = React.createClass({
|
|||||||
|
|
||||||
renderFlag() {
|
renderFlag() {
|
||||||
return (
|
return (
|
||||||
<img className={this.props.className} src={`../images/icons/${this.props.name}.png`} aria-hidden="true" />
|
<img className={this.props.className} src={`/images/icons/${this.props.name}.png`} aria-hidden="true" />
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
&__list-item {
|
&__list-item {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|
||||||
|
&_selected,
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $primary-red;
|
background-color: $primary-red;
|
||||||
color: white;
|
color: white;
|
||||||
@ -23,6 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&_secondary {
|
&_secondary {
|
||||||
|
.menu__list-item_selected,
|
||||||
.menu__list-item:hover {
|
.menu__list-item:hover {
|
||||||
background-color: $secondary-blue;
|
background-color: $secondary-blue;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"slim/slim": "~2.0",
|
"slim/slim": "~2.0",
|
||||||
"gabordemooij/redbean": "~4.2",
|
"gabordemooij/redbean": "~4.2",
|
||||||
|
"respect/validation": "^1.1",
|
||||||
"phpmailer/phpmailer": "^5.2"
|
"phpmailer/phpmailer": "^5.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
include 'ticket/create.php';
|
include 'ticket/create.php';
|
||||||
|
include 'ticket/comment.php';
|
||||||
|
|
||||||
$ticketControllers = new ControllerGroup();
|
$ticketControllers = new ControllerGroup();
|
||||||
$ticketControllers->setGroupPath('/ticket');
|
$ticketControllers->setGroupPath('/ticket');
|
||||||
|
|
||||||
$ticketControllers->addController(new CreateController);
|
$ticketControllers->addController(new CreateController);
|
||||||
|
$ticketControllers->addController(new CommentController);
|
||||||
|
|
||||||
$ticketControllers->finalize();
|
$ticketControllers->finalize();
|
39
server/controllers/ticket/comment.php
Normal file
39
server/controllers/ticket/comment.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
use RedBeanPHP\Facade as RedBean;
|
||||||
|
|
||||||
|
class CommentController extends Controller {
|
||||||
|
const PATH = '/comment';
|
||||||
|
|
||||||
|
private $ticketId;
|
||||||
|
private $content;
|
||||||
|
|
||||||
|
public function validations() {
|
||||||
|
return [
|
||||||
|
'permission' => 'any',
|
||||||
|
'requestData' => []
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handler() {
|
||||||
|
$this->requestData();
|
||||||
|
$this->storeComment();
|
||||||
|
|
||||||
|
Response::respondSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function requestData() {
|
||||||
|
$this->ticketId = Controller::request('ticketId');
|
||||||
|
$this->content = Controller::request('content');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function storeComment() {
|
||||||
|
$comment = new Comment();
|
||||||
|
$comment->setProperties(array(
|
||||||
|
'content' => $this->content
|
||||||
|
));
|
||||||
|
|
||||||
|
$ticket = Ticket::getTicket($this->ticketId);
|
||||||
|
$ticket->addComment($comment);
|
||||||
|
$ticket->store();
|
||||||
|
}
|
||||||
|
}
|
@ -1,51 +1,46 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use RedBeanPHP\Facade as RedBean;
|
||||||
|
|
||||||
|
use Respect\Validation\Validator as DataValidator;
|
||||||
|
|
||||||
class CreateController extends Controller {
|
class CreateController extends Controller {
|
||||||
const PATH = '/create';
|
const PATH = '/create';
|
||||||
|
|
||||||
private $title ;
|
private $title;
|
||||||
private $content;
|
private $content;
|
||||||
private $departmentId;
|
private $departmentId;
|
||||||
private $language;
|
private $language;
|
||||||
|
|
||||||
public function handler() {
|
public function validations() {
|
||||||
$this->requestTicketData();
|
return [
|
||||||
|
'permission' => 'any',
|
||||||
$validateResult = $this->validateData();
|
'requestData' => [
|
||||||
|
'title' => [
|
||||||
if ($validateResult !== true) {
|
'validation' => DataValidator::length(3, 30),
|
||||||
Response::respondError($validateResult);
|
'error' => ERRORS::INVALID_TITLE
|
||||||
} else {
|
],
|
||||||
$this->storeTicket();
|
'content' => [
|
||||||
|
'validation' => DataValidator::length(10, 500),
|
||||||
Response::respondSuccess();
|
'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->title = Controller::request('title');
|
||||||
$this->content = Controller::request('content');
|
$this->content = Controller::request('content');
|
||||||
$this->departmentId = Controller::request('departmentId');
|
$this->departmentId = Controller::request('departmentId');
|
||||||
$this->language = Controller::request('language');
|
$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() {
|
private function storeTicket() {
|
||||||
$ticket = new Ticket();
|
$ticket = new Ticket();
|
||||||
$ticket->setProperties(array(
|
$ticket->setProperties(array(
|
||||||
@ -55,13 +50,14 @@ class CreateController extends Controller {
|
|||||||
'language' => $this->language,
|
'language' => $this->language,
|
||||||
'department' => $this->departmentId,
|
'department' => $this->departmentId,
|
||||||
'file' => '',
|
'file' => '',
|
||||||
'date' => date("F j, Y, g:i a"),
|
'date' => date('F j, Y, g:i a'),
|
||||||
'unread' => false,
|
'unread' => false,
|
||||||
'closed' => false,
|
'closed' => false
|
||||||
'author' => '',
|
|
||||||
'owner'=> '',
|
|
||||||
'ownComments' => []
|
|
||||||
));
|
));
|
||||||
|
|
||||||
|
//TODO: Add logged user as author
|
||||||
|
$ticket->setAuthor(User::getUser(1));
|
||||||
|
|
||||||
$ticket->store();
|
$ticket->store();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,6 +5,13 @@ class LoginController extends Controller {
|
|||||||
|
|
||||||
private $userInstance;
|
private $userInstance;
|
||||||
private $session;
|
private $session;
|
||||||
|
|
||||||
|
public function validations() {
|
||||||
|
return [
|
||||||
|
'permission' => 'any',
|
||||||
|
'requestData' => []
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function handler() {
|
public function handler() {
|
||||||
if ($this->isAlreadyLoggedIn()) {
|
if ($this->isAlreadyLoggedIn()) {
|
||||||
|
@ -2,6 +2,13 @@
|
|||||||
class LogoutController extends Controller {
|
class LogoutController extends Controller {
|
||||||
const PATH = '/logout';
|
const PATH = '/logout';
|
||||||
|
|
||||||
|
public function validations() {
|
||||||
|
return [
|
||||||
|
'permission' => 'any',
|
||||||
|
'requestData' => []
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function handler() {
|
public function handler() {
|
||||||
$session = Session::getInstance();
|
$session = Session::getInstance();
|
||||||
$session->closeSession();
|
$session->closeSession();
|
||||||
|
@ -3,24 +3,25 @@
|
|||||||
class SignUpController extends Controller {
|
class SignUpController extends Controller {
|
||||||
const PATH = '/signup';
|
const PATH = '/signup';
|
||||||
|
|
||||||
private $email;
|
public function validations() {
|
||||||
private $password;
|
return [
|
||||||
|
'permission' => 'any',
|
||||||
|
'requestData' => []
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function handler() {
|
public function handler() {
|
||||||
$this->requestUserData();
|
$email = Controller::request('email');
|
||||||
|
$password = Controller::request('password');
|
||||||
|
|
||||||
$userId = $this->createNewUserAndRetrieveId($this->email, $this->password);
|
$userId = $this->createNewUserAndRetrieveId($email, $password);
|
||||||
|
|
||||||
|
EmailSender::validRegister($email);
|
||||||
|
|
||||||
Response::respondSuccess(array(
|
Response::respondSuccess(array(
|
||||||
'userId' => $userId,
|
'userId' => $userId,
|
||||||
'userEmail' => $this->email
|
'userEmail' => $email
|
||||||
));
|
));
|
||||||
|
|
||||||
EmailSender::validRegister($this->email);
|
|
||||||
}
|
|
||||||
public function requestUserData(){
|
|
||||||
$this->email = Controller::request('email');
|
|
||||||
$this->password = Controller::request('password');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createNewUserAndRetrieveId($email, $password) {
|
public function createNewUserAndRetrieveId($email, $password) {
|
||||||
|
@ -21,13 +21,13 @@ spl_autoload_register(function ($class) {
|
|||||||
$classPath = "models/{$class}.php";
|
$classPath = "models/{$class}.php";
|
||||||
|
|
||||||
if(file_exists($classPath)) {
|
if(file_exists($classPath)) {
|
||||||
include $classPath;
|
include_once $classPath;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// LOAD CONTROLLERS
|
// LOAD CONTROLLERS
|
||||||
foreach (glob('controllers/*.php') as $controller) {
|
foreach (glob('controllers/*.php') as $controller) {
|
||||||
include $controller;
|
include_once $controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
$app->run();
|
$app->run();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
require_once 'libs/Validator.php';
|
||||||
|
|
||||||
abstract class Controller {
|
abstract class Controller {
|
||||||
|
|
||||||
@ -6,40 +7,37 @@ abstract class Controller {
|
|||||||
* Instance-related stuff
|
* Instance-related stuff
|
||||||
*/
|
*/
|
||||||
abstract public function handler();
|
abstract public function handler();
|
||||||
|
abstract public function validations();
|
||||||
|
|
||||||
public function getHandler() {
|
public function getHandler() {
|
||||||
return function () {
|
return function () {
|
||||||
|
try {
|
||||||
|
$this->validate();
|
||||||
|
} catch (ValidationException $exception) {
|
||||||
|
Response::respondError($exception->getMessage());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$this->handler();
|
$this->handler();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function validate() {
|
||||||
|
$validator = new Validator();
|
||||||
|
|
||||||
|
$validator->validate($this->validations());
|
||||||
|
}
|
||||||
|
|
||||||
public static function request($key) {
|
public static function request($key) {
|
||||||
$app = self::getAppInstance();
|
$app = self::getAppInstance();
|
||||||
|
|
||||||
return $app->request()->post($key);
|
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() {
|
public static function getLoggedUser() {
|
||||||
return User::getUser((int)self::request('csrf_userid'));
|
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() {
|
public static function getAppInstance() {
|
||||||
return \Slim\Slim::getInstance();
|
return \Slim\Slim::getInstance();
|
||||||
}
|
}
|
||||||
|
61
server/libs/Validator.php
Normal file
61
server/libs/Validator.php
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class Comment extends DataStore {
|
class Comment extends DataStore {
|
||||||
const TABLE = 'comments';
|
const TABLE = 'comment';
|
||||||
|
|
||||||
public static function getProps() {
|
public static function getProps() {
|
||||||
return array(
|
return array(
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
class ERRORS {
|
class ERRORS {
|
||||||
const INVALID_CREDENTIALS = 'User or password is not defined';
|
const INVALID_CREDENTIALS = 'User or password is not defined';
|
||||||
const SESSION_EXISTS = 'User is already logged in';
|
const SESSION_EXISTS = 'User is already logged in';
|
||||||
const SHORT_TITLE = 'Title is too short';
|
const NO_PERMISSION = 'You have no permission to access';
|
||||||
const LONG_TITLE = 'Title is very long';
|
const INVALID_TITLE = 'Invalid title';
|
||||||
const SHORT_CONTENT = 'Content is too short';
|
const INVALID_CONTENT = 'Invalid content';
|
||||||
const LONG_CONTENT = 'Content is very long';
|
|
||||||
}
|
}
|
||||||
|
@ -38,8 +38,12 @@ class Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function checkAuthentication($data) {
|
public function checkAuthentication($data) {
|
||||||
return $this->getStoredData('userId') === $data['userId'] &&
|
$userId = $this->getStoredData('userId');
|
||||||
$this->getStoredData('token') === $data['token'];
|
$token = $this->getStoredData('token');
|
||||||
|
|
||||||
|
return $userId && $token &&
|
||||||
|
$userId === $data['userId'] &&
|
||||||
|
$token === $data['token'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isLoggedWithId($userId) {
|
public function isLoggedWithId($userId) {
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use RedBeanPHP\Facade as RedBean;
|
||||||
|
|
||||||
class Ticket extends DataStore {
|
class Ticket extends DataStore {
|
||||||
const TABLE = 'tickets';
|
const TABLE = 'ticket';
|
||||||
|
|
||||||
|
private $author;
|
||||||
|
|
||||||
public static function getProps() {
|
public static function getProps() {
|
||||||
return array(
|
return array(
|
||||||
'ticketId',
|
'ticketNumber',
|
||||||
'title',
|
'title',
|
||||||
'content',
|
'content',
|
||||||
'language',
|
'language',
|
||||||
@ -16,11 +19,38 @@ class Ticket extends DataStore {
|
|||||||
'closed',
|
'closed',
|
||||||
'author',
|
'author',
|
||||||
'owner',
|
'owner',
|
||||||
'ownComments'
|
'ownCommentList'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDefaultProps() {
|
public static function getTicket($value, $property = 'id') {
|
||||||
return array();
|
return parent::getDataStore($value, $property);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDefaultProps() {
|
||||||
|
return array(
|
||||||
|
'owner' => null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAuthor(User $user) {
|
||||||
|
$this->author = $user;
|
||||||
|
$this->author->addTicket($this);
|
||||||
|
|
||||||
|
$this->setProperties(array(
|
||||||
|
'author' => $this->author->getBeanInstance()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addComment(Comment $comment) {
|
||||||
|
$this->getBeanInstance()->ownCommentList[] = $comment->getBeanInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store() {
|
||||||
|
parent::store();
|
||||||
|
|
||||||
|
if ($this->author instanceof User) {
|
||||||
|
$this->author->store();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
use RedBeanPHP\Facade as RedBean;
|
||||||
|
|
||||||
class User extends DataStore {
|
class User extends DataStore {
|
||||||
const TABLE = 'users';
|
const TABLE = 'user';
|
||||||
|
|
||||||
public static function authenticate($userEmail, $userPassword) {
|
public static function authenticate($userEmail, $userPassword) {
|
||||||
$user = User::getUser($userEmail, 'email');
|
$user = User::getUser($userEmail, 'email');
|
||||||
@ -14,19 +15,16 @@ class User extends DataStore {
|
|||||||
'email',
|
'email',
|
||||||
'password',
|
'password',
|
||||||
'name',
|
'name',
|
||||||
'verificationToken',
|
'verificationToken'
|
||||||
'ownTickets'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDefaultProps() {
|
public function getDefaultProps() {
|
||||||
return array(
|
return array();
|
||||||
'ownTickets' => []
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addTicket($ticket) {
|
public function addTicket(Ticket $ticket) {
|
||||||
$this->ownTickets[] = $ticket;
|
$this->getBeanInstance()->sharedTicketList[] = $ticket->getBeanInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getUser($value, $property = 'id') {
|
public static function getUser($value, $property = 'id') {
|
||||||
|
14
tests/ticket/comment.rb
Normal file
14
tests/ticket/comment.rb
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
describe 'ticket/comment/' do
|
||||||
|
it 'should fail if not logged' do
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'on successful request' do
|
||||||
|
it 'should add comment to current ticket' do
|
||||||
|
|
||||||
|
end
|
||||||
|
it 'should link the comment to author' do
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,11 +1,11 @@
|
|||||||
describe '/user/login' do
|
describe '/ticket/create' do
|
||||||
it 'should fail if title is too short' do
|
it 'should fail if title is too short' do
|
||||||
result = request('/ticket/create',{
|
result = request('/ticket/create', {
|
||||||
title: 'GG'
|
title: 'GG'
|
||||||
})
|
})
|
||||||
|
|
||||||
(result['status']).should.equal('fail')
|
(result['status']).should.equal('fail')
|
||||||
(result['message']).should.equal('Title is too short')
|
(result['message']).should.equal('Invalid title')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ describe '/user/login' do
|
|||||||
})
|
})
|
||||||
|
|
||||||
(result['status']).should.equal('fail')
|
(result['status']).should.equal('fail')
|
||||||
(result['message']).should.equal('Title is very long')
|
(result['message']).should.equal('Invalid title')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ describe '/user/login' do
|
|||||||
})
|
})
|
||||||
|
|
||||||
(result['status']).should.equal('fail')
|
(result['status']).should.equal('fail')
|
||||||
(result['message']).should.equal('Content is too short')
|
(result['message']).should.equal('Invalid content')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should fail if content is very long' do
|
it 'should fail if content is very long' do
|
||||||
@ -39,7 +39,7 @@ describe '/user/login' do
|
|||||||
})
|
})
|
||||||
|
|
||||||
(result['status']).should.equal('fail')
|
(result['status']).should.equal('fail')
|
||||||
(result['message']).should.equal('Content is very long')
|
(result['message']).should.equal('Invalid content')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ describe '/user/login' do
|
|||||||
})
|
})
|
||||||
|
|
||||||
(result['status']).should.equal('success')
|
(result['status']).should.equal('success')
|
||||||
ticket = $database.getRow('tickets','Winter is coming','title')
|
ticket = $database.getRow('ticket','Winter is coming','title')
|
||||||
(ticket['content']).should.equal('The north remembers')
|
(ticket['content']).should.equal('The north remembers')
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -5,7 +5,7 @@ describe '/user/signup' do
|
|||||||
'password' => 'custom'
|
'password' => 'custom'
|
||||||
})
|
})
|
||||||
|
|
||||||
userRow = $database.getRow('users', response['data']['userId'])
|
userRow = $database.getRow('user', response['data']['userId'])
|
||||||
|
|
||||||
(userRow['email']).should.equal('steve@jobs.com')
|
(userRow['email']).should.equal('steve@jobs.com')
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user