package at.gv.egiz.moazs.backend; import at.gv.egiz.moazs.MoaZSException; import at.gv.egiz.moazs.repository.DeliveryRepository; import at.gv.egiz.moazs.scheme.MsgResponse; import at.gv.egiz.moazs.service.MsgService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.function.Consumer; import static at.gv.egiz.moazs.MoaZSException.*; import static java.lang.String.format; import static java.util.concurrent.CompletableFuture.supplyAsync; @Component public class MsgResponseBackend implements Consumer { private static final Logger log = LoggerFactory.getLogger(MsgService.class); public static final String MOASP_SIGNATURE_INVALID_ERROR_MSG = "Signature of Msg Response " + "with AppDeliveryID=%s is not valid."; public static final String BINARY_RESPONSE_MISSING_ERROR_MSG = "Binary Response is not in repository."; public static final String RESPONSE_MISSING_ERROR_MSG = "Response with ResponseID=%s is not in repository."; public static final String REQUEST_MISSING_ERROR_MSG = "Request with AppDeliveryID=%s is not in repository."; private final DeliveryRepository repository; private final Consumer signatureVerifier; private final MsgResponseSinkHub hub; @Autowired public MsgResponseBackend(DeliveryRepository repository, Consumer signatureVerifier, MsgResponseSinkHub hub) { this.repository = repository; this.signatureVerifier = signatureVerifier; this.hub = hub; } /** * Performs all {@code MsgResponse}'s Back-End Tasks, such as verifying * its signature and archiving the response. * * Note: When the signature verification fails, this method will not archive * the original response (the one that was received from msg) to the sink, * but an error message. * * @param responseID refers to MsgResponse Object. */ @Override public void accept(String responseID) { log.info("Backend accepts MsgResponse with responseID={}.", responseID); supplyAsync(() -> verifySignature(responseID)) .thenAcceptAsync(msgResponse -> applySinks(msgResponse)) .exceptionally(ex -> { log.error(ex.getMessage(), ex); return null; }); } private MsgResponse verifySignature(String responseID) { var response = repository.retrieveResponse(responseID).orElseThrow( ()-> moaZSException(format(RESPONSE_MISSING_ERROR_MSG, responseID))); try { var binaryResponse = repository.retrieveBinaryResponse(responseID).orElseThrow( () -> moaZSException(BINARY_RESPONSE_MISSING_ERROR_MSG, MoaZSException.ERROR_MZS_BINARY_RESPONSE_MISSING)); log.info("Verify Signature of msg:{} with AppDeliveryID={}.", response.getRootElementLocalPart(), response.getAppDeliveryID()); signatureVerifier.accept(binaryResponse); return response; } catch (MoaZSException ex) { log.error(ex.getMessage(), ex); var text = format(MOASP_SIGNATURE_INVALID_ERROR_MSG, response.getAppDeliveryID()); var code = ERROR_MOASP_SIGNATURE_INVALID; return response.generateError(text, code); } } private void applySinks(MsgResponse msgResponse) { var appDeliveryID = msgResponse.getAppDeliveryID(); var request = repository.retrieveDeliveryRequest(appDeliveryID).orElseThrow( ()-> moaZSException(format(REQUEST_MISSING_ERROR_MSG, appDeliveryID))); var sinkParams = request.getConfig().getMsgResponseSinks(); hub.applySinks(msgResponse, sinkParams); } }