From 8b8cfb62075d6ed233d55aa6e9ca673675d84200 Mon Sep 17 00:00:00 2001 From: Sven Carstensen Date: Thu, 28 Aug 2025 11:35:43 +0200 Subject: [PATCH] Erweiterungen --- .../pages/service/AppUserService.java | 28 ++++ .../votianlt/pages/view/AppUserView.java | 16 +- .../votianlt/pages/view/EditAppUserView.java | 146 ++++++++++++++++-- 3 files changed, 176 insertions(+), 14 deletions(-) diff --git a/src/main/java/de/assecutor/votianlt/pages/service/AppUserService.java b/src/main/java/de/assecutor/votianlt/pages/service/AppUserService.java index 40420d5..19f5578 100644 --- a/src/main/java/de/assecutor/votianlt/pages/service/AppUserService.java +++ b/src/main/java/de/assecutor/votianlt/pages/service/AppUserService.java @@ -5,6 +5,7 @@ import de.assecutor.votianlt.repository.AppUserRepository; import de.assecutor.votianlt.security.SecurityService; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -16,14 +17,22 @@ public class AppUserService { private final AppUserRepository appUserRepository; private final SecurityService securityService; + private final BCryptPasswordEncoder passwordEncoder; @Autowired public AppUserService(AppUserRepository appUserRepository, SecurityService securityService) { this.appUserRepository = appUserRepository; this.securityService = securityService; + this.passwordEncoder = new BCryptPasswordEncoder(); } public AppUser createAppUser(AppUser appUser) { + // Hash the password before saving + if (appUser.getPassword() != null && !appUser.getPassword().isEmpty()) { + String hashedPassword = passwordEncoder.encode(appUser.getPassword()); + appUser.setPassword(hashedPassword); + } + // Set creation and update metadata appUser.setErstelltAm(java.time.LocalDateTime.now()); appUser.setAktualisiertAm(java.time.LocalDateTime.now()); @@ -51,10 +60,29 @@ public class AppUserService { } public AppUser updateAppUser(AppUser appUser) { + // Hash the password if it's being updated and not empty + if (appUser.getPassword() != null && !appUser.getPassword().isEmpty()) { + // Only hash if it's not already hashed (BCrypt hashes start with $2a$, $2b$, or $2y$) + if (!appUser.getPassword().startsWith("$2")) { + String hashedPassword = passwordEncoder.encode(appUser.getPassword()); + appUser.setPassword(hashedPassword); + } + } + appUser.setAktualisiertAm(java.time.LocalDateTime.now()); appUser.setAktualisiertVon(securityService.getCurrentUserId()); return appUserRepository.save(appUser); } + + /** + * Verify a plain text password against the stored hashed password + * @param plainPassword The plain text password to verify + * @param hashedPassword The stored BCrypt hashed password + * @return true if the password matches, false otherwise + */ + public boolean verifyPassword(String plainPassword, String hashedPassword) { + return passwordEncoder.matches(plainPassword, hashedPassword); + } public void deleteById(ObjectId id) { appUserRepository.deleteById(id); diff --git a/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java b/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java index ff9f253..3422a2e 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/AppUserView.java @@ -12,8 +12,11 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import de.assecutor.votianlt.model.AppUser; +import de.assecutor.votianlt.model.AppDevice; import de.assecutor.votianlt.pages.service.AppUserService; +import de.assecutor.votianlt.pages.service.AppDeviceService; import jakarta.annotation.security.RolesAllowed; +import org.springframework.beans.factory.annotation.Autowired; @PageTitle("App-Nutzer") @Route(value = "app-user", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class) @@ -21,10 +24,13 @@ import jakarta.annotation.security.RolesAllowed; public class AppUserView extends VerticalLayout { private final AppUserService appUserService; + private final AppDeviceService appDeviceService; private final Grid appUserGrid; - public AppUserView(AppUserService appUserService) { + @Autowired + public AppUserView(AppUserService appUserService, AppDeviceService appDeviceService) { this.appUserService = appUserService; + this.appDeviceService = appDeviceService; setSizeFull(); setPadding(true); @@ -57,7 +63,13 @@ public class AppUserView extends VerticalLayout { appUserGrid.addColumn(AppUser::getTelefon).setHeader("Telefon").setAutoWidth(true); appUserGrid.addColumn(AppUser::getAppCode).setHeader("App-Code").setAutoWidth(true); appUserGrid.addColumn(AppUser::getEmail).setHeader("E-Mail").setAutoWidth(true); - appUserGrid.addColumn(AppUser::getGeraet).setHeader("Gerät").setAutoWidth(true); + appUserGrid.addColumn(appUser -> { + if (appUser.getAppDeviceId() != null) { + AppDevice device = appDeviceService.findById(appUser.getAppDeviceId()); + return device != null ? device.getName() : "Nicht gefunden"; + } + return "Kein Gerät zugewiesen"; + }).setHeader("Endgerät").setAutoWidth(true); // Make grid rows clickable appUserGrid.setSelectionMode(Grid.SelectionMode.SINGLE); diff --git a/src/main/java/de/assecutor/votianlt/pages/view/EditAppUserView.java b/src/main/java/de/assecutor/votianlt/pages/view/EditAppUserView.java index 9fc495b..ee40843 100644 --- a/src/main/java/de/assecutor/votianlt/pages/view/EditAppUserView.java +++ b/src/main/java/de/assecutor/votianlt/pages/view/EditAppUserView.java @@ -11,6 +11,7 @@ import com.vaadin.flow.component.notification.Notification; import com.vaadin.flow.component.orderedlayout.FlexComponent; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout; +import com.vaadin.flow.component.textfield.PasswordField; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.binder.Binder; import com.vaadin.flow.data.binder.ValidationException; @@ -19,17 +20,23 @@ import com.vaadin.flow.router.HasUrlParameter; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import de.assecutor.votianlt.model.AppUser; +import de.assecutor.votianlt.model.AppDevice; import de.assecutor.votianlt.pages.service.AppUserService; +import de.assecutor.votianlt.pages.service.AppDeviceService; import jakarta.annotation.security.RolesAllowed; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; +import java.util.List; + @PageTitle("App-Nutzer bearbeiten") @Route(value = "edit-app-user", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class) @RolesAllowed({"USER","ADMIN"}) public class EditAppUserView extends VerticalLayout implements HasUrlParameter { private final AppUserService appUserService; + private final AppDeviceService appDeviceService; private AppUser appUser; private final Binder binder = new Binder<>(AppUser.class); @@ -40,11 +47,16 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter deviceField = new ComboBox<>("kein Gerät"); + private final PasswordField changePasswordField = new PasswordField("Passwort ändern"); + private final PasswordField confirmChangePasswordField = new PasswordField("Passwort ändern wiederholen"); + private final ComboBox deviceComboBox = new ComboBox<>("Endgerät"); + + private ObjectId previousDeviceId; @Autowired - public EditAppUserView(AppUserService appUserService) { + public EditAppUserView(AppUserService appUserService, AppDeviceService appDeviceService) { this.appUserService = appUserService; + this.appDeviceService = appDeviceService; setSizeFull(); setPadding(true); setSpacing(true); @@ -102,9 +114,16 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter device.getName()); + deviceComboBox.setPlaceholder("Bitte wählen..."); // Add fields to form formLayout.add(designationField); @@ -112,7 +131,9 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter getCurrentDevice(appUser), // Get current device + (appUser, appDevice) -> appUser.setAppDeviceId(appDevice != null ? appDevice.getId() : null) + ); } @Override @@ -154,13 +179,11 @@ public class EditAppUserView extends VerticalLayout implements HasUrlParameter availableDevices = new ArrayList<>(); + + // First, add the currently assigned device if it exists + AppDevice currentDevice = getCurrentDevice(appUser); + if (currentDevice != null) { + availableDevices.add(currentDevice); + } + + // Then add all unassigned devices + List unassignedDevices = appDeviceService.findUnassignedDevices(); + availableDevices.addAll(unassignedDevices); + + deviceComboBox.setItems(availableDevices); + + // Set the current device as selected + if (currentDevice != null) { + deviceComboBox.setValue(currentDevice); + } + } private void deleteAppUser() { // Show confirmation dialog