Compare commits
1 Commits
9a67832faa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b313cd588 |
@@ -67,6 +67,21 @@ public class SimCardAssignmentService {
|
||||
}
|
||||
}
|
||||
|
||||
public void releaseSimCard(SimCardInfo simCard) {
|
||||
try {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(buildUri("/api/simcards/" + simCard.simCardId() + "/assign")).DELETE().build();
|
||||
|
||||
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
ensureSuccessful(response, "Zuordnung der SIM-Karte konnte nicht aufgehoben werden.");
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Zuordnung der SIM-Karte konnte nicht aufgehoben werden.", e);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IllegalStateException("Aufheben der Zuordnung wurde unterbrochen.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void assignSimCard(CourierInfo courier, SimCardInfo simCard) {
|
||||
try {
|
||||
String payload = objectMapper.writeValueAsString(
|
||||
|
||||
@@ -40,6 +40,8 @@ import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@AnonymousAllowed
|
||||
@Route("main")
|
||||
@@ -335,6 +337,8 @@ public final class MainView extends Main implements BeforeEnterObserver {
|
||||
downloadApp();
|
||||
|
||||
installApp();
|
||||
|
||||
startApp();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// Logging, Fehlerbehandlung …
|
||||
@@ -415,6 +419,83 @@ public final class MainView extends Main implements BeforeEnterObserver {
|
||||
}
|
||||
}
|
||||
|
||||
private void startApp() {
|
||||
String packageName = listThirdPartyPackage();
|
||||
if (packageName == null || packageName.isBlank()) {
|
||||
logger.error("Konnte Package-Namen der installierten App nicht ermitteln - App wird nicht gestartet");
|
||||
return;
|
||||
}
|
||||
logger.info("Starte App mit Package-Name: {}", packageName);
|
||||
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
String jsonPayload = """
|
||||
{
|
||||
"Cmd": ["adb", "shell", "monkey", "-p", "%s", "-c", "android.intent.category.LAUNCHER", "1"],
|
||||
"AttachStdout": true,
|
||||
"AttachStderr": true
|
||||
}""".formatted(packageName);
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(
|
||||
"http://" + server + ":2375/containers/android-container-" + niederlassung.name() + "/exec"))
|
||||
.header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
|
||||
.build();
|
||||
|
||||
try {
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
logger.info("HTTP-Response-Code: {}", response.statusCode());
|
||||
logger.info("Response-Body: {}", response.body());
|
||||
|
||||
var execId = ExecResponse.parse(response.body());
|
||||
|
||||
exec(execId);
|
||||
} catch (Exception e) {
|
||||
logger.error("Fehler beim Starten der App", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String listThirdPartyPackage() {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
String jsonPayload = """
|
||||
{
|
||||
"Cmd": ["adb", "shell", "pm", "list", "packages", "-3"],
|
||||
"AttachStdout": true,
|
||||
"AttachStderr": true
|
||||
}""";
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(
|
||||
"http://" + server + ":2375/containers/android-container-" + niederlassung.name() + "/exec"))
|
||||
.header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
|
||||
.build();
|
||||
|
||||
try {
|
||||
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
logger.info("HTTP-Response-Code: {}", response.statusCode());
|
||||
logger.info("Response-Body: {}", response.body());
|
||||
|
||||
var execId = ExecResponse.parse(response.body());
|
||||
var execResponse = exec(execId);
|
||||
return extractFirstPackageName(execResponse);
|
||||
} catch (Exception e) {
|
||||
logger.error("Fehler beim Ermitteln des Package-Namens", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String extractFirstPackageName(String body) {
|
||||
if (body == null) {
|
||||
return null;
|
||||
}
|
||||
Matcher matcher = Pattern.compile("package:([A-Za-z0-9_.]+)").matcher(body);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void installApp() {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
|
||||
|
||||
@@ -7,12 +7,14 @@ import com.vaadin.flow.component.dialog.Dialog;
|
||||
import com.vaadin.flow.component.html.Div;
|
||||
import com.vaadin.flow.component.html.H1;
|
||||
import com.vaadin.flow.component.html.Paragraph;
|
||||
import com.vaadin.flow.component.html.Span;
|
||||
import com.vaadin.flow.component.icon.Icon;
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.notification.Notification;
|
||||
import com.vaadin.flow.component.orderedlayout.FlexComponent;
|
||||
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
|
||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||
import com.vaadin.flow.data.renderer.ComponentRenderer;
|
||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
@@ -28,14 +30,20 @@ import de.assecutor.emulatorstation.base.ui.view.security.SsoConfiguration;
|
||||
import de.assecutor.emulatorstation.pojo.CourierInfo;
|
||||
import de.assecutor.emulatorstation.pojo.NiederlassungInfo;
|
||||
import de.assecutor.emulatorstation.pojo.SimCardInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Route("sim-config")
|
||||
@PageTitle("SIM-Konfiguration")
|
||||
@AnonymousAllowed
|
||||
public class SimCardConfigurationView extends VerticalLayout implements BeforeEnterObserver {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SimCardConfigurationView.class);
|
||||
|
||||
private final AuthenticationContext authenticationContext;
|
||||
private final LoginSessionService loginSessionService;
|
||||
private final EmulatorContainerService emulatorContainerService;
|
||||
@@ -47,6 +55,7 @@ public class SimCardConfigurationView extends VerticalLayout implements BeforeEn
|
||||
private final ComboBox<SimCardInfo> simCardSelect = new ComboBox<>("SIM-Karte");
|
||||
private final Paragraph statusText = new Paragraph("Lade Kuriere und SIM-Karten...");
|
||||
private final Button assignButton;
|
||||
private final Map<Long, String> courierSidByUserId = new HashMap<>();
|
||||
|
||||
public SimCardConfigurationView(AuthenticationContext authenticationContext,
|
||||
LoginSessionService loginSessionService, EmulatorContainerService emulatorContainerService,
|
||||
@@ -89,6 +98,39 @@ public class SimCardConfigurationView extends VerticalLayout implements BeforeEn
|
||||
simCardSelect.setWidthFull();
|
||||
simCardSelect.setPlaceholder("SIM-Karte auswählen");
|
||||
simCardSelect.setItemLabelGenerator(SimCardInfo::displayLabel);
|
||||
simCardSelect.setRenderer(new ComponentRenderer<>(simCard -> {
|
||||
HorizontalLayout row = new HorizontalLayout();
|
||||
row.setAlignItems(Alignment.CENTER);
|
||||
row.setSpacing(true);
|
||||
row.setPadding(false);
|
||||
row.setWidthFull();
|
||||
row.setJustifyContentMode(JustifyContentMode.BETWEEN);
|
||||
|
||||
Span label = new Span(simCard.displayLabel());
|
||||
row.add(label);
|
||||
|
||||
if (isSimCardOccupied(simCard)) {
|
||||
String courierSid = courierSidByUserId.getOrDefault(simCard.userId(),
|
||||
String.valueOf(simCard.userId()));
|
||||
Span badge = new Span("Belegt durch " + courierSid);
|
||||
badge.getElement().getThemeList().add("badge error small");
|
||||
|
||||
Button releaseButton = new Button(new Icon(VaadinIcon.UNLINK));
|
||||
releaseButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE, ButtonVariant.LUMO_SMALL,
|
||||
ButtonVariant.LUMO_ERROR);
|
||||
releaseButton.getElement().setAttribute("title", "Zuordnung aufheben");
|
||||
releaseButton.addClickListener(event -> confirmReleaseSimCard(simCard));
|
||||
releaseButton.getElement().addEventListener("click", event -> {
|
||||
}).addEventData("event.stopPropagation()");
|
||||
|
||||
HorizontalLayout actionsLayout = new HorizontalLayout(badge, releaseButton);
|
||||
actionsLayout.setAlignItems(Alignment.CENTER);
|
||||
actionsLayout.setSpacing(true);
|
||||
actionsLayout.setPadding(false);
|
||||
row.add(actionsLayout);
|
||||
}
|
||||
return row;
|
||||
}));
|
||||
|
||||
assignButton = new Button("Weiter", new Icon(VaadinIcon.CHECK), event -> assignSimCard());
|
||||
assignButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
|
||||
@@ -135,6 +177,11 @@ public class SimCardConfigurationView extends VerticalLayout implements BeforeEn
|
||||
List<CourierInfo> couriers = simCardAssignmentService.fetchCouriers();
|
||||
List<SimCardInfo> simCards = simCardAssignmentService.fetchSimCards();
|
||||
|
||||
courierSidByUserId.clear();
|
||||
for (CourierInfo courier : couriers) {
|
||||
courierSidByUserId.putIfAbsent(courier.userId(), courier.courierSid());
|
||||
}
|
||||
|
||||
courierSelect.setItems(couriers);
|
||||
simCardSelect.setItems(simCards);
|
||||
courierSelect.clear();
|
||||
@@ -217,6 +264,8 @@ public class SimCardConfigurationView extends VerticalLayout implements BeforeEn
|
||||
}
|
||||
|
||||
try {
|
||||
logger.info("Sende SIM-Zuordnung: Kurier='{}', SIM-Karte='{}'", courier.displayLabel(),
|
||||
simCard.displayLabel());
|
||||
simCardAssignmentService.assignSimCard(courier, simCard);
|
||||
loginSessionService.markSimConfigurationCompleted(ui.getSession());
|
||||
statusText.setText("SIM-Karte wurde erfolgreich zugeordnet.");
|
||||
@@ -233,4 +282,45 @@ public class SimCardConfigurationView extends VerticalLayout implements BeforeEn
|
||||
statusText.setText(message);
|
||||
Notification.show(message, 5000, Notification.Position.MIDDLE);
|
||||
}
|
||||
|
||||
private void confirmReleaseSimCard(SimCardInfo simCard) {
|
||||
simCardSelect.getElement().executeJs("this.close()");
|
||||
|
||||
Dialog dialog = new Dialog();
|
||||
dialog.setHeaderTitle("Zuordnung aufheben");
|
||||
|
||||
Paragraph text = new Paragraph(
|
||||
"Möchten Sie die Zuordnung der SIM-Karte '" + simCard.displayLabel() + "' wirklich aufheben?");
|
||||
|
||||
Button confirmButton = new Button("Aufheben", event -> {
|
||||
dialog.close();
|
||||
releaseSimCard(simCard);
|
||||
});
|
||||
confirmButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_ERROR);
|
||||
|
||||
Button cancelButton = new Button("Abbrechen", event -> dialog.close());
|
||||
|
||||
HorizontalLayout buttons = new HorizontalLayout(cancelButton, confirmButton);
|
||||
buttons.setWidthFull();
|
||||
buttons.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
|
||||
|
||||
dialog.add(text, buttons);
|
||||
dialog.open();
|
||||
}
|
||||
|
||||
private void releaseSimCard(SimCardInfo simCard) {
|
||||
try {
|
||||
simCardAssignmentService.releaseSimCard(simCard);
|
||||
Notification.show("Zuordnung der SIM-Karte '" + simCard.displayLabel() + "' wurde aufgehoben.", 3000,
|
||||
Notification.Position.MIDDLE);
|
||||
loadOptions();
|
||||
} catch (Exception ex) {
|
||||
showError(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSimCardOccupied(SimCardInfo simCard) {
|
||||
Long userId = simCard.userId();
|
||||
return userId != null && userId != 0L;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.assecutor.emulatorstation.base.ui.view.security;
|
||||
|
||||
import com.vaadin.flow.spring.security.VaadinWebSecurity;
|
||||
import de.assecutor.emulatorstation.base.ui.view.LoginView;
|
||||
import de.assecutor.emulatorstation.base.ui.view.SimCardConfigurationView;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
@@ -24,7 +25,11 @@ public class SecurityConfig extends VaadinWebSecurity {
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
super.configure(http);
|
||||
|
||||
if (ssoConfiguration.isEnabled()) {
|
||||
setLoginView(http, LoginView.class);
|
||||
} else {
|
||||
setLoginView(http, SimCardConfigurationView.class);
|
||||
}
|
||||
|
||||
http.sessionManagement(session -> session
|
||||
// Wichtig: Session-Fixation so konfigurieren, dass Session-Attribute (z.B. "user") erhalten bleiben
|
||||
|
||||
Reference in New Issue
Block a user