Erweiterungen

This commit is contained in:
2025-08-20 09:46:59 +02:00
parent 4d691d9b11
commit 73415def42
11 changed files with 168 additions and 126 deletions

Binary file not shown.

View File

@@ -60,8 +60,8 @@ public class AdminView extends Main {
private void logout() {
VaadinService.getCurrentRequest().getWrappedSession().invalidate();
// Navigiere den Benutzer zur Login-Seite
UI.getCurrent().navigate("");
// Navigiere den Benutzer zur Main-Seite
UI.getCurrent().navigate("main");
}
private void savePreferences() {

View File

@@ -1,17 +1,13 @@
package de.assecutor.emulatorstation.base.ui.view;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.login.LoginForm;
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.router.Route;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinSession;
import de.assecutor.emulatorstation.Application;
import com.vaadin.flow.server.auth.AnonymousAllowed;
@Route("")
@Route("login")
@AnonymousAllowed
public class LoginView extends VerticalLayout {
public LoginView() {
@@ -20,45 +16,14 @@ public class LoginView extends VerticalLayout {
Span title = new Span("Anmelden");
title.getStyle().set("font-size", "24px").set("font-weight", "bold");
TextField usernameField = new TextField("Benutzername");
PasswordField passwordField = new PasswordField("Passwort");
Button loginButton = new Button("Login", event -> {
String username = usernameField.getValue();
String password = passwordField.getValue();
LoginForm loginForm = new LoginForm();
loginForm.setAction("login");
loginForm.setForgotPasswordButtonVisible(false);
if (authenticate(username, password)) {
var currentSession = VaadinSession.getCurrent().getSession();
currentSession.setMaxInactiveInterval(60); // Timeout in Sekunden
currentSession.setAttribute("username", username);
add(title, loginForm);
VaadinService.getCurrentRequest().getWrappedSession().setAttribute("user", username);
Notification.show("Anmeldung erfolgreich!");
if (username.equals("admin")) {
getUI().ifPresent(ui -> ui.navigate(AdminView.class));
} else {
getUI().ifPresent(ui -> ui.navigate(MainView.class));
}
} else {
Notification.show("Anmeldung fehlgeschlagen. Bitte überprüfen Sie Ihre Daten!", 3000, Notification.Position.MIDDLE);
}
});
loginButton.getStyle().set("margin-top", "10px");
add(title, usernameField, passwordField, loginButton);
MainLayout.instance.setDrawerOpened(false);
}
// Einfache Authentifizierung (hier nur als Beispiel, später durch echte Logik ersetzen)
private boolean authenticate(String username, String password) {
if (Application.users.containsKey(username)) {
var userPassword = Application.users.get(username);
return userPassword.equals(password);
if (MainLayout.instance != null) {
MainLayout.instance.setDrawerOpened(false);
}
return false;
}
}

View File

@@ -46,7 +46,7 @@ public final class MainLayout extends AppLayout {
ui.addPollListener(event -> {
if (!isUserSessionValid()) {
VaadinSession.getCurrent().getSession().invalidate(); // Session invalidieren
ui.access(() -> ui.navigate("login")); // Benutzer zur Login-Seite weiterleiten
ui.access(() -> ui.navigate("main")); // Immer zur Main-Seite weiterleiten
}
});
}

View File

@@ -15,6 +15,7 @@ import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed;
import com.vaadin.flow.theme.lumo.LumoUtility;
import de.assecutor.emulatorstation.pojo.ExecResponse;
import jakarta.annotation.security.PermitAll;
@@ -29,6 +30,7 @@ import java.util.concurrent.Executors;
@PermitAll // When security is enabled, allow all authenticated users
@Route("main")
@AnonymousAllowed
public final class MainView extends Main implements BeforeEnterObserver
{
private final String username;
@@ -101,10 +103,7 @@ public final class MainView extends Main implements BeforeEnterObserver
@Override
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
String user = (String) VaadinService.getCurrentRequest().getWrappedSession().getAttribute("user");
if (user == null) {
beforeEnterEvent.rerouteTo("login");
}
// Kein Redirect mehr zur Login-Seite bei fehlender Session
}
private void startup() {
@@ -414,8 +413,8 @@ public final class MainView extends Main implements BeforeEnterObserver
vaadinSession.invalidate();
// Navigiere den Benutzer zur Login-Seite
ui.navigate("");
// Navigiere den Benutzer zur Main-Seite
ui.navigate("main");
});
}
});

View File

@@ -0,0 +1,17 @@
package de.assecutor.emulatorstation.base.ui.view;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.VaadinService;
@Route("")
public class RootView implements BeforeEnterObserver {
@Override
public void beforeEnter(BeforeEnterEvent event) {
event.rerouteTo("main");
}
}

View File

@@ -0,0 +1,69 @@
package de.assecutor.emulatorstation.base.ui.view.security;
import com.vaadin.flow.spring.security.VaadinWebSecurity;
import de.assecutor.emulatorstation.base.ui.view.LoginView;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import de.assecutor.emulatorstation.Application;
@Configuration
public class SecurityConfig extends VaadinWebSecurity {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
// FormLogin verwenden; Vaadin-LoginView
setLoginView(http, LoginView.class);
http
.formLogin(form -> form
.loginPage("/login")
.successHandler(authenticationSuccessHandler())
.permitAll()
)
.logout(logout -> logout
.logoutSuccessUrl("/main")
);
}
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
Application.users.forEach((username, rawPassword) ->
manager.createUser(User.withUsername(username)
.password(rawPassword)
.roles("USER")
.build())
);
return manager;
}
@Bean
@SuppressWarnings("deprecation")
public PasswordEncoder passwordEncoder() {
// Für Demo-Zwecke: Passwörter sind im Klartext hinterlegt
return NoOpPasswordEncoder.getInstance();
}
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return (request, response, authentication) -> {
var session = request.getSession(true);
String username = authentication.getName();
session.setAttribute("user", username);
session.setAttribute("username", username);
response.sendRedirect("/main");
};
}
}

View File

@@ -0,0 +1,57 @@
package de.assecutor.emulatorstation.base.ui.view.security;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.server.VaadinServiceInitListener;
import com.vaadin.flow.shared.Registration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class VaadinAccessHandler {
@Bean
public VaadinServiceInitListener registerSessionGuard() {
return event -> event.getSource().addUIInitListener(uiInit -> {
UI ui = uiInit.getUI();
Registration reg = ui.addBeforeEnterListener(this::guardRoute);
ui.addDetachListener(detach -> reg.remove());
});
}
private void guardRoute(BeforeEnterEvent event) {
var request = VaadinService.getCurrentRequest();
if (request == null) {
if (!event.getLocation().getPath().equals("main")) {
event.rerouteTo("main");
}
return;
}
var session = request.getWrappedSession(false);
if (session == null) {
if (!event.getLocation().getPath().equals("main")) {
event.rerouteTo("main");
}
return;
}
// Login-Route immer erlauben
String path = event.getLocation().getPath();
if (path.equals("login")) {
return;
}
// Wenn keine Benutzer-Session vorhanden ist, immer zu "main"
Object user = session.getAttribute("user");
if (user == null) {
if (!path.equals("main")) {
event.rerouteTo("main");
}
}
}
}

View File

@@ -1,50 +0,0 @@
package de.assecutor.emulatorstation.taskmanagement.ui.view;
import de.assecutor.emulatorstation.base.ui.component.ViewToolbar;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.notification.NotificationVariant;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.Menu;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.theme.lumo.LumoUtility;
import jakarta.annotation.security.PermitAll;
import java.time.Clock;
@Route("task-list")
@PageTitle("Task List")
@Menu(order = 0, icon = "vaadin:clipboard-check", title = "Task List")
@PermitAll // When security is enabled, allow all authenticated users
public class TaskListView extends Main {
final TextField description;
final DatePicker dueDate;
final Button createBtn;
public TaskListView() {
description = new TextField();
description.setPlaceholder("What do you want to do?");
description.setAriaLabel("Task description");
description.setMinWidth("20em");
dueDate = new DatePicker();
dueDate.setPlaceholder("Due date");
dueDate.setAriaLabel("Due date");
createBtn = new Button("Create", event -> createTask());
createBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
setSizeFull();
addClassNames(LumoUtility.BoxSizing.BORDER, LumoUtility.Display.FLEX, LumoUtility.FlexDirection.COLUMN,
LumoUtility.Padding.MEDIUM, LumoUtility.Gap.SMALL);
add(new ViewToolbar("Task List", ViewToolbar.group(description, dueDate, createBtn)));
}
private void createTask() {
}
}