Skip to content

Commit

Permalink
Merge pull request #26 from dselimovic1/dev
Browse files Browse the repository at this point in the history
Final merge
  • Loading branch information
dselimovic1 authored Mar 30, 2020
2 parents 207df20 + 65f67d4 commit 004db84
Show file tree
Hide file tree
Showing 53 changed files with 2,521 additions and 98 deletions.
2 changes: 2 additions & 0 deletions .idea/CashRegisterApp.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/cssdialects.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
# CashRegisterApp
# CashRegisterApp

## Description
> JavaFX cross-platform desktop app
## Contributors

<a href="https://github.com/ebejtovic1" target="_blank"><img width="100px" height="100px" src="https://github.com/ebejtovic1.png"></a>
<a href="https://github.com/Lino2007" target="_blank"><img width="100px" height="100px" src="https://github.com/Lino2007.png"></a>
<a href="https://github.com/mand0ne" target="_blank"><img width="100px" height="100px" src="https://github.com/mand0ne.png"></a>
<a href="https://github.com/mrndjo" target="_blank"><img width="100px" height="100px" src="https://github.com/mrndjo.png"></a>
<a href="https://github.com/nosmanbegovic" target="_blank"><img width="100px" height="100px" src="https://github.com/nosmanbegovic.png"></a>
<a href="https://github.com/dselimovic1" target="_blank"><img width="100px" height="100px" src="https://github.com/dselimovic1.png"></a>
<a href="https://github.com/silegrb" target="_blank"><img width="100px" height="100px" src="https://github.com/silegrb.png"></a>
26 changes: 26 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,30 @@
<classifier>linux</classifier>
</dependency>

<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20190722</version>
</dependency>

<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-swing</artifactId>
<version>11</version>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>

</dependencies>

<build>
Expand All @@ -97,6 +121,8 @@
<version>3.8.0</version>
<configuration>
<release>14</release>
<source>14</source>
<target>14</target>
</configuration>
</plugin>

Expand Down
36 changes: 27 additions & 9 deletions src/main/java/ba/unsa/etf/si/App.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package ba.unsa.etf.si;

import ba.unsa.etf.si.controllers.LoginFormController;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

import java.io.IOException;

Expand All @@ -13,24 +18,37 @@
*/
public class App extends Application {

private static Scene scene;
public static Stage primaryStage;
public static final String DOMAIN = "http://cash-register-server-si.herokuapp.com";

@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("fxml/primary.fxml"), 640, 480);
stage.setScene(scene);
stage.show();
primaryStage = stage;
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setResizable(false);
primaryStage.setTitle("Cash Register App");
primaryStage.getIcons().add(new Image("/ba/unsa/etf/si/img/appIcon.png"));

Scene scene = new Scene(loadFXML());
centerStage(800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}

static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}

public static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml));
private Parent loadFXML() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource("fxml/loginForm.fxml"));
return fxmlLoader.load();
}

public static void centerStage(int width, int height) {
primaryStage.setWidth(width);
primaryStage.setHeight(height);
Rectangle2D primScreenBounds = Screen.getPrimary().getVisualBounds();
primaryStage.setX((primScreenBounds.getWidth() - primaryStage.getWidth()) / 2);
primaryStage.setY((primScreenBounds.getHeight() - primaryStage.getHeight()) / 2);
}

public static void main(String[] args) {
launch();
}
Expand Down
4 changes: 0 additions & 4 deletions src/main/java/ba/unsa/etf/si/controllers/FirstController.java

This file was deleted.

179 changes: 179 additions & 0 deletions src/main/java/ba/unsa/etf/si/controllers/LoginFormController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package ba.unsa.etf.si.controllers;

import ba.unsa.etf.si.App;
import ba.unsa.etf.si.models.User;
import ba.unsa.etf.si.utility.HttpUtils;
import ba.unsa.etf.si.utility.UserDeserializer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.jfoenix.controls.JFXButton;
import javafx.stage.StageStyle;
import org.json.JSONObject;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.scene.control.ProgressIndicator;

import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.function.Consumer;

import static ba.unsa.etf.si.App.DOMAIN;
import static ba.unsa.etf.si.App.primaryStage;

public class LoginFormController {

@FXML
private TextField usernameField, passwordField, errorField;
@FXML
private JFXButton submitButton;
@FXML
private ProgressIndicator progressIndicator;

public static String token = null;

@FXML
public void initialize() {
progressIndicator.setVisible(false);
submitButton.setOnAction(e -> submitButtonClick());

ChangeListener<Boolean> loginFieldListener = (observableValue, aBoolean, t1) -> {
usernameField.getStyleClass().removeAll("poljeNeispravno");
passwordField.getStyleClass().removeAll("poljeNeispravno");
errorField.setText("");
};

usernameField.focusedProperty().addListener(loginFieldListener);
passwordField.focusedProperty().addListener(loginFieldListener);
}

/**
* onAction method for the 'Submit' button
*/
public void submitButtonClick() {
try {
String username = usernameField.getText();
//String password = getHashedPassword(passwordField.getText()); -- soon to be hashed
String password = passwordField.getText();

// Request body for the POST login (raw JSON)
HttpRequest.BodyPublisher bodyPublisher =
HttpRequest.BodyPublishers.ofString("{\"username\":\"" + username + "\"," +
"\"password\":\"" + password + "\"}");

HttpRequest httpRequest = HttpUtils.POST(bodyPublisher, DOMAIN + "/api/login",
"Content-Type", "application/json");

// The callback after receiving the response for the login request
Consumer<String> consumer = loginResponse -> Platform.runLater(
() -> {
JSONObject loginResponseJson = new JSONObject(loginResponse);

// JSON contains field "error" => JSON request body is invalid
if (!loginResponseJson.isNull("error")) {
displayError("Invalid username or password!");
usernameField.getStyleClass().add("poljeNeispravno");
passwordField.getStyleClass().add("poljeNeispravno");
} else {
// At this point, send a GET request to receive
// more info about the User who is trying to log in
token = loginResponseJson.getString("token");
HttpRequest getUserInfoRequest = HttpUtils.GET(DOMAIN + "/api/profile",
"Authorization", "Bearer " + token);

// The callback after receveing the response for the user info request
Consumer<String> infoConsumer = infoResponse -> Platform.runLater(
() -> {
try {
ObjectMapper userMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(User.class, new UserDeserializer());
userMapper.registerModule(module);

User user = userMapper.readValue(infoResponse, User.class);
user.setToken(loginResponseJson.getString("token"));
startApplication(user);
} catch (JsonProcessingException e) {
displayError("Something went wrong. Please try again.");
}
});

HttpUtils.send(getUserInfoRequest, HttpResponse.BodyHandlers.ofString(), infoConsumer,
() -> displayError("Something went wrong. Please try again."));
}
});

progressIndicator.setVisible(true);
HttpUtils.send(httpRequest, HttpResponse.BodyHandlers.ofString(), consumer,
() -> displayError("Something went wrong. Please try again."));
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* Display appropriate error message
*/
private void displayError(String errorMessage) {
progressIndicator.setVisible(false);
errorField.setText(errorMessage);
}

/**
* To change the scene of the stage from login to home
*
* @param loggedInUser - the user that is trying to log in;
* should be forwarded to PrimaryController for further needs
*/
private void startApplication(User loggedInUser) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource("fxml/primary.fxml"));
fxmlLoader.setControllerFactory(c -> new PrimaryController(loggedInUser));
Scene scene = new Scene(fxmlLoader.load());

Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
primaryStage.setX(bounds.getMinX());
primaryStage.setY(bounds.getMinY());
primaryStage.setWidth(bounds.getWidth());
primaryStage.setHeight(bounds.getHeight());

primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}

/*
* @param password - plain text from password text field
* @return the same password hashed with SHA256
* @throws NoSuchAlgorithmException
private String getHashedPassword(String password) throws NoSuchAlgorithmException {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] encodedHash = digest.digest(password.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : encodedHash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1)
hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
*/

}
Loading

0 comments on commit 004db84

Please sign in to comment.