Erweiterungen
This commit is contained in:
9
.claude/settings.local.json
Normal file
9
.claude/settings.local.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(mvn compile:*)"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>de.assecutor.emulatorstation</groupId>
|
<groupId>de.assecutor.emulatorstation</groupId>
|
||||||
<artifactId>emulatorstation</artifactId>
|
<artifactId>emulatorstation</artifactId>
|
||||||
<version>0.9.6</version>
|
<version>0.9.7</version>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -6,26 +6,38 @@ import com.vaadin.flow.theme.Theme;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import de.assecutor.emulatorstation.pojo.UserInfo;
|
import de.assecutor.emulatorstation.pojo.UserInfo;
|
||||||
|
import de.assecutor.emulatorstation.pojo.NiederlassungInfo;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@Push
|
@Push
|
||||||
@Theme("default")
|
@Theme("default")
|
||||||
public class Application implements AppShellConfigurator {
|
public class Application implements AppShellConfigurator {
|
||||||
public static final Map<String, UserInfo> users = Map.ofEntries(
|
public static final Map<String, UserInfo> users = Map.ofEntries(
|
||||||
Map. entry("admin", new UserInfo("ZY6X9X93Co8m", null, null, null)),
|
Map.entry("user1", new UserInfo("pass1")),
|
||||||
Map.entry("GFL", new UserInfo("GFL123", "172.18.0.112", "6092", "/gfl")),
|
Map.entry("user2", new UserInfo("pass2")),
|
||||||
Map.entry("Berlin", new UserInfo("Berlin123", "172.18.0.103", "6083", "/berlin")),
|
Map.entry("user3", new UserInfo("pass3")),
|
||||||
Map.entry("Bremen", new UserInfo("Bremen123", "172.18.0.101", "6081", "/bremen")),
|
Map.entry("user4", new UserInfo("pass4")),
|
||||||
Map.entry("Hamburg", new UserInfo("Hamburg123", "172.18.0.102", "6082", "/hamburg")),
|
Map.entry("user5", new UserInfo("pass5"))
|
||||||
Map.entry("Essen", new UserInfo("Essen123", "172.18.0.107", "6087", "/essen")),
|
|
||||||
Map.entry("Leipzig", new UserInfo("Leipzig123", "172.18.0.108", "6088", "/leipzig")),
|
|
||||||
Map.entry("Dresden", new UserInfo("Dresden123", "172.18.0.106", "6086", "/dresden")),
|
|
||||||
Map.entry("Hannover", new UserInfo("Hannover123", "172.18.0.104", "6084", "")),
|
|
||||||
Map.entry("Stuttgart", new UserInfo("Stuttgart123", "172.18.0.111", "6091", "/stuttgart")),
|
|
||||||
Map.entry("FrankfurtAmMain", new UserInfo("FrankfurtAmMain123", "172.18.0.105", "6085", "/frankfurt"))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public static final Map<String, NiederlassungInfo> niederlassungen = Map.ofEntries(
|
||||||
|
Map.entry("Berlin", new NiederlassungInfo("Berlin", "172.18.0.103", "6083", "/berlin")),
|
||||||
|
Map.entry("Bremen", new NiederlassungInfo("Bremen", "172.18.0.101", "6081", "/bremen")),
|
||||||
|
Map.entry("Hamburg", new NiederlassungInfo("Hamburg", "172.18.0.102", "6082", "/hamburg")),
|
||||||
|
Map.entry("Essen", new NiederlassungInfo("Essen", "172.18.0.107", "6087", "/essen")),
|
||||||
|
Map.entry("Leipzig", new NiederlassungInfo("Leipzig", "172.18.0.108", "6088", "/leipzig")),
|
||||||
|
Map.entry("Dresden", new NiederlassungInfo("Dresden", "172.18.0.106", "6086", "/dresden")),
|
||||||
|
Map.entry("Hannover", new NiederlassungInfo("Hannover", "172.18.0.104", "6084", "/hannover")),
|
||||||
|
Map.entry("Stuttgart", new NiederlassungInfo("Stuttgart", "172.18.0.111", "6091", "/stuttgart")),
|
||||||
|
Map.entry("Frankfurt am Main", new NiederlassungInfo("Frankfurt am Main", "172.18.0.105", "6085", "/frankfurt")),
|
||||||
|
Map.entry("Geschäftführung", new NiederlassungInfo("Geschäftführung", "172.18.0.112", "6092", "/gfl")),
|
||||||
|
Map.entry("Admin", new NiederlassungInfo("Admin", "172.18.0.110", "6090", "/admin"))
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final Map<String, String> activeNiederlassungen = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(Application.class, args);
|
SpringApplication.run(Application.class, args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,18 @@ package de.assecutor.emulatorstation.base.ui.view;
|
|||||||
import com.vaadin.flow.component.html.Span;
|
import com.vaadin.flow.component.html.Span;
|
||||||
import com.vaadin.flow.component.login.LoginForm;
|
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.select.Select;
|
||||||
|
import com.vaadin.flow.component.button.Button;
|
||||||
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
|
import com.vaadin.flow.component.textfield.PasswordField;
|
||||||
|
import com.vaadin.flow.component.notification.Notification;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||||
|
import de.assecutor.emulatorstation.Application;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Route("login")
|
@Route("login")
|
||||||
@AnonymousAllowed
|
@AnonymousAllowed
|
||||||
@@ -16,11 +26,56 @@ 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");
|
||||||
|
|
||||||
LoginForm loginForm = new LoginForm();
|
TextField usernameField = new TextField("Benutzername");
|
||||||
loginForm.setAction("login");
|
PasswordField passwordField = new PasswordField("Passwort");
|
||||||
loginForm.setForgotPasswordButtonVisible(false);
|
|
||||||
|
|
||||||
add(title, loginForm);
|
Select<String> niederlassungSelect = new Select<>();
|
||||||
|
niederlassungSelect.setLabel("Niederlassung");
|
||||||
|
niederlassungSelect.setItems(Application.niederlassungen.keySet().stream().sorted().toList());
|
||||||
|
niederlassungSelect.setPlaceholder("Wählen Sie eine Niederlassung");
|
||||||
|
|
||||||
|
Button loginButton = new Button("Anmelden", event -> {
|
||||||
|
String username = usernameField.getValue();
|
||||||
|
String password = passwordField.getValue();
|
||||||
|
String niederlassung = niederlassungSelect.getValue();
|
||||||
|
|
||||||
|
if (username.isEmpty() || password.isEmpty() || niederlassung == null) {
|
||||||
|
Notification.show("Bitte alle Felder ausfüllen", 3000, Notification.Position.MIDDLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Application.users.containsKey(username) ||
|
||||||
|
!Application.users.get(username).password().equals(password)) {
|
||||||
|
Notification.show("Ungültige Anmeldedaten", 3000, Notification.Position.MIDDLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Application.activeNiederlassungen.containsKey(niederlassung)) {
|
||||||
|
Notification.show("Niederlassung ist bereits von einem anderen Benutzer belegt", 3000, Notification.Position.MIDDLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.activeNiederlassungen.put(niederlassung, username);
|
||||||
|
|
||||||
|
// Spring Security Authentifizierung setzen
|
||||||
|
var authorities = List.of(new SimpleGrantedAuthority("ROLE_USER"));
|
||||||
|
var authentication = new UsernamePasswordAuthenticationToken(username, password, authorities);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
|
||||||
|
getUI().ifPresent(ui -> {
|
||||||
|
ui.getSession().setAttribute("user", username);
|
||||||
|
ui.getSession().setAttribute("username", username);
|
||||||
|
ui.getSession().setAttribute("niederlassung", niederlassung);
|
||||||
|
|
||||||
|
System.out.println("Login erfolgreich - Session-Daten gesetzt:");
|
||||||
|
System.out.println("Username: " + username);
|
||||||
|
System.out.println("Niederlassung: " + niederlassung);
|
||||||
|
|
||||||
|
ui.navigate("main");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add(title, usernameField, passwordField, niederlassungSelect, loginButton);
|
||||||
|
|
||||||
if (MainLayout.instance != null) {
|
if (MainLayout.instance != null) {
|
||||||
MainLayout.instance.setDrawerOpened(false);
|
MainLayout.instance.setDrawerOpened(false);
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import com.vaadin.flow.component.ClientCallable;
|
|||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
import com.vaadin.flow.component.button.ButtonVariant;
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
import com.vaadin.flow.component.dialog.Dialog;
|
import com.vaadin.flow.component.dialog.Dialog;
|
||||||
|
import com.vaadin.flow.component.html.Div;
|
||||||
|
import com.vaadin.flow.component.html.H2;
|
||||||
import com.vaadin.flow.component.html.IFrame;
|
import com.vaadin.flow.component.html.IFrame;
|
||||||
import com.vaadin.flow.component.html.Paragraph;
|
import com.vaadin.flow.component.html.Paragraph;
|
||||||
|
import com.vaadin.flow.component.icon.Icon;
|
||||||
|
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||||
@@ -16,11 +20,11 @@ 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.server.auth.AnonymousAllowed;
|
||||||
import com.vaadin.flow.theme.lumo.LumoUtility;
|
|
||||||
import de.assecutor.emulatorstation.pojo.ExecResponse;
|
import de.assecutor.emulatorstation.pojo.ExecResponse;
|
||||||
import de.assecutor.emulatorstation.Application;
|
import de.assecutor.emulatorstation.Application;
|
||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import util.Util;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
@@ -34,25 +38,46 @@ import java.util.concurrent.Executors;
|
|||||||
@AnonymousAllowed
|
@AnonymousAllowed
|
||||||
public final class MainView extends Main implements BeforeEnterObserver
|
public final class MainView extends Main implements BeforeEnterObserver
|
||||||
{
|
{
|
||||||
private final String username;
|
private static final Logger logger = LoggerFactory.getLogger(MainView.class);
|
||||||
private final String server;
|
private String username;
|
||||||
|
private String niederlassung;
|
||||||
|
private String server;
|
||||||
|
|
||||||
private final IFrame webView;
|
private final IFrame webView = new IFrame();
|
||||||
|
private final Div emulatorContainer = new Div();
|
||||||
|
private final Div welcomeMessage = new Div();
|
||||||
|
|
||||||
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
MainView() {
|
MainView() {
|
||||||
try {
|
setSizeFull();
|
||||||
} catch (Exception ex) {
|
getStyle()
|
||||||
showWaitDialog("Fehler!\n" + ex.toString());
|
.set("display", "flex")
|
||||||
|
.set("flex-direction", "column")
|
||||||
|
.set("align-items", "center")
|
||||||
|
.set("justify-content", "center")
|
||||||
|
.set("padding", "5%")
|
||||||
|
.set("box-sizing", "border-box")
|
||||||
|
.set("overflow", "hidden");
|
||||||
|
|
||||||
|
var contentContainer = new Div();
|
||||||
|
contentContainer.getStyle()
|
||||||
|
.set("width", "95%")
|
||||||
|
.set("height", "95%")
|
||||||
|
.set("display", "flex")
|
||||||
|
.set("flex-direction", "column")
|
||||||
|
.set("box-sizing", "border-box");
|
||||||
|
|
||||||
|
setupInactivityTimer();
|
||||||
|
setupWelcomeMessage(contentContainer);
|
||||||
|
setupEmulatorContainer(contentContainer);
|
||||||
|
setupButtonLayout(contentContainer);
|
||||||
|
|
||||||
|
add(contentContainer);
|
||||||
|
addAttachListener(event -> loadSessionData());
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentSession = VaadinService.getCurrentRequest().getWrappedSession();
|
private void setupInactivityTimer() {
|
||||||
username = Util.getSessionAttributeWithDefault(currentSession, "username", null);
|
|
||||||
server = Util.getSessionAttributeWithDefault(currentSession, "server", "172.16.0.158");
|
|
||||||
|
|
||||||
addClassName(LumoUtility.Padding.MEDIUM);
|
|
||||||
|
|
||||||
String jsCode = """
|
String jsCode = """
|
||||||
var inactivityTime = function () {
|
var inactivityTime = function () {
|
||||||
var time;
|
var time;
|
||||||
@@ -63,41 +88,106 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
document.onscroll = resetTimer;
|
document.onscroll = resetTimer;
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
$0.$server.logout(); // Server-Logout via RPC
|
$0.$server.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetTimer() {
|
function resetTimer() {
|
||||||
clearTimeout(time);
|
clearTimeout(time);
|
||||||
time = setTimeout(logout, 5 * 60 * 1000); // 5 Minute Inaktivität
|
time = setTimeout(logout, 4 * 60 * 60 * 1000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
inactivityTime();
|
inactivityTime();
|
||||||
""";
|
""";
|
||||||
|
|
||||||
UI.getCurrent().getPage().executeJs(jsCode, this);
|
UI.getCurrent().getPage().executeJs(jsCode, this);
|
||||||
|
}
|
||||||
|
|
||||||
var horizontalLayout = new HorizontalLayout();
|
private void setupWelcomeMessage(Div container) {
|
||||||
add(horizontalLayout);
|
welcomeMessage.addClassName("welcome-panel");
|
||||||
|
welcomeMessage.getStyle()
|
||||||
|
.set("display", "flex")
|
||||||
|
.set("flex-direction", "column")
|
||||||
|
.set("align-items", "center")
|
||||||
|
.set("justify-content", "center")
|
||||||
|
.set("flex-grow", "1")
|
||||||
|
.set("background-color", "#f8f9fa")
|
||||||
|
.set("border", "2px dashed #dee2e6")
|
||||||
|
.set("border-radius", "8px")
|
||||||
|
.set("color", "#6c757d");
|
||||||
|
|
||||||
Button startBtn = new Button("Start", event -> startup());
|
Icon icon = new Icon(VaadinIcon.DESKTOP);
|
||||||
|
icon.setSize("48px");
|
||||||
|
icon.getStyle().set("margin-bottom", "12px");
|
||||||
|
|
||||||
|
H2 title = new H2("Willkommen bei der Emulator Station");
|
||||||
|
title.getStyle().set("margin", "0 0 6px 0").set("color", "#495057").set("font-size", "1.5rem");
|
||||||
|
|
||||||
|
Paragraph description = new Paragraph("Klicken Sie auf 'Start', um Ihren Android Emulator zu starten.");
|
||||||
|
description.getStyle().set("margin", "0").set("text-align", "center").set("font-size", "0.9rem");
|
||||||
|
|
||||||
|
welcomeMessage.add(icon, title, description);
|
||||||
|
container.add(welcomeMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupButtonLayout(Div container) {
|
||||||
|
var buttonLayout = new HorizontalLayout();
|
||||||
|
buttonLayout.setJustifyContentMode(HorizontalLayout.JustifyContentMode.CENTER);
|
||||||
|
buttonLayout.getStyle()
|
||||||
|
.set("margin", "0")
|
||||||
|
.set("padding", "8px 0")
|
||||||
|
.set("flex-shrink", "0");
|
||||||
|
|
||||||
|
Button startBtn = new Button("Emulator starten", new Icon(VaadinIcon.PLAY), event -> startup());
|
||||||
startBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
startBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||||
horizontalLayout.add(startBtn);
|
|
||||||
|
|
||||||
Button logoutBtn = new Button("Logout", event -> logout());
|
Button logoutBtn = new Button("Abmelden", new Icon(VaadinIcon.SIGN_OUT), event -> logout());
|
||||||
logoutBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
logoutBtn.addThemeVariants(ButtonVariant.LUMO_CONTRAST);
|
||||||
horizontalLayout.add(logoutBtn);
|
|
||||||
|
|
||||||
webView = new IFrame();
|
buttonLayout.add(startBtn, logoutBtn);
|
||||||
webView.setSizeFull(); // IFrame auf volle Größe setzen
|
container.add(buttonLayout);
|
||||||
webView.getElement().setAttribute("frameborder", "0"); // Optional: Rahmen entfernen
|
}
|
||||||
|
|
||||||
// Layout konfigurieren
|
private void setupEmulatorContainer(Div container) {
|
||||||
setSizeFull(); // Vertikales Layout auf volle Größe setzen
|
emulatorContainer.getStyle()
|
||||||
add(webView);
|
.set("border", "2px solid #e9ecef")
|
||||||
|
.set("border-radius", "8px")
|
||||||
|
.set("background-color", "#ffffff")
|
||||||
|
.set("box-shadow", "0 2px 4px rgba(0,0,0,0.1)")
|
||||||
|
.set("overflow", "hidden")
|
||||||
|
.set("display", "none")
|
||||||
|
.set("flex-grow", "1");
|
||||||
|
|
||||||
addAttachListener(event -> {
|
webView.setSizeFull();
|
||||||
event.getUI();
|
webView.getElement().setAttribute("frameborder", "0");
|
||||||
});
|
|
||||||
|
emulatorContainer.add(webView);
|
||||||
|
container.add(emulatorContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSessionData() {
|
||||||
|
var currentUI = getUI();
|
||||||
|
if (currentUI.isPresent()) {
|
||||||
|
var vaadinSession = currentUI.get().getSession();
|
||||||
|
username = (String) vaadinSession.getAttribute("username");
|
||||||
|
niederlassung = (String) vaadinSession.getAttribute("niederlassung");
|
||||||
|
server = (String) vaadinSession.getAttribute("server");
|
||||||
|
} else {
|
||||||
|
System.err.println("UI nicht verfügbar - kann Session-Daten nicht laden");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server == null) {
|
||||||
|
server = "172.16.0.158";
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("MainView Session-Daten geladen:");
|
||||||
|
System.out.println("Username: " + username);
|
||||||
|
System.out.println("Niederlassung: " + niederlassung);
|
||||||
|
System.out.println("Server: " + server);
|
||||||
|
|
||||||
|
if (niederlassung == null) {
|
||||||
|
System.err.println("FEHLER: Niederlassung ist null! Benutzer muss sich neu anmelden.");
|
||||||
|
getUI().ifPresent(ui -> ui.navigate("login"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -131,6 +221,10 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
ui.access(() -> {
|
ui.access(() -> {
|
||||||
dialog.close();
|
dialog.close();
|
||||||
|
|
||||||
|
// Willkommensnachricht ausblenden und Emulator anzeigen
|
||||||
|
welcomeMessage.getStyle().set("display", "none");
|
||||||
|
emulatorContainer.getStyle().set("display", "block");
|
||||||
|
|
||||||
refreshWebView();
|
refreshWebView();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -144,7 +238,18 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void refreshWebView() {
|
private void refreshWebView() {
|
||||||
var url = "https://sb-app.emu.assecutor.org" + Application.users.get(username).urlExtension() + "?autoconnect=true";
|
if (niederlassung == null) {
|
||||||
|
System.err.println("Niederlassung ist null - kann WebView nicht aktualisieren");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var niederlassungInfo = Application.niederlassungen.get(niederlassung);
|
||||||
|
if (niederlassungInfo == null) {
|
||||||
|
System.err.println("Niederlassungsinfo für '" + niederlassung + "' nicht gefunden");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = "https://sb-app.emu.assecutor.org" + niederlassungInfo.urlExtension() + "?autoconnect=true";
|
||||||
|
|
||||||
System.out.println("URL: " + url);
|
System.out.println("URL: " + url);
|
||||||
|
|
||||||
@@ -181,10 +286,10 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
|
|
||||||
exec(execId);
|
exec(execId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("Fehler beim Senden der HTTP-Anfrage für App-Download", e);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("Fehler beim Download der App", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +318,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
|
|
||||||
exec(execId);
|
exec(execId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("Fehler bei der App-Installation", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +338,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
|
|
||||||
return response.body();
|
return response.body();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace(); // Fehler behandeln
|
logger.error("Fehler beim Ausführen des Befehls mit execId: {}", execId, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -252,7 +357,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
System.out.println("HTTP-Response-Code: " + response.statusCode()); // Statuscode ausgeben
|
System.out.println("HTTP-Response-Code: " + response.statusCode()); // Statuscode ausgeben
|
||||||
System.out.println("Response-Body: " + response.body()); // Antwort-Body ausgeben
|
System.out.println("Response-Body: " + response.body()); // Antwort-Body ausgeben
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace(); // Fehler behandeln
|
logger.error("Fehler beim HTTP-Request", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +399,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("Fehler beim Warten auf Container-Start", e);
|
||||||
}
|
}
|
||||||
} while (!endLoop);
|
} while (!endLoop);
|
||||||
}
|
}
|
||||||
@@ -312,6 +417,8 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
],
|
],
|
||||||
"HostConfig": {
|
"HostConfig": {
|
||||||
"NetworkMode": "votianBridge",
|
"NetworkMode": "votianBridge",
|
||||||
|
"Memory": 10737418240,
|
||||||
|
"CpuCount": 4,
|
||||||
"Dns": [
|
"Dns": [
|
||||||
"172.18.0.15"
|
"172.18.0.15"
|
||||||
],
|
],
|
||||||
@@ -343,7 +450,20 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".formatted(Application.users.get(username).port(), Application.users.get(username).ip());
|
""";
|
||||||
|
|
||||||
|
if (niederlassung == null) {
|
||||||
|
System.err.println("Niederlassung ist null - kann Container nicht erstellen");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var niederlassungInfo = Application.niederlassungen.get(niederlassung);
|
||||||
|
if (niederlassungInfo == null) {
|
||||||
|
System.err.println("Niederlassungsinfo für '" + niederlassung + "' nicht gefunden");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonPayload = jsonPayload.formatted(niederlassungInfo.port(), niederlassungInfo.ip());
|
||||||
|
|
||||||
System.out.println(jsonPayload);
|
System.out.println(jsonPayload);
|
||||||
|
|
||||||
@@ -360,7 +480,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
System.out.println("HTTP-Response-Code: " + response.statusCode());
|
System.out.println("HTTP-Response-Code: " + response.statusCode());
|
||||||
System.out.println("Response-Body: " + response.body());
|
System.out.println("Response-Body: " + response.body());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
logger.error("Fehler beim Erstellen des Containers", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +497,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
System.out.println("HTTP-Response-Code: " + response.statusCode()); // Statuscode ausgeben
|
System.out.println("HTTP-Response-Code: " + response.statusCode()); // Statuscode ausgeben
|
||||||
System.out.println("Response-Body: " + response.body()); // Antwort-Body ausgeben
|
System.out.println("Response-Body: " + response.body()); // Antwort-Body ausgeben
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace(); // Fehler behandeln
|
logger.error("Fehler beim HTTP-Request", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +514,7 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
System.out.println("HTTP-Response-Code: " + response.statusCode()); // Statuscode ausgeben
|
System.out.println("HTTP-Response-Code: " + response.statusCode()); // Statuscode ausgeben
|
||||||
System.out.println("Response-Body: " + response.body()); // Antwort-Body ausgeben
|
System.out.println("Response-Body: " + response.body()); // Antwort-Body ausgeben
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace(); // Fehler behandeln
|
logger.error("Fehler beim HTTP-Request", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,10 +552,15 @@ public final class MainView extends Main implements BeforeEnterObserver
|
|||||||
ui.access(() -> {
|
ui.access(() -> {
|
||||||
dialog.close();
|
dialog.close();
|
||||||
|
|
||||||
|
// Session cleanup vor Navigation
|
||||||
|
if (niederlassung != null) {
|
||||||
|
Application.activeNiederlassungen.remove(niederlassung);
|
||||||
|
}
|
||||||
|
|
||||||
vaadinSession.invalidate();
|
vaadinSession.invalidate();
|
||||||
|
|
||||||
// Navigiere den Benutzer zur Main-Seite
|
// Navigiere direkt zur Login-Seite
|
||||||
ui.navigate("main");
|
ui.navigate("login");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,15 +2,8 @@ package de.assecutor.emulatorstation.base.ui.view.security;
|
|||||||
|
|
||||||
import com.vaadin.flow.spring.security.VaadinWebSecurity;
|
import com.vaadin.flow.spring.security.VaadinWebSecurity;
|
||||||
import de.assecutor.emulatorstation.base.ui.view.LoginView;
|
import de.assecutor.emulatorstation.base.ui.view.LoginView;
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
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;
|
import de.assecutor.emulatorstation.Application;
|
||||||
|
|
||||||
@@ -21,50 +14,21 @@ public class SecurityConfig extends VaadinWebSecurity {
|
|||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
super.configure(http);
|
super.configure(http);
|
||||||
|
|
||||||
// FormLogin verwenden; Vaadin-LoginView
|
|
||||||
setLoginView(http, LoginView.class);
|
setLoginView(http, LoginView.class);
|
||||||
|
|
||||||
http
|
http
|
||||||
.formLogin(form -> form
|
|
||||||
.loginPage("/login")
|
|
||||||
.successHandler(authenticationSuccessHandler())
|
|
||||||
.permitAll()
|
|
||||||
)
|
|
||||||
.logout(logout -> logout
|
.logout(logout -> logout
|
||||||
.logoutSuccessUrl("/main")
|
.logoutSuccessUrl("/login")
|
||||||
);
|
.addLogoutHandler((request, response, authentication) -> {
|
||||||
}
|
if (authentication != null) {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public UserDetailsService userDetailsService() {
|
|
||||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
|
||||||
Application.users.forEach((username, info) ->
|
|
||||||
manager.createUser(User.withUsername(username)
|
|
||||||
.password(info.password())
|
|
||||||
.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();
|
String username = authentication.getName();
|
||||||
session.setAttribute("user", username);
|
Application.activeNiederlassungen.entrySet().removeIf(entry ->
|
||||||
session.setAttribute("username", username);
|
entry.getValue().equals(username));
|
||||||
String target = "admin".equalsIgnoreCase(username) ? "/admin" : "/main";
|
|
||||||
response.sendRedirect(target);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package de.assecutor.emulatorstation.base.ui.view.security;
|
||||||
|
|
||||||
|
import com.vaadin.flow.server.SessionDestroyEvent;
|
||||||
|
import com.vaadin.flow.server.SessionDestroyListener;
|
||||||
|
import com.vaadin.flow.spring.annotation.SpringComponent;
|
||||||
|
import de.assecutor.emulatorstation.Application;
|
||||||
|
|
||||||
|
@SpringComponent
|
||||||
|
public class SessionListener implements SessionDestroyListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sessionDestroy(SessionDestroyEvent event) {
|
||||||
|
String username = (String) event.getSession().getAttribute("user");
|
||||||
|
String niederlassung = (String) event.getSession().getAttribute("niederlassung");
|
||||||
|
|
||||||
|
if (username != null && niederlassung != null) {
|
||||||
|
Application.activeNiederlassungen.remove(niederlassung);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package de.assecutor.emulatorstation.pojo;
|
||||||
|
|
||||||
|
public record NiederlassungInfo(String name, String ip, String port, String urlExtension) {
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package de.assecutor.emulatorstation.pojo;
|
package de.assecutor.emulatorstation.pojo;
|
||||||
|
|
||||||
public record UserInfo(String password, String ip, String port, String urlExtension) {
|
public record UserInfo(String password) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user