Skip to content

Commit

Permalink
fix StorageForm, add ChangePasswordForm
Browse files Browse the repository at this point in the history
fix two fields being named the same in storageform

Signed-off-by: Aleksandar Zivkovic <[email protected]>
  • Loading branch information
anywaywayany committed Feb 29, 2024
1 parent 74728e4 commit 803d01e
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 11 deletions.
154 changes: 154 additions & 0 deletions src/main/java/com/samic/samic/components/form/ChangePasswordForm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package com.samic.samic.components.form;

import com.nulabinc.zxcvbn.Zxcvbn;
import com.samic.samic.components.UIFactory;
import com.samic.samic.data.entity.User;
import com.samic.samic.security.UserDetailsServiceImpl;
import com.vaadin.flow.component.Text;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.value.ValueChangeMode;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
* @author Aleksandar Zivkovic
*/

@Component
@Scope("prototype")
public class ChangePasswordForm extends Dialog {

private final PasswordField oldPassword = new PasswordField("Altes Passwort");
private final PasswordField newPassword = new PasswordField("Neues Passwort");
private final PasswordField newPasswordConfirm = new PasswordField("Neues Passwort wiederholen");

private final Binder<User> userBinder = new Binder<>(User.class);
private final FormLayout formLayout = new FormLayout();
private final UserDetailsServiceImpl userDetailsService;
private final Zxcvbn zxcvbn = new Zxcvbn();
private final Icon checkIcon = VaadinIcon.CHECK.create();

private Span passwordStrengthText;

public ChangePasswordForm(UserDetailsServiceImpl userDetailsService) {
this.userDetailsService = userDetailsService;
}


@PostConstruct
private void initUI() {
add(formLayout);
formLayout.add(oldPassword, newPassword, newPasswordConfirm);
Div buttonDiv = new Div();
buttonDiv.add(UIFactory.btnPrimary("Passwort ändern", event -> onSave()));
buttonDiv.add(UIFactory.btnPrimaryError("Abbrechen", event -> onClose()));
formLayout.add(buttonDiv);
setCloseOnOutsideClick(false);
initBinder();
initPasswordfield();
}

private void onClose() {
this.close();
oldPassword.clear();
newPassword.clear();
newPasswordConfirm.clear();
}

public Dialog setBean(User user) {
userBinder.setBean(user);
return this;
}

private void onSave() {
if (isValid()) {
if (userDetailsService.oldPasswordMatches(oldPassword.getValue())) {
userDetailsService.changePassword(newPassword.getValue());
UIFactory.notificationSuccess("Passwort erfolgreich geändert").open();
userBinder.setBean(null);
onClose();
} else {
UIFactory.notificationError("Fehler: Altes Passwort stimmt nicht überein").open();
}
} else {
UIFactory.notificationError("Fehler: Passwort entspricht nicht den Anforderungen").open();
}
}

private void initBinder() {
userBinder.forField(newPassword).asRequired("Neues Passwort darf nicht leer sein")
.bind(User::getHashedPassword, User::setHashedPassword);
userBinder.forField(newPasswordConfirm)
.asRequired("Neues Passwort wiederholen darf nicht leer sein")
.withValidator(value -> value.equals(newPassword.getValue()),
"Passwörter stimmen nicht überein")
.bind(User::getHashedPassword, User::setHashedPassword);
}

private Boolean isValid() {
userBinder.validate();
return userBinder.isValid();
}

private void initPasswordfield() {
newPassword.setRevealButtonVisible(true);
newPasswordConfirm.setRevealButtonVisible(true);
checkIcon.setVisible(false);
newPassword.setClassName("Password");
checkIcon.getStyle().set("color", "var(--lumo-success-color)");
newPassword.setSuffixComponent(checkIcon);

Div passwordStrength = new Div();
passwordStrengthText = new Span();
passwordStrength.add(new Text(""),
passwordStrengthText);
newPassword.setHelperComponent(passwordStrength);

newPassword.setValueChangeMode(ValueChangeMode.EAGER);
newPassword.addValueChangeListener(e -> {
String password = e.getValue();
updateHelper(password);
});
updateHelper("");

}

private void updateHelper(String password) {
int strength = zxcvbn.measure(password).getScore();

passwordStrengthText.setText(String.valueOf(strength));

switch (strength) {
case 0 -> {
passwordStrengthText.setText("sehr unsicher");
passwordStrengthText.getStyle().set("color", "#FF0800");
}
case 1 -> {
passwordStrengthText.setText("unsicher");
passwordStrengthText.getStyle().set("color", "#FF5601");
}
case 2 -> {
passwordStrengthText.setText("mittelmäßig");
passwordStrengthText.getStyle().set("color", "#FF9B01");
}
case 3 -> {
passwordStrengthText.setText("stark");
passwordStrengthText.getStyle().set("color", "#300A233");
checkIcon.setVisible(true);
}
case 4 -> {
passwordStrengthText.setText("sehr stark");
passwordStrengthText.getStyle().set("color", "#00A233");
checkIcon.setVisible(true);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ public class StorageForm extends FormLayout {
private final TextField street = new TextField("Straße");
private final IntegerField houseNo = new IntegerField("Hausnummer");
private final IntegerField doorNo = new IntegerField("Türnummer");
private final IntegerField zipCode = new IntegerField("Türnummer");
private final IntegerField zipCode = new IntegerField("Postleitzahl");
private final TextField city = new TextField("Stadt");

private final Binder<Storage> storageBinder = new Binder<>(Storage.class);

@PostConstruct
private void initUI() {
add(name, street, houseNo, doorNo, zipCode, city);
storageBinder.bind(name, Storage::getName, Storage::setName);
storageBinder.forField(name).asRequired().bind(Storage::getName, Storage::setName);
storageBinder.forField(street).bind("address.street");
storageBinder.forField(houseNo).bind("address.houseNo");
storageBinder.forField(doorNo).bind("address.doorNo");
Expand Down
18 changes: 11 additions & 7 deletions src/main/java/com/samic/samic/components/form/UserForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private void initPasswordfield() {

Div passwordStrength = new Div();
passwordStrengthText = new Span();
passwordStrength.add(new Text("Password strength: "),
passwordStrength.add(new Text(""),
passwordStrengthText);
password.setHelperComponent(passwordStrength);

Expand All @@ -80,9 +80,13 @@ private void initBinder() {
.bind(User::getMail, User::setMail);
binderUser.forField(password).asRequired()
.bind(User::getHashedPassword, User::setHashedPassword);
binderUser.forField(passwordConfirm).asRequired()
.withValidator(p -> p.equals(password.getValue()),
"Passwörter stimmen nicht überein")
.bind(User::getHashedPassword, User::setHashedPassword);
binderUser.forField(surname).asRequired().bind("profile.firstName");
binderUser.forField(lastname).asRequired().bind("profile.lastName");
binderUser.forField(username).bind("profile.username");
binderUser.forField(username).asRequired().bind("profile.username");
binderUser.forField(role).asRequired().bind(User::getRole, User::setRole);
}

Expand All @@ -93,24 +97,24 @@ private void updateHelper(String password) {

switch (strength) {
case 0 -> {
passwordStrengthText.setText("very weak");
passwordStrengthText.setText("sehr unsicher");
passwordStrengthText.getStyle().set("color", "#FF0800");
}
case 1 -> {
passwordStrengthText.setText("weak");
passwordStrengthText.setText("unsicher");
passwordStrengthText.getStyle().set("color", "#FF5601");
}
case 2 -> {
passwordStrengthText.setText("medium");
passwordStrengthText.setText("mittelmäßig");
passwordStrengthText.getStyle().set("color", "#FF9B01");
}
case 3 -> {
passwordStrengthText.setText("strong");
passwordStrengthText.setText("stark");
passwordStrengthText.getStyle().set("color", "#300A233");
checkIcon.setVisible(true);
}
case 4 -> {
passwordStrengthText.setText("very strong");
passwordStrengthText.setText("sehr stark");
passwordStrengthText.getStyle().set("color", "#00A233");
checkIcon.setVisible(true);
}
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/samic/samic/security/UserDetailsServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private final PasswordEncoder passwordEncoder;
@Autowired
private final AuthenticatedUser authenticatedUser;

private static List<GrantedAuthority> getAuthorities(User user) {
Role userRole = user.getRole();
Expand Down Expand Up @@ -67,4 +69,16 @@ public void register(User user) {
repositoryUser.save(user);
}

public Boolean oldPasswordMatches(String oldPassword) {
return passwordEncoder.matches(oldPassword,
repositoryUser.findById(authenticatedUser.getUser().get().getId()).get()
.getHashedPassword());
}

public void changePassword(String value) {
repositoryUser.findById(authenticatedUser.getUser().get().getId()).ifPresent(user -> {
user.setHashedPassword(passwordEncoder.encode(value));
repositoryUser.save(user);
});
}
}
11 changes: 9 additions & 2 deletions src/main/java/com/samic/samic/views/MainLayout.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.samic.samic.views;

import com.samic.samic.components.form.ChangePasswordForm;
import com.samic.samic.data.entity.User;
import com.samic.samic.security.AuthenticatedUser;
import com.samic.samic.views.abfragen.AbfragenView;
Expand Down Expand Up @@ -39,11 +40,14 @@ public class MainLayout extends AppLayout {

private final AccessAnnotationChecker accessChecker;
private final AuthenticatedUser authenticatedUser;
private final ChangePasswordForm changePasswordForm;
private H2 viewTitle;

public MainLayout(AuthenticatedUser authenticatedUser, AccessAnnotationChecker accessChecker) {
public MainLayout(AuthenticatedUser authenticatedUser, AccessAnnotationChecker accessChecker,
ChangePasswordForm changePasswordForm) {
this.authenticatedUser = authenticatedUser;
this.accessChecker = accessChecker;
this.changePasswordForm = changePasswordForm;

setPrimarySection(Section.DRAWER);
addDrawerContent();
Expand Down Expand Up @@ -154,10 +158,13 @@ private Footer createFooter() {
div.getElement().getStyle().set("align-items", "center");
div.getElement().getStyle().set("gap", "var(--lumo-space-s)");
userName.add(div);
userName.getSubMenu()
.addItem("Passwort ändern", e -> changePasswordForm.setBean(User.builder()
.build()).open());
userName
.getSubMenu()
.addItem(
"Sign out",
"Abmelden",
e -> authenticatedUser.logout());

layout.add(userMenu);
Expand Down

0 comments on commit 803d01e

Please sign in to comment.