app/addons/replication/components/auth-options.js (151 lines of code) (raw):

// Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. import PropTypes from 'prop-types'; import FauxtonAPI from '../../../core/api'; import app from '../../../app'; import React from 'react'; import Constants from '../constants'; import Form from 'react-bootstrap/Form'; export class ReplicationAuth extends React.Component { constructor (props) { super(props); this.onChangeType = this.onChangeType.bind(this); this.onChangeValue = this.onChangeValue.bind(this); // init auth extensions // The extension should provide: // - 'inputComponent' a React component that will be displayed when the user selects the auth method. // - 'typeValue' field with an arbitrary ID representing the auth type the extension supports. // - 'typeLabel' field containing the display label for the authentication method. this.customAuths = FauxtonAPI.getExtensions('Replication:Auth'); if (!this.customAuths) { this.customAuths = []; } this.customAuthTypes = this.customAuths.map(auth => auth.typeValue); // The extension should provide: // - 'authType' is a string representing the auth type. // - 'helpText' string with the text to be displayed when the auth type is selected. this.customAuthHelp = FauxtonAPI.getExtensions('Replication:Auth-help'); if (!this.customAuthHelp) { this.customAuthHelp = []; } } getAuthOptions = () => { const userPasswordLabel = app.i18n.en_US['replication-user-password-auth-label']; const authOptions = [ { value: Constants.REPLICATION_AUTH_METHOD.NO_AUTH, label: 'None' }, { value: Constants.REPLICATION_AUTH_METHOD.BASIC, label: userPasswordLabel } ]; this.customAuths.map(auth => { authOptions.push({ value: auth.typeValue, label: auth.typeLabel }); }); return authOptions.map(option => <option value={option.value} key={option.value}>{option.label}</option>); }; onChangeType(newType) { this.props.onChangeAuthType(newType); } onChangeValue(newValue) { this.props.onChangeAuth(newValue); } getAuthInputFields(authValue, authType) { const {authId} = this.props; if (authType == Constants.REPLICATION_AUTH_METHOD.BASIC) { return <UserPasswordAuthInput onChange={this.onChangeValue} auth={authValue} authId={authId}/>; } const matchedAuths = this.customAuths.filter(el => el.typeValue === authType); if (matchedAuths && matchedAuths.length > 0) { const InputComp = matchedAuths[0].inputComponent; return <InputComp onChange={this.onChangeValue} auth={authValue} />; } return null; } getHelpText(authType) { const helpText = this.customAuthHelp.filter(el => authType === el.authType).map(el => el.helpText); if (helpText.length == 0) { return null; } return ( <span id="replications-auth-help-span" className="form-text">{helpText[0]}</span> ); } render () { const {credentials, authType, authId} = this.props; return ( <div className="row"> <div className="col-12 col-md-2">Authentication:</div> <div className="col-12 col-md mt-1 mt-md-0"> <Form.Select onChange={(e) => this.onChangeType(e.target.value)} id={'select-' + authId} value={authType} > {this.getAuthOptions()} </Form.Select> {this.getAuthInputFields(credentials, authType)} {this.getHelpText(authType)} </div> </div> ); } } ReplicationAuth.propTypes = { authId: PropTypes.string.isRequired, authType: PropTypes.string.isRequired, credentials: PropTypes.object, onChangeAuth: PropTypes.func.isRequired, onChangeAuthType: PropTypes.func.isRequired }; ReplicationAuth.defaultProps = { authType: Constants.REPLICATION_AUTH_METHOD.NO_AUTH, onChangeAuthType: () => {}, onChangeAuth: () => {} }; export class UserPasswordAuthInput extends React.Component { constructor (props) { super(props); this.updatePassword = this.updatePassword.bind(this); this.updateUsername = this.updateUsername.bind(this); this.state = { username: props.auth && props.auth.username ? props.auth.username : '', password: props.auth && props.auth.password ? props.auth.password : '' }; } updatePassword(newValue) { this.setState({password: newValue}); this.props.onChange({ username: this.state.username, password: newValue }); } updateUsername(newValue) { this.setState({username: newValue}); this.props.onChange({ username: newValue, password: this.state.password }); } render () { const usernamePlaceholder = app.i18n.en_US['replication-username-input-placeholder']; const passwordPlaceholder = app.i18n.en_US['replication-password-input-placeholder']; const { authId } = this.props; return ( <React.Fragment> <div className="row"> <div className="col-12 mt-2"> <Form.Control id={authId + '-username'} type="text" className="form-control" placeholder={usernamePlaceholder} value={this.state.username} onChange={(e) => this.updateUsername(e.target.value)} /> </div> <div className="col-12 mt-2"> <Form.Control id={authId + '-password'} type="password" className="form-control" placeholder={passwordPlaceholder} value={this.state.password} onChange={(e) => this.updatePassword(e.target.value)} /> </div> </div> </React.Fragment> ); } } UserPasswordAuthInput.propTypes = { auth: PropTypes.object.isRequired, onChange: PropTypes.func.isRequired };