Example #1
0
        public void ThreeSteps_SecondStepThrowsException_DoesntRunThirdStep()
        {
            var stepOneCount   = 0;
            var stepTwoCount   = 0;
            var stepThreeCount = 0;
            var stepper        = new Stepper();

            stepper
            .AddFirstStep(() =>
            {
                stepOneCount++;
                return(StepResult.Success(1));
            })
            .Then <int>(test =>
            {
                stepTwoCount++;
                throw new Exception("Fake Exception!");
            })
            .Then(test =>
            {
                stepThreeCount++;
                return(StepResult.Success(1));
            });

            stepper.RunJob();

            Assert.AreEqual(1, stepOneCount);
            Assert.AreEqual(1, stepTwoCount);
            Assert.AreEqual(0, stepThreeCount);
        }
        private static StepResult CreateSignalResult(MessagingContext context)
        {
            if (Logger.IsInfoEnabled)
            {
                string ConcatErrorDescriptions(Error e)
                {
                    if (e.ErrorLines != null)
                    {
                        return(String.Join(", ", e.ErrorLines.Select(er => er.Detail).Choose(x => x)));
                    }

                    return(String.Empty);
                }

                MessageUnit primaryMessageUnit = context.AS4Message.PrimaryMessageUnit;
                string      errorDescriptions  =
                    primaryMessageUnit is Error error
                        ? ": " + ConcatErrorDescriptions(error)
                        : String.Empty;

                Logger.Info(
                    $"({context.Mode}) <- response with {primaryMessageUnit.GetType().Name} {primaryMessageUnit.MessageId} {errorDescriptions}");
            }

            return(StepResult.Success(context));
        }
Example #3
0
        public void ThreeSteps_SecondStepReturnsFailedStepResult_DoesntRunThirdStep()
        {
            var stepOneCount   = 0;
            var stepTwoCount   = 0;
            var stepThreeCount = 0;
            var stepper        = new Stepper();

            stepper
            .AddFirstStep(() =>
            {
                stepOneCount++;
                return(StepResult.Success(1));
            })
            .Then(test =>
            {
                stepTwoCount++;
                if (false)
                {
                    return(StepResult.Success(2));
                }
                return(StepResult.Failure());
            })
            .Then(test =>
            {
                stepThreeCount++;
                return(StepResult.Success(1));
            });

            stepper.RunJob();

            Assert.AreEqual(1, stepOneCount);
            Assert.AreEqual(1, stepTwoCount);
            Assert.AreEqual(0, stepThreeCount);
        }
Example #4
0
        /// <summary>
        /// Execute the step for a given <paramref name="messagingContext" />.
        /// </summary>
        /// <param name="messagingContext">Message used during the step execution.</param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            var pullRequest = messagingContext?.AS4Message?.FirstSignalMessage as PullRequest;

            if (pullRequest == null)
            {
                throw new InvalidMessageException(
                          "The received message is not a PullRequest message, " +
                          "therefore no UserMessage can be selected to return to the sender");
            }

            (bool hasMatch, OutMessage match) = RetrieveUserMessageForPullRequest(pullRequest);
            if (hasMatch)
            {
                // Retrieve the existing MessageBody and put that stream in the MessagingContext.
                // The HttpReceiver processor will make sure that it gets serialized to the http response stream.
                Stream messageBody = await match.RetrieveMessageBody(_messageBodyStore).ConfigureAwait(false);

                messagingContext.ModifyContext(
                    new ReceivedMessage(messageBody, match.ContentType),
                    MessagingContextMode.Send);

                messagingContext.SendingPMode = AS4XmlSerializer.FromString <SendingProcessingMode>(match.PMode);

                return(StepResult.Success(messagingContext));
            }

            AS4Message pullRequestWarning = AS4Message.Create(Error.CreatePullRequestWarning(IdentifierFactory.Instance.Create()));

            messagingContext.ModifyContext(pullRequestWarning);

            return(StepResult.Success(messagingContext).AndStopExecution());
        }
        private async Task <StepResult> DecryptAS4MessageAsync(MessagingContext messagingContext)
        {
            try
            {
                Logger.Trace("Start decrypting AS4Message ...");
                X509Certificate2 decryptionCertificate = GetCertificate(messagingContext);
                messagingContext.AS4Message.Decrypt(decryptionCertificate);
                Logger.Info($"{messagingContext.LogTag} AS4Message is decrypted correctly");

                JournalLogEntry entry =
                    JournalLogEntry.CreateFrom(
                        messagingContext.AS4Message,
                        $"Decrypted using certificate {decryptionCertificate.FriendlyName}");

                return(await StepResult
                       .Success(messagingContext)
                       .WithJournalAsync(entry));
            }
            catch (Exception ex) when(ex is CryptoException || ex is CryptographicException)
            {
                Logger.Error(ex);

                messagingContext.ErrorResult = new ErrorResult(
                    description: "Decryption of message failed",
                    alias: ErrorAlias.FailedDecryption);

                Logger.Error(messagingContext.ErrorResult.Description);
                return(StepResult.Failed(messagingContext));
            }
        }
Example #6
0
        /// <summary>
        /// Handle the given <paramref name="response" />, but delegate to the next handler if you can't.
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        public async Task <StepResult> HandleResponse(IAS4Response response)
        {
            if (response.ReceivedAS4Message.IsEmpty)
            {
                if (response.StatusCode == HttpStatusCode.Accepted)
                {
                    response.OriginalRequest.ModifyContext(response.ReceivedAS4Message, MessagingContextMode.Send);
                    return(StepResult.Success(response.OriginalRequest).AndStopExecution());
                }

                Logger.Error($"Response with HTTP status: {response.StatusCode}");

                if (Logger.IsErrorEnabled)
                {
                    using (var r = new StreamReader(response.ReceivedStream.UnderlyingStream))
                    {
                        string content = await r.ReadToEndAsync();

                        if (!string.IsNullOrEmpty(content))
                        {
                            Logger.Error("Response with HTTP content: " + content);
                        }
                    }
                }

                response.OriginalRequest.ModifyContext(response.ReceivedStream, MessagingContextMode.Send);
                return(StepResult.Failed(response.OriginalRequest).AndStopExecution());
            }

            return(await _nextHandler.HandleResponse(response));
        }
Example #7
0
        private static async Task <StepResult> ExecuteSteps(
            IEnumerable <IStep> steps,
            MessagingContext context)
        {
            StepResult result = StepResult.Success(context);

            var currentContext = context;

            foreach (IStep step in steps)
            {
                result = await step.ExecuteAsync(currentContext).ConfigureAwait(false);

                if (result.CanProceed == false || result.Succeeded == false || result.MessagingContext?.Exception != null)
                {
                    return(result);
                }

                if (result.MessagingContext != null && currentContext != result.MessagingContext)
                {
                    currentContext = result.MessagingContext;
                }
            }

            return(result);
        }
Example #8
0
        public void ThreeSteps_UsingLambdaFunctions_RunsEachStepOnce()
        {
            var stepOneCount   = 0;
            var stepTwoCount   = 0;
            var stepThreeCount = 0;
            var stepper        = new Stepper();

            stepper
            .AddFirstStep(() =>
            {
                stepOneCount++;
                return(StepResult.Success("ghj"));
            })
            .Then(test =>
            {
                stepTwoCount++;
                return(StepResult.Success(1));
            })
            .Then(test =>
            {
                stepThreeCount++;
                return(StepResult.Success(1));
            });

            stepper.RunJob();

            Assert.AreEqual(1, stepOneCount);
            Assert.AreEqual(1, stepTwoCount);
            Assert.AreEqual(1, stepThreeCount);
        }
        /// <summary>
        /// Execute the step for a given <paramref name="messagingContext"/>.
        /// </summary>
        /// <param name="messagingContext">Message used during the step execution.</param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext?.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SetMessageToBeSentStep)} requires an AS4Message to mark for sending but no AS4Message is present in the MessagingContext");
            }

            Logger.Trace($"{messagingContext.LogTag} Set the message's Operation=ToBeSent");
            if (messagingContext.MessageEntityId == null)
            {
                throw new InvalidOperationException(
                          $"{messagingContext.LogTag} MessagingContext does not contain the ID of the OutMessage that must be set to ToBeSent");
            }

            using (DatastoreContext context = _createContext())
            {
                var repository = new DatastoreRepository(context);
                var service    = new OutMessageService(repository, _messageStore);

                service.UpdateAS4MessageToBeSent(
                    messagingContext.MessageEntityId.Value,
                    messagingContext.AS4Message,
                    messagingContext.SendingPMode?.Reliability?.ReceptionAwareness);

                await context.SaveChangesAsync().ConfigureAwait(false);
            }

            return(StepResult.Success(messagingContext));
        }
Example #10
0
 public Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
 {
     return(StepResult
            .Success(messagingContext)
            .WithJournalAsync(
                JournalLogEntry.CreateFrom(
                    messagingContext.AS4Message,
                    "Log entry 2")));
 }
Example #11
0
        /// <summary>
        /// Sign the <see cref="AS4Message" />
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SignAS4MessageStep)} requires an AS4Message to sign but no AS4Message is present in the MessagingContext");
            }

            if (messagingContext.AS4Message.IsEmpty)
            {
                Logger.Debug("No signing will be performed on the message because it's empty");
                return(await StepResult.SuccessAsync(messagingContext));
            }

            Signing signInfo = RetrieveSigningInformation(
                messagingContext.AS4Message,
                messagingContext.SendingPMode,
                messagingContext.ReceivingPMode);

            if (signInfo == null)
            {
                Logger.Trace("No signing will be performend on the message because no signing information was found in either Sending or Receiving PMode");
                return(await StepResult.SuccessAsync(messagingContext));
            }

            if (signInfo.IsEnabled == false)
            {
                Logger.Trace("No signing will be performend on the message because the PMode siging information is disabled");
                return(await StepResult.SuccessAsync(messagingContext));
            }

            Logger.Info($"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Sign AS4Message with given signing information of the PMode");

            X509Certificate2 certificate = RetrieveCertificate(signInfo);
            var settings =
                new CalculateSignatureConfig(
                    signingCertificate: certificate,
                    referenceTokenType: signInfo.KeyReferenceMethod,
                    signingAlgorithm: signInfo.Algorithm,
                    hashFunction: signInfo.HashFunction);

            SignAS4Message(settings, messagingContext.AS4Message);

            JournalLogEntry logEntry = JournalLogEntry.CreateFrom(
                messagingContext.AS4Message,
                $"Signed with certificate {settings.SigningCertificate.FriendlyName} and reference {settings.ReferenceTokenType} "
                + $"using algorithm {settings.SigningAlgorithm} and hash {settings.HashFunction}");

            return(await StepResult
                   .Success(messagingContext)
                   .WithJournalAsync(logEntry));
        }
Example #12
0
            public void IsTrueIfStopExecutiongIsntCalled()
            {
                // Act
                StepResult actualStepResult = StepResult.Success(AnonymousMessage());

                // Assert
                Assert.True(actualStepResult.CanProceed);
                Assert.True(actualStepResult.Succeeded);
            }
        /// <summary>
        /// Start Encrypting AS4 Message
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(EncryptAS4MessageStep)} requires an AS4Message to encrypt but no AS4Message is present in the MessagingContext");
            }

            if (messagingContext.SendingPMode == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(EncryptAS4MessageStep)} requires a SendingPMode to encrypt the AS4Message but no SendingPMode is present in the MessagingContext");
            }

            if (messagingContext.SendingPMode.Security?.Encryption == null ||
                messagingContext.SendingPMode.Security.Encryption.IsEnabled == false)
            {
                Logger.Trace(
                    "No encryption of the AS4Message will happen because the " +
                    $"SendingPMode {messagingContext.SendingPMode?.Id} Security.Encryption.IsEnabled is disabled");

                return(await StepResult.SuccessAsync(messagingContext));
            }

            Logger.Info(
                $"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Encrypt AS4Message with given encryption information " +
                $"configured in the SendingPMode: {messagingContext.SendingPMode.Id}");

            KeyEncryptionConfiguration keyEncryptionConfig = RetrieveKeyEncryptionConfig(messagingContext.SendingPMode);
            Encryption encryptionSettings   = messagingContext.SendingPMode.Security.Encryption;
            var        dataEncryptionConfig = new DataEncryptionConfiguration(
                encryptionMethod: encryptionSettings.Algorithm,
                algorithmKeySize: encryptionSettings.AlgorithmKeySize);

            EncryptAS4Message(
                messagingContext.AS4Message,
                keyEncryptionConfig,
                dataEncryptionConfig);

            var journal = JournalLogEntry.CreateFrom(
                messagingContext.AS4Message,
                $"Encrypted using certificate {keyEncryptionConfig.EncryptionCertificate.FriendlyName} and "
                + $"key encryption method: {keyEncryptionConfig.EncryptionMethod}, key digest method: {keyEncryptionConfig.DigestMethod}, "
                + $"key mgf: {keyEncryptionConfig.Mgf} and Data encryption method: {dataEncryptionConfig.EncryptionMethod}, "
                + $" data encryption type: {dataEncryptionConfig.EncryptionType}, data transport algorithm: {dataEncryptionConfig.TransformAlgorithm}");

            return(await StepResult
                   .Success(messagingContext)
                   .WithJournalAsync(journal));
        }
        /// <summary>
        /// Execute the step for a given <paramref name="messagingContext" />.
        /// </summary>
        /// <param name="messagingContext">Message used during the step execution.</param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext?.ErrorResult == null)
            {
                return(StepResult.Success(messagingContext));
            }

            await InsertReferencedInException(messagingContext, CancellationToken.None).ConfigureAwait(false);

            return(StepResult.Success(messagingContext));
        }
 private static StepResult CreateEmptySoapResult(MessagingContext messagingContext)
 {
     Logger.Debug("Empty Accepted response will be send to requested party since signal will be sent async");
     return(StepResult.Success(
                new MessagingContext(
                    AS4Message.Create(messagingContext.SendingPMode),
                    MessagingContextMode.Receive)
     {
         ReceivingPMode = messagingContext.ReceivingPMode
     }));
 }
Example #16
0
 public Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
 {
     return(StepResult
            .Success(messagingContext)
            .WithJournalAsync(
                JournalLogEntry.CreateFrom(
                    AS4Message.Create(new Receipt(
                                          $"receipt-{Guid.NewGuid()}",
                                          messagingContext.AS4Message.PrimaryMessageUnit.MessageId)),
                    "Log entry 1")));
 }
        /// <summary>
        /// Execute the step for a given <paramref name="messagingContext"/>.
        /// </summary>
        /// <param name="messagingContext">Message used during the step execution.</param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            var entityMessage = messagingContext?.ReceivedMessage as ReceivedEntityMessage;

            if (!(entityMessage?.Entity is InMessage receivedInMessage))
            {
                throw new InvalidOperationException(
                          "The MessagingContext must contain a ReceivedMessage that represents an InMessage." + Environment.NewLine +
                          "Other types of ReceivedMessage models are not supported in this Step.");
            }

            // Forward message by creating an OutMessage and set operation to 'ToBeProcessed'.
            Logger.Info($"{messagingContext.LogTag} Create a message that will be forwarded to the next MSH");
            using (Stream originalInMessage =
                       await _messageStore.LoadMessageBodyAsync(receivedInMessage.MessageLocation))
            {
                string outLocation = await _messageStore.SaveAS4MessageStreamAsync(
                    _configuration.OutMessageStoreLocation,
                    originalInMessage);

                originalInMessage.Position = 0;

                AS4Message msg =
                    await SerializerProvider.Default
                    .Get(receivedInMessage.ContentType)
                    .DeserializeAsync(originalInMessage, receivedInMessage.ContentType);

                using (DatastoreContext dbContext = _createDataStoreContext())
                {
                    var repository = new DatastoreRepository(dbContext);

                    // Only create an OutMessage for the primary message-unit.
                    OutMessage outMessage = OutMessageBuilder
                                            .ForMessageUnit(
                        msg.PrimaryMessageUnit,
                        receivedInMessage.ContentType,
                        messagingContext.SendingPMode)
                                            .BuildForForwarding(outLocation, receivedInMessage);

                    Logger.Debug("Insert OutMessage {{Intermediary=true, Operation=ToBeProcesed}}");
                    repository.InsertOutMessage(outMessage);

                    // Set the InMessage to Forwarded.
                    // We do this for all InMessages that are present in this AS4 Message
                    repository.UpdateInMessages(
                        m => msg.MessageIds.Contains(m.EbmsMessageId),
                        r => r.Operation = Operation.Forwarded);

                    await dbContext.SaveChangesAsync();
                }
            }

            return(StepResult.Success(messagingContext));
        }
Example #18
0
        private static async Task <StepResult> TryVerifyingSignatureAsync(
            MessagingContext messagingContext,
            SigningVerification verification)
        {
            try
            {
                VerifySignatureConfig options =
                    CreateVerifyOptionsForAS4Message(messagingContext.AS4Message, verification);

                Logger.Debug($"Verify signature on the AS4Message {{AllowUnknownRootCertificateAuthority={options.AllowUnknownRootCertificateAuthority}}}");
                if (!messagingContext.AS4Message.VerifySignature(options))
                {
                    return(InvalidSignatureResult(
                               "The signature is invalid",
                               ErrorAlias.FailedAuthentication,
                               messagingContext));
                }

                Logger.Info($"{messagingContext.LogTag} AS4Message has a valid signature present");

                JournalLogEntry entry =
                    JournalLogEntry.CreateFrom(
                        messagingContext.AS4Message,
                        $"Signature verified with {(options.AllowUnknownRootCertificateAuthority ? "allowing" : "disallowing")} unknown certificate authorities");

                return(await StepResult
                       .Success(messagingContext)
                       .WithJournalAsync(entry));
            }
            catch (CryptographicException exception)
            {
                var description = "Signature verification failed";

                if (messagingContext.AS4Message.IsEncrypted)
                {
                    Logger.Error(
                        "Signature verification failed because the received message is still encrypted. "
                        + "Make sure that you specify <Decryption/> information in the <Security/> element of the "
                        + "ReceivingPMode so the ebMS MessagingHeader is first decrypted before it's signature gets verified");

                    description = "Signature verification failed because the message is still encrypted";
                }

                Logger.Error($"{messagingContext.LogTag} An exception occured while validating the signature: {exception.Message}");
                return(InvalidSignatureResult(
                           description,
                           ErrorAlias.FailedAuthentication,
                           messagingContext));
            }
        }
        /// <summary>
        /// Start determine the Receiving Processing Mode
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(DeterminePModesStep)} requires an AS4Message but no AS4Message is present in the MessagingContext");
            }

            AS4Message as4Message = messagingContext.AS4Message;
            bool       containsSignalThatNotPullRequest = as4Message.SignalMessages.Any(s => !(s is Model.Core.PullRequest));

            if (containsSignalThatNotPullRequest && (as4Message.IsMultiHopMessage || messagingContext.SendingPMode == null))
            {
                messagingContext.SendingPMode = await DetermineSendingPModeForSignalMessageAsync(as4Message);
            }

            if (messagingContext.ReceivingPMode != null)
            {
                Logger.Debug(
                    $"Will not determine ReceivingPMode: incoming message has already a ReceivingPMode: {messagingContext.ReceivingPMode.Id} configured. "
                    + $"{Environment.NewLine} This happens when the Receive Agent is configured as a \"Static Receive Agent\"");
            }
            else if (as4Message.HasUserMessage || as4Message.SignalMessages.Any(s => s.IsMultihopSignal))
            {
                Logger.Trace("Incoming message hasn't yet a ReceivingPMode, will determine one");
                UserMessage userMessage = GetUserMessageFromFirstMessageUnitOrRoutingInput(messagingContext.AS4Message);
                IEnumerable <ReceivePMode> possibilities = GetMatchingReceivingPModeForUserMessage(userMessage);

                if (possibilities.Any() == false)
                {
                    return(NoMatchingPModeFoundFailure(messagingContext));
                }

                if (possibilities.Count() > 1)
                {
                    return(TooManyPossibilitiesFailure(messagingContext, possibilities));
                }

                ReceivePMode pmode = possibilities.First();
                Logger.Info($"Found ReceivingPMode \"{pmode.Id}\" to further process the incoming message");
                messagingContext.ReceivingPMode = pmode;
            }

            return(StepResult.Success(messagingContext));
        }
            public async void ThenTransmitMessageSucceeds()
            {
                // Arrange
                MessagingContext dummyMessage       = CreateDummyMessageWithAttachment();
                StepResult       expectedStepResult = StepResult.Success(dummyMessage);

                var compositeStep = new CompositeStep(CreateMockStepWith(expectedStepResult).Object);

                // Act
                StepResult actualStepResult = await compositeStep.ExecuteAsync(dummyMessage);

                // Assert
                Assert.Equal(expectedStepResult.MessagingContext, actualStepResult.MessagingContext);
            }
Example #21
0
        public void OneStep_UsingLambdaFunction_RunsFunctionOnce()
        {
            var runCount = 0;
            var stepper  = new Stepper();

            stepper.AddFirstStep(() =>
            {
                runCount++;
                return(StepResult.Success(0));
            });

            stepper.RunJob();

            Assert.AreEqual(1, runCount);
        }
        /// <summary>
        /// Start updating the Data store
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        /// <exception cref="Exception">A delegate callback throws an exception.</exception>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.ReceivedMessage == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SaveReceivedMessageStep)} requires a ReceivedMessage to store the incoming message into the datastore but no ReceivedMessage is present in the MessagingContext");
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(SaveReceivedMessageStep)} requires an AS4Message to save but no AS4Message is present in the MessagingContext");
            }

            Logger.Trace($"{messagingContext.LogTag} Store the incoming AS4 Message to the datastore");
            MessagingContext resultContext = await InsertReceivedAS4MessageAsync(messagingContext);

            if (resultContext != null && resultContext.Exception == null)
            {
                /* PullRequests will not be notified, so we don't need a referenced Id,
                 * Receipts and Errors will need to have a referenced UserMessage
                 * if we want to know the original Sending PMode required for the notification. */

                MessageUnit primaryMessageUnit = resultContext.AS4Message.PrimaryMessageUnit;
                if ((primaryMessageUnit is Receipt || primaryMessageUnit is Error) &&
                    string.IsNullOrWhiteSpace(primaryMessageUnit.RefToMessageId))
                {
                    Logger.Warn(
                        $"{messagingContext.LogTag} Received message is a SignalMessage without RefToMessageId. " +
                        "No such SignalMessage are supported so the message cannot be processed any further");

                    return(StepResult
                           .Success(new MessagingContext(AS4Message.Empty, messagingContext.Mode))
                           .AndStopExecution());
                }

                Logger.Trace($"{messagingContext.LogTag} The AS4Message is successfully stored into the datastore");
                return(StepResult.Success(resultContext));
            }

            Logger.Error($"{messagingContext.LogTag} The AS4Message is not stored correctly into the datastore {resultContext?.Exception}");
            return(StepResult.Failed(resultContext));
        }
Example #23
0
        public void ThreeSteps_FirstStepCreatesString_SecondStepGetsString()
        {
            var testString = "This is a test string";
            var stepper    = new Stepper();

            stepper.AddFirstStep(() =>
            {
                var stringInFirstStep = testString;
                return(StepResult.Success(stringInFirstStep));
            })
            .Then(stringUnderTest =>
            {
                Assert.AreEqual(testString, stringUnderTest);
                return(StepResult.Success(stringUnderTest));
            });
        }
            public async void ThenStepStopExecutionWithMarkedStepResult()
            {
                // Arrange
                MessagingContext expectedMessage     = CreateDummyMessageWithAttachment();
                StepResult       stopExecutionResult = StepResult.Success(expectedMessage).AndStopExecution();

                var spyStep       = new SpyStep();
                var compositeStep = new CompositeStep(CreateMockStepWith(stopExecutionResult).Object, spyStep);

                // Act
                StepResult actualResult = await compositeStep.ExecuteAsync(new EmptyMessagingContext());

                // Assert
                Assert.False(spyStep.IsCalled);
                Assert.Equal(expectedMessage, actualResult.MessagingContext);
            }
        /// <summary>
        /// Compress the <see cref="AS4Message" /> if required
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(CompressAttachmentsStep)} requires an AS4Message to compress it attachments but no AS4Message is present in the MessagingContext");
            }

            if (messagingContext.SendingPMode == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(CompressAttachmentsStep)} requires a Sending Processing Mode to use during the compression but no Sending Processing Mode is present in the MessagingContext");
            }

            if (messagingContext.SendingPMode.MessagePackaging?.UseAS4Compression == false)
            {
                Logger.Trace($"No compression will happen because the SendingPMode {messagingContext.SendingPMode.Id} MessagePackaging.UseAS4Compression is disabled");
                return(StepResult.Success(messagingContext));
            }

            try
            {
                Logger.Info($"(Outbound)[{messagingContext.AS4Message.GetPrimaryMessageId()}] Compress AS4Message attachments with GZip compression");
                messagingContext.AS4Message.CompressAttachments();
            }
            catch (SystemException exception)
            {
                const string description = "Attachments cannot be compressed because of an exception";
                Logger.Error(description);

                throw new InvalidDataException(description, exception);
            }

            JournalLogEntry journal =
                JournalLogEntry.CreateFrom(
                    messagingContext.AS4Message,
                    $"Compressed {messagingContext.AS4Message.Attachments.Count()} attachments with GZip compression");

            return(await StepResult
                   .Success(messagingContext)
                   .WithJournalAsync(journal));
        }
Example #26
0
        /// <summary>
        /// Execute the step on a given <paramref name="messagingContext"/>.
        /// </summary>
        /// <param name="messagingContext"><see cref="MessagingContext"/> on which the step must be executed.</param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(BundleSignalMessageToPullRequestStep)} requires a AS4Message to possible bundle a "
                          + "SignalMessage to the PullRequest but there's not a AS4Message present in the MessagingContext");
            }

            if (messagingContext.SendingPMode == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(BundleSignalMessageToPullRequestStep)} requires a SendingPMode to select the right "
                          + "SignalMessages for piggybacking but there's not a SendingPMode present in the MessagingContext");
            }

            if (!(messagingContext.AS4Message.PrimaryMessageUnit is PullRequest pullRequest))
            {
                throw new InvalidOperationException(
                          $"{nameof(BundleSignalMessageToPullRequestStep)} requires a PullRequest as primary message unit in the "
                          + "AS4Message but there's not a PullRequest present in the MessagingContext");
            }

            using (DatastoreContext db = _createContext())
            {
                var service = new PiggyBackingService(db);
                IEnumerable <SignalMessage> signals =
                    await service.SelectToBePiggyBackedSignalMessagesAsync(pullRequest, messagingContext.SendingPMode, _bodyStore);

                foreach (SignalMessage signal in signals)
                {
                    Logger.Info(
                        $"PiggyBack the {signal.GetType().Name} \"{signal.MessageId}\" which reference "
                        + $"UserMessage \"{signal.RefToMessageId}\" to the PullRequest");

                    messagingContext.AS4Message.AddMessageUnit(signal);
                }

                return(StepResult.Success(messagingContext));
            }
        }
        /// <summary>
        /// Handle the given <paramref name="response" />, but delegate to the next handler if you can't.
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        public async Task <StepResult> HandleResponse(IAS4Response response)
        {
            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }

            MessagingContext request = response.OriginalRequest;

            if (request?.AS4Message?.IsPullRequest == true)
            {
                bool pullRequestWasPiggyBacked =
                    request.AS4Message.SignalMessages.Any(s => !(s is PullRequest));

                if (pullRequestWasPiggyBacked)
                {
                    using (DatastoreContext ctx = _createContext())
                    {
                        SendResult result =
                            response.StatusCode == HttpStatusCode.Accepted ||
                            response.StatusCode == HttpStatusCode.OK
                                ? SendResult.Success
                                : SendResult.RetryableFail;

                        var service = new PiggyBackingService(ctx);
                        service.ResetSignalMessagesToBePiggyBacked(request.AS4Message.SignalMessages, result);

                        await ctx.SaveChangesAsync().ConfigureAwait(false);
                    }
                }

                bool isEmptyChannelWarning =
                    (response.ReceivedAS4Message?.FirstSignalMessage as Error)?.IsPullRequestWarning == true;

                if (isEmptyChannelWarning)
                {
                    request.ModifyContext(response.ReceivedAS4Message, MessagingContextMode.Send);
                    return(StepResult.Success(response.OriginalRequest).AndStopExecution());
                }
            }

            return(await _nextHandler.HandleResponse(response));
        }
Example #28
0
        /// <summary>
        /// Start zipping <see cref="Attachment"/> Models
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext?.AS4Message == null)
            {
                throw new InvalidOperationException(
                          $"{nameof(ZipAttachmentsStep)} requires an AS4Message to zip the attachments but no AS4Message is present in the MessagingContext");
            }

            if (messagingContext.AS4Message.Attachments.Count() > 1)
            {
                Stream zippedStream = await ZipAttachmentsInAS4MessageAsync(messagingContext.AS4Message).ConfigureAwait(false);

                Attachment zipAttachment = CreateZippedAttachment(zippedStream);

                OverwriteAttachmentEntries(messagingContext.AS4Message, zipAttachment);
            }

            LogManager.GetCurrentClassLogger().Info($"{messagingContext.LogTag} Zip the Attachments to a single file");
            return(StepResult.Success(messagingContext));
        }
Example #29
0
        /// <summary>
        /// Start sending the AS4 Messages
        /// to the consuming business application
        /// </summary>
        /// <param name="messagingContext"></param>
        /// <returns></returns>
        public async Task <StepResult> ExecuteAsync(MessagingContext messagingContext)
        {
            if (messagingContext == null)
            {
                throw new ArgumentNullException(nameof(messagingContext));
            }

            if (messagingContext.ReceivingPMode == null)
            {
                throw new InvalidOperationException(
                          "Unable to send DeliverMessage: no ReceivingPMode is set");
            }

            if (messagingContext.ReceivingPMode.MessageHandling?.DeliverInformation == null)
            {
                throw new InvalidOperationException(
                          $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} does not contain any <DeliverInformation />." +
                          "Please provide a correct <DeliverInformation /> tag to indicate where the deliver message (and its attachments) should be send to.");
            }

            if (messagingContext.ReceivingPMode.MessageHandling.DeliverInformation.DeliverMethod?.Type == null)
            {
                throw new InvalidOperationException(
                          $"Unable to send the DeliverMessage: the ReceivingPMode {messagingContext.ReceivingPMode.Id} "
                          + "does not contain any <Type/> element indicating the uploading strategy in the MessageHandling.Deliver.DeliverMethod element. "
                          + "Default sending strategies are: 'FILE' and 'HTTP'. See 'Deliver Uploading' for more information");
            }

            Logger.Trace($"{messagingContext.LogTag} Start sending the DeliverMessage to the consuming business application...");
            SendResult result =
                await SendDeliverMessageAsync(
                    messagingContext.ReceivingPMode.MessageHandling.DeliverInformation.DeliverMethod,
                    messagingContext.DeliverMessage);

            Logger.Trace($"{messagingContext.LogTag} Done sending the DeliverMesssage to the consuming business application");

            await UpdateDeliverMessageAsync(messagingContext, result);

            return(StepResult.Success(messagingContext));
        }
Example #30
0
        public void OneStep_HasBothSuccessAndFailStepResult_DoesntThrowException()
        {
            var stepper = new Stepper();

            stepper.AddFirstStep(() =>
            {
                if (true)
                {
                    return(StepResult.Success(1));
                }
                return(StepResult.Failure());
            })
            .Then(test =>
            {
                Console.WriteLine(test);
                return(StepResult.Success());
            });

            var jobResult = stepper.RunJob();

            Assert.AreEqual(false, jobResult.HasFailed);
        }