Skip to content

Commit

Permalink
SAML support (mattermost#3494)
Browse files Browse the repository at this point in the history
* PLT-3073: Implement SAML/Okta Server side (EE) (mattermost#3422)

* PLT-3137 Support for SAML configuration

* PLT-3410 SAML Database Store

* PLT-3411 CLI to add Identity Provider Certificate and Service Provider Private Key

* PLT-3409 SAML Interface for EE

* PLT-3139 Handle SAML authentication server side

* Add localization messages

* PLT-3443 SAML Obtain SP metadata

* PLT-3142 Login & Switch to/from SAML

* Remove Certs for Database & Clean SAML Request

* Make required Username, FirstName and LastName

* PLT-3140 Add SAML to System Console (mattermost#3476)

* PLT-3140 Add SAML to System Console

* Move web_client functions to client.jsx

* Fix issues found by PM

* update package.json mattermost driver

* Fix text messages for SAML
  • Loading branch information
enahum committed Jul 5, 2016
1 parent c1953d9 commit bd3b647
Show file tree
Hide file tree
Showing 17 changed files with 914 additions and 9 deletions.
16 changes: 16 additions & 0 deletions components/admin_console/admin_sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export default class AdminSidebar extends React.Component {

render() {
let ldapSettings = null;
let samlSettings = null;
let complianceSettings = null;

let license = null;
Expand All @@ -198,6 +199,20 @@ export default class AdminSidebar extends React.Component {
);
}

if (global.window.mm_license.SAML === 'true') {
samlSettings = (
<AdminSidebarSection
name='saml'
title={
<FormattedMessage
id='admin.sidebar.saml'
defaultMessage='SAML'
/>
}
/>
);
}

if (global.window.mm_license.Compliance === 'true') {
complianceSettings = (
<AdminSidebarSection
Expand Down Expand Up @@ -391,6 +406,7 @@ export default class AdminSidebar extends React.Component {
}
/>
{ldapSettings}
{samlSettings}
</AdminSidebarSection>
<AdminSidebarSection
name='security'
Expand Down
124 changes: 124 additions & 0 deletions components/admin_console/file_upload_setting.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

import $ from 'jquery';
import React from 'react';
import {FormattedMessage} from 'react-intl';

import Setting from './setting.jsx';

import * as Utils from 'utils/utils.jsx';

export default class FileUploadSetting extends Setting {
static get propTypes() {
return {
id: React.PropTypes.string.isRequired,
label: React.PropTypes.node.isRequired,
helpText: React.PropTypes.node,
uploadingText: React.PropTypes.node,
onSubmit: React.PropTypes.func.isRequired,
disabled: React.PropTypes.bool,
fileType: React.PropTypes.string.isRequired
};
}

constructor(props) {
super(props);

this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);

this.state = {
fileName: null
};
}

handleChange() {
const files = this.refs.fileInput.files;
if (files && files.length > 0) {
this.setState({fileSelected: true, fileName: files[0].name});
}
}

handleSubmit(e) {
e.preventDefault();

$(this.refs.upload_button).button('loading');
this.props.onSubmit(this.props.id, this.refs.fileInput.files[0], (error) => {
$(this.refs.upload_button).button('reset');
if (error) {
Utils.clearFileInput(this.refs.fileInput);
}
this.setState({fileSelected: false, fileName: null, serverError: error});
});
}

render() {
let serverError;
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
}

var btnClass = 'btn';
if (this.state.fileSelected) {
btnClass = 'btn btn-primary';
}

let fileName;
if (this.state.fileName) {
fileName = this.state.fileName;
} else {
fileName = (
<FormattedMessage
id='admin.file_upload.noFile'
defaultMessage='No file uploaded'
/>
);
}

return (
<Setting
label={this.props.label}
helpText={this.props.helpText}
inputId={this.props.id}
>
<div>
<div className='file__upload'>
<button
className='btn btn-default'
disabled={this.props.disabled}
>
<FormattedMessage
id='admin.file_upload.chooseFile'
defaultMessage='Choose File'
/>
</button>
<input
ref='fileInput'
type='file'
disabled={this.props.disabled}
accept={this.props.fileType}
onChange={this.handleChange}
/>
</div>
<button
className={btnClass}
disabled={!this.state.fileSelected}
onClick={this.handleSubmit}
ref='upload_button'
data-loading-text={`<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ${this.props.uploadingText}`}
>
<FormattedMessage
id='admin.file_upload.uploadFile'
defaultMessage='Upload'
/>
</button>
<div className='help-text no-margin'>
{fileName}
</div>
{serverError}
</div>
</Setting>
);
}
}
72 changes: 72 additions & 0 deletions components/admin_console/remove_file_setting.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

import $ from 'jquery';
import React from 'react';

import Setting from './setting.jsx';

export default class RemoveFileSetting extends Setting {
static get propTypes() {
return {
id: React.PropTypes.string.isRequired,
label: React.PropTypes.node.isRequired,
helpText: React.PropTypes.node,
removeButtonText: React.PropTypes.node.isRequired,
removingText: React.PropTypes.node,
fileName: React.PropTypes.string.isRequired,
onSubmit: React.PropTypes.func.isRequired,
disabled: React.PropTypes.bool
};
}

constructor(props) {
super(props);
this.handleRemove = this.handleRemove.bind(this);

this.state = {
serverError: null
};
}

handleRemove(e) {
e.preventDefault();

$(this.refs.remove_button).button('loading');
this.props.onSubmit(this.props.id, (error) => {
$(this.refs.remove_button).button('reset');
this.setState({serverError: error});
});
}

render() {
let serverError;
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
}

return (
<Setting
label={this.props.label}
helpText={this.props.helpText}
inputId={this.props.id}
>
<div>
<div className='help-text remove-filename'>
{this.props.fileName}
</div>
<button
className='btn btn-danger'
onClick={this.handleRemove}
ref='remove_button'
disabled={this.props.disabled}
data-loading-text={`<span class='glyphicon glyphicon-refresh glyphicon-refresh-animate'></span> ${this.props.removingText}`}
>
{this.props.removeButtonText}
</button>
{serverError}
</div>
</Setting>
);
}
}
Loading

0 comments on commit bd3b647

Please sign in to comment.