forked from p15670423/monkey
Merge pull request #1189 from guardicore/config_export_popup
Config export modal
This commit is contained in:
commit
badcd0e87c
|
@ -0,0 +1,115 @@
|
|||
import {Button, Modal, Form} from 'react-bootstrap';
|
||||
import React, {useState} from 'react';
|
||||
|
||||
import AuthComponent from '../AuthComponent';
|
||||
import '../../styles/components/configuration-components/ExportConfigModal.scss';
|
||||
|
||||
|
||||
type Props = {
|
||||
show: boolean,
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
const ConfigExportModal = (props: Props) => {
|
||||
// TODO implement the back end
|
||||
const configExportEndpoint = '/api/configuration/export';
|
||||
|
||||
const [pass, setPass] = useState('');
|
||||
const [radioValue, setRadioValue] = useState('password');
|
||||
const authComponent = new AuthComponent({});
|
||||
|
||||
function isExportBtnDisabled() {
|
||||
return pass === '' && radioValue === 'password';
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
authComponent.authFetch(configExportEndpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
should_encrypt: (radioValue === 'password'),
|
||||
password: pass
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal show={props.show}
|
||||
onHide={props.onClick}
|
||||
size={'lg'}
|
||||
className={'config-export-modal'}>
|
||||
<Modal.Header closeButton>
|
||||
<Modal.Title>Configuration export</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<div key={'config-export-option'}
|
||||
className={`mb-3 export-type-radio-buttons`}>
|
||||
<Form>
|
||||
<Form.Check
|
||||
type={'radio'}
|
||||
className={'password-radio-button'}
|
||||
label={<PasswordInput onChange={setPass}/>}
|
||||
name={'export-choice'}
|
||||
value={'password'}
|
||||
onChange={evt => {
|
||||
setRadioValue(evt.target.value)
|
||||
}}
|
||||
checked={radioValue === 'password'}
|
||||
/>
|
||||
<ExportPlaintextChoiceField onChange={setRadioValue}
|
||||
radioValue={radioValue}/>
|
||||
</Form>
|
||||
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button variant={'info'}
|
||||
onClick={onSubmit}
|
||||
disabled={isExportBtnDisabled()}>
|
||||
Export
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>)
|
||||
}
|
||||
|
||||
const PasswordInput = (props: {
|
||||
onChange: (passValue) => void
|
||||
}) => {
|
||||
return (
|
||||
<div className={'config-export-password-input'}>
|
||||
<p>Encrypt with a password:</p>
|
||||
<Form.Control type='password'
|
||||
placeholder='Password'
|
||||
onChange={evt => (props.onChange(evt.target.value))}/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ExportPlaintextChoiceField = (props: {
|
||||
radioValue: string,
|
||||
onChange: (radioValue) => void
|
||||
}) => {
|
||||
return (
|
||||
<div className={'config-export-plaintext'}>
|
||||
<Form.Check
|
||||
type={'radio'}
|
||||
label={'Skip encryption (export as plaintext)'}
|
||||
name={'export-choice'}
|
||||
value={'plaintext'}
|
||||
checked={props.radioValue === 'plaintext'}
|
||||
onChange={evt => {
|
||||
props.onChange(evt.target.value);
|
||||
}}
|
||||
/>
|
||||
<p className={`export-warning text-secondary`}>
|
||||
Configuration may contain stolen credentials or sensitive data.<br/>
|
||||
It is advised to use password encryption.
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default ConfigExportModal;
|
|
@ -14,6 +14,7 @@ import InternalConfig from '../configuration-components/InternalConfig';
|
|||
import UnsafeOptionsConfirmationModal from '../configuration-components/UnsafeOptionsConfirmationModal.js';
|
||||
import UnsafeOptionsWarningModal from '../configuration-components/UnsafeOptionsWarningModal.js';
|
||||
import isUnsafeOptionSelected from '../utils/SafeOptionValidator.js';
|
||||
import ConfigExportModal from '../configuration-components/ExportConfigModal';
|
||||
|
||||
const ATTACK_URL = '/api/attack';
|
||||
const CONFIG_URL = '/api/configuration/island';
|
||||
|
@ -40,7 +41,8 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
selectedSection: 'attack',
|
||||
showAttackAlert: false,
|
||||
showUnsafeOptionsConfirmation: false,
|
||||
showUnsafeAttackOptionsWarning: false
|
||||
showUnsafeAttackOptionsWarning: false,
|
||||
showConfigExportModal: false
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -220,6 +222,14 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
this.setState({configuration: newConfig, lastAction: 'none'});
|
||||
};
|
||||
|
||||
renderConfigExportModal = () => {
|
||||
return (<ConfigExportModal show={this.state.showConfigExportModal}
|
||||
onClick={this.onExport} />)}
|
||||
|
||||
onExport = () => {
|
||||
this.setState({showConfigExportModal: false})
|
||||
}
|
||||
|
||||
renderAttackAlertModal = () => {
|
||||
return (<Modal show={this.state.showAttackAlert} onHide={() => {
|
||||
this.setState({showAttackAlert: false})
|
||||
|
@ -488,6 +498,7 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
<Col sm={{offset: 3, span: 9}} md={{offset: 3, span: 9}}
|
||||
lg={{offset: 3, span: 8}} xl={{offset: 2, span: 8}}
|
||||
className={'main'}>
|
||||
{this.renderConfigExportModal()}
|
||||
{this.renderAttackAlertModal()}
|
||||
{this.renderUnsafeOptionsConfirmationModal()}
|
||||
{this.renderUnsafeAttackOptionsWarningModal()}
|
||||
|
@ -509,7 +520,9 @@ class ConfigurePageComponent extends AuthComponent {
|
|||
</button>
|
||||
<input id='uploadInputInternal' type='file' accept='.conf' onChange={this.importConfig}
|
||||
style={{display: 'none'}}/>
|
||||
<button type='button' onClick={this.exportConfig} className='btn btn-info btn-lg' style={{margin: '5px'}}>
|
||||
<button type='button'
|
||||
onClick={() => {this.setState({showConfigExportModal: true})}}
|
||||
className='btn btn-info btn-lg' style={{margin: '5px'}}>
|
||||
Export config
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
.config-export-modal .config-export-password-input p {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.config-export-modal .export-type-radio-buttons
|
||||
.password-radio-button .config-export-password-input input {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
top: 0;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.config-export-modal .export-type-radio-buttons .password-radio-button input{
|
||||
margin-top: 0;
|
||||
top: 50%;
|
||||
-ms-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.config-export-modal div.config-export-plaintext p.export-warning {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.config-export-modal div.config-export-plaintext {
|
||||
margin-top: 15px;
|
||||
}
|
Loading…
Reference in New Issue