Ivan - Fix AreYouSure design, fix stats, rename get-api-keys, use allow-attachment, fix login verificationToken, fix deletion, fix ticket view permission, fix last events when empty, fix configuration in frontend, fix system preferences and my account
This commit is contained in:
parent
3d27415041
commit
5126b40538
|
@ -1,9 +1,9 @@
|
|||
|
||||
export default {
|
||||
openModal(content) {
|
||||
openModal(config) {
|
||||
return {
|
||||
type: 'OPEN_MODAL',
|
||||
payload: content
|
||||
payload: config
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ class ActivityRow extends React.Component {
|
|||
</Link>
|
||||
</span>
|
||||
<span className="activity-row__message"> {i18n('ACTIVITY_' + this.props.type)} </span>
|
||||
{_.includes(ticketRelatedTypes, this.props.type) ? this.renderTicketNumber() : null}
|
||||
{_.includes(ticketRelatedTypes, this.props.type) ? this.renderTicketNumber() : this.props.to}
|
||||
<span className="separator" />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
&__ticket-link {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 15px;
|
||||
}
|
||||
.separator {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import React from 'react';
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
|
||||
import Button from 'core-components/button';
|
||||
import Input from 'core-components/input';
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
import Icon from 'core-components/icon';
|
||||
|
||||
|
||||
class AreYouSure extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -26,7 +29,8 @@ class AreYouSure extends React.Component {
|
|||
|
||||
static openModal(description, onYes, type) {
|
||||
ModalContainer.openModal(
|
||||
<AreYouSure description={description} onYes={onYes} type={type}/>
|
||||
<AreYouSure description={description} onYes={onYes} type={type}/>,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -40,21 +44,25 @@ class AreYouSure extends React.Component {
|
|||
<div className="are-you-sure__header" id="are-you-sure__header">
|
||||
{i18n('ARE_YOU_SURE')}
|
||||
</div>
|
||||
<span className="are-you-sure__close-icon" onClick={this.onNo.bind(this)}>
|
||||
<Icon name="times" size="2x"/>
|
||||
</span>
|
||||
<div className="are-you-sure__description" id="are-you-sure__description">
|
||||
{this.props.description || (this.props.type === 'secure' && i18n('PLEASE_CONFIRM_PASSWORD'))}
|
||||
</div>
|
||||
{(this.props.type === 'secure') ? this.renderPassword() : null}
|
||||
<span className="separator" />
|
||||
<div className="are-you-sure__buttons">
|
||||
<div className="are-you-sure__yes-button">
|
||||
<Button type="secondary" size="small" onClick={this.onYes.bind(this)} ref="yesButton" tabIndex="2">
|
||||
{i18n('YES')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="are-you-sure__no-button">
|
||||
<Button type="link" size="auto" onClick={this.onNo.bind(this)} tabIndex="2">
|
||||
{i18n('CANCEL')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="are-you-sure__yes-button">
|
||||
<Button type="secondary" size="small" onClick={this.onYes.bind(this)} ref="yesButton" tabIndex="2">
|
||||
{i18n('YES')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -62,7 +70,7 @@ class AreYouSure extends React.Component {
|
|||
|
||||
renderPassword() {
|
||||
return (
|
||||
<Input className="are-you-sure__password" password placeholder="password" name="password" value={this.state.password} onChange={this.onPasswordChange.bind(this)} onKeyDown={this.onInputKeyDown.bind(this)}/>
|
||||
<Input className="are-you-sure__password" password placeholder="password" name="password" ref="password" size="medium" value={this.state.password} onChange={this.onPasswordChange.bind(this)} onKeyDown={this.onInputKeyDown.bind(this)}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -79,7 +87,11 @@ class AreYouSure extends React.Component {
|
|||
}
|
||||
|
||||
onYes() {
|
||||
if (this.props.type === 'default' || this.state.password){
|
||||
if (this.props.type === 'secure' && !this.state.password) {
|
||||
this.refs.password.focus()
|
||||
}
|
||||
|
||||
if (this.props.type === 'default' || this.state.password) {
|
||||
this.closeModal();
|
||||
|
||||
if (this.props.onYes) {
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
@import "../scss/vars";
|
||||
|
||||
.are-you-sure {
|
||||
width: 400px;
|
||||
text-align: center;
|
||||
width: 800px;
|
||||
text-align: left;
|
||||
|
||||
&__header {
|
||||
color: $primary-red;
|
||||
font-size: $font-size--xl;
|
||||
background-color: $secondary-blue;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
color: white;
|
||||
font-size: $font-size--lg;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
|
||||
margin-bottom: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
&__description {
|
||||
color: $dark-grey;
|
||||
font-size: $font-size--md;
|
||||
margin-bottom: 50px;
|
||||
padding: 14px 5% 0;
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
margin: 0 auto;
|
||||
margin-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&__yes-button,
|
||||
|
@ -30,7 +35,25 @@
|
|||
|
||||
&__password {
|
||||
margin: 0 auto;
|
||||
margin-top: -30px;
|
||||
margin-bottom: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
&__close-icon {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.separator {
|
||||
width: 90%;
|
||||
margin: 30px auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.are-you-sure {
|
||||
width: auto;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import keyCode from 'keycode';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import store from 'app/store';
|
||||
import ModalActions from 'actions/modal-actions';
|
||||
|
@ -8,11 +9,12 @@ import Modal from 'core-components/modal';
|
|||
|
||||
class ModalContainer extends React.Component {
|
||||
|
||||
static openModal(content) {
|
||||
static openModal(content, noPadding) {
|
||||
store.dispatch(
|
||||
ModalActions.openModal(
|
||||
content
|
||||
)
|
||||
ModalActions.openModal({
|
||||
content,
|
||||
noPadding
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -48,7 +50,7 @@ class ModalContainer extends React.Component {
|
|||
|
||||
renderModal() {
|
||||
return (
|
||||
<Modal content={this.props.modal.content} />
|
||||
<Modal content={this.props.modal.content} noPadding={this.props.modal.noPadding}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ class PeopleList extends React.Component {
|
|||
name: React.PropTypes.node,
|
||||
assignedTickets: React.PropTypes.number,
|
||||
closedTickets: React.PropTypes.number,
|
||||
lastLogin: React.PropTypes.number
|
||||
lastLogin: React.PropTypes.oneOfType([React.PropTypes.number, React.PropTypes.string])
|
||||
})),
|
||||
pageSize: React.PropTypes.number,
|
||||
page: React.PropTypes.number,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import RichTextEditor from 'react-rte-browserify';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import API from 'lib-app/api-call';
|
||||
|
@ -190,7 +191,7 @@ class TicketViewer extends React.Component {
|
|||
<div className="ticket-viewer__response-field row">
|
||||
<Form {...this.getCommentFormProps()}>
|
||||
<FormField name="content" validation="TEXT_AREA" required field="textarea" />
|
||||
<FormField name="file" field="file"/>
|
||||
{(this.props.allowAttachments) ? <FormField name="file" field="file"/> : null}
|
||||
<SubmitButton>{i18n('RESPOND_TICKET')}</SubmitButton>
|
||||
</Form>
|
||||
</div>
|
||||
|
@ -333,7 +334,9 @@ class TicketViewer extends React.Component {
|
|||
onCommentSuccess() {
|
||||
this.setState({
|
||||
loading: false,
|
||||
commentError: false
|
||||
commentValue: RichTextEditor.createEmptyValue(),
|
||||
commentError: false,
|
||||
commentEdited: false
|
||||
});
|
||||
|
||||
this.onTicketModification();
|
||||
|
@ -353,4 +356,8 @@ class TicketViewer extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default TicketViewer;
|
||||
export default connect((store) => {
|
||||
return {
|
||||
allowAttachments: store.config['allow-attachments']
|
||||
};
|
||||
})(TicketViewer);
|
||||
|
|
|
@ -23,11 +23,11 @@ class AdminPanelMyAccount extends React.Component {
|
|||
getEditorProps() {
|
||||
return {
|
||||
myAccount: true,
|
||||
staffId: this.props.userId,
|
||||
staffId: this.props.userId * 1,
|
||||
name: this.props.userName,
|
||||
email: this.props.userEmail,
|
||||
profilePic: this.props.userProfilePic,
|
||||
level: this.props.userLevel,
|
||||
level: this.props.userLevel * 1,
|
||||
departments: this.props.userDepartments,
|
||||
onChange: () => this.props.dispatch(SessionActions.getUserData(null, null, true))
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@ class AdminPanelStats extends React.Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div class="admin-panel-stats">
|
||||
<div className="admin-panel-stats">
|
||||
<Header title={i18n('STATISTICS')} description={i18n('STATISTICS_DESCRIPTION')}/>
|
||||
<Stats type="general"/>
|
||||
</div>
|
||||
|
|
|
@ -213,15 +213,15 @@ class AdminPanelSystemPreferences extends React.Component {
|
|||
'reCaptchaPrivate': result.data.reCaptchaPrivate,
|
||||
'url': result.data['url'],
|
||||
'title': result.data['title'],
|
||||
'layout': result.data['layout'] == 'full-width' ? 1 : 0,
|
||||
'layout': (result.data['layout'] == 'full-width') ? 1 : 0,
|
||||
'time-zone': result.data['time-zone'],
|
||||
'no-reply-email': result.data['no-reply-email'],
|
||||
'smtp-host': result.data['smtp-host'],
|
||||
'smtp-port': result.data['smtp-port'],
|
||||
'smtp-user': result.data['smtp-user'],
|
||||
'smtp-pass': '',
|
||||
'maintenance-mode': result.data['maintenance-mode'],
|
||||
'allow-attachments': result.data['allow-attachments'],
|
||||
'maintenance-mode': !!(result.data['maintenance-mode'] * 1),
|
||||
'allow-attachments': !!(result.data['allow-attachments'] * 1),
|
||||
'max-size': result.data['max-size'],
|
||||
'allowedLanguages': result.data.allowedLanguages.map(lang => (_.indexOf(languageKeys, lang))),
|
||||
'supportedLanguages': result.data.supportedLanguages.map(lang => (_.indexOf(languageKeys, lang)))
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
&__update-name-button {
|
||||
float: left;
|
||||
min-width: 156px;
|
||||
}
|
||||
|
||||
&__optional-buttons {
|
||||
|
|
|
@ -68,9 +68,9 @@ class AdminPanelStaffMembers extends React.Component {
|
|||
if(!this.state.selectedDepartment) {
|
||||
staffList = this.state.staffList;
|
||||
} else {
|
||||
staffList = _.filter(this.state.staffList, (o) => {
|
||||
return _.findIndex(o.departments, {id: this.state.selectedDepartment}) !== -1;
|
||||
})
|
||||
staffList = _.filter(this.state.staffList, (staff) => {
|
||||
return _.findIndex(staff.departments, {id: this.state.selectedDepartment}) !== -1;
|
||||
});
|
||||
}
|
||||
|
||||
return staffList.map(staff => {
|
||||
|
|
|
@ -31,6 +31,10 @@ class StaffEditor extends React.Component {
|
|||
onDelete: React.PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
tickets: []
|
||||
};
|
||||
|
||||
state = {
|
||||
email: this.props.email,
|
||||
level: this.props.level - 1,
|
||||
|
|
|
@ -151,8 +151,8 @@ class AdminPanelListUsers extends React.Component {
|
|||
|
||||
onUsersRetrieved(result) {
|
||||
this.setState({
|
||||
page: result.data.page,
|
||||
pages: result.data.pages,
|
||||
page: result.data.page * 1,
|
||||
pages: result.data.pages * 1,
|
||||
users: result.data.users,
|
||||
orderBy: result.data.orderBy,
|
||||
desc: (result.data.desc === '1'),
|
||||
|
|
|
@ -153,9 +153,7 @@ let DemoPage = React.createClass({
|
|||
title: 'ModalTrigger',
|
||||
render: (
|
||||
<Button onClick={function () {
|
||||
ModalContainer.openModal(
|
||||
<AreYouSure description="I confirm I want to perform this action." onYes={()=> {alert('yes');}} />
|
||||
);
|
||||
AreYouSure.openModal('I confirm I want to perform this action.', ()=> {alert('yes');}, 'secure')
|
||||
}}>
|
||||
Open Modal
|
||||
</Button>
|
||||
|
|
|
@ -3,7 +3,6 @@ import React from 'react';
|
|||
import API from 'lib-app/api-call';
|
||||
import i18n from 'lib-app/i18n';
|
||||
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
import AreYouSure from 'app-components/are-you-sure';
|
||||
|
||||
import Header from 'core-components/header';
|
||||
|
@ -64,11 +63,11 @@ class DashboardEditProfilePage extends React.Component {
|
|||
}
|
||||
}
|
||||
onSubmitEditEmail(formState) {
|
||||
ModalContainer.openModal(<AreYouSure onYes={this.callEditEmailAPI.bind(this, formState)}/>);
|
||||
AreYouSure.openModal(i18n('EMAIL_WILL_CHANGE'), this.callEditEmailAPI.bind(this, formState));
|
||||
}
|
||||
|
||||
onSubmitEditPassword(formState) {
|
||||
ModalContainer.openModal(<AreYouSure onYes={this.callEditPassAPI.bind(this, formState)}/>);
|
||||
AreYouSure.openModal(i18n('PASSWORD_WILL_CHANGE'), this.callEditPassAPI.bind(this, formState));
|
||||
}
|
||||
|
||||
callEditEmailAPI(formState){
|
||||
|
|
|
@ -32,7 +32,7 @@ class MainLayoutHeader extends React.Component {
|
|||
result = (
|
||||
<div className="main-layout-header__login-links">
|
||||
<Button type="clean" route={{to:'/'}}>{i18n('LOG_IN')}</Button>
|
||||
{(this.props.config['registration']) ? <Button type="clean" route={{to:'/signup'}}>{i18n('SIGN_UP')}</Button> : null}
|
||||
{(!!(this.props.config['registration'] * 1)) ? <Button type="clean" route={{to:'/signup'}}>{i18n('SIGN_UP')}</Button> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import {Motion, spring} from 'react-motion';
|
||||
|
||||
class Modal extends React.Component {
|
||||
static propTypes = {
|
||||
content: React.PropTypes.node
|
||||
content: React.PropTypes.node,
|
||||
noPadding: React.PropTypes.bool
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -30,13 +32,22 @@ class Modal extends React.Component {
|
|||
|
||||
renderModal(animation) {
|
||||
return (
|
||||
<div className="modal" style={{opacity: animation.fade}}>
|
||||
<div className={this.getClass()} style={{opacity: animation.fade}}>
|
||||
<div className="modal__content" style={{transform: 'scale(' + animation.scale + ')'}}>
|
||||
{this.props.content}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
getClass() {
|
||||
let classes = {
|
||||
'modal': true,
|
||||
'modal_no-padding': this.props.noPadding
|
||||
};
|
||||
|
||||
return classNames(classes);
|
||||
}
|
||||
}
|
||||
|
||||
export default Modal;
|
|
@ -18,4 +18,11 @@
|
|||
padding: 50px;
|
||||
box-shadow: 0 0 10px white;
|
||||
}
|
||||
|
||||
&_no-padding {
|
||||
|
||||
.modal__content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -281,7 +281,9 @@ export default {
|
|||
'TICKET_SENT': 'Ticket has been created successfully.',
|
||||
'VALID_RECOVER': 'Password recovered successfully',
|
||||
'EMAIL_EXISTS': 'Email already exists',
|
||||
'ARE_YOU_SURE': 'Are you sure?',
|
||||
'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',
|
||||
|
|
|
@ -29,6 +29,7 @@ function processData (data, dataAsForm = false) {
|
|||
|
||||
module.exports = {
|
||||
call: function ({path, data, plain, dataAsForm}) {
|
||||
console.log('request ' + path, data);
|
||||
return new Promise(function (resolve, reject) {
|
||||
APIUtils.post(apiUrl + path, processData(data, dataAsForm), dataAsForm)
|
||||
.then(function (result) {
|
||||
|
|
|
@ -62,6 +62,7 @@ class SessionStore {
|
|||
this.setItem('title', configs.title);
|
||||
this.setItem('registration', configs.registration);
|
||||
this.setItem('user-system-enabled', configs['user-system-enabled']);
|
||||
this.setItem('allow-attachments', configs['allow-attachments']);
|
||||
}
|
||||
|
||||
getConfigs() {
|
||||
|
@ -72,9 +73,11 @@ class SessionStore {
|
|||
allowedLanguages: JSON.parse(this.getItem('allowedLanguages')),
|
||||
supportedLanguages: JSON.parse(this.getItem('supportedLanguages')),
|
||||
layout: this.getItem('layout'),
|
||||
registration: this.getItem('registration'),
|
||||
title: this.getItem('title'),
|
||||
['user-system-enabled']: this.getItem('user-system-enabled')
|
||||
registration: !!(this.getItem('registration') * 1),
|
||||
'user-system-enabled': !!(this.getItem('user-system-enabled') * 1),
|
||||
'allow-attachments': !!(this.getItem('allow-attachments') * 1),
|
||||
'maintenance-mode': !!(this.getItem('maintenance-mode') * 1)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ class AdminDataReducer extends Reducer {
|
|||
getTypeHandlers() {
|
||||
return {
|
||||
'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses,
|
||||
'SESSION_CHECKED': this.onSessionChecked,
|
||||
|
||||
'MY_TICKETS_FULFILLED': this.onMyTicketsRetrieved,
|
||||
'MY_TICKETS_REJECTED': this.onMyTicketsRejected,
|
||||
|
@ -51,15 +50,6 @@ class AdminDataReducer extends Reducer {
|
|||
});
|
||||
}
|
||||
|
||||
onSessionChecked(state) {
|
||||
const customResponses = sessionStore.getItem('customResponses');
|
||||
|
||||
return _.extend({}, state, {
|
||||
customResponses: JSON.parse(customResponses),
|
||||
customResponsesLoaded: true
|
||||
});
|
||||
}
|
||||
|
||||
onMyTicketsRetrieved(state, payload) {
|
||||
return _.extend({}, state, {
|
||||
myTickets: payload.data,
|
||||
|
|
|
@ -37,6 +37,10 @@ class ConfigReducer extends Reducer {
|
|||
|
||||
return _.extend({}, state, payload.data, {
|
||||
language: currentLanguage || payload.language,
|
||||
registration: !!(payload.data.registration * 1),
|
||||
'user-system-enabled': !!(payload.data['user-system-enabled']* 1),
|
||||
'allow-attachments': !!(payload.data['allow-attachments']* 1),
|
||||
'maintenance-mode': !!(payload.data['maintenance-mode']* 1),
|
||||
initDone: true
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ class ModalReducer extends Reducer {
|
|||
getInitialState() {
|
||||
return {
|
||||
opened: false,
|
||||
noPadding: false,
|
||||
content: null
|
||||
};
|
||||
}
|
||||
|
@ -23,7 +24,8 @@ class ModalReducer extends Reducer {
|
|||
|
||||
return _.extend({}, state, {
|
||||
opened: true,
|
||||
content: payload
|
||||
content: payload.content,
|
||||
noPadding: payload.noPadding || false
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -32,7 +34,8 @@ class ModalReducer extends Reducer {
|
|||
|
||||
return _.extend({}, state, {
|
||||
opened: false,
|
||||
content: null
|
||||
content: null,
|
||||
noPadding: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,11 @@ class LastEventsStaffController extends Controller {
|
|||
$query = substr($query,0,-3);
|
||||
$query .= ') ORDER BY id desc LIMIT ? OFFSET ?' ;
|
||||
|
||||
$eventList = Ticketevent::find($query, [10, 10*($page-1)]);
|
||||
|
||||
Response::respondSuccess($eventList->toArray());
|
||||
if(Ticketevent::count() && !$user->sharedTicketList->isEmpty()) {
|
||||
$eventList = Ticketevent::find($query, [10, 10*($page-1)]);
|
||||
Response::respondSuccess($eventList->toArray());
|
||||
} else {
|
||||
Response::respondSuccess([]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ require_once 'system/disable-user-system.php';
|
|||
require_once 'system/enabled-user-system.php';
|
||||
require_once 'system/add-api-key.php';
|
||||
require_once 'system/delete-api-key.php';
|
||||
require_once 'system/get-all-keys.php';
|
||||
require_once 'system/get-api-keys.php';
|
||||
require_once 'system/get-stats.php';
|
||||
require_once 'system/delete-all-users.php';
|
||||
require_once 'system/csv-import.php';
|
||||
|
@ -40,7 +40,7 @@ $systemControllerGroup->addController(new EnableRegistrationController);
|
|||
$systemControllerGroup->addController(new GetStatsController);
|
||||
$systemControllerGroup->addController(new AddAPIKeyController);
|
||||
$systemControllerGroup->addController(new DeleteAPIKeyController);
|
||||
$systemControllerGroup->addController(new GetAllKeyController);
|
||||
$systemControllerGroup->addController(new GetAPIKeysController);
|
||||
$systemControllerGroup->addController(new DeleteAllUsersController);
|
||||
$systemControllerGroup->addController(new BackupDatabaseController);
|
||||
$systemControllerGroup->addController(new DownloadController);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
|
||||
class GetAllKeyController extends Controller {
|
||||
const PATH = '/get-all-keys';
|
||||
class GetAPIKeysController extends Controller {
|
||||
const PATH = '/get-api-keys';
|
||||
const METHOD = 'POST';
|
||||
|
||||
public function validations() {
|
|
@ -86,6 +86,6 @@ class TicketGetController extends Controller {
|
|||
$user = Controller::getLoggedUser();
|
||||
|
||||
return (!Controller::isStaffLogged() && (Controller::isUserSystemEnabled() && $this->ticket->author->id !== $user->id)) ||
|
||||
(Controller::isStaffLogged() && $this->ticket->owner && $this->ticket->owner->id !== $user->id);
|
||||
(Controller::isStaffLogged() && !$user->sharedDepartmentList->includesId($this->ticket->department->id));
|
||||
}
|
||||
}
|
|
@ -30,6 +30,11 @@ class DeleteUserController extends Controller {
|
|||
|
||||
Log::createLog('DELETE_USER', $user->name);
|
||||
RedBean::exec('DELETE FROM log WHERE author_user_id = ?', [$userId]);
|
||||
|
||||
foreach($user->sharedTicketList as $ticket) {
|
||||
$ticket->delete();
|
||||
}
|
||||
|
||||
$user->delete();
|
||||
|
||||
Response::respondSuccess();
|
||||
|
|
|
@ -24,6 +24,11 @@ class LoginController extends Controller {
|
|||
}
|
||||
|
||||
if ($this->checkInputCredentials() || $this->checkRememberToken()) {
|
||||
if($this->userInstance->verificationToken !== null) {
|
||||
Response::respondError(ERRORS::UNVERIFIED_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->createUserSession();
|
||||
$this->createSessionCookie();
|
||||
if(Controller::request('staff')) {
|
||||
|
@ -31,14 +36,6 @@ class LoginController extends Controller {
|
|||
$this->userInstance->store();
|
||||
}
|
||||
|
||||
$email = Controller::request('email');
|
||||
$userRow = User::getDataStore($email, 'email');
|
||||
|
||||
if($userRow->verificationToken !== null) {
|
||||
Response::respondError(ERRORS::UNVERIFIED_USER);
|
||||
return;
|
||||
}
|
||||
|
||||
Response::respondSuccess($this->getUserData());
|
||||
} else {
|
||||
Response::respondError(ERRORS::INVALID_CREDENTIALS);
|
||||
|
|
|
@ -79,7 +79,9 @@ abstract class Controller {
|
|||
}
|
||||
|
||||
public function uploadFile() {
|
||||
if(!isset($_FILES['file'])) return '';
|
||||
$allowAttachments = Setting::getSetting('allow-attachments')->getValue();
|
||||
|
||||
if(!isset($_FILES['file']) || !$allowAttachments) return '';
|
||||
|
||||
$maxSize = Setting::getSetting('max-size')->getValue();
|
||||
$fileGap = Setting::getSetting('file-gap')->getValue();
|
||||
|
|
|
@ -45,6 +45,10 @@ class DataStoreList implements IteratorAggregate {
|
|||
return $includes;
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return empty($list);
|
||||
}
|
||||
|
||||
public function toBeanList() {
|
||||
$beanList = [];
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ 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-all-keys.rb'
|
||||
require './system/get-api-keys.rb'
|
||||
require './system/file-upload-download.rb'
|
||||
require './system/csv-import.rb'
|
||||
require './system/disable-user-system.rb'
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
describe'system/get-all-keys' do
|
||||
describe'system/get-api-keys' do
|
||||
request('/user/logout')
|
||||
Scripts.login($staff[:email], $staff[:password], true)
|
||||
|
||||
it 'should get all API keys' do
|
||||
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-all-keys', {
|
||||
result = request('/system/get-api-keys', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
})
|
Loading…
Reference in New Issue