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

Kai Reinhard
21.56.2018 0bdefbf053beb80736eff0a13fe8b90618c8d6dc
ServerConfiguration is also stored in json.
1 files deleted
12 files modified
331 ■■■■ changed files
borgbutler-core/src/main/java/de/micromata/borgbutler/config/BorgRepoConfig.java 1 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java 15 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java 32 ●●●● patch | view | raw | blame | history
borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java 2 ●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java 4 ●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java 32 ●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfigurationHandler.java 117 ●●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/jetty/JettyServer.java 11 ●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java 23 ●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/user/SingleUserManager.java 29 ●●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/config/ConfigurationAccountTab.jsx 26 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/config/ConfigurationPage.jsx 8 ●●●● patch | view | raw | blame | history
borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx 31 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/config/BorgRepoConfig.java
@@ -10,7 +10,6 @@
     * A name describing this config. Only used for displaying purposes.
     */
    @Getter @Setter
    @JsonProperty("display_name")
    private String displayName;
    @Getter @Setter
    private String repo;
borgbutler-core/src/main/java/de/micromata/borgbutler/config/Configuration.java
@@ -17,26 +17,28 @@
     * Default dir name for restoring archives.
     */
    private static final String RESTORE_DIRNAME = "restore";
    @JsonIgnore
    private File workingDir;
    @Getter
    private String borgCommand = "borg";
    /**
     * Default is 100 MB (approximately).
     */
    @Getter
    @JsonProperty("max_archive_ontent_cache_capacity_mb")
    private int maxArchiveContentCacheCapacityMb = 100;
    /**
     * Default is restore inside BorgButler's home dir (~/.borgbutler/restore).
     */
    @Getter
    @JsonProperty("restore_dir")
    @JsonProperty("restoreDir")
    private String restoreDirPath;
    @JsonIgnore
    private File restoreHomeDir;
    @Getter
    @JsonProperty("repo-configs")
    private List<BorgRepoConfig> repoConfigs = new ArrayList<>();
    public void add(BorgRepoConfig repoConfig) {
@@ -60,7 +62,7 @@
            if (StringUtils.isNotBlank(restoreDirPath)) {
                restoreHomeDir = new File(restoreDirPath);
            } else {
                restoreHomeDir = new File(ConfigurationHandler.getInstance().getWorkingDir(), RESTORE_DIRNAME);
                restoreHomeDir = new File(workingDir, RESTORE_DIRNAME);
            }
            if (!restoreHomeDir.exists()) {
                log.info("Creating dir '" + restoreHomeDir.getAbsolutePath() + "' for restoring backup files and directories.");
@@ -68,4 +70,9 @@
        }
        return restoreHomeDir;
    }
    public void copyFrom(Configuration other) {
        this.borgCommand = other.borgCommand;
        this.maxArchiveContentCacheCapacityMb = other.maxArchiveContentCacheCapacityMb;
    }
}
borgbutler-core/src/main/java/de/micromata/borgbutler/config/ConfigurationHandler.java
@@ -2,6 +2,7 @@
import de.micromata.borgbutler.json.JsonUtils;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -12,7 +13,7 @@
public class ConfigurationHandler {
    private static Logger log = LoggerFactory.getLogger(ConfigurationHandler.class);
    private static ConfigurationHandler instance = new ConfigurationHandler();
    private static ConfigurationHandler instance;
    private static final String BUTLER_HOME_DIR = ".borgbutler";
    private static final String CONFIG_FILENAME = "borgbutler-config.json";
    private static final String CONFIG_BACKUP_FILENAME = "borgbutler-config-bak.json";
@@ -21,24 +22,37 @@
    private File configBackupFile;
    @Getter
    private File workingDir;
    private Configuration configuration = new Configuration();
    private Configuration configuration;
    @Setter
    private static Class<? extends Configuration> configClazz = Configuration.class;
    public static ConfigurationHandler getInstance() {
        if (instance == null) instance = new ConfigurationHandler();
        return instance;
    }
    public static Configuration getConfiguration() {
        return instance.configuration;
        return getInstance().configuration;
    }
    private void read() {
        log.info("Reading config file '" + configFile.getAbsolutePath() + "'");
        try {
            String json = FileUtils.readFileToString(configFile, Definitions.STD_CHARSET);
            this.configuration = JsonUtils.fromJson(Configuration.class, json);
            for (BorgRepoConfig repoConfig : this.configuration.getRepoConfigs()) {
                if (StringUtils.isBlank(repoConfig.getDisplayName())) {
                    repoConfig.setDisplayName(repoConfig.getRepo());
            String json = "{}";
            if (configFile.exists()) {
                json = FileUtils.readFileToString(configFile, Definitions.STD_CHARSET);
                // Migrate from first version:
                if (json.contains("repo-configs")) {
                    json = json.replace("repo-configs", "repoConfigs");
                    json = json.replace("display_name", "displayName");
                }
            }
            this.configuration = JsonUtils.fromJson(configClazz, json);
            if (this.configuration.getRepoConfigs() != null) {
                for (BorgRepoConfig repoConfig : this.configuration.getRepoConfigs()) {
                    if (StringUtils.isBlank(repoConfig.getDisplayName())) {
                        repoConfig.setDisplayName(repoConfig.getRepo());
                    }
                }
            }
        } catch (IOException ex) {
@@ -47,7 +61,7 @@
        }
    }
    public void write() {
    public void save() {
        String json = JsonUtils.toJson(configuration, true);
        try {
            if (configFile.exists()) {
borgbutler-core/src/test/java/de/micromata/borgbutler/config/ConfigHandlerTest.java
@@ -12,7 +12,7 @@
        File workingDir = ConfigurationHandler.getInstance().getWorkingDir();
        File origConfigFile = new File(workingDir, ".borgbutler-orig.json");
        FileUtils.copyFile(ConfigurationHandler.getInstance().getConfigFile(), origConfigFile);
        ConfigurationHandler.getInstance().write();
        ConfigurationHandler.getInstance().save();
        FileUtils.copyFile(origConfigFile, ConfigurationHandler.getInstance().getConfigFile());
    }
}
borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java
@@ -1,6 +1,7 @@
package de.micromata.borgbutler.server;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.json.borg.BorgFilesystemItem;
import de.micromata.borgbutler.server.jetty.JettyServer;
import de.micromata.borgbutler.server.user.SingleUserManager;
@@ -45,6 +46,7 @@
    private void _start(String[] args) {
        ConfigurationHandler.setConfigClazz(ServerConfiguration.class);
        // create Options object
        Options options = new Options();
        options.addOption("e", "extract-archive-content", true, "Extracts the content of an archive cache file only (doesn't start the server). A complete file list of the archive will be extracted to stdout.");
@@ -73,7 +75,7 @@
                        System.err.println("Port outside range.");
                        return;
                    }
                    ServerConfigurationHandler.getDefaultConfiguration().setPort(port);
                    ServerConfiguration.get().setPort(port);
                } catch (NumberFormatException ex) {
                    printHelp(options);
                    return;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java
@@ -1,5 +1,9 @@
package de.micromata.borgbutler.server;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.micromata.borgbutler.config.Configuration;
import de.micromata.borgbutler.config.ConfigurationHandler;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
@@ -8,20 +12,24 @@
import java.beans.Transient;
public class ServerConfiguration {
public class ServerConfiguration extends Configuration {
    private static Logger log = LoggerFactory.getLogger(ServerConfiguration.class);
    private final static String[] SUPPORTED_LANGUAGES = {"en", "de"};
    public static final int WEBSERVER_PORT_DEFAULT = 9042;
    private static final boolean SHOW_TEST_DATA_PREF_DEFAULT = false;
    private static final boolean WEB_DEVELOPMENT_MODE_PREF_DEFAULT = false;
    private static String applicationHome;
    private int port;
    private int port = WEBSERVER_PORT_DEFAULT;
    @Getter
    @Setter
    private boolean showTestData = true;
    private boolean webDevelopmentMode = false;
    private boolean templatesDirModified = false;
    @JsonIgnore
    private boolean showTestData = SHOW_TEST_DATA_PREF_DEFAULT;
    private boolean webDevelopmentMode = WEB_DEVELOPMENT_MODE_PREF_DEFAULT;
    public static ServerConfiguration getDefault() {
        return ServerConfigurationHandler.getDefaultConfiguration();
    public static ServerConfiguration get() {
        return (ServerConfiguration)ConfigurationHandler.getConfiguration();
    }
    public static String[] getSupportedLanguages() {
@@ -39,15 +47,6 @@
        return applicationHome;
    }
    public void resetModifiedFlag() {
        templatesDirModified = false;
    }
    @Transient
    public boolean isTemplatesDirModified() {
        return templatesDirModified;
    }
    public int getPort() {
        return port;
    }
@@ -68,6 +67,7 @@
    }
    public void copyFrom(ServerConfiguration other) {
        super.copyFrom(other);
        this.port = other.port;
        this.showTestData = other.showTestData;
        this.webDevelopmentMode = other.webDevelopmentMode;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfigurationHandler.java
File was deleted
borgbutler-server/src/main/java/de/micromata/borgbutler/server/jetty/JettyServer.java
@@ -1,7 +1,6 @@
package de.micromata.borgbutler.server.jetty;
import de.micromata.borgbutler.server.ServerConfiguration;
import de.micromata.borgbutler.server.ServerConfigurationHandler;
import de.micromata.borgbutler.server.RunningMode;
import de.micromata.borgbutler.server.rest.ConfigurationRest;
import de.micromata.borgbutler.server.user.UserFilter;
@@ -99,7 +98,7 @@
        errorHandler.addErrorPage(404, "/");
        ctx.setErrorHandler(errorHandler);
        if (RunningMode.isDevelopmentMode() || ServerConfigurationHandler.getDefaultConfiguration().isWebDevelopmentMode()) {
        if (RunningMode.isDevelopmentMode() || ServerConfiguration.get().isWebDevelopmentMode()) {
            log.warn("*********************************");
            log.warn("***********            **********");
            log.warn("*********** ATTENTION! **********");
@@ -139,7 +138,7 @@
    }
    private int findFreePort() {
        int port = ServerConfigurationHandler.getInstance().getConfiguration().getPort();
        int port = ServerConfiguration.get().getPort();
        return findFreePort(port);
    }
@@ -147,7 +146,7 @@
        int port = startPort > 0 ? startPort : 1;
        if (port > MAX_PORT_NUMBER) {
            log.warn("Port can't be higher than " + MAX_PORT_NUMBER + ": " + port + ". It's a possible mis-configuration.");
            port = ServerConfigurationHandler.WEBSERVER_PORT_DEFAULT;
            port = ServerConfiguration.WEBSERVER_PORT_DEFAULT;
        }
        for (int i = port; i < port + 10; i++) {
            try (ServerSocket socket = new ServerSocket()) {
@@ -158,9 +157,9 @@
                continue; // try next port
            }
        }
        if (startPort != ServerConfigurationHandler.WEBSERVER_PORT_DEFAULT) {
        if (startPort != ServerConfiguration.WEBSERVER_PORT_DEFAULT) {
            log.info("Trying to fix port due to a possible mis-configuration.");
            return findFreePort(ServerConfigurationHandler.WEBSERVER_PORT_DEFAULT);
            return findFreePort(ServerConfiguration.WEBSERVER_PORT_DEFAULT);
        }
        log.error("No free port found! Giving up.");
        return -1;
borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java
@@ -1,9 +1,9 @@
package de.micromata.borgbutler.server.rest;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.config.ConfigurationHandler;
import de.micromata.borgbutler.json.JsonUtils;
import de.micromata.borgbutler.server.ServerConfiguration;
import de.micromata.borgbutler.server.ServerConfigurationHandler;
import de.micromata.borgbutler.server.user.UserData;
import de.micromata.borgbutler.server.user.UserManager;
import org.apache.commons.lang3.StringUtils;
@@ -26,9 +26,7 @@
     * @see JsonUtils#toJson(Object, boolean)
     */
    public String getConfig(@QueryParam("prettyPrinter") boolean prettyPrinter) {
        ServerConfiguration config = new ServerConfiguration();
        config.copyFrom(ServerConfigurationHandler.getInstance().getConfiguration());
        String json = JsonUtils.toJson(config, prettyPrinter);
        String json = JsonUtils.toJson(ServerConfiguration.get(), prettyPrinter);
        return json;
    }
@@ -36,8 +34,8 @@
    @Path("config")
    @Produces(MediaType.TEXT_PLAIN)
    public void setConfig(String jsonConfig) {
        ServerConfigurationHandler configurationHandler = ServerConfigurationHandler.getInstance();
        ServerConfiguration config = configurationHandler.getConfiguration();
        ConfigurationHandler configurationHandler = ConfigurationHandler.getInstance();
        ServerConfiguration config = (ServerConfiguration)configurationHandler.getConfiguration();
        ServerConfiguration srcConfig = JsonUtils.fromJson(ServerConfiguration.class, jsonConfig);
        config.copyFrom(srcConfig);
        configurationHandler.save();
@@ -77,19 +75,6 @@
     * Resets the settings to default values (deletes all settings).
     */
    @GET
    @Path("reset")
    @Produces(MediaType.APPLICATION_JSON)
    public String resetConfig(@QueryParam("IKnowWhatImDoing") boolean securityQuestion) {
        if (securityQuestion) {
            ServerConfigurationHandler.getInstance().removeAllSettings();
        }
        return getConfig(false);
    }
    /**
     * Resets the settings to default values (deletes all settings).
     */
    @GET
    @Path("clearAllCaches")
    @Produces(MediaType.APPLICATION_JSON)
    public String clearAllCaches() {
borgbutler-server/src/main/java/de/micromata/borgbutler/server/user/SingleUserManager.java
@@ -2,11 +2,12 @@
import de.micromata.borgbutler.server.Languages;
import de.micromata.borgbutler.server.RunningMode;
import de.micromata.borgbutler.server.ServerConfigurationHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Locale;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
/**
 * Contains only one (dummy) user (for desktop version).
@@ -15,6 +16,7 @@
    private static final String USER_LOCAL_PREF_KEY = "userLocale";
    private static Logger log = LoggerFactory.getLogger(SingleUserManager.class);
    private UserData singleUser;
    private Preferences preferences;
    public SingleUserManager() {
        if (RunningMode.getUserManagement() != RunningMode.UserManagement.SINGLE) {
@@ -22,14 +24,11 @@
                    + "'. Only allowed in '" + RunningMode.UserManagement.SINGLE + "'.");
        }
        log.info("Using SingleUserManger as user manager.");
        preferences = Preferences.userRoot().node("de").node("micromata").node("borgbutler");
        singleUser = new UserData();
        singleUser.setUsername("admin");
        singleUser.setAdmin(true);
        String language = ServerConfigurationHandler.getInstance().get("userLocale", null);
        Locale locale = Languages.asLocale(language);
        singleUser.setLocale(locale);
        String dateFormat = ServerConfigurationHandler.getInstance().get("userDateFormat", null);
        singleUser.setDateFormat(dateFormat);
        load(singleUser);
    }
    public UserData getUser(String id) {
@@ -37,10 +36,10 @@
    }
    /**
     * Stores only the user's configured locale.
     * Stores only the user's configured locale as preference.
     *
     * @param userData
     * @see ServerConfigurationHandler#save(String, String)
     * @see Preferences
     */
    @Override
    public void saveUser(UserData userData) {
@@ -49,7 +48,17 @@
        String dateFormat = userData.getDateFormat();
        this.singleUser.setDateFormat(dateFormat);
        String lang = Languages.asString(locale);
        ServerConfigurationHandler.getInstance().save("userLocale", lang);
        ServerConfigurationHandler.getInstance().save("userDateFormat", dateFormat);
        preferences.put(USER_LOCAL_PREF_KEY, lang);
        try {
            preferences.flush();
        } catch (BackingStoreException ex) {
            log.error("Can't save user locale to preferences: " + ex.getMessage(), ex);
        }
    }
    private void load(UserData userData) {
        String language = preferences.get(USER_LOCAL_PREF_KEY, "en");
        Locale locale = Languages.asLocale(language);
        singleUser.setLocale(locale);
    }
}
borgbutler-webapp/src/components/views/config/ConfigurationAccountTab.jsx
@@ -32,11 +32,10 @@
                return resp.json()
            })
            .then((data) => {
                const {locale, dateFormat, ...user} = data;
                const {locale, ...user} = data;
                this.setState({
                    loading: false,
                    locale: locale ? locale : '',
                    dateFormat: dateFormat ? dateFormat : '',
                    ...user
                })
            })
@@ -55,8 +54,7 @@
        this.state = {
            loading: true,
            failed: false,
            locale: null,
            dateFormat: null
            locale: null
        };
        this.handleTextChange = this.handleTextChange.bind(this);
@@ -74,8 +72,7 @@
    save() {
        var user = {
            locale: this.state.locale,
            dateFormat: this.state.dateFormat
            locale: this.state.locale
        };
        return fetch(getRestServiceUrl("configuration/user"), {
            method: 'POST',
@@ -113,23 +110,6 @@
                        <FormOption value={'de'} i18nKey={'language.german'}/>
                    </FormSelect>
                </FormLabelField>
                <FormGroup>
                    <FormLabel length={2} htmlFor={'dateFormat'}>
                        <I18n name={'configuration.application.dateFormat'}/>
                    </FormLabel>
                    <FormField length={2}>
                        <FormSelect value={this.state.dateFormat} name={'dateFormat'} onChange={this.handleTextChange}>
                            <FormOption value={''} i18nKey={'configuration.application.dateFormat.option.auto'}/>
                            <FormOption value={'dd.MM.yyyy'} label={'16.01.2018'}/>
                            <FormOption value={'d.M.yy'} label={'16.1.18'}/>
                            <FormOption value={'yyyy-MM-dd'} label={'2018-01-16'}/>
                            <FormOption value={'dd/MM/yyyy'} label={'16/01/2018'}/>
                            <FormOption value={'d/M/yy'} label={'16/1/18'}/>
                            <FormOption value={'MM/dd/yyyy'} label={'01/16/2018'}/>
                            <FormOption value={'M/d/yy'} label={'1/16/18'}/>
                        </FormSelect>
                    </FormField>
                </FormGroup>
            </form>
        );
    }
borgbutler-webapp/src/components/views/config/ConfigurationPage.jsx
@@ -71,23 +71,23 @@
                        className={classNames({active: this.state.activeTab === '1'})}
                        onClick={this.toggleTab('1')}
                    >
                        <I18n name={'configuration.account'}/>
                        <I18n name={'configuration.server'}/>
                    </NavLink>
                    <NavLink
                        className={classNames({active: this.state.activeTab === '2'})}
                        onClick={this.toggleTab('2')}
                    >
                        <I18n name={'configuration.server'}/>
                        <I18n name={'configuration.account'}/>
                    </NavLink>
                </Nav>
                <TabContent activeTab={this.state.activeTab}>
                    <TabPane tabId={'1'}>
                        <ConfigAccountTab ref={this.accountTabRef}/>
                        <ConfigServerTab ref={this.serverTabRef}/>
                    </TabPane>
                </TabContent>
                <TabContent activeTab={this.state.activeTab}>
                    <TabPane tabId={'2'}>
                        <ConfigServerTab ref={this.serverTabRef}/>
                        <ConfigAccountTab ref={this.accountTabRef}/>
                    </TabPane>
                </TabContent>
                <FormGroup>
borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
@@ -1,8 +1,6 @@
import React from 'react';
import {FormButton, FormCheckbox, FormLabelField, FormLabelInputField} from "../../general/forms/FormComponents";
import {getRestServiceUrl} from "../../../utilities/global";
import {IconDanger} from '../../general/IconComponents';
import {getTranslation} from "../../../utilities/i18n";
import I18n from "../../general/translation/I18n";
import ErrorAlertGenericRestFailure from '../../general/ErrorAlertGenericRestFailure';
import Loading from "../../general/Loading";
@@ -45,13 +43,13 @@
            loading: true,
            failed: false,
            port: 9042,
            webDevelopmentMode: false,
            webdevelopmentMode: false,
            maxArchiveContentCacheCapacityMb: 100,
            redirect: false
        };
        this.handleTextChange = this.handleTextChange.bind(this);
        this.handleCheckboxChange = this.handleCheckboxChange.bind(this);
        this.onResetConfiguration = this.onResetConfiguration.bind(this);
        this.onClearAllCaches = this.onClearAllCaches.bind(this);
        this.loadConfig = this.loadConfig.bind(this);
    }
@@ -72,6 +70,7 @@
    save() {
        var config = {
            port: this.state.port,
            maxArchiveContentCacheCapacityMb : this.state.maxArchiveContentCacheCapacityMb,
            webDevelopmentMode: this.state.webDevelopmentMode
        };
        return fetch(getRestServiceUrl("configuration/config"), {
@@ -83,18 +82,6 @@
        })
    }
    onResetConfiguration() {
        if (window.confirm(getTranslation('configuration.resetAllSettings.question'))) {
            fetch(getRestServiceUrl("configuration/reset?IKnowWhatImDoing=true"), {
                method: "GET",
                dataType: "JSON",
                headers: {
                    "Content-Type": "text/plain; charset=utf-8"
                }
            })
        }
    }
    onClearAllCaches() {
        if (window.confirm('Do you really want to clear all caches? All Archive file lists and caches for repo and archive informatino will be cleared.')) {
            fetch(getRestServiceUrl("configuration/clearAllCaches"), {
@@ -115,7 +102,6 @@
        if (this.state.failed) {
            return <ErrorAlertGenericRestFailure handleClick={this.loadConfig}/>;
        }
        return (
            <form>
                <FormLabelField>
@@ -127,18 +113,17 @@
                                     name={'port'} value={this.state.port}
                                     onChange={this.handleTextChange}
                                     placeholder="Enter port"/>
                <FormLabelInputField label={'Maximum disc capacity (MB)'} fieldLength={2} type="number" min={50} max={10000}
                                     step={50}
                                     name={'maxArchiveContentCacheCapacityMb'} value={this.state.maxArchiveContentCacheCapacityMb}
                                     onChange={this.handleTextChange}
                                     placeholder="Enter maximum Capacity"/>
                <FormLabelField label={<I18n name={'configuration.webDevelopmentMode'}/>} fieldLength={2}>
                    <FormCheckbox checked={this.state.webDevelopmentMode}
                                  hintKey={'configuration.webDevelopmentMode.hint'}
                                  name="webDevelopmentMode"
                                  onChange={this.handleCheckboxChange}/>
                </FormLabelField>
                <FormLabelField>
                    <FormButton id={'resetFactorySettings'} onClick={this.onResetConfiguration}
                                hintKey={'configuration.resetAllSettings.hint'}> <IconDanger/> <I18n
                        name={'configuration.resetAllSettings'}/>
                    </FormButton>
                </FormLabelField>
            </form>
        );
    }