diff --git a/client/package.json b/client/package.json
index 21e3f053..0033b6df 100644
--- a/client/package.json
+++ b/client/package.json
@@ -54,6 +54,7 @@
},
"dependencies": {
"app-module-path": "^1.0.3",
+ "chart.js": "^2.4.0",
"classnames": "^2.1.3",
"draft-js": "^0.8.1",
"draft-js-export-html": "^0.4.0",
@@ -63,6 +64,7 @@
"lodash": "^3.10.0",
"messageformat": "^0.2.2",
"react": "^15.0.1",
+ "react-chartjs-2": "^2.0.0",
"react-document-title": "^1.0.2",
"react-dom": "^15.0.1",
"react-google-recaptcha": "^0.5.2",
diff --git a/client/src/app-components/stats-chart.js b/client/src/app-components/stats-chart.js
new file mode 100644
index 00000000..ca1a2d49
--- /dev/null
+++ b/client/src/app-components/stats-chart.js
@@ -0,0 +1,100 @@
+import React from 'react';
+import {Line} from 'react-chartjs-2';
+
+import i18n from 'lib-app/i18n';
+
+class StatsChart extends React.Component {
+
+ static propTypes = {
+ strokes: React.PropTypes.arrayOf(React.PropTypes.shape({
+ name: React.PropTypes.string,
+ values: React.PropTypes.arrayOf(React.PropTypes.shape({
+ date: React.PropTypes.string,
+ value: React.PropTypes.number
+ }))
+ })),
+ period: React.PropTypes.number
+ };
+
+ render() {
+ return (
+
+
{this.props.items.map(this.renderItem.bind(this))}
);
}
+ getClass() {
+ let classes = {
+ 'toggle-list': true,
+ 'toggle-list_small': this.props.type == 'small',
+ [this.props.className]: (this.props.className)
+ };
+
+ return classNames(classes);
+ }
+
renderItem(obj, index) {
return (
@@ -35,16 +46,17 @@ class ToggleList extends React.Component {
let classes = {
'toggle-list__item': true,
'toggle-list__first-item': (index === 0),
- 'toggle-list__selected': _.includes(this.state.selected, index)
+ 'toggle-list__last-item': (index === this.props.items.length - 1),
+ 'toggle-list__selected': _.includes(this.getSelectedList(), index)
};
return classNames(classes);
}
selectItem(index) {
- let newSelected = _.clone(this.state.selected);
+ let newSelected = _.clone(this.getSelectedList());
- _.includes(this.state.selected, index) ? _.remove(newSelected, _index => _index == index) : newSelected.push(index);
+ _.includes(this.getSelectedList(), index) ? _.remove(newSelected, _index => _index == index) : newSelected.push(index);
this.setState({
selected: newSelected
@@ -58,6 +70,10 @@ class ToggleList extends React.Component {
});
}
}
+
+ getSelectedList() {
+ return (this.props.values === undefined) ? this.state.selected : this.props.values;
+ }
}
export default ToggleList;
diff --git a/client/src/core-components/toggle-list.scss b/client/src/core-components/toggle-list.scss
index 7bf244cb..1ba34f67 100644
--- a/client/src/core-components/toggle-list.scss
+++ b/client/src/core-components/toggle-list.scss
@@ -8,14 +8,28 @@
width: 180px;
height: 120px;
display: inline-block;
- transition: background-color 0.4s ease;
+ transition: box-shadow 0.2s ease-in-out;
+ user-select: none;
+ cursor: default;
}
&__selected {
- background-color: $light-grey;
+ box-shadow: inset 0 -5px 40px 10px rgba(0, 0, 0, 0.08);
}
&__first-item {
border: 1px $light-grey solid;
+ border-radius: 4px 0 0 4px;
+ }
+
+ &__last-item {
+ border-radius: 0 4px 4px 0;
+ }
+
+ &_small {
+ .toggle-list__item {
+ height: 80px;
+ width: 120px;
+ }
}
}
diff --git a/client/src/data/fixtures/system-fixtures.js b/client/src/data/fixtures/system-fixtures.js
index b317c0b1..d98c393a 100644
--- a/client/src/data/fixtures/system-fixtures.js
+++ b/client/src/data/fixtures/system-fixtures.js
@@ -20,6 +20,7 @@ module.exports = [
'smtp-user': 'Wesa',
'maintenance-mode': false,
'allow-attachments': true,
+ 'registration': true,
'max-size': 500,
'departments': [
{id: 1, name: 'Sales Support', owners: 2},
@@ -168,6 +169,71 @@ module.exports = [
};
}
},
+ {
+ path: '/system/get-stats',
+ time: 200,
+ response: function(_data) {
+ let generalVal = _data.staffId;
+
+ let ID = {
+ 'WEEK': 7,
+ 'MONTH': 30,
+ 'QUARTER': 90,
+ 'YEAR': 365
+ };
+
+ let k = ID[_data.period];
+ let DATA = [];
+
+ for (let i = 0; i < k; i++) {
+ if(generalVal){
+ DATA.push({
+ date: '201701' + (i + 103) % 100,
+ type: 'ASSIGN',
+ general: generalVal,
+ value: (Math.floor((Math.random() + 17) * i)).toString()
+ });
+ DATA.push({
+ date: '201701' + (i + 109) % 100,
+ type: 'CLOSE',
+ general: generalVal,
+ value: (Math.floor((Math.random() + 12) * i )).toString()
+ });
+ }
+ else {
+ DATA.push({
+ date: '201701' + (i + 107) % 100,
+ type: 'COMMENT',
+ general: generalVal,
+ value: (Math.floor((Math.random() + 5) * i)).toString()
+ });
+ DATA.push({
+ date: '201701' + (i + 104) % 100,
+ type: 'SIGNUP',
+ general: generalVal,
+ value: (Math.floor(Math.random() * (i - 180) * (i - 185) / 400)).toString()
+ });
+ DATA.push({
+ date: '201701' + (i + 103) % 100,
+ type: 'CLOSE',
+ general: generalVal,
+ value: (Math.floor((Math.random() + 12) * i )).toString()
+ });
+ DATA.push({
+ date: '201701' + (i + 99) % 100,
+ type: 'CREATE_TICKET',
+ general: generalVal,
+ value: (Math.floor((Math.random() + 7) * i)).toString()
+ });
+ }
+ }
+
+ return {
+ status: "success",
+ data: DATA
+ };
+ }
+ },
{
path: '/system/get-logs',
time: 300,
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index 882ffabf..81277ea4 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -36,7 +36,7 @@ export default {
'DASHBOARD': 'Dashboard',
'USERS': 'Users',
'SETTINGS': 'Settings',
- 'TICKET_STATS': 'Ticket Stats',
+ 'STATISTICS': 'Statistics',
'LAST_ACTIVITY': 'Last Activity',
'MY_TICKETS': 'My Tickets',
'NEW_TICKETS': 'New Tickets',
@@ -154,6 +154,15 @@ export default {
'VERIFY_SUCCESS': 'User verified',
'VERIFY_FAILED': 'Could not verify',
'CHECK_TICKET': 'Check Ticket',
+ 'STATISTICS': 'Statistics',
+ 'ACTIVITY': 'Activity',
+
+
+ 'CHART_CREATE_TICKET': 'Tickets created',
+ 'CHART_CLOSE': 'Tickets closed',
+ 'CHART_SIGNUP': 'Signups',
+ 'CHART_COMMENT': 'Replies',
+ 'CHART_ASSIGN': 'Assigned',
//ACTIVITIES
'ACTIVITY_COMMENT': 'commented ticket',
@@ -188,7 +197,7 @@ export default {
'TICKET_LIST_DESCRIPTION': 'Here you can find a list of all tickets you have sent to our support team.',
'TICKETS_DESCRIPTION': 'Send ticket through our support center and get response of your doubts, suggestions and issues.',
'ARTICLES_DESCRIPTION': 'Take a look to our articles about common issues, guides and documentation.',
- 'ACCOUNT_DESCRIPTION': 'All your tickets are stored in your accounts\'s profile. Keep track off all your tickets you send to our staff team.',
+ 'ACCOUNT_DESCRIPTION': 'All your tickets are stored in your account\'s profile. Keep track of all your tickets you send to our staff team.',
'SUPPORT_CENTER_DESCRIPTION': 'Welcome to our support center. You can contact us through a tickets system. Your tickets will be answered by our staff.',
'CUSTOM_RESPONSES_DESCRIPTION': 'Custom responses are automated responses for common problems',
'MY_TICKETS_DESCRIPTION': 'Here you can view the tickets you are responsible for.',
@@ -204,7 +213,7 @@ export default {
'ADD_ARTICLE_DESCRIPTION': 'Here you can add an article that will be available for every user. It will be added inside the category {category}.',
'LIST_ARTICLES_DESCRIPTION': 'This is a list of articles that includes information about our services.',
'ADD_TOPIC_DESCRIPTION': 'Here you can add a topic that works as a category for articles.',
- 'DELETE_ARTICLE_DESCRIPTION': 'You\'re going to delete this article for ever.',
+ 'DELETE_ARTICLE_DESCRIPTION': 'You\'re going to delete this article forever.',
'STAFF_MEMBERS_DESCRIPTION': 'Here you can see who are your staff members.',
'ADD_STAFF_DESCRIPTION': 'Here you can add staff members to your teams.',
'EDIT_STAFF_DESCRIPTION': 'Here you can edit information about a staff member.',
@@ -215,6 +224,7 @@ export default {
'SYSTEM_PREFERENCES_DESCRIPTION': 'Here you can edit the preferences of the system.',
'VERIFY_SUCCESS_DESCRIPTION': 'You user has been verified correctly. You can log in now.',
'VERIFY_FAILED_DESCRIPTION': 'The verification could not be done.',
+ 'STATISTICS_DESCRIPTION': 'Here you can view statistics related to tickets and signups.',
//ERRORS
'EMAIL_OR_PASSWORD': 'Email or password invalid',
diff --git a/client/src/reducers/session-reducer.js b/client/src/reducers/session-reducer.js
index be4323cc..a51d7e67 100644
--- a/client/src/reducers/session-reducer.js
+++ b/client/src/reducers/session-reducer.js
@@ -44,7 +44,8 @@ class SessionReducer extends Reducer {
logged: true,
pending: false,
failed: false,
- staff: payload.data.staff
+ staff: payload.data.staff,
+ userId: payload.data.userId
});
}
@@ -75,7 +76,8 @@ class SessionReducer extends Reducer {
initDone: true,
logged: true,
pending: false,
- failed: false
+ failed: false,
+ userId: payload.data.userId
});
}
@@ -117,6 +119,7 @@ class SessionReducer extends Reducer {
onSessionChecked(state) {
let userData = sessionStore.getUserData();
+ let userId = sessionStore.getSessionData().userId;
return _.extend({}, state, {
initDone: true,
@@ -127,7 +130,8 @@ class SessionReducer extends Reducer {
userProfilePic: userData.profilePic,
userLevel: userData.level,
userDepartments: userData.departments,
- userTickets: userData.tickets
+ userTickets: userData.tickets,
+ userId: userId
});
}
diff --git a/server/controllers/article/get-all.php b/server/controllers/article/get-all.php
index 9d90e152..40a49efc 100644
--- a/server/controllers/article/get-all.php
+++ b/server/controllers/article/get-all.php
@@ -7,7 +7,7 @@ class GetAllArticlesController extends Controller {
public function validations() {
return [
- 'permission' => 'user',
+ 'permission' => (Controller::isUserSystemEnabled()) ? 'user' : 'any',
'requestData' => []
];
}
diff --git a/server/controllers/system.php b/server/controllers/system.php
index 0ffd8dde..b36fc8c6 100644
--- a/server/controllers/system.php
+++ b/server/controllers/system.php
@@ -9,13 +9,16 @@ require_once 'system/get-logs.php';
require_once 'system/get-mail-templates.php';
require_once 'system/edit-mail-template.php';
require_once 'system/recover-mail-template.php';
-require_once 'system/get-stats.php';
require_once 'system/disable-registration.php';
require_once 'system/enable-registration.php';
+require_once 'system/disable-user-system.php';
+require_once 'system/enabled-user-system.php';
require_once 'system/add-api-key.php';
require_once 'system/delete-api-key.php';
require_once 'system/get-all-keys.php';
+require_once 'system/get-stats.php';
require_once 'system/delete-all-users.php';
+require_once 'system/csv-import.php';
require_once 'system/backup-database.php';
require_once 'system/download.php';
@@ -41,5 +44,8 @@ $systemControllerGroup->addController(new GetAllKeyController);
$systemControllerGroup->addController(new DeleteAllUsersController);
$systemControllerGroup->addController(new BackupDatabaseController);
$systemControllerGroup->addController(new DownloadController);
+$systemControllerGroup->addController(new CSVImportController);
+$systemControllerGroup->addController(new DisableUserSystemController);
+$systemControllerGroup->addController(new EnabledUserSystemController);
$systemControllerGroup->finalize();
\ No newline at end of file
diff --git a/server/controllers/system/csv-import.php b/server/controllers/system/csv-import.php
new file mode 100644
index 00000000..ea3093b8
--- /dev/null
+++ b/server/controllers/system/csv-import.php
@@ -0,0 +1,55 @@
+ 'staff_3',
+ 'requestData' => []
+ ];
+ }
+
+ public function handler() {
+ $fileUploader = $this->uploadFile();
+
+ if(!$fileUploader instanceof FileUploader) {
+ throw new Exception(ERRORS::INVALID_FILE);
+ }
+
+ $file = fopen($fileUploader->getFullFilePath(),'r');
+ $errors = [];
+
+ while(!feof($file)) {
+ $userList = fgetcsv($file);
+
+ Controller::setDataRequester(function ($key) use ($userList) {
+ switch ($key) {
+ case 'email':
+ return $userList[0];
+ case 'password':
+ return $userList[1];
+ case 'name':
+ return $userList[2];
+ }
+
+ return null;
+ });
+
+ $signupController = new SignUpController(true);
+
+ try {
+ $signupController->validate();
+ $signupController->handler();
+ } catch (\Exception $exception) {
+ $errors[] = $exception->getMessage() . ' in email ' . $userList[0];
+ }
+ }
+
+ fclose($file);
+
+ unlink($fileUploader->getFullFilePath());
+
+ Response::respondSuccess($errors);
+ }
+}
\ No newline at end of file
diff --git a/server/controllers/system/disable-user-system.php b/server/controllers/system/disable-user-system.php
new file mode 100644
index 00000000..fc1cc0a1
--- /dev/null
+++ b/server/controllers/system/disable-user-system.php
@@ -0,0 +1,58 @@
+ 'staff_3',
+ 'requestData' => []
+ ];
+ }
+
+ public function handler() {
+ $password = Controller::request('password');
+
+ if(!Hashing::verifyPassword($password, Controller::getLoggedUser()->password)) {
+ throw new Exception(ERRORS::INVALID_PASSWORD);
+
+ }
+
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::SYSTEM_USER_IS_ALREADY_DISABLED);
+ }
+
+ $userSystemEnabled = Setting::getSetting('user-system-enabled');
+ $userSystemEnabled->value = 0 ;
+ $userSystemEnabled->store();
+
+ $userList = User::getAll();
+
+ foreach($userList as $user) {
+ $ticketNumberList = [];
+
+ foreach($user->sharedTicketList as $ticket) {
+ $ticket->authorEmail = $user->email;
+ $ticket->authorName = $user->name;
+ $ticket->author = null;
+
+ $ticketNumberList[] = $ticket->ticketNumber;
+ $ticket->store();
+ }
+
+ $mailSender = new MailSender();
+
+ $mailSender->setTemplate(MailTemplate::USER_SYSTEM_DISABLED, [
+ 'to' => $user->email,
+ 'name' => $user->name,
+ 'tickets' => json_encode($ticketNumberList)
+ ]);
+
+ $mailSender->send();
+
+ $user->delete();
+ }
+
+ Response::respondSuccess();
+ }
+}
\ No newline at end of file
diff --git a/server/controllers/system/enabled-user-system.php b/server/controllers/system/enabled-user-system.php
new file mode 100644
index 00000000..0139608a
--- /dev/null
+++ b/server/controllers/system/enabled-user-system.php
@@ -0,0 +1,78 @@
+ 'staff_3',
+ 'requestData' => []
+ ];
+ }
+
+ public function handler() {
+ $password = Controller::request('password');
+
+ if(!Hashing::verifyPassword($password, Controller::getLoggedUser()->password)) {
+ throw new Exception(ERRORS::INVALID_PASSWORD);
+
+ }
+
+ if(Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::SYSTEM_USER_IS_ALREADY_ENABLED);
+ }
+
+ $userSystemEnabled = Setting::getSetting('user-system-enabled');
+ $userSystemEnabled->value = 1 ;
+ $userSystemEnabled->store();
+
+ $ticketList = Ticket::getAll();
+
+ foreach($ticketList as $ticket) {
+
+ $userRow = User::getDataStore($ticket->authorEmail, 'email');
+
+ if($userRow->isNull()) {
+ $this->createUser($ticket->authorEmail,$ticket->authorName);
+
+ } else {
+ $userRow->tickets = $userRow->tickets + 1;
+ $userRow->sharedTicketList->add($ticket);
+ $userRow->store();
+ }
+
+ $actualUserRow = User::getDataStore($ticket->authorEmail,'email');
+ $ticket->author = $actualUserRow;
+ $ticket->authorName = null;
+ $ticket->authorEmail = null;
+ $ticket->store();
+ }
+
+ Response::respondSuccess();
+ }
+ public function createUser($email,$name) {
+ $userInstance = new User();
+
+ $password = Hashing::generateRandomToken();
+
+ $userInstance->setProperties([
+ 'name' => $name,
+ 'signupDate' => Date::getCurrentDate(),
+ 'tickets' => 1,
+ 'email' => $email,
+ 'password' => Hashing::hashPassword($password),
+ 'verificationToken' => null
+ ]);
+
+ $userInstance->store();
+
+ $mailSender = new MailSender();
+ $mailSender->setTemplate(MailTemplate::USER_SYSTEM_ENABLED, [
+ 'to' => $email,
+ 'name' => $name,
+ 'password' => $password
+ ]);
+ $mailSender->send();
+
+ }
+}
\ No newline at end of file
diff --git a/server/controllers/system/get-settings.php b/server/controllers/system/get-settings.php
index 9cddb302..41e2299d 100644
--- a/server/controllers/system/get-settings.php
+++ b/server/controllers/system/get-settings.php
@@ -46,7 +46,8 @@ class GetSettingsController extends Controller {
'registration' => Setting::getSetting('registration')->getValue(),
'departments' => Department::getDepartmentNames(),
'supportedLanguages' => Language::getSupportedLanguages(),
- 'allowedLanguages' => Language::getAllowedLanguages()
+ 'allowedLanguages' => Language::getAllowedLanguages(),
+ 'user-system-enabled' => Setting::getSetting('user-system-enabled')->getValue()
];
}
diff --git a/server/controllers/system/init-settings.php b/server/controllers/system/init-settings.php
index b5d7c6d3..4106797b 100644
--- a/server/controllers/system/init-settings.php
+++ b/server/controllers/system/init-settings.php
@@ -42,6 +42,7 @@ class InitSettingsController extends Controller {
'title' => 'Support Center',
'url' => 'http://www.opensupports.com/support',
'registration' => true,
+ 'user-system-enabled' => true,
'last-stat-day' => '20170101', //TODO: get current date
'ticket-gap' => Hashing::generateRandomPrime(100000, 999999),
'file-gap' => Hashing::generateRandomPrime(100000, 999999),
diff --git a/server/controllers/ticket/comment.php b/server/controllers/ticket/comment.php
index 6a043757..cd7713e1 100644
--- a/server/controllers/ticket/comment.php
+++ b/server/controllers/ticket/comment.php
@@ -9,7 +9,7 @@ class CommentController extends Controller {
private $content;
public function validations() {
- return [
+ $validations = [
'permission' => 'user',
'requestData' => [
'content' => [
@@ -22,13 +22,23 @@ class CommentController extends Controller {
]
]
];
+
+ if(!Controller::isUserSystemEnabled()) {
+ $validations['permission'] = 'any';
+ $validations['requestData']['email'] = [
+ 'validation' => DataValidator::email(),
+ 'error' => ERRORS::INVALID_EMAIL
+ ];
+ }
+
+ return $validations;
}
public function handler() {
$session = Session::getInstance();
$this->requestData();
- if ($session->isLoggedWithId($this->ticket->author->id) || Controller::isStaffLogged()) {
+ if (!Controller::isUserSystemEnabled() || $session->isLoggedWithId($this->ticket->author->id) || Controller::isStaffLogged()) {
$this->storeComment();
Log::createLog('COMMENT', $this->ticket->ticketNumber);
@@ -41,23 +51,29 @@ class CommentController extends Controller {
private function requestData() {
$ticketNumber = Controller::request('ticketNumber');
-
+ $email = Controller::request('email');
$this->ticket = Ticket::getByTicketNumber($ticketNumber);
$this->content = Controller::request('content');
+
+ if(!Controller::isUserSystemEnabled() && $this->ticket->authorEmail !== $email && !Controller::isStaffLogged()) {
+ throw new Exception(ERRORS::NO_PERMISSION);
+ }
}
private function storeComment() {
+ $fileUploader = $this->uploadFile();
+
$comment = Ticketevent::getEvent(Ticketevent::COMMENT);
$comment->setProperties(array(
'content' => $this->content,
- 'file' => $this->uploadFile(),
+ 'file' => ($fileUploader instanceof FileUploader) ? $fileUploader->getFileName() : null,
'date' => Date::getCurrentDate()
));
if(Controller::isStaffLogged()) {
$this->ticket->unread = true;
$comment->authorStaff = Controller::getLoggedUser();
- } else {
+ } else if(Controller::isUserSystemEnabled()) {
$this->ticket->unreadStaff = true;
$comment->authorUser = Controller::getLoggedUser();
}
diff --git a/server/controllers/ticket/create.php b/server/controllers/ticket/create.php
index fbcd9203..5b39ab47 100644
--- a/server/controllers/ticket/create.php
+++ b/server/controllers/ticket/create.php
@@ -10,9 +10,11 @@ class CreateController extends Controller {
private $departmentId;
private $language;
private $ticketNumber;
+ private $email;
+ private $name;
public function validations() {
- return [
+ $validations = [
'permission' => 'user',
'requestData' => [
'title' => [
@@ -33,6 +35,16 @@ class CreateController extends Controller {
]
]
];
+
+ if(!Controller::isUserSystemEnabled()) {
+ $validations['permission'] = 'any';
+ $validations['requestData']['captcha'] = [
+ 'validation' => DataValidator::captcha(),
+ 'error' => ERRORS::INVALID_CAPTCHA
+ ];
+ }
+
+ return $validations;
}
public function handler() {
@@ -40,6 +52,8 @@ class CreateController extends Controller {
$this->content = Controller::request('content');
$this->departmentId = Controller::request('departmentId');
$this->language = Controller::request('language');
+ $this->email = Controller::request('email');
+ $this->name = Controller::request('name');
$this->storeTicket();
@@ -53,6 +67,8 @@ class CreateController extends Controller {
$department = Department::getDataStore($this->departmentId);
$author = Controller::getLoggedUser();
+ $fileUploader = $this->uploadFile();
+
$ticket = new Ticket();
$ticket->setProperties(array(
'title' => $this->title,
@@ -60,17 +76,22 @@ class CreateController extends Controller {
'language' => $this->language,
'author' => $author,
'department' => $department,
- 'file' => $this->uploadFile(),
+ 'file' => ($fileUploader instanceof FileUploader) ? $fileUploader->getFileName() : null,
'date' => Date::getCurrentDate(),
'unread' => false,
'unreadStaff' => true,
'closed' => false,
+ 'authorName' => $this->name,
+ 'authorEmail' => $this->email
));
- $author->sharedTicketList->add($ticket);
- $author->tickets++;
+ if(Controller::isUserSystemEnabled()) {
+ $author->sharedTicketList->add($ticket);
+ $author->tickets++;
+
+ $author->store();
+ }
- $author->store();
$ticket->store();
$this->ticketNumber = $ticket->ticketNumber;
diff --git a/server/controllers/ticket/get.php b/server/controllers/ticket/get.php
index 36ef3f8b..6e2a6758 100644
--- a/server/controllers/ticket/get.php
+++ b/server/controllers/ticket/get.php
@@ -8,7 +8,7 @@ class TicketGetController extends Controller {
private $ticket;
public function validations() {
- return [
+ $validations = [
'permission' => 'user',
'requestData' => [
'ticketNumber' => [
@@ -17,13 +17,38 @@ class TicketGetController extends Controller {
]
]
];
+
+ if(!Controller::isUserSystemEnabled() && !Controller::isStaffLogged()) {
+ $validations['permission'] = 'any';
+ $validations['requestData']['email'] = [
+ 'validation' => DataValidator::email(),
+ 'error' => ERRORS::INVALID_EMAIL
+ ];
+ $validations['requestData']['captcha'] = [
+ 'validation' => DataValidator::captcha(),
+ 'error' => ERRORS::INVALID_CAPTCHA
+ ];
+ }
+
+ return $validations;
}
public function handler() {
+ $email = Controller::request('email');
+
$this->ticket = Ticket::getByTicketNumber(Controller::request('ticketNumber'));
+ if(!Controller::isUserSystemEnabled() && !Controller::isStaffLogged()) {
+ if($this->ticket->authorEmail === $email) {
+ Response::respondSuccess($this->ticket->toArray());
+ return;
+ } else {
+ throw new Exception(ERRORS::NO_PERMISSION);
+ }
+ }
+
if ($this->shouldDenyPermission()) {
- Response::respondError(ERRORS::NO_PERMISSION);
+ throw new Exception(ERRORS::NO_PERMISSION);
} else {
Response::respondSuccess($this->ticket->toArray());
}
@@ -32,7 +57,7 @@ class TicketGetController extends Controller {
private function shouldDenyPermission() {
$user = Controller::getLoggedUser();
- return (!Controller::isStaffLogged() && $this->ticket->author->id !== $user->id) ||
+ return (!Controller::isStaffLogged() && (Controller::isUserSystemEnabled() && $this->ticket->author->id !== $user->id)) ||
(Controller::isStaffLogged() && $this->ticket->owner && $this->ticket->owner->id !== $user->id);
}
}
\ No newline at end of file
diff --git a/server/controllers/user/delete.php b/server/controllers/user/delete.php
index 75cf7dfc..b17ed8a4 100644
--- a/server/controllers/user/delete.php
+++ b/server/controllers/user/delete.php
@@ -20,6 +20,10 @@ class DeleteUserController extends Controller {
}
public function handler() {
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
$userId = Controller::request('userId');
$user = User::getDataStore($userId);
diff --git a/server/controllers/user/get-user.php b/server/controllers/user/get-user.php
index 8ea55c09..ae9b4f9e 100644
--- a/server/controllers/user/get-user.php
+++ b/server/controllers/user/get-user.php
@@ -18,6 +18,11 @@ class GetUserByIdController extends Controller {
}
public function handler() {
+
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
$userId = Controller::request('userId');
$user = User::getDataStore($userId);
$staff = Controller::getLoggedUser();
diff --git a/server/controllers/user/get-users.php b/server/controllers/user/get-users.php
index eadd6922..5d8daf28 100644
--- a/server/controllers/user/get-users.php
+++ b/server/controllers/user/get-users.php
@@ -21,6 +21,10 @@ class GetUsersController extends Controller {
}
public function handler() {
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
$userList = $this->getUserList();
$userListArray = [];
diff --git a/server/controllers/user/login.php b/server/controllers/user/login.php
index 7eada075..ebd55c30 100644
--- a/server/controllers/user/login.php
+++ b/server/controllers/user/login.php
@@ -14,9 +14,12 @@ class LoginController extends Controller {
}
public function handler() {
+ if(!Controller::isUserSystemEnabled() && !Controller::request('staff')) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
if ($this->isAlreadyLoggedIn()) {
- Response::respondError(ERRORS::SESSION_EXISTS);
- return;
+ throw new Exception(ERRORS::SESSION_EXISTS);
}
if ($this->checkInputCredentials() || $this->checkRememberToken()) {
diff --git a/server/controllers/user/recover-password.php b/server/controllers/user/recover-password.php
index c5cec698..ac3ceef2 100644
--- a/server/controllers/user/recover-password.php
+++ b/server/controllers/user/recover-password.php
@@ -27,6 +27,10 @@ class RecoverPasswordController extends Controller {
}
public function handler() {
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
$this->requestData();
$this->changePassword();
}
diff --git a/server/controllers/user/send-recover-password.php b/server/controllers/user/send-recover-password.php
index e92d1ae6..c59eebb1 100644
--- a/server/controllers/user/send-recover-password.php
+++ b/server/controllers/user/send-recover-password.php
@@ -21,6 +21,10 @@ class SendRecoverPasswordController extends Controller {
}
public function handler() {
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
$email = Controller::request('email');
$this->user = User::getUser($email,'email');
diff --git a/server/controllers/user/signup.php b/server/controllers/user/signup.php
index cee72f1b..4b9e4d89 100644
--- a/server/controllers/user/signup.php
+++ b/server/controllers/user/signup.php
@@ -10,9 +10,14 @@ class SignUpController extends Controller {
private $userName;
private $userPassword;
private $verificationToken;
+ private $csvImported;
+
+ public function __construct($csvImported = false) {
+ $this->csvImported = $csvImported;
+ }
public function validations() {
- return [
+ $validations = [
'permission' => 'any',
'requestData' => [
'name' => [
@@ -26,35 +31,41 @@ class SignUpController extends Controller {
'password' => [
'validation' => DataValidator::length(5, 200),
'error' => ERRORS::INVALID_PASSWORD
- ],
- 'captcha' => [
- 'validation' => DataValidator::captcha(),
- 'error' => ERRORS::INVALID_CAPTCHA
]
]
];
+
+ if(!$this->csvImported) {
+ $validations['requestData']['captcha'] = [
+ 'validation' => DataValidator::captcha(),
+ 'error' => ERRORS::INVALID_CAPTCHA
+ ];
+ }
+
+ return $validations;
}
public function handler() {
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
$this->storeRequestData();
$apiKey = APIKey::getDataStore(Controller::request('apiKey'), 'token');
$existentUser = User::getUser($this->userEmail, 'email');
if (!$existentUser->isNull()) {
- Response::respondError(ERRORS::USER_EXISTS);
- return;
+ throw new Exception(ERRORS::USER_EXISTS);
}
$banRow = Ban::getDataStore($this->userEmail,'email');
if (!$banRow->isNull()) {
- Response::respondError(ERRORS::ALREADY_BANNED);
- return;
+ throw new Exception(ERRORS::ALREADY_BANNED);
}
- if (!Setting::getSetting('registration')->value && $apiKey->isNull() ) {
- Response::respondError(ERRORS::NO_PERMISSION);
- return;
+ if (!Setting::getSetting('registration')->value && $apiKey->isNull() && !$this->csvImported) {
+ throw new Exception(ERRORS::NO_PERMISSION);
}
$userId = $this->createNewUserAndRetrieveId();
diff --git a/server/controllers/user/verify.php b/server/controllers/user/verify.php
index 616d3b92..aa2dd31d 100644
--- a/server/controllers/user/verify.php
+++ b/server/controllers/user/verify.php
@@ -17,6 +17,10 @@ class VerifyController extends Controller{
}
public function handler() {
+ if(!Controller::isUserSystemEnabled()) {
+ throw new Exception(ERRORS::USER_SYSTEM_DISABLED);
+ }
+
$email = Controller::request('email');
$token = Controller::request('token');
diff --git a/server/data/ERRORS.php b/server/data/ERRORS.php
index 5f47e71a..d75c7e2b 100644
--- a/server/data/ERRORS.php
+++ b/server/data/ERRORS.php
@@ -35,6 +35,9 @@ class ERRORS {
const INVALID_TEMPLATE = 'INVALID_TEMPLATE';
const INVALID_SUBJECT = 'INVALID_SUBJECT';
const INVALID_BODY = 'INVALID_BODY';
+ const USER_SYSTEM_DISABLED = 'USER_SYSTEM_DISABLED';
+ const SYSTEM_USER_IS_ALREADY_DISABLED = 'SYSTEM_USER_IS_ALREADY_DISABLED';
+ const SYSTEM_USER_IS_ALREADY_ENABLED = 'SYSTEM_USER_IS_ALREADY_ENABLED';
const INVALID_PERIOD = 'INVALID_PERIOD';
const NAME_ALREADY_USED = 'NAME_ALREADY_USED';
const INVALID_FILE = 'INVALID_FILE';
diff --git a/server/data/InitialMails.php b/server/data/InitialMails.php
index 899d9af3..7be66192 100644
--- a/server/data/InitialMails.php
+++ b/server/data/InitialMails.php
@@ -53,6 +53,26 @@ class InitialMails {
'body' => file_get_contents('data/mail-templates/user-recovered-password-es.html')
]
],
+ 'USER_SYSTEM_DISABLED' => [
+ 'en' => [
+ 'subject' => 'Account has been deleted - OpenSupports',
+ 'body' => file_get_contents('data/mail-templates/user-system-disabled-en.html')
+ ],
+ 'es' => [
+ 'subject' => 'cuanta borrada - OpenSupports',
+ 'body' => file_get_contents('data/mail-templates/user-system-disabled-es.html')
+ ]
+ ],
+ 'USER_SYSTEM_ENABLED' => [
+ 'en' => [
+ 'subject' => 'account has been created - OpenSupports',
+ 'body' => file_get_contents('data/mail-templates/user-system-enabled-en.html')
+ ],
+ 'es' => [
+ 'subject' => 'se te ha creado una cuenta - OpenSupports',
+ 'body' => file_get_contents('data/mail-templates/user-system-enabled-es.html')
+ ]
+ ]
];
}
}
\ No newline at end of file
diff --git a/server/data/mail-templates/user-system-disabled-en.html b/server/data/mail-templates/user-system-disabled-en.html
new file mode 100644
index 00000000..d42819c1
--- /dev/null
+++ b/server/data/mail-templates/user-system-disabled-en.html
@@ -0,0 +1,3 @@
+
+ Hi {{name}} the system user has been deleted this is the list of your tickets {{tickets}}
+
\ No newline at end of file
diff --git a/server/data/mail-templates/user-system-disabled-es.html b/server/data/mail-templates/user-system-disabled-es.html
new file mode 100644
index 00000000..fb4f3603
--- /dev/null
+++ b/server/data/mail-templates/user-system-disabled-es.html
@@ -0,0 +1,3 @@
+
+ hoola {{name}} the system user has been deleted this is the list of your tickets {{tickets}}
+
\ No newline at end of file
diff --git a/server/data/mail-templates/user-system-enabled-en.html b/server/data/mail-templates/user-system-enabled-en.html
new file mode 100644
index 00000000..5b2bd906
--- /dev/null
+++ b/server/data/mail-templates/user-system-enabled-en.html
@@ -0,0 +1,4 @@
+
+ hi {{name}} the system user has been Created this is your new password {{password}} , you can change it if you want
+ maxi puto
+
\ No newline at end of file
diff --git a/server/data/mail-templates/user-system-enabled-es.html b/server/data/mail-templates/user-system-enabled-es.html
new file mode 100644
index 00000000..a1081984
--- /dev/null
+++ b/server/data/mail-templates/user-system-enabled-es.html
@@ -0,0 +1,3 @@
+
+ hoola {{name}} el sistema de usuarios se ha creado este es tu contra {{password}} , puedes cambairla si quieres
+
\ No newline at end of file
diff --git a/server/index.php b/server/index.php
index d8508ba3..041b96a4 100644
--- a/server/index.php
+++ b/server/index.php
@@ -23,6 +23,8 @@ include_once 'libs/FileManager.php';
include_once 'libs/FileDownloader.php';
include_once 'libs/FileUploader.php';
+Controller::init();
+
// LOAD DATA
spl_autoload_register(function ($class) {
$classPath = "data/{$class}.php";
diff --git a/server/libs/Controller.php b/server/libs/Controller.php
index b82bdb0f..88e6b997 100644
--- a/server/libs/Controller.php
+++ b/server/libs/Controller.php
@@ -3,6 +3,7 @@ require_once 'libs/Validator.php';
require_once 'models/Session.php';
abstract class Controller {
+ private static $dataRequester;
/**
* Instance-related stuff
@@ -28,10 +29,20 @@ abstract class Controller {
$validator->validate($this->validations());
}
- public static function request($key) {
- $app = self::getAppInstance();
+ public static function init() {
+ self::$dataRequester = function ($key) {
+ $app = self::getAppInstance();
- return $app->request()->post($key);
+ return $app->request()->post($key);
+ };
+ }
+
+ public static function setDataRequester($dataRequester) {
+ self::$dataRequester = $dataRequester;
+ }
+
+ public static function request($key) {
+ return call_user_func(self::$dataRequester, $key);
}
public static function getLoggedUser() {
@@ -77,9 +88,13 @@ abstract class Controller {
$fileQuantity->value++;
$fileQuantity->store();
- return $fileUploader->getFileName();
+ return $fileUploader;
} else {
throw new Exception(ERRORS::INVALID_FILE);
}
}
+
+ public static function isUserSystemEnabled() {
+ return Setting::getSetting('user-system-enabled')->getValue();
+ }
}
\ No newline at end of file
diff --git a/server/models/MailTemplate.php b/server/models/MailTemplate.php
index a2931061..0379693b 100644
--- a/server/models/MailTemplate.php
+++ b/server/models/MailTemplate.php
@@ -8,6 +8,8 @@ class MailTemplate extends DataStore {
const USER_PASSWORD = 'USER_PASSWORD';
const PASSWORD_FORGOT = 'PASSWORD_FORGOT';
const PASSWORD_RECOVERED = 'PASSWORD_RECOVERED';
+ const USER_SYSTEM_DISABLED = 'USER_SYSTEM_DISABLED';
+ const USER_SYSTEM_ENABLED = 'USER_SYSTEM_ENABLED';
public static function getTemplate($type) {
$globalLanguage = Setting::getSetting('language')->value;
diff --git a/server/models/Ticket.php b/server/models/Ticket.php
index 88351ea6..e1e3d9b1 100644
--- a/server/models/Ticket.php
+++ b/server/models/Ticket.php
@@ -20,7 +20,9 @@ class Ticket extends DataStore {
'owner',
'ownTicketeventList',
'unreadStaff',
- 'language'
+ 'language',
+ 'authorEmail',
+ 'authorName'
);
}
@@ -79,7 +81,9 @@ class Ticket extends DataStore {
'priority' => $this->priority,
'author' => $this->authorToArray(),
'owner' => $this->ownerToArray(),
- 'events' => $this->eventsToArray()
+ 'events' => $this->eventsToArray(),
+ 'authorEmail' => $this->authorEmail,
+ 'authorName' => $this->authorName
];
}
diff --git a/tests/init.rb b/tests/init.rb
index 1ecc936f..91e50a42 100644
--- a/tests/init.rb
+++ b/tests/init.rb
@@ -5,7 +5,6 @@ require 'uri'
require 'mysql'
require 'json'
require 'mechanize'
-require 'date'
require './libs.rb'
require './scripts.rb'
@@ -59,3 +58,5 @@ require './system/add-api-key.rb'
require './system/delete-api-key.rb'
require './system/get-all-keys.rb'
require './system/file-upload-download.rb'
+require './system/csv-import.rb'
+require './system/disable-user-system.rb'
diff --git a/tests/system/csv-import.rb b/tests/system/csv-import.rb
new file mode 100644
index 00000000..61ac34ba
--- /dev/null
+++ b/tests/system/csv-import.rb
@@ -0,0 +1,28 @@
+describe'system/csv-import' do
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
+
+ it 'should create user with csv-import' do
+
+ file = File.new('../server/files/test.csv', 'w+')
+ file.puts('prueba1@hotmail.com, contrasena1,ma')
+ file.puts('prueba2@hotmail.com,contrasena2,max')
+ file.puts('prueba3@hotmail.com,contrasena3,maxi')
+ file.close
+ result= request('/system/csv-import', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ file: File.open( "../server/files/test.csv")
+ })
+
+ (result['status']).should.equal('success')
+ row = $database.getRow('user', 'prueba1@hotmail.com', 'email')
+ (row['name']).should.equal('ma')
+
+ row = $database.getRow('user', 'prueba2@hotmail.com', 'email')
+ (row['name']).should.equal('max')
+
+ row = $database.getRow('user', 'prueba3@hotmail.com', 'email')
+ (row['name']).should.equal('maxi')
+ end
+end
diff --git a/tests/system/disable-user-system.rb b/tests/system/disable-user-system.rb
new file mode 100644
index 00000000..076fdb23
--- /dev/null
+++ b/tests/system/disable-user-system.rb
@@ -0,0 +1,89 @@
+describe'system/disable-user-system' do
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
+
+ it 'should disable the user system' do
+ result = request('/system/disable-user-system', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ password:$staff[:password]
+ })
+
+ puts result['message']
+ (result['status']).should.equal('success')
+
+ row = $database.getRow('setting', 'user-system-enabled', 'name')
+
+ (row['value']).should.equal('0')
+ row = $database.getRow('user', 1, 'id')
+ (row).should.equal(nil)
+
+ numberOftickets= $database.query("SELECT * FROM ticket WHERE author_id IS NULL AND author_email IS NOT NULL AND author_name IS NOT NULL")
+
+ (numberOftickets.num_rows).should.equal(35)
+
+ request('/user/logout')
+
+ result = request('/user/signup', {
+ :name => 'test name',
+ :email => 'steve@mail.com',
+ :password => 'customm'
+ })
+
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('USER_SYSTEM_DISABLED')
+
+ result = request('/user/login', {
+ email: @loginEmail,
+ password: @loginPass
+ })
+
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('USER_SYSTEM_DISABLED')
+ end
+
+ it 'should not disable the user system if it is already disabled 'do
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
+
+ result = request('/system/disable-user-system', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ password:$staff[:password]
+ })
+
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('SYSTEM_USER_IS_ALREADY_DISABLED')
+ end
+
+ it 'should enabled the user system' do
+ result = request('/system/enabled-user-system', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ password:$staff[:password]
+ })
+
+ puts result['message']
+ (result['status']).should.equal('success')
+
+ row = $database.getRow('setting', 'user-system-enabled', 'name')
+ (row['value']).should.equal('1')
+
+ numberOftickets= $database.query("SELECT * FROM ticket WHERE author_email IS NULL AND author_name IS NULL AND author_id IS NOT NULL" )
+
+ (numberOftickets.num_rows).should.equal(35)
+
+ end
+
+ it 'should not enabled the user system' do
+ result = request('/system/enabled-user-system', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ password:$staff[:password]
+ })
+
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('SYSTEM_USER_IS_ALREADY_ENABLED')
+
+ end
+end
diff --git a/tests/system/get-mail-templates.rb b/tests/system/get-mail-templates.rb
index 8e067655..f6b4ab10 100644
--- a/tests/system/get-mail-templates.rb
+++ b/tests/system/get-mail-templates.rb
@@ -10,6 +10,6 @@ describe'system/get-mail-templates' do
(result['status']).should.equal('success')
- (result['data'].size).should.equal(10)
+ (result['data'].size).should.equal(14)
end
end