diff --git a/client/src/main/java/envoy/client/net/Client.java b/client/src/main/java/envoy/client/net/Client.java index c395045..15e3c01 100644 --- a/client/src/main/java/envoy/client/net/Client.java +++ b/client/src/main/java/envoy/client/net/Client.java @@ -158,6 +158,12 @@ public class Client implements Closeable { // Process IsTyping events receiver.registerProcessor(IsTyping.class, eventBus::dispatch); + // Process PasswordChangeResults + receiver.registerProcessor(PasswordChangeResult.class, eventBus::dispatch); + + // Process ProfilePicChanges + receiver.registerProcessor(ProfilePicChange.class, eventBus::dispatch); + // Send event eventBus.register(SendEvent.class, evt -> { try { diff --git a/client/src/main/java/envoy/client/ui/settings/UserSettingsPane.java b/client/src/main/java/envoy/client/ui/settings/UserSettingsPane.java index 2ea37f4..1b5e2de 100644 --- a/client/src/main/java/envoy/client/ui/settings/UserSettingsPane.java +++ b/client/src/main/java/envoy/client/ui/settings/UserSettingsPane.java @@ -6,10 +6,10 @@ import java.io.IOException; import java.nio.file.Files; import javafx.event.EventHandler; +import javafx.geometry.Pos; import javafx.scene.Cursor; -import javafx.scene.control.Alert; +import javafx.scene.control.*; import javafx.scene.control.Alert.AlertType; -import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.InputEvent; @@ -35,7 +35,7 @@ public class UserSettingsPane extends SettingsPane { private boolean profilePicChanged, usernameChanged, passwordChanged, validPassword; private byte[] currentImageBytes; - private String newUsername, newPassword; + private String newUsername, newPassword = ""; /** * Creates a new {@code UserSettingsPane}. @@ -81,7 +81,8 @@ public class UserSettingsPane extends SettingsPane { hbox.getChildren().add(profilePic); // Displaying the username change mechanism - final var username = user.getName(); + final var username = user.getName(); + newUsername = username; final var usernameTextField = new TextField(username); final EventHandler textChanged = e -> { newUsername = usernameTextField.getText(); @@ -91,6 +92,39 @@ public class UserSettingsPane extends SettingsPane { usernameTextField.setOnKeyTyped(textChanged); hbox.getChildren().add(usernameTextField); vbox.getChildren().add(hbox); + + // "Displaying" the password change mechanism + final HBox[] passwordHBoxes = { new HBox(), new HBox(), new HBox() }; + final Label[] passwordLabels = { new Label("Enter current password:"), new Label("Enter new password:"), + new Label("Repeat new password:") }; + + final var currentPasswordField = new PasswordField(); + final var newPasswordField = new PasswordField(); + final var repeatNewPasswordField = new PasswordField(); + final PasswordField[] passwordFields = { currentPasswordField, newPasswordField, repeatNewPasswordField }; + final EventHandler passwordEntered = e -> { + newPassword = newPasswordField.getText(); + validPassword = newPassword.equals(repeatNewPasswordField.getText()) + && !newPasswordField.getText().isBlank(); + }; + newPasswordField.setOnInputMethodTextChanged(passwordEntered); + newPasswordField.setOnKeyTyped(passwordEntered); + repeatNewPasswordField.setOnInputMethodTextChanged(passwordEntered); + repeatNewPasswordField.setOnKeyTyped(passwordEntered); + + for (int i = 0; i < passwordHBoxes.length; i++) { + final var hBox2 = passwordHBoxes[i]; + hBox2.getChildren().add(passwordLabels[i]); + hBox2.getChildren().add(passwordFields[i]); + vbox.getChildren().add(hBox2); + } + + // Displaying the save button + final var saveButton = new Button("Save"); + saveButton.setOnAction(e -> save(user.getID(), currentPasswordField.getText())); + saveButton.setAlignment(Pos.BOTTOM_RIGHT); + vbox.getChildren().add(saveButton); + } /** @@ -118,7 +152,7 @@ public class UserSettingsPane extends SettingsPane { // The password was changed if (passwordChanged && validPassword) eventbus.dispatch(new SendEvent(new PasswordChangeRequest(newPassword, oldPassword, userID))); - else if (!(validPassword || newPassword != null && newPassword.isBlank())) { + else if (!(validPassword || newPassword.isBlank())) { final var alert = new Alert(AlertType.ERROR); alert.setTitle("Unequal Password"); alert.setContentText("Repeated password is unequal to the chosen new password"); diff --git a/common/src/main/java/envoy/event/PasswordChangeRequest.java b/common/src/main/java/envoy/event/PasswordChangeRequest.java new file mode 100644 index 0000000..9b16a5d --- /dev/null +++ b/common/src/main/java/envoy/event/PasswordChangeRequest.java @@ -0,0 +1,44 @@ +package envoy.event; + +import envoy.data.Contact; + +/** + * Project: envoy-common
+ * File: PasswordChangeRequest.java
+ * Created: 31.07.2020
+ * + * @author Leon Hofmeister + * @since Envoy Common v0.2-beta + */ +public class PasswordChangeRequest extends Event { + + private final long id; + + private final String oldPassword; + + private static final long serialVersionUID = 0L; + + /** + * @param newPassword the new password of that user + * @param oldPassword the old password of that user + * @param userID the ID of the user who wants to change his password + * @since Envoy Common v0.2-beta + */ + public PasswordChangeRequest(String newPassword, String oldPassword, long userID) { + super(newPassword); + this.oldPassword = oldPassword; + id = userID; + } + + /** + * @return the ID of the {@link Contact} this event is related to + * @since Envoy Common v0.2-alpha + */ + public long getID() { return id; } + + /** + * @return the old password of the underlying user + * @since Envoy Common v0.2-beta + */ + public String getOldPassword() { return oldPassword; } +} diff --git a/common/src/main/java/envoy/event/PasswordChangeResult.java b/common/src/main/java/envoy/event/PasswordChangeResult.java new file mode 100644 index 0000000..6252980 --- /dev/null +++ b/common/src/main/java/envoy/event/PasswordChangeResult.java @@ -0,0 +1,26 @@ +package envoy.event; + +/** + * This class acts as a notice to the user whether his + * {@link envoy.event.PasswordChangeRequest} was successful. + *

+ * Project: envoy-common
+ * File: PasswordChangeResult.java
+ * Created: 01.08.2020
+ * + * @author Leon Hofmeister + * @since Envoy Common v0.2-beta + */ +public class PasswordChangeResult extends Event { + + private static final long serialVersionUID = 1L; + + /** + * Creates an instance of {@code PasswordChangeResult}. + * + * @param value whether the preceding {@link envoy.event.PasswordChangeRequest} + * was successful. + * @since Envoy Common v0.2-beta + */ + public PasswordChangeResult(boolean value) { super(value); } +} diff --git a/server/src/main/java/envoy/server/processors/PasswordChangeRequestProcessor.java b/server/src/main/java/envoy/server/processors/PasswordChangeRequestProcessor.java new file mode 100644 index 0000000..7d41c7f --- /dev/null +++ b/server/src/main/java/envoy/server/processors/PasswordChangeRequestProcessor.java @@ -0,0 +1,29 @@ +package envoy.server.processors; + +import java.io.IOException; + +import envoy.event.PasswordChangeRequest; +import envoy.event.PasswordChangeResult; +import envoy.server.data.PersistenceManager; +import envoy.server.net.ObjectWriteProxy; +import envoy.server.util.PasswordUtil; + +/** + * Project: envoy-server-standalone
+ * File: PasswordChangeRequestProcessor.java
+ * Created: 31.07.2020
+ * + * @author Leon Hofmeister + * @since Envoy Server v0.2-beta + */ +public class PasswordChangeRequestProcessor implements ObjectProcessor { + + @Override + public void process(PasswordChangeRequest event, long socketID, ObjectWriteProxy writeProxy) throws IOException { + final var persistenceManager = PersistenceManager.getInstance(); + final var user = persistenceManager.getUserByID(event.getID()); + final var correctAuthentication = PasswordUtil.validate(event.getOldPassword(), user.getPasswordHash()); + if (correctAuthentication) user.setPasswordHash(PasswordUtil.hash(event.get())); + writeProxy.write(socketID, new PasswordChangeResult(correctAuthentication)); + } +}