Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.ComponentModel.DataAnnotations;
using Bit.Core;
using Bit.Core.AdminConsole.AbilitiesCache;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider;
Expand Down Expand Up @@ -59,6 +60,7 @@ public class ProviderService : IProviderService
private readonly IStripeAdapter _stripeAdapter;
private readonly IDataProtectorTokenFactory<ProviderDeleteTokenable> _providerDeleteTokenDataFactory;
private readonly IApplicationCacheService _applicationCacheService;
private readonly IProviderAbilityCacheService _providerAbilityCacheService;
private readonly IProviderBillingService _providerBillingService;
private readonly IPricingClient _pricingClient;
private readonly IProviderClientOrganizationSignUpCommand _providerClientOrganizationSignUpCommand;
Expand All @@ -71,7 +73,8 @@ public ProviderService(IProviderRepository providerRepository, IProviderUserRepo
IOrganizationRepository organizationRepository, GlobalSettings globalSettings,
ICurrentContext currentContext, IStripeAdapter stripeAdapter,
IDataProtectorTokenFactory<ProviderDeleteTokenable> providerDeleteTokenDataFactory,
IApplicationCacheService applicationCacheService, IProviderBillingService providerBillingService, IPricingClient pricingClient,
IApplicationCacheService applicationCacheService, IProviderAbilityCacheService providerAbilityCacheService,
IProviderBillingService providerBillingService, IPricingClient pricingClient,
IProviderClientOrganizationSignUpCommand providerClientOrganizationSignUpCommand,
IPolicyRequirementQuery policyRequirementQuery)
{
Expand All @@ -90,6 +93,7 @@ public ProviderService(IProviderRepository providerRepository, IProviderUserRepo
_stripeAdapter = stripeAdapter;
_providerDeleteTokenDataFactory = providerDeleteTokenDataFactory;
_applicationCacheService = applicationCacheService;
_providerAbilityCacheService = providerAbilityCacheService;
_providerBillingService = providerBillingService;
_pricingClient = pricingClient;
_providerClientOrganizationSignUpCommand = providerClientOrganizationSignUpCommand;
Expand Down Expand Up @@ -707,7 +711,7 @@ public async Task DeleteAsync(Provider provider, string token)
public async Task DeleteAsync(Provider provider)
{
await _providerRepository.DeleteAsync(provider);
await _applicationCacheService.DeleteProviderAbilityAsync(provider.Id);
await _providerAbilityCacheService.DeleteProviderAbilityAsync(provider.Id);
}

private async Task SendInviteAsync(ProviderUser providerUser, Provider provider)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ο»Ώusing Bit.Commercial.Core.AdminConsole.Services;
using Bit.Commercial.Core.Test.AdminConsole.AutoFixture;
using Bit.Core.AdminConsole.AbilitiesCache;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider;
Expand Down Expand Up @@ -1245,12 +1246,12 @@ await sutProvider.GetDependency<IOrganizationService>()
public async Task Delete_Success(Provider provider, SutProvider<ProviderService> sutProvider)
{
var providerRepository = sutProvider.GetDependency<IProviderRepository>();
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();
var providerAbilityCacheService = sutProvider.GetDependency<IProviderAbilityCacheService>();

await sutProvider.Sut.DeleteAsync(provider);

await providerRepository.Received().DeleteAsync(provider);
await applicationCacheService.Received().DeleteProviderAbilityAsync(provider.Id);
await providerAbilityCacheService.Received().DeleteProviderAbilityAsync(provider.Id);
}

[Theory, BitAutoData]
Expand Down
10 changes: 5 additions & 5 deletions src/Admin/AdminConsole/Controllers/ProvidersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Bit.Admin.Enums;
using Bit.Admin.Services;
using Bit.Admin.Utilities;
using Bit.Core.AdminConsole.AbilitiesCache;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
Expand All @@ -25,7 +26,6 @@
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -48,7 +48,7 @@ public class ProvidersController : Controller
private readonly IProviderOrganizationRepository _providerOrganizationRepository;
private readonly IProviderService _providerService;
private readonly GlobalSettings _globalSettings;
private readonly IApplicationCacheService _applicationCacheService;
private readonly IProviderAbilityCacheService _providerAbilityCacheService;
private readonly ICreateProviderCommand _createProviderCommand;
private readonly IProviderPlanRepository _providerPlanRepository;
private readonly IProviderBillingService _providerBillingService;
Expand All @@ -65,7 +65,7 @@ public ProvidersController(IOrganizationRepository organizationRepository,
IProviderOrganizationRepository providerOrganizationRepository,
IProviderService providerService,
GlobalSettings globalSettings,
IApplicationCacheService applicationCacheService,
IProviderAbilityCacheService providerAbilityCacheService,
ICreateProviderCommand createProviderCommand,
IProviderPlanRepository providerPlanRepository,
IProviderBillingService providerBillingService,
Expand All @@ -83,7 +83,7 @@ public ProvidersController(IOrganizationRepository organizationRepository,
_providerOrganizationRepository = providerOrganizationRepository;
_providerService = providerService;
_globalSettings = globalSettings;
_applicationCacheService = applicationCacheService;
_providerAbilityCacheService = providerAbilityCacheService;
_createProviderCommand = createProviderCommand;
_providerPlanRepository = providerPlanRepository;
_providerBillingService = providerBillingService;
Expand Down Expand Up @@ -325,7 +325,7 @@ public async Task<IActionResult> Edit(Guid id, ProviderEditModel model)
? model.Enabled : originalProviderStatus;

await _providerService.UpdateAsync(provider);
await _applicationCacheService.UpsertProviderAbilityAsync(provider);
await _providerAbilityCacheService.UpsertProviderAbilityAsync(provider);

// Sync billing email changes to Stripe
if (!string.IsNullOrEmpty(provider.GatewayCustomerId) && originalBillingEmail != provider.BillingEmail)
Expand Down
1 change: 0 additions & 1 deletion src/Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ public static class FeatureFlagKeys
public const string PublicMembersInviteRefactor = "pm-33398-refactor-members-invite-org-users-command";
public const string GenerateInviteLink = "pm-32497-generate-invite-link";
public const string OrgAbilityExtendedCache = "pm-32104-org-ability-extended-cache";
public const string ProviderAbilityExtendedCache = "pm-32111-provider-ability-extended-cache";
public const string PolicyDrawers = "pm-34804-policy-drawers";
public const string PM35153CollectionSdkDecryption = "pm-35153-collection-sdk-decryption";
public const string PoliciesInAcceptedState = "pm-34145-policies-in-accepted-state";
Expand Down
10 changes: 7 additions & 3 deletions src/Core/Dirt/Services/Implementations/EventService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ο»Ώ// FIXME: Update this file to be null safe and then delete the line below
#nullable disable

using Bit.Core.AdminConsole.AbilitiesCache;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Interfaces;
Expand All @@ -25,6 +26,7 @@ public class EventService : IEventService
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly IProviderUserRepository _providerUserRepository;
private readonly IApplicationCacheService _applicationCacheService;
private readonly IProviderAbilityCacheService _providerAbilityCacheService;
private readonly ICurrentContext _currentContext;
private readonly GlobalSettings _globalSettings;

Expand All @@ -33,13 +35,15 @@ public EventService(
IOrganizationUserRepository organizationUserRepository,
IProviderUserRepository providerUserRepository,
IApplicationCacheService applicationCacheService,
IProviderAbilityCacheService providerAbilityCacheService,
ICurrentContext currentContext,
GlobalSettings globalSettings)
{
_eventWriteService = eventWriteService;
_organizationUserRepository = organizationUserRepository;
_providerUserRepository = providerUserRepository;
_applicationCacheService = applicationCacheService;
_providerAbilityCacheService = providerAbilityCacheService;
_currentContext = currentContext;
_globalSettings = globalSettings;
}
Expand Down Expand Up @@ -92,7 +96,7 @@ public async Task LogUserEventAsync(Guid userId, EventType type, DateTime? date
}

var providers = await _currentContext.ProviderMembershipAsync(_providerUserRepository, userId);
var providerAbilities = await _applicationCacheService.GetProviderAbilitiesAsync(providers.Select(provider => provider.Id));
var providerAbilities = await _providerAbilityCacheService.GetProviderAbilitiesAsync(providers.Select(provider => provider.Id));
var providerEvents = providers.Where(o => CanUseProviderEvents(providerAbilities, o.Id))
.Select(p => new EventMessage(_currentContext)
{
Expand Down Expand Up @@ -383,7 +387,7 @@ public async Task LogProviderUserEventAsync(ProviderUser providerUser, EventType
public async Task LogProviderUsersEventAsync(IEnumerable<(ProviderUser, EventType, DateTime?)> events)
{
var materializedEvents = events.ToList();
var providerAbilities = await _applicationCacheService.GetProviderAbilitiesAsync(
var providerAbilities = await _providerAbilityCacheService.GetProviderAbilitiesAsync(
materializedEvents.Select(materializedEvent => materializedEvent.Item1.ProviderId));
var eventMessages = new List<IEvent>();
foreach (var (providerUser, type, date) in materializedEvents)
Expand Down Expand Up @@ -415,7 +419,7 @@ public async Task LogProviderOrganizationEventAsync(ProviderOrganization provide
public async Task LogProviderOrganizationEventsAsync(IEnumerable<(ProviderOrganization, EventType, DateTime?)> events)
{
var materializedEvents = events.ToList();
var providerAbilities = await _applicationCacheService.GetProviderAbilitiesAsync(
var providerAbilities = await _providerAbilityCacheService.GetProviderAbilitiesAsync(
materializedEvents.Select(materializedEvent => materializedEvent.Item1.ProviderId));
var eventMessages = new List<IEvent>();
foreach (var (providerOrganization, type, date) in materializedEvents)
Expand Down
16 changes: 0 additions & 16 deletions src/Core/Services/IApplicationCacheService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
ο»Ώusing Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.Models.Data.Organizations;

Expand All @@ -11,31 +10,16 @@ public interface IApplicationCacheService
Task<IDictionary<Guid, OrganizationAbility>> GetOrganizationAbilitiesAsync();
#nullable enable
Task<OrganizationAbility?> GetOrganizationAbilityAsync(Guid orgId);
/// <summary>
/// Gets the cached <see cref="ProviderAbility"/> for the specified provider.
/// </summary>
/// <param name="providerId">The ID of the provider.</param>
/// <returns>The <see cref="ProviderAbility"/> if found; otherwise, <c>null</c>.</returns>
Task<ProviderAbility?> GetProviderAbilityAsync(Guid providerId);
#nullable disable
[Obsolete("We are transitioning to a new cache pattern. Please consult the Admin Console team before using.", false)]
Task<IDictionary<Guid, ProviderAbility>> GetProviderAbilitiesAsync();
/// <summary>
/// Gets cached <see cref="ProviderAbility"/> entries for the specified providers.
/// Provider IDs not found in the cache are silently excluded from the result.
/// </summary>
/// <param name="providerIds">The IDs of the providers to look up.</param>
/// <returns>A dictionary mapping each found provider ID to its <see cref="ProviderAbility"/>.</returns>
Task<IDictionary<Guid, ProviderAbility>> GetProviderAbilitiesAsync(IEnumerable<Guid> providerIds);
/// <summary>
/// Gets cached <see cref="OrganizationAbility"/> entries for the specified organizations.
/// Organization IDs not found in the cache are silently excluded from the result.
/// </summary>
/// <param name="orgIds">The IDs of the organizations to look up.</param>
/// <returns>A dictionary mapping each found organization ID to its <see cref="OrganizationAbility"/>.</returns>
Task<IDictionary<Guid, OrganizationAbility>> GetOrganizationAbilitiesAsync(IEnumerable<Guid> orgIds);
Task UpsertOrganizationAbilityAsync(Organization organization);
Task UpsertProviderAbilityAsync(Provider provider);
Task DeleteOrganizationAbilityAsync(Guid organizationId);
Task DeleteProviderAbilityAsync(Guid providerId);
}
47 changes: 0 additions & 47 deletions src/Core/Services/Implementations/FeatureRoutedCacheService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
ο»Ώusing Bit.Core.AdminConsole.AbilitiesCache;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Models.Data.Provider;
using Bit.Core.Models.Data.Organizations;

Expand All @@ -9,7 +8,6 @@ namespace Bit.Core.Services.Implementations;
public class FeatureRoutedCacheService(
IVCurrentInMemoryApplicationCacheService inMemoryApplicationCacheService,
IOrganizationAbilityCacheService extendedOrgAbilityCacheService,
IProviderAbilityCacheService providerAbilityCacheService,
IFeatureService featureService)
: IApplicationCacheService
{
Expand All @@ -24,31 +22,6 @@ public Task<IDictionary<Guid, OrganizationAbility>> GetOrganizationAbilitiesAsyn
public Task<IDictionary<Guid, ProviderAbility>> GetProviderAbilitiesAsync() =>
inMemoryApplicationCacheService.GetProviderAbilitiesAsync();

public async Task<ProviderAbility?> GetProviderAbilityAsync(Guid providerId)
{
if (featureService.IsEnabled(FeatureFlagKeys.ProviderAbilityExtendedCache))
{
return await providerAbilityCacheService.GetProviderAbilityAsync(providerId);
}

(await GetProviderAbilitiesAsync([providerId])).TryGetValue(providerId, out var providerAbility);
return providerAbility;
}

public async Task<IDictionary<Guid, ProviderAbility>> GetProviderAbilitiesAsync(IEnumerable<Guid> providerIds)
{
if (featureService.IsEnabled(FeatureFlagKeys.ProviderAbilityExtendedCache))
{
return await providerAbilityCacheService.GetProviderAbilitiesAsync(providerIds);
}

var allProviderAbilities = await inMemoryApplicationCacheService.GetProviderAbilitiesAsync();
return providerIds
.Distinct()
.Where(allProviderAbilities.ContainsKey)
.ToDictionary(id => id, id => allProviderAbilities[id]);
}

public async Task<IDictionary<Guid, OrganizationAbility>> GetOrganizationAbilitiesAsync(IEnumerable<Guid> orgIds)
{
if (featureService.IsEnabled(FeatureFlagKeys.OrgAbilityExtendedCache))
Expand All @@ -68,31 +41,11 @@ public Task UpsertOrganizationAbilityAsync(Organization organization) =>
? extendedOrgAbilityCacheService.UpsertOrganizationAbilityAsync(organization)
: inMemoryApplicationCacheService.UpsertOrganizationAbilityAsync(organization);

public Task UpsertProviderAbilityAsync(Provider provider)
{
if (featureService.IsEnabled(FeatureFlagKeys.ProviderAbilityExtendedCache))
{
return providerAbilityCacheService.UpsertProviderAbilityAsync(provider);
}

return inMemoryApplicationCacheService.UpsertProviderAbilityAsync(provider);
}

public Task DeleteOrganizationAbilityAsync(Guid organizationId) =>
featureService.IsEnabled(FeatureFlagKeys.OrgAbilityExtendedCache)
? extendedOrgAbilityCacheService.DeleteOrganizationAbilityAsync(organizationId)
: inMemoryApplicationCacheService.DeleteOrganizationAbilityAsync(organizationId);

public Task DeleteProviderAbilityAsync(Guid providerId)
{
if (featureService.IsEnabled(FeatureFlagKeys.ProviderAbilityExtendedCache))
{
return providerAbilityCacheService.DeleteProviderAbilityAsync(providerId);
}

return inMemoryApplicationCacheService.DeleteProviderAbilityAsync(providerId);
}

public async Task BaseUpsertOrganizationAbilityAsync(Organization organization)
{
if (featureService.IsEnabled(FeatureFlagKeys.OrgAbilityExtendedCache))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
using Bit.Api.AdminConsole.Models.Request.Providers;
using Bit.Api.IntegrationTest.Factories;
using Bit.Api.IntegrationTest.Helpers;
using Bit.Core;
using Bit.Core.AdminConsole.AbilitiesCache;
using Bit.Core.AdminConsole.Entities.Provider;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Repositories;
using Bit.Core.Services;
using NSubstitute;
using Xunit;

namespace Bit.Api.IntegrationTest.AdminConsole.Controllers;
Expand All @@ -25,12 +23,6 @@ public class ProviderAbilityCacheTests : IClassFixture<ApiApplicationFactory>, I
public ProviderAbilityCacheTests(ApiApplicationFactory factory)
{
_factory = factory;
_factory.SubstituteService<IFeatureService>(featureService =>
{
featureService
.IsEnabled(FeatureFlagKeys.ProviderAbilityExtendedCache)
.Returns(true);
});
_client = factory.CreateClient();
_loginHelper = new LoginHelper(_factory, _client);
}
Expand Down Expand Up @@ -87,7 +79,7 @@ public async Task Put_UpdatesProvider_CacheReflectsUpdatedValues()
// Assert - endpoint succeeded and cache was populated
Assert.Equal(HttpStatusCode.OK, response.StatusCode);

var cacheService = _factory.GetService<IApplicationCacheService>();
var cacheService = _factory.GetService<IProviderAbilityCacheService>();
var ability = await cacheService.GetProviderAbilityAsync(_provider.Id);
Assert.NotNull(ability);
Assert.Equal(_provider.Id, ability.Id);
Expand All @@ -97,7 +89,7 @@ public async Task Put_UpdatesProvider_CacheReflectsUpdatedValues()
public async Task Delete_RemovesProvider_CacheReturnsNull()
{
// Arrange - populate the cache before deletion
var cacheService = _factory.GetService<IApplicationCacheService>();
var cacheService = _factory.GetService<IProviderAbilityCacheService>();
await cacheService.UpsertProviderAbilityAsync(_provider);

var abilityBeforeDelete = await cacheService.GetProviderAbilityAsync(_provider.Id);
Expand Down
Loading
Loading