use of org.ehrbase.api.exception.PreconditionFailedException in project ehrbase by ehrbase.
the class OpenehrEhrStatusController method updateEhrStatus.
/**
* {@inheritDoc}
*/
@Override
@PutMapping
@PreAuthorize("checkAbacPre(@openehrEhrStatusController.EHR_STATUS, @ehrService.getSubjectExtRef(#ehrIdString))")
public ResponseEntity<EhrStatusResponseData> updateEhrStatus(@PathVariable("ehr_id") UUID ehrId, @RequestHeader(name = IF_MATCH) String versionUid, @RequestHeader(name = PREFER, required = false) String prefer, @RequestHeader(name = HttpHeaders.ACCEPT, required = false) String accept, @RequestHeader(name = HttpHeaders.CONTENT_TYPE, required = false) String contentType, @RequestBody EhrStatus ehrStatus) {
assertEhrExists(ehrId);
// If-Match header check
String latestVersionUid = ehrService.getLatestVersionUidOfStatus(ehrId);
if (!latestVersionUid.equals(versionUid)) {
throw new PreconditionFailedException("Given If-Match header does not match latest existing version");
}
// update EHR_STATUS and check for success
Optional<EhrStatus> updateStatus = ehrService.updateStatus(ehrId, ehrStatus, null);
EhrStatus status = updateStatus.orElseThrow(() -> new InvalidApiParameterException("Could not update EHR_STATUS"));
// update and prepare current version number
String newLatestVersionUid = ehrService.getLatestVersionUidOfStatus(ehrId);
String[] split = latestVersionUid.split("::");
if (latestVersionUid.equals(newLatestVersionUid) || split.length != 3) {
throw new InvalidApiParameterException("Update of EHR_STATUS failed");
}
int version = Integer.parseInt(split[split.length - 1]) + 1;
List<String> headerList = Arrays.asList(CONTENT_TYPE, LOCATION, ETAG, // whatever is required by REST spec
LAST_MODIFIED);
// variable to overload with more specific object if requested
Optional<InternalResponse<EhrStatusResponseData>> respData;
UUID statusUid = UUID.fromString(status.getUid().getValue().split("::")[0]);
respData = buildEhrStatusResponseData(EhrStatusResponseData::new, ehrId, statusUid, version, accept, headerList);
return respData.map(i -> ResponseEntity.ok().headers(i.getHeaders()).body(i.getResponseData())).orElse(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
}
use of org.ehrbase.api.exception.PreconditionFailedException in project ehrbase by ehrbase.
the class OpenehrCompositionController method updateComposition.
@PutMapping("/{ehr_id}/composition/{versioned_object_uid}")
// checkAbacPre /-Post attributes (type, subject, payload, content type)
@PreAuthorize("checkAbacPre(@openehrCompositionController.COMPOSITION, " + "@ehrService.getSubjectExtRef(#ehrIdString), #composition, #contentType)")
@Override
public ResponseEntity updateComposition(String openehrVersion, @RequestHeader(value = "openEHR-AUDIT_DETAILS", required = false) String openehrAuditDetails, @RequestHeader(value = CONTENT_TYPE, required = false) String contentType, @RequestHeader(value = ACCEPT, required = false) String accept, @RequestHeader(value = PREFER, required = false) String prefer, @RequestHeader(value = IF_MATCH) String ifMatch, @PathVariable(value = "ehr_id") String ehrIdString, @PathVariable(value = "versioned_object_uid") String versionedObjectUidString, @RequestBody String composition, HttpServletRequest request) {
UUID ehrId = getEhrUuid(ehrIdString);
UUID versionedObjectUid = getCompositionVersionedObjectUidString(versionedObjectUidString);
CompositionFormat compositionFormat = extractCompositionFormat(contentType);
// check if composition ID path variable is valid
compositionService.exists(versionedObjectUid);
// If the If-Match is not the latest latest existing version, throw error
if (!((versionedObjectUid + "::" + compositionService.getServerConfig().getNodename() + "::" + compositionService.getLastVersionNumber(extractVersionedObjectUidFromVersionUid(versionedObjectUid.toString()))).equals(ifMatch))) {
throw new PreconditionFailedException("If-Match header does not match latest existing version");
}
// If body already contains a composition uid it must match the {versioned_object_uid} in request url
Optional<String> inputUuid = Optional.ofNullable(compositionService.getUidFromInputComposition(composition, compositionFormat));
inputUuid.ifPresent(id -> {
// TODO it is further unclear what exactly the REST spec's "match" means, see: https://github.com/openEHR/specifications-ITS-REST/issues/83
if (!versionedObjectUid.equals(extractVersionedObjectUidFromVersionUid(id))) {
throw new PreconditionFailedException("UUID from input must match given versioned_object_uid in request URL");
}
});
// variable to overload with more specific object if requested
Optional<InternalResponse<CompositionResponseData>> respData = Optional.empty();
try {
Composition compoObj = compositionService.buildComposition(composition, compositionFormat, null);
// TODO should have EHR as parameter and check for existence as precondition - see EHR-245 (no direct EHR access in this controller)
// ifMatch header has to be tested for correctness already above
Optional<CompositionDto> dtoOptional = compositionService.update(ehrId, new ObjectVersionId(ifMatch), compoObj);
var compositionVersionUid = dtoOptional.orElseThrow(() -> new InternalServerException("Failed to create composition")).getComposition().getUid().toString();
var uri = URI.create(this.encodePath(getBaseEnvLinkURL() + "/rest/openehr/v1/ehr/" + ehrId.toString() + "/composition/" + compositionVersionUid));
List<String> headerList = Arrays.asList(LOCATION, ETAG, // whatever is required by REST spec - CONTENT_TYPE only needed for 200, so handled separately
LAST_MODIFIED);
UUID compositionId = extractVersionedObjectUidFromVersionUid(compositionVersionUid);
if (RETURN_REPRESENTATION.equals(prefer)) {
// both options extract needed info from versionUid
respData = buildCompositionResponseData(compositionId, extractVersionFromVersionUid(compositionVersionUid), accept, uri, headerList, () -> new CompositionResponseData(null, null));
} else {
// "minimal" is default fallback
respData = buildCompositionResponseData(compositionId, extractVersionFromVersionUid(compositionVersionUid), accept, uri, headerList, () -> null);
}
// Enriches request attributes with current compositionId for later audit processing
request.setAttribute(OpenEhrAuditInterceptor.EHR_ID_ATTRIBUTE, Collections.singleton(ehrId));
request.setAttribute(CompositionAuditInterceptor.COMPOSITION_ID_ATTRIBUTE, compositionId);
} catch (ObjectNotFoundException e) {
// composition not found
return ResponseEntity.notFound().build();
}
// returns 200 with body + headers, 204 only with headers or 500 error depending on what processing above yields
return respData.map(i -> Optional.ofNullable(i.getResponseData()).map(StructuredString::getValue).map(j -> ResponseEntity.ok().headers(i.getHeaders()).body(j)).orElse(ResponseEntity.noContent().headers(i.getHeaders()).build())).orElse(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build());
}
use of org.ehrbase.api.exception.PreconditionFailedException in project ehrbase by ehrbase.
the class OpenehrDirectoryController method checkDirectoryVersionConflicts.
private void checkDirectoryVersionConflicts(ObjectVersionId requestedFolderId, UUID ehrId) {
UUID directoryUuid = ehrService.getDirectoryId(ehrId);
int latestVersion = folderService.getLastVersionNumber(new ObjectVersionId(directoryUuid.toString()));
// TODO: Change column 'directory' in EHR to String with ObjectVersionId
String directoryId = String.format("%s::%s::%d", directoryUuid, ehrService.getServerConfig().getNodename(), latestVersion);
if (requestedFolderId != null && !requestedFolderId.toString().equals(directoryId)) {
throw new PreconditionFailedException("If-Match version_uid does not match latest version.", directoryId, encodePath(getBaseEnvLinkURL() + "/rest/openehr/v1/ehr/" + ehrId.toString() + "/directory/" + directoryId));
}
}
Aggregations