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 at.gv.zustellung.app2mzs.xsd.MsgResponseSinksType; 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."; private final DeliveryRepository repository; private final Consumer signatureVerifier; private final SaveResponseToFileSink saveResponseSink; private final LogResponseSink logResponseSink; private final ForwardResponseToServiceSink forwardResponseSink; @Autowired public MsgResponseBackend(DeliveryRepository repository, Consumer signatureVerifier, SaveResponseToFileSink saveResponseToFileSink, LogResponseSink logResponseSink, ForwardResponseToServiceSink forwardResponseSink) { this.repository = repository; this.signatureVerifier = signatureVerifier; this.saveResponseSink = saveResponseToFileSink; this.logResponseSink = logResponseSink; this.forwardResponseSink = forwardResponseSink; } /** * 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) { supplyAsync(() -> verify(responseID)) .thenAcceptAsync(msgResponse -> applySinks(msgResponse)) .exceptionally(ex -> { log.error(ex.getMessage(), ex); return null; }); } private MsgResponse verify(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)); 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 sinkParams = getSinkParams(msgResponse); if (sinkParams.getSaveResponseToFile().isActive()) { supplyAsync(() -> saveResponseSink.save(msgResponse, sinkParams.getSaveResponseToFile().getPath())); } if (sinkParams.isLogResponse()) { supplyAsync(() -> logResponseSink.log(msgResponse)); } if (sinkParams.getForwardResponseToService().isActive()) { supplyAsync(() -> forwardResponseSink.send( msgResponse, sinkParams.getForwardResponseToService().getMzsClient())); } } private MsgResponseSinksType getSinkParams(MsgResponse msgResponse) { var appDeliveryID = msgResponse.getAppDeliveryID(); var request = repository.retrieveDeliveryRequest(appDeliveryID).get(); return request.getConfig().getMsgResponseSinks(); } }