Skip to content

Commit ad19d3d

Browse files
[PM-17562] Add feature flag for event-based organization integrations (#5710)
* Added EventBasedOrganizationIntegrations feature flag; Added enforcement of flag at the API layer * [PM-17562] Use EventBasedOrganizationIntegrations feature flag to turn on/off event queue * Optimization that removes the need for EventRouteService (from @justindbaur)
1 parent 9a7fddd commit ad19d3d

File tree

6 files changed

+46
-10
lines changed

6 files changed

+46
-10
lines changed

src/Api/AdminConsole/Controllers/OrganizationIntegrationConfigurationController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
using Bit.Api.AdminConsole.Models.Request.Organizations;
22
using Bit.Api.AdminConsole.Models.Response.Organizations;
3+
using Bit.Core;
34
using Bit.Core.Context;
45
using Bit.Core.Exceptions;
56
using Bit.Core.Repositories;
7+
using Bit.Core.Utilities;
68
using Microsoft.AspNetCore.Authorization;
79
using Microsoft.AspNetCore.Mvc;
810

911
namespace Bit.Api.AdminConsole.Controllers;
1012

13+
[RequireFeature(FeatureFlagKeys.EventBasedOrganizationIntegrations)]
1114
[Route("organizations/{organizationId:guid}/integrations/{integrationId:guid}/configurations")]
1215
[Authorize("Application")]
1316
public class OrganizationIntegrationConfigurationController(

src/Api/AdminConsole/Controllers/OrganizationIntegrationController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
using Bit.Api.AdminConsole.Models.Request.Organizations;
22
using Bit.Api.AdminConsole.Models.Response.Organizations;
3+
using Bit.Core;
34
using Bit.Core.Context;
45
using Bit.Core.Exceptions;
56
using Bit.Core.Repositories;
7+
using Bit.Core.Utilities;
68
using Microsoft.AspNetCore.Authorization;
79
using Microsoft.AspNetCore.Mvc;
810

911
#nullable enable
1012

1113
namespace Bit.Api.AdminConsole.Controllers;
1214

15+
[RequireFeature(FeatureFlagKeys.EventBasedOrganizationIntegrations)]
1316
[Route("organizations/{organizationId:guid}/integrations")]
1417
[Authorize("Application")]
1518
public class OrganizationIntegrationController(

src/Api/AdminConsole/Controllers/SlackIntegrationController.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
using System.Text.Json;
22
using Bit.Api.AdminConsole.Models.Response.Organizations;
3+
using Bit.Core;
34
using Bit.Core.AdminConsole.Entities;
45
using Bit.Core.Context;
56
using Bit.Core.Enums;
67
using Bit.Core.Exceptions;
78
using Bit.Core.Models.Data.Integrations;
89
using Bit.Core.Repositories;
910
using Bit.Core.Services;
11+
using Bit.Core.Utilities;
1012
using Microsoft.AspNetCore.Authorization;
1113
using Microsoft.AspNetCore.Mvc;
1214

1315
namespace Bit.Api.AdminConsole.Controllers;
1416

17+
[RequireFeature(FeatureFlagKeys.EventBasedOrganizationIntegrations)]
1518
[Route("organizations/{organizationId:guid}/integrations/slack")]
1619
[Authorize("Application")]
1720
public class SlackIntegrationController(

src/Core/Constants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public static class FeatureFlagKeys
108108
public const string PolicyRequirements = "pm-14439-policy-requirements";
109109
public const string SsoExternalIdVisibility = "pm-18630-sso-external-id-visibility";
110110
public const string ScimInviteUserOptimization = "pm-16811-optimize-invite-user-flow-to-fail-fast";
111+
public const string EventBasedOrganizationIntegrations = "event-based-organization-integrations";
111112

112113
/* Auth Team */
113114
public const string PM9112DeviceApprovalPersistence = "pm-9112-device-approval-persistence";

src/Events/Startup.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Globalization;
2+
using Bit.Core;
23
using Bit.Core.AdminConsole.Services.Implementations;
34
using Bit.Core.AdminConsole.Services.NoopImplementations;
45
using Bit.Core.Context;
@@ -62,33 +63,45 @@ public void ConfigureServices(IServiceCollection services)
6263
{
6364
services.AddSingleton<IApplicationCacheService, InMemoryApplicationCacheService>();
6465
}
65-
services.AddScoped<IEventService, EventService>();
66+
6667
if (!globalSettings.SelfHosted && CoreHelpers.SettingHasValue(globalSettings.Events.ConnectionString))
6768
{
69+
services.AddKeyedSingleton<IEventWriteService, AzureQueueEventWriteService>("storage");
70+
6871
if (CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.ConnectionString) &&
6972
CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.TopicName))
7073
{
71-
services.AddSingleton<IEventWriteService, AzureServiceBusEventWriteService>();
74+
services.AddKeyedSingleton<IEventWriteService, AzureServiceBusEventWriteService>("broadcast");
7275
}
7376
else
7477
{
75-
services.AddSingleton<IEventWriteService, AzureQueueEventWriteService>();
78+
services.AddKeyedSingleton<IEventWriteService, NoopEventWriteService>("broadcast");
7679
}
7780
}
7881
else
7982
{
83+
services.AddKeyedSingleton<IEventWriteService, RepositoryEventWriteService>("storage");
84+
8085
if (CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.HostName) &&
8186
CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.Username) &&
8287
CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.Password) &&
8388
CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.ExchangeName))
8489
{
85-
services.AddSingleton<IEventWriteService, RabbitMqEventWriteService>();
90+
services.AddKeyedSingleton<IEventWriteService, RabbitMqEventWriteService>("broadcast");
8691
}
8792
else
8893
{
89-
services.AddSingleton<IEventWriteService, RepositoryEventWriteService>();
94+
services.AddKeyedSingleton<IEventWriteService, NoopEventWriteService>("broadcast");
9095
}
9196
}
97+
services.AddScoped<IEventWriteService>(sp =>
98+
{
99+
var featureService = sp.GetRequiredService<IFeatureService>();
100+
var key = featureService.IsEnabled(FeatureFlagKeys.EventBasedOrganizationIntegrations)
101+
? "broadcast" : "storage";
102+
return sp.GetRequiredKeyedService<IEventWriteService>(key);
103+
});
104+
services.AddScoped<IEventService, EventService>();
92105

93106
services.AddOptionality();
94107

src/SharedWeb/Utilities/ServiceCollectionExtensions.cs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Security.Cryptography.X509Certificates;
55
using AspNetCoreRateLimit;
66
using Azure.Storage.Queues;
7+
using Bit.Core;
78
using Bit.Core.AdminConsole.Models.Business.Tokenables;
89
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
910
using Bit.Core.AdminConsole.Services;
@@ -332,34 +333,46 @@ public static void AddDefaultServices(this IServiceCollection services, GlobalSe
332333

333334
if (!globalSettings.SelfHosted && CoreHelpers.SettingHasValue(globalSettings.Events.ConnectionString))
334335
{
336+
services.AddKeyedSingleton<IEventWriteService, AzureQueueEventWriteService>("storage");
337+
335338
if (CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.ConnectionString) &&
336339
CoreHelpers.SettingHasValue(globalSettings.EventLogging.AzureServiceBus.TopicName))
337340
{
338-
services.AddSingleton<IEventWriteService, AzureServiceBusEventWriteService>();
341+
services.AddKeyedSingleton<IEventWriteService, AzureServiceBusEventWriteService>("broadcast");
339342
}
340343
else
341344
{
342-
services.AddSingleton<IEventWriteService, AzureQueueEventWriteService>();
345+
services.AddKeyedSingleton<IEventWriteService, NoopEventWriteService>("broadcast");
343346
}
344347
}
345348
else if (globalSettings.SelfHosted)
346349
{
350+
services.AddKeyedSingleton<IEventWriteService, RepositoryEventWriteService>("storage");
351+
347352
if (CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.HostName) &&
348353
CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.Username) &&
349354
CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.Password) &&
350355
CoreHelpers.SettingHasValue(globalSettings.EventLogging.RabbitMq.ExchangeName))
351356
{
352-
services.AddSingleton<IEventWriteService, RabbitMqEventWriteService>();
357+
services.AddKeyedSingleton<IEventWriteService, RabbitMqEventWriteService>("broadcast");
353358
}
354359
else
355360
{
356-
services.AddSingleton<IEventWriteService, RepositoryEventWriteService>();
361+
services.AddKeyedSingleton<IEventWriteService, NoopEventWriteService>("broadcast");
357362
}
358363
}
359364
else
360365
{
361-
services.AddSingleton<IEventWriteService, NoopEventWriteService>();
366+
services.AddKeyedSingleton<IEventWriteService, NoopEventWriteService>("storage");
367+
services.AddKeyedSingleton<IEventWriteService, NoopEventWriteService>("broadcast");
362368
}
369+
services.AddScoped<IEventWriteService>(sp =>
370+
{
371+
var featureService = sp.GetRequiredService<IFeatureService>();
372+
var key = featureService.IsEnabled(FeatureFlagKeys.EventBasedOrganizationIntegrations)
373+
? "broadcast" : "storage";
374+
return sp.GetRequiredKeyedService<IEventWriteService>(key);
375+
});
363376

364377
if (CoreHelpers.SettingHasValue(globalSettings.Attachment.ConnectionString))
365378
{

0 commit comments

Comments
 (0)