private async Task <StepResult> ExerciseVerifyNRRReceipt(
            IAS4MessageBodyStore messageStore,
            AS4Message signedReceiptResult,
            bool verifyNrr)
        {
            var verifyNrrPMode = new SendingProcessingMode {
                ReceiptHandling = { VerifyNRR = verifyNrr }
            };
            var verifySignaturePMode = new ReceivingProcessingMode {
                Security = { SigningVerification = { Signature = Limit.Required } }
            };

            var step = new VerifySignatureAS4MessageStep(
                GetDataStoreContext,
                messageStore);

            return(await step.ExecuteAsync(
                       new MessagingContext(
                           signedReceiptResult,
                           MessagingContextMode.Receive)
            {
                SendingPMode = verifyNrrPMode,
                ReceivingPMode = verifySignaturePMode
            }));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="PullSendAgentExceptionHandler" /> class.
        /// </summary>
        /// <param name="createContext">The create context.</param>
        /// <param name="configuration"></param>
        /// <param name="bodyStore"></param>
        public PullSendAgentExceptionHandler(
            Func <DatastoreContext> createContext,
            IConfig configuration,
            IAS4MessageBodyStore bodyStore)
        {
            if (createContext == null)
            {
                throw new ArgumentNullException(nameof(createContext));
            }

            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (bodyStore == null)
            {
                throw new ArgumentNullException(nameof(bodyStore));
            }

            _createContext            = createContext;
            _configuration            = configuration;
            _bodyStore                = bodyStore;
            _outboundExceptionHandler = new OutboundExceptionHandler(createContext, configuration, bodyStore);
        }
Пример #3
0
        /// <summary>
        /// Retrieves the Message body as a stream.
        /// </summary>
        /// <param name="store">
        /// The <see cref="MessageBodyStore" /> which is responsible for providing the correct
        /// <see cref="IAS4MessageBodyStore" /> that loads the <see cref="AS4Message" /> body.
        /// </param>
        /// <returns>A Stream which contains the MessageBody</returns>
        public async Task <Stream> RetrieveMessageBody(IAS4MessageBodyStore store)
        {
            if (string.IsNullOrWhiteSpace(MessageLocation))
            {
                LogManager.GetCurrentClassLogger().Warn("Unable to retrieve the AS4 Message Body: MessageLocation is not set.");
                return(null);
            }

            return(await TryLoadMessageBody(store));
        }
Пример #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="MonitorService" /> class.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="pmodeSource">The pmode source.</param>
 /// <param name="datastoreRepository">The datastore repository.</param>
 /// <param name="bodyStore">The body store.</param>
 /// <param name="mapperConfig">The mapper configuration.</param>
 public MonitorService(
     DatastoreContext context,
     IAs4PmodeSource pmodeSource,
     IDatastoreRepository datastoreRepository,
     IAS4MessageBodyStore bodyStore,
     MapperConfiguration mapperConfig)
 {
     this.context             = context;
     this.pmodeSource         = pmodeSource;
     this.datastoreRepository = datastoreRepository;
     this.bodyStore           = bodyStore;
     this.mapperConfig        = mapperConfig;
 }
Пример #5
0
        private async Task <Stream> TryLoadMessageBody(IAS4MessageBodyStore store)
        {
            try
            {
                return(await store.LoadMessageBodyAsync(MessageLocation));
            }
            catch (Exception exception)
            {
                LogManager.GetCurrentClassLogger().Error(exception.Message);

                return(null);
            }
        }
Пример #6
0
        /// <summary>
        /// Accepts the specified condition.
        /// </summary>
        /// <param name="condition">The condition.</param>
        /// <param name="persister">The persister.</param>
        public void Accept(Func <string, bool> condition, IAS4MessageBodyStore persister)
        {
            if (condition == null)
            {
                throw new ArgumentNullException(nameof(condition));
            }

            if (persister == null)
            {
                throw new ArgumentNullException(nameof(persister));
            }

            _stores[condition] = persister;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SetMessageToBeSentStep"/> class.
        /// </summary>
        /// <param name="createContext">The get data store context.</param>
        /// <param name="messageStore">The message store.</param>
        public SetMessageToBeSentStep(Func <DatastoreContext> createContext, IAS4MessageBodyStore messageStore)
        {
            if (createContext == null)
            {
                throw new ArgumentNullException(nameof(createContext));
            }

            if (messageStore == null)
            {
                throw new ArgumentNullException(nameof(messageStore));
            }

            _createContext = createContext;
            _messageStore  = messageStore;
        }
Пример #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BundleSignalMessageToPullRequestStep"/> class.
        /// </summary>
        /// <param name="createContext">The create datastore context function.</param>
        /// <param name="bodyStore">The store to use for persisting messages.</param>
        public BundleSignalMessageToPullRequestStep(Func <DatastoreContext> createContext, IAS4MessageBodyStore bodyStore)
        {
            if (createContext == null)
            {
                throw new ArgumentNullException(nameof(createContext));
            }

            if (bodyStore == null)
            {
                throw new ArgumentNullException(nameof(bodyStore));
            }

            _createContext = createContext;
            _bodyStore     = bodyStore;
        }
Пример #9
0
        /// <summary>
        /// Inserts a received Message in the DataStore.
        /// For each message-unit that exists in the AS4Message,an InMessage record is created.
        /// The AS4 Message Body is persisted as it has been received.
        /// </summary>
        /// <remarks>The received Message is parsed to an AS4 Message instance.</remarks>
        /// <param name="sendingPMode"></param>
        /// <param name="mep"></param>
        /// <param name="messageBodyStore"></param>
        /// <param name="as4Message"></param>
        /// <param name="originalMessage"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        /// <returns>A MessagingContext instance that contains the parsed AS4 Message.</returns>
        public async Task <AS4Message> InsertAS4MessageAsync(
            AS4Message as4Message,
            ReceivedMessage originalMessage,
            SendingProcessingMode sendingPMode,
            MessageExchangePattern mep,
            IAS4MessageBodyStore messageBodyStore)
        {
            if (as4Message == null)
            {
                throw new ArgumentNullException(nameof(as4Message));
            }

            if (originalMessage == null)
            {
                throw new InvalidOperationException("The MessagingContext must contain a ReceivedMessage");
            }

            if (messageBodyStore == null)
            {
                throw new ArgumentNullException(nameof(messageBodyStore));
            }

            // TODO: should we start the transaction here.
            string location =
                await messageBodyStore.SaveAS4MessageStreamAsync(
                    location : _configuration.InMessageStoreLocation,
                    as4MessageStream : originalMessage.UnderlyingStream).ConfigureAwait(false);

            StreamUtilities.MovePositionToStreamStart(originalMessage.UnderlyingStream);

            try
            {
                InsertUserMessages(as4Message, mep, location, sendingPMode);
                InsertSignalMessages(as4Message, mep, location, sendingPMode);

                return(as4Message);
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message);

                var service = new ExceptionService(_configuration, _repository, messageBodyStore);
                await service.InsertIncomingExceptionAsync(ex, new MemoryStream(Encoding.UTF8.GetBytes(location)));

                throw;
            }
        }
Пример #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="VerifySignatureAS4MessageStep" /> class.
        /// </summary>
        /// <param name="createContext">The create context.</param>
        /// <param name="bodyStore">The body store.</param>
        public VerifySignatureAS4MessageStep(
            Func <DatastoreContext> createContext,
            IAS4MessageBodyStore bodyStore)
        {
            if (createContext == null)
            {
                throw new ArgumentNullException(nameof(createContext));
            }

            if (bodyStore == null)
            {
                throw new ArgumentNullException(nameof(bodyStore));
            }

            _storeExpression = createContext;
            _bodyStore       = bodyStore;
        }
Пример #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OutMessageService" /> class.
        /// </summary>
        /// <param name="config">The configuration used to retrieve the response <see cref="SendingProcessingMode"/> while inserting messages and the store location for <see cref="OutMessage"/>s.</param>
        /// <param name="repository">The repository used to insert and update <see cref="OutMessage"/>s.</param>
        /// <param name="messageBodyStore">The <see cref="IAS4MessageBodyStore"/> that must be used to persist the AS4 Message Body.</param>
        public OutMessageService(IConfig config, IDatastoreRepository repository, IAS4MessageBodyStore messageBodyStore)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            if (repository == null)
            {
                throw new ArgumentNullException(nameof(repository));
            }

            if (messageBodyStore == null)
            {
                throw new ArgumentNullException(nameof(messageBodyStore));
            }

            _configuration    = config;
            _repository       = repository;
            _messageBodyStore = messageBodyStore;
        }
Пример #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UpdateReceivedAS4MessageBodyStep" /> class.
        /// </summary>
        /// <param name="configuration">The configuration used to save the message</param>
        /// <param name="createDatastoreContext">The create Datastore Context.</param>
        /// <param name="messageBodyStore">The <see cref="IAS4MessageBodyStore" /> that must be used to persist the messagebody content.</param>
        public UpdateReceivedAS4MessageBodyStep(
            IConfig configuration,
            Func <DatastoreContext> createDatastoreContext,
            IAS4MessageBodyStore messageBodyStore)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (createDatastoreContext == null)
            {
                throw new ArgumentNullException(nameof(createDatastoreContext));
            }

            if (messageBodyStore == null)
            {
                throw new ArgumentNullException(nameof(messageBodyStore));
            }

            _configuration          = configuration;
            _createDatastoreContext = createDatastoreContext;
            _messageBodyStore       = messageBodyStore;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CreateForwardMessageStep" /> class.
        /// </summary>
        /// <param name="configuration">The local configuration.</param>
        /// <param name="messageStore">The store where the datastore persist its messages.</param>
        /// <param name="createDatastoreContext">Create a new datastore context.</param>
        public CreateForwardMessageStep(
            IConfig configuration,
            IAS4MessageBodyStore messageStore,
            Func <DatastoreContext> createDatastoreContext)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (messageStore == null)
            {
                throw new ArgumentNullException(nameof(messageStore));
            }

            if (createDatastoreContext == null)
            {
                throw new ArgumentNullException(nameof(createDatastoreContext));
            }

            _configuration          = configuration;
            _messageStore           = messageStore;
            _createDataStoreContext = createDatastoreContext;
        }
Пример #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ExceptionService"/> class.
        /// </summary>
        public ExceptionService(
            IConfig config,
            IDatastoreRepository repository,
            IAS4MessageBodyStore bodyStore)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            if (repository == null)
            {
                throw new ArgumentNullException(nameof(repository));
            }

            if (bodyStore == null)
            {
                throw new ArgumentNullException(nameof(bodyStore));
            }

            _config     = config;
            _repository = repository;
            _bodyStore  = bodyStore;
        }
Пример #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OutMessageService"/> class.
 /// </summary>
 /// <param name="repository">The repository used to insert and update <see cref="OutMessage"/>s.</param>
 /// <param name="messageBodyStore">The <see cref="IAS4MessageBodyStore"/> that must be used to persist the AS4 Message Body.</param>
 public OutMessageService(IDatastoreRepository repository, IAS4MessageBodyStore messageBodyStore)
     : this(Config.Instance, repository, messageBodyStore)
 {
 }
Пример #16
0
        /// <summary>
        /// Updates an <see cref="AS4Message"/> for delivery and notification.
        /// </summary>
        /// <param name="as4Message">The message.</param>
        /// <param name="receivingPMode"></param>
        /// <param name="messageBodyStore">The as4 message body persister.</param>
        /// <param name="sendingPMode"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <returns></returns>
        public void UpdateAS4MessageForMessageHandling(
            AS4Message as4Message,
            SendingProcessingMode sendingPMode,
            ReceivingProcessingMode receivingPMode,
            IAS4MessageBodyStore messageBodyStore)
        {
            if (as4Message == null)
            {
                throw new ArgumentNullException(nameof(as4Message));
            }

            if (messageBodyStore == null)
            {
                throw new ArgumentNullException(nameof(messageBodyStore));
            }

            if (as4Message.HasUserMessage)
            {
                string savedLocation =
                    messageBodyStore.SaveAS4Message(_configuration.InMessageStoreLocation, as4Message);

                IEnumerable <string> userMessageIds = as4Message.UserMessages.Select(u => u.MessageId);

                _repository.UpdateInMessages(
                    m => userMessageIds.Any(id => id == m.EbmsMessageId),
                    m => m.MessageLocation = savedLocation);
            }

            if (receivingPMode?.MessageHandling?.MessageHandlingType == MessageHandlingChoiceType.Forward)
            {
                Logger.Debug($"Received AS4Message must be forwarded since the ReceivingPMode {receivingPMode?.Id} MessageHandling has a <Forward/> element");

                string pmodeString = AS4XmlSerializer.ToString(receivingPMode);
                string pmodeId     = receivingPMode.Id;

                // Only set the Operation of the InMessage that represents the
                // Primary Message-Unit to 'ToBeForwarded' since we want to prevent
                // that the same message is forwarded more than once (x number of messaging units
                // present in the AS4 Message).

                _repository.UpdateInMessages(
                    m => as4Message.MessageIds.Contains(m.EbmsMessageId),
                    m =>
                {
                    m.Intermediary = true;
                    m.SetPModeInformation(pmodeId, pmodeString);
                    Logger.Debug($"Update InMessage {m.EbmsMessageType} with {{Intermediary={m.Intermediary}, PMode={pmodeId}}}");
                });

                _repository.UpdateInMessage(
                    as4Message.GetPrimaryMessageId(),
                    m =>
                {
                    m.Operation = Operation.ToBeForwarded;
                    Logger.Debug($"Update InMessage {m.EbmsMessageType} with Operation={m.Operation}");
                });
            }
            else if (receivingPMode?.MessageHandling?.MessageHandlingType == MessageHandlingChoiceType.Deliver)
            {
                UpdateUserMessagesForDelivery(as4Message.UserMessages, receivingPMode);
                UpdateSignalMessagesForNotification(as4Message.SignalMessages, sendingPMode);
            }
            else
            {
                UpdateSignalMessagesForNotification(as4Message.SignalMessages, sendingPMode);
            }
        }
Пример #17
0
        /// <summary>
        /// Selects the available <see cref="SignalMessage"/>s that are ready to be bundled (PiggyBacked) with the given <see cref="PullRequest"/>.
        /// </summary>
        /// <param name="pr">The <see cref="PullRequest"/> for which a selection of <see cref="SignalMessage"/>s are returned.</param>
        /// <param name="sendingPMode">The sending configuration used to select <see cref="SignalMessage"/>s with the same configuration.</param>
        /// <param name="bodyStore">The body store at which the <see cref="SignalMessage"/>s are persisted.</param>
        /// <returns>
        ///     An subsection of the <see cref="SignalMessage"/>s where the referenced send <see cref="UserMessage"/> matches the given <paramref name="pr"/>
        ///     and where the sending configuration given in the <paramref name="sendingPMode"/> matches the stored <see cref="SignalMessage"/> sending configuration.
        /// </returns>
        internal async Task <IEnumerable <SignalMessage> > SelectToBePiggyBackedSignalMessagesAsync(
            PullRequest pr,
            SendingProcessingMode sendingPMode,
            IAS4MessageBodyStore bodyStore)
        {
            if (pr == null)
            {
                throw new ArgumentNullException(nameof(pr));
            }

            if (sendingPMode == null)
            {
                throw new ArgumentNullException(nameof(sendingPMode));
            }

            if (bodyStore == null)
            {
                throw new ArgumentNullException(nameof(bodyStore));
            }

            string url = sendingPMode.PushConfiguration?.Protocol?.Url;

            if (String.IsNullOrWhiteSpace(url))
            {
                throw new ArgumentException(
                          @"SendingPMode.PushConfiguration.Protocol.Url cannot be blank",
                          nameof(sendingPMode.PushConfiguration.Protocol.Url));
            }

            bool pullRequestSigned = sendingPMode.Security?.Signing?.IsEnabled == true;

            return(await _context.TransactionalAsync(async db =>
            {
                IEnumerable <OutMessage> query =
                    db.NativeCommands
                    .SelectToBePiggyBackedSignalMessages(url, pr.Mpc);

                var toBePiggyBackedSignals = new Collection <MessageUnit>();
                foreach (OutMessage found in query)
                {
                    Stream body = await bodyStore.LoadMessageBodyAsync(found.MessageLocation);
                    AS4Message signal =
                        await SerializerProvider
                        .Default
                        .Get(found.ContentType)
                        .DeserializeAsync(body, found.ContentType);

                    var toBePiggyBacked = signal.SignalMessages.FirstOrDefault(s => s.MessageId == found.EbmsMessageId);
                    if (toBePiggyBacked is Receipt || toBePiggyBacked is Error)
                    {
                        if (!pullRequestSigned && signal.IsSigned)
                        {
                            Logger.Warn(
                                $"Can't PiggyBack {toBePiggyBacked.GetType().Name} {toBePiggyBacked.MessageId} because SignalMessage is signed "
                                + $"while the SendingPMode {sendingPMode.Id} used is not configured for signing");
                        }
                        else
                        {
                            found.Operation = Operation.Sending;
                            toBePiggyBackedSignals.Add(toBePiggyBacked);
                        }
                    }
                    else if (toBePiggyBacked != null)
                    {
                        Logger.Warn(
                            $"Will not select {toBePiggyBacked.GetType().Name} {toBePiggyBacked.MessageId} "
                            + "for PiggyBacking because only Receipts and Errors are allowed SignalMessages to be PiggyBacked with PullRequests");
                    }
                    else
                    {
                        Logger.Warn("Will not select AS4Message for PiggyBacking because it doesn't contains any Message Units");
                    }
                }

                if (toBePiggyBackedSignals.Any())
                {
                    await db.SaveChangesAsync()
                    .ConfigureAwait(false);
                }

                return toBePiggyBackedSignals.Cast <SignalMessage>().AsEnumerable();
            }));
        }