mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
11.31.2019 403fb2eb98deb2e352f700b2503fdf5b27679c96
Adding and removing repos.
6 files modified
178 ■■■■ changed files
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java 15 ●●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java 38 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/repos/ConfigureRepoPage.jsx 16 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx 50 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/repos/RepoConfigPanel.jsx 45 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/repos/RepoConfigPasswordPanel.jsx 14 ●●●● patch | view | raw | blame | history
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});
        }
    }