borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
@@ -59,6 +59,21 @@ } } public boolean remove(String idOrName) { if (idOrName == null) { return false; } synchronized (repoConfigs) { for (BorgRepoConfig repoConfig : getAllRepoConfigs()) { if (StringUtils.equals(idOrName, repoConfig.getRepo()) || StringUtils.equals(idOrName, repoConfig.getId())) { repoConfigs.remove(repoConfig); return true; } } } return false; } public BorgRepoConfig getRepoConfig(String idOrName) { if (idOrName == null) { return null; borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java
@@ -35,18 +35,44 @@ @Produces(MediaType.TEXT_PLAIN) public void setRepoConfig(String jsonConfig) { BorgRepoConfig newRepoConfig = JsonUtils.fromJson(BorgRepoConfig.class, jsonConfig); BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(newRepoConfig.getId()); if (repoConfig == null) { log.error("Can't find repo config '" + newRepoConfig.getId() + "'. Can't save new settings."); if (newRepoConfig == null) { log.error("Internal Rest error. Can't parse BorgRepoConfig: " + jsonConfig); return; } ButlerCache.getInstance().clearRepoCacheAccess(repoConfig.getRepo()); ButlerCache.getInstance().clearRepoCacheAccess(newRepoConfig.getRepo()); repoConfig.copyFrom(newRepoConfig); if ("new".equals(newRepoConfig.getId())) { newRepoConfig.setId(null); ConfigurationHandler.getConfiguration().add(newRepoConfig); } else { BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(newRepoConfig.getId()); if (repoConfig == null) { log.error("Can't find repo config '" + newRepoConfig.getId() + "'. Can't save new settings."); return; } ButlerCache.getInstance().clearRepoCacheAccess(repoConfig.getRepo()); ButlerCache.getInstance().clearRepoCacheAccess(newRepoConfig.getRepo()); repoConfig.copyFrom(newRepoConfig); } ConfigurationHandler.getInstance().save(); } /** * @param idOrName id or name of repo to remove from BorgButler. * @return "OK" if removed or error string. */ @GET @Path("remove") @Produces(MediaType.APPLICATION_JSON) public String removeRepoConfig(@QueryParam("id") String idOrName) { boolean result = ConfigurationHandler.getConfiguration().remove(idOrName); if (!result) { String error = "Repo config with id or name '" + idOrName + "' not found. Can't remove the repo."; log.error(error); return error; } return "OK"; } /** * @param jsonRepoConfig All configuration value of the repo to check. * @return Result of borg (tbd.). */ borgbutler-webapp/src/components/views/repos/ConfigureRepoPage.jsx
@@ -14,23 +14,35 @@ import RepoConfigBasePanel from './RepoConfigBasePanel'; import RepoConfigPasswordPanel from './RepoConfigPasswordPanel'; import RepoConfigTestPanel from './RepoConfigTestPanel'; import {getRestServiceUrl} from "../../../utilities/global"; class ConfigureRepoPage extends React.Component { constructor(props) { super(props); this.onSave = this.onSave.bind(this); this.handleRepoConfigChange = this.handleRepoConfigChange.bind(this); this.handleInputChange = this.handleInputChange.bind(this); this.handleCheckboxChange = this.handleCheckboxChange.bind(this); this.setRepoValue = this.setRepoValue.bind(this); this.state = { repoConfig: {}, repoConfig: {id: 'new'}, encryption: 'repoKey', mode: 'existingRepo', localRemote: 'local' }; } onSave(event) { const response = fetch(getRestServiceUrl("repoConfig"), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(this.state.repoConfig) }); } handleRepoConfigChange = event => { event.preventDefault(); this.setRepoValue(event.target.name, event.target.value); @@ -108,7 +120,7 @@ repoConfig={repoConfig} handleRepoConfigChange={this.handleRepoConfigChange} setRepoValue={this.setRepoValue}/> <FormGroup row={true}> <FormGroup> <FormLabel length={2}/> <FormField length={10}> <Link to={'/repos'} className={'btn btn-outline-primary'}><I18n name={'common.cancel'}/> borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx
@@ -160,30 +160,32 @@ </tr> } content1 = <Table hover> <tbody> <tr> <th>Archive</th> <th>Time</th> <th></th> <th>Id</th> </tr> {repo.archives.map((archive) => { // Return the element. Also pass key let loaded = ''; if (archive.fileListAlreadyCached) { loaded = <IconCheck/>; } return ( <tr key={archive.id}> <td><Link to={`/archives/${repo.id}/${archive.id}/`}>{archive.name}</Link></td> <td>{archive.time}</td> <td>{loaded}</td> <td>{archive.id}</td> </tr>); })} </tbody> </Table>; if (repo.archives) { content1 = <Table hover> <tbody> <tr> <th>Archive</th> <th>Time</th> <th></th> <th>Id</th> </tr> {repo.archives.map((archive) => { // Return the element. Also pass key let loaded = ''; if (archive.fileListAlreadyCached) { loaded = <IconCheck/>; } return ( <tr key={archive.id}> <td><Link to={`/archives/${repo.id}/${archive.id}/`}>{archive.name}</Link></td> <td>{archive.time}</td> <td>{loaded}</td> <td>{archive.id}</td> </tr>); })} </tbody> </Table>; } content2 = <Table striped bordered hover> <tbody> <tr> borgbutler-webapp/src/components/views/repos/RepoConfigPanel.jsx
@@ -8,6 +8,7 @@ import RepoConfigBasePanel from './RepoConfigBasePanel'; import RepoConfigPasswordPanel from './RepoConfigPasswordPanel'; import RepoConfigTestPanel from './RepoConfigTestPanel'; import ConfirmModal from '../../general/modal/ConfirmModal'; class RepoConfigPanel extends React.Component { @@ -15,17 +16,26 @@ super(props); this.state = { loading: false, repoConfig: undefined repoConfig: undefined, confirmModal: false }; this.fetch = this.fetch.bind(this); this.setRepoValue = this.setRepoValue.bind(this); this.onSave = this.onSave.bind(this); this.onRemove = this.onRemove.bind(this); this.onCancel = this.onCancel.bind(this); this.toggleModal = this.toggleModal.bind(this); } componentDidMount = () => this.fetch(); toggleModal() { this.setState({ confirmModal: !this.state.confirmModal }) } fetch = () => { this.setState({ isFetching: true, @@ -68,6 +78,23 @@ }) } onRemove(event) { const response = fetch(getRestServiceUrl('repoConfig/remove', { id: this.props.id }), { method: 'GET', headers: { 'Accept': 'application/json' } }) .then(response => response.text()) .then(text => { }) .catch((error) => { console.log("error", error); }) } async onSave(event) { const response = fetch(getRestServiceUrl("repoConfig"), { method: 'POST', @@ -129,6 +156,7 @@ <FormButton onClick={this.onCancel} hintKey="configuration.cancel.hint"><I18n name={'common.cancel'}/> </FormButton> <FormButton onClick={this.toggleModal} bsStyle={'outline-danger'}>Remove</FormButton> <FormButton onClick={this.onSave} bsStyle="primary" hintKey="configuration.save.hint"><I18n name={'common.save'}/> </FormButton> @@ -139,7 +167,20 @@ <LoadingOverlay active={this.state.loading}/> </React.Fragment>; } return <React.Fragment>{content}{repoError}</React.Fragment>; return <React.Fragment> <ConfirmModal onConfirm={this.onRemove} title={'Are you sure?'} toggle={this.toggleModal} open={this.state.confirmModal} > Do you really want to remove this repository from BorgButler? <br/> The Borg repository itself and its content will be left untouched. </ConfirmModal> {content} {repoError} </React.Fragment>; } } borgbutler-webapp/src/components/views/repos/RepoConfigPasswordPanel.jsx
@@ -32,7 +32,7 @@ } else if (repoConfig.passphrase && repoConfig.passphrase.length > 0) { passwordMethod = 'passphrase'; } else { passwordMethod = 'passwordCommand'; // Default. passwordMethod = 'none'; // Default. } } this.state = { @@ -46,8 +46,8 @@ this.setState({[event.target.name]: event.target.value}); if (event.target.name === 'passwordMethod') { const value = event.target.value; var passwordCommand = null; var passwordCreate = null; var passwordCommand = undefined; var passwordCreate = undefined; if (value === 'passwordFile') { passwordCommand = 'cat ~/.borg-passphrase'; passwordCreate = <React.Fragment> @@ -89,10 +89,16 @@ </div> </React.Fragment>; } if (value === 'none') { this.setState({passwordCreate: '', passphrase: ''}); this.props.setRepoValue('passwordCommand', undefined); } else if (value !== 'passphrase') { this.setState({passphrase: ''}); } if (passwordCommand) { this.props.setRepoValue('passwordCommand', passwordCommand); } this.setState({'passwordCreate': passwordCreate}); this.setState({passwordCreate: passwordCreate}); } }