WiP on permissions

Table of shares per user
This commit is contained in:
Tomas Bures 2017-07-27 17:11:22 +03:00
parent 89c9615592
commit 89256d62bd
20 changed files with 354 additions and 171 deletions

View file

@ -110,19 +110,18 @@ export default class Share extends Component {
render() {
const t = this.props.t;
const roles = mailtrainConfig.roles[this.props.entityTypeId];
const actions = data => [
{
label: 'Delete',
action: () => this.deleteShare(data[4])
action: () => this.deleteShare(data[3])
}
];
const sharesColumns = [
{ data: 1, title: t('Username') },
{ data: 2, title: t('Name') },
{ data: 3, title: t('Role'), render: data => roles[data] ? roles[data].name : data }
{ data: 0, title: t('Username') },
{ data: 1, title: t('Name') },
{ data: 2, title: t('Role') }
];
@ -144,13 +143,6 @@ export default class Share extends Component {
];
const rolesData = [];
for (const key in roles) {
const role = roles[key];
rolesData.push([ key, role.name, role.description ]);
}
if (this.state.entity) {
return (
<div>
@ -158,8 +150,8 @@ export default class Share extends Component {
<h3 className="legend">{t('Add User')}</h3>
<Form stateOwner={this} onSubmitAsync={::this.submitHandler}>
<TableSelect ref={node => this.usersTableSelect = node} id="userId" label={t('User')} withHeader dropdown dataUrl={`/rest/shares-users-table/${this.props.entityTypeId}/${this.state.entityId}`} columns={usersColumns} selectionLabelIndex={usersLabelIndex}/>
<TableSelect id="role" label={t('Role')} withHeader dropdown data={rolesData} columns={rolesColumns} selectionLabelIndex={1}/>
<TableSelect ref={node => this.usersTableSelect = node} id="userId" label={t('User')} withHeader dropdown dataUrl={`/rest/shares-unassigned-users-table/${this.props.entityTypeId}/${this.state.entityId}`} columns={usersColumns} selectionLabelIndex={usersLabelIndex}/>
<TableSelect id="role" label={t('Role')} withHeader dropdown dataUrl={`/rest/shares-roles-table/${this.props.entityTypeId}`} columns={rolesColumns} selectionLabelIndex={1}/>
<ButtonRow>
<Button type="submit" className="btn-primary" icon="ok" label={t('Share')}/>
@ -169,7 +161,7 @@ export default class Share extends Component {
<hr/>
<h3 className="legend">{t('Existing Users')}</h3>
<Table ref={node => this.sharesTable = node} withHeader dataUrl={`/rest/shares-table/${this.props.entityTypeId}/${this.state.entityId}`} columns={sharesColumns} actions={actions}/>
<Table ref={node => this.sharesTable = node} withHeader dataUrl={`/rest/shares-table-by-entity/${this.props.entityTypeId}/${this.state.entityId}`} columns={sharesColumns} actions={actions}/>
</div>
);
} else {

View file

@ -0,0 +1,93 @@
'use strict';
import React, { Component } from 'react';
import { translate } from 'react-i18next';
import { requiresAuthenticatedUser, withPageHelpers, Title } from '../lib/page';
import { withErrorHandling, withAsyncErrorHandler } from '../lib/error-handling';
import { Table } from '../lib/table';
import axios from '../lib/axios';
import mailtrainConfig from 'mailtrainConfig';
@translate()
@withPageHelpers
@withErrorHandling
@requiresAuthenticatedUser
export default class UserShares extends Component {
constructor(props) {
super(props);
this.sharesTables = {};
this.state = {
userId: parseInt(props.match.params.id)
};
}
@withAsyncErrorHandler
async loadEntity() {
const response = await axios.get(`/rest/users/${this.state.userId}`);
this.setState({
username: response.data.username
});
}
@withAsyncErrorHandler
async deleteShare(entityTypeId, entityId) {
const data = {
entityTypeId,
entityId,
userId: this.state.userId
};
await axios.put('/rest/shares', data);
for (const key in this.sharesTables) {
this.sharesTables[key].refresh();
}
}
componentDidMount() {
this.loadEntity();
}
render() {
const renderSharesTable = (entityTypeId, title) => {
const actions = data => {
const actions = [];
const perms = data[3];
if (perms.includes('share')) {
actions.push({
label: 'Delete',
action: () => this.deleteShare(entityTypeId, data[2])
});
}
return actions;
};
const columns = [
{ data: 0, title: t('Name') },
{ data: 1, title: t('Role') }
];
return (
<div>
<h3>{title}</h3>
<Table ref={node => this.sharesTables[entityTypeId] = node} withHeader dataUrl={`/rest/shares-table-by-user/${entityTypeId}/${this.state.userId}`} columns={columns} actions={actions}/>
</div>
);
};
const t = this.props.t;
return (
<div>
<Title>{t('Shares for user "{{username}}"', {username: this.state.username})}</Title>
{renderSharesTable('namespace', t('Namespaces'))}
{renderSharesTable('reportTemplate', t('Report Templates'))}
{renderSharesTable('report', t('Reports'))}
</div>
);
}
}

View file

@ -24,9 +24,7 @@ export default class CUD extends Component {
this.passwordValidator = passwordValidator(props.t);
this.state = {
globalRoles: []
};
this.state = {};
if (props.edit) {
this.state.entityId = parseInt(props.match.params.id);
@ -49,14 +47,6 @@ export default class CUD extends Component {
return this.props.match.params.action === 'delete';
}
@withAsyncErrorHandler
async fetchGlobalRoles() {
const result = await axios.get('/rest/users-global-roles');
this.setState({
globalRoles: result.data
});
}
@withAsyncErrorHandler
async loadFormValues() {
await this.getFormValuesFromURL(`/rest/users/${this.state.entityId}`, data => {
@ -221,20 +211,12 @@ export default class CUD extends Component {
const userId = this.getFormValue('id');
const canDelete = userId !== 1 && mailtrainConfig.userId !== userId;
const roles = mailtrainConfig.roles.global;
const rolesColumns = [
{ data: 1, title: "Name" },
{ data: 2, title: "Description" },
];
const rolesData = [];
for (const key in roles) {
const role = roles[key];
rolesData.push([ key, role.name, role.description ]);
}
return (
<div>
{edit && canDelete &&
@ -258,7 +240,7 @@ export default class CUD extends Component {
<InputField id="password2" label={t('Repeat Password')} type="password"/>
</div>
}
<TableSelect id="role" label={t('Role')} withHeader dropdown data={rolesData} columns={rolesColumns} selectionLabelIndex={1}/>
<TableSelect id="role" label={t('Role')} withHeader dropdown dataUrl={'/rest/shares-roles-table/global'} columns={rolesColumns} selectionLabelIndex={1}/>
<NamespaceSelect/>
<ButtonRow>

View file

@ -21,6 +21,10 @@ export default class List extends Component {
{
label: 'Edit',
link: '/users/edit/' + data[0]
},
{
label: 'Shares',
link: '/users/shares/' + data[0]
}
];
@ -34,6 +38,7 @@ export default class List extends Component {
}
columns.push({ data: 3, title: "Namespace" });
columns.push({ data: 4, title: "Role" });
return (
<div>

View file

@ -8,24 +8,9 @@ import i18n from '../lib/i18n';
import { Section } from '../lib/page';
import CUD from './CUD';
import List from './List';
import mailtrainConfig from 'mailtrainConfig';
import UserShares from '../shares/UserShares';
const getStructure = t => {
const subPaths = {};
if (mailtrainConfig.isAuthMethodLocal) {
subPaths.edit = {
title: t('Edit User'),
params: [':id', ':action?'],
render: props => (<CUD edit {...props} />)
};
subPaths.create = {
title: t('Create User'),
render: props => (<CUD {...props} />)
};
}
return {
'': {
title: t('Home'),
@ -35,7 +20,22 @@ const getStructure = t => {
title: t('Users'),
link: '/users',
component: List,
children: subPaths
children: {
edit: {
title: t('Edit User'),
params: [':id', ':action?'],
render: props => (<CUD edit {...props} />)
},
create: {
title: t('Create User'),
render: props => (<CUD {...props} />)
},
shares: {
title: t('User Shares'),
params: [':id' ],
component: UserShares
}
}
}
}
}