diff --git a/src/de/deadlocker8/budgetmaster/logic/ExceptionHandler.java b/src/de/deadlocker8/budgetmaster/logic/ExceptionHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..65c70667af0213cb7ce5e1bc6030893935939ae5 --- /dev/null +++ b/src/de/deadlocker8/budgetmaster/logic/ExceptionHandler.java @@ -0,0 +1,35 @@ +package de.deadlocker8.budgetmaster.logic; + +public class ExceptionHandler +{ + public static String getMessageForException(Exception e) + { + if(e instanceof ServerConnectionException) + { + return handleServerConnectionException(e); + } + + if(e.getMessage().contains("Connection refused")) + { + return "Server nicht erreichbar."; + } + else if(e.getMessage().contains("HTTPS hostname wrong")) + { + return "Der Server verwendet ein selbst signiertes Zertifkat für die Verschlüsselung. " + + "Aus Sicherheitsgründen werden diese Zertifikate standardmäßig blockiert. " + + "Wenn du dem Zertifikat trotzdem vertrauen möchtest, dann füge den Hostnamen des Servers zur Liste der vertrauenswürdigen Hosts in den Einstellungen hinzu."; + } + return e.getMessage(); + } + + private static String handleServerConnectionException(Exception e) + { + switch(e.getMessage()) + { + case "400": return "Der Server erhielt eine fehlerhafte Anfrage oder ungültige Parameter."; + case "401": return "Ungültiges Passwort."; + case "500": return "Beim Ausführen der Anfrage ist ein interner Serverfehler ist aufgetreten."; + default: return e.getMessage(); + } + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/logic/Helpers.java b/src/de/deadlocker8/budgetmaster/logic/Helpers.java index 946b14824832b24e64e4670ef289d9e5903b0876..9190df3577db8a5f28558da7a167bc9e24489ed6 100644 --- a/src/de/deadlocker8/budgetmaster/logic/Helpers.java +++ b/src/de/deadlocker8/budgetmaster/logic/Helpers.java @@ -10,8 +10,10 @@ import java.util.ArrayList; public class Helpers { public static final DecimalFormat NUMBER_FORMAT = new DecimalFormat("0.00"); + public static final String COLOR_INCOME = "#22BAD9"; public static final String COLOR_PAYMENT = "#F2612D"; + public static final String SALT = "ny9/Y+G|WrJ,82|oIYQQ X %i-sq#4,uA-qKPtwFPnw+s(k2`rV)^-a1|t{D3Z>S"; public static String getURLEncodedString(String input) { diff --git a/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java b/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java index 64e7cb4202ac6d126c10eed8967182e47bdb9809..4759378f49b10f740085be73f845fb8e1ff51062 100644 --- a/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java +++ b/src/de/deadlocker8/budgetmaster/logic/ServerConnection.java @@ -18,6 +18,7 @@ import org.joda.time.DateTime; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import de.deadlocker8.budgetmasterserver.main.Database; import tools.ConvertTo; import tools.Read; @@ -51,7 +52,9 @@ public class ServerConnection SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> hostname.equals("localhost")); + + // check whitelist + HttpsURLConnection.setDefaultHostnameVerifier((hostname, sslSession) -> settings.getTrustedHosts().contains(hostname)); } /* @@ -75,10 +78,10 @@ public class ServerConnection } else { - return null; + return new ArrayList<>(); } } - + public Category getCategory(int ID) throws Exception { URL url = new URL(settings.getUrl() + "/category/single?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&id=" + ID); @@ -103,9 +106,16 @@ public class ServerConnection HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setRequestMethod("POST"); httpsCon.setDoInput(true); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } public void updateCategory(Category category) throws Exception @@ -114,9 +124,16 @@ public class ServerConnection HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setRequestMethod("PUT"); httpsCon.setDoInput(true); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } public void deleteCategory(int ID) throws Exception @@ -125,11 +142,18 @@ public class ServerConnection HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setRequestMethod("DELETE"); httpsCon.setDoInput(true); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } - + /* * Payment */ @@ -139,7 +163,7 @@ public class ServerConnection HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setDoOutput(true); httpsCon.setRequestMethod("GET"); - + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) { String result = Read.getStringFromInputStream(httpsCon.getInputStream()); @@ -151,7 +175,7 @@ public class ServerConnection } else { - return null; + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); } } @@ -173,10 +197,10 @@ public class ServerConnection } else { - return null; + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); } } - + public RepeatingPayment getRepeatingPayment(int ID) throws Exception { URL url = new URL(settings.getUrl() + "/repeatingpayment/single?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&id=" + ID); @@ -186,46 +210,51 @@ 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 { - return null; + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); } } 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); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } 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); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } public void addRepeatingPayment(RepeatingPayment payment) throws Exception @@ -237,21 +266,21 @@ 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); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } public void deleteNormalPayment(NormalPayment payment) throws Exception @@ -260,22 +289,36 @@ public class ServerConnection HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setRequestMethod("DELETE"); httpsCon.setDoInput(true); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } - + public void deleteRepeatingPayment(RepeatingPaymentEntry payment) throws Exception { URL url = new URL(settings.getUrl() + "/repeatingpayment?secret=" + Helpers.getURLEncodedString(settings.getSecret()) + "&id=" + payment.getRepeatingPaymentID()); HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); httpsCon.setRequestMethod("DELETE"); httpsCon.setDoInput(true); - InputStream stream = httpsCon.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - reader.close(); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } } - + /* * CATEGORYBUDGET */ @@ -297,10 +340,10 @@ public class ServerConnection } else { - return null; + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); } } - + /* * REST */ @@ -313,14 +356,73 @@ 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 { - return 0; + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); } } + + /* + * DATABASE + */ + public void deleteDatabase() throws Exception + { + URL url = new URL(settings.getUrl() + "/database?secret=" + Helpers.getURLEncodedString(settings.getSecret())); + HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); + httpsCon.setRequestMethod("DELETE"); + httpsCon.setDoInput(true); + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + InputStream stream = httpsCon.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + reader.close(); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } + } + + public String exportDatabase() throws Exception + { + URL url = new URL(settings.getUrl() + "/database?secret=" + Helpers.getURLEncodedString(settings.getSecret())); + HttpsURLConnection httpsCon = (HttpsURLConnection)url.openConnection(); + httpsCon.setDoOutput(true); + httpsCon.setRequestMethod("GET"); + + if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) + { + return Read.getStringFromInputStream(httpsCon.getInputStream()); + } + else + { + throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); + } + } + + 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); +// if(httpsCon.getResponseCode() == HttpsURLConnection.HTTP_OK) +// { +// InputStream stream = httpsCon.getInputStream(); +// BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); +// reader.close(); +// } +// else +// { +// throw new ServerConnectionException(String.valueOf(httpsCon.getResponseCode())); +// } + } /* * CHARTS diff --git a/src/de/deadlocker8/budgetmaster/logic/ServerConnectionException.java b/src/de/deadlocker8/budgetmaster/logic/ServerConnectionException.java new file mode 100644 index 0000000000000000000000000000000000000000..c18a1663b3a6774129233997db6a08d99535f9e4 --- /dev/null +++ b/src/de/deadlocker8/budgetmaster/logic/ServerConnectionException.java @@ -0,0 +1,31 @@ +package de.deadlocker8.budgetmaster.logic; + +public class ServerConnectionException extends Exception +{ + private static final long serialVersionUID = 2784475774757068549L; + + public ServerConnectionException() + { + super(); + } + + public ServerConnectionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ServerConnectionException(String message, Throwable cause) + { + super(message, cause); + } + + public ServerConnectionException(String message) + { + super(message); + } + + public ServerConnectionException(Throwable cause) + { + super(cause); + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/logic/Settings.java b/src/de/deadlocker8/budgetmaster/logic/Settings.java index 84a6b6ff524b6d19e94dcaf081e953e7ff75ab4e..f95ce96203ee507679c9ffb83ebc92efee79183a 100644 --- a/src/de/deadlocker8/budgetmaster/logic/Settings.java +++ b/src/de/deadlocker8/budgetmaster/logic/Settings.java @@ -1,11 +1,14 @@ package de.deadlocker8.budgetmaster.logic; +import java.util.ArrayList; + public class Settings { private String url; private String secret; private String currency; private boolean restActivated; + private ArrayList<String> trustedHosts; public Settings() { @@ -51,10 +54,20 @@ public class Settings { this.restActivated = restActivated; } + + public ArrayList<String> getTrustedHosts() + { + return trustedHosts; + } + + public void setTrustedHosts(ArrayList<String> trustedHosts) + { + this.trustedHosts = trustedHosts; + } @Override public String toString() { - return "Settings [url=" + url + ", secret=" + secret + ", currency=" + currency + ", restActivated=" + restActivated + "]"; + return "Settings [url=" + url + ", secret=" + secret + ", currency=" + currency + ", restActivated=" + restActivated + ", trustedHosts=" + trustedHosts + "]"; } } \ 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 55789dca5c6081740ca9e6a6fb2d427eda140c45..e50e6b35045c06865a81d446037a2a0dad8e5fac 100644 --- a/src/de/deadlocker8/budgetmaster/logic/Utils.java +++ b/src/de/deadlocker8/budgetmaster/logic/Utils.java @@ -12,6 +12,7 @@ import java.util.ResourceBundle; import com.google.gson.Gson; +import de.deadlocker8.budgetmasterserver.main.Database; import tools.PathUtils; public class Utils @@ -23,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(); @@ -40,9 +40,25 @@ 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) 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 + { + Writer writer = Files.newBufferedWriter(Paths.get(file.getAbsolutePath()), Charset.forName("UTF-8")); + writer.write(databaseJSON); + writer.close(); + } } \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/main/Main.java b/src/de/deadlocker8/budgetmaster/main/Main.java index a4c07a2311d5a1abfb4f2c4d4c66916f1c57a08f..a2a24cf7e5355bfad397ae5afdc5b0ef628d1023 100644 --- a/src/de/deadlocker8/budgetmaster/main/Main.java +++ b/src/de/deadlocker8/budgetmaster/main/Main.java @@ -18,7 +18,7 @@ import tools.PathUtils; public class Main extends Application { public static ResourceBundle bundle = ResourceBundle.getBundle("de/deadlocker8/budgetmaster/main/", Locale.GERMANY); - + @Override public void start(Stage stage) { @@ -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, 650, 650); + Scene scene = new Scene(root, 650, 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); @@ -45,23 +45,23 @@ public class Main extends Application Logger.error(e); } } - + @Override public void init() throws Exception - { + { Parameters params = getParameters(); - String logLevelParam = params.getNamed().get("loglevel"); - Logger.setLevel(logLevelParam); + String logLevelParam = params.getNamed().get("loglevel"); + Logger.setLevel(logLevelParam); - File logFolder = new File(PathUtils.getOSindependentPath() + bundle.getString("folder")); + File logFolder = new File(PathUtils.getOSindependentPath() + bundle.getString("folder")); PathUtils.checkFolder(logFolder); Logger.enableFileOutput(logFolder, System.out, System.err, FileOutputMode.COMBINED); - - Logger.appInfo(bundle.getString("app.name"), bundle.getString("version.name"), bundle.getString("version.code"), bundle.getString("version.date")); + + Logger.appInfo(bundle.getString("app.name"), bundle.getString("version.name"), bundle.getString("version.code"), bundle.getString("version.date")); } public static void main(String[] args) - { + { launch(args); - } + } } \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/ui/CategoryController.java b/src/de/deadlocker8/budgetmaster/ui/CategoryController.java index 0cdb686ec6f8cef2adb986699347810bbe9e468c..52e908a7fbafa75bb17f8e33b56ac056b2413b14 100644 --- a/src/de/deadlocker8/budgetmaster/ui/CategoryController.java +++ b/src/de/deadlocker8/budgetmaster/ui/CategoryController.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.util.ArrayList; import de.deadlocker8.budgetmaster.logic.Category; +import de.deadlocker8.budgetmaster.logic.ExceptionHandler; import de.deadlocker8.budgetmaster.logic.ServerConnection; import de.deadlocker8.budgetmaster.ui.cells.CategoryCell; import fontAwesome.FontIcon; @@ -162,7 +163,7 @@ public class CategoryController implements Refreshable catch(Exception e) { e.printStackTrace(); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); } } diff --git a/src/de/deadlocker8/budgetmaster/ui/Controller.java b/src/de/deadlocker8/budgetmaster/ui/Controller.java index 785fe987806364bddda3c01e0bde140bf2e28ee8..1888e00c172aa44f43048e5eed571a1b914f8647 100644 --- a/src/de/deadlocker8/budgetmaster/ui/Controller.java +++ b/src/de/deadlocker8/budgetmaster/ui/Controller.java @@ -9,6 +9,7 @@ import org.joda.time.DateTime; import de.deadlocker8.budgetmaster.logic.CategoryBudget; import de.deadlocker8.budgetmaster.logic.CategoryHandler; +import de.deadlocker8.budgetmaster.logic.ExceptionHandler; import de.deadlocker8.budgetmaster.logic.FilterSettings; import de.deadlocker8.budgetmaster.logic.NormalPayment; import de.deadlocker8.budgetmaster.logic.PaymentHandler; @@ -142,6 +143,7 @@ public class Controller { Platform.runLater(() -> { AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Bitte gibt zuerst deine Serverdaten ein!", icon, stage, null, false); + toggleAllTabsExceptSettings(true); tabPane.getSelectionModel().select(tabSettings); }); } @@ -226,23 +228,33 @@ public class Controller return currentDate; } - public void showConnectionErrorAlert() - { + public void showConnectionErrorAlert(String errorMessage) + { if(!alertIsShowing) { Platform.runLater(() -> { + toggleAllTabsExceptSettings(true); + tabPane.getSelectionModel().select(tabSettings); + alertIsShowing = true; Alert alert = new Alert(AlertType.ERROR); alert.setTitle("Fehler"); alert.setHeaderText(""); - alert.setContentText("Beim Herstellen der Verbindung zum Server ist ein Fehler aufgetreten. Bitte überprüfe deine Einstellungen und ob der Server läuft."); + if(errorMessage == null) + { + alert.setContentText("Beim Herstellen der Verbindung zum Server ist ein Fehler aufgetreten. Bitte überprüfe deine Einstellungen und ob der Server läuft."); + } + else + { + alert.setContentText("Beim Herstellen der Verbindung zum Server ist ein Fehler aufgetreten. Bitte überprüfe deine Einstellungen und ob der Server läuft.\n\n" + + "Fehlerdetails:\n" + errorMessage); + } + Stage dialogStage = (Stage)alert.getDialogPane().getScene().getWindow(); dialogStage.getIcons().add(icon); dialogStage.initOwner(stage); - dialogStage.setOnCloseRequest((event) -> { - alertIsShowing = false; - }); alert.showAndWait(); + alertIsShowing = false; }); } } @@ -279,6 +291,14 @@ public class Controller { this.filterSettings = filterSettings; } + + public void toggleAllTabsExceptSettings(boolean disable) + { + tabHome.setDisable(disable); + tabPayments.setDisable(disable); + tabCategories.setDisable(disable); + tabCharts.setDisable(disable); + } public void about() { @@ -289,7 +309,7 @@ public class Controller { try { - ServerConnection connection = new ServerConnection(settings); + ServerConnection connection = new ServerConnection(settings); paymentHandler = new PaymentHandler(); paymentHandler.getPayments().addAll(connection.getPayments(currentDate.getYear(), currentDate.getMonthOfYear())); @@ -306,12 +326,14 @@ public class Controller categoryBudgets = connection.getCategoryBudgets(currentDate.getYear(), currentDate.getMonthOfYear()); paymentHandler.filter(newFilterSettings); + + toggleAllTabsExceptSettings(false); } catch(Exception e) { Logger.error(e); - categoryHandler = new CategoryHandler(null); - showConnectionErrorAlert(); + categoryHandler = new CategoryHandler(null); + showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); } refreshAllTabs(); diff --git a/src/de/deadlocker8/budgetmaster/ui/HomeController.java b/src/de/deadlocker8/budgetmaster/ui/HomeController.java index ab2bb352069d6ad6a76237b90cd55989d57e64f4..a17c5d1effb508eaa3c5b2fafacf6e9ca34024ed 100644 --- a/src/de/deadlocker8/budgetmaster/ui/HomeController.java +++ b/src/de/deadlocker8/budgetmaster/ui/HomeController.java @@ -77,7 +77,12 @@ public class HomeController implements Refreshable { Budget budget = new Budget(controller.getPaymentHandler().getPayments()); double remaining = budget.getIncomeSum() + budget.getPaymentSum(); - labelBudget.setText(String.valueOf(Helpers.NUMBER_FORMAT.format(remaining).replace(".", ",")) + " " + controller.getSettings().getCurrency()); + String currency = "€"; + if(controller.getSettings() != null) + { + currency = controller.getSettings().getCurrency(); + } + labelBudget.setText(String.valueOf(Helpers.NUMBER_FORMAT.format(remaining).replace(".", ",")) + " " + currency); if(remaining <= 0) { labelBudget.setStyle("-fx-text-fill: #CC0000"); @@ -86,7 +91,7 @@ public class HomeController implements Refreshable { labelBudget.setStyle("-fx-text-fill: " + controller.getBundle().getString("color.text")); } - labelStartBudget.setText("von " + String.valueOf(Helpers.NUMBER_FORMAT.format(budget.getIncomeSum()).replace(".", ",")) + " " + controller.getSettings().getCurrency() + " verbleibend"); + labelStartBudget.setText("von " + String.valueOf(Helpers.NUMBER_FORMAT.format(budget.getIncomeSum()).replace(".", ",")) + " " + currency + " verbleibend"); double factor = remaining / budget.getIncomeSum(); if(factor < 0) diff --git a/src/de/deadlocker8/budgetmaster/ui/Modal.fxml b/src/de/deadlocker8/budgetmaster/ui/Modal.fxml new file mode 100644 index 0000000000000000000000000000000000000000..33759ff9bb89cf861f75e900f957f48ee27a25fd --- /dev/null +++ b/src/de/deadlocker8/budgetmaster/ui/Modal.fxml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ProgressIndicator?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.text.Font?> + +<AnchorPane fx:id="anchorPaneMain" prefHeight="100.0" prefWidth="375.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="de.deadlocker8.budgetmaster.ui.ModalController"> + <children> + <HBox alignment="CENTER_LEFT" spacing="10.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="14.0"> + <children> + <Label fx:id="labelMessage" maxWidth="1.7976931348623157E308" HBox.hgrow="ALWAYS"> + <font> + <Font size="15.0" /> + </font> + </Label> + <ProgressIndicator prefHeight="72.0" prefWidth="34.0" /> + </children> + </HBox> + </children> +</AnchorPane> diff --git a/src/de/deadlocker8/budgetmaster/ui/ModalController.java b/src/de/deadlocker8/budgetmaster/ui/ModalController.java new file mode 100644 index 0000000000000000000000000000000000000000..042c7345a46f1f688df26dc19bf4eaf82a317c42 --- /dev/null +++ b/src/de/deadlocker8/budgetmaster/ui/ModalController.java @@ -0,0 +1,18 @@ +package de.deadlocker8.budgetmaster.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.stage.Stage; + +public class ModalController +{ + @FXML private Label labelMessage; + + public void init(Stage stage, String message) + { + labelMessage.setText(message); + stage.setOnCloseRequest((e)->{ + e.consume(); + }); + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java b/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java index 4a94063bfc834cc950c48a9956a696740eb65fb2..d0ab8dd13f7a575c5765ed274ec99d023d3b1534 100644 --- a/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java +++ b/src/de/deadlocker8/budgetmaster/ui/NewCategoryController.java @@ -6,6 +6,7 @@ import org.controlsfx.control.PopOver; import org.controlsfx.control.PopOver.ArrowLocation; import de.deadlocker8.budgetmaster.logic.Category; +import de.deadlocker8.budgetmaster.logic.ExceptionHandler; import de.deadlocker8.budgetmaster.logic.ServerConnection; import fontAwesome.FontIcon; import fontAwesome.FontIconType; @@ -135,6 +136,12 @@ public class NewCategoryController return; } + if(name.length() > 45) + { + AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Der Name darf maximal 45 Zeichen lang sein.", controller.getIcon(), controller.getStage(), null, false); + return; + } + if(edit) { category.setName(name); @@ -147,7 +154,7 @@ public class NewCategoryController } catch(Exception e) { - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); } } else @@ -161,7 +168,7 @@ public class NewCategoryController } catch(Exception e) { - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(e.getMessage()); } } diff --git a/src/de/deadlocker8/budgetmaster/ui/NewCategoryGUI.fxml b/src/de/deadlocker8/budgetmaster/ui/NewCategoryGUI.fxml index 9a6736f6a807a48ae2359b47ada1e91e2bfb6277..203d4acb88da4931ec70ca307d61d331d061861c 100644 --- a/src/de/deadlocker8/budgetmaster/ui/NewCategoryGUI.fxml +++ b/src/de/deadlocker8/budgetmaster/ui/NewCategoryGUI.fxml @@ -15,11 +15,20 @@ <children> <HBox alignment="CENTER_LEFT" prefHeight="30.0" prefWidth="465.0"> <children> - <Label prefHeight="29.0" prefWidth="125.0" text="Name:"> - <font> - <Font name="System Bold" size="14.0" /> - </font> - </Label> + <VBox> + <children> + <Label prefHeight="29.0" prefWidth="125.0" text="Name:"> + <font> + <Font name="System Bold" size="14.0" /> + </font> + </Label> + <Label prefHeight="29.0" prefWidth="125.0" text="(max. 45 Zeichen)"> + <font> + <Font size="11.0" /> + </font> + </Label> + </children> + </VBox> <TextField fx:id="textFieldName" prefHeight="29.0" HBox.hgrow="ALWAYS"> <font> <Font size="13.0" /> diff --git a/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java b/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java index ed8398a8b749967e0b6b6c4d435861ff70b3ed7e..1cdd2f05dc59b1c6400127ab386abcfa60e34f2b 100644 --- a/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java +++ b/src/de/deadlocker8/budgetmaster/ui/NewPaymentController.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import org.joda.time.DateTime; import de.deadlocker8.budgetmaster.logic.Category; +import de.deadlocker8.budgetmaster.logic.ExceptionHandler; import de.deadlocker8.budgetmaster.logic.Helpers; import de.deadlocker8.budgetmaster.logic.NormalPayment; import de.deadlocker8.budgetmaster.logic.Payment; @@ -106,6 +107,7 @@ public class NewPaymentController comboBoxCategory.setCellFactory((view) -> { return new SmallCategoryCell(); }); + comboBoxRepeatingDay.setValue(1); buttonCategoryCell = new ButtonCategoryCell(Color.WHITE); comboBoxCategory.setButtonCell(buttonCategoryCell); comboBoxCategory.setStyle("-fx-border-color: #000000; -fx-border-width: 2; -fx-border-radius: 5; -fx-background-radius: 5;"); @@ -137,7 +139,7 @@ public class NewPaymentController } catch(Exception e) { - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); stage.close(); return; } @@ -235,6 +237,12 @@ public class NewPaymentController AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Das Feld für den Namen darf nicht leer sein.", controller.getIcon(), controller.getStage(), null, false); return; } + + if(name.length() > 150) + { + AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Der Name darf maximal 150 Zeichen lang sein.", controller.getIcon(), controller.getStage(), null, false); + return; + } String amountText = textFieldAmount.getText(); if(!amountText.matches("^-?\\d+(,\\d+)*(\\.\\d+(e\\d+)?)?$")) @@ -316,7 +324,7 @@ public class NewPaymentController catch(Exception e) { Logger.error(e); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); } } else @@ -330,7 +338,7 @@ public class NewPaymentController catch(Exception e) { Logger.error(e); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(e.getMessage()); } } } @@ -356,7 +364,7 @@ public class NewPaymentController catch(Exception e) { Logger.error(e); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(e.getMessage()); } } else @@ -370,7 +378,7 @@ public class NewPaymentController catch(Exception e) { Logger.error(e); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(e.getMessage()); } } } diff --git a/src/de/deadlocker8/budgetmaster/ui/NewPaymentGUI.fxml b/src/de/deadlocker8/budgetmaster/ui/NewPaymentGUI.fxml index 9235231a6402291bd989eb171cb5cfe6d0d201aa..31366e41dd3bded01be30e3b15e6ab06cdce95be 100644 --- a/src/de/deadlocker8/budgetmaster/ui/NewPaymentGUI.fxml +++ b/src/de/deadlocker8/budgetmaster/ui/NewPaymentGUI.fxml @@ -22,11 +22,20 @@ <children> <HBox alignment="CENTER_LEFT" prefHeight="30.0" prefWidth="465.0"> <children> - <Label prefHeight="29.0" prefWidth="125.0" text="Name:"> - <font> - <Font name="System Bold" size="14.0" /> - </font> - </Label> + <VBox> + <children> + <Label prefHeight="29.0" prefWidth="125.0" text="Name:"> + <font> + <Font name="System Bold" size="14.0" /> + </font> + </Label> + <Label prefHeight="29.0" prefWidth="125.0" text="(max. 150 Zeichen)"> + <font> + <Font size="11.0" /> + </font> + </Label> + </children> + </VBox> <TextField fx:id="textFieldName" prefHeight="29.0" HBox.hgrow="ALWAYS"> <font> <Font size="13.0" /> diff --git a/src/de/deadlocker8/budgetmaster/ui/PaymentController.java b/src/de/deadlocker8/budgetmaster/ui/PaymentController.java index db5adcc84d3d952eae84f269b1acce9e1e9d976e..c4b7cc52c7d3ea25d3030b59c9c2c4c165637487 100644 --- a/src/de/deadlocker8/budgetmaster/ui/PaymentController.java +++ b/src/de/deadlocker8/budgetmaster/ui/PaymentController.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.ArrayList; import de.deadlocker8.budgetmaster.logic.Budget; +import de.deadlocker8.budgetmaster.logic.ExceptionHandler; import de.deadlocker8.budgetmaster.logic.FilterSettings; import de.deadlocker8.budgetmaster.logic.Helpers; import de.deadlocker8.budgetmaster.logic.NormalPayment; @@ -74,6 +75,7 @@ public class PaymentController implements Refreshable } } }); + cell.prefWidthProperty().bind(listView.widthProperty().subtract(2)); return cell; } }); @@ -204,7 +206,7 @@ public class PaymentController implements Refreshable catch(Exception e) { e.printStackTrace(); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); } } @@ -219,7 +221,7 @@ public class PaymentController implements Refreshable catch(Exception e) { e.printStackTrace(); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); } } @@ -238,7 +240,7 @@ public class PaymentController implements Refreshable catch(Exception e) { e.printStackTrace(); - controller.showConnectionErrorAlert(); + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); } } diff --git a/src/de/deadlocker8/budgetmaster/ui/SettingsController.java b/src/de/deadlocker8/budgetmaster/ui/SettingsController.java index 471619dc9dbe1c4788c6de5b70a64e7354e13d9f..c96a8494d388876dc1e6ce10551dbf9e44ca23c4 100644 --- a/src/de/deadlocker8/budgetmaster/ui/SettingsController.java +++ b/src/de/deadlocker8/budgetmaster/ui/SettingsController.java @@ -1,19 +1,43 @@ package de.deadlocker8.budgetmaster.ui; +import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Optional; +import de.deadlocker8.budgetmaster.logic.ExceptionHandler; +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; import javafx.scene.control.TextField; +import javafx.scene.control.TextInputDialog; import javafx.scene.control.ToggleGroup; import javafx.scene.layout.AnchorPane; +import javafx.stage.FileChooser; +import javafx.stage.Modality; +import javafx.stage.Stage; import logger.Logger; import tools.AlertGenerator; +import tools.BASE58Type; +import tools.ConvertTo; +import tools.HashUtils; +import tools.RandomCreations; +import tools.Worker; public class SettingsController { @@ -25,8 +49,12 @@ public class SettingsController @FXML private TextField textFieldCurrency; @FXML private Label labelCurrency; @FXML private Button buttonSave; + @FXML private Button buttonExportDB; + @FXML private Button buttonImportDB; + @FXML private Button buttonDeleteDB; @FXML private RadioButton radioButtonRestActivated; @FXML private RadioButton radioButtonRestDeactivated; + @FXML private TextArea textAreaTrustedHosts; private Controller controller; @@ -36,7 +64,7 @@ public class SettingsController if(controller.getSettings() != null) { textFieldURL.setText(controller.getSettings().getUrl()); - textFieldSecret.setText(controller.getSettings().getSecret()); + textFieldSecret.setText("******"); textFieldCurrency.setText(controller.getSettings().getCurrency()); if(controller.getSettings().isRestActivated()) { @@ -46,74 +74,326 @@ public class SettingsController { radioButtonRestDeactivated.setSelected(true); } + setTextAreaTrustedHosts(controller.getSettings().getTrustedHosts()); } - + anchorPaneMain.setStyle("-fx-background-color: #F4F4F4;"); labelSecret.setStyle("-fx-text-fill: " + controller.getBundle().getString("color.text")); 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;"); + buttonSave.setStyle("-fx-background-color: #2E79B9; -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"); + ToggleGroup toggleGroup = new ToggleGroup(); radioButtonRestActivated.setToggleGroup(toggleGroup); radioButtonRestDeactivated.setToggleGroup(toggleGroup); } - + + private void setTextAreaTrustedHosts(ArrayList<String> trustedHosts) + { + StringBuilder trustedHostsString = new StringBuilder(); + if(trustedHosts != null) + { + for(String currentHost : trustedHosts) + { + trustedHostsString.append(currentHost); + trustedHostsString.append("\n"); + } + textAreaTrustedHosts.setText(trustedHostsString.toString()); + } + else + { + textAreaTrustedHosts.setText(""); + } + } + public void save() { String url = textFieldURL.getText().trim(); String secret = textFieldSecret.getText().trim(); String currency = textFieldCurrency.getText().trim(); - if(url != null && !url.equals("")) + if(url == null || url.equals("")) + { + AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Das Feld für die Server URL darf nicht leer sein!", controller.getIcon(), controller.getStage(), null, false); + return; + } + + if(secret == null || secret.equals("")) + { + AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Das Server Passwortfeld darf nicht leer sein!", controller.getIcon(), controller.getStage(), null, false); + return; + } + + if(currency == null || currency.equals("")) + { + AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Bitte gib deine gewünschte Währung ein!", controller.getIcon(), controller.getStage(), null, false); + return; + } + + ArrayList<String> trustedHosts = new ArrayList<>(); + String trustedHostText = textAreaTrustedHosts.getText(); + String[] trustedHostsArray = trustedHostText.split("\n"); + for(String currentHost : trustedHostsArray) + { + currentHost = currentHost.trim(); + if(!currentHost.equals("")) + { + trustedHosts.add(currentHost); + } + } + setTextAreaTrustedHosts(trustedHosts); + + if(controller.getSettings() != null) { - if(secret != null && !secret.equals("")) + if(!secret.equals("******")) { - if(currency != null && !currency.equals("")) + controller.getSettings().setSecret(HashUtils.hash(secret, Helpers.SALT)); + } + controller.getSettings().setUrl(url); + controller.getSettings().setCurrency(currency); + controller.getSettings().setRestActivated(radioButtonRestActivated.isSelected()); + controller.getSettings().setTrustedHosts(trustedHosts); + } + else + { + Settings settings = new Settings(); + settings.setUrl(url); + settings.setSecret(HashUtils.hash(secret, Helpers.SALT)); + settings.setCurrency(currency); + settings.setRestActivated(radioButtonRestActivated.isSelected()); + settings.setTrustedHosts(trustedHosts); + controller.setSettings(settings); + } + + try + { + Utils.saveSettings(controller.getSettings()); + } + catch(IOException e) + { + Logger.error(e); + AlertGenerator.showAlert(AlertType.ERROR, "Fehler", "", "Beim Speichern der Einstellungen ist ein Fehler aufgetreten", controller.getIcon(), controller.getStage(), null, false); + } + + textFieldSecret.setText("******"); + + controller.refresh(controller.getFilterSettings()); + controller.showNotification("Erfolgreich gespeichert"); + } + + public void exportDB() + { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Datenbank exportieren"); + FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("JSON (*.json)", "*.json"); + fileChooser.getExtensionFilters().add(extFilter); + File file = fileChooser.showSaveDialog(controller.getStage()); + if(file != null) + { + Stage modalStage = showModal("Vorgang läuft", "Die Datenbank wird exportiert, bitte warten..."); + + Worker.runLater(() -> { + try { - if(controller.getSettings() != null) - { - controller.getSettings().setUrl(url); - controller.getSettings().setSecret(secret); - controller.getSettings().setCurrency(currency); - controller.getSettings().setRestActivated(radioButtonRestActivated.isSelected()); - } - else - { - Settings settings = new Settings(); - settings.setUrl(url); - settings.setSecret(secret); - settings.setCurrency(currency); - settings.setRestActivated(radioButtonRestActivated.isSelected()); - controller.setSettings(settings); - } - + ServerConnection connection = new ServerConnection(controller.getSettings()); + String databaseJSON = connection.exportDatabase(); + Utils.saveDatabaseJSON(file, databaseJSON); + + Platform.runLater(() -> { + if(modalStage != null) + { + modalStage.close(); + } + AlertGenerator.showAlert(AlertType.INFORMATION, "Erfolgreich exportiert", "", "Die Datenbank wurder erfolgreich exportiert.", controller.getIcon(), controller.getStage(), null, false); + }); + } + catch(Exception e) + { + Logger.error(e); + Platform.runLater(() -> { + if(modalStage != null) + { + modalStage.close(); + } + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); + }); + } + }); + } + } + + 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(() -> { + if(modalStage != null) + { + modalStage.close(); + } + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); + }); + } + }); + } + } + + 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); + + TextInputDialog dialog = new TextInputDialog(); + dialog.setTitle("Datenbank löschen"); + dialog.setHeaderText("Soll die Datenbank wirklich gelöscht werden?"); + dialog.setContentText("Zur Bestätigung gib folgenden Code ein:\t" + verificationCode); + Stage dialogStage = (Stage)dialog.getDialogPane().getScene().getWindow(); + dialogStage.getIcons().add(controller.getIcon()); + dialogStage.initOwner(controller.getStage()); + + Optional<String> result = dialog.showAndWait(); + if(result.isPresent()) + { + if(result.get().equals(verificationCode)) + { + Stage modalStage = showModal("Vorgang läuft", "Die Datenbank wird gelöscht, bitte warten..."); + + Worker.runLater(() -> { try { - Utils.saveSettings(controller.getSettings()); + ServerConnection connection = new ServerConnection(controller.getSettings()); + connection.deleteDatabase(); + Platform.runLater(() -> { + if(modalStage != null) + { + modalStage.close(); + if(importPending) + { + importDatabase(); + } + } + }); } - catch(IOException e) + catch(Exception e) { Logger.error(e); - AlertGenerator.showAlert(AlertType.ERROR, "Fehler", "", "Beim Speichern der Einstellungen ist ein Fehler aufgetreten", controller.getIcon(), controller.getStage(), null, false); - } - controller.refresh(controller.getFilterSettings()); - controller.showNotification("Erfolgreich gespeichert"); - } - else - { - AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Bitte gib deine gewünschte Währung ein!", controller.getIcon(), controller.getStage(), null, false); - } + Platform.runLater(() -> { + if(modalStage != null) + { + modalStage.close(); + } + controller.showConnectionErrorAlert(ExceptionHandler.getMessageForException(e)); + }); + } + }); } else { - AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Das Server Passwortfeld darf nicht leer sein!", controller.getIcon(), controller.getStage(), null, false); + AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Die Eingabe stimmt nicht mit dem Bestätigungscode überein.", controller.getIcon(), controller.getStage(), null, false); + deleteDB(); } } - else + } + + private Stage showModal(String title, String message) + { + try { - AlertGenerator.showAlert(AlertType.WARNING, "Warnung", "", "Das Feld für die Server URL darf nicht leer sein!", controller.getIcon(), controller.getStage(), null, false); + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/de/deadlocker8/budgetmaster/ui/Modal.fxml")); + Parent root = (Parent)fxmlLoader.load(); + Stage newStage = new Stage(); + newStage.initOwner(controller.getStage()); + newStage.initModality(Modality.APPLICATION_MODAL); + newStage.setTitle(title); + newStage.setScene(new Scene(root)); + newStage.getIcons().add(controller.getIcon()); + newStage.setResizable(false); + ModalController newController = fxmlLoader.getController(); + newController.init(newStage, message); + newStage.show(); + + return newStage; + } + catch(IOException e) + { + Logger.error(e); + return null; } } } \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml b/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml index 0fc94536e52887e64a3a83aaab44298d89253d10..8014a8cab8429d648976e326a52d09a1abbe935d 100644 --- a/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml +++ b/src/de/deadlocker8/budgetmaster/ui/SettingsTab.fxml @@ -4,9 +4,11 @@ <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.RadioButton?> +<?import javafx.scene.control.TextArea?> <?import javafx.scene.control.TextField?> <?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.Region?> <?import javafx.scene.layout.VBox?> <?import javafx.scene.text.Font?> @@ -14,7 +16,7 @@ <children> <VBox alignment="TOP_CENTER" layoutY="24.0" prefHeight="562.0" prefWidth="772.0" spacing="25.0" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="14.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="25.0"> <children> - <HBox prefHeight="70.0"> + <HBox prefHeight="359.0" prefWidth="722.0"> <children> <VBox alignment="CENTER_RIGHT" prefHeight="25.0" prefWidth="158.0" spacing="20.0"> <children> @@ -41,6 +43,39 @@ <Font name="System Bold" size="16.0" /> </font> </Label> + <Label fx:id="labelSecret111" alignment="CENTER_RIGHT" contentDisplay="RIGHT" maxHeight="-Infinity" minHeight="60.0" prefWidth="158.0" text="Vertrauenswürdige Hosts:" textAlignment="RIGHT" wrapText="true"> + <font> + <Font name="System Bold" size="16.0" /> + </font> + <VBox.margin> + <Insets top="-5.0" /> + </VBox.margin> + </Label> + <Label fx:id="labelSecret1111" alignment="CENTER" contentDisplay="CENTER" maxHeight="-Infinity" text="(ein Host pro Zeile)" textAlignment="CENTER" wrapText="true" VBox.vgrow="ALWAYS"> + <font> + <Font size="14.0" /> + </font> + <VBox.margin> + <Insets top="-20.0" /> + </VBox.margin> + </Label> + <Label fx:id="labelSecret1112" alignment="CENTER_RIGHT" contentDisplay="RIGHT" maxHeight="-Infinity" prefWidth="158.0" text="Datenbank:" textAlignment="RIGHT" wrapText="true"> + <font> + <Font name="System Bold" size="16.0" /> + </font> + <VBox.margin> + <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> <Insets right="25.0" /> @@ -51,14 +86,14 @@ <TextField fx:id="textFieldURL" /> <TextField fx:id="textFieldSecret" /> <TextField fx:id="textFieldCurrency" /> - <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0"> + <HBox alignment="CENTER" prefHeight="11.0" prefWidth="539.0" spacing="30.0"> <children> <RadioButton fx:id="radioButtonRestActivated" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="aktiviert"> <font> <Font size="14.0" /> </font> <HBox.margin> - <Insets right="30.0" /> + <Insets /> </HBox.margin> </RadioButton> <RadioButton fx:id="radioButtonRestDeactivated" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="deaktiviert" HBox.hgrow="ALWAYS"> @@ -68,15 +103,45 @@ </RadioButton> </children> </HBox> + <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="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> + </Button> + <Button fx:id="buttonDeleteDB" mnemonicParsing="false" onAction="#deleteDB" text="Löschen"> + <font> + <Font name="System Bold" size="14.0" /> + </font> + </Button> + </children> + <VBox.margin> + <Insets /> + </VBox.margin> + </HBox> + <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" /> diff --git a/src/de/deadlocker8/budgetmaster/ui/cells/PaymentCell.java b/src/de/deadlocker8/budgetmaster/ui/cells/PaymentCell.java index dfdd6c5a8b4d299a7b54827e40c47bb4eefbe7aa..e096c9a72a0c14fdabd8972136b64e235e739ac2 100644 --- a/src/de/deadlocker8/budgetmaster/ui/cells/PaymentCell.java +++ b/src/de/deadlocker8/budgetmaster/ui/cells/PaymentCell.java @@ -69,6 +69,7 @@ public class PaymentCell extends ListCell<Payment> labelDate.setAlignment(Pos.CENTER); labelDate.getStyleClass().add("greylabel"); labelDate.setStyle("-fx-font-weight: bold; -fx-font-size: 16; -fx-text-fill: #212121"); + labelDate.setMinWidth(75); hbox.getChildren().add(labelDate); FontIcon iconRepeating = new FontIcon(FontIconType.CALENDAR); @@ -88,7 +89,7 @@ public class PaymentCell extends ListCell<Payment> labelRepeating.setAlignment(Pos.CENTER); labelRepeating.getStyleClass().add("greylabel"); hbox.getChildren().add(labelRepeating); - HBox.setMargin(labelRepeating, new Insets(0, 30, 0, 15)); + HBox.setMargin(labelRepeating, new Insets(0, 20, 0, 15)); String categoryName = category.getName(); if(categoryName.equals("NONE")) @@ -97,8 +98,8 @@ public class PaymentCell extends ListCell<Payment> } Label labelCircle = new Label(categoryName.substring(0, 1).toUpperCase()); - labelCircle.setPrefWidth(HEIGHT); - labelCircle.setPrefHeight(HEIGHT); + labelCircle.setMinWidth(HEIGHT); + labelCircle.setMinHeight(HEIGHT); labelCircle.setAlignment(Pos.CENTER); labelCircle.getStyleClass().add("greylabel"); String textColor = ConvertTo.toRGBHex(ConvertTo.getAppropriateTextColor(category.getColor())); @@ -106,14 +107,13 @@ public class PaymentCell extends ListCell<Payment> Tooltip tooltip = new Tooltip(categoryName); tooltip.setStyle("-fx-font-size: 14"); labelCircle.setTooltip(tooltip); - hbox.getChildren().add(labelCircle); - + hbox.getChildren().add(labelCircle); Label labelName = new Label(item.getName()); labelName.setPrefHeight(HEIGHT); labelName.setStyle("-fx-font-weight: bold; -fx-font-size: 16; -fx-text-fill: #212121"); labelName.setAlignment(Pos.CENTER); - labelName.getStyleClass().add("greylabel"); + labelName.getStyleClass().add("greylabel"); hbox.getChildren().add(labelName); HBox.setMargin(labelName, new Insets(0, 0, 0, 20)); @@ -126,6 +126,7 @@ public class PaymentCell extends ListCell<Payment> labelBudget.setStyle("-fx-font-weight: bold; -fx-font-size: 16; -fx-text-fill: #247A2D"); labelBudget.setAlignment(Pos.CENTER); labelBudget.getStyleClass().add("greylabel"); + labelBudget.setMinWidth(90); hbox.getChildren().add(labelBudget); HBox.setMargin(labelBudget, new Insets(0, 0, 0, 20)); @@ -185,14 +186,14 @@ public class PaymentCell extends ListCell<Payment> } }); hbox.getChildren().add(buttonDelete); - HBox.setMargin(buttonDelete, new Insets(0, 0, 0, 25)); + HBox.setMargin(buttonDelete, new Insets(0, 0, 0, 10)); // don't allow "Übertrag" to be deleted if(item.getID() == -1) { buttonDelete.setVisible(false); } - hbox.setPadding(new Insets(10)); + hbox.setPadding(new Insets(10, 8, 10, 5)); setStyle("-fx-background: transparent; -fx-border-color: #545454; -fx-border-width: 0 0 1 0"); setGraphic(hbox); setAlignment(Pos.CENTER); diff --git a/src/de/deadlocker8/budgetmasterserver/main/Database.java b/src/de/deadlocker8/budgetmasterserver/main/Database.java new file mode 100644 index 0000000000000000000000000000000000000000..e4d927792ff3c9377a634e99735ca18f82da0cf6 --- /dev/null +++ b/src/de/deadlocker8/budgetmasterserver/main/Database.java @@ -0,0 +1,41 @@ +package de.deadlocker8.budgetmasterserver.main; + +import java.util.ArrayList; + +import de.deadlocker8.budgetmaster.logic.Category; +import de.deadlocker8.budgetmaster.logic.NormalPayment; +import de.deadlocker8.budgetmaster.logic.RepeatingPayment; + +public class Database +{ + private ArrayList<Category> categories; + private ArrayList<NormalPayment> normalPayments; + private ArrayList<RepeatingPayment> repeatingPayments; + + public Database() + { + + } + + public Database(ArrayList<Category> categories, ArrayList<NormalPayment> normalPayments, ArrayList<RepeatingPayment> repeatingPayments) + { + this.categories = categories; + this.normalPayments = normalPayments; + this.repeatingPayments = repeatingPayments; + } + + public ArrayList<Category> getCategories() + { + return categories; + } + + public ArrayList<NormalPayment> getNormalPayments() + { + return normalPayments; + } + + public ArrayList<RepeatingPayment> getRepeatingPayments() + { + return repeatingPayments; + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmasterserver/main/DatabaseCreator.java b/src/de/deadlocker8/budgetmasterserver/main/DatabaseCreator.java index 7a512f12e66f69b9d9b4a4a98e7a0794ad959f34..90fc9452b4e7008e66cb493e3da72b35f35a4654 100644 --- a/src/de/deadlocker8/budgetmasterserver/main/DatabaseCreator.java +++ b/src/de/deadlocker8/budgetmasterserver/main/DatabaseCreator.java @@ -109,7 +109,7 @@ public class DatabaseCreator Statement stmt = null; String query = "CREATE TABLE `payment` (" + "`ID` int(11) NOT NULL COMMENT 'ID'," + - "`Name` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'payment name (description)'," + + "`Name` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'payment name (description)'," + "`CategoryID` int(11) DEFAULT NULL COMMENT 'category ID'," + "`Amount` int(11) DEFAULT NULL COMMENT 'amount in cents'," + "`Date` date DEFAULT NULL COMMENT 'payment date'," + @@ -190,7 +190,7 @@ public class DatabaseCreator Statement stmt = null; String query = "CREATE TABLE `repeating_payment` (" + "`ID` int(11) NOT NULL COMMENT 'ID'," + - "`Name` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'payment name (description)'," + + "`Name` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'payment name (description)'," + "`CategoryID` int(11) DEFAULT NULL COMMENT 'category ID'," + "`Amount` int(11) DEFAULT NULL COMMENT 'amount in cents'," + "`Date` date DEFAULT NULL COMMENT 'payment date'," + diff --git a/src/de/deadlocker8/budgetmasterserver/main/DatabaseExporter.java b/src/de/deadlocker8/budgetmasterserver/main/DatabaseExporter.java new file mode 100644 index 0000000000000000000000000000000000000000..c89d0ba1e058dd8357f915d9b8667b2599eb710f --- /dev/null +++ b/src/de/deadlocker8/budgetmasterserver/main/DatabaseExporter.java @@ -0,0 +1,171 @@ +package de.deadlocker8.budgetmasterserver.main; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; + +import de.deadlocker8.budgetmaster.logic.Category; +import de.deadlocker8.budgetmaster.logic.NormalPayment; +import de.deadlocker8.budgetmaster.logic.RepeatingPayment; +import javafx.scene.paint.Color; +import logger.Logger; + +public class DatabaseExporter +{ + private Connection connection; + + public DatabaseExporter(Settings settings) throws IllegalStateException + { + try + { + this.connection = DriverManager.getConnection(settings.getDatabaseUrl() + settings.getDatabaseName() + "?useLegacyDatetimeCode=false&serverTimezone=Europe/Berlin", settings.getDatabaseUsername(), settings.getDatabasePassword()); + } + catch(Exception e) + { + Logger.error(e); + throw new IllegalStateException("Cannot connect the database!", e); + } + } + + public Database exportDatabase() + { + ArrayList<Category> categories = getAllCategories(); + ArrayList<NormalPayment> normalPayments = getAllNormalPayments(); + ArrayList<RepeatingPayment> repeatingPayments = getAllRepeatingPayments(); + + return new Database(categories, normalPayments, repeatingPayments); + } + + private ArrayList<Category> getAllCategories() + { + Statement stmt = null; + String query = "SELECT * FROM category ORDER BY category.ID"; + ArrayList<Category> results = new ArrayList<>(); + try + { + stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(query); + while(rs.next()) + { + int id = rs.getInt("ID"); + String name = rs.getString("Name"); + String color = rs.getString("Color"); + + results.add(new Category(id, name, Color.web(color))); + } + } + catch(SQLException e) + { + Logger.error(e); + } + finally + { + if(stmt != null) + { + try + { + stmt.close(); + } + catch(SQLException e) + { + } + } + } + + return results; + } + + private ArrayList<NormalPayment> getAllNormalPayments() + { + Statement stmt = null; + String query = "SELECT * FROM payment;"; + + ArrayList<NormalPayment> results = new ArrayList<>(); + try + { + stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(query); + + while(rs.next()) + { + int resultID = rs.getInt("ID"); + String name = rs.getString("Name"); + int amount = rs.getInt("amount"); + String date = rs.getString("Date"); + int categoryID = rs.getInt("CategoryID"); + String description = rs.getString("Description"); + + results.add(new NormalPayment(resultID, amount, date, categoryID, name, description)); + } + } + catch(SQLException e) + { + Logger.error(e); + } + finally + { + if(stmt != null) + { + try + { + stmt.close(); + } + catch(SQLException e) + { + } + } + } + + return results; + } + + private ArrayList<RepeatingPayment> getAllRepeatingPayments() + { + Statement stmt = null; + String query = "SELECT * FROM repeating_payment;"; + + ArrayList<RepeatingPayment> results = new ArrayList<>(); + try + { + stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery(query); + + while(rs.next()) + { + int resultID = rs.getInt("ID"); + String name = rs.getString("Name"); + String description = rs.getString("Description"); + int amount = rs.getInt("amount"); + String date = rs.getString("Date"); + int categoryID = rs.getInt("CategoryID"); + int repeatInterval = rs.getInt("RepeatInterval"); + String repeatEndDate = rs.getString("RepeatEndDate"); + int repeatMonthDay = rs.getInt("RepeatMonthDay"); + + results.add(new RepeatingPayment(resultID, amount, date, categoryID, name, description, repeatInterval, repeatEndDate, repeatMonthDay)); + } + } + catch(SQLException e) + { + Logger.error(e); + } + finally + { + if(stmt != null) + { + try + { + stmt.close(); + } + catch(SQLException e) + { + } + } + } + + return results; + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmasterserver/main/DatabaseHandler.java b/src/de/deadlocker8/budgetmasterserver/main/DatabaseHandler.java index cae8ee9afe0489a217d66b69c34cdd10da0053ea..ebb47565aedf5c1f614acd25ec7d9abe90097951 100644 --- a/src/de/deadlocker8/budgetmasterserver/main/DatabaseHandler.java +++ b/src/de/deadlocker8/budgetmasterserver/main/DatabaseHandler.java @@ -56,7 +56,15 @@ public class DatabaseHandler while(rs.next()) { - dateTime = formatter.parseDateTime(rs.getString("min")); + String min = rs.getString("min"); + if(min == null) + { + dateTime = null; + } + else + { + dateTime = formatter.parseDateTime(rs.getString("min")); + } } } catch(SQLException e) @@ -79,7 +87,7 @@ public class DatabaseHandler return dateTime; } - + public DateTime getFirstRepeatingPaymentDate() { Statement stmt = null; @@ -92,7 +100,15 @@ public class DatabaseHandler while(rs.next()) { - dateTime = formatter.parseDateTime(rs.getString("min")); + String min = rs.getString("min"); + if(min == null) + { + dateTime = null; + } + else + { + dateTime = formatter.parseDateTime(rs.getString("min")); + } } } catch(SQLException e) @@ -117,20 +133,28 @@ public class DatabaseHandler } public int getRestForAllPreviousMonths(int year, int month) - { + { + DateTimeFormatter formatter = DateTimeFormat.forPattern("MM.yyyy"); + String dateString = String.valueOf(month) + "." + year; + DateTime currentDate = formatter.parseDateTime(dateString); + DateTime firstNormalPaymentDate = getFirstNormalPaymentDate(); + if(firstNormalPaymentDate == null) + { + firstNormalPaymentDate = currentDate; + } DateTime firstRepeatingPaymentDate = getFirstRepeatingPaymentDate(); - + if(firstRepeatingPaymentDate == null) + { + firstRepeatingPaymentDate = currentDate; + } + DateTime firstDate = firstNormalPaymentDate; if(firstRepeatingPaymentDate.isBefore(firstNormalPaymentDate)) { firstDate = firstRepeatingPaymentDate; } - - DateTimeFormatter formatter = DateTimeFormat.forPattern("MM.yyyy"); - String dateString = String.valueOf(month) + "." + year; - DateTime currentDate = formatter.parseDateTime(dateString);// - + if(firstDate.isAfter(currentDate)) { return 0; @@ -139,10 +163,10 @@ public class DatabaseHandler int startYear = firstDate.getYear(); int startMonth = firstDate.getMonthOfYear(); int totalRest = 0; - + while(startYear < year || startMonth < month) { - totalRest += getRest(startYear, startMonth); + totalRest += getRest(startYear, startMonth); startMonth++; if(startMonth > 12) @@ -159,13 +183,13 @@ public class DatabaseHandler ArrayList<Payment> payments = new ArrayList<>(); payments.addAll(getPayments(year, month)); payments.addAll(getRepeatingPayments(year, month)); - + int rest = 0; for(Payment currentPayment : payments) { rest += currentPayment.getAmount(); } - + return rest; } @@ -207,16 +231,16 @@ public class DatabaseHandler return results; } - + public Category getCategory(int ID) { Statement stmt = null; - String query = "SELECT * FROM category WHERE category.ID = " + ID; + String query = "SELECT * FROM category WHERE category.ID = " + ID; Category result = null; try { stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery(query); + ResultSet rs = stmt.executeQuery(query); while(rs.next()) { int id = rs.getInt("ID"); @@ -246,7 +270,7 @@ public class DatabaseHandler return result; } - + public NormalPayment getPayment(int ID) { Statement stmt = null; @@ -302,13 +326,13 @@ public class DatabaseHandler while(rs.next()) { - int resultID = rs.getInt("ID"); + int resultID = rs.getInt("ID"); String name = rs.getString("Name"); int amount = rs.getInt("amount"); - String date = rs.getString("Date"); + String date = rs.getString("Date"); int categoryID = rs.getInt("CategoryID"); String description = rs.getString("Description"); - + results.add(new NormalPayment(resultID, amount, date, categoryID, name, description)); } } @@ -380,7 +404,8 @@ public class DatabaseHandler public ArrayList<RepeatingPaymentEntry> getRepeatingPayments(int year, int month) { Statement stmt = null; - String query = "SELECT repeating_entry.ID, repeating_entry.RepeatingPaymentID, repeating_entry.Date, repeating_payment.Name, repeating_payment.CategoryID, repeating_payment.Amount, repeating_payment.RepeatInterval, repeating_payment.RepeatEndDate, repeating_payment.RepeatMonthDay, repeating_payment.Description FROM repeating_entry, repeating_payment WHERE repeating_entry.RepeatingPaymentID = repeating_payment.ID AND YEAR(repeating_entry.Date) = " + year + " AND MONTH(repeating_entry.Date) = " + month; + String query = "SELECT repeating_entry.ID, repeating_entry.RepeatingPaymentID, repeating_entry.Date, repeating_payment.Name, repeating_payment.CategoryID, repeating_payment.Amount, repeating_payment.RepeatInterval, repeating_payment.RepeatEndDate, repeating_payment.RepeatMonthDay, repeating_payment.Description FROM repeating_entry, repeating_payment WHERE repeating_entry.RepeatingPaymentID = repeating_payment.ID AND YEAR(repeating_entry.Date) = " + + year + " AND MONTH(repeating_entry.Date) = " + month; ArrayList<RepeatingPaymentEntry> results = new ArrayList<>(); try @@ -391,17 +416,17 @@ public class DatabaseHandler while(rs.next()) { int resultID = rs.getInt("ID"); - int repeatingPaymentID = rs.getInt("repeatingPaymentID"); + int repeatingPaymentID = rs.getInt("repeatingPaymentID"); String name = rs.getString("Name"); String description = rs.getString("Description"); int amount = rs.getInt("amount"); - String date = rs.getString("Date"); + String date = rs.getString("Date"); int categoryID = rs.getInt("CategoryID"); int repeatInterval = rs.getInt("RepeatInterval"); String repeatEndDate = rs.getString("RepeatEndDate"); - int repeatMonthDay = rs.getInt("RepeatMonthDay"); - - results.add(new RepeatingPaymentEntry(resultID, repeatingPaymentID, date, amount, categoryID, name, description,repeatInterval, repeatEndDate, repeatMonthDay)); + int repeatMonthDay = rs.getInt("RepeatMonthDay"); + + results.add(new RepeatingPaymentEntry(resultID, repeatingPaymentID, date, amount, categoryID, name, description, repeatInterval, repeatEndDate, repeatMonthDay)); } } catch(SQLException e) @@ -472,9 +497,9 @@ public class DatabaseHandler return results; } - + public ArrayList<RepeatingPayment> getAllRepeatingPayments() - { + { Statement stmt = null; String query = "SELECT * FROM repeating_payment;"; @@ -486,15 +511,15 @@ public class DatabaseHandler while(rs.next()) { - int resultID = rs.getInt("ID"); + int resultID = rs.getInt("ID"); String name = rs.getString("Name"); int amount = rs.getInt("amount"); - String date = rs.getString("Date"); + String date = rs.getString("Date"); String description = rs.getString("Description"); int categoryID = rs.getInt("CategoryID"); int repeatInterval = rs.getInt("RepeatInterval"); String repeatEndDate = rs.getString("RepeatEndDate"); - int repeatMonthDay = rs.getInt("RepeatMonthDay"); + int repeatMonthDay = rs.getInt("RepeatMonthDay"); results.add(new RepeatingPayment(resultID, amount, date, categoryID, name, description, repeatInterval, repeatEndDate, repeatMonthDay)); } @@ -519,7 +544,7 @@ public class DatabaseHandler return results; } - + public ArrayList<LatestRepeatingPayment> getLatestRepeatingPaymentEntries() { Statement stmt = null; @@ -534,9 +559,9 @@ public class DatabaseHandler while(rs.next()) { int resultID = rs.getInt("ID"); - int repeatingPaymentID = rs.getInt("repeatingPaymentID"); + int repeatingPaymentID = rs.getInt("repeatingPaymentID"); String date = rs.getString("LastDate"); - + results.add(new LatestRepeatingPayment(resultID, repeatingPaymentID, date)); } } @@ -560,19 +585,19 @@ public class DatabaseHandler return results; } - + public RepeatingPayment getRepeatingPayment(int ID) { Statement stmt = null; - String query = "SELECT * FROM repeating_payment WHERE ID = " + ID; + String query = "SELECT * FROM repeating_payment WHERE ID = " + ID; RepeatingPayment result = null; try { stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery(query); + ResultSet rs = stmt.executeQuery(query); while(rs.next()) { - int id = rs.getInt("ID"); + int id = rs.getInt("ID"); int amount = rs.getInt("amount"); String date = rs.getString("Date"); int categoryID = rs.getInt("CategoryID"); @@ -636,7 +661,7 @@ public class DatabaseHandler } } } - + public void deletePayment(int ID) { Statement stmt = null; @@ -664,7 +689,7 @@ public class DatabaseHandler } } } - + public void deleteRepeatingPayment(int ID) { Statement stmt = null; @@ -693,6 +718,46 @@ public class DatabaseHandler } } + public void deleteDatabase() + { + Statement stmt = null; + String tableCategory = "DROP TABLE IF EXISTS category;"; + String tablePayment = "DROP TABLE IF EXISTS payment;"; + String tableRepeatingPayment = "DROP TABLE IF EXISTS repeating_payment;"; + String tableRepeatingEntry = "DROP TABLE IF EXISTS repeating_entry;"; + try + { + stmt = connection.createStatement(); + stmt.execute("SET FOREIGN_KEY_CHECKS = 0;"); + stmt.execute(tableCategory); + Logger.info("Deleted table: category"); + stmt.execute(tablePayment); + Logger.info("Deleted table: payment"); + stmt.execute(tableRepeatingPayment); + Logger.info("Deleted table: repeating_payment"); + stmt.execute(tableRepeatingEntry); + Logger.info("Deleted table: repeating_entry"); + stmt.execute("SET FOREIGN_KEY_CHECKS = 1;"); + } + catch(SQLException e) + { + Logger.error(e); + } + finally + { + if(stmt != null) + { + try + { + stmt.close(); + } + catch(SQLException e) + { + } + } + } + } + /* * ADD */ @@ -724,6 +789,35 @@ public class DatabaseHandler } } + public void importCategory(Category category) + { + Statement stmt = null; + String query = "INSERT INTO category (ID, Name, Color) VALUES('" + category.getID() + "', '" + category.getName() + "' , '" + ConvertTo.toRGBHexWithoutOpacity(category.getColor()) + "') ON DUPLICATE KEY UPDATE Name='" + category.getName() + "', Color='" + + ConvertTo.toRGBHexWithoutOpacity(category.getColor()) + "';"; + try + { + stmt = connection.createStatement(); + stmt.execute(query); + } + catch(SQLException e) + { + Logger.error(e); + } + finally + { + if(stmt != null) + { + try + { + stmt.close(); + } + catch(SQLException e) + { + } + } + } + } + public void addNormalPayment(int amount, String date, int categoryID, String name, String description) { Statement stmt = null; @@ -751,21 +845,58 @@ public class DatabaseHandler } } } - + + public void importNormalPayment(NormalPayment payment) + { + if(payment.getDescription() == null) + { + payment.setDescription(""); + } + + Statement stmt = null; + String query = "INSERT INTO payment (ID, Amount, Date, CategoryID, Name, Description) VALUES('" + payment.getID() + "', '" + payment.getAmount() + "' , '" + payment.getDate() + "' , '" + payment.getCategoryID() + "' , '" + payment.getName() + "' , '" + payment.getDescription() + "')" + + "ON DUPLICATE KEY UPDATE Amount='" + payment.getAmount() + "', Date='" + payment.getDate() + "', CategoryID='" + payment.getCategoryID() + "', Name='" + payment.getName() + "', Description='" + payment.getDescription() + "';"; + try + { + stmt = connection.createStatement(); + stmt.execute(query); + } + catch(SQLException e) + { + Logger.error(e); + } + finally + { + if(stmt != null) + { + try + { + stmt.close(); + } + catch(SQLException e) + { + } + } + } + } + public void addRepeatingPayment(int amount, String date, int categoryID, String name, String description, int repeatInterval, String repeatEndDate, int repeatMonthDay) { Statement stmt = null; - String query; - //A is placeholder for empty repeatEndDate - if(repeatEndDate.equals("A") || repeatEndDate == null) - { - query = "INSERT INTO repeating_payment (Amount, Date, CategoryID, Name, RepeatInterval, RepeatEndDate, RepeatMonthDay, Description) VALUES('" + amount + "' , '" + date + "' , '" + categoryID + "' , '" + name + "' , '" + repeatInterval + "' , NULL , '" + repeatMonthDay + "' , '" + description + "');"; + String query; + String correctRepeatEndDate = repeatEndDate; + if(correctRepeatEndDate == null || correctRepeatEndDate.equals("A")) + { + correctRepeatEndDate = "NULL"; } else { - query = "INSERT INTO repeating_payment (Amount, Date, CategoryID, Name, RepeatInterval, RepeatEndDate, RepeatMonthDay, Description) VALUES('" + amount + "' , '" + date + "' , '" + categoryID + "' , '" + name + "' , '" + repeatInterval + "' , '" + repeatEndDate + "' , '" + repeatMonthDay + "' , '" + description + "');"; + correctRepeatEndDate = "'" + correctRepeatEndDate + "'"; } - + + query = "INSERT INTO repeating_payment (Amount, Date, CategoryID, Name, RepeatInterval, RepeatEndDate, RepeatMonthDay, Description) VALUES('" + amount + "' , '" + date + "' , '" + categoryID + "' , '" + name + "' , '" + repeatInterval + "' , " + correctRepeatEndDate + " , '" + repeatMonthDay + + "' , '" + description + "');"; + try { stmt = connection.createStatement(); @@ -789,12 +920,59 @@ public class DatabaseHandler } } } - + + public void importRepeatingPayment(RepeatingPayment payment) + { + Statement stmt = null; + String query; + // A is placeholder for empty repeatEndDate + String repeatEndDate = payment.getRepeatEndDate(); + if(repeatEndDate == null || repeatEndDate.equals("A")) + { + repeatEndDate = "NULL"; + } + else + { + repeatEndDate = "'" + repeatEndDate + "'"; + } + + if(payment.getDescription() == null) + { + payment.setDescription(""); + } + + query = "INSERT INTO repeating_payment (ID, Amount, Date, CategoryID, Name, RepeatInterval, RepeatEndDate, RepeatMonthDay, Description) VALUES('" + payment.getID() + "', '" + payment.getAmount() + "' , '" + payment.getDate() + "' , '" + payment.getCategoryID() + "' , '" + payment.getName() + + "' , '" + payment.getRepeatInterval() + "' ," + repeatEndDate + ", '" + payment.getRepeatMonthDay() + "' , '" + payment.getDescription() + "')" + " ON DUPLICATE KEY UPDATE " + "Amount='" + payment.getAmount() + "', Date='" + payment.getDate() + "', CategoryID='" + + payment.getCategoryID() + "', Name='" + payment.getName() + "', RepeatInterval='" + payment.getRepeatInterval() + "', RepeatEndDate=" + repeatEndDate + ", RepeatMonthDay='" + payment.getRepeatMonthDay() + "', Description='" + payment.getDescription() + "';"; + try + { + stmt = connection.createStatement(); + stmt.execute(query); + } + catch(SQLException e) + { + Logger.error(e); + } + finally + { + if(stmt != null) + { + try + { + stmt.close(); + } + catch(SQLException e) + { + } + } + } + } + public void addRepeatingPaymentEntry(int repeatingPaymentID, String date) { Statement stmt = null; - String query; - query = "INSERT INTO repeating_entry (RepeatingPaymentID, Date) VALUES('" + repeatingPaymentID + "' , '" + date + "');"; + String query; + query = "INSERT INTO repeating_entry (RepeatingPaymentID, Date) VALUES('" + repeatingPaymentID + "' , '" + date + "');"; try { stmt = connection.createStatement(); @@ -848,8 +1026,8 @@ public class DatabaseHandler } } } - } - + } + public void updateNormalPayment(int ID, int amount, String date, int categoryID, String name, String description) { Statement stmt = null; diff --git a/src/de/deadlocker8/budgetmasterserver/main/DatabaseImporter.java b/src/de/deadlocker8/budgetmasterserver/main/DatabaseImporter.java new file mode 100644 index 0000000000000000000000000000000000000000..d76aaa646bc879bd0965e175fe2baa311cb5d82b --- /dev/null +++ b/src/de/deadlocker8/budgetmasterserver/main/DatabaseImporter.java @@ -0,0 +1,48 @@ +package de.deadlocker8.budgetmasterserver.main; + +import java.util.ArrayList; + +import de.deadlocker8.budgetmaster.logic.Category; +import de.deadlocker8.budgetmaster.logic.NormalPayment; +import de.deadlocker8.budgetmaster.logic.RepeatingPayment; + +public class DatabaseImporter +{ + private DatabaseHandler handler; + + public DatabaseImporter(DatabaseHandler handler) throws IllegalStateException + { + this.handler = handler; + } + + public void importDatabase(Database database) + { + importCategories(database.getCategories()); + importNormalPayments(database.getNormalPayments()); + importRepeatingPayments(database.getRepeatingPayments()); + } + + private void importCategories(ArrayList<Category> categories) + { + for(Category currentCategory : categories) + { + handler.importCategory(currentCategory); + } + } + + private void importNormalPayments(ArrayList<NormalPayment> normalPayments) + { + for(NormalPayment currentPayment : normalPayments) + { + handler.importNormalPayment(currentPayment); + } + } + + private void importRepeatingPayments(ArrayList<RepeatingPayment> repeatingPayments) + { + for(RepeatingPayment currentPayment : repeatingPayments) + { + handler.importRepeatingPayment(currentPayment); + } + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmasterserver/main/Main.java b/src/de/deadlocker8/budgetmasterserver/main/Main.java index d2df69c2cf433a2d0254a7b045df54373dca9965..f9c4fd0c4ca100f62da146f4993d63daf07927bc 100644 --- a/src/de/deadlocker8/budgetmasterserver/main/Main.java +++ b/src/de/deadlocker8/budgetmasterserver/main/Main.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Locale; import java.util.ResourceBundle; @@ -24,36 +25,44 @@ public class Main Logger.appInfo(bundle.getString("app.name"), bundle.getString("version.name"), bundle.getString("version.code"), bundle.getString("version.date")); try { - File logFolder = Paths.get(SparkServer.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent().toFile(); - PathUtils.checkFolder(logFolder); + File logFolder = Paths.get(SparkServer.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent().toFile(); Logger.enableFileOutput(logFolder, System.out, System.err, FileOutputMode.COMBINED); } catch(URISyntaxException e1) { Logger.error(e1); - } + } - if(!Files.exists(Paths.get("settings.json"))) + try { + Path settingsPath = Paths.get(Settings.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent().resolve("settings.json"); + + if(!Files.exists(settingsPath)) + { + try + { + Files.copy(SparkServer.class.getClassLoader().getResourceAsStream("de/deadlocker8/budgetmasterserver/resources/settings.json"), settingsPath); + } + catch(IOException e) + { + Logger.error(e); + } + } + + Settings settings; try { - Files.copy(SparkServer.class.getClassLoader().getResourceAsStream("de/deadlocker8/budgetmasterserver/resources/settings.json"), Paths.get("settings.json")); + settings = Utils.loadSettings(); + new SparkServer(settings); } - catch(IOException e) + catch(IOException | URISyntaxException e) { Logger.error(e); } } - - Settings settings; - try - { - settings = Utils.loadSettings(); - new SparkServer(settings); - } - catch(IOException e) - { - Logger.error(e); - } + catch(URISyntaxException e1) + { + Logger.error(e1); + } } -} +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmasterserver/main/Utils.java b/src/de/deadlocker8/budgetmasterserver/main/Utils.java index 417375ffc23b3164fd3e54bbb54fc37c73534438..c7880cbdd343c704ed5749b8b07b66c5672f90e2 100644 --- a/src/de/deadlocker8/budgetmasterserver/main/Utils.java +++ b/src/de/deadlocker8/budgetmasterserver/main/Utils.java @@ -1,6 +1,7 @@ package de.deadlocker8.budgetmasterserver.main; import java.io.IOException; +import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; @@ -8,13 +9,14 @@ import com.google.gson.Gson; public class Utils { - public static Settings loadSettings() throws IOException + public static Settings loadSettings() throws IOException, URISyntaxException { String settingsJSON; Settings settings; Gson gson = new Gson(); - settingsJSON = new String(Files.readAllBytes(Paths.get("settings.json"))); + + settingsJSON = new String(Files.readAllBytes(Paths.get(Settings.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParent().resolve("settings.json"))); settings = gson.fromJson(settingsJSON, Settings.class); return settings; } diff --git a/src/de/deadlocker8/budgetmasterserver/server/SparkServer.java b/src/de/deadlocker8/budgetmasterserver/server/SparkServer.java index b5b450a50ace9761233c0be7da82218dddff9117..506e12159c182251820fe1bd6d1b40629873f12d 100644 --- a/src/de/deadlocker8/budgetmasterserver/server/SparkServer.java +++ b/src/de/deadlocker8/budgetmasterserver/server/SparkServer.java @@ -17,6 +17,7 @@ import org.joda.time.DateTime; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import de.deadlocker8.budgetmaster.logic.Helpers; import de.deadlocker8.budgetmasterserver.main.DatabaseHandler; import de.deadlocker8.budgetmasterserver.main.Settings; import de.deadlocker8.budgetmasterserver.server.category.CategoryAdd; @@ -27,6 +28,9 @@ import de.deadlocker8.budgetmasterserver.server.category.CategoryUpdate; import de.deadlocker8.budgetmasterserver.server.categorybudget.CategoryBudgetGet; import de.deadlocker8.budgetmasterserver.server.charts.CategoryInOutSumForMonth; import de.deadlocker8.budgetmasterserver.server.charts.MonthInOutSum; +import de.deadlocker8.budgetmasterserver.server.database.DatabaseDelete; +import de.deadlocker8.budgetmasterserver.server.database.DatabaseExport; +import de.deadlocker8.budgetmasterserver.server.database.DatabaseImport; import de.deadlocker8.budgetmasterserver.server.payment.normal.PaymentAdd; import de.deadlocker8.budgetmasterserver.server.payment.normal.PaymentDelete; import de.deadlocker8.budgetmasterserver.server.payment.normal.PaymentGet; @@ -40,6 +44,7 @@ import de.deadlocker8.budgetmasterserver.server.updater.RepeatingPaymentUpdater; import logger.Logger; import spark.Spark; import spark.route.RouteOverview; +import tools.HashUtils; public class SparkServer { @@ -79,7 +84,7 @@ public class SparkServer String clientSecret = request.queryMap("secret").value(); - if(clientSecret == null || !clientSecret.equals(settings.getServerSecret())) + if(clientSecret == null || !clientSecret.equals(HashUtils.hash(settings.getServerSecret(), Helpers.SALT))) { halt(401, "Unauthorized"); } @@ -111,12 +116,16 @@ public class SparkServer get("/categorybudget", new CategoryBudgetGet(handler, gson)); // Rest - get("/rest", new RestGet(handler, gson)); - + get("/rest", new RestGet(handler, gson)); + //charts get("/charts/categoryInOutSum", new CategoryInOutSumForMonth(handler, gson)); get("/charts/monthInOutSum", new MonthInOutSum(handler, gson)); - + + // Database + get("/database", new DatabaseExport(settings, gson)); + post("/database", new DatabaseImport(handler, gson)); + delete("/database", new DatabaseDelete(handler, settings)); after((request, response) -> { new RepeatingPaymentUpdater(handler).updateRepeatingPayments(DateTime.now()); diff --git a/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseDelete.java b/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseDelete.java new file mode 100644 index 0000000000000000000000000000000000000000..7fb2e8496cc75220de6f4859b3b7f119f403821e --- /dev/null +++ b/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseDelete.java @@ -0,0 +1,39 @@ +package de.deadlocker8.budgetmasterserver.server.database; + +import static spark.Spark.halt; + +import de.deadlocker8.budgetmasterserver.main.DatabaseHandler; +import de.deadlocker8.budgetmasterserver.main.Settings; +import spark.Request; +import spark.Response; +import spark.Route; + +public class DatabaseDelete implements Route +{ + private DatabaseHandler handler; + private Settings settings; + + public DatabaseDelete(DatabaseHandler handler, Settings settings) + { + this.handler = handler; + this.settings = settings; + } + + @Override + public Object handle(Request req, Response res) throws Exception + { + try + { + handler.deleteDatabase(); + handler = new DatabaseHandler(settings); + + return ""; + } + catch(IllegalStateException ex) + { + halt(500, "Internal Server Error"); + } + + return ""; + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseExport.java b/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseExport.java new file mode 100644 index 0000000000000000000000000000000000000000..7c5c2ad8a7758b1af56a40b34c3cb3604626e0e9 --- /dev/null +++ b/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseExport.java @@ -0,0 +1,41 @@ +package de.deadlocker8.budgetmasterserver.server.database; + +import static spark.Spark.halt; + +import com.google.gson.Gson; + +import de.deadlocker8.budgetmasterserver.main.DatabaseExporter; +import de.deadlocker8.budgetmasterserver.main.Settings; +import logger.Logger; +import spark.Request; +import spark.Response; +import spark.Route; + +public class DatabaseExport implements Route +{ + private Settings settings; + private Gson gson; + + public DatabaseExport(Settings settings, Gson gson) + { + this.settings = settings; + this.gson = gson; + } + + @Override + public Object handle(Request req, Response res) throws Exception + { + try + { + DatabaseExporter exporter = new DatabaseExporter(settings); + return gson.toJson(exporter.exportDatabase()); + } + catch(Exception e) + { + Logger.error(e); + halt(500, "Internal Server Error"); + } + + return ""; + } +} \ No newline at end of file diff --git a/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseImport.java b/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseImport.java new file mode 100644 index 0000000000000000000000000000000000000000..d3962efeb2c94105ef23d46f7137c99092d4a00a --- /dev/null +++ b/src/de/deadlocker8/budgetmasterserver/server/database/DatabaseImport.java @@ -0,0 +1,47 @@ +package de.deadlocker8.budgetmasterserver.server.database; + +import static spark.Spark.halt; + +import com.google.gson.Gson; + +import de.deadlocker8.budgetmasterserver.main.Database; +import de.deadlocker8.budgetmasterserver.main.DatabaseHandler; +import de.deadlocker8.budgetmasterserver.main.DatabaseImporter; +import logger.Logger; +import spark.Request; +import spark.Response; +import spark.Route; + +public class DatabaseImport implements Route +{ + private DatabaseHandler handler; + private Gson gson; + + public DatabaseImport(DatabaseHandler handler, Gson gson) + { + this.handler = handler; + this.gson = gson; + } + + @Override + public Object handle(Request req, Response res) throws Exception + { + String databaseJSON = req.body(); + + try + { + Database database = gson.fromJson(databaseJSON, Database.class); + + DatabaseImporter importer = new DatabaseImporter(handler); + importer.importDatabase(database); + return ""; + } + catch(Exception e) + { + Logger.error(e); + halt(500, "Internal Server Error"); + } + + return ""; + } +} \ No newline at end of file