added login logic excl refresh call
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package com.vaessl.app.connection;
|
||||
|
||||
import jakarta.persistence.DiscriminatorColumn;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Inheritance;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "connections")
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name = "service_type")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public abstract class ConnectionEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String appUrl;
|
||||
}
|
||||
@@ -6,6 +6,10 @@ import com.vaessl.app.dto.ConnectionResponse;
|
||||
public interface ConnectionProvider {
|
||||
|
||||
String getServiceType();
|
||||
|
||||
ConnectionResponse authenticate (ConnectionRequest connectionRequest);
|
||||
|
||||
ConnectionResponse authenticate(ConnectionRequest request);
|
||||
|
||||
ConnectionEntity connectionToEntity(ConnectionRequest request, ConnectionResponse response);
|
||||
|
||||
void updateToRepository(ConnectionEntity existing, ConnectionResponse response);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.vaessl.app.connection;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ConnectionRepository extends JpaRepository<ConnectionEntity, Long> {
|
||||
|
||||
ConnectionEntity findByAppUrl(String appUrl);
|
||||
}
|
||||
@@ -8,24 +8,40 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import com.vaessl.app.dto.ConnectionRequest;
|
||||
import com.vaessl.app.dto.ConnectionResponse;
|
||||
import com.vaessl.app.exception.ProviderNotFoundException;
|
||||
|
||||
@Service
|
||||
public class ConnectionService {
|
||||
|
||||
private final Map<String, ConnectionProvider> providerRegistry;
|
||||
|
||||
public ConnectionService(List<ConnectionProvider> providers) {
|
||||
private final ConnectionRepository cRepository;
|
||||
|
||||
public ConnectionService(List<ConnectionProvider> providers, ConnectionRepository cRepository) {
|
||||
this.providerRegistry = providers.stream()
|
||||
.collect(Collectors.toMap(ConnectionProvider::getServiceType, p -> p));
|
||||
this.cRepository = cRepository;
|
||||
}
|
||||
|
||||
public ConnectionResponse login(ConnectionRequest request) {
|
||||
ConnectionProvider provider = providerRegistry.get(request.serviceType().toUpperCase());
|
||||
|
||||
ConnectionProvider provider = providerRegistry.get(request.serviceType());
|
||||
|
||||
if (provider == null) {
|
||||
throw new IllegalArgumentException("Unknown provider: " + request.serviceType());
|
||||
throw new ProviderNotFoundException();
|
||||
}
|
||||
|
||||
return provider.authenticate(request);
|
||||
ConnectionResponse response = provider.authenticate(request);
|
||||
|
||||
ConnectionEntity existing = cRepository.findByAppUrl(request.appUrl());
|
||||
|
||||
if (existing != null) {
|
||||
provider.updateToRepository(existing, response);
|
||||
} else {
|
||||
ConnectionEntity newEntity = provider.connectionToEntity(request, response);
|
||||
cRepository.save(newEntity);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.vaessl.app.connection;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -8,15 +10,18 @@ import org.springframework.web.client.RestClient;
|
||||
import com.vaessl.app.dto.ConnectionRequest;
|
||||
import com.vaessl.app.dto.ConnectionResponse;
|
||||
|
||||
import static com.vaessl.app.connection.Endpoints.*;
|
||||
import static com.vaessl.app.connection.Endpoint.*;
|
||||
|
||||
@Component
|
||||
public class HomeBoxConnectionProvider implements ConnectionProvider {
|
||||
|
||||
private final RestClient.Builder restClientBuilder;
|
||||
|
||||
public HomeBoxConnectionProvider(RestClient.Builder restClientBuilder) {
|
||||
private final ConnectionRepository cRepository;
|
||||
|
||||
public HomeBoxConnectionProvider(RestClient.Builder restClientBuilder, ConnectionRepository cRepository) {
|
||||
this.restClientBuilder = restClientBuilder;
|
||||
this.cRepository = cRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -25,17 +30,50 @@ public class HomeBoxConnectionProvider implements ConnectionProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionResponse authenticate(ConnectionRequest connectionRequest) {
|
||||
Map<String, Object> homeboxPayload = Map.of("username", connectionRequest.credentials().get("username"),
|
||||
"password", connectionRequest.credentials().get("password"), "stayLoggedIn",
|
||||
connectionRequest.stayLoggedIn());
|
||||
public ConnectionResponse authenticate(ConnectionRequest request) {
|
||||
Map<String, Object> homeboxPayload = Map.of("username", request.credentials().get("username"),
|
||||
"password", request.credentials().get("password"), "stayLoggedIn",
|
||||
request.stayLoggedIn());
|
||||
|
||||
return restClientBuilder.baseUrl(connectionRequest.appUrl())
|
||||
HomeboxLoginResponse hbResponse = restClientBuilder.baseUrl(request.appUrl())
|
||||
.build()
|
||||
.post()
|
||||
.uri(HOMEBOX_LOGIN.getEndpoint())
|
||||
.uri(HOMEBOX_LOGIN.getValue())
|
||||
.body(homeboxPayload)
|
||||
.retrieve()
|
||||
.body(ConnectionResponse.class);
|
||||
.body(HomeboxLoginResponse.class);
|
||||
|
||||
if (hbResponse == null) {
|
||||
throw new IllegalStateException("Remote API returned an empty body for " + request.appUrl());
|
||||
}
|
||||
|
||||
Map<String, Object> attachmentToken = new HashMap<>();
|
||||
|
||||
attachmentToken.put("attachmentToken", hbResponse.attachmentToken());
|
||||
|
||||
return new ConnectionResponse(hbResponse.token(), hbResponse.expiresAt(), attachmentToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionEntity connectionToEntity(ConnectionRequest request, ConnectionResponse response) {
|
||||
return HomeboxEntity.from(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateToRepository(ConnectionEntity existing, ConnectionResponse response) {
|
||||
|
||||
|
||||
if (existing instanceof HomeboxEntity hbE) {
|
||||
|
||||
hbE.setToken(response.token());
|
||||
hbE.setExpiresAt(response.expiresAt());
|
||||
hbE.setAttachmentToken(response.getExtraVar("attachmentToken"));
|
||||
|
||||
cRepository.save(hbE);
|
||||
}
|
||||
}
|
||||
|
||||
private record HomeboxLoginResponse(String token, String attachmentToken, Instant expiresAt) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.vaessl.app.connection;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import com.vaessl.app.dto.ConnectionRequest;
|
||||
import com.vaessl.app.dto.ConnectionResponse;
|
||||
|
||||
import jakarta.persistence.DiscriminatorValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("HOMEBOX")
|
||||
@Getter
|
||||
@Setter
|
||||
public class HomeboxEntity extends ConnectionEntity {
|
||||
|
||||
private String token;
|
||||
private String attachmentToken;
|
||||
private Instant expiresAt;
|
||||
|
||||
public static HomeboxEntity from(ConnectionRequest request, ConnectionResponse response) {
|
||||
|
||||
HomeboxEntity he = new HomeboxEntity();
|
||||
|
||||
he.setAppUrl(request.appUrl());
|
||||
he.setToken(response.token());
|
||||
he.setAttachmentToken(response.getExtraVar("attachmentToken"));
|
||||
he.setExpiresAt(response.expiresAt());
|
||||
|
||||
return he;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.vaessl.app.connection;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum ServiceType {
|
||||
HOMEBOX("HOMEBOX");
|
||||
|
||||
private final String value;
|
||||
|
||||
private ServiceType(String value){
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package com.vaessl.app.dto;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
@@ -9,5 +11,11 @@ public record ConnectionRequest(
|
||||
@NotBlank(message = "App URL is mandatory") String appUrl,
|
||||
@NotBlank(message = "Service type is mandatory") String serviceType,
|
||||
@NotEmpty(message = "Credentials are mandatory") Map<String, String> credentials,
|
||||
boolean stayLoggedIn) {
|
||||
@JsonProperty(defaultValue = "false") Boolean stayLoggedIn) {
|
||||
|
||||
public ConnectionRequest {
|
||||
if (stayLoggedIn == null) {
|
||||
stayLoggedIn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
package com.vaessl.app.dto;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
public record ConnectionResponse(String token, String attachmentToken, Instant expiresAt) {
|
||||
public record ConnectionResponse(String token, Instant expiresAt, Map<String, Object> extraResponseData) {
|
||||
|
||||
public String getExtraVar(String key) {
|
||||
if(extraResponseData == null) {
|
||||
return null;
|
||||
} else {
|
||||
Object value = extraResponseData.get(key);
|
||||
|
||||
return value != null ? String.valueOf(value) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.HttpServerErrorException;
|
||||
import org.springframework.web.client.ResourceAccessException;
|
||||
|
||||
import static com.vaessl.app.exception.ErrorMessages.*;
|
||||
import static com.vaessl.app.exception.ErrorMessage.*;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
@@ -40,4 +40,9 @@ public class GlobalExceptionHandler {
|
||||
.forStatusAndDetail(e.getStatusCode(),
|
||||
SERVER_ERROR_GENERAL.getMessage() + e.getStatusText());
|
||||
}
|
||||
|
||||
@ExceptionHandler(ProviderNotFoundException.class)
|
||||
public ProblemDetail handleWrongServiceType(ProviderNotFoundException e) {
|
||||
return ProblemDetail.forStatusAndDetail(WRONG_SERVICE_TYPE.getStatus(), WRONG_SERVICE_TYPE.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.vaessl.app.exception;
|
||||
|
||||
public class ProviderNotFoundException extends RuntimeException {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user