diff options
Diffstat (limited to 'webapp/components/integrations/components/add_oauth_app/add_oauth_app.jsx')
-rw-r--r-- | webapp/components/integrations/components/add_oauth_app/add_oauth_app.jsx | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/webapp/components/integrations/components/add_oauth_app/add_oauth_app.jsx b/webapp/components/integrations/components/add_oauth_app/add_oauth_app.jsx new file mode 100644 index 000000000..cad3244e3 --- /dev/null +++ b/webapp/components/integrations/components/add_oauth_app/add_oauth_app.jsx @@ -0,0 +1,441 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React from 'react'; +import PropTypes from 'prop-types'; + +import BackstageHeader from 'components/backstage/components/backstage_header.jsx'; +import {FormattedMessage} from 'react-intl'; +import FormError from 'components/form_error.jsx'; +import {browserHistory, Link} from 'react-router/es6'; +import SpinnerButton from 'components/spinner_button.jsx'; + +export default class AddOAuthApp extends React.PureComponent { + static propTypes = { + + /** + * The team data + */ + team: PropTypes.object, + + /** + * The request state for addOAuthApp action. Contains status and error + */ + addOAuthAppRequest: PropTypes.object.isRequired, + + actions: PropTypes.shape({ + + /** + * The function to call to add new OAuthApp + */ + addOAuthApp: PropTypes.func.isRequired + }).isRequired + } + + constructor(props) { + super(props); + + this.image = new Image(); + this.image.onload = this.imageLoaded; + + this.state = { + name: '', + description: '', + homepage: '', + icon_url: '', + callbackUrls: '', + is_trusted: false, + has_icon: false, + saving: false, + serverError: '', + clientError: null + }; + } + + imageLoaded = () => { + this.setState({ + has_icon: true, + icon_url: this.refs.icon_url.value + }); + } + + handleSubmit = (e) => { + e.preventDefault(); + + if (this.state.saving) { + return; + } + + this.setState({ + saving: true, + serverError: '', + clientError: '' + }); + + if (!this.state.name) { + this.setState({ + saving: false, + clientError: ( + <FormattedMessage + id='add_oauth_app.nameRequired' + defaultMessage='Name for the OAuth 2.0 application is required.' + /> + ) + }); + + return; + } + + if (!this.state.description) { + this.setState({ + saving: false, + clientError: ( + <FormattedMessage + id='add_oauth_app.descriptionRequired' + defaultMessage='Description for the OAuth 2.0 application is required.' + /> + ) + }); + + return; + } + + if (!this.state.homepage) { + this.setState({ + saving: false, + clientError: ( + <FormattedMessage + id='add_oauth_app.homepageRequired' + defaultMessage='Homepage for the OAuth 2.0 application is required.' + /> + ) + }); + + return; + } + + const callbackUrls = []; + for (let callbackUrl of this.state.callbackUrls.split('\n')) { + callbackUrl = callbackUrl.trim(); + + if (callbackUrl.length > 0) { + callbackUrls.push(callbackUrl); + } + } + + if (callbackUrls.length === 0) { + this.setState({ + saving: false, + clientError: ( + <FormattedMessage + id='add_oauth_app.callbackUrlsRequired' + defaultMessage='One or more callback URLs are required.' + /> + ) + }); + + return; + } + + const app = { + name: this.state.name, + callback_urls: callbackUrls, + homepage: this.state.homepage, + description: this.state.description, + is_trusted: this.state.is_trusted, + icon_url: this.state.icon_url + }; + + this.props.actions.addOAuthApp(app).then( + (data) => { + const {error} = this.props.addOAuthAppRequest; + if (error) { + this.setState({ + saving: false, + serverError: error.message + }); + } else { + browserHistory. + push(`/${this.props.team.name}/integrations/confirm?type=oauth2-apps&id=${data.id}`); + } + } + ); + } + + updateName = (e) => { + this.setState({ + name: e.target.value + }); + } + + updateTrusted = (e) => { + this.setState({ + is_trusted: e.target.value === 'true' + }); + } + + updateDescription = (e) => { + this.setState({ + description: e.target.value + }); + } + + updateHomepage = (e) => { + this.setState({ + homepage: e.target.value + }); + } + + updateIconUrl = (e) => { + this.setState({ + has_icon: false, + icon_url: '' + }); + this.image.src = e.target.value; + } + + updateCallbackUrls = (e) => { + this.setState({ + callbackUrls: e.target.value + }); + } + + render() { + let icon; + if (this.state.has_icon) { + icon = ( + <div className='integration__icon'> + <img src={this.state.icon_url}/> + </div> + ); + } + + return ( + <div className='backstage-content'> + <BackstageHeader> + <Link to={`/${this.props.team.name}/integrations/oauth2-apps`}> + <FormattedMessage + id='installed_oauth_apps.header' + defaultMessage='Installed OAuth2 Apps' + /> + </Link> + <FormattedMessage + id='add_oauth_app.header' + defaultMessage='Add' + /> + </BackstageHeader> + <div className='backstage-form'> + {icon} + <form className='form-horizontal'> + <div className='form-group'> + <label + className='control-label col-sm-4' + htmlFor='is_trusted' + > + <FormattedMessage + id='installed_oauth_apps.trusted' + defaultMessage='Is Trusted' + /> + </label> + <div className='col-md-5 col-sm-8'> + <label className='radio-inline'> + <input + type='radio' + value='true' + name='is_trusted' + checked={this.state.is_trusted} + onChange={this.updateTrusted} + /> + <FormattedMessage + id='installed_oauth_apps.trusted.yes' + defaultMessage='Yes' + /> + </label> + <label className='radio-inline'> + <input + type='radio' + value='false' + name='is_trusted' + checked={!this.state.is_trusted} + onChange={this.updateTrusted} + /> + <FormattedMessage + id='installed_oauth_apps.trusted.no' + defaultMessage='No' + /> + </label> + <div className='form__help'> + <FormattedMessage + id='add_oauth_app.trusted.help' + defaultMessage="When true, the OAuth 2.0 application is considered trusted by the Mattermost server and doesn't require the user to accept authorization. When false, an additional window will appear, asking the user to accept or deny the authorization." + /> + </div> + </div> + </div> + <div className='form-group'> + <label + className='control-label col-sm-4' + htmlFor='name' + > + <FormattedMessage + id='installed_oauth_apps.name' + defaultMessage='Display Name' + /> + </label> + <div className='col-md-5 col-sm-8'> + <input + id='name' + type='text' + maxLength='64' + className='form-control' + value={this.state.name} + onChange={this.updateName} + /> + <div className='form__help'> + <FormattedMessage + id='add_oauth_app.name.help' + defaultMessage='Display name for your OAuth 2.0 application made of up to 64 characters.' + /> + </div> + </div> + </div> + <div className='form-group'> + <label + className='control-label col-sm-4' + htmlFor='description' + > + <FormattedMessage + id='installed_oauth_apps.description' + defaultMessage='Description' + /> + </label> + <div className='col-md-5 col-sm-8'> + <input + id='description' + type='text' + maxLength='512' + className='form-control' + value={this.state.description} + onChange={this.updateDescription} + /> + <div className='form__help'> + <FormattedMessage + id='add_oauth_app.description.help' + defaultMessage='Description for your OAuth 2.0 application.' + /> + </div> + </div> + </div> + <div className='form-group'> + <label + className='control-label col-sm-4' + htmlFor='homepage' + > + <FormattedMessage + id='installed_oauth_apps.homepage' + defaultMessage='Homepage' + /> + </label> + <div className='col-md-5 col-sm-8'> + <input + id='homepage' + type='url' + maxLength='256' + className='form-control' + value={this.state.homepage} + onChange={this.updateHomepage} + /> + <div className='form__help'> + <FormattedMessage + id='add_oauth_app.homepage.help' + defaultMessage='The URL for the homepage of the OAuth 2.0 application. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.' + /> + </div> + </div> + </div> + <div className='form-group'> + <label + className='control-label col-sm-4' + htmlFor='icon_url' + > + <FormattedMessage + id='installed_oauth_apps.iconUrl' + defaultMessage='Icon URL' + /> + </label> + <div className='col-md-5 col-sm-8'> + <input + id='icon_url' + ref='icon_url' + type='url' + maxLength='512' + className='form-control' + onChange={this.updateIconUrl} + /> + <div className='form__help'> + <FormattedMessage + id='add_oauth_app.icon.help' + defaultMessage='The URL for the homepage of the OAuth 2.0 application. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.' + /> + </div> + </div> + </div> + <div className='form-group'> + <label + className='control-label col-sm-4' + htmlFor='callbackUrls' + > + <FormattedMessage + id='installed_oauth_apps.callbackUrls' + defaultMessage='Callback URLs (One Per Line)' + /> + </label> + <div className='col-md-5 col-sm-8'> + <textarea + id='callbackUrls' + rows='3' + maxLength='1024' + className='form-control' + value={this.state.callbackUrls} + onChange={this.updateCallbackUrls} + /> + <div className='form__help'> + <FormattedMessage + id='add_oauth_app.callbackUrls.help' + defaultMessage='The redirect URIs to which the service will redirect users after accepting or denying authorization of your application, and which will handle authorization codes or access tokens. Must be a valid URL and start with http:// or https://.' + /> + </div> + </div> + </div> + <div className='backstage-form__footer'> + <FormError + type='backstage' + errors={[this.state.serverError, this.state.clientError]} + /> + <Link + className='btn btn-sm' + to={`/${this.props.team.name}/integrations/oauth2-apps`} + > + <FormattedMessage + id='installed_oauth_apps.cancel' + defaultMessage='Cancel' + /> + </Link> + <SpinnerButton + className='btn btn-primary' + type='submit' + spinning={this.state.saving} + onClick={this.handleSubmit} + > + <FormattedMessage + id='installed_oauth_apps.save' + defaultMessage='Save' + /> + </SpinnerButton> + </div> + </form> + </div> + </div> + ); + } +} |