diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index 162725d8..2c4ed3b9 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -8,6 +8,7 @@ import i18n from 'lib-app/i18n'; import API from 'lib-app/api-call'; import SessionStore from 'lib-app/session-store'; import MentionsParser from 'lib-app/mentions-parser'; +import history from 'lib-app/history'; import TicketEvent from 'app-components/ticket-event'; import AreYouSure from 'app-components/are-you-sure'; @@ -465,7 +466,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) { 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 index 2dd4f530..f5726f2c 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-search-tickets.js @@ -20,7 +20,7 @@ class AdminPanelSearchTickets extends React.Component { } getFilters() { - let customList = window.customTicketList[this.props.location.query.custom*1] ? window.customTicketList[this.props.location.query.custom*1] : null + let customList = (window.customTicketList && window.customTicketList[this.props.location.query.custom*1]) ? window.customTicketList[this.props.location.query.custom*1] : null return { ...customList }; diff --git a/client/src/app/main/dashboard/dashboard-edit-profile/dashboard-edit-profile-page.js b/client/src/app/main/dashboard/dashboard-edit-profile/dashboard-edit-profile-page.js index 6bf28bfb..75fbd39b 100644 --- a/client/src/app/main/dashboard/dashboard-edit-profile/dashboard-edit-profile-page.js +++ b/client/src/app/main/dashboard/dashboard-edit-profile/dashboard-edit-profile-page.js @@ -4,6 +4,7 @@ import _ from 'lodash'; import API from 'lib-app/api-call'; import i18n from 'lib-app/i18n'; +import { getCustomFieldParamName } from 'lib-core/APIUtils'; import SessionActions from 'actions/session-actions'; import AreYouSure from 'app-components/are-you-sure'; @@ -42,15 +43,6 @@ class DashboardEditProfilePage extends React.Component { return (
-
{i18n('ADDITIONAL_FIELDS')}
-
this.setState({customFieldsFrom: form})} onSubmit={this.onCustomFieldsSubmit.bind(this)}> -
- {this.state.customFields.map(this.renderCustomField.bind(this))} -
-
- {i18n('SAVE')} -
-
{i18n('EDIT_EMAIL')}
@@ -65,6 +57,23 @@ class DashboardEditProfilePage extends React.Component { {i18n('CHANGE_PASSWORD')} {this.renderMessagePass()} + {this.state.customFields.length ? this.renderCustomFields() : null} +
+ ); + } + + renderCustomFields() { + return ( +
+
{i18n('ADDITIONAL_FIELDS')}
+
this.setState({customFieldsFrom: form})} onSubmit={this.onCustomFieldsSubmit.bind(this)}> +
+ {this.state.customFields.map(this.renderCustomField.bind(this))} +
+
+ {i18n('SAVE')} +
+
); } @@ -116,9 +125,9 @@ class DashboardEditProfilePage extends React.Component { customFields.forEach(customField => { if(customField.type === 'select') { - parsedFrom[`customfield_${customField.name}`] = customField.options[form[customField.name]].name; + parsedFrom[getCustomFieldParamName(customField.name)] = customField.options[form[customField.name]].name; } else { - parsedFrom[`customfield_${customField.name}`] = form[customField.name]; + parsedFrom[getCustomFieldParamName(customField.name)] = form[customField.name]; } }); diff --git a/client/src/app/main/main-signup/main-signup-widget.js b/client/src/app/main/main-signup/main-signup-widget.js index b0a77964..bfe390fe 100644 --- a/client/src/app/main/main-signup/main-signup-widget.js +++ b/client/src/app/main/main-signup/main-signup-widget.js @@ -26,7 +26,7 @@ class MainSignUpWidget extends React.Component { this.state = { loading: false, email: null, - customFields: [] + customFields: null }; } @@ -39,6 +39,7 @@ class MainSignUpWidget extends React.Component { } render() { + if(!this.state.customFields) return null; return (
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js new file mode 100644 index 00000000..dc512fd5 --- /dev/null +++ b/client/src/data/languages/en.js @@ -0,0 +1,436 @@ +export default { + 'WELCOME': 'Welcome', + 'TICKETS': 'Tickets', + 'ARTICLES': 'Articles', + 'ACCOUNT': 'Account', + 'SUBMIT': 'Submit', + 'EMAIL': 'Email', + 'PASSWORD': 'Password', + 'REPEAT_PASSWORD': 'Repeat password', + 'LOG_IN': 'Log in', + 'SIGN_UP': 'Sign up', + 'FORGOT_PASSWORD': 'Forgot your password?', + 'RECOVER_PASSWORD': 'Recover Password', + 'SET_UP_PASSWORD': 'Set up your password', + 'RECOVER_SENT': 'An email with recover instructions has been sent.', + 'NEW_EMAIL': 'New email', + 'FULL_NAME': 'Full name', + 'OLD_PASSWORD': 'Old password', + 'NEW_PASSWORD': 'New password', + 'REPEAT_NEW_PASSWORD': 'Repeat new password', + 'BACK_LOGIN_FORM': 'Back to login form', + 'VIEW_ARTICLES': 'View Articles', + 'EDIT_PROFILE': 'Edit Profile', + 'CLOSE_SESSION': 'Close session', + 'CREATE_TICKET': 'Create Ticket', + 'TICKET_LIST': 'Ticket List', + 'SUPPORT_CENTER': 'Support Center', + 'DEPARTMENT': 'Department', + 'AUTHOR': 'Author', + 'DATE': 'Date', + 'RESPOND': 'Respond', + 'RESPOND_TICKET': 'Respond Ticket', + 'CLOSE_TICKET': 'Close ticket', + 'DELETE_TICKET': 'Delete ticket', + 'NO_ATTACHMENT': 'No file attachment', + 'STAFF': 'Staff', + 'CUSTOMER': 'Customer', + 'YES': 'Yes', + 'NO': 'No', + 'CANCEL': 'Cancel', + 'MY_ACCOUNT': 'My Account', + 'DASHBOARD': 'Dashboard', + 'USERS': 'Users', + 'SETTINGS': 'Settings', + 'STATISTICS': 'Statistics', + 'LAST_ACTIVITY': 'Last Activity', + 'MY_TICKETS': 'My Tickets', + 'NEW_TICKETS': 'New Tickets', + 'ALL_TICKETS': 'All Tickets', + 'CUSTOM_RESPONSES': 'Custom Responses', + 'CUSTOM_TAGS': 'Custom Tags', + 'LIST_USERS': 'List Users', + 'BAN_USERS': 'Ban Users', + 'LIST_ARTICLES': 'Article List', + 'STAFF_MEMBERS': 'Staff Members', + 'DEPARTMENTS': 'Departments', + 'SYSTEM_PREFERENCES': 'System Preferences', + 'ADVANCED_SETTINGS': 'Advanced Settings', + 'EMAIL_TEMPLATES': 'Email Templates', + 'FILTERS_CUSTOM_FIELDS': 'Filters and Custom Fields', + 'PRIORITY': 'Priority', + 'NUMBER': 'Number', + 'HIGH': 'High', + 'MEDIUM': 'Medium', + 'LOW': 'Low', + 'TITLE': 'Title', + 'CONTENT': 'Content', + 'SAVE': 'Save', + 'DISCARD_CHANGES': 'Discard changes', + 'DELETE': 'Delete', + 'LANGUAGE': 'Language', + 'OWNER': 'Owner', + 'OWNED': 'Owned', + 'STATUS': 'Status', + 'NONE': 'None', + 'OPENED': 'Opened', + 'CLOSED': 'Closed', + 'CLOSE': 'Close', + 'RE_OPEN': 'Re open', + 'ASSIGN_TO_ME': 'Assign to me', + 'UN_ASSIGN': 'Unassign', + 'VIEW_TICKET': 'View Ticket', + 'VIEW_TICKET_DESCRIPTION': 'Check the status of your ticket using your ticket number and email.', + 'SELECT_CUSTOM_RESPONSE': 'Select a custom response...', + 'WARNING': 'Warning', + 'INFO': 'Information', + 'ALL_DEPARTMENTS': 'All Departments', + 'EMAIL_BANNED': 'Email banned', + 'UN_BAN': 'Disable ban', + 'BAN_NEW_EMAIL': 'Ban new email', + 'BAN_EMAIL': 'Ban email', + 'EDIT_EMAIL': 'Edit email', + 'EDIT_PASSWORD': 'Edit password', + '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...', + 'USER_VIEW_TITLE': 'User #{userId}', + 'EDIT_TOPIC': 'Edit Topic', + 'ADD_TOPIC': 'Add Topic', + 'ICON': 'Icon', + 'COLOR': 'Color', + 'ADD_NEW_ARTICLE': 'Add new article', + 'ADD_ARTICLE': 'Add article', + 'LAST_EDITED_IN': 'Last edited in {date}', + 'EDIT': 'Edit', + 'ADD_CUSTOM_TAG': 'Add custom tag', + 'EDIT_CUSTOM_TAG': 'Edit custom tag', + 'NO_RESULTS': 'No results', + 'DELETE_AND_BAN': 'Delete and ban', + 'STAFF_LEVEL': 'Staff Level', + 'ASSIGNED': 'Assigned', + 'ASSIGNED_TICKETS': '{tickets} assigned tickets', + 'CLOSED_TICKETS': '{tickets} closed tickets', + 'LAST_LOGIN': 'Last login', + 'ADD_NEW_STAFF': 'Add new staff', + 'ADD_STAFF': 'Add staff', + 'LEVEL': 'Level', + 'LEVEL_1': 'Level 1 (Tickets)', + 'LEVEL_2': 'Level 2 (Tickets + Articles)', + 'LEVEL_3': 'Level 3 (Tickets + Articles + Staff)', + 'LEVEL_1_DESCRIPTION': 'can only respond tickets and manage users.', + 'LEVEL_2_DESCRIPTION': 'can do every Level 1 does, can create or edit articles and it can create custom responses.', + 'LEVEL_3_DESCRIPTION': 'can do every Level 2 does, can create or edit staff members and can manage the whole system.', + 'UPDATE_EMAIL': 'Update email', + 'UPDATE_PASSWORD': 'Update password', + 'UPDATE_LEVEL': 'Update level', + 'UPDATE_DEPARTMENTS': 'Update departments', + 'EDIT_STAFF': 'Edit staff member', + 'ADD_DEPARTMENT': 'Add department', + 'UPDATE_DEPARTMENT': 'Update department', + 'TRANSFER_TICKETS_TO': 'Transfer tickets to', + 'COMMENTS': 'Comments', + 'DELETE_STAFF_MEMBER': 'Delete staff member', + 'MAINTENANCE_MODE': 'Maintenance mode', + 'MAINTENANCE_MODE_INFO': 'It will temporary disable the system for regular users.', + 'RECOVER_DEFAULT': 'Recover default', + 'SUPPORT_CENTER_URL': 'Support Center URL', + 'SUPPORT_CENTER_TITLE': 'Support Center Title', + 'SUPPORT_CENTER_LAYOUT': 'Support Center Layout', + 'DEFAULT_TIMEZONE': 'Default Timezone (GMT)', + 'NOREPLY_EMAIL': 'Noreply Email', + 'SMTP_USER': 'SMTP User', + 'SMTP_SERVER': 'SMTP Server', + 'SMTP_PASSWORD': 'SMTP Password', + 'IMAP_USER': 'IMAP User', + 'IMAP_SERVER': 'IMAP Server', + 'IMAP_PASSWORD': 'IMAP Password', + 'IMAP_TOKEN': 'IMAP Token', + 'IMAP_TOKEN_DESCRIPTION': 'Use this token to authenticate the polling request.', + 'PORT': 'Port', + 'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Public Key', + 'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Private Key', + 'ALLOW_FILE_ATTACHMENTS': 'Allow file attachments', + 'MAX_SIZE_MB': 'Max Size (MB)', + 'UPDATE_SETTINGS': 'Update settings', + 'DEFAULT_LANGUAGE': 'Default Language', + 'SUPPORTED_LANGUAGES': 'Supported Languages', + 'SUPPORTED_LANGUAGES_INFO': 'Supported languages are the languages that tickets can be written in.', + 'ALLOWED_LANGUAGES': 'Allowed Languages', + 'ALLOWED_LANGUAGES_INFO': 'Allowed languages are the languages that can be used by an user.', + 'SETTINGS_UPDATED': 'Settings have been updated', + 'ON': 'On', + 'OFF': 'Off', + 'BOXED': 'Boxed', + 'FULL_WIDTH': 'Full width', + 'LOAD_MORE': 'Load More', + 'MY_NOTIFICATIONS': 'My notifications', + 'ALL_NOTIFICATIONS': 'All notifications', + 'VERIFY_SUCCESS': 'User verified', + 'VERIFY_FAILED': 'Could not verify', + 'ENABLE_USER_SYSTEM': 'Use user system for customers', + 'ENABLE_USER_REGISTRATION': 'Enable user registration', + 'INCLUDE_USERS_VIA_CSV': 'Include users via CSV file', + 'BACKUP_DATABASE': 'Backup database', + 'DELETE_ALL_USERS': 'Delete all users', + 'PLEASE_CONFIRM_PASSWORD': 'Please confirm your password to make these changes', + 'REGISTRATION_API_KEYS': 'Registration API keys', + 'NAME_OF_KEY': 'Name of key', + 'KEY': 'Key', + 'ADD_API_KEY': 'Add API Key', + 'NO_KEY_SELECTED': 'No Key selected', + 'CHECK_TICKET': 'Check Ticket', + 'ACTIVITY': 'Activity', + 'HOME': 'Home', + 'TICKET_NUMBER': 'Ticket number', + 'NEXT': 'Next', + 'SUBJECT': 'Subject', + 'SEND_EMAIL_ON_NEW_TICKET': 'Send email on new ticket', + 'STAFF_UPDATED': 'Staff member has been updated', + 'UPDATE': 'Update', + 'NEVER': 'Never', + 'HIMSELF': 'himself', + 'ADD_USER': 'Add user', + 'INVITE_USER': 'Invite user', + 'INVITE_STAFF': 'Invite staff', + 'UPLOAD_FILE': 'Upload file', + 'PRIVATE': 'Private', + 'ENABLE_USER': 'Enable User', + 'DISABLE_USER': 'Disable User', + 'SHOW_CLOSED_TICKETS': 'Show Closed Tickets', + 'IMAGE_HEADER_URL': 'Image header URL', + 'IMAGE_HEADER_DESCRIPTION': 'Image that will be used as header of the email', + 'EMAIL_SETTINGS': 'Email Settings', + 'ADDITIONAL_FIELDS': 'Edit additonal fields', + 'NEW_CUSTOM_FIELD': 'New Custom field', + 'TYPE': 'Type', + 'SELECT_INPUT': 'Select input', + 'TEXT_INPUT': 'Text input', + 'OPTION': 'Option {index}', + 'OPTIONS': 'Options', + 'FIELD_DESCRIPTION': 'Field description (Optional)', + 'DESCRIPTION_ADD_CUSTOM_TAG': 'here you can add a new custom tag', + 'DESCRIPTION_EDIT_CUSTOM_TAG': 'here you can edit a custom tag', + 'CUSTOM_FIELDS': 'Custom fields', + + 'CHART_CREATE_TICKET': 'Tickets created', + 'CHART_CLOSE': 'Tickets closed', + 'CHART_SIGNUP': 'Signups', + 'CHART_COMMENT': 'Replies', + 'CHART_ASSIGN': 'Assigned', + + //ACTIVITIES + 'ACTIVITY_COMMENT': 'commented ticket', + 'ACTIVITY_ASSIGN': 'assigned ticket', + 'ACTIVITY_UN_ASSIGN': 'unassigned ticket', + 'ACTIVITY_CLOSE': 'closed ticket', + 'ACTIVITY_CREATE_TICKET': 'created ticket', + 'ACTIVITY_RE_OPEN': 'reopened ticket', + 'ACTIVITY_DEPARTMENT_CHANGED': 'changed department of ticket', + 'ACTIVITY_PRIORITY_CHANGED': 'changed priority of ticket', + 'ACTIVITY_EDIT_COMMENT': 'edited a comment of ticket', + + 'ACTIVITY_EDIT_SETTINGS': 'edited settings', + 'ACTIVITY_SIGNUP': 'signed up', + 'ACTIVITY_INVITE': 'invited user', + 'ACTIVITY_ADD_TOPIC': 'added topic', + 'ACTIVITY_ADD_ARTICLE': 'added article', + 'ACTIVITY_DELETE_TOPIC': 'deleted topic', + 'ACTIVITY_DELETE_ARTICLE': 'deleted article', + 'ACTIVITY_EDIT_ARTICLE': 'edited article', + 'ACTIVITY_ADD_STAFF': 'added staff', + 'ACTIVITY_ADD_DEPARTMENT': 'added department', + 'ACTIVITY_DELETE_DEPARTMENT': 'deleted department', + 'ACTIVITY_EDIT_DEPARTMENT': 'edited department', + 'ACTIVITY_ADD_CUSTOM_RESPONSE': 'added custom response', + 'ACTIVITY_DELETE_CUSTOM_RESPONSE': 'deleted custom response', + 'ACTIVITY_EDIT_CUSTOM_RESPONSE': 'edited custom response', + 'ACTIVITY_BAN_USER': 'banned user', + 'ACTIVITY_DELETE_USER': 'deleted user', + 'ACTIVITY_UN_BAN_USER': 'unbanned user', + + 'SERVER_REQUIREMENTS': 'Server requirements', + 'DATABASE_CONFIGURATION': 'Database configuration', + 'ADMIN_SETUP': 'Admin setup', + 'COMPLETED': 'Completed', + 'INSTALL_HEADER_TITLE': 'OpenSupports Installation Wizard', + 'INSTALL_HEADER_DESCRIPTION': 'This wizard will help you to configure and install OpenSupports on your website', + 'SELECT_LANGUAGE': 'Select language', + 'REQUIREMENT': 'Requirement', + 'VALUE': 'Value', + 'REFRESH': 'Refresh', + 'USER_SYSTEM': 'User System', + 'PREVIOUS': 'Previous', + 'DATABASE_HOST': 'MySQL server', + 'DATABASE_PORT': 'MySQL server port', + 'DATABASE_NAME': 'MySQL database name', + 'DATABASE_USER': 'MySQL user', + 'DATABASE_PASSWORD': 'MySQL password', + 'ADMIN_NAME': 'Admin account name', + 'ADMIN_EMAIL': 'Admin account email', + 'ADMIN_PASSWORD': 'Admin account password', + 'ADMIN_PASSWORD_DESCRIPTION': 'Please remember this password. It is needed for accessing the admin panel. You can change it later.', + 'INSTALLATION_COMPLETED': 'Installation completed.', + 'INSTALLATION_COMPLETED_DESCRIPTION': 'The installation of OpenSupports is completed. Redirecting to admin panel...', + + 'STEP_TITLE': 'Step {current} of {total} - {title}', + 'STEP_1_DESCRIPTION': 'Select your preferred language for the installation wizard.', + 'STEP_2_DESCRIPTION': 'Here are listed the requirements for running OpenSupports. Please make sure that all requirements are satisfied.', + 'STEP_3_DESCRIPTION': 'Please fill the MySQL database configuration.', + 'STEP_4_DESCRIPTION': 'Please select your user system preferences.', + 'STEP_5_DESCRIPTION': 'Please fill your general system preferences.', + 'STEP_6_DESCRIPTION': 'Please configure the administrator account.', + 'STEP_7_DESCRIPTION': 'Installation is completed.', + + //VIEW DESCRIPTIONS + 'CREATE_TICKET_DESCRIPTION': 'This is a form for creating tickets. Fill the form and send us your issues/doubts/suggestions. Our support system will answer it as soon as possible.', + '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 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', + 'CUSTOM_TAGS_DESCRIPTION': 'Here you can view manage the custom tags for tickets to identify them better', + '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.', + 'USER_VIEW_DESCRIPTION': 'Here you can find all the information about an user and all the tickets sent by the user. You can also delete or ban it.', + 'DELETE_USER_DESCRIPTION': 'The user will not be able to log in aging and all its tickets will be erased. Also, the email can not be used any more.', + 'DELETE_TOPIC_DESCRIPTION': 'By deleting the topic, all articles on it will be erased.', + 'EDIT_TOPIC_DESCRIPTION': 'Here you can change the name, the icon and the icon color of the topic.', + '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 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.', + 'MY_ACCOUNT_DESCRIPTION': 'Here you can edit information about you.', + 'DEPARTMENTS_DESCRIPTION': 'A department is a group where the tickets can go. They are used to categorize the tickets. You can assign them to other staff members.', + 'MAINTENANCE_MODE_DESCRIPTION': 'The support system is in maintenance mode, thus unavailable at the moment. We will come back as soon as possible.', + 'EMAIL_TEMPLATES_DESCRIPTION': 'Here you can edit the templates of the emails that will be sent to users. Remember that the double brackets curly braces indicate a variable value. For example, \'name\' represents the user\'s name.', + '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.', + 'ADVANCED_SETTINGS_DESCRIPTION': 'Here you can change the advanced settings of your system. Please be careful, the changes you make can not be reversed.', + 'USER_SYSTEM_DISABLED': 'User system has been disabled', + 'USER_SYSTEM_ENABLED': 'User system has been enabled', + 'REGISTRATION_DISABLED': 'Registration has been disabled', + 'REGISTRATION_ENABLED': 'Registration has been enabled', + 'ADD_API_KEY_DESCRIPTION': 'Insert the name and a registration api key will be generated.', + 'SIGN_UP_VIEW_DESCRIPTION': 'Here you can create an account for our support center. It is required to send tickets and see documentation.', + 'EDIT_PROFILE_VIEW_DESCRIPTION': 'Here you can edit your user preferences.', + 'ENABLE_USER_SYSTEM_DESCRIPTION': 'Enable/disable the use of an user system. If you disable it, all users will be deleted but the tickets will be kept. If you enable it, the users of existent tickets will be created.', + 'CSV_DESCRIPTION': 'The CSV file must have 3 columns: email, password, name. There is no limit in row count. It will be created one user per row in the file.', + 'SMTP_SERVER_DESCRIPTION': 'The configuration of the SMTP server allows the application to send mails. If you do not configure it, no emails will be sent by OpenSupports.', + 'IMAP_SERVER_DESCRIPTION': 'The configuration of the IMAP server allows the application to create tickets from the emails sent to a mailbox.', + 'ENABLE_USER_DESCRIPTION': 'This action allows the user to sign in and create tickets.', + 'DISABLE_USER_DESCRIPTION': 'User will be disabled and will not be able to sign in and create tickets.', + 'PRIVATE_RESPONSE_DESCRIPTION': 'This response will only be seen by staff members', + 'PRIVATE_TOPIC_DESCRIPTION': 'This topic will only be seen by staff members', + 'PRIVATE_DEPARTMENT_DESCRIPTION': 'This department will only be seen by staff members', + 'EMAIL_SETTINGS_DESCRIPTION': 'Here you can edit the settings for receiving and sending email to your customers.', + 'IMAP_POLLING_DESCRIPTION': 'Inbox checking will not be done automatically by OpenSupports. You have to make POST requests periodically to this url to process the emails: {url}', + 'NEW_CUSTOM_FIELD_DESCRIPTION': 'Here you can create a custom field for an user, it can be a blank text box or a fixed set of options.', + 'CUSTOM_FIELDS_DESCRIPTION': 'Custom fields are defined additional fields the users are able to fill to provide more information about them.', + 'INVITE_USER_VIEW_DESCRIPTION': 'Here you can invite an user to join our support system, he will just need to provide his password to create a new user.', + 'INVITE_STAFF_DESCRIPTION': 'Here you can invite staff members to your teams.', + + //ERRORS + 'EMAIL_OR_PASSWORD': 'Email or password invalid', + 'EMAIL_NOT_EXIST': 'Email does not exist', + 'ERROR_EMPTY': 'Invalid value', + 'ERROR_PASSWORD': 'Invalid password', + 'ERROR_NAME': 'Invalid name', + 'ERROR_TITLE': 'Invalid title', + 'ERROR_EMAIL': 'Invalid email', + 'ERROR_CONTENT_SHORT': 'Content too short', + 'PASSWORD_NOT_MATCH': 'Password does not match', + 'INVALID_RECOVER': 'Invalid recover data', + 'TICKET_SENT_ERROR': 'An error occurred while trying to create the ticket.', + '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', + '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.', + 'ERROR_BANNING_EMAIL': 'An error occurred while trying to ban the email.', + 'ERROR_RETRIEVING_ARTICLES': 'An error occurred while trying to retrieve articles.', + 'ERROR_LIST': 'Select at least one', + 'ERROR_URL': 'Invalid URL', + 'UNVERIFIED_EMAIL': 'Email is not verified yet', + 'ERROR_UPDATING_SETTINGS': 'An error occurred while trying to update settings', + 'INVALID_EMAIL_OR_TICKET_NUMBER': 'Invalid email or ticket number', + 'INVALID_FILE': 'Invalid file', + 'ERRORS_FOUND': 'Errors found', + 'ERROR_IMAGE_SIZE': 'No image can have a size greater than {size} MB', + 'USER_DISABLED': 'This account is disabled.', + 'INVALID_SYNTAX': 'Invalid syntax.', + 'DEPARTMENT_PRIVATE_TICKETS': 'This department has tickets created by non-staff and it can not be private', + 'CURRENTLY_UNAVAILABLE': 'Currently unavailable', + + //MESSAGES + 'SIGNUP_SUCCESS': 'You have registered successfully in our support system.', + 'INVITE_USER_SUCCESS': 'You have invited a new user successfully in our support system', + 'TICKET_SENT': 'Ticket has been created successfully.', + 'VALID_RECOVER': 'Password recovered successfully', + 'EMAIL_EXISTS': 'Email already exists', + 'ARE_YOU_SURE': 'Confirm action', + 'EMAIL_WILL_CHANGE': 'The current email will be changed', + 'PASSWORD_WILL_CHANGE': 'The current password will be changed', + 'EMAIL_CHANGED': 'Email has been changed successfully', + 'PASSWORD_CHANGED': 'Password has been changed successfully', + 'OLD_PASSWORD_INCORRECT': 'Old password is incorrect', + 'WILL_LOSE_CHANGES': 'You haven\'t save. Your changes will be lost.', + 'WILL_DELETE_CUSTOM_RESPONSE': 'The custom response will be deleted.', + 'WILL_DELETE_DEPARTMENT': 'The department will be deleted. All the tickets will be transfer to the department selected.', + 'NO_STAFF_ASSIGNED': 'No staff member is assigned to this department.', + 'NO_DEPARTMENT_ASSIGNED': 'No ticket department is assigned you.', + 'LEVEL_UPDATED': 'Level has been updated successfully.', + 'DEPARTMENTS_UPDATED': 'Departments have been updated successfully.', + 'FAILED_EDIT_STAFF': 'An error occurred while trying to edit staff member.', + 'EMAIL_BANNED_SUCCESSFULLY': 'Email has been banned successfully', + 'WILL_DELETE_STAFF': 'This staff member will be deleted and all its tickets will be unassigned.', + 'WILL_RECOVER_EMAIL_TEMPLATE': 'This email template will be recover to it\'s default value on this language.', + 'SUCCESS_IMPORTING_CSV_DESCRIPTION': 'CSV File has been imported successfully', + 'SUCCESS_DELETING_ALL_USERS': 'Users have beend deleted successfully', + 'SUCCESSFUL_CONNECTION': 'Successful connection', + 'UNSUCCESSFUL_CONNECTION': 'Unsuccessful connection', + '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?', + + 'COMMENT_EDITED': '(comment edited)', + 'LAST_7_DAYS': 'Last 7 days', + 'LAST_30_DAYS': 'Last 30 days', + 'LAST_90_DAYS': 'Last 90 days', + 'LAST_365_DAYS': 'Last 365 days', + + 'TEST': 'Test', + 'ACTIVITY_COMMENT_THIS': 'commented this ticket', + 'ACTIVITY_ASSIGN_THIS': 'assigned this ticket to', + 'ACTIVITY_UN_ASSIGN_THIS': 'unassigned this ticket to', + 'ACTIVITY_CLOSE_THIS': 'closed this ticket', + 'ACTIVITY_CREATE_TICKET_THIS': 'created this ticket', + 'ACTIVITY_RE_OPEN_THIS': 'reopened this ticket', + 'ACTIVITY_DEPARTMENT_CHANGED_THIS': 'changed department of this ticket to ', + 'ACTIVITY_PRIORITY_CHANGED_THIS': 'changed priority of this ticket to', + 'DATE_PREFIX': 'on', + 'LEFT_EMPTY_DATABASE': 'Leave empty for automatic database creation', + 'DEFAULT_PORT': 'Leave empty for 3306 as default', + 'REMEMBER_ME': 'Remember me', + 'EMAIL_LOWERCASE': 'email', + 'PASSWORD_LOWERCASE': 'password', + 'TEST_SMTP_CONNECTION': 'Test SMTP connection', + 'SERVER_ERROR': 'Can not connect to server.', + 'EMAIL_SERVER_ADDRESS': 'Email server address', + 'EMAIL_SERVER_ADDRESS_DESCRIPTION': 'Address where mails will be received and sent' +}; diff --git a/client/src/lib-core/APIUtils.js b/client/src/lib-core/APIUtils.js index c9c544f5..d8ca183e 100644 --- a/client/src/lib-core/APIUtils.js +++ b/client/src/lib-core/APIUtils.js @@ -44,4 +44,8 @@ const APIUtils = { } }; +export const getCustomFieldParamName = function (customFieldName) { + return `customfield_${customFieldName}`.replace(/ /g,'_'); +} + export default APIUtils; 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/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/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 2e56b685..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'; @@ -326,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/Controller.php b/server/libs/Controller.php index e8c61ff2..04711b5f 100755 --- a/server/libs/Controller.php +++ b/server/libs/Controller.php @@ -152,9 +152,8 @@ abstract class Controller { public static function getCustomFieldValues() { $customFields = Customfield::getAll(); $customFieldValues = new DataStoreList(); - foreach($customFields as $customField) { - $value = Controller::request('customfield_' . $customField->name); + $value = Controller::request('customfield_' . str_replace(' ', '_', $customField->name)); if($value !== null) { $customFieldValue = new Customfieldvalue(); $customFieldValue->setProperties([ @@ -183,7 +182,6 @@ abstract class Controller { $customFieldValues->add($customFieldValue); } } - return $customFieldValues; } } 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/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/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/tests/init.rb b/tests/init.rb index 8c6cb9f4..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' 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/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 7f3c63e1..a9279051 100644 --- a/tests/system/disable-user-system.rb +++ b/tests/system/disable-user-system.rb @@ -17,7 +17,7 @@ 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(52) @@ -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) 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