PLT-2115 Adding compliance
Этот коммит содержится в:
@@ -22,6 +22,7 @@ import LegalAndSupportSettingsTab from './legal_and_support_settings.jsx';
|
||||
import TeamUsersTab from './team_users.jsx';
|
||||
import TeamAnalyticsTab from '../analytics/team_analytics.jsx';
|
||||
import LdapSettingsTab from './ldap_settings.jsx';
|
||||
import ComplianceSettingsTab from './compliance_settings.jsx';
|
||||
import LicenseSettingsTab from './license_settings.jsx';
|
||||
import SystemAnalyticsTab from '../analytics/system_analytics.jsx';
|
||||
|
||||
@@ -156,6 +157,8 @@ export default class AdminController extends React.Component {
|
||||
tab = <LegalAndSupportSettingsTab config={this.state.config}/>;
|
||||
} else if (this.state.selected === 'ldap_settings') {
|
||||
tab = <LdapSettingsTab config={this.state.config}/>;
|
||||
} else if (this.state.selected === 'compliance_settings') {
|
||||
tab = <ComplianceSettingsTab config={this.state.config}/>;
|
||||
} else if (this.state.selected === 'license') {
|
||||
tab = <LicenseSettingsTab config={this.state.config}/>;
|
||||
} else if (this.state.selected === 'team_users') {
|
||||
|
||||
@@ -176,6 +176,7 @@ export default class AdminSidebar extends React.Component {
|
||||
}
|
||||
|
||||
let ldapSettings;
|
||||
let complianceSettings;
|
||||
let licenseSettings;
|
||||
if (global.window.mm_config.BuildEnterpriseReady === 'true') {
|
||||
if (global.window.mm_license.IsLicensed === 'true') {
|
||||
@@ -193,6 +194,21 @@ export default class AdminSidebar extends React.Component {
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
|
||||
complianceSettings = (
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
className={this.isSelected('compliance_settings')}
|
||||
onClick={this.handleClick.bind(this, 'compliance_settings', null)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.sidebar.compliance'
|
||||
defaultMessage='Compliance Settings'
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
licenseSettings = (
|
||||
@@ -386,6 +402,7 @@ export default class AdminSidebar extends React.Component {
|
||||
</a>
|
||||
</li>
|
||||
{ldapSettings}
|
||||
{complianceSettings}
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
import LoadingScreen from '../loading_screen.jsx';
|
||||
import AuditTable from '../audit_table.jsx';
|
||||
import ComplianceReports from './compliance_reports.jsx';
|
||||
|
||||
import AdminStore from '../../stores/admin_store.jsx';
|
||||
|
||||
@@ -58,36 +59,40 @@ export default class Audits extends React.Component {
|
||||
} else {
|
||||
content = (
|
||||
<div style={{margin: '10px'}}>
|
||||
<AuditTable
|
||||
audits={this.state.audits}
|
||||
showUserId={true}
|
||||
showIp={true}
|
||||
showSession={true}
|
||||
/>
|
||||
<AuditTable
|
||||
audits={this.state.audits}
|
||||
showUserId={true}
|
||||
showIp={true}
|
||||
showSession={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='panel'>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id='admin.audits.title'
|
||||
defaultMessage='User Activity'
|
||||
/>
|
||||
</h3>
|
||||
<button
|
||||
type='submit'
|
||||
className='btn btn-primary'
|
||||
onClick={this.reload}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.audits.reload'
|
||||
defaultMessage='Reload'
|
||||
/>
|
||||
</button>
|
||||
<div className='log__panel'>
|
||||
{content}
|
||||
<div>
|
||||
<ComplianceReports/>
|
||||
|
||||
<div className='panel'>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id='admin.audits.title'
|
||||
defaultMessage='User Activity'
|
||||
/>
|
||||
</h3>
|
||||
<button
|
||||
type='submit'
|
||||
className='btn btn-primary'
|
||||
onClick={this.reload}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.audits.reload'
|
||||
defaultMessage='Reload'
|
||||
/>
|
||||
</button>
|
||||
<div className='audit__panel'>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
384
web/react/components/admin_console/compliance_reports.jsx
Обычный файл
384
web/react/components/admin_console/compliance_reports.jsx
Обычный файл
@@ -0,0 +1,384 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import LoadingScreen from '../loading_screen.jsx';
|
||||
import * as Utils from '../../utils/utils.jsx';
|
||||
import AdminStore from '../../stores/admin_store.jsx';
|
||||
import UserStore from '../../stores/user_store.jsx';
|
||||
|
||||
import * as Client from '../../utils/client.jsx';
|
||||
import * as AsyncClient from '../../utils/async_client.jsx';
|
||||
|
||||
import {FormattedMessage, FormattedDate, FormattedTime} from 'mm-intl';
|
||||
|
||||
export default class ComplianceReports extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onComplianceReportsListenerChange = this.onComplianceReportsListenerChange.bind(this);
|
||||
this.reload = this.reload.bind(this);
|
||||
this.runReport = this.runReport.bind(this);
|
||||
this.getDateTime = this.getDateTime.bind(this);
|
||||
|
||||
this.state = {
|
||||
reports: AdminStore.getComplianceReports(),
|
||||
serverError: null
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
AdminStore.addComplianceReportsChangeListener(this.onComplianceReportsListenerChange);
|
||||
|
||||
if (global.window.mm_license.IsLicensed !== 'true' || global.window.mm_config.EnableCompliance !== 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncClient.getComplianceReports();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
AdminStore.removeComplianceReportsChangeListener(this.onComplianceReportsListenerChange);
|
||||
}
|
||||
|
||||
onComplianceReportsListenerChange() {
|
||||
this.setState({
|
||||
reports: AdminStore.getComplianceReports()
|
||||
});
|
||||
}
|
||||
|
||||
reload() {
|
||||
AdminStore.saveComplianceReports(null);
|
||||
this.setState({
|
||||
reports: null,
|
||||
serverError: null
|
||||
});
|
||||
|
||||
AsyncClient.getComplianceReports();
|
||||
}
|
||||
|
||||
runReport(e) {
|
||||
e.preventDefault();
|
||||
$('#run-button').button('loading');
|
||||
|
||||
var job = {};
|
||||
job.desc = ReactDOM.findDOMNode(this.refs.desc).value;
|
||||
job.emails = ReactDOM.findDOMNode(this.refs.emails).value;
|
||||
job.keywords = ReactDOM.findDOMNode(this.refs.keywords).value;
|
||||
job.start_at = Date.parse(ReactDOM.findDOMNode(this.refs.from).value);
|
||||
job.end_at = Date.parse(ReactDOM.findDOMNode(this.refs.to).value);
|
||||
|
||||
Client.saveComplianceReports(
|
||||
job,
|
||||
() => {
|
||||
ReactDOM.findDOMNode(this.refs.emails).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.keywords).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.desc).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.from).value = '';
|
||||
ReactDOM.findDOMNode(this.refs.to).value = '';
|
||||
this.reload();
|
||||
$('#run-button').button('reset');
|
||||
},
|
||||
(err) => {
|
||||
this.setState({serverError: err.message});
|
||||
$('#run-button').button('reset');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
getDateTime(millis) {
|
||||
const date = new Date(millis);
|
||||
return (
|
||||
<span style={{whiteSpace: 'nowrap'}}>
|
||||
<FormattedDate
|
||||
value={date}
|
||||
day='2-digit'
|
||||
month='short'
|
||||
year='numeric'
|
||||
/>
|
||||
{' - '}
|
||||
<FormattedTime
|
||||
value={date}
|
||||
hour='2-digit'
|
||||
minute='2-digit'
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
var content = null;
|
||||
|
||||
if (global.window.mm_license.IsLicensed !== 'true' || global.window.mm_config.EnableCompliance !== 'true') {
|
||||
return <div/>;
|
||||
}
|
||||
|
||||
if (this.state.reports === null) {
|
||||
content = <LoadingScreen/>;
|
||||
} else {
|
||||
var list = [];
|
||||
|
||||
for (var i = 0; i < this.state.reports.length; i++) {
|
||||
const report = this.state.reports[i];
|
||||
|
||||
var params = '';
|
||||
if (report.type === 'adhoc') {
|
||||
params = (
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.from'
|
||||
defaultMessage='From:'
|
||||
/>{' '}{this.getDateTime(report.start_at)}
|
||||
<br/>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.to'
|
||||
defaultMessage='To:'
|
||||
/>{' '}{this.getDateTime(report.end_at)}
|
||||
<br/>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.emails'
|
||||
defaultMessage='Emails:'
|
||||
/>{' '}{report.emails}
|
||||
<br/>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.keywords'
|
||||
defaultMessage='Keywords:'
|
||||
/>{' '}{report.keywords}
|
||||
</span>);
|
||||
}
|
||||
|
||||
var download = '';
|
||||
if (report.status === 'finished') {
|
||||
download = (
|
||||
<a href={'/api/v1/admin/download_compliance_report/' + report.id}>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.download'
|
||||
defaultMessage='Download'
|
||||
/>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
var status = report.status;
|
||||
if (report.status === 'finished') {
|
||||
status = (
|
||||
<span style={{color: 'green'}}>{report.status}</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (report.status === 'failed') {
|
||||
status = (
|
||||
<span style={{color: 'red'}}>{report.status}</span>
|
||||
);
|
||||
}
|
||||
|
||||
var user = report.user_id;
|
||||
var profile = UserStore.getProfile(report.user_id);
|
||||
if (profile) {
|
||||
user = profile.email;
|
||||
}
|
||||
|
||||
list[i] = (
|
||||
<tr key={report.id}>
|
||||
<td style={{whiteSpace: 'nowrap'}}>{download}</td>
|
||||
<td>{this.getDateTime(report.create_at)}</td>
|
||||
<td>{status}</td>
|
||||
<td>{report.count}</td>
|
||||
<td>{report.type}</td>
|
||||
<td style={{whiteSpace: 'nowrap'}}>{report.desc}</td>
|
||||
<td>{user}</td>
|
||||
<td style={{whiteSpace: 'nowrap'}}>{params}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
content = (
|
||||
<div style={{margin: '10px'}}>
|
||||
<table className='table'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.timestamp'
|
||||
defaultMessage='Timestamp'
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.status'
|
||||
defaultMessage='Status'
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.records'
|
||||
defaultMessage='Records'
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.type'
|
||||
defaultMessage='Type'
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.desc'
|
||||
defaultMessage='Description'
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.userId'
|
||||
defaultMessage='Requested By'
|
||||
/>
|
||||
</th>
|
||||
<th>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_table.params'
|
||||
defaultMessage='Params'
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{list}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let serverError = '';
|
||||
if (this.state.serverError) {
|
||||
serverError = (
|
||||
<div
|
||||
className='form-group has-error'
|
||||
style={{marginTop: '10px'}}
|
||||
>
|
||||
<label className='control-label'>{this.state.serverError}</label>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='panel'>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.title'
|
||||
defaultMessage='Compliance Reports'
|
||||
/>
|
||||
</h3>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colSpan='5'
|
||||
style={{paddingBottom: '6px'}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.desc'
|
||||
defaultMessage='Job Name:'
|
||||
/>
|
||||
<input
|
||||
style={{width: '425px'}}
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='desc'
|
||||
ref='desc'
|
||||
placeholder={Utils.localizeMessage('admin.compliance_reports.desc_placeholder', 'Ex "Audit 445 for HR"')}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.from'
|
||||
defaultMessage='From:'
|
||||
/>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='from'
|
||||
ref='from'
|
||||
placeholder={Utils.localizeMessage('admin.compliance_reports.from_placeholder', 'Ex "2016-03-11"')}
|
||||
/>
|
||||
</td>
|
||||
<td style={{paddingLeft: '4px'}}>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.to'
|
||||
defaultMessage='To:'
|
||||
/>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='to'
|
||||
ref='to'
|
||||
placeholder={Utils.localizeMessage('admin.compliance_reports.to_placeholder', 'Ex "2016-03-15"')}
|
||||
/>
|
||||
</td>
|
||||
<td style={{paddingLeft: '4px'}}>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.emails'
|
||||
defaultMessage='Emails:'
|
||||
/>
|
||||
<input
|
||||
style={{width: '325px'}}
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='emails'
|
||||
ref='emails'
|
||||
placeholder={Utils.localizeMessage('admin.compliance_reports.emails_placeholder', 'Ex "bill@example.com, bob@example.com"')}
|
||||
/>
|
||||
</td>
|
||||
<td style={{paddingLeft: '4px'}}>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.keywords'
|
||||
defaultMessage='Keywords:'
|
||||
/>
|
||||
<input
|
||||
style={{width: '250px'}}
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='keywords'
|
||||
ref='keywords'
|
||||
placeholder={Utils.localizeMessage('admin.compliance_reports.keywords_placeholder', 'Ex "shorting stock"')}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
id='run-button'
|
||||
type='submit'
|
||||
className='btn btn-primary'
|
||||
onClick={this.runReport}
|
||||
style={{marginTop: '20px', marginLeft: '20px'}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.run'
|
||||
defaultMessage='Run'
|
||||
/>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{serverError}
|
||||
<div style={{marginTop: '20px'}}>
|
||||
<button
|
||||
type='submit'
|
||||
className='btn btn-primary'
|
||||
onClick={this.reload}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.compliance_reports.reload'
|
||||
defaultMessage='Reload'
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div className='compliance__panel'>
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
271
web/react/components/admin_console/compliance_settings.jsx
Обычный файл
271
web/react/components/admin_console/compliance_settings.jsx
Обычный файл
@@ -0,0 +1,271 @@
|
||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import * as Client from '../../utils/client.jsx';
|
||||
import * as AsyncClient from '../../utils/async_client.jsx';
|
||||
|
||||
import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
|
||||
|
||||
var holders = defineMessages({
|
||||
saving: {
|
||||
id: 'admin.compliance.saving',
|
||||
defaultMessage: 'Saving Config...'
|
||||
},
|
||||
directoryExample: {
|
||||
id: 'admin.compliance.directoryExample',
|
||||
defaultMessage: 'Ex "./data/"'
|
||||
}
|
||||
});
|
||||
|
||||
class ComplianceSettings extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleEnable = this.handleEnable.bind(this);
|
||||
this.handleDisable = this.handleDisable.bind(this);
|
||||
|
||||
this.state = {
|
||||
saveNeeded: false,
|
||||
serverError: null,
|
||||
enable: this.props.config.ComplianceSettings.Enable
|
||||
};
|
||||
}
|
||||
handleChange() {
|
||||
this.setState({saveNeeded: true});
|
||||
}
|
||||
handleEnable() {
|
||||
this.setState({saveNeeded: true, enable: true});
|
||||
}
|
||||
handleDisable() {
|
||||
this.setState({saveNeeded: true, enable: false});
|
||||
}
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
$('#save-button').button('loading');
|
||||
|
||||
const config = this.props.config;
|
||||
config.ComplianceSettings.Enable = this.refs.Enable.checked;
|
||||
config.ComplianceSettings.Directory = ReactDOM.findDOMNode(this.refs.Directory).value;
|
||||
config.ComplianceSettings.EnableDaily = this.refs.EnableDaily.checked;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
() => {
|
||||
AsyncClient.getConfig();
|
||||
this.setState({
|
||||
serverError: null,
|
||||
saveNeeded: false
|
||||
});
|
||||
$('#save-button').button('reset');
|
||||
},
|
||||
(err) => {
|
||||
this.setState({
|
||||
serverError: err.message,
|
||||
saveNeeded: true
|
||||
});
|
||||
$('#save-button').button('reset');
|
||||
}
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
let serverError = '';
|
||||
if (this.state.serverError) {
|
||||
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
|
||||
}
|
||||
|
||||
let saveClass = 'btn';
|
||||
if (this.state.saveNeeded) {
|
||||
saveClass = 'btn btn-primary';
|
||||
}
|
||||
|
||||
const licenseEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.Compliance === 'true';
|
||||
|
||||
let bannerContent;
|
||||
if (!licenseEnabled) {
|
||||
bannerContent = (
|
||||
<div className='banner warning'>
|
||||
<div className='banner__content'>
|
||||
<FormattedHTMLMessage
|
||||
id='admin.compliance.noLicense'
|
||||
defaultMessage='<h4 class="banner__heading">Note:</h4><p>Compliance is an enterprise feature. Your current license does not support Compliance. Click <a href="http://mattermost.com"target="_blank">here</a> for information and pricing on enterprise licenses.</p>'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='wrapper--fixed'>
|
||||
{bannerContent}
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.title'
|
||||
defaultMessage='Compliance Settings'
|
||||
/>
|
||||
</h3>
|
||||
<form
|
||||
className='form-horizontal'
|
||||
role='form'
|
||||
>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='Enable'
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.enableTitle'
|
||||
defaultMessage='Enable Compliance:'
|
||||
/>
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='Enable'
|
||||
value='true'
|
||||
ref='Enable'
|
||||
defaultChecked={this.props.config.ComplianceSettings.Enable}
|
||||
onChange={this.handleEnable}
|
||||
disabled={!licenseEnabled}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.true'
|
||||
defaultMessage='true'
|
||||
/>
|
||||
</label>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='Enable'
|
||||
value='false'
|
||||
defaultChecked={!this.props.config.ComplianceSettings.Enable}
|
||||
onChange={this.handleDisable}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.false'
|
||||
defaultMessage='false'
|
||||
/>
|
||||
</label>
|
||||
<p className='help-text'>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.enableDesc'
|
||||
defaultMessage='When true, Mattermost allows compliance reporting'
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='Directory'
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.directoryTitle'
|
||||
defaultMessage='Compliance Directory Location:'
|
||||
/>
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='Directory'
|
||||
ref='Directory'
|
||||
placeholder={formatMessage(holders.directoryExample)}
|
||||
defaultValue={this.props.config.ComplianceSettings.Directory}
|
||||
onChange={this.handleChange}
|
||||
disabled={!this.state.enable}
|
||||
/>
|
||||
<p className='help-text'>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.directoryDescription'
|
||||
defaultMessage='Directory to which compliance reports are written. If blank, will be set to ./data/.'
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='EnableDaily'
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.enableDailyTitle'
|
||||
defaultMessage='Enable Daily Report:'
|
||||
/>
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnableDaily'
|
||||
value='true'
|
||||
ref='EnableDaily'
|
||||
defaultChecked={this.props.config.ComplianceSettings.EnableDaily}
|
||||
onChange={this.handleChange}
|
||||
disabled={!this.state.enable}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.true'
|
||||
defaultMessage='true'
|
||||
/>
|
||||
</label>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnableDaily'
|
||||
value='false'
|
||||
defaultChecked={!this.props.config.ComplianceSettings.EnableDaily}
|
||||
disabled={!this.state.enable}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.false'
|
||||
defaultMessage='false'
|
||||
/>
|
||||
</label>
|
||||
<p className='help-text'>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.enableDesc'
|
||||
defaultMessage='When true, Mattermost will generate a daily compliance report.'
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<div className='col-sm-12'>
|
||||
{serverError}
|
||||
<button
|
||||
disabled={!this.state.saveNeeded}
|
||||
type='submit'
|
||||
className={saveClass}
|
||||
onClick={this.handleSubmit}
|
||||
id='save-button'
|
||||
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='admin.compliance.save'
|
||||
defaultMessage='Save'
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
ComplianceSettings.defaultProps = {
|
||||
};
|
||||
|
||||
ComplianceSettings.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
config: React.PropTypes.object
|
||||
};
|
||||
|
||||
export default injectIntl(ComplianceSettings);
|
||||
@@ -217,7 +217,12 @@ class AuditTable extends React.Component {
|
||||
|
||||
let uContent;
|
||||
if (this.props.showUserId) {
|
||||
uContent = <td>{auditInfo.userId}</td>;
|
||||
var profile = UserStore.getProfile(auditInfo.userId);
|
||||
if (profile) {
|
||||
uContent = <td>{profile.email}</td>;
|
||||
} else {
|
||||
uContent = <td>{auditInfo.userId}</td>;
|
||||
}
|
||||
}
|
||||
|
||||
let iContent;
|
||||
@@ -560,6 +565,8 @@ export function formatAuditInfo(audit, formatMessage) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (actionURL.indexOf('/admin/download_compliance_report') === 0) {
|
||||
auditDesc = Utils.toTitleCase(audit.extra_info);
|
||||
} else {
|
||||
switch (actionURL) {
|
||||
case '/logout':
|
||||
|
||||
@@ -13,6 +13,7 @@ const LOG_CHANGE_EVENT = 'log_change';
|
||||
const SERVER_AUDIT_CHANGE_EVENT = 'server_audit_change';
|
||||
const CONFIG_CHANGE_EVENT = 'config_change';
|
||||
const ALL_TEAMS_EVENT = 'all_team_change';
|
||||
const SERVER_COMPLIANCE_REPORT_CHANGE_EVENT = 'server_compliance_reports_change';
|
||||
|
||||
class AdminStoreClass extends EventEmitter {
|
||||
constructor() {
|
||||
@@ -22,6 +23,7 @@ class AdminStoreClass extends EventEmitter {
|
||||
this.audits = null;
|
||||
this.config = null;
|
||||
this.teams = null;
|
||||
this.complianceReports = null;
|
||||
|
||||
this.emitLogChange = this.emitLogChange.bind(this);
|
||||
this.addLogChangeListener = this.addLogChangeListener.bind(this);
|
||||
@@ -31,6 +33,10 @@ class AdminStoreClass extends EventEmitter {
|
||||
this.addAuditChangeListener = this.addAuditChangeListener.bind(this);
|
||||
this.removeAuditChangeListener = this.removeAuditChangeListener.bind(this);
|
||||
|
||||
this.emitComplianceReportsChange = this.emitComplianceReportsChange.bind(this);
|
||||
this.addComplianceReportsChangeListener = this.addComplianceReportsChangeListener.bind(this);
|
||||
this.removeComplianceReportsChangeListener = this.removeComplianceReportsChangeListener.bind(this);
|
||||
|
||||
this.emitConfigChange = this.emitConfigChange.bind(this);
|
||||
this.addConfigChangeListener = this.addConfigChangeListener.bind(this);
|
||||
this.removeConfigChangeListener = this.removeConfigChangeListener.bind(this);
|
||||
@@ -64,6 +70,18 @@ class AdminStoreClass extends EventEmitter {
|
||||
this.removeListener(SERVER_AUDIT_CHANGE_EVENT, callback);
|
||||
}
|
||||
|
||||
emitComplianceReportsChange() {
|
||||
this.emit(SERVER_COMPLIANCE_REPORT_CHANGE_EVENT);
|
||||
}
|
||||
|
||||
addComplianceReportsChangeListener(callback) {
|
||||
this.on(SERVER_COMPLIANCE_REPORT_CHANGE_EVENT, callback);
|
||||
}
|
||||
|
||||
removeComplianceReportsChangeListener(callback) {
|
||||
this.removeListener(SERVER_COMPLIANCE_REPORT_CHANGE_EVENT, callback);
|
||||
}
|
||||
|
||||
emitConfigChange() {
|
||||
this.emit(CONFIG_CHANGE_EVENT);
|
||||
}
|
||||
@@ -104,6 +122,14 @@ class AdminStoreClass extends EventEmitter {
|
||||
this.audits = audits;
|
||||
}
|
||||
|
||||
getComplianceReports() {
|
||||
return this.complianceReports;
|
||||
}
|
||||
|
||||
saveComplianceReports(complianceReports) {
|
||||
this.complianceReports = complianceReports;
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
@@ -147,6 +173,10 @@ AdminStoreClass.dispatchToken = AppDispatcher.register((payload) => {
|
||||
AdminStore.saveAudits(action.audits);
|
||||
AdminStore.emitAuditChange();
|
||||
break;
|
||||
case ActionTypes.RECEIVED_SERVER_COMPLIANCE_REPORTS:
|
||||
AdminStore.saveComplianceReports(action.complianceReports);
|
||||
AdminStore.emitComplianceReportsChange();
|
||||
break;
|
||||
case ActionTypes.RECEIVED_CONFIG:
|
||||
AdminStore.saveConfig(action.config);
|
||||
AdminStore.emitConfigChange();
|
||||
|
||||
@@ -341,6 +341,32 @@ export function getServerAudits() {
|
||||
);
|
||||
}
|
||||
|
||||
export function getComplianceReports() {
|
||||
if (isCallInProgress('getComplianceReports')) {
|
||||
return;
|
||||
}
|
||||
|
||||
callTracker.getComplianceReports = utils.getTimestamp();
|
||||
client.getComplianceReports(
|
||||
(data, textStatus, xhr) => {
|
||||
callTracker.getComplianceReports = 0;
|
||||
|
||||
if (xhr.status === 304 || !data) {
|
||||
return;
|
||||
}
|
||||
|
||||
AppDispatcher.handleServerAction({
|
||||
type: ActionTypes.RECEIVED_SERVER_COMPLIANCE_REPORTS,
|
||||
complianceReports: data
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
callTracker.getComplianceReports = 0;
|
||||
dispatchError(err, 'getComplianceReports');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function getConfig() {
|
||||
if (isCallInProgress('getConfig')) {
|
||||
return;
|
||||
|
||||
@@ -412,6 +412,35 @@ export function getAudits(userId, success, error) {
|
||||
});
|
||||
}
|
||||
|
||||
export function getComplianceReports(success, error) {
|
||||
$.ajax({
|
||||
url: '/api/v1/admin/compliance_reports',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'GET',
|
||||
success,
|
||||
error: function onError(xhr, status, err) {
|
||||
var e = handleError('getComplianceReports', xhr, status, err);
|
||||
error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function saveComplianceReports(job, success, error) {
|
||||
$.ajax({
|
||||
url: '/api/v1/admin/save_compliance_report',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
type: 'POST',
|
||||
data: JSON.stringify(job),
|
||||
success,
|
||||
error: (xhr, status, err) => {
|
||||
var e = handleError('saveComplianceReports', xhr, status, err);
|
||||
error(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function getLogs(success, error) {
|
||||
$.ajax({
|
||||
url: '/api/v1/admin/logs',
|
||||
|
||||
@@ -47,6 +47,7 @@ export default {
|
||||
RECEIVED_CONFIG: null,
|
||||
RECEIVED_LOGS: null,
|
||||
RECEIVED_SERVER_AUDITS: null,
|
||||
RECEIVED_SERVER_COMPLIANCE_REPORTS: null,
|
||||
RECEIVED_ALL_TEAMS: null,
|
||||
|
||||
RECEIVED_LOCALE: null,
|
||||
|
||||
Ссылка в новой задаче
Block a user