diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..fec1c41 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(mvn compile:*)" + ], + "deny": [], + "ask": [] + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9da44e6..c79e1c7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.assecutor.emulatorstation emulatorstation - 0.9.6 + 0.9.7 jar diff --git a/src/main/bundles/prod.bundle b/src/main/bundles/prod.bundle index 1771856..d54a10f 100644 Binary files a/src/main/bundles/prod.bundle and b/src/main/bundles/prod.bundle differ diff --git a/src/main/java/de/assecutor/emulatorstation/Application.java b/src/main/java/de/assecutor/emulatorstation/Application.java index 5cd39ef..3ad6318 100644 --- a/src/main/java/de/assecutor/emulatorstation/Application.java +++ b/src/main/java/de/assecutor/emulatorstation/Application.java @@ -6,26 +6,38 @@ import com.vaadin.flow.theme.Theme; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import de.assecutor.emulatorstation.pojo.UserInfo; +import de.assecutor.emulatorstation.pojo.NiederlassungInfo; @SpringBootApplication @Push @Theme("default") public class Application implements AppShellConfigurator { public static final Map users = Map.ofEntries( - Map. entry("admin", new UserInfo("ZY6X9X93Co8m", null, null, null)), - Map.entry("GFL", new UserInfo("GFL123", "172.18.0.112", "6092", "/gfl")), - Map.entry("Berlin", new UserInfo("Berlin123", "172.18.0.103", "6083", "/berlin")), - Map.entry("Bremen", new UserInfo("Bremen123", "172.18.0.101", "6081", "/bremen")), - Map.entry("Hamburg", new UserInfo("Hamburg123", "172.18.0.102", "6082", "/hamburg")), - 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")) + Map.entry("user1", new UserInfo("pass1")), + Map.entry("user2", new UserInfo("pass2")), + Map.entry("user3", new UserInfo("pass3")), + Map.entry("user4", new UserInfo("pass4")), + Map.entry("user5", new UserInfo("pass5")) ); + public static final Map 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 activeNiederlassungen = new ConcurrentHashMap<>(); + public static void main(String[] args) { SpringApplication.run(Application.class, args); } 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 aebe489..f39c48f 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 @@ -3,8 +3,18 @@ package de.assecutor.emulatorstation.base.ui.view; import com.vaadin.flow.component.html.Span; import com.vaadin.flow.component.login.LoginForm; 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.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") @AnonymousAllowed @@ -16,11 +26,56 @@ public class LoginView extends VerticalLayout { Span title = new Span("Anmelden"); title.getStyle().set("font-size", "24px").set("font-weight", "bold"); - LoginForm loginForm = new LoginForm(); - loginForm.setAction("login"); - loginForm.setForgotPasswordButtonVisible(false); + TextField usernameField = new TextField("Benutzername"); + PasswordField passwordField = new PasswordField("Passwort"); - add(title, loginForm); + Select 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) { MainLayout.instance.setDrawerOpened(false); 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 f03a187..4c9ead1 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 @@ -4,8 +4,12 @@ import com.vaadin.flow.component.ClientCallable; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; 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.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.VerticalLayout; 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.router.Route; import com.vaadin.flow.server.auth.AnonymousAllowed; -import com.vaadin.flow.theme.lumo.LumoUtility; import de.assecutor.emulatorstation.pojo.ExecResponse; import de.assecutor.emulatorstation.Application; import jakarta.annotation.security.PermitAll; -import util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.net.URI; import java.net.http.HttpClient; @@ -34,25 +38,46 @@ import java.util.concurrent.Executors; @AnonymousAllowed public final class MainView extends Main implements BeforeEnterObserver { - private final String username; - private final String server; + private static final Logger logger = LoggerFactory.getLogger(MainView.class); + 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(); MainView() { - try { - } catch (Exception ex) { - showWaitDialog("Fehler!\n" + ex.toString()); - } + setSizeFull(); + getStyle() + .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 currentSession = VaadinService.getCurrentRequest().getWrappedSession(); - username = Util.getSessionAttributeWithDefault(currentSession, "username", null); - server = Util.getSessionAttributeWithDefault(currentSession, "server", "172.16.0.158"); + var contentContainer = new Div(); + contentContainer.getStyle() + .set("width", "95%") + .set("height", "95%") + .set("display", "flex") + .set("flex-direction", "column") + .set("box-sizing", "border-box"); - addClassName(LumoUtility.Padding.MEDIUM); + setupInactivityTimer(); + setupWelcomeMessage(contentContainer); + setupEmulatorContainer(contentContainer); + setupButtonLayout(contentContainer); + add(contentContainer); + addAttachListener(event -> loadSessionData()); + } + + private void setupInactivityTimer() { String jsCode = """ var inactivityTime = function () { var time; @@ -63,41 +88,106 @@ public final class MainView extends Main implements BeforeEnterObserver document.onscroll = resetTimer; function logout() { - $0.$server.logout(); // Server-Logout via RPC + $0.$server.logout(); } function resetTimer() { clearTimeout(time); - time = setTimeout(logout, 5 * 60 * 1000); // 5 Minute Inaktivität + time = setTimeout(logout, 4 * 60 * 60 * 1000); } }; inactivityTime(); """; UI.getCurrent().getPage().executeJs(jsCode, this); + } - var horizontalLayout = new HorizontalLayout(); - add(horizontalLayout); + private void setupWelcomeMessage(Div container) { + 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); - horizontalLayout.add(startBtn); - Button logoutBtn = new Button("Logout", event -> logout()); - logoutBtn.addThemeVariants(ButtonVariant.LUMO_PRIMARY); - horizontalLayout.add(logoutBtn); + Button logoutBtn = new Button("Abmelden", new Icon(VaadinIcon.SIGN_OUT), event -> logout()); + logoutBtn.addThemeVariants(ButtonVariant.LUMO_CONTRAST); - webView = new IFrame(); - webView.setSizeFull(); // IFrame auf volle Größe setzen - webView.getElement().setAttribute("frameborder", "0"); // Optional: Rahmen entfernen + buttonLayout.add(startBtn, logoutBtn); + container.add(buttonLayout); + } - // Layout konfigurieren - setSizeFull(); // Vertikales Layout auf volle Größe setzen - add(webView); + private void setupEmulatorContainer(Div container) { + emulatorContainer.getStyle() + .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 -> { - event.getUI(); - }); + webView.setSizeFull(); + 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 @@ -131,6 +221,10 @@ public final class MainView extends Main implements BeforeEnterObserver ui.access(() -> { dialog.close(); + // Willkommensnachricht ausblenden und Emulator anzeigen + welcomeMessage.getStyle().set("display", "none"); + emulatorContainer.getStyle().set("display", "block"); + refreshWebView(); }); } @@ -144,7 +238,18 @@ public final class MainView extends Main implements BeforeEnterObserver } 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); @@ -181,10 +286,10 @@ public final class MainView extends Main implements BeforeEnterObserver exec(execId); } catch (Exception e) { - e.printStackTrace(); + logger.error("Fehler beim Senden der HTTP-Anfrage für App-Download", 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); } 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(); } catch (Exception e) { - e.printStackTrace(); // Fehler behandeln + logger.error("Fehler beim Ausführen des Befehls mit execId: {}", execId, e); } 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("Response-Body: " + response.body()); // Antwort-Body ausgeben } 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) { - e.printStackTrace(); + logger.error("Fehler beim Warten auf Container-Start", e); } } while (!endLoop); } @@ -312,6 +417,8 @@ public final class MainView extends Main implements BeforeEnterObserver ], "HostConfig": { "NetworkMode": "votianBridge", + "Memory": 10737418240, + "CpuCount": 4, "Dns": [ "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); @@ -360,7 +480,7 @@ public final class MainView extends Main implements BeforeEnterObserver System.out.println("HTTP-Response-Code: " + response.statusCode()); System.out.println("Response-Body: " + response.body()); } 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("Response-Body: " + response.body()); // Antwort-Body ausgeben } 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("Response-Body: " + response.body()); // Antwort-Body ausgeben } 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(() -> { dialog.close(); + // Session cleanup vor Navigation + if (niederlassung != null) { + Application.activeNiederlassungen.remove(niederlassung); + } + vaadinSession.invalidate(); - // Navigiere den Benutzer zur Main-Seite - ui.navigate("main"); + // Navigiere direkt zur Login-Seite + ui.navigate("login"); }); } }); 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 index 79866a1..161a956 100644 --- 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 @@ -2,15 +2,8 @@ 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; @@ -21,50 +14,21 @@ public class SecurityConfig extends VaadinWebSecurity { 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") + .logoutSuccessUrl("/login") + .addLogoutHandler((request, response, authentication) -> { + if (authentication != null) { + String username = authentication.getName(); + Application.activeNiederlassungen.entrySet().removeIf(entry -> + entry.getValue().equals(username)); + } + }) ); } - @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(); - session.setAttribute("user", username); - session.setAttribute("username", username); - String target = "admin".equalsIgnoreCase(username) ? "/admin" : "/main"; - response.sendRedirect(target); - }; - } } diff --git a/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/SessionListener.java b/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/SessionListener.java new file mode 100644 index 0000000..c6f7b8f --- /dev/null +++ b/src/main/java/de/assecutor/emulatorstation/base/ui/view/security/SessionListener.java @@ -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); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/assecutor/emulatorstation/pojo/NiederlassungInfo.java b/src/main/java/de/assecutor/emulatorstation/pojo/NiederlassungInfo.java new file mode 100644 index 0000000..4a7856e --- /dev/null +++ b/src/main/java/de/assecutor/emulatorstation/pojo/NiederlassungInfo.java @@ -0,0 +1,4 @@ +package de.assecutor.emulatorstation.pojo; + +public record NiederlassungInfo(String name, String ip, String port, String urlExtension) { +} \ No newline at end of file diff --git a/src/main/java/de/assecutor/emulatorstation/pojo/UserInfo.java b/src/main/java/de/assecutor/emulatorstation/pojo/UserInfo.java index 1019f47..cf3a04b 100644 --- a/src/main/java/de/assecutor/emulatorstation/pojo/UserInfo.java +++ b/src/main/java/de/assecutor/emulatorstation/pojo/UserInfo.java @@ -1,6 +1,6 @@ package de.assecutor.emulatorstation.pojo; -public record UserInfo(String password, String ip, String port, String urlExtension) { +public record UserInfo(String password) { }