developers-api/src/main/java/eu/dnetlib/developers/services/APIService.java

188 lines
8.9 KiB
Java

package eu.dnetlib.developers.services;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import eu.dnetlib.developers.configuration.Properties;
import eu.dnetlib.developers.dto.*;
import eu.dnetlib.developers.entities.RegisteredService;
import eu.dnetlib.developers.exceptions.EntityMissingException;
import eu.dnetlib.developers.exceptions.EntityNotFoundException;
import eu.dnetlib.developers.exceptions.ForbiddenException;
import eu.dnetlib.developers.repositories.RegisteredServiceDAO;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service()
public class APIService {
private RegisteredServiceDAO dao;
private RestTemplate template;
private String issuer;
@Autowired
public APIService(RegisteredServiceDAO dao, RestTemplate template, Properties properties) {
this.dao = dao;
this.template = template;
this.issuer = properties.getIssuer();
}
public List<API> getAll() {
return this.dao.findAll().stream().map(service -> {
API details = new API();
details.setService(service);
details.setDetails(this.readService(service.getClientId(), service.getRegistrationAccessToken()));
return details;
}).collect(Collectors.toList());
}
public List<API> getMyServices() {
OIDCAuthenticationToken authentication = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
return this.dao.findAllByOwnerOrderByCreationDateAsc(authentication.getSub()).stream().map(service -> {
API details = new API();
details.setService(service);
details.setDetails(this.readService(service.getClientId(), service.getRegistrationAccessToken()));
return details;
}).collect(Collectors.toList());
}
public List<API> migrateAccessToken(List<RegisteredAT> registeredAT) {
List<API> apis = new ArrayList<>();
registeredAT.forEach( element -> {
RegisteredService service = this.dao.findByClientId(element.getClientId()).orElse(null);
if(service != null) {
service.setRegistrationAccessToken(element.getRegistrationAccessToken());
API api = new API();
api.setService(this.dao.save(service));
api.setDetails(this.readService(service.getClientId(), service.getRegistrationAccessToken()));
apis.add(api);
}
});
return apis;
}
public API save(ServiceForm form, Long id) {
ServiceRequest request;
API api = new API();
OIDCAuthenticationToken authentication = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if(id != null) {
RegisteredService service = this.dao.findById(id).orElse(null);
if(service == null) {
throw new EntityNotFoundException("Service with id " + id + " does not exist.");
}
api.setService(service);
api.setDetails(readService(service.getClientId(), service.getRegistrationAccessToken()));
} else {
api.setService(new RegisteredService(authentication.getSub(), form.getName(), form.getUrl(), form.getKeyType()));
}
String keyType = form.getKeyType();
if(keyType != null && keyType.equals("uri")) {
if(form.getUri() == null) {
throw new EntityMissingException("Uri is required in this type of key");
}
request = ServiceRequest.createServiceRequest(api.getService().getClientId(), form.getName(), form.getLogoURL(), authentication.getUserInfo().getEmail(), form.getUri());
} else if(keyType != null && keyType.equals("value")) {
Gson gson = new GsonBuilder().registerTypeAdapter(Jwks.class, new JwksDeserializer()).create();
String jwksSet = String.format("{\"keys\":[%s]}", form.getValue());
form.setJwks(gson.fromJson(jwksSet, Jwks.class));
if(!form.getJwks().isValid()) {
throw new EntityMissingException("Jwks value is not valid");
}
request = ServiceRequest.createServiceRequest(api.getService().getClientId(), form.getName(), form.getLogoURL(), authentication.getUserInfo().getEmail(), form.getJwks());
} else {
request = ServiceRequest.createServiceRequest(api.getService().getClientId(), form.getName(), form.getLogoURL(), authentication.getUserInfo().getEmail());
}
ServiceResponse response;
if(api.getService().getClientId() != null) {
response = this.updateService(api.getService().getClientId(), request, api.getService().getRegistrationAccessToken());
} else {
if(this.dao.findAllByOwnerOrderByCreationDateAsc(authentication.getSub()).size() < 5) {
response = this.createService(request);
} else {
throw new ForbiddenException("You are not allowed to own more than 5 services.");
}
}
api.getService().setKeyType(form.getKeyType());
api.getService().setUrl(form.getUrl());
api.getService().setName(request.getClientName());
api.getService().setClientId(response.getClientId());
api.getService().setRegistrationAccessToken(response.getRegistrationAccessToken());
api.setService(this.dao.save(api.getService()));
api.setDetails(response);
return api;
}
public API save(ServiceForm form) {
return this.save(form, null);
}
public void delete(Long id) {
RegisteredService service = this.dao.findById(id).orElse(null);
if(service == null) {
throw new EntityNotFoundException("Service with id " + id + " does not exist.");
} else {
this.deleteService(service.getClientId(), service.getRegistrationAccessToken());
this.dao.delete(id);
}
}
private ServiceResponse createService(ServiceRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<>(request.toJson(), headers);
try {
ResponseEntity<String> response = template.exchange(this.issuer, HttpMethod.POST, requestEntity, String.class);
return ServiceResponse.fromString(response.getBody());
} catch (Exception e) {
e.printStackTrace();
throw new EntityMissingException("Register of this service couldn't be completed. Check again your parameters");
}
}
private ServiceResponse updateService(String clientId, ServiceRequest request, String token) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + token);
HttpEntity<String> requestEntity = new HttpEntity<>(request.toJson(), headers);
try {
ResponseEntity<String> response = template.exchange(this.issuer + "/" + clientId, HttpMethod.PUT, requestEntity, String.class);
return ServiceResponse.fromString(response.getBody());
} catch (Exception e) {
e.printStackTrace();
throw new EntityMissingException("Update of service with client id: " + clientId + " couldn't be completed. Check again your parameters");
}
}
private ServiceResponse readService(String clientId, String token) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + token);
HttpEntity<String> requestEntity = new HttpEntity<>(headers);
try {
ResponseEntity<String> response = template.exchange(this.issuer + "/" + clientId, HttpMethod.GET, requestEntity, String.class);
return ServiceResponse.fromString(response.getBody());
} catch (Exception e) {
return null;
}
}
private void deleteService(String clientId, String token) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set(HttpHeaders.AUTHORIZATION, "Bearer " + token);
HttpEntity<ServiceRequest> requestEntity = new HttpEntity<>(headers);
try {
template.exchange(this.issuer + "/" + clientId, HttpMethod.DELETE, requestEntity, String.class);
} catch (Exception e) {
throw new EntityMissingException("Delete of service with client id: " + clientId + " couldn't be completed. Check again your parameters");
}
}
}