UsersController.java
package se.jobtechdev.personaldatagateway.api.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.request.NativeWebRequest;
import se.jobtechdev.personaldatagateway.api.generated.api.UsersApi;
import se.jobtechdev.personaldatagateway.api.generated.entities.ClientEntity;
import se.jobtechdev.personaldatagateway.api.generated.entities.SharingEntity;
import se.jobtechdev.personaldatagateway.api.generated.model.Sharing;
import se.jobtechdev.personaldatagateway.api.service.ClientService;
import se.jobtechdev.personaldatagateway.api.service.DatasourceService;
import se.jobtechdev.personaldatagateway.api.service.PersonService;
import se.jobtechdev.personaldatagateway.api.service.SharingService;
import se.jobtechdev.personaldatagateway.api.util.LinkHeaderUtil;
import se.jobtechdev.personaldatagateway.api.util.OffsetBasedPageRequest;
import se.jobtechdev.personaldatagateway.api.util.ResponseFactory;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import static se.jobtechdev.personaldatagateway.api.util.ControllerUtil.earlyExit;
import static se.jobtechdev.personaldatagateway.api.util.ControllerUtil.throwApiExceptionOnAbsentValue;
@Controller
public class UsersController implements UsersApi {
private final String baseUrl;
private final NativeWebRequest request;
private final SharingService sharingService;
private final PersonService personService;
private final DatasourceService datasourceService;
private final ClientService clientService;
@Autowired
public UsersController(
@Value("${pdg-api.base-url}") String baseUrl,
NativeWebRequest request,
SharingService sharingService,
PersonService personService,
DatasourceService datasourceService,
ClientService clientService) {
this.baseUrl = baseUrl;
this.request = request;
this.sharingService = sharingService;
this.personService = personService;
this.datasourceService = datasourceService;
this.clientService = clientService;
}
@Override
public ResponseEntity<Sharing> postUserSharing(String userId, Sharing sharing) {
final var publicSharing = sharing.getPublic();
final var clientId = sharing.getClientId();
final var expires = sharing.getExpires();
final var datasourceId = sharing.getDatasourceId();
final var user =
personService.getPersonById(userId).orElseGet(() -> personService.createPerson(userId));
final var datasource =
throwApiExceptionOnAbsentValue(
datasourceService.getDatasourceById(datasourceId),
HttpStatus.BAD_REQUEST,
"Could not find datasource by datasourceId: " + datasourceId);
final SharingEntity sharingEntity;
ClientEntity client = null;
if (Boolean.TRUE.equals(publicSharing)) {
earlyExit(
clientId,
Objects::nonNull,
HttpStatus.UNPROCESSABLE_ENTITY,
"The \"public\" and \"clientId\" properties are mutually exclusive");
} else {
earlyExit(
clientId,
Objects::isNull,
HttpStatus.UNPROCESSABLE_ENTITY,
"One of \"public\" or \"clientId\" properties must be defined");
client =
throwApiExceptionOnAbsentValue(
clientService.getClientById(clientId),
HttpStatus.BAD_REQUEST,
"Could not find client by clientId: " + clientId);
}
final var activeSharings = sharingService.getActiveSharings(user, datasource, client);
final HttpStatus httpStatus;
if (!activeSharings.isEmpty()) {
sharingEntity = activeSharings.getFirst();
httpStatus = HttpStatus.OK;
} else {
sharingEntity = sharingService.createSharing(user, datasource, publicSharing, expires, client);
httpStatus = HttpStatus.CREATED;
}
final var response = ResponseFactory.createSharing(sharingEntity);
final var headers =
LinkHeaderUtil.createHeadersWithLocation(
response.getSharingId().toString(), new Class<?>[]{String.class, Sharing.class}, userId, response);
return ResponseEntity.status(httpStatus)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
public ResponseEntity<Sharing> getUserSharing(String userId, UUID sharingId) {
final var sharing =
throwApiExceptionOnAbsentValue(
sharingService.getSharingById(sharingId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle GET user sharing request - Could not find sharing with id:"
+ " %s",
sharingId));
final var response = ResponseFactory.createSharing(sharing);
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{String.class, UUID.class}, userId, sharingId);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
public ResponseEntity<List<Sharing>> getUserSharings(
String userId, Integer offset, Integer limit) {
throwApiExceptionOnAbsentValue(
personService.getPersonById(userId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to handle GET user sharings request - Could not find user with id: %s",
userId));
final var pageable = OffsetBasedPageRequest.of(offset, limit);
final var sharings = sharingService.getSharingsByUserId(userId, pageable);
final var response =
sharings.stream()
.map(ResponseFactory::createSharing)
.toList();
final var headers =
LinkHeaderUtil.createHeadersWithPagination(
sharings, new Class<?>[]{String.class, Integer.class, Integer.class}, userId, (int) pageable.getOffset(), pageable.getPageSize());
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
@Override
public ResponseEntity<Sharing> postUserSharingRevoke(String userId, UUID sharingId) {
final var sharing =
throwApiExceptionOnAbsentValue(
sharingService.getSharingById(sharingId),
HttpStatus.NOT_FOUND,
String.format(
"Failed to revoke sharing - Could not find sharing with id:"
+ " %s",
sharingId));
final var revokedSharing = sharingService.revoke(sharing);
final var response = ResponseFactory.createSharing(revokedSharing);
final var headers = LinkHeaderUtil.createHeaders(new Class<?>[]{String.class, UUID.class}, userId, sharingId);
return ResponseEntity.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.headers(headers)
.body(response);
}
}