diff --git a/client/src/app-components/activity-row.js b/client/src/app-components/activity-row.js
index 1b3da113..ef029498 100644
--- a/client/src/app-components/activity-row.js
+++ b/client/src/app-components/activity-row.js
@@ -19,6 +19,7 @@ class ActivityRow extends React.Component {
'RE_OPEN',
'DEPARTMENT_CHANGED',
'PRIORITY_CHANGED',
+ 'EDIT_TITLE',
'EDIT_COMMENT',
'EDIT_SETTINGS',
@@ -60,6 +61,8 @@ class ActivityRow extends React.Component {
'DEPARTMENT_CHANGED',
'PRIORITY_CHANGED',
'COMMENT_EDITED',
+ 'EDIT_TITLE',
+ 'EDIT_COMMENT',
];
return (
@@ -113,6 +116,7 @@ class ActivityRow extends React.Component {
'RE_OPEN': 'unlock-alt',
'DEPARTMENT_CHANGED': 'exchange',
'PRIORITY_CHANGED': 'exclamation',
+ 'EDIT_TITLE': 'edit',
'EDIT_COMMENT': 'edit',
'EDIT_SETTINGS': 'wrench',
diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js
index d23ecf0f..6f85dc43 100644
--- a/client/src/app-components/ticket-list.js
+++ b/client/src/app-components/ticket-list.js
@@ -274,4 +274,4 @@ export default connect((store) => {
return {
tags: store.config['tags']
};
-})(TicketList);
\ No newline at end of file
+})(TicketList);
diff --git a/client/src/app-components/ticket-query-list.js b/client/src/app-components/ticket-query-list.js
new file mode 100644
index 00000000..f28dbc3b
--- /dev/null
+++ b/client/src/app-components/ticket-query-list.js
@@ -0,0 +1,90 @@
+import React from 'react';
+import _ from 'lodash';
+
+import API from 'lib-app/api-call';
+import i18n from 'lib-app/i18n';
+import {connect} from 'react-redux';
+
+import TicketList from 'app-components/ticket-list';
+import Message from 'core-components/message';
+
+class TicketQueryList extends React.Component {
+
+ state = {
+ tickets: [],
+ page: 1,
+ pages: 0,
+ error: null,
+ loading: true
+ };
+
+ componentDidMount() {
+ this.getTickets();
+ }
+
+ componentDidUpdate(prevProps) {
+ if (this.props.customList.title !== prevProps.customList.title) {
+ this.getTickets();
+ }
+ }
+
+ render() {
+ return (
+
-
- #{ticket.ticketNumber}
- {ticket.title}
-
-
-
-
+ {this.state.editTitle ? this.renderEditableTitle() : this.renderTitleHeader()}
{this.props.editable ? this.renderEditableHeaders() : this.renderHeaders()}
+ #{ticketNumber}
+ {title}
+
+
+
+ {((author.id == userId && author.staff == userStaff) || userStaff) ? this.renderEditTitleOption() : null}
+ {editedTitle ? this.renderEditedTitleText() : null }
+
+ )
+ }
+
+ renderEditedTitleText(){
+ return(
+
{i18n('TITLE_EDITED')}
+ )
+ }
+
+ renderEditTitleOption() {
+ return(
+
+ this.setState({editTitle: true})} />
+
+ )
+ }
+
+ renderEditableTitle(){
+ return(
+
+
+ this.setState({newTitle: e.target.value })} />
+
+
+
+ )
+ }
+
renderEditableHeaders() {
const ticket = this.props.ticket;
const departments = this.getDepartmentsForTransfer();
@@ -403,6 +445,26 @@ class TicketViewer extends React.Component {
AreYouSure.openModal(null, this.deleteTicket.bind(this));
}
+ changeTitle(){
+ API.call({
+ path: '/ticket/edit-title',
+ data: {
+ ticketNumber: this.props.ticket.ticketNumber,
+ title: this.state.newTitle
+ }
+ }).then(() => {
+ this.setState({
+ editTitle: false,
+ editTitleError: false
+ });
+ this.onTicketModification();
+ }).catch((result) => {
+ this.setState({
+ editTitleError: i18n(result.message)
+ })
+ });
+ }
+
reopenTicket() {
API.call({
path: '/ticket/re-open',
@@ -427,7 +489,10 @@ class TicketViewer extends React.Component {
data: {
ticketNumber: this.props.ticket.ticketNumber
}
- }).then(this.onTicketModification.bind(this));
+ }).then((result) => {
+ this.onTicketModification(result);
+ history.push('/admin/panel/tickets/my-tickets/');
+ });
}
changeDepartment(index) {
@@ -640,7 +705,6 @@ class TicketViewer extends React.Component {
}
export default connect((store) => {
-
return {
userId: store.session.userId,
userStaff: store.session.staff,
diff --git a/client/src/app-components/ticket-viewer.scss b/client/src/app-components/ticket-viewer.scss
index 17de6a8c..87b2f6fe 100644
--- a/client/src/app-components/ticket-viewer.scss
+++ b/client/src/app-components/ticket-viewer.scss
@@ -9,6 +9,42 @@
color: white;
font-size: 16px;
padding: 6px 0;
+ display: flex;
+ align-items:center;
+ justify-content:center;
+ position: relative;
+ &:hover {
+ .ticket-viewer__edit-title-icon {
+ color: $grey;
+ }
+ }
+ }
+
+ &__edited-title-text {
+ font-style: italic;
+ font-size: 14px;
+ margin-left: 10px;
+ }
+
+ &__edit-title-icon {
+ position: absolute;
+ color: #414A59;
+ right: 12px;
+ &:hover {
+ cursor:pointer;
+ }
+ }
+
+ &___input-edit-title {
+ color: black;
+ align-items:center;
+ justify-content: center;
+ margin-bottom: 6px;
+ margin-right: 6px;
+
+ .input__text {
+ height: 25px;
+ }
}
&__number {
diff --git a/client/src/app/Routes.js b/client/src/app/Routes.js
index 0419c0db..b9d43065 100644
--- a/client/src/app/Routes.js
+++ b/client/src/app/Routes.js
@@ -33,6 +33,7 @@ import AdminPanelMyAccount from 'app/admin/panel/dashboard/admin-panel-my-accoun
import AdminPanelMyTickets from 'app/admin/panel/tickets/admin-panel-my-tickets';
import AdminPanelNewTickets from 'app/admin/panel/tickets/admin-panel-new-tickets';
import AdminPanelAllTickets from 'app/admin/panel/tickets/admin-panel-all-tickets';
+import AdminPanelSearchTickets from 'app/admin/panel/tickets/admin-panel-search-tickets';
import AdminPanelViewTicket from 'app/admin/panel/tickets/admin-panel-view-ticket';
import AdminPanelCustomResponses from 'app/admin/panel/tickets/admin-panel-custom-responses';
@@ -113,6 +114,7 @@ export default (
+
diff --git a/client/src/app/admin/panel/admin-panel-menu.js b/client/src/app/admin/panel/admin-panel-menu.js
index 4ab4ca79..9627947a 100644
--- a/client/src/app/admin/panel/admin-panel-menu.js
+++ b/client/src/app/admin/panel/admin-panel-menu.js
@@ -76,7 +76,7 @@ class AdminPanelMenu extends React.Component {
getGroupItemIndex() {
const group = this.getRoutes()[this.getGroupIndex()];
- const pathname = this.props.location.pathname;
+ const pathname = this.props.location.pathname + this.props.location.search;
return _.findIndex(group.items, {path: pathname});
}
@@ -90,7 +90,23 @@ class AdminPanelMenu extends React.Component {
return (groupIndex === -1) ? 0 : groupIndex;
}
+ getCustomlists() {
+ if(window.customTicketList){
+ return window.customTicketList.map((item, index) => {
+ return {
+ name: item.title,
+ path: '/admin/panel/tickets/search-tickets?custom=' + index,
+ level: 1
+ }
+ })
+ } else {
+ return [];
+ }
+ }
+
getRoutes() {
+ const customLists = this.getCustomlists();
+
return this.getItemsByFilteredByLevel(_.without([
{
groupName: i18n('DASHBOARD'),
@@ -135,7 +151,8 @@ class AdminPanelMenu extends React.Component {
name: i18n('CUSTOM_RESPONSES'),
path: '/admin/panel/tickets/custom-responses',
level: 2
- }
+ },
+ ...customLists
])
},
this.props.config['user-system-enabled'] ? {
diff --git a/client/src/app/admin/panel/settings/admin-panel-advanced-settings.js b/client/src/app/admin/panel/settings/admin-panel-advanced-settings.js
index 39f769e0..0855e6e7 100644
--- a/client/src/app/admin/panel/settings/admin-panel-advanced-settings.js
+++ b/client/src/app/admin/panel/settings/admin-panel-advanced-settings.js
@@ -153,7 +153,7 @@ class AdminPanelAdvancedSettings extends React.Component {
ModalContainer.closeModal();
API.call({
path: '/system/add-api-key',
- data: {name}
+ data: {name, type: 'REGISTRATION'}
}).then(this.getAllKeys.bind(this));
}
@@ -177,7 +177,7 @@ class AdminPanelAdvancedSettings extends React.Component {
onRetrieveSuccess(result) {
this.setState({
- APIKeys: result.data,
+ APIKeys: result.data.filter(key => key['type'] === 'REGISTRATION'),
selectedAPIKey: -1
});
}
diff --git a/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js
new file mode 100644
index 00000000..f5726f2c
--- /dev/null
+++ b/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import {connect} from 'react-redux';
+
+import i18n from 'lib-app/i18n';
+
+import TicketQueryList from 'app-components/ticket-query-list';
+
+import Header from 'core-components/header';
+import Message from 'core-components/message';
+
+class AdminPanelSearchTickets extends React.Component {
+
+ render() {
+ return (
+
+
+ {(this.props.error) ? {i18n('ERROR_RETRIEVING_TICKETS')} : }
+
+ );
+ }
+
+ getFilters() {
+ let customList = (window.customTicketList && window.customTicketList[this.props.location.query.custom*1]) ? window.customTicketList[this.props.location.query.custom*1] : null
+ return {
+ ...customList
+ };
+ }
+}
+
+export default connect((store) => {
+ return {
+ error: store.adminData.allTicketsError
+ };
+})(AdminPanelSearchTickets);
diff --git a/client/src/core-components/menu.js b/client/src/core-components/menu.js
index 25cd805d..40ef6de2 100644
--- a/client/src/core-components/menu.js
+++ b/client/src/core-components/menu.js
@@ -140,4 +140,4 @@ class Menu extends React.Component {
}
}
-export default Menu;
\ No newline at end of file
+export default Menu;
diff --git a/client/src/core-components/menu.scss b/client/src/core-components/menu.scss
index 64eab16c..d8b06c20 100644
--- a/client/src/core-components/menu.scss
+++ b/client/src/core-components/menu.scss
@@ -201,4 +201,4 @@ $transition: background-color 0.3s ease, color 0.3s ease;
color: white;
}
}
-}
\ No newline at end of file
+}
diff --git a/client/src/core-components/pagination.js b/client/src/core-components/pagination.js
index 4b4ad162..8ce28a8d 100644
--- a/client/src/core-components/pagination.js
+++ b/client/src/core-components/pagination.js
@@ -98,4 +98,4 @@ class Pagination extends React.Component {
}
}
-export default Pagination;
\ No newline at end of file
+export default Pagination;
diff --git a/client/src/core-components/table.js b/client/src/core-components/table.js
index fe882f72..07c9f29f 100644
--- a/client/src/core-components/table.js
+++ b/client/src/core-components/table.js
@@ -55,7 +55,7 @@ class Table extends React.Component {
'table__header-column': true,
[header.className]: (header.className)
};
-
+
return (
{header.value}
@@ -97,7 +97,7 @@ class Table extends React.Component {
};
return (
-
+
| {row[key]} |
);
}
@@ -139,15 +139,15 @@ class Table extends React.Component {
this.props.onPageChange({target: {value: index}});
}
}
-
+
getRowClass(row) {
let classes = {
'table__row': true,
'table__row-highlighted': row.highlighted
};
-
+
classes[row.className] = (row.className);
-
+
return classNames(classes);
}
@@ -167,4 +167,4 @@ class Table extends React.Component {
}
}
-export default Table;
\ No newline at end of file
+export default Table;
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index 361dcb00..c1839ae1 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -91,9 +91,11 @@ export default {
'BAN_EMAIL': 'Ban email',
'EDIT_EMAIL': 'Edit email',
'EDIT_PASSWORD': 'Edit password',
+ 'EDIT_TITLE': 'Edit title',
'CHANGE_EMAIL': 'Change email',
'CHANGE_PASSWORD': 'Change password',
'NAME': 'Name',
+ 'SEARCH': 'Search',
'SIGNUP_DATE': 'Sign up date',
'SEARCH_USERS': 'Search users...',
'SEARCH_EMAIL': 'Search email...',
@@ -232,7 +234,7 @@ export default {
'ACTIVITY_DEPARTMENT_CHANGED': 'changed department of ticket',
'ACTIVITY_PRIORITY_CHANGED': 'changed priority of ticket',
'ACTIVITY_EDIT_COMMENT': 'edited a comment of ticket',
-
+ 'ACTIVITY_EDIT_TITLE': 'edited title of ticket',
'ACTIVITY_EDIT_SETTINGS': 'edited settings',
'ACTIVITY_SIGNUP': 'signed up',
'ACTIVITY_INVITE': 'invited user',
@@ -297,6 +299,7 @@ export default {
'MY_TICKETS_DESCRIPTION': 'Here you can view the tickets you are responsible for.',
'NEW_TICKETS_DESCRIPTION': 'Here you can view all the new tickets that are not assigned by anyone.',
'ALL_TICKETS_DESCRIPTION': 'Here you can view the tickets of the departments you are assigned.',
+ 'SEARCH_TICKETS_DESCRIPTION': 'Here you can search tickets by specific filters',
'TICKET_VIEW_DESCRIPTION': 'This ticket has been sent by a customer. Here you can respond or assign the ticket',
'BAN_USERS_DESCRIPTION': 'Here you can see a list of banned emails, you can un-ban them or add more emails to the list.',
'LIST_USERS_DESCRIPTION': 'This is the list of users that are registered in this platform. You can search for someone in particular, delete it or ban it.',
@@ -358,6 +361,7 @@ export default {
'TICKET_COMMENT_ERROR': 'An error occurred while trying to add the comment.',
'NO_PERMISSION': 'You\'ve no permission to access to this page.',
'INVALID_USER': 'User id is invalid',
+ 'INVALID_TITLE': 'invalid title',
'ERROR_RETRIEVING_TICKETS': 'An error occurred while trying to retrieve tickets.',
'ERROR_RETRIEVING_USERS': 'An error occurred while trying to retrieve users.',
'ERROR_RETRIEVING_BAN_LIST': 'An error occurred while trying to retrieve the list of banned emails.',
@@ -406,6 +410,7 @@ export default {
'SERVER_CREDENTIALS_WORKING': 'Server credentials are working correctly',
'DELETE_CUSTOM_FIELD_SURE': 'Some users may be using this field. Are you sure you want to delete it?',
+ 'TITLE_EDITED': '(title edited)',
'COMMENT_EDITED': '(comment edited)',
'LAST_7_DAYS': 'Last 7 days',
'LAST_30_DAYS': 'Last 30 days',
diff --git a/client/src/data/languages/pl.js b/client/src/data/languages/pl.js
index ac44a9cf..a03bd8af 100644
--- a/client/src/data/languages/pl.js
+++ b/client/src/data/languages/pl.js
@@ -29,8 +29,8 @@ export default {
'DATE': 'Data',
'RESPOND': 'Odpowiedz',
'RESPOND_TICKET': 'Odpowiedź na zgłoszenie',
- 'CLOSE_TICKET': 'blisko bilet',
- 'DELETE_TICKET': 'Usuń bilet',
+ 'CLOSE_TICKET': 'Zamknij zgłoszenie',
+ 'DELETE_TICKET': 'Usuń zgłoszenie',
'NO_ATTACHMENT': 'Bez załącznika',
'STAFF': 'Personel',
'CUSTOMER': 'Klient',
diff --git a/client/src/index.html b/client/src/index.html
index 90c8c2e2..a00af5b1 100755
--- a/client/src/index.html
+++ b/client/src/index.html
@@ -12,7 +12,6 @@
-
diff --git a/server/controllers/staff/get-all-tickets.php b/server/controllers/staff/get-all-tickets.php
index 93a30975..a1530e8f 100755
--- a/server/controllers/staff/get-all-tickets.php
+++ b/server/controllers/staff/get-all-tickets.php
@@ -50,7 +50,7 @@ class GetAllTicketsStaffController extends Controller {
]);
return;
}
-
+
Response::respondSuccess([
'tickets' => $this->getTicketList()->toArray(true),
'pages' => $this->getTotalPages()
diff --git a/server/controllers/system/add-api-key.php b/server/controllers/system/add-api-key.php
index 38ef0861..fbb34107 100755
--- a/server/controllers/system/add-api-key.php
+++ b/server/controllers/system/add-api-key.php
@@ -14,10 +14,12 @@ use Respect\Validation\Validator as DataValidator;
* @apiPermission staff3
*
* @apiParam {String} name Name of the new APIKey.
+ * @apiParam {String} type Type of APIKey: "REGISTRATION" or "TICKET_CREATE"
*
* @apiUse NO_PERMISSION
* @apiUse INVALID_NAME
* @apiUse NAME_ALREADY_USED
+ * @apiUse INVALID_API_KEY_TYPE
*
* @apiSuccess {String} data Token of the APIKey.
*
@@ -34,6 +36,10 @@ class AddAPIKeyController extends Controller {
'name' => [
'validation' => DataValidator::length(2, 55)->alnum(),
'error' => ERRORS::INVALID_NAME
+ ],
+ 'type' => [
+ 'validation' => DataValidator::in(APIKey::TYPES),
+ 'error' => ERRORS::INVALID_API_KEY_TYPE
]
]
];
@@ -43,6 +49,7 @@ class AddAPIKeyController extends Controller {
$apiInstance = new APIKey();
$name = Controller::request('name');
+ $type = Controller::request('type');
$keyInstance = APIKey::getDataStore($name, 'name');
@@ -51,7 +58,8 @@ class AddAPIKeyController extends Controller {
$apiInstance->setProperties([
'name' => $name,
- 'token' => $token
+ 'token' => $token,
+ 'type' => $type,
]);
$apiInstance->store();
diff --git a/server/controllers/ticket.php b/server/controllers/ticket.php
index 5afbf8d5..bc046c51 100755
--- a/server/controllers/ticket.php
+++ b/server/controllers/ticket.php
@@ -4,6 +4,7 @@ $ticketControllers->setGroupPath('/ticket');
$ticketControllers->addController(new CreateController);
$ticketControllers->addController(new EditCommentController);
+$ticketControllers->addController(new EditTitleController);
$ticketControllers->addController(new CommentController);
$ticketControllers->addController(new TicketGetController);
$ticketControllers->addController(new CheckTicketController);
@@ -23,5 +24,6 @@ $ticketControllers->addController(new DeleteTagController);
$ticketControllers->addController(new GetTagsController);
$ticketControllers->addController(new AddTagController);
$ticketControllers->addController(new RemoveTagController);
+$ticketControllers->addController(new SearchController);
$ticketControllers->finalize();
diff --git a/server/controllers/ticket/create.php b/server/controllers/ticket/create.php
index 1ea18790..6fb76b28 100755
--- a/server/controllers/ticket/create.php
+++ b/server/controllers/ticket/create.php
@@ -75,7 +75,7 @@ class CreateController extends Controller {
if(!Controller::isUserSystemEnabled() && !Controller::isStaffLogged()) {
$validations['permission'] = 'any';
$validations['requestData']['captcha'] = [
- 'validation' => DataValidator::captcha(),
+ 'validation' => DataValidator::captcha(APIKey::TICKET_CREATE),
'error' => ERRORS::INVALID_CAPTCHA
];
$validations['requestData']['email'] = [
diff --git a/server/controllers/ticket/edit-comment.php b/server/controllers/ticket/edit-comment.php
index c924694b..a0ffe1bf 100644
--- a/server/controllers/ticket/edit-comment.php
+++ b/server/controllers/ticket/edit-comment.php
@@ -20,6 +20,7 @@ DataValidator::with('CustomValidations', true);
*
* @apiUse NO_PERMISSION
* @apiUse INVALID_CONTENT
+ * @apiUse INVALID_TOKEN
*
* @apiSuccess {Object} data Empty object
*
@@ -30,15 +31,39 @@ class EditCommentController extends Controller {
const METHOD = 'POST';
public function validations() {
- return [
- 'permission' => 'user',
- 'requestData' => [
- 'content' => [
- 'validation' => DataValidator::length(10, 5000),
- 'error' => ERRORS::INVALID_CONTENT
+ if(Controller::isUserSystemEnabled()){
+ return [
+ 'permission' => 'user',
+ 'requestData' => [
+ 'content' => [
+ 'validation' => DataValidator::length(10, 5000),
+ 'error' => ERRORS::INVALID_CONTENT
+ ],
+ 'ticketNumber' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validTicketNumber(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_TICKET
+ ]
]
- ]
- ];
+ ];
+ } else {
+ return [
+ 'permission' => 'any',
+ 'requestData' => [
+ 'content' => [
+ 'validation' => DataValidator::length(10, 5000),
+ 'error' => ERRORS::INVALID_CONTENT
+ ],
+ 'ticketNumber' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validTicketNumber(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_TICKET
+ ],
+ 'csrf_token' => [
+ 'validation' => DataValidator::equals(Session::getInstance()->getToken()),
+ 'error' => ERRORS::INVALID_TOKEN
+ ]
+ ]
+ ];
+ }
}
public function handler() {
@@ -49,7 +74,7 @@ class EditCommentController extends Controller {
$ticketevent = Ticketevent::getTicketEvent(Controller::request('ticketEventId'));
$ticket = Ticket::getByTicketNumber(Controller::request('ticketNumber'));
- if(!Controller::isStaffLogged() && ($user->id !== $ticketevent->authorUserId && $user->id !== $ticket->authorId ) ){
+ if(Controller::isUserSystemEnabled() && !Controller::isStaffLogged() && ($user->id !== $ticketevent->authorUserId && $user->id !== $ticket->authorId ) ){
throw new RequestException(ERRORS::NO_PERMISSION);
}
diff --git a/server/controllers/ticket/edit-title.php b/server/controllers/ticket/edit-title.php
new file mode 100644
index 00000000..f407d28d
--- /dev/null
+++ b/server/controllers/ticket/edit-title.php
@@ -0,0 +1,86 @@
+ 'user',
+ 'requestData' => [
+ 'title' => [
+ 'validation' => DataValidator::length(1, 200),
+ 'error' => ERRORS::INVALID_TITLE
+ ],
+ 'ticketNumber' => [
+ 'validation' => DataValidator::validTicketNumber(),
+ 'error' => ERRORS::INVALID_TICKET
+ ]
+ ]
+ ];
+ } else {
+ return [
+ 'permission' => 'any',
+ 'requestData' => [
+ 'title' => [
+ 'validation' => DataValidator::length(1, 200),
+ 'error' => ERRORS::INVALID_TITLE
+ ],
+ 'ticketNumber' => [
+ 'validation' => DataValidator::validTicketNumber(),
+ 'error' => ERRORS::INVALID_TICKET
+ ],
+ 'csrf_token' => [
+ 'validation' => DataValidator::equals(Session::getInstance()->getToken()),
+ 'error' => ERRORS::INVALID_TOKEN
+ ]
+ ]
+ ];
+ }
+ }
+
+ public function handler() {
+ $user = Controller::getLoggedUser();
+ $newtitle = Controller::request('title');
+ $ticket = Ticket::getByTicketNumber(Controller::request('ticketNumber'));
+
+ if(Controller::isUserSystemEnabled() && !$user->canManageTicket($ticket)) {
+ throw new RequestException(ERRORS::NO_PERMISSION);
+ }
+
+ $ticket->title = $newtitle;
+ $ticket->editedTitle = true;
+ $ticket->store();
+
+ $ticketNumber = $ticket->ticketNumber;
+ Log::createLog('EDIT_TITLE', $ticketNumber);
+
+ Response::respondSuccess();
+ }
+}
diff --git a/server/controllers/ticket/search.php b/server/controllers/ticket/search.php
new file mode 100644
index 00000000..00431c34
--- /dev/null
+++ b/server/controllers/ticket/search.php
@@ -0,0 +1,348 @@
+ 'staff_1',
+ 'requestData' => [
+ 'page' => [
+ 'validation' => DataValidator::oneOf(DataValidator::numeric()->positive(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_PAGE
+ ],
+ 'tags' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validTagsId(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_TAG_FILTER
+ ],
+ 'closed' => [
+ 'validation' => DataValidator::oneOf(DataValidator::in(['0','1']),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_CLOSED_FILTER
+ ],
+ 'unreadStaff' => [
+ 'validation' => DataValidator::oneOf(DataValidator::in(['0','1']),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_UNREAD_STAFF_FILTER
+ ],
+ 'priority' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validPriorities(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_PRIORITY_FILTER
+ ],
+ 'dateRange' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validDateRange(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_DATE_RANGE_FILTER
+ ],
+ 'departments' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validDepartmentsId(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_DEPARTMENT_FILTER
+ ],
+ 'authors' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validAuthorsId(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_AUTHOR_FILTER
+ ],
+ 'assigned' => [
+ 'validation' => DataValidator::oneOf(DataValidator::in(['0','1']),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_ASSIGNED_FILTER
+ ],
+ 'orderBy' => [
+ 'validation' => DataValidator::oneOf(DataValidator::validOrderBy(),DataValidator::nullType()),
+ 'error' => ERRORS::INVALID_ORDER_BY
+ ],
+ ]
+ ];
+ }
+
+ public function handler() {
+ $inputs = [
+ 'closed' => Controller::request('closed'),
+ 'tags' => json_decode(Controller::request('tags')),
+ 'unreadStaff' => Controller::request('unreadStaff'),
+ 'priority' => json_decode(Controller::request('priority')),
+ 'dateRange' => json_decode(Controller::request('dateRange')),
+ 'departments' => json_decode(Controller::request('departments')),
+ 'authors' => json_decode(Controller::request('authors'),true),
+ 'assigned' => Controller::request('assigned'),
+ 'query' => Controller::request('query'),
+ 'orderBy' => json_decode(Controller::request('orderBy'),true),
+ 'page' => Controller::request('page'),
+ 'allowedDepartments' => Controller::getLoggedUser()->sharedDepartmentList->toArray(),
+ ];
+
+
+ $query = $this->getSQLQuery($inputs);
+ $queryWithOrder = $this->getSQLQueryWithOrder($inputs);
+ $totalCount = RedBean::getAll("SELECT COUNT(*) FROM (SELECT COUNT(*) " . $query . " ) AS T2", [':query' => $inputs['query']])[0]['COUNT(*)'];
+ $ticketIdList = RedBean::getAll($queryWithOrder, [':query' => "%" . $inputs['query'] . "%"]);
+ $ticketList = [];
+
+ foreach ($ticketIdList as $item) {
+ $ticket = Ticket::getDataStore($item['id']);
+ array_push($ticketList, $ticket->toArray());
+ }
+ $ticketTableExists = RedBean::exec("select table_name from information_schema.tables where table_name = 'ticket';");
+
+ if($ticketTableExists){
+ Response::respondSuccess([
+ 'tickets' => $ticketList,
+ 'pages' => ceil($totalCount / 10),
+ 'page' => $inputs['page'] ? ($inputs['page']*1) : 1
+ ]);
+ }else{
+ Response::respondSuccess([]);
+ }
+
+ }
+
+ public function getSQLQuery($inputs) {
+ $tagsTableExists = RedBean::exec("select table_name from information_schema.tables where table_name = 'tag_ticket';");
+ $ticketEventTableExists = RedBean::exec("select table_name from information_schema.tables where table_name = 'ticketevent';");
+
+ $taglistQuery = ( $tagsTableExists ? " LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id" : '');
+ $ticketeventlistQuery = ( $ticketEventTableExists ? " LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id" : '');
+
+ $query = "FROM (ticket" . $taglistQuery . $ticketeventlistQuery .")";
+ $filters = "";
+ $this->setQueryFilters($inputs, $filters);
+ $query .= $filters . " GROUP BY ticket.id";
+ return $query;
+ }
+
+ public function getSQLQueryWithOrder($inputs) {
+ $query = $this->getSQLQuery($inputs);
+ $order = "";
+ $query = "SELECT" . " ticket.id " . $query;
+
+ $this->setQueryOrder($inputs, $order);
+ $inputs['page'] ? $page = $inputs['page'] : $page = 1 ;
+ $query .= $order ." LIMIT 10 OFFSET " . (($page-1)*10);
+ return $query;
+ }
+
+ //FILTER
+ private function setQueryFilters($inputs, &$filters){
+ if(array_key_exists('tags',$inputs)) $this->setTagFilter($inputs['tags'], $filters);
+ if(array_key_exists('closed',$inputs)) $this->setClosedFilter($inputs['closed'], $filters);
+ if(array_key_exists('assigned',$inputs)) $this->setAssignedFilter($inputs['assigned'], $filters);
+ if(array_key_exists('unreadStaff',$inputs)) $this->setSeenFilter($inputs['unreadStaff'], $filters);
+ if(array_key_exists('priority',$inputs)) $this->setPriorityFilter($inputs['priority'], $filters);
+ if(array_key_exists('dateRange',$inputs)) $this->setDateFilter($inputs['dateRange'], $filters);
+ if(array_key_exists('departments',$inputs)) $this->setDepartmentFilter($inputs['departments'],$inputs['allowedDepartments'], $filters);
+ if(array_key_exists('authors',$inputs)) $this->setAuthorFilter($inputs['authors'], $filters);
+ if(array_key_exists('query',$inputs)) $this->setStringFilter($inputs['query'], $filters);
+ if($filters != "") $filters = " WHERE " . $filters;
+ }
+
+ private function setTagFilter($tagList, &$filters){
+ $tagsTableExists = RedBean::exec("select table_name from information_schema.tables where table_name = 'tag_ticket';");
+
+ if($tagList && $tagsTableExists){
+ $filters != "" ? $filters .= " and " : null;
+
+ foreach($tagList as $key => $tag) {
+
+ $key == 0 ? $filters .= " ( " : null;
+ ($key != 0 && $key != sizeof($tagList)) ? $filters .= " or " : null;
+
+ $filters .= "tag_ticket.tag_id = " . $tag ;
+ }
+ $filters .= ")";
+ }
+ }
+ public function setClosedFilter($closed, &$filters){
+ if ($closed !== null) {
+ if ($filters != "") $filters .= " and ";
+ $filters .= "ticket.closed = " . $closed ;
+ }
+ }
+ private function setSeenFilter($unreadStaff, &$filters){
+ if ($unreadStaff !== null) {
+ if ($filters != "") $filters .= " and ";
+ $filters .= "ticket.unread_staff = " . $unreadStaff;
+ }
+ }
+ private function setPriorityFilter($priorities, &$filters){
+ if($priorities !== null){
+ $first = TRUE;
+ if ($filters != "") $filters .= " and ";
+ foreach(array_unique($priorities) as $priority) {
+
+ if($first){
+ $filters .= " ( ";
+ $first = FALSE;
+ } else {
+ $filters .= " or ";
+ }
+
+ if($priority == 0){
+ $filters .= "ticket.priority = 'low'";
+ }elseif($priority == 1){
+ $filters .= "ticket.priority = 'medium'";
+ }elseif($priority == 2){
+ $filters .= "ticket.priority = 'high'";
+ }
+
+
+ }
+ $priorities != "" ? $filters .= ") " : null;
+ }
+
+ }
+
+ private function setDateFilter($dateRange, &$filters){
+ if ($dateRange !== null) {
+ if ($filters != "") $filters .= " and ";
+
+ foreach($dateRange as $key => $date) {
+ $key == 0 ? ($filters .= "(ticket.date >= " . $date ): ($filters .= " and ticket.date <= " . $date . ")");
+ }
+ }
+ }
+
+ private function setDepartmentFilter($departments,$allowedDepartments, &$filters){
+ $validDepartments = $this->generateValidDepartmentList($departments, $allowedDepartments);
+ if ($filters != "") $filters .= " and ";
+ $first = TRUE;
+
+ foreach($validDepartments as $department) {
+ if($first){
+ $filters .= " ( ";
+ $first = FALSE;
+ } else {
+ $filters .= " or ";
+ }
+ $filters .= "ticket.department_id = " . $department;
+ }
+ $filters .= ")";
+
+ }
+
+ private function setAuthorFilter($authors, &$filters){
+ if($authors !== null){
+ $first = TRUE;
+ if ($filters != "") $filters .= " and ";
+
+ foreach($authors as $author){
+
+ if($first){
+ $filters .= " ( ";
+ $first = FALSE;
+ } else {
+ $filters .= " or ";
+ }
+
+ if($author['staff']){
+ $filters .= "ticket.author_staff_id = " . $author['id'];
+ } else {
+ $filters .= "ticket.author_id = " . $author['id'];
+ }
+ }
+
+ $filters .= ")";
+
+ }
+ }
+
+ private function setAssignedFilter($assigned, &$filters){
+ if($assigned !== null){
+ if ($filters != "") $filters .= " and ";
+ $key = "";
+ $assigned == 0 ? $key = "IS NULL" : $key = "IS NOT NULL";
+ $filters .= "ticket.owner_id " . $key;
+ }
+ }
+
+ private function setStringFilter($search, &$filters){
+ $ticketEventTableExists = RedBean::exec("select table_name from information_schema.tables where table_name = 'ticketevent';");
+
+ if($search !== null){
+ if ($filters != "") $filters .= " and ";
+ $ticketevent = ( $ticketEventTableExists ? " or (ticketevent.type = 'COMMENT' and ticketevent.content LIKE :query)" : "");
+ $filters .= " (ticket.title LIKE :query or ticket.content LIKE :query or ticket.ticket_number LIKE :query". $ticketevent ." )";
+ };
+ }
+
+ private function generateValidDepartmentList($departments, $allowedDepartments){
+ $result = [];
+ $managedDepartments = [];
+ if($departments == null) $departments = [];
+ foreach ($allowedDepartments as $department) {
+ array_push($managedDepartments,$department['id']);
+ }
+ $result = array_intersect($departments,$managedDepartments);
+
+ if(empty($result)) $result = $managedDepartments;
+
+ $result = array_unique($result);
+
+ return $result;
+ }
+
+ //ORDER
+ private function setQueryOrder($inputs, &$order){
+ $order = " ORDER BY ";
+ if(array_key_exists('query',$inputs)) $this->setStringOrder($inputs['query'], $order);
+ if(array_key_exists('orderBy',$inputs)) $this->setEspecificOrder($inputs['orderBy'], $order);
+ $order .= "ticket.closed asc, ticket.owner_id asc, ticket.unread_staff asc, ticket.priority desc, ticket.date desc ";
+ }
+ private function setEspecificOrder($orderBy, &$order){
+ if($orderBy !== null){
+ $orientation = ($orderBy['asc'] ? " asc" : " desc" );
+ $order .= "ticket." . $orderBy['value'] . $orientation . ",";
+ };
+ }
+ private function setStringOrder($querysearch, &$order){
+ $ticketEventTableExists = RedBean::exec("select table_name from information_schema.tables where table_name = 'ticketevent';");
+
+ if($querysearch !== null){
+ $ticketeventOrder = ( $ticketEventTableExists ? " CASE WHEN (ticketevent.type = 'COMMENT' and ticketevent.content LIKE :query) THEN ticketevent.content END desc," : "");
+ $order .= "CASE WHEN (ticket.ticket_number LIKE :query) THEN ticket.ticket_number END desc,CASE WHEN (ticket.title LIKE :query) THEN ticket.title END desc, CASE WHEN ( ticket.content LIKE :query) THEN ticket.content END desc," . $ticketeventOrder ;
+ }
+ }
+
+}
diff --git a/server/controllers/user/signup.php b/server/controllers/user/signup.php
index ec6736cb..12184a0b 100755
--- a/server/controllers/user/signup.php
+++ b/server/controllers/user/signup.php
@@ -72,7 +72,7 @@ class SignUpController extends Controller {
if(!$this->csvImported) {
$validations['requestData']['captcha'] = [
- 'validation' => DataValidator::captcha(),
+ 'validation' => DataValidator::captcha(APIKey::REGISTRATION),
'error' => ERRORS::INVALID_CAPTCHA
];
}
@@ -103,6 +103,10 @@ class SignUpController extends Controller {
throw new RequestException(ERRORS::NO_PERMISSION);
}
+ if(!$apiKey->isNull() && $apiKey->type !== APIKey::REGISTRATION) {
+ throw new RequestException(ERRORS::INVALID_API_KEY_TYPE);
+ }
+
$userId = $this->createNewUserAndRetrieveId();
if(MailSender::getInstance()->isConnected()) {
diff --git a/server/data/ERRORS.php b/server/data/ERRORS.php
index 831086a9..34338349 100755
--- a/server/data/ERRORS.php
+++ b/server/data/ERRORS.php
@@ -251,6 +251,10 @@
* @apiDefine INVALID_COLOR
* @apiError {String} INVALID_COLOR The color should be in hexadecimal, preceded by a '#'
*/
+/**
+ * @apiDefine INVALID_API_KEY_TYPE
+ * @apiError {String} INVALID_API_KEY_TYPE Api key type is not one of the availables
+ */
class ERRORS {
const INVALID_CREDENTIALS = 'INVALID_CREDENTIALS';
@@ -277,6 +281,15 @@ class ERRORS {
const INVALID_PRIORITY = 'INVALID_PRIORITY';
const INVALID_PAGE = 'INVALID_PAGE';
const INVALID_QUERY = 'INVALID_QUERY';
+ const INVALID_TAG_FILTER = 'INVALID_TAG_FILTER';
+ const INVALID_CLOSED_FILTER = 'INVALID_CLOSED_FILTER';
+ const INVALID_UNREAD_STAFF_FILTER = 'INVALID_UNREAD_STAFF_FILTER';
+ const INVALID_PRIORITY_FILTER = 'INVALID_PRIORITY_FILTER';
+ const INVALID_DATE_RANGE_FILTER = 'INVALID_DATE_RANGE_FILTER';
+ const INVALID_DEPARTMENT_FILTER = 'INVALID_DEPARTMENT_FILTER';
+ const INVALID_AUTHOR_FILTER = 'INVALID_AUTHOR_FILTER';
+ const INVALID_ASSIGNED_FILTER = 'INVALID_ASSIGNED_FILTER';
+ const INVALID_ORDER_BY = 'INVALID_ORDER_BY';
const INVALID_TOPIC = 'INVALID_TOPIC';
const INVALID_SEARCH = 'INVALID_SEARCH';
const INVALID_ORDER = 'INVALID_ORDER';
@@ -317,4 +330,5 @@ class ERRORS {
const INVALID_CUSTOM_FIELD_OPTION = 'INVALID_CUSTOM_FIELD_OPTION';
const UNAVAILABLE_STATS = 'UNAVAILABLE_STATS';
const INVALID_COLOR = 'INVALID_COLOR';
+ const INVALID_API_KEY_TYPE = 'INVALID_API_KEY_TYPE';
}
diff --git a/server/libs/validations/captcha.php b/server/libs/validations/captcha.php
index 7ac805c2..e37ca9fa 100755
--- a/server/libs/validations/captcha.php
+++ b/server/libs/validations/captcha.php
@@ -5,12 +5,22 @@ namespace CustomValidations;
use Respect\Validation\Rules\AbstractRule;
class Captcha extends AbstractRule {
+ private $dataStoreName;
+
+ public function __construct($apiKeyType = '') {
+ if (in_array($apiKeyType, \APIKey::TYPES)) {
+ $this->apiKeyType = $apiKeyType;
+ } else if($apiKeyType) {
+ throw new \Exception(\ERRORS::INVALID_API_KEY_TYPE);
+ }
+ }
public function validate($reCaptchaResponse) {
$reCaptchaPrivateKey = \Setting::getSetting('recaptcha-private')->getValue();
$apiKey = \APIKey::getDataStore(\Controller::request('apiKey'), 'token');
- if (!$reCaptchaPrivateKey || !$apiKey->isNull()) return true;
+ if (!$reCaptchaPrivateKey) return true;
+ if (!$apiKey->isNull() && $apiKey->type === $apiKeyType) return true;
$reCaptcha = new \ReCaptcha\ReCaptcha($reCaptchaPrivateKey);
$reCaptchaValidation = $reCaptcha->verify($reCaptchaResponse, $_SERVER['REMOTE_ADDR']);
diff --git a/server/libs/validations/validAuthorsId.php b/server/libs/validations/validAuthorsId.php
new file mode 100644
index 00000000..3cda8229
--- /dev/null
+++ b/server/libs/validations/validAuthorsId.php
@@ -0,0 +1,23 @@
+staff){
+ $author = \Staff::getDataStore($authorObject->id);
+ }else{
+ $author = \User::getDataStore($authorObject->id);
+ }
+ if($author->isNull()) return false;
+ }
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/server/libs/validations/validDateRange.php b/server/libs/validations/validDateRange.php
new file mode 100644
index 00000000..c2bb3f05
--- /dev/null
+++ b/server/libs/validations/validDateRange.php
@@ -0,0 +1,20 @@
+isNull()) return false;
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/server/libs/validations/validOrderBy.php b/server/libs/validations/validOrderBy.php
new file mode 100644
index 00000000..40babc27
--- /dev/null
+++ b/server/libs/validations/validOrderBy.php
@@ -0,0 +1,19 @@
+asc !== 1 && $object->asc !== 0) || !in_array($object->value, $values)) return false;
+
+ return true;
+ }
+ }
+}
diff --git a/server/libs/validations/validPriorities.php b/server/libs/validations/validPriorities.php
new file mode 100644
index 00000000..aa3ba658
--- /dev/null
+++ b/server/libs/validations/validPriorities.php
@@ -0,0 +1,19 @@
+isNull()) return false;
+ }
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/server/models/APIKey.php b/server/models/APIKey.php
index 436b2b14..9cb1c4ff 100755
--- a/server/models/APIKey.php
+++ b/server/models/APIKey.php
@@ -9,18 +9,29 @@
class APIKey extends DataStore {
const TABLE = 'apikey';
+ const REGISTRATION = 'REGISTRATION';
+ const TICKET_CREATE = 'TICKET_CREATE';
+ const TYPES = [APIKey::REGISTRATION, APIKey::TICKET_CREATE];
public static function getProps() {
return [
'name',
- 'token'
+ 'token',
+ 'type'
+ ];
+ }
+
+ public function getDefaultProps() {
+ return [
+ 'type' => APIKey::REGISTRATION
];
}
public function toArray() {
return [
'name' => $this->name,
- 'token' => $this->token
+ 'token' => $this->token,
+ 'type' => $this->type
];
}
}
\ No newline at end of file
diff --git a/server/models/Ticket.php b/server/models/Ticket.php
index 5ad71589..991487fc 100755
--- a/server/models/Ticket.php
+++ b/server/models/Ticket.php
@@ -51,7 +51,8 @@ class Ticket extends DataStore {
'authorEmail',
'authorName',
'sharedTagList',
- 'editedContent'
+ 'editedContent',
+ 'editedTitle'
);
}
@@ -132,7 +133,8 @@ class Ticket extends DataStore {
'owner' => $this->ownerToArray(),
'events' => $minimized ? [] : $this->eventsToArray(),
'tags' => $this->sharedTagList->toArray(true),
- 'edited' => $this->editedContent
+ 'edited' => $this->editedContent,
+ 'editedTitle' => $this->editedTitle
];
}
diff --git a/server/tests/__mocks__/APIKeyMock.php b/server/tests/__mocks__/APIKeyMock.php
index 7ef32d77..70f5d0d8 100755
--- a/server/tests/__mocks__/APIKeyMock.php
+++ b/server/tests/__mocks__/APIKeyMock.php
@@ -2,6 +2,10 @@
include_once 'tests/__mocks__/NullDataStoreMock.php';
class APIKey extends \Mock {
+ const REGISTRATION = 'REGISTRATION';
+ const TICKET_CREATE = 'TICKET_CREATE';
+ const TYPES = [APIKey::REGISTRATION, APIKey::TICKET_CREATE];
+
public static $functionList = array();
public static function initStubs() {
diff --git a/server/tests/__mocks__/ControllerMock.php b/server/tests/__mocks__/ControllerMock.php
index 7a4e8149..fa24452a 100755
--- a/server/tests/__mocks__/ControllerMock.php
+++ b/server/tests/__mocks__/ControllerMock.php
@@ -1,13 +1,19 @@
\Mock::stub()->returns(1)
+ ]);
+ Controller::$requestReturnMock = null;
+ $_SERVER['REMOTE_ADDR'] = 'MOCK_REMOTE';
+ $this->searchController = new SearchController();
+ }
+
+ public function testTagsFilter() {
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'tags' => []
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'tags' => [0]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( tag_ticket.tag_id = 0) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'tags' => [0,1,2]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( tag_ticket.tag_id = 0 or tag_ticket.tag_id = 1 or tag_ticket.tag_id = 2) GROUP BY ticket.id'
+ );
+ }
+
+ public function testClosedFilter() {
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'closed'=> null
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'closed'=> 1
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ticket.closed = 1 GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'closed'=> '0'
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ticket.closed = 0 GROUP BY ticket.id'
+ );
+ }
+ public function testAssignedFilter(){
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'assigned'=> null
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'assigned'=> '0'
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ticket.owner_id IS NULL GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'assigned'=> 1
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ticket.owner_id IS NOT NULL GROUP BY ticket.id'
+ );
+ }
+ public function testUnreadStaffFilter() {
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'unreadStaff' => null
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'unreadStaff' => '0'
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ticket.unread_staff = 0 GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'unreadStaff' => 1
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ticket.unread_staff = 1 GROUP BY ticket.id'
+ );
+ }
+
+ public function testPriorityFilter() {
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'tags' => []
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'tags' => [1]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( tag_ticket.tag_id = 1) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'tags' => [2,3]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( tag_ticket.tag_id = 2 or tag_ticket.tag_id = 3) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'tags' => [1,2,3]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( tag_ticket.tag_id = 1 or tag_ticket.tag_id = 2 or tag_ticket.tag_id = 3) GROUP BY ticket.id'
+ );
+ }
+
+ public function testdateRangeFilter() {
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'dateRange' => null
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'dateRange' => [1,2]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE (ticket.date >= 1 and ticket.date <= 2) GROUP BY ticket.id'
+ );
+ }
+
+ public function testDepartmentsFilter() {
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'departments' => null,
+ 'allowedDepartments' => [
+ [
+ 'id' => 2
+ ],
+ [
+ 'id' => 1
+ ],
+ [
+ 'id' => 3
+ ]
+ ]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( ticket.department_id = 2 or ticket.department_id = 1 or ticket.department_id = 3) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'departments' => [1],
+ 'allowedDepartments' => [
+ [
+ 'id' => 2
+ ],
+ [
+ 'id' => 1
+ ],
+ [
+ 'id' => 3
+ ]
+ ]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( ticket.department_id = 1) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'departments' => [1,2,3],
+ 'allowedDepartments' => [
+ [
+ 'id' => 2
+ ],
+ [
+ 'id' => 1
+ ],
+ [
+ 'id' => 3
+ ]
+ ]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( ticket.department_id = 1 or ticket.department_id = 2 or ticket.department_id = 3) GROUP BY ticket.id'
+ );
+ }
+
+ public function testAuthorsFilter() {
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'authors' => null
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'authors' => [
+ [
+ 'id' => 1,
+ 'staff' => 1
+ ],
+ [
+ 'id' => 2,
+ 'staff' => 0
+ ]
+ ]
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE ( ticket.author_staff_id = 1 or ticket.author_id = 2) GROUP BY ticket.id'
+ );
+ }
+
+ public function testQueryFilter() {
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'query' => null
+ ]),
+ 'FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id'
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQuery([
+ 'query' => 'hello world'
+ ]),
+ "FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE (ticket.title LIKE :query or ticket.content LIKE :query or ticket.ticket_number LIKE :query or (ticketevent.type = 'COMMENT' and ticketevent.content LIKE :query) ) GROUP BY ticket.id"
+
+ );
+ }
+ public function testQueryWithOrder() {
+ $this->assertEquals(
+ $this->searchController->getSQLQueryWithOrder([
+ 'page' => 1
+ ]),
+ "SELECT ticket.id FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id ORDER BY ticket.closed asc, ticket.owner_id asc, ticket.unread_staff asc, ticket.priority desc, ticket.date desc LIMIT 10 OFFSET 0"
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQueryWithOrder([
+ 'page' => 1,
+ 'query' => 'stark'
+ ]),
+ "SELECT ticket.id FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) WHERE (ticket.title LIKE :query or ticket.content LIKE :query or ticket.ticket_number LIKE :query or (ticketevent.type = 'COMMENT' and ticketevent.content LIKE :query) ) GROUP BY ticket.id ORDER BY CASE WHEN (ticket.ticket_number LIKE :query) THEN ticket.ticket_number END desc,CASE WHEN (ticket.title LIKE :query) THEN ticket.title END desc, CASE WHEN ( ticket.content LIKE :query) THEN ticket.content END desc, CASE WHEN (ticketevent.type = 'COMMENT' and ticketevent.content LIKE :query) THEN ticketevent.content END desc,ticket.closed asc, ticket.owner_id asc, ticket.unread_staff asc, ticket.priority desc, ticket.date desc LIMIT 10 OFFSET 0"
+ );
+
+ $this->assertEquals(
+ $this->searchController->getSQLQueryWithOrder([
+ 'page' => 1,
+ 'orderBy' => ['value' => 'closed', 'asc' => 1]
+ ]),
+ "SELECT ticket.id FROM (ticket LEFT JOIN tag_ticket ON tag_ticket.ticket_id = ticket.id LEFT JOIN ticketevent ON ticketevent.ticket_id = ticket.id) GROUP BY ticket.id ORDER BY ticket.closed asc,ticket.closed asc, ticket.owner_id asc, ticket.unread_staff asc, ticket.priority desc, ticket.date desc LIMIT 10 OFFSET 0"
+ );
+ }
+}
diff --git a/server/tests/controllers/user/loginTest.php b/server/tests/controllers/user/loginTest.php
index 035aaa70..d9615ff3 100755
--- a/server/tests/controllers/user/loginTest.php
+++ b/server/tests/controllers/user/loginTest.php
@@ -35,9 +35,9 @@ class LoginControllerTest extends TestCase {
public function testShouldCreateSessionAndRespondSuccessIfCredentialsAreValid() {
Session::mockInstanceFunction('sessionExists', \Mock::stub()->returns(false));
+ Controller::useValueReturn();
$this->loginController->handler();
-
$this->assertTrue(!!Session::getInstance()->createSession->hasBeenCalledWithArgs('MOCK_ID', false));
$this->assertTrue(Response::get('respondSuccess')->hasBeenCalledWithArgs(array(
'userId' => 'MOCK_ID',
diff --git a/tests/init.rb b/tests/init.rb
index ffffdcb7..c4291800 100644
--- a/tests/init.rb
+++ b/tests/init.rb
@@ -56,11 +56,11 @@ require './system/edit-department.rb'
require './system/delete-department.rb'
require './staff/last-events.rb'
# require './system/mail-templates.rb'
-require './system/disable-registration.rb'
-require './system/enable-registration.rb'
require './system/add-api-key.rb'
require './system/delete-api-key.rb'
require './system/get-api-keys.rb'
+require './system/disable-registration.rb'
+require './system/enable-registration.rb'
require './system/file-upload-download.rb'
require './system/csv-import.rb'
require './ticket/create-tag.rb'
@@ -70,5 +70,7 @@ require './ticket/delete-tag.rb'
require './ticket/add-tag.rb'
require './ticket/delete-tag.rb'
require './ticket/edit-comment.rb'
+require './ticket/edit-title.rb'
require './system/disable-user-system.rb'
+require './ticket/search.rb'
# require './system/get-stats.rb'
diff --git a/tests/scripts.rb b/tests/scripts.rb
index e0c7e24c..2e7a7715 100644
--- a/tests/scripts.rb
+++ b/tests/scripts.rb
@@ -97,11 +97,12 @@ class Scripts
result['data']
end
- def self.createAPIKey(name)
+ def self.createAPIKey(name, type)
request('/system/add-api-key', {
csrf_userid: $csrf_userid,
csrf_token: $csrf_token,
- name: name
+ name: name,
+ type: type
})
end
diff --git a/tests/staff/get-all.rb b/tests/staff/get-all.rb
index dec7fdc5..f8571c71 100644
--- a/tests/staff/get-all.rb
+++ b/tests/staff/get-all.rb
@@ -10,14 +10,18 @@ describe'/staff/get-all' do
(result['status']).should.equal('success')
+ result['data'][0]['departments'] = result['data'][0]['departments'].sort_by do |department|
+ department['id'].to_i
+ end
+
(result['data'][0]['name']).should.equal('Emilia Clarke')
(result['data'][0]['email']).should.equal('staff@opensupports.com')
(result['data'][0]['profilePic']).should.equal('')
(result['data'][0]['level']).should.equal('3')
- (result['data'][0]['departments'][0]['id']).should.equal('2')
- (result['data'][0]['departments'][0]['name']).should.equal('useless private deapartment')
- (result['data'][0]['departments'][1]['id']).should.equal('1')
- (result['data'][0]['departments'][1]['name']).should.equal('Help and Support')
+ (result['data'][0]['departments'][0]['id']).should.equal('1')
+ (result['data'][0]['departments'][0]['name']).should.equal('Help and Support')
+ (result['data'][0]['departments'][1]['id']).should.equal('2')
+ (result['data'][0]['departments'][1]['name']).should.equal('useless private deapartment')
(result['data'][0]['departments'][2]['id']).should.equal('3')
(result['data'][0]['departments'][2]['name']).should.equal('Suggestions')
(result['data'][0]['assignedTickets']).should.equal(10)
diff --git a/tests/system/add-api-key.rb b/tests/system/add-api-key.rb
index cf8c86d5..ecf2f431 100644
--- a/tests/system/add-api-key.rb
+++ b/tests/system/add-api-key.rb
@@ -1,30 +1,44 @@
describe'system/add-api-key' do
- request('/user/logout')
- Scripts.login($staff[:email], $staff[:password], true)
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
- it 'should add API key' do
- result= request('/system/add-api-key', {
- csrf_userid: $csrf_userid,
- csrf_token: $csrf_token,
- name: 'new API'
- })
+ it 'should add API key' do
+ result= request('/system/add-api-key', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ name: 'new API',
+ type: 'REGISTRATION'
+ })
- (result['status']).should.equal('success')
+ (result['status']).should.equal('success')
- row = $database.getRow('apikey', 1, 'id')
+ row = $database.getRow('apikey', 1, 'id')
- (row['name']).should.equal('new API')
- (result['data']).should.equal(row['token'])
+ (row['name']).should.equal('new API')
+ (result['data']).should.equal(row['token'])
+ end
- end
- it 'should not add API key' do
- result= request('/system/add-api-key', {
- csrf_userid: $csrf_userid,
- csrf_token: $csrf_token,
- name: 'new API'
- })
+ it 'should not add API key if name already used' do
+ result= request('/system/add-api-key', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ name: 'new API',
+ type: 'REGISTRATION'
+ })
- (result['status']).should.equal('fail')
- (result['message']).should.equal('NAME_ALREADY_USED')
- end
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('NAME_ALREADY_USED')
+ end
+
+ it 'should not add API key if invalid type is used' do
+ result= request('/system/add-api-key', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ name: 'new API2',
+ type: 'REGISTRATON'
+ })
+
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_API_KEY_TYPE')
+ end
end
diff --git a/tests/system/disable-registration.rb b/tests/system/disable-registration.rb
index 13e4c06c..539a29dc 100644
--- a/tests/system/disable-registration.rb
+++ b/tests/system/disable-registration.rb
@@ -1,6 +1,7 @@
describe'/system/disable-registration' do
request('/user/logout')
Scripts.login($staff[:email], $staff[:password], true)
+ api_key = Scripts.createAPIKey('registrationKey', 'REGISTRATION')['data']
it 'should not disable registration if password is not correct' do
result= request('/system/disable-registration', {
@@ -17,7 +18,7 @@ describe'/system/disable-registration' do
end
it 'should disable registration' do
- result= request('/system/disable-registration', {
+ result = request('/system/disable-registration', {
csrf_userid: $csrf_userid,
csrf_token: $csrf_token,
password: $staff[:password]
@@ -31,13 +32,23 @@ describe'/system/disable-registration' do
end
it 'should not create user in database if registration is false' do
- response = request('/user/signup', {
+ result = request('/user/signup', {
:name => 'ponzio',
:email => 'jc@ponziolandia.com',
:password => 'tequila'
})
- (response['status']).should.equal('fail')
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('NO_PERMISSION')
+ end
+ it 'should create user if using api key' do
+ result = request('/user/signup', {
+ :name => 'ponzio',
+ :email => 'jc@ponziolandia.com',
+ :password => 'tequila',
+ :apiKey => api_key
+ })
+ (result['status']).should.equal('success')
end
end
diff --git a/tests/system/disable-user-system.rb b/tests/system/disable-user-system.rb
index 9ae8dd15..9550c0df 100644
--- a/tests/system/disable-user-system.rb
+++ b/tests/system/disable-user-system.rb
@@ -17,9 +17,9 @@ describe'system/disable-user-system' do
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 = $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(51)
+ (numberOftickets.num_rows).should.equal(52)
request('/user/logout')
@@ -122,7 +122,7 @@ describe'system/disable-user-system' do
(result['status']).should.equal('success')
(result['data'].size).should.equal(10)
end
-
+
it 'should be able to get system logs as admin' do
result = request('/system/get-logs', {
page: 1,
@@ -148,6 +148,21 @@ describe'system/disable-user-system' do
(ticket['author_staff_id']).should.equal('1')
end
+ it 'should be able to create a ticket using api' do
+ api_key = Scripts.createAPIKey('ticketCreateKey', 'TICKET_CREATE')['data']
+ request('/user/logout')
+ result = request('/ticket/create', {
+ email: 'fromapi@testemail.com',
+ name: 'Random user',
+ title: 'created by api',
+ content: 'this ticket was created using anapi key while user system is disabled',
+ departmentId: 1,
+ language: 'en',
+ apiKey: api_key
+ })
+ (result['status']).should.equal('success')
+ end
+
it 'should not disable the user system if it is already disabled 'do
request('/user/logout')
Scripts.login($staff[:email], $staff[:password], true)
@@ -205,7 +220,7 @@ describe'system/disable-user-system' do
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(53)
+ (numberOftickets.num_rows).should.equal(55)
end
it 'should not enable the user system' do
diff --git a/tests/system/get-api-keys.rb b/tests/system/get-api-keys.rb
index 518dc818..e6c62900 100644
--- a/tests/system/get-api-keys.rb
+++ b/tests/system/get-api-keys.rb
@@ -1,26 +1,25 @@
describe'system/get-api-keys' do
- request('/user/logout')
- Scripts.login($staff[:email], $staff[:password], true)
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
- it 'should get all API keys' do
- Scripts.createAPIKey('namekey1')
- Scripts.createAPIKey('namekey2')
- Scripts.createAPIKey('namekey3')
- Scripts.createAPIKey('namekey4')
- Scripts.createAPIKey('namekey5')
-
- result = request('/system/get-api-keys', {
- csrf_userid: $csrf_userid,
- csrf_token: $csrf_token,
- })
+ it 'should get all API keys' do
+ Scripts.createAPIKey('namekey1', 'REGISTRATION')
+ Scripts.createAPIKey('namekey2', 'REGISTRATION')
+ Scripts.createAPIKey('namekey3', 'REGISTRATION')
+ Scripts.createAPIKey('namekey4', 'REGISTRATION')
+ Scripts.createAPIKey('namekey5', 'REGISTRATION')
+
+ result = request('/system/get-api-keys', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ })
- (result['status']).should.equal('success')
- (result['data'][0]['name']).should.equal('namekey1')
- (result['data'][1]['name']).should.equal('namekey2')
- (result['data'][2]['name']).should.equal('namekey3')
- (result['data'][3]['name']).should.equal('namekey4')
- (result['data'][4]['name']).should.equal('namekey5')
-
- end
+ (result['status']).should.equal('success')
+ (result['data'][0]['name']).should.equal('namekey1')
+ (result['data'][1]['name']).should.equal('namekey2')
+ (result['data'][2]['name']).should.equal('namekey3')
+ (result['data'][3]['name']).should.equal('namekey4')
+ (result['data'][4]['name']).should.equal('namekey5')
+ end
end
diff --git a/tests/system/get-settings.rb b/tests/system/get-settings.rb
index 383d1207..84ac35bd 100644
--- a/tests/system/get-settings.rb
+++ b/tests/system/get-settings.rb
@@ -1,7 +1,7 @@
describe '/system/get-settings' do
it 'should return correct values' do
result = request('/system/get-settings')
-
+
(result['status']).should.equal('success')
(result['data']['language']).should.equal('en')
(result['data']['departments'][0]['name']).should.equal('Help and Support')
diff --git a/tests/ticket/edit-comment.rb b/tests/ticket/edit-comment.rb
index 89b8d662..ae1093b9 100644
--- a/tests/ticket/edit-comment.rb
+++ b/tests/ticket/edit-comment.rb
@@ -15,7 +15,7 @@ describe '/ticket/edit-comment' do
})
ticket = $database.getRow('ticket', 'ticket made by an user', 'title')
-
+
(result['status']).should.equal('success')
(ticket['content']).should.equal('content edited by the user')
end
diff --git a/tests/ticket/edit-title.rb b/tests/ticket/edit-title.rb
new file mode 100644
index 00000000..2f1a3242
--- /dev/null
+++ b/tests/ticket/edit-title.rb
@@ -0,0 +1,76 @@
+describe '/ticket/edit-title' do
+
+ request('/user/logout')
+ Scripts.login();
+ Scripts.createTicket('Valar Morghulis','content of the ticket made by an user')
+ ticket = $database.getRow('ticket', 'Valar Morghulis', 'title')
+ ticketNumber = ticket['ticket_number']
+
+ it 'should fail change title of the ticket if the title is invalid' do
+ result = request('/ticket/edit-title', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ title: '',
+ ticketNumber: ticket['ticket_number']
+ })
+
+ ticket = $database.getRow('ticket', ticketNumber, 'ticket_number')
+
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_TITLE')
+ end
+
+ it 'should change title of the ticket if the author user tries it' do
+ result = request('/ticket/edit-title', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ title: 'Valar dohaeris',
+ ticketNumber: ticket['ticket_number']
+ })
+
+ ticket = $database.getRow('ticket', ticketNumber, 'ticket_number')
+
+ (result['status']).should.equal('success')
+ (ticket['title']).should.equal('Valar dohaeris')
+ (ticket['edited_title']).should.equal('1')
+ end
+
+ it 'should change the title of the ticket if staff is logged' do
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
+
+ result = request('/ticket/edit-title', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ title: 'Valar dohaeris by Staff',
+ ticketNumber: ticket['ticket_number']
+ })
+
+ ticket = $database.getRow('ticket', ticketNumber, 'ticket_number')
+
+ (result['status']).should.equal('success')
+ (ticket['title']).should.equal('Valar dohaeris by Staff')
+ (ticket['edited_title']).should.equal('1')
+
+ end
+
+ it 'should not change the title if the user is not the author' do
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
+ Scripts.createTicket('Winterfell')
+ ticket = $database.getRow('ticket', 'Winterfell', 'title')
+
+ request('/user/logout')
+ Scripts.login()
+
+ result = request('/ticket/edit-title', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ title: 'Casterly Rock',
+ ticketNumber: ticket['ticket_number']
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('NO_PERMISSION')
+ end
+
+end
diff --git a/tests/ticket/search.rb b/tests/ticket/search.rb
new file mode 100644
index 00000000..2ae320d6
--- /dev/null
+++ b/tests/ticket/search.rb
@@ -0,0 +1,145 @@
+describe '/ticket/search' do
+ request('/user/logout')
+ Scripts.login($staff[:email], $staff[:password], true)
+
+
+ it 'should fail if the page is invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: -1
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_PAGE')
+ end
+
+ it 'should fail if the tags are invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ tags: "[1,11,111,1111,11111,111111,1111111,11111111]"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_TAG_FILTER')
+ end
+
+ it 'should fail if the closed value is invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ closed: 3
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_CLOSED_FILTER')
+ end
+
+ it 'should fail if the unreadStaff value is invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ unreadStaff: 3
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_UNREAD_STAFF_FILTER')
+ end
+
+ it 'should fail if the priority values are invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ priority: "[0,1,5,6]"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_PRIORITY_FILTER')
+ end
+
+ it 'should fail if the priority' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ priority: "[0,1,),hi]"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_PRIORITY_FILTER')
+ end
+
+ it 'should fail if the dateRange values are invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ dateRange: "[11,69,()) ]"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_DATE_RANGE_FILTER')
+ end
+
+ it 'should fail if the departments are invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ departments: "[-1,-2,99]"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_DEPARTMENT_FILTER')
+ end
+
+ it 'should fail if the authors are invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ authors: "[{id:30001, staff: 1},{id:30,staff: 3}]"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_AUTHOR_FILTER')
+
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ authors: "[{id:'delete all)', staff: 1},{id:30,staff: 3}]"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_AUTHOR_FILTER')
+ end
+
+ it 'should fail if the assigned value is invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ assigned: 3
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_ASSIGNED_FILTER')
+ end
+
+ it 'should fail if the assigned value is invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ assigned: 11113
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_ASSIGNED_FILTER')
+ end
+
+ it 'should fail if the orderBy values are invalid' do
+ result = request('/ticket/search', {
+ csrf_userid: $csrf_userid,
+ csrf_token: $csrf_token,
+ page: 1,
+ orderBy: "{value: 'closeddd', asc: 11}"
+ })
+ (result['status']).should.equal('fail')
+ (result['message']).should.equal('INVALID_ORDER_BY')
+ end
+end