using Azure.Storage.Queues; using Bit.Core.Platform.Push; using Bit.Core.Platform.Push.Internal; using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.Extensions.DependencyInjection.Extensions; namespace Microsoft.Extensions.DependencyInjection; /// /// Extension methods for adding the Push feature. /// public static class PushServiceCollectionExtensions { /// /// Adds a to the services that can be used to send push notifications to /// end user devices. This method is safe to be ran multiple time provided does not /// change between calls. /// /// The to add services to. /// The to use to configure services. /// The for additional chaining. public static IServiceCollection AddPush(this IServiceCollection services, GlobalSettings globalSettings) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(globalSettings); services.TryAddSingleton(TimeProvider.System); services.TryAddSingleton(); if (globalSettings.SelfHosted) { if (globalSettings.Installation.Id == Guid.Empty) { throw new InvalidOperationException("Installation Id must be set for self-hosted installations."); } if (CoreHelpers.SettingHasValue(globalSettings.PushRelayBaseUri) && CoreHelpers.SettingHasValue(globalSettings.Installation.Key)) { // TODO: We should really define the HttpClient we will use here services.AddHttpClient(); services.AddHttpContextAccessor(); // We also depend on IDeviceRepository but don't explicitly add it right now. services.TryAddEnumerable(ServiceDescriptor.Singleton()); } if (CoreHelpers.SettingHasValue(globalSettings.InternalIdentityKey) && CoreHelpers.SettingHasValue(globalSettings.BaseServiceUri.InternalNotifications)) { // TODO: We should really define the HttpClient we will use here services.AddHttpClient(); services.AddHttpContextAccessor(); services.TryAddEnumerable(ServiceDescriptor.Singleton()); } } else { services.TryAddSingleton(); services.AddHttpContextAccessor(); // We also depend on IInstallationDeviceRepository but don't explicitly add it right now. services.TryAddEnumerable(ServiceDescriptor.Singleton()); services.TryAddSingleton(); if (CoreHelpers.SettingHasValue(globalSettings.Notifications?.ConnectionString)) { services.TryAddKeyedSingleton("notifications", static (sp, _) => { var gs = sp.GetRequiredService(); return new QueueClient(gs.Notifications.ConnectionString, "notifications"); }); // We not IHttpContextAccessor will be added above, no need to do it here. services.TryAddEnumerable(ServiceDescriptor.Singleton()); } } return services; } }