diff --git a/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java b/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java index ad344823192657c89d1b1d4d902e60efb33df3ee..a603722b4e0a9c76a80ebcccf8a85a56055047ca 100644 --- a/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java +++ b/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java @@ -16,6 +16,7 @@ import javax.net.ssl.X509TrustManager; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import de.deadlocker8.budgetmasterserver.main.Database; import tools.ConvertTo; import tools.Read; @@ -48,10 +49,10 @@ public class ServerConnection // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); - HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - - //check whitelist - HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession)->settings.getTrustedHosts().contains(hostname)); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + + // check whitelist + HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> settings.getTrustedHosts().contains(hostname)); } /* @@ -78,7 +79,7 @@ public class ServerConnection return null; } } - + public Category getCategory(int ID) throws Exception { URL url = new URL(settings.getUrl() + "/category/single?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&id=" + ID); @@ -129,7 +130,7 @@ public class ServerConnection BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); reader.close(); } - + /* * Payment */ @@ -176,7 +177,7 @@ public class ServerConnection return null; } } - + public RepeatingPayment getRepeatingPayment(int ID) throws Exception { URL url = new URL(settings.getUrl() + "/repeatingpayment/single?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&id=" + ID); @@ -186,7 +187,7 @@ public class ServerConnection if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) { - String result = Read.getStringFromInputStream(httpsCon.getInputStream()); + String result = Read.getStringFromInputStream(httpsCon.getInputStream()); return gson.fromJson(result, RepeatingPayment.class); } else @@ -197,12 +198,8 @@ public class ServerConnection public void addNormalPayment(NormalPayment payment) throws Exception { - URL url = new URL(settings.getUrl() + "/payment?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + - "&amount=" + payment.getAmount() + - "&date=" + payment.getDate() + - "&categoryID=" + payment.getCategoryID() + - "&name=" + Helpers.getURLEncodedString(payment.getName()) + - "&description=" + Helpers.getURLEncodedString(payment.getDescription())); + URL url = new URL(settings.getUrl() + "/payment?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&amount=" + payment.getAmount() + "&date=" + payment.getDate() + "&categoryID=" + payment.getCategoryID() + "&name=" + Helpers.getURLEncodedString(payment.getName()) + + "&description=" + Helpers.getURLEncodedString(payment.getDescription())); HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setRequestMethod("POST"); httpsCon.setDoInput(true); @@ -213,19 +210,14 @@ public class ServerConnection public void updateNormalPayment(NormalPayment payment) throws Exception { - URL url = new URL(settings.getUrl() + "/payment?secret=" + settings.getSecret() + - "&id=" + payment.getID() + - "&amount=" + payment.getAmount() + - "&date=" + payment.getDate() + - "&categoryID=" + payment.getCategoryID() + - "&name=" + Helpers.getURLEncodedString(payment.getName()) + - "&description=" + Helpers.getURLEncodedString(payment.getDescription())); - HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); - httpsCon.setRequestMethod("PUT"); - httpsCon.setDoInput(true); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + URL url = new URL(settings.getUrl() + "/payment?secret=" + settings.getSecret() + "&id=" + payment.getID() + "&amount=" + payment.getAmount() + "&date=" + payment.getDate() + "&categoryID=" + payment.getCategoryID() + "&name=" + Helpers.getURLEncodedString(payment.getName()) + + "&description=" + Helpers.getURLEncodedString(payment.getDescription())); + HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); + httpsCon.setRequestMethod("PUT"); + httpsCon.setDoInput(true); + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); } public void addRepeatingPayment(RepeatingPayment payment) throws Exception @@ -237,15 +229,8 @@ public class ServerConnection repeatEndDate = "A"; } - URL url = new URL(settings.getUrl() + "/repeatingpayment?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + - "&amount=" + payment.getAmount() + - "&date=" + payment.getDate() + - "&categoryID=" + payment.getCategoryID() + - "&name=" + Helpers.getURLEncodedString(payment.getName()) + - "&repeatInterval=" + payment.getRepeatInterval() + - "&repeatEndDate=" + repeatEndDate + - "&repeatMonthDay=" + payment.getRepeatMonthDay() + - "&description=" + Helpers.getURLEncodedString(payment.getDescription())); + URL url = new URL(settings.getUrl() + "/repeatingpayment?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&amount=" + payment.getAmount() + "&date=" + payment.getDate() + "&categoryID=" + payment.getCategoryID() + "&name=" + Helpers.getURLEncodedString(payment.getName()) + + "&repeatInterval=" + payment.getRepeatInterval() + "&repeatEndDate=" + repeatEndDate + "&repeatMonthDay=" + payment.getRepeatMonthDay() + "&description=" + Helpers.getURLEncodedString(payment.getDescription())); HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setRequestMethod("POST"); httpsCon.setDoInput(true); @@ -264,7 +249,7 @@ public class ServerConnection BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); reader.close(); } - + public void deleteRepeatingPayment(RepeatingPaymentEntry payment) throws Exception { URL url = new URL(settings.getUrl() + "/repeatingpayment?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&id=" + payment.getRepeatingPaymentID()); @@ -275,7 +260,7 @@ public class ServerConnection BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); reader.close(); } - + /* * CATEGORYBUDGET */ @@ -300,7 +285,7 @@ public class ServerConnection return null; } } - + /* * REST */ @@ -313,7 +298,7 @@ public class ServerConnection if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) { - String result = Read.getStringFromInputStream(httpsCon.getInputStream()); + String result = Read.getStringFromInputStream(httpsCon.getInputStream()); return gson.fromJson(result, Integer.class); } else @@ -321,10 +306,10 @@ public class ServerConnection return 0; } } - + /* * DATABASE - */ + */ public void deleteDatabase() throws Exception { URL url = new URL(settings.getUrl() + "/database?secret=" + Helpers.getURLEncodedString(settings.getSecret())); @@ -335,7 +320,7 @@ public class ServerConnection BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); reader.close(); } - + public String exportDatabase() throws Exception { URL url = new URL(settings.getUrl() + "/database?secret=" + Helpers.getURLEncodedString(settings.getSecret())); @@ -345,11 +330,25 @@ public class ServerConnection if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) { - return Read.getStringFromInputStream(httpsCon.getInputStream()); + return Read.getStringFromInputStream(httpsCon.getInputStream()); } else { return null; } } + + public void importDatabase(Database database) throws Exception + { + //TODO +// String databaseJSON = new Gson().toJson(database); +// +// URL url = new URL(settings.getUrl() + "/database?secret=" + Helpers.getURLEncodedString(settings.getSecret())); +// HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); +// httpsCon.setRequestMethod("POST"); +// httpsCon.setDoInput(true); +// InputStream stream = httpsCon.getInputStream(); +// BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); +// reader.close(); + } } \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/logic/Utils.java b/src/de/deadlocker8/budgetmaster/logic/Utils.java index 79ba8e1906f783abc0fe3c05ff02ec64364fae8e..e50e6b35045c06865a81d446037a2a0dad8e5fac 100644 --- a/src/de/deadlocker8/budgetmaster/logic/Utils.java +++ b/src/de/deadlocker8/budgetmaster/logic/Utils.java @@ -24,8 +24,7 @@ public class Utils Settings settings; try { - Gson gson = new Gson(); - PathUtils.checkFolder(new File(PathUtils.getOSindependentPath() + bundle.getString("folder"))); + Gson gson = new Gson(); Reader reader = Files.newBufferedReader(Paths.get(PathUtils.getOSindependentPath() + bundle.getString("folder") + "/settings.json"), Charset.forName("UTF-8")); settings = gson.fromJson(reader, Settings.class); reader.close(); @@ -41,28 +40,19 @@ public class Utils { Gson gson = new Gson(); String jsonString = gson.toJson(settings); - + PathUtils.checkFolder(new File(PathUtils.getOSindependentPath() + bundle.getString("folder"))); Writer writer = Files.newBufferedWriter(Paths.get(PathUtils.getOSindependentPath() + bundle.getString("folder") + "/settings.json"), Charset.forName("UTF-8")); writer.write(jsonString); writer.close(); } - public static Database loadDatabaseJSON(File file) - { - Database database; - try - { - Gson gson = new Gson(); - PathUtils.checkFolder(file.getParentFile()); - Reader reader = Files.newBufferedReader(Paths.get(file.getAbsolutePath()), Charset.forName("UTF-8")); - database = gson.fromJson(reader, Database.class); - reader.close(); - return database; - } - catch(IOException e) - { - return null; - } + public static Database loadDatabaseJSON(File file) throws IOException + { + Gson gson = new Gson(); + Reader reader = Files.newBufferedReader(Paths.get(file.getAbsolutePath()), Charset.forName("UTF-8")); + Database database = gson.fromJson(reader, Database.class); + reader.close(); + return database; } public static void saveDatabaseJSON(File file, String databaseJSON) throws IOException diff --git a/src/de/deadlocker8/budgetmaster/main/Main.java b/src/de/deadlocker8/budgetmaster/main/Main.java index cc47c5474cad07b07ca9cfc89dc525e7f8ae328d..ebbc0ab0f3027ef5a9bd76337a1124135d6b7736 100644 --- a/src/de/deadlocker8/budgetmaster/main/Main.java +++ b/src/de/deadlocker8/budgetmaster/main/Main.java @@ -27,13 +27,13 @@ public class Main extends Application FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("de/deadlocker8/budgetmaster/ui/GUI.fxml")); Parent root = (Parent)loader.load(); - Scene scene = new Scene(root, 600, 650); + Scene scene = new Scene(root, 610, 650); ((Controller)loader.getController()).init(stage); stage.setResizable(true); - stage.setMinHeight(600); - stage.setMinWidth(600); + stage.setMinHeight(650); + stage.setMinWidth(610); stage.getIcons().add(new Image("/de/deadlocker8/budgetmaster/resources/icon.png")); stage.setTitle(bundle.getString("app.name")); stage.setScene(scene); diff --git a/src/de/deadlocker8/budgetmaster/ui/SettingsController.java b/src/de/deadlocker8/budgetmaster/ui/SettingsController.java index ac6f9aba6f8f7dc621309fb621c84ad96ab36021..c66d001ae841bb84420a09e1b4aeef799592669c 100644 --- a/src/de/deadlocker8/budgetmaster/ui/SettingsController.java +++ b/src/de/deadlocker8/budgetmaster/ui/SettingsController.java @@ -9,13 +9,17 @@ import de.deadlocker8.budgetmaster.logic.Helpers; import de.deadlocker8.budgetmaster.logic.ServerConnection; import de.deadlocker8.budgetmaster.logic.Settings; import de.deadlocker8.budgetmaster.logic.Utils; +import de.deadlocker8.budgetmasterserver.main.Database; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.control.ButtonType; import javafx.scene.control.Label; import javafx.scene.control.RadioButton; import javafx.scene.control.TextArea; @@ -44,7 +48,8 @@ public class SettingsController @FXML private TextField textFieldCurrency; @FXML private Label labelCurrency; @FXML private Button buttonSave; - @FXML private Button buttonBackupDB; + @FXML private Button buttonExportDB; + @FXML private Button buttonImportDB; @FXML private Button buttonDeleteDB; @FXML private RadioButton radioButtonRestActivated; @FXML private RadioButton radioButtonRestDeactivated; @@ -76,8 +81,9 @@ public class SettingsController labelURL.setStyle("-fx-text-fill: " + controller.getBundle().getString("color.text")); labelCurrency.setStyle("-fx-text-fill: " + controller.getBundle().getString("color.text")); buttonSave.setStyle("-fx-background-color: #2E79B9; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16;"); - buttonBackupDB.setStyle("-fx-background-color: #2E79B9; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16;"); - buttonDeleteDB.setStyle("-fx-background-color: #FF5047; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 16;"); + buttonExportDB.setStyle("-fx-background-color: #2E79B9; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 14;"); + buttonImportDB.setStyle("-fx-background-color: #2E79B9; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 14;"); + buttonDeleteDB.setStyle("-fx-background-color: #FF5047; -fx-text-fill: white; -fx-font-weight: bold; -fx-font-size: 14;"); textFieldURL.setPromptText("z.B. https://yourdomain.de"); textFieldCurrency.setPromptText("z.B. €, CHF, $"); textAreaTrustedHosts.setPromptText("z.B. localhost"); @@ -179,7 +185,7 @@ public class SettingsController controller.showNotification("Erfolgreich gespeichert"); } - public void backupDB() + public void exportDB() { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Datenbank exportieren"); @@ -193,10 +199,10 @@ public class SettingsController Worker.runLater(() -> { try { - ServerConnection connection = new ServerConnection(controller.getSettings()); + ServerConnection connection = new ServerConnection(controller.getSettings()); String databaseJSON = connection.exportDatabase(); Utils.saveDatabaseJSON(file, databaseJSON); - + Platform.runLater(() -> { if(modalStage != null) { @@ -215,8 +221,92 @@ public class SettingsController }); } } + + private void importDatabase() + { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Datenbank importieren"); + FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("JSON (*.json)", "*.json"); + fileChooser.getExtensionFilters().add(extFilter); + File file = fileChooser.showOpenDialog(controller.getStage()); + if(file != null) + { + Database database; + try + { + database = Utils.loadDatabaseJSON(file); + if(database.getCategories() == null || database.getNormalPayments() == null || database.getRepeatingPayments() == null) + { + AlertGenerator.showAlert(AlertType.ERROR, "Fehler", "", "Die angegebene Datei enthält kein gültiges BudgetMaster-Datenformat und kann daher nicht importiert werden.", controller.getIcon(), controller.getStage(), null, false); + return; + } + } + catch(IOException e1) + { + Logger.error(e1); + AlertGenerator.showAlert(AlertType.ERROR, "Fehler", "", "Beim Einlesen der Datei ist ein Fehler aufgetreten.", controller.getIcon(), controller.getStage(), null, false); + return; + } + + Stage modalStage = showModal("Vorgang läuft", "Die Datenbank wird importiert, bitte warten..."); + + Worker.runLater(() -> { + try + { + ServerConnection connection = new ServerConnection(controller.getSettings()); + connection.importDatabase(database); + Platform.runLater(() -> { + if(modalStage != null) + { + modalStage.close(); + } + AlertGenerator.showAlert(AlertType.INFORMATION, "Erfolgreich exportiert", "", "Die Datenbank wurder erfolgreich importiert.", controller.getIcon(), controller.getStage(), null, false); + }); + } + catch(Exception e) + { + Logger.error(e); + Platform.runLater(() -> { + controller.showConnectionErrorAlert(e.getMessage()); + }); + } + }); + } + } + + public void importDB() + { + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.setTitle("Datenbank importieren"); + alert.setHeaderText(""); + alert.setContentText("Soll die Datenbank vor dem Importieren gelöscht werden?"); + Stage dialogStage = (Stage)alert.getDialogPane().getScene().getWindow(); + dialogStage.getIcons().add(controller.getIcon()); + dialogStage.initOwner(controller.getStage()); + + ButtonType buttonTypeDelete = new ButtonType("Ja, Datenbank löschen"); + ButtonType buttonTypeAppend = new ButtonType("Nein, Daten hinzufügen"); + ButtonType buttonTypeCancel = new ButtonType("Abbrechen", ButtonData.CANCEL_CLOSE); + + alert.getButtonTypes().setAll(buttonTypeDelete, buttonTypeAppend, buttonTypeCancel); + Optional<ButtonType> result = alert.showAndWait(); + if(result.get() == buttonTypeDelete) + { + deleteDatabase(true); + } + else if(result.get() == buttonTypeAppend) + { + importDatabase(); + } + } + public void deleteDB() + { + deleteDatabase(false); + } + + public void deleteDatabase(boolean importPending) { String verificationCode = ConvertTo.toBase58(RandomCreations.generateRandomMixedCaseString(4, true), true, BASE58Type.UPPER); @@ -244,6 +334,10 @@ public class SettingsController if(modalStage != null) { modalStage.close(); + if(importPending) + { + importDatabase(); + } } }); } diff --git a/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml b/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml index 7b620aeca8369bbb3f5776ea3d140e67fe0c997e..8014a8cab8429d648976e326a52d09a1abbe935d 100644 --- a/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml +++ b/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml @@ -67,6 +67,14 @@ <Insets top="35.0" /> </VBox.margin> </Label> + <Label fx:id="labelSecret11121" alignment="CENTER_RIGHT" contentDisplay="RIGHT" maxHeight="-Infinity" prefWidth="158.0" textAlignment="RIGHT" wrapText="true"> + <font> + <Font name="System Bold" size="16.0" /> + </font> + <VBox.margin> + <Insets top="15.0" /> + </VBox.margin> + </Label> <Region prefHeight="19.0" prefWidth="158.0" VBox.vgrow="ALWAYS" /> </children> <HBox.margin> @@ -95,13 +103,18 @@ </RadioButton> </children> </HBox> - <TextArea fx:id="textAreaTrustedHosts" prefWidth="539.0" VBox.vgrow="ALWAYS"> + <TextArea fx:id="textAreaTrustedHosts" minHeight="110.0" prefHeight="148.0" prefWidth="539.0" VBox.vgrow="ALWAYS"> <VBox.margin> <Insets /> </VBox.margin></TextArea> <HBox alignment="CENTER_LEFT" prefHeight="11.0" prefWidth="539.0" spacing="30.0"> <children> - <Button fx:id="buttonBackupDB" mnemonicParsing="false" onAction="#backupDB" text="Backup"> + <Button fx:id="buttonExportDB" mnemonicParsing="false" onAction="#exportDB" text="Exportieren"> + <font> + <Font name="System Bold" size="14.0" /> + </font> + </Button> + <Button fx:id="buttonImportDB" mnemonicParsing="false" onAction="#importDB" text="Importieren"> <font> <Font name="System Bold" size="14.0" /> </font> @@ -112,17 +125,23 @@ </font> </Button> </children> + <VBox.margin> + <Insets /> + </VBox.margin> </HBox> - <Region prefHeight="19.0" prefWidth="158.0" VBox.vgrow="ALWAYS" /> + <Button fx:id="buttonSave" mnemonicParsing="false" onAction="#save" text="Speichern"> + <font> + <Font name="System Bold" size="14.0" /> + </font> + <VBox.margin> + <Insets top="15.0" /> + </VBox.margin> + </Button> + <Region prefWidth="158.0" VBox.vgrow="ALWAYS" /> </children> </VBox> </children> </HBox> - <Button fx:id="buttonSave" mnemonicParsing="false" onAction="#save" text="Speichern"> - <font> - <Font name="System Bold" size="14.0" /> - </font> - </Button> </children> <padding> <Insets right="50.0" />