From 403fb2eb98deb2e352f700b2503fdf5b27679c96 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Mon, 11 Feb 2019 22:31:55 +0000
Subject: [PATCH] Adding and removing repos.

---
 borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java              |   15 +++++
 borgbutler-webapp/src/components/views/repos/ConfigureRepoPage.jsx                           |   16 ++++
 borgbutler-webapp/src/components/views/repos/RepoConfigPasswordPanel.jsx                     |   14 +++-
 borgbutler-webapp/src/components/views/repos/RepoConfigPanel.jsx                             |   45 ++++++++++++++
 borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx                         |   50 ++++++++--------
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java |   38 ++++++++++--
 6 files changed, 140 insertions(+), 38 deletions(-)

diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
index 94365cf..5853a43 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
+++ b/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;
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java
index d80f327..a11e3ad 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/BorgRepoConfigsRest.java
+++ b/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.).
      */
diff --git a/borgbutler-webapp/src/components/views/repos/ConfigureRepoPage.jsx b/borgbutler-webapp/src/components/views/repos/ConfigureRepoPage.jsx
index a03aeb3..8e10c2c 100644
--- a/borgbutler-webapp/src/components/views/repos/ConfigureRepoPage.jsx
+++ b/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'}/>
diff --git a/borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx b/borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx
index 05789f6..566a083 100644
--- a/borgbutler-webapp/src/components/views/repos/RepoArchiveListView.jsx
+++ b/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>
diff --git a/borgbutler-webapp/src/components/views/repos/RepoConfigPanel.jsx b/borgbutler-webapp/src/components/views/repos/RepoConfigPanel.jsx
index d97d0d0..88ef7e8 100644
--- a/borgbutler-webapp/src/components/views/repos/RepoConfigPanel.jsx
+++ b/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>;
     }
 }
 
diff --git a/borgbutler-webapp/src/components/views/repos/RepoConfigPasswordPanel.jsx b/borgbutler-webapp/src/components/views/repos/RepoConfigPasswordPanel.jsx
index cf0054c..9e0e891 100644
--- a/borgbutler-webapp/src/components/views/repos/RepoConfigPasswordPanel.jsx
+++ b/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});
         }
     }
 

--
Gitblit v1.10.0