Erweiterungen
This commit is contained in:
23
README.md
23
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.
|
|
||||||
|
|||||||
6
pom.xml
6
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>de.assecutor.emulatorstation</groupId>
|
<groupId>de.assecutor.emulatorstation</groupId>
|
||||||
<artifactId>emulatorstation</artifactId>
|
<artifactId>emulatorstation</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>0.9</version>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
@@ -71,6 +71,10 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
|||||||
BIN
src/main/bundles/prod.bundle
Normal file
BIN
src/main/bundles/prod.bundle
Normal file
Binary file not shown.
@@ -60,8 +60,8 @@ public class AdminView extends Main {
|
|||||||
private void logout() {
|
private void logout() {
|
||||||
VaadinService.getCurrentRequest().getWrappedSession().invalidate();
|
VaadinService.getCurrentRequest().getWrappedSession().invalidate();
|
||||||
|
|
||||||
// Navigiere den Benutzer zur Login-Seite
|
// Navigiere den Benutzer zur Main-Seite
|
||||||
UI.getCurrent().navigate("");
|
UI.getCurrent().navigate("main");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void savePreferences() {
|
private void savePreferences() {
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
package de.assecutor.emulatorstation.base.ui.view;
|
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.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.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.router.Route;
|
||||||
import com.vaadin.flow.server.VaadinService;
|
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||||
import com.vaadin.flow.server.VaadinSession;
|
|
||||||
import de.assecutor.emulatorstation.Application;
|
|
||||||
|
|
||||||
@Route("")
|
@Route("login")
|
||||||
|
@AnonymousAllowed
|
||||||
public class LoginView extends VerticalLayout {
|
public class LoginView extends VerticalLayout {
|
||||||
|
|
||||||
public LoginView() {
|
public LoginView() {
|
||||||
@@ -20,45 +16,14 @@ public class LoginView extends VerticalLayout {
|
|||||||
Span title = new Span("Anmelden");
|
Span title = new Span("Anmelden");
|
||||||
title.getStyle().set("font-size", "24px").set("font-weight", "bold");
|
title.getStyle().set("font-size", "24px").set("font-weight", "bold");
|
||||||
|
|
||||||
TextField usernameField = new TextField("Benutzername");
|
LoginForm loginForm = new LoginForm();
|
||||||
PasswordField passwordField = new PasswordField("Passwort");
|
loginForm.setAction("login");
|
||||||
|
loginForm.setForgotPasswordButtonVisible(false);
|
||||||
Button loginButton = new Button("Login", event -> {
|
|
||||||
String username = usernameField.getValue();
|
|
||||||
String password = passwordField.getValue();
|
|
||||||
|
|
||||||
if (authenticate(username, password)) {
|
add(title, loginForm);
|
||||||
var currentSession = VaadinSession.getCurrent().getSession();
|
|
||||||
currentSession.setMaxInactiveInterval(60); // Timeout in Sekunden
|
|
||||||
currentSession.setAttribute("username", username);
|
|
||||||
|
|
||||||
VaadinService.getCurrentRequest().getWrappedSession().setAttribute("user", username);
|
if (MainLayout.instance != null) {
|
||||||
Notification.show("Anmeldung erfolgreich!");
|
MainLayout.instance.setDrawerOpened(false);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ public final class MainLayout extends AppLayout {
|
|||||||
ui.addPollListener(event -> {
|
ui.addPollListener(event -> {
|
||||||
if (!isUserSessionValid()) {
|
if (!isUserSessionValid()) {
|
||||||
VaadinSession.getCurrent().getSession().invalidate(); // Session invalidieren
|
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
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import com.vaadin.flow.server.VaadinService;
|
|||||||
import com.vaadin.flow.component.UI;
|
import com.vaadin.flow.component.UI;
|
||||||
import com.vaadin.flow.component.html.Main;
|
import com.vaadin.flow.component.html.Main;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
|
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
import com.vaadin.flow.theme.lumo.LumoUtility;
|
||||||
import de.assecutor.emulatorstation.pojo.ExecResponse;
|
import de.assecutor.emulatorstation.pojo.ExecResponse;
|
||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
@@ -29,6 +30,7 @@ import java.util.concurrent.Executors;
|
|||||||
|
|
||||||
@PermitAll // When security is enabled, allow all authenticated users
|
@PermitAll // When security is enabled, allow all authenticated users
|
||||||
@Route("main")
|
@Route("main")
|
||||||
|
@AnonymousAllowed
|
||||||
public final class MainView extends Main implements BeforeEnterObserver
|
public final class MainView extends Main implements BeforeEnterObserver
|
||||||
{
|
{
|
||||||
private final String username;
|
private final String username;
|
||||||
@@ -101,10 +103,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
|
public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
|
||||||
String user = (String) VaadinService.getCurrentRequest().getWrappedSession().getAttribute("user");
|
// Kein Redirect mehr zur Login-Seite bei fehlender Session
|
||||||
if (user == null) {
|
|
||||||
beforeEnterEvent.rerouteTo("login");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startup() {
|
private void startup() {
|
||||||
@@ -414,8 +413,8 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
|
|
||||||
vaadinSession.invalidate();
|
vaadinSession.invalidate();
|
||||||
|
|
||||||
// Navigiere den Benutzer zur Login-Seite
|
// Navigiere den Benutzer zur Main-Seite
|
||||||
ui.navigate("");
|
ui.navigate("main");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user