diff --git a/README.md b/README.md
index cfb9ad2..ef5b496 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,4 @@
-# Emulatorstation README
+Bauen im Produktionsmodus:
-- [ ] TODO Replace or update this README with instructions relevant to your application
+./mvnw -Pproduction clean package -DskipTests
-To start the application in development mode, import it into your IDE and run the `Application` class.
-You can also start the application from the command line by running:
-
-```bash
-./mvnw
-```
-
-To build the application in production mode, run:
-
-```bash
-./mvnw -Pproduction package
-```
-
-## Getting Started
-
-The [Getting Started](https://vaadin.com/docs/latest/getting-started) guide will quickly familiarize you with your new
-Emulatorstation implementation. You'll learn how to set up your development environment, understand the project
-structure, and find resources to help you add muscles to your skeleton — transforming it into a fully-featured
-application.
diff --git a/pom.xml b/pom.xml
index d3679ce..7fe0693 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
de.assecutor.emulatorstation
emulatorstation
- 1.0-SNAPSHOT
+ 0.9
jar
@@ -71,6 +71,10 @@
org.springframework.boot
spring-boot-starter-actuator
+
+ org.springframework.boot
+ spring-boot-starter-security
+
org.springframework.boot
spring-boot-starter-validation
diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle
new file mode 100644
index 0000000..3168f43
Binary files /dev/null and b/src/main/bundles/prod.bundle differ
diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/AdminView.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/AdminView.java
index d8753f2..b29b035 100644
--- a/src/main/java/de/assecutor/emulatorstation/base/ui/view/AdminView.java
+++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/AdminView.java
@@ -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() {
diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/LoginView.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/LoginView.java
index 628ef17..aebe489 100644
--- a/src/main/java/de/assecutor/emulatorstation/base/ui/view/LoginView.java
+++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/LoginView.java
@@ -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;
}
}
\ No newline at end of file
diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainLayout.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainLayout.java
index 21e6c9f..2f95ed0 100644
--- a/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainLayout.java
+++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainLayout.java
@@ -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
}
});
}
diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainView.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainView.java
index 183c3dc..36403d3 100644
--- a/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainView.java
+++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/MainView.java
@@ -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");
});
}
});
diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/RootView.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/RootView.java
new file mode 100644
index 0000000..4c6cb80
--- /dev/null
+++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/RootView.java
@@ -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");
+ }
+}
+
+
diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/SecurityConfig.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/SecurityConfig.java
new file mode 100644
index 0000000..6974bf8
--- /dev/null
+++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/SecurityConfig.java
@@ -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");
+ };
+ }
+}
+
+
diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/VaadinAccessHandler.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/VaadinAccessHandler.java
new file mode 100644
index 0000000..b34c7cf
--- /dev/null
+++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/VaadinAccessHandler.java
@@ -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");
+ }
+ }
+ }
+}
+
+
diff --git a/src/main/java/de/assecutor/emulatorstation/taskmanagement/ui/view/TaskListView.java b/src/main/java/de/assecutor/emulatorstation/taskmanagement/ui/view/TaskListView.java
deleted file mode 100644
index cd8027a..0000000
--- a/src/main/java/de/assecutor/emulatorstation/taskmanagement/ui/view/TaskListView.java
+++ /dev/null
@@ -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() {
- }
-}