Erweiterungen
This commit is contained in:
@@ -1,8 +1,14 @@
|
||||
package de.assecutor.votianlt.controller;
|
||||
|
||||
import de.assecutor.votianlt.dto.AppLoginRequest;
|
||||
import de.assecutor.votianlt.dto.AppLoginResponse;
|
||||
import de.assecutor.votianlt.model.AppUser;
|
||||
import de.assecutor.votianlt.pages.service.AppUserService;
|
||||
import de.assecutor.votianlt.repository.AppUserRepository;
|
||||
import org.springframework.messaging.handler.annotation.MessageMapping;
|
||||
import org.springframework.messaging.handler.annotation.SendTo;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.messaging.simp.annotation.SendToUser;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -20,6 +26,12 @@ public class MessageController {
|
||||
@Autowired
|
||||
private SimpMessagingTemplate messagingTemplate;
|
||||
|
||||
@Autowired
|
||||
private AppUserRepository appUserRepository;
|
||||
|
||||
@Autowired
|
||||
private AppUserService appUserService;
|
||||
|
||||
/**
|
||||
* Handles messages sent to /app/message and broadcasts them to all subscribers of /topic/messages
|
||||
*/
|
||||
@@ -82,4 +94,30 @@ public class MessageController {
|
||||
|
||||
messagingTemplate.convertAndSend("/topic/broadcasts", broadcast);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication endpoint for mobile app users via STOMP.
|
||||
* Client sends to /app/auth/login with payload { email, password }.
|
||||
* The response is sent back to the requesting user on /user/queue/auth
|
||||
*/
|
||||
@MessageMapping("/auth/login")
|
||||
@SendToUser("/queue/auth")
|
||||
public AppLoginResponse handleAppLogin(AppLoginRequest request) {
|
||||
if (request == null || request.getEmail() == null || request.getPassword() == null
|
||||
|| request.getEmail().isBlank() || request.getPassword().isBlank()) {
|
||||
return new AppLoginResponse(false, "E-Mail und Passwort sind erforderlich", null);
|
||||
}
|
||||
|
||||
AppUser user = appUserRepository.findByEmail(request.getEmail());
|
||||
if (user == null) {
|
||||
return new AppLoginResponse(false, "Benutzer nicht gefunden", null);
|
||||
}
|
||||
|
||||
boolean ok = appUserService.verifyPassword(request.getPassword(), user.getPassword());
|
||||
if (!ok) {
|
||||
return new AppLoginResponse(false, "Ungültige Anmeldedaten", null);
|
||||
}
|
||||
|
||||
return new AppLoginResponse(true, "Anmeldung erfolgreich", user.getId() != null ? user.getId().toHexString() : null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package de.assecutor.votianlt.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AppLoginRequest {
|
||||
private String email;
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package de.assecutor.votianlt.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class AppLoginResponse {
|
||||
private boolean success;
|
||||
private String message;
|
||||
private String appUserId; // MongoDB ObjectId as hex string
|
||||
}
|
||||
@@ -13,8 +13,9 @@ public interface AppUserRepository extends MongoRepository<AppUser, ObjectId> {
|
||||
// Find all AppUsers created by a specific user
|
||||
List<AppUser> findByErstelltVon(ObjectId erstelltVon);
|
||||
|
||||
// Find AppUser by email for login
|
||||
AppUser findByEmail(String email);
|
||||
|
||||
// Custom query methods can be added here if needed
|
||||
// For example:
|
||||
// List<AppUser> findByEmail(String email);
|
||||
// List<AppUser> findByBezeichnung(String bezeichnung);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package de.assecutor.votianlt.zeroconf;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* Publishes the STOMP WebSocket endpoint via Zeroconf (mDNS/Bonjour) using reflection.
|
||||
* If JmDNS is present on the classpath, it will register the service _stomp._tcp.local.
|
||||
*/
|
||||
@Component
|
||||
public class ZeroconfPublisher {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ZeroconfPublisher.class);
|
||||
|
||||
@Value("${server.port:8080}")
|
||||
private int serverPort;
|
||||
|
||||
// Expose stomp endpoints paths via TXT records
|
||||
@Value("${app.stomp.wsPath:/ws}")
|
||||
private String wsPath;
|
||||
|
||||
@Value("${app.stomp.websocketPath:/websocket}")
|
||||
private String websocketPath;
|
||||
|
||||
@Value("${app.zeroconf.enabled:true}")
|
||||
private boolean enabled;
|
||||
|
||||
@Value("${app.zeroconf.serviceName:votianlt-stomp}")
|
||||
private String serviceName;
|
||||
|
||||
// Controls whether to log a notice if JmDNS is not available
|
||||
@Value("${app.zeroconf.warnWhenMissing:false}")
|
||||
private boolean warnWhenMissing;
|
||||
|
||||
private Object jmdns; // javax.jmdns.JmDNS instance if available
|
||||
|
||||
@EventListener(org.springframework.boot.context.event.ApplicationReadyEvent.class)
|
||||
public void onAppReady() {
|
||||
if (!enabled) return;
|
||||
try {
|
||||
Class<?> jmDNSClass = Class.forName("javax.jmdns.JmDNS");
|
||||
Class<?> serviceInfoClass = Class.forName("javax.jmdns.ServiceInfo");
|
||||
|
||||
InetAddress addr = InetAddress.getLocalHost();
|
||||
Method createMethod = jmDNSClass.getMethod("create", InetAddress.class);
|
||||
jmdns = createMethod.invoke(null, addr);
|
||||
|
||||
String type = "_stomp._tcp.local.";
|
||||
String text = "path=" + wsPath + ",websocket=" + websocketPath + ",protocol=stomp";
|
||||
|
||||
Method createServiceInfo = serviceInfoClass.getMethod("create", String.class, String.class, int.class, String.class);
|
||||
Object serviceInfo = createServiceInfo.invoke(null, type, serviceName, serverPort, text);
|
||||
|
||||
Method registerService = jmDNSClass.getMethod("registerService", serviceInfoClass);
|
||||
registerService.invoke(jmdns, serviceInfo);
|
||||
|
||||
logger.info("STOMP-Service veröffentlicht: {} name={} port={}", type, serviceName, serverPort);
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (warnWhenMissing) {
|
||||
logger.warn("Hinweis: JmDNS ist nicht vorhanden – Zeroconf ist deaktiviert.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Registrierung fehlgeschlagen: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener(ContextClosedEvent.class)
|
||||
public void onShutdown() {
|
||||
if (jmdns != null) {
|
||||
try {
|
||||
Method unregisterAll = jmdns.getClass().getMethod("unregisterAllServices");
|
||||
unregisterAll.invoke(jmdns);
|
||||
Method close = jmdns.getClass().getMethod("close");
|
||||
close.invoke(jmdns);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user