Merge a180d49612
into c3b968aa10
This commit is contained in:
commit
7f84cb81b1
38 changed files with 205 additions and 43 deletions
|
@ -10,6 +10,7 @@ import {Button} from '../lib/bootstrap-components';
|
||||||
import {getUrl} from "../lib/urls";
|
import {getUrl} from "../lib/urls";
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
import styles from "./styles.scss"
|
import styles from "./styles.scss"
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -35,6 +36,10 @@ export default class API extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageApi) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageApi');
|
||||||
|
}
|
||||||
// noinspection JSIgnoredPromiseFromCall
|
// noinspection JSIgnoredPromiseFromCall
|
||||||
this.loadAccessToken();
|
this.loadAccessToken();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {Button} from "../lib/bootstrap-components";
|
||||||
import {HTTPMethod} from "../lib/axios";
|
import {HTTPMethod} from "../lib/axios";
|
||||||
import {tableAddRestActionButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../lib/modals";
|
import {tableAddRestActionButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../lib/modals";
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -87,6 +88,10 @@ export default class List extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageBlacklist) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageBlacklist');
|
||||||
|
}
|
||||||
this.clearFields();
|
this.clearFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,4 +144,4 @@ export default class List extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,6 +254,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageCampaigns) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageCampaigns');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRe
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
import styles from "./styles.scss";
|
import styles from "./styles.scss";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -34,6 +35,13 @@ export default class List extends Component {
|
||||||
tableRestActionDialogInit(this);
|
tableRestActionDialogInit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageCampaigns) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageCampaigns');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
permissions: PropTypes.object,
|
permissions: PropTypes.object,
|
||||||
channel: PropTypes.object
|
channel: PropTypes.object
|
||||||
|
|
|
@ -254,6 +254,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageChannels) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageChannels');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRe
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
import styles from "./styles.scss";
|
import styles from "./styles.scss";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -31,6 +32,13 @@ export default class List extends Component {
|
||||||
permissions: PropTypes.object
|
permissions: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageChannels) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageChannels');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const t = this.props.t;
|
const t = this.props.t;
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import {FieldWizard, UnsubscriptionMode} from '../../../shared/lists';
|
||||||
import styles from "../lib/styles.scss";
|
import styles from "../lib/styles.scss";
|
||||||
import {getMailerTypes} from "../send-configurations/helpers";
|
import {getMailerTypes} from "../send-configurations/helpers";
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -73,6 +74,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRe
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
import {withForm} from "../lib/form";
|
import {withForm} from "../lib/form";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -26,6 +27,13 @@ export default class List extends Component {
|
||||||
tableRestActionDialogInit(this);
|
tableRestActionDialogInit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
permissions: PropTypes.object
|
permissions: PropTypes.object
|
||||||
}
|
}
|
||||||
|
@ -132,6 +140,7 @@ export default class List extends Component {
|
||||||
|
|
||||||
<Table ref={node => this.table = node} withHeader dataUrl="rest/lists-table" columns={columns} />
|
<Table ref={node => this.table = node} withHeader dataUrl="rest/lists-table" columns={columns} />
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import styles from "../../lib/styles.scss";
|
||||||
import 'ace-builds/src-noconflict/mode-json';
|
import 'ace-builds/src-noconflict/mode-json';
|
||||||
import 'ace-builds/src-noconflict/mode-handlebars';
|
import 'ace-builds/src-noconflict/mode-handlebars';
|
||||||
import {withComponentMixins} from "../../lib/decorator-helpers";
|
import {withComponentMixins} from "../../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -178,6 +179,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {getFieldTypes} from './helpers';
|
||||||
import {Icon} from "../../lib/bootstrap-components";
|
import {Icon} from "../../lib/bootstrap-components";
|
||||||
import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../../lib/modals";
|
import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../../lib/modals";
|
||||||
import {withComponentMixins} from "../../lib/decorator-helpers";
|
import {withComponentMixins} from "../../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -32,6 +33,10 @@ export default class List extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -77,4 +82,4 @@ export default class List extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import listStyles from "../styles.scss";
|
||||||
import styles from "../../lib/styles.scss";
|
import styles from "../../lib/styles.scss";
|
||||||
import interoperableErrors from "../../../../shared/interoperable-errors";
|
import interoperableErrors from "../../../../shared/interoperable-errors";
|
||||||
import {withComponentMixins} from "../../lib/decorator-helpers";
|
import {withComponentMixins} from "../../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
|
|
||||||
function truncate(str, len, ending = '...') {
|
function truncate(str, len, ending = '...') {
|
||||||
|
@ -209,6 +210,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.initFromEntity(this.props.entity);
|
this.initFromEntity(this.props.entity);
|
||||||
} else {
|
} else {
|
||||||
|
@ -469,4 +474,4 @@ export default class CUD extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,10 @@ export default class List extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -95,4 +99,4 @@ export default class List extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {getRuleHelpers} from "./helpers";
|
||||||
import RuleSettingsPane from "./RuleSettingsPane";
|
import RuleSettingsPane from "./RuleSettingsPane";
|
||||||
import {withComponentMixins} from "../../lib/decorator-helpers";
|
import {withComponentMixins} from "../../lib/decorator-helpers";
|
||||||
import clone from "clone";
|
import clone from "clone";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
// https://stackoverflow.com/a/4819886/1601953
|
// https://stackoverflow.com/a/4819886/1601953
|
||||||
const isTouchDevice = !!('ontouchstart' in window || navigator.maxTouchPoints);
|
const isTouchDevice = !!('ontouchstart' in window || navigator.maxTouchPoints);
|
||||||
|
@ -123,6 +124,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
|
|
||||||
|
@ -401,4 +406,4 @@ export default class CUD extends Component {
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {Table} from '../../lib/table';
|
||||||
import {Icon} from "../../lib/bootstrap-components";
|
import {Icon} from "../../lib/bootstrap-components";
|
||||||
import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../../lib/modals";
|
import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../../lib/modals";
|
||||||
import {withComponentMixins} from "../../lib/decorator-helpers";
|
import {withComponentMixins} from "../../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -29,6 +30,10 @@ export default class List extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -69,4 +74,4 @@ export default class List extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {getFieldColumn, SubscriptionStatus} from '../../../../shared/lists';
|
||||||
import {getFieldTypes, getSubscriptionStatusLabels} from './helpers';
|
import {getFieldTypes, getSubscriptionStatusLabels} from './helpers';
|
||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import {withComponentMixins} from "../../lib/decorator-helpers";
|
import {withComponentMixins} from "../../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -89,6 +90,11 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
} from "../../lib/modals";
|
} from "../../lib/modals";
|
||||||
import listStyles from "../styles.scss";
|
import listStyles from "../styles.scss";
|
||||||
import {withComponentMixins} from "../../lib/decorator-helpers";
|
import {withComponentMixins} from "../../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -58,6 +59,10 @@ export default class List extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageLists) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageLists');
|
||||||
|
}
|
||||||
this.populateFormValues({
|
this.populateFormValues({
|
||||||
segment: this.props.segmentId || ''
|
segment: this.props.segmentId || ''
|
||||||
});
|
});
|
||||||
|
@ -188,4 +193,4 @@ export default class List extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageNamespaces) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageNamespaces');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,7 +29,12 @@ export default class List extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
permissions: PropTypes.object
|
permissions: PropTypes.object
|
||||||
}
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageNamespaces) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageNamespaces');
|
||||||
|
}
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
const t = this.props.t;
|
const t = this.props.t;
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,10 @@ import {getUrl} from "./lib/urls";
|
||||||
import {withComponentMixins} from "./lib/decorator-helpers";
|
import {withComponentMixins} from "./lib/decorator-helpers";
|
||||||
import Update from "./settings/Update";
|
import Update from "./settings/Update";
|
||||||
|
|
||||||
const topLevelMenuKeys = ['lists', 'channels', 'templates', 'campaigns'];
|
const topLevelMenuKeys = ['Lists', 'Channels', 'Templates', 'Campaigns'];
|
||||||
|
|
||||||
if (mailtrainConfig.reportsEnabled) {
|
if (mailtrainConfig.reportsEnabled) {
|
||||||
topLevelMenuKeys.push('reports');
|
topLevelMenuKeys.push('Reports');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,30 +67,43 @@ class Root extends Component {
|
||||||
|
|
||||||
const topLevelMenu = [];
|
const topLevelMenu = [];
|
||||||
|
|
||||||
for (const entryKey of topLevelMenuKeys) {
|
|
||||||
const entry = topLevelItems[entryKey];
|
|
||||||
const link = entry.link || entry.externalLink;
|
|
||||||
|
|
||||||
if (link && path.startsWith(link)) {
|
|
||||||
topLevelMenu.push(<NavLink key={entryKey} className="active" to={link}>{entry.title} <span className="sr-only">{t('current')}</span></NavLink>);
|
|
||||||
} else {
|
|
||||||
topLevelMenu.push(<NavLink key={entryKey} to={link}>{entry.title}</NavLink>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mailtrainConfig.isAuthenticated) {
|
if (mailtrainConfig.isAuthenticated) {
|
||||||
|
|
||||||
|
const gP = mailtrainConfig.globalPermissions;
|
||||||
|
|
||||||
|
for (const entryKey of topLevelMenuKeys) {
|
||||||
|
const entry = topLevelItems[entryKey.toLowerCase()];
|
||||||
|
const link = entry.link || entry.externalLink;
|
||||||
|
|
||||||
|
if (gP["manage"+entryKey]) {
|
||||||
|
if (link && path.startsWith(link)) {
|
||||||
|
topLevelMenu.push(<NavLink key={entryKey.toLowerCase()} className="active" to={link}>{entry.title} <span className="sr-only">{t('current')}</span></NavLink>);
|
||||||
|
} else {
|
||||||
|
topLevelMenu.push(<NavLink key={entryKey.toLowerCase()} to={link}>{entry.title}</NavLink>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ul className="navbar-nav mt-navbar-nav-left">
|
<ul className="navbar-nav mt-navbar-nav-left">
|
||||||
{topLevelMenu}
|
{topLevelMenu}
|
||||||
<NavDropdown label={t('administration')}>
|
{(gP.manageUsers || gP.manageNamespaces || gP.manageSettings ||
|
||||||
{mailtrainConfig.globalPermissions.displayManageUsers && <DropdownLink to="/users">{t('users')}</DropdownLink>}
|
gP.manageSendConfigurations || gP.manageBlacklist || gP.manageApi) &&
|
||||||
<DropdownLink to="/namespaces">{t('namespaces')}</DropdownLink>
|
<NavDropdown label={t('administration')}>
|
||||||
{mailtrainConfig.globalPermissions.manageSettings && <DropdownLink to="/settings">{t('globalSettings')}</DropdownLink>}
|
{(gP.manageUsers) &&
|
||||||
<DropdownLink to="/send-configurations">{t('sendConfigurations')}</DropdownLink>
|
<DropdownLink to="/users">{t('users')}</DropdownLink>}
|
||||||
{mailtrainConfig.globalPermissions.manageBlacklist && <DropdownLink to="/blacklist">{t('blacklist')}</DropdownLink>}
|
{(gP.manageNamespaces) &&
|
||||||
<DropdownLink to="/account/api">{t('api')}</DropdownLink>
|
<DropdownLink to="/namespaces">{t('namespaces')}</DropdownLink>}
|
||||||
</NavDropdown>
|
{(gP.manageSettings) &&
|
||||||
|
<DropdownLink to="/settings">{t('globalSettings')}</DropdownLink>}
|
||||||
|
{(gP.manageSendConfigurations) &&
|
||||||
|
<DropdownLink to="/send-configurations">{t('sendConfigurations')}</DropdownLink>}
|
||||||
|
{(gP.manageBlacklist) &&
|
||||||
|
<DropdownLink to="/blacklist">{t('blacklist')}</DropdownLink>}
|
||||||
|
{(gP.manageApi) &&
|
||||||
|
<DropdownLink to="/account/api">{t('api')}</DropdownLink>}
|
||||||
|
</NavDropdown>}
|
||||||
</ul>
|
</ul>
|
||||||
<ul className="navbar-nav mt-navbar-nav-right">
|
<ul className="navbar-nav mt-navbar-nav-right">
|
||||||
{getLanguageChooser(t)}
|
{getLanguageChooser(t)}
|
||||||
|
@ -101,6 +114,7 @@ class Root extends Component {
|
||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -91,6 +91,10 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageSendConfigurations) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageSendConfigurations');
|
||||||
|
}
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {getMailerTypes} from './helpers';
|
||||||
import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../lib/modals";
|
import {tableAddDeleteButton, tableRestActionDialogInit, tableRestActionDialogRender} from "../lib/modals";
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
|
@ -33,6 +34,13 @@ export default class List extends Component {
|
||||||
permissions: PropTypes.object
|
permissions: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageSendConfigurations) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageSendConfigurations');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const t = this.props.t;
|
const t = this.props.t;
|
||||||
|
|
||||||
|
@ -87,4 +95,4 @@ export default class List extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
} from '../lib/form';
|
} from '../lib/form';
|
||||||
import {withErrorHandling} from '../lib/error-handling';
|
import {withErrorHandling} from '../lib/error-handling';
|
||||||
import {withComponentMixins} from "../lib/decorator-helpers";
|
import {withComponentMixins} from "../lib/decorator-helpers";
|
||||||
|
import mailtrainConfig from 'mailtrainConfig';
|
||||||
|
|
||||||
@withComponentMixins([
|
@withComponentMixins([
|
||||||
withTranslation,
|
withTranslation,
|
||||||
|
@ -45,6 +46,10 @@ export default class Update extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
const t = this.props.t;
|
||||||
|
if (!mailtrainConfig.globalPermissions.manageSettings) {
|
||||||
|
this.navigateToWithFlashMessage('/', 'danger', t('permissionDenied')+': manageSettings');
|
||||||
|
}
|
||||||
this.getFormValuesFromEntity(this.props.entity);
|
this.getFormValuesFromEntity(this.props.entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,4 +107,4 @@ export default class Update extends Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1065,5 +1065,6 @@
|
||||||
"channelName": "Channel \"{{name}}\"",
|
"channelName": "Channel \"{{name}}\"",
|
||||||
"cloneCampaign": "Clone Campaign",
|
"cloneCampaign": "Clone Campaign",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
"selectCampaignToBeCloned": "Select campaign to be cloned."
|
"selectCampaignToBeCloned": "Select campaign to be cloned.",
|
||||||
|
"permissionDenied": "Zugang verweigert"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1071,5 +1071,6 @@
|
||||||
"channelName": "Channel \"{{name}}\"",
|
"channelName": "Channel \"{{name}}\"",
|
||||||
"cloneCampaign": "Clone Campaign",
|
"cloneCampaign": "Clone Campaign",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
"selectCampaignToBeCloned": "Select campaign to be cloned."
|
"selectCampaignToBeCloned": "Select campaign to be cloned.",
|
||||||
|
"permissionDenied": "Permission Denied"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1095,5 +1095,6 @@
|
||||||
"selectCampaignToBeCloned": "Elige la campaña que será clonada.",
|
"selectCampaignToBeCloned": "Elige la campaña que será clonada.",
|
||||||
"tagLanguage": "Lenguaje de marcado",
|
"tagLanguage": "Lenguaje de marcado",
|
||||||
"tagLanguageMustBeSelected": "Debes seleccionar un lenguaje de marcado",
|
"tagLanguageMustBeSelected": "Debes seleccionar un lenguaje de marcado",
|
||||||
"helpText": "Texto de ayuda"
|
"helpText": "Texto de ayuda",
|
||||||
|
"permissionDenied": "Permiso denegado"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1066,5 +1066,6 @@
|
||||||
"channelName": "Channel \"{{name}}\"",
|
"channelName": "Channel \"{{name}}\"",
|
||||||
"cloneCampaign": "Clone Campaign",
|
"cloneCampaign": "Clone Campaign",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
"selectCampaignToBeCloned": "Select campaign to be cloned."
|
"selectCampaignToBeCloned": "Select campaign to be cloned.",
|
||||||
|
"permissionDenied": "Permission refusée"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1144,5 +1144,6 @@
|
||||||
"channelName": "Channel \"{{name}}\"",
|
"channelName": "Channel \"{{name}}\"",
|
||||||
"cloneCampaign": "Clone Campaign",
|
"cloneCampaign": "Clone Campaign",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
"selectCampaignToBeCloned": "Select campaign to be cloned."
|
"selectCampaignToBeCloned": "Select campaign to be cloned.",
|
||||||
|
"permissionDenied": "Permissão negada"
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,12 +277,12 @@ defaultRoles:
|
||||||
name: Global Master
|
name: Global Master
|
||||||
admin: true
|
admin: true
|
||||||
description: All permissions
|
description: All permissions
|
||||||
permissions: [rebuildPermissions, createJavascriptWithROAccess, displayManageUsers, manageBlacklist, manageSettings, setupAutomation]
|
permissions: [rebuildPermissions, createJavascriptWithROAccess, manageBlacklist, manageSettings, manageUsers, manageLists, manageChannels, manageTemplates, manageCampaigns, manageReports, manageApi, manageSendConfigurations, manageNamespaces, setupAutomation]
|
||||||
rootNamespaceRole: master
|
rootNamespaceRole: master
|
||||||
campaignsAdmin:
|
campaignsAdmin:
|
||||||
name: Campaigns Admin
|
name: Campaigns Admin
|
||||||
description: Under the namespace in which the user is located, the user has all permissions for managing lists, templates and campaigns and the permission to send to send configurations.
|
description: Under the namespace in which the user is located, the user has all permissions for managing lists, templates and campaigns and the permission to send to send configurations.
|
||||||
permissions: [setupAutomation]
|
permissions: [setupAutomation, manageLists, manageChannels, manageTemplates, manageCampaigns, manageReports, manageApi, manageSendConfigurations, manageNamespaces]
|
||||||
ownNamespaceRole: campaignsAdmin
|
ownNamespaceRole: campaignsAdmin
|
||||||
campaignsAdminWithoutNamespace:
|
campaignsAdminWithoutNamespace:
|
||||||
name: Campaigns Admin (multiple namespaces)
|
name: Campaigns Admin (multiple namespaces)
|
||||||
|
|
|
@ -15,6 +15,8 @@ function loadLanguage(longCode) {
|
||||||
loadLanguage('en-US');
|
loadLanguage('en-US');
|
||||||
loadLanguage('es-ES');
|
loadLanguage('es-ES');
|
||||||
loadLanguage('pt-BR');
|
loadLanguage('pt-BR');
|
||||||
|
loadLanguage('de-DE');
|
||||||
|
loadLanguage('fr-FR');
|
||||||
resourcesCommon['fk-FK'] = convertToFake(resourcesCommon['en-US']);
|
resourcesCommon['fk-FK'] = convertToFake(resourcesCommon['en-US']);
|
||||||
|
|
||||||
const resources = {};
|
const resources = {};
|
||||||
|
|
|
@ -445,6 +445,7 @@ async function getByCid(context, cid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _validateAndPreprocess(tx, context, entity, isCreate, content) {
|
async function _validateAndPreprocess(tx, context, entity, isCreate, content) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageCampaigns');
|
||||||
if (content === Content.ALL || content === Content.WITHOUT_SOURCE_CUSTOM || content === Content.RSS_ENTRY) {
|
if (content === Content.ALL || content === Content.WITHOUT_SOURCE_CUSTOM || content === Content.RSS_ENTRY) {
|
||||||
await namespaceHelpers.validateEntity(tx, entity);
|
await namespaceHelpers.validateEntity(tx, entity);
|
||||||
|
|
||||||
|
@ -481,6 +482,7 @@ async function _validateAndPreprocess(tx, context, entity, isCreate, content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _createTx(tx, context, entity, content) {
|
async function _createTx(tx, context, entity, content) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageCampaigns');
|
||||||
return await knex.transaction(async tx => {
|
return await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createCampaign');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createCampaign');
|
||||||
|
|
||||||
|
@ -579,6 +581,7 @@ async function createRssTx(tx, context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _validateChannelMoveTx(tx, context, entity, existing) {
|
async function _validateChannelMoveTx(tx, context, entity, existing) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageCampaigns');
|
||||||
if (existing.channel !== entity.channel) {
|
if (existing.channel !== entity.channel) {
|
||||||
await shares.enforceEntityPermission(context, 'channel', entity.channel, 'createCampaign');
|
await shares.enforceEntityPermission(context, 'channel', entity.channel, 'createCampaign');
|
||||||
await shares.enforceEntityPermission(context, 'campaign', entity.id, 'delete');
|
await shares.enforceEntityPermission(context, 'campaign', entity.id, 'delete');
|
||||||
|
@ -637,6 +640,7 @@ async function updateWithConsistencyCheck(context, entity, content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _removeTx(tx, context, id, existing = null, overrideTypeCheck = false) {
|
async function _removeTx(tx, context, id, existing = null, overrideTypeCheck = false) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageCampaigns');
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'campaign', id, 'delete');
|
await shares.enforceEntityPermissionTx(tx, context, 'campaign', id, 'delete');
|
||||||
|
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
|
@ -861,6 +865,7 @@ async function prepareCampaignMessages(campaignId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _changeStatus(context, campaignId, permittedCurrentStates, newState, invalidStateMessage, extraData) {
|
async function _changeStatus(context, campaignId, permittedCurrentStates, newState, invalidStateMessage, extraData) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageCampaigns');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
// This is quite inefficient because it selects the same row 3 times. However as status is changed
|
// This is quite inefficient because it selects the same row 3 times. However as status is changed
|
||||||
// rather infrequently, we keep it this way for simplicity
|
// rather infrequently, we keep it this way for simplicity
|
||||||
|
@ -925,6 +930,7 @@ async function stop(context, campaignId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function reset(context, campaignId) {
|
async function reset(context, campaignId) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageCampaigns');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
// This is quite inefficient because it selects the same row 3 times. However as RESET is
|
// This is quite inefficient because it selects the same row 3 times. However as RESET is
|
||||||
// going to be called rather infrequently, we keep it this way for simplicity
|
// going to be called rather infrequently, we keep it this way for simplicity
|
||||||
|
|
|
@ -140,6 +140,7 @@ async function _validateAndPreprocess(tx, context, entity, isCreate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function _createTx(tx, context, entity, content) {
|
async function _createTx(tx, context, entity, content) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageChannels');
|
||||||
return await knex.transaction(async tx => {
|
return await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createCampaign');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createCampaign');
|
||||||
|
|
||||||
|
@ -169,6 +170,7 @@ async function create(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateWithConsistencyCheck(context, entity) {
|
async function updateWithConsistencyCheck(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageChannels');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'channel', entity.id, 'edit');
|
await shares.enforceEntityPermissionTx(tx, context, 'channel', entity.id, 'edit');
|
||||||
|
|
||||||
|
@ -198,6 +200,7 @@ async function updateWithConsistencyCheck(context, entity) {
|
||||||
|
|
||||||
|
|
||||||
async function remove(context, id) {
|
async function remove(context, id) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageChannels');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'channel', id, 'delete');
|
await shares.enforceEntityPermissionTx(tx, context, 'channel', id, 'delete');
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ async function listByNamespaceDTAjax(context, namespaceId, params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listWithSegmentByCampaignDTAjax(context, campaignId, params) {
|
async function listWithSegmentByCampaignDTAjax(context, campaignId, params) {
|
||||||
|
await shares.enforceEntityPermissionTx(tx, context, 'list', id, 'view');
|
||||||
return await dtHelpers.ajaxListWithPermissions(
|
return await dtHelpers.ajaxListWithPermissions(
|
||||||
context,
|
context,
|
||||||
[{ entityTypeId: 'list', requiredOperations: ['view'] }],
|
[{ entityTypeId: 'list', requiredOperations: ['view'] }],
|
||||||
|
@ -84,7 +85,6 @@ async function listWithSegmentByCampaignDTAjax(context, campaignId, params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getByIdTx(tx, context, id) {
|
async function getByIdTx(tx, context, id) {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'list', id, 'view');
|
|
||||||
const entity = await tx('lists').where('id', id).first();
|
const entity = await tx('lists').where('id', id).first();
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
@ -153,6 +153,7 @@ async function _validateAndPreprocess(tx, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function create(context, entity) {
|
async function create(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageLists');
|
||||||
return await knex.transaction(async tx => {
|
return await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createList');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createList');
|
||||||
|
|
||||||
|
@ -248,6 +249,7 @@ async function create(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateWithConsistencyCheck(context, entity) {
|
async function updateWithConsistencyCheck(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageLists');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'list', entity.id, 'edit');
|
await shares.enforceEntityPermissionTx(tx, context, 'list', entity.id, 'edit');
|
||||||
|
|
||||||
|
@ -274,6 +276,7 @@ async function updateWithConsistencyCheck(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function remove(context, id) {
|
async function remove(context, id) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageLists');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'list', id, 'delete');
|
await shares.enforceEntityPermissionTx(tx, context, 'list', id, 'delete');
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,6 @@ async function getById(context, id) {
|
||||||
|
|
||||||
async function getChildrenTx(tx, context, id) {
|
async function getChildrenTx(tx, context, id) {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', id, 'view');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', id, 'view');
|
||||||
|
|
||||||
const entityType = entitySettings.getEntityType('namespace');
|
const entityType = entitySettings.getEntityType('namespace');
|
||||||
|
|
||||||
const extraKeys = em.get('models.namespaces.extraKeys', []);
|
const extraKeys = em.get('models.namespaces.extraKeys', []);
|
||||||
|
@ -162,6 +161,7 @@ async function getChildrenTx(tx, context, id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTx(tx, context, entity) {
|
async function createTx(tx, context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageNamespaces');
|
||||||
enforce(entity.namespace, 'Parent namespace must be set');
|
enforce(entity.namespace, 'Parent namespace must be set');
|
||||||
|
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createNamespace');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createNamespace');
|
||||||
|
@ -183,6 +183,7 @@ async function create(context, entity) {
|
||||||
|
|
||||||
async function updateWithConsistencyCheck(context, entity) {
|
async function updateWithConsistencyCheck(context, entity) {
|
||||||
enforce(entity.id !== 1 || entity.namespace === null, 'Cannot assign a parent to the root namespace.');
|
enforce(entity.id !== 1 || entity.namespace === null, 'Cannot assign a parent to the root namespace.');
|
||||||
|
shares.enforceGlobalPermission(context, 'manageNamespaces');
|
||||||
|
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.id, 'edit');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.id, 'edit');
|
||||||
|
@ -221,6 +222,7 @@ async function updateWithConsistencyCheck(context, entity) {
|
||||||
|
|
||||||
async function remove(context, id) {
|
async function remove(context, id) {
|
||||||
enforce(id !== 1, 'Cannot delete the root namespace.');
|
enforce(id !== 1, 'Cannot delete the root namespace.');
|
||||||
|
shares.enforceGlobalPermission(context, 'manageNamespaces');
|
||||||
|
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', id, 'delete');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', id, 'delete');
|
||||||
|
|
|
@ -64,6 +64,7 @@ async function listDTAjax(context, params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function create(context, entity) {
|
async function create(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageReports');
|
||||||
let id;
|
let id;
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createReport');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createReport');
|
||||||
|
@ -85,6 +86,7 @@ async function create(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateWithConsistencyCheck(context, entity) {
|
async function updateWithConsistencyCheck(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageReports');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'report', entity.id, 'edit');
|
await shares.enforceEntityPermissionTx(tx, context, 'report', entity.id, 'edit');
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'reportTemplate', entity.report_template, 'execute');
|
await shares.enforceEntityPermissionTx(tx, context, 'reportTemplate', entity.report_template, 'execute');
|
||||||
|
@ -120,6 +122,7 @@ async function updateWithConsistencyCheck(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeTx(tx, context, id) {
|
async function removeTx(tx, context, id) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageReports');
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'report', id, 'delete');
|
await shares.enforceEntityPermissionTx(tx, context, 'report', id, 'delete');
|
||||||
|
|
||||||
const report = await tx('reports').where('id', id).first();
|
const report = await tx('reports').where('id', id).first();
|
||||||
|
|
|
@ -120,6 +120,7 @@ async function _validateAndPreprocess(tx, entity, isCreate) {
|
||||||
|
|
||||||
|
|
||||||
async function create(context, entity) {
|
async function create(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageSendConfigurations');
|
||||||
return await knex.transaction(async tx => {
|
return await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createSendConfiguration');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createSendConfiguration');
|
||||||
|
|
||||||
|
@ -138,6 +139,7 @@ async function create(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateWithConsistencyCheck(context, entity) {
|
async function updateWithConsistencyCheck(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageSendConfigurations');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'sendConfiguration', entity.id, 'edit');
|
await shares.enforceEntityPermissionTx(tx, context, 'sendConfiguration', entity.id, 'edit');
|
||||||
|
|
||||||
|
@ -167,6 +169,7 @@ async function updateWithConsistencyCheck(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function remove(context, id) {
|
async function remove(context, id) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageSendConfigurations');
|
||||||
if (id === getSystemSendConfigurationId()) {
|
if (id === getSystemSendConfigurationId()) {
|
||||||
shares.throwPermissionDenied();
|
shares.throwPermissionDenied();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ const log = require('../lib/log');
|
||||||
const {getGlobalNamespaceId} = require('../../shared/namespaces');
|
const {getGlobalNamespaceId} = require('../../shared/namespaces');
|
||||||
const {getAdminId} = require('../../shared/users');
|
const {getAdminId} = require('../../shared/users');
|
||||||
|
|
||||||
|
|
||||||
// TODO: This would really benefit from some permission cache connected to rebuildPermissions
|
// TODO: This would really benefit from some permission cache connected to rebuildPermissions
|
||||||
// A bit of the problem is that the cache would have to expunged as the result of other processes modifying entites/permissions
|
// A bit of the problem is that the cache would have to expunged as the result of other processes modifying entites/permissions
|
||||||
|
|
||||||
|
@ -726,4 +727,4 @@ module.exports.regenerateRoleNamesTable = regenerateRoleNamesTable;
|
||||||
module.exports.getGlobalPermissions = getGlobalPermissions;
|
module.exports.getGlobalPermissions = getGlobalPermissions;
|
||||||
module.exports.getPermissionsTx = getPermissionsTx;
|
module.exports.getPermissionsTx = getPermissionsTx;
|
||||||
module.exports.filterPermissionsByRestrictedAccessHandler = filterPermissionsByRestrictedAccessHandler;
|
module.exports.filterPermissionsByRestrictedAccessHandler = filterPermissionsByRestrictedAccessHandler;
|
||||||
module.exports.isAccessibleByRestrictedAccessHandler = isAccessibleByRestrictedAccessHandler;
|
module.exports.isAccessibleByRestrictedAccessHandler = isAccessibleByRestrictedAccessHandler;
|
||||||
|
|
|
@ -70,6 +70,7 @@ async function _validateAndPreprocess(tx, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function create(context, entity) {
|
async function create(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageTemplates');
|
||||||
return await knex.transaction(async tx => {
|
return await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createTemplate');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', entity.namespace, 'createTemplate');
|
||||||
|
|
||||||
|
@ -114,6 +115,7 @@ async function create(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateWithConsistencyCheck(context, entity) {
|
async function updateWithConsistencyCheck(context, entity) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageTemplates');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'template', entity.id, 'edit');
|
await shares.enforceEntityPermissionTx(tx, context, 'template', entity.id, 'edit');
|
||||||
|
|
||||||
|
@ -143,6 +145,7 @@ async function updateWithConsistencyCheck(context, entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function remove(context, id) {
|
async function remove(context, id) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageTemplates');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'template', id, 'delete');
|
await shares.enforceEntityPermissionTx(tx, context, 'template', id, 'delete');
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@ async function _validateAndPreprocess(tx, entity, isCreate, isOwnAccount) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function create(context, user) {
|
async function create(context, user) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageUsers');
|
||||||
let id;
|
let id;
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
await shares.enforceEntityPermissionTx(tx, context, 'namespace', user.namespace, 'manageUsers');
|
await shares.enforceEntityPermissionTx(tx, context, 'namespace', user.namespace, 'manageUsers');
|
||||||
|
@ -192,6 +193,7 @@ async function create(context, user) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateWithConsistencyCheck(context, user, isOwnAccount) {
|
async function updateWithConsistencyCheck(context, user, isOwnAccount) {
|
||||||
|
shares.enforceGlobalPermission(context, 'manageUsers');
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
const existing = await tx('users').where('id', user.id).first();
|
const existing = await tx('users').where('id', user.id).first();
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
|
@ -240,6 +242,7 @@ async function updateWithConsistencyCheck(context, user, isOwnAccount) {
|
||||||
async function remove(context, userId) {
|
async function remove(context, userId) {
|
||||||
enforce(userId !== 1, 'Admin cannot be deleted');
|
enforce(userId !== 1, 'Admin cannot be deleted');
|
||||||
enforce(context.user.id !== userId, 'User cannot delete himself/herself');
|
enforce(context.user.id !== userId, 'User cannot delete himself/herself');
|
||||||
|
shares.enforceGlobalPermission(context, 'manageUsers');
|
||||||
|
|
||||||
await knex.transaction(async tx => {
|
await knex.transaction(async tx => {
|
||||||
const existing = await tx('users').where('id', userId).first();
|
const existing = await tx('users').where('id', userId).first();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue