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); }
/// <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)); }
/// <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; }
private async Task <Stream> TryLoadMessageBody(IAS4MessageBodyStore store) { try { return(await store.LoadMessageBodyAsync(MessageLocation)); } catch (Exception exception) { LogManager.GetCurrentClassLogger().Error(exception.Message); return(null); } }
/// <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; }
/// <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; }
/// <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; } }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
/// <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) { }
/// <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); } }
/// <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(); })); }