add session-based connection management and React dashboard

Backend: adds JDBC session support, login/status/logout endpoints, and
new DTOs (AuthResponse, ConnectionStatusResponse, LoginResult). Frontend
replaces the Vite boilerplate with a Dashboard, ServiceCard, and
ConnectModal backed by a typed API client.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 03:30:36 +02:00
parent 0127706262
commit 43bbcece7a
30 changed files with 1307 additions and 350 deletions
@@ -1,5 +1,6 @@
package com.vaessl.app.connection;
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -8,6 +9,8 @@ import org.springframework.stereotype.Service;
import com.vaessl.app.dto.ConnectionRequest;
import com.vaessl.app.dto.ConnectionResponse;
import com.vaessl.app.dto.ConnectionStatusResponse;
import com.vaessl.app.dto.LoginResult;
import com.vaessl.app.exception.WrongServiceTypeException;
@Service
@@ -23,7 +26,7 @@ public class ConnectionService {
this.cRepository = cRepository;
}
public ConnectionResponse login(ConnectionRequest request) {
public LoginResult login(ConnectionRequest request) {
ConnectionProvider provider = providerRegistry.get(request.serviceType());
@@ -37,13 +40,27 @@ public class ConnectionService {
ConnectionEntity existing = provider.findUniqueConnectionEntry(request);
ConnectionEntity saved;
if (existing != null) {
provider.updateToRepository(existing, response);
saved = existing;
} else {
ConnectionEntity newEntity = provider.connectionToEntity(request, response);
cRepository.save(newEntity);
saved = cRepository.save(newEntity);
}
return response;
return new LoginResult(saved.getId(), response.expiresAt());
}
}
public ConnectionStatusResponse getConnectionStatus(String serviceType, Long connectionId) {
ConnectionEntity entity = cRepository.findById(connectionId).orElse(null);
if (entity == null) return null;
ConnectionProvider provider = providerRegistry.get(serviceType);
Instant expiresAt = (provider != null) ? provider.getTokenExpiry(entity) : null;
boolean connected = expiresAt == null || expiresAt.isAfter(Instant.now());
return new ConnectionStatusResponse(serviceType, entity.getAppUrl(),
entity.getUsername(), expiresAt, connected);
}
}