public void MutateIncoming(TransportMessage transportMessage) { var messageTypeString = GetSubscriptionMessageTypeFrom(transportMessage); var intent = transportMessage.MessageIntent; if (string.IsNullOrEmpty(messageTypeString) && intent != MessageIntentEnum.Subscribe && intent != MessageIntentEnum.Unsubscribe) { return; } if (string.IsNullOrEmpty(messageTypeString)) { throw new InvalidOperationException("Message intent is Subscribe, but the subscription message type header is missing!"); } if (intent != MessageIntentEnum.Subscribe && intent != MessageIntentEnum.Unsubscribe) { throw new InvalidOperationException("Subscription messages need to have intent set to Subscribe/Unsubscribe"); } var subscriberAddress = transportMessage.ReplyToAddress; if (subscriberAddress == null || subscriberAddress == Address.Undefined) { throw new InvalidOperationException("Subscription message arrived without a valid ReplyToAddress"); } if (SubscriptionStorage == null) { var warning = string.Format("Subscription message from {0} arrived at this endpoint, yet this endpoint is not configured to be a publisher. To avoid this warning make this endpoint a publisher by configuring a subscription storage or using the AsA_Publisher role.", subscriberAddress); Logger.WarnFormat(warning); if (Debugger.IsAttached) // only under debug, so that we don't expose ourselves to a denial of service { throw new InvalidOperationException(warning); // and cause message to go to error queue by throwing an exception } return; } //service locate to avoid a circular dependency Builder.Build <IBus>().DoNotContinueDispatchingCurrentMessageToHandlers(); if (transportMessage.MessageIntent == MessageIntentEnum.Subscribe) { if (!SubscriptionAuthorizer.AuthorizeSubscribe(messageTypeString, subscriberAddress.ToString(), transportMessage.Headers)) { Logger.Debug(string.Format("Subscription request from {0} on message type {1} was refused.", subscriberAddress, messageTypeString)); } else { Logger.Info("Subscribing " + subscriberAddress + " to message type " + messageTypeString); var mt = new MessageType(messageTypeString); SubscriptionStorage.Subscribe(transportMessage.ReplyToAddress, new[] { mt }); if (ClientSubscribed != null) { ClientSubscribed(this, new SubscriptionEventArgs { MessageType = messageTypeString, SubscriberReturnAddress = subscriberAddress }); } } return; } if (!SubscriptionAuthorizer.AuthorizeUnsubscribe(messageTypeString, subscriberAddress.ToString(), transportMessage.Headers)) { Logger.Debug(string.Format("Unsubscribe request from {0} on message type {1} was refused.", subscriberAddress, messageTypeString)); return; } Logger.Info("Unsubscribing " + subscriberAddress + " from message type " + messageTypeString); SubscriptionStorage.Unsubscribe(subscriberAddress, new[] { new MessageType(messageTypeString) }); }
/// <summary> /// Set a <see cref="SubscriptionAuthorizer"/> to be used when verifying a <see cref="MessageIntentEnum.Subscribe"/> or <see cref="MessageIntentEnum.Unsubscribe"/> message. /// </summary> /// <remarks>This is a "single instance" extension point. So calling this api multiple time will result in only the last one added being executed at message receive time.</remarks> /// <param name="transportExtensions">The <see cref="TransportExtensions"/> to extend.</param> /// <param name="authorizer">The <see cref="SubscriptionAuthorizer"/> to execute.</param> public static void SubscriptionAuthorizer(this TransportExtensions transportExtensions, SubscriptionAuthorizer authorizer) { Guard.AgainstNull(nameof(authorizer), authorizer); var settings = transportExtensions.Settings; var transport = settings.Get <TransportDefinition>(); if (transport.GetOutboundRoutingPolicy(settings).Publishes == OutboundRoutingType.Multicast) { var message = $"The transport {transport.GetType().Name} supports native publish-subscribe so subscriptions are not managed by the transport in the publishing endpoint. Use the native transport tools managing subscritions."; throw new ArgumentException(message, nameof(authorizer)); } settings.Set <SubscriptionAuthorizer>(authorizer); }