From 739bc65e87d00369e401ee97c4a25aebb686c611 Mon Sep 17 00:00:00 2001 From: jrmccannon Date: Tue, 1 Apr 2025 14:35:04 -0500 Subject: [PATCH] Delayed the hasSecretsManagerStandalone call as long as possible. --- .../src/Scim/Models/ScimUserRequestModel.cs | 6 ++---- .../src/Scim/Users/PostUserCommand.cs | 5 +---- .../InviteUserOrganizationValidationRequest.cs | 13 +++++++++++-- .../Models/OrganizationUserInvite.cs | 16 ++++++++++++++-- .../InviteOrganizationUserValidator.cs | 18 +++++++++++++++++- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/bitwarden_license/src/Scim/Models/ScimUserRequestModel.cs b/bitwarden_license/src/Scim/Models/ScimUserRequestModel.cs index 9e17890365..295db790e3 100644 --- a/bitwarden_license/src/Scim/Models/ScimUserRequestModel.cs +++ b/bitwarden_license/src/Scim/Models/ScimUserRequestModel.cs @@ -32,8 +32,7 @@ public class ScimUserRequestModel : BaseScimUserModel public InviteOrganizationUsersRequest ToRequest( ScimProviderType scimProvider, InviteOrganization inviteOrganization, - DateTimeOffset performedAt, - bool hasSecretsManagerStandalone) + DateTimeOffset performedAt) { var email = EmailForInvite(scimProvider); @@ -47,8 +46,7 @@ public class ScimUserRequestModel : BaseScimUserModel [ new Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Models.OrganizationUserInvite( email: email, - externalId: ExternalIdForInvite(), - accessSecretsManager: hasSecretsManagerStandalone + externalId: ExternalIdForInvite() ) ], inviteOrganization: inviteOrganization, diff --git a/bitwarden_license/src/Scim/Users/PostUserCommand.cs b/bitwarden_license/src/Scim/Users/PostUserCommand.cs index 822fcbb563..46116a46ae 100644 --- a/bitwarden_license/src/Scim/Users/PostUserCommand.cs +++ b/bitwarden_license/src/Scim/Users/PostUserCommand.cs @@ -56,13 +56,10 @@ public class PostUserCommand( var plan = await pricingClient.GetPlanOrThrow(organization.PlanType); - var hasSecretsManagerStandalone = await paymentService.HasSecretsManagerStandalone(organization); - var request = model.ToRequest( scimProvider: scimProvider, inviteOrganization: new InviteOrganization(organization, plan), - performedAt: timeProvider.GetUtcNow(), - hasSecretsManagerStandalone); + performedAt: timeProvider.GetUtcNow()); var orgUsers = await organizationUserRepository .GetManyDetailsByOrganizationAsync(request.InviteOrganization.OrganizationId); diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/InviteUserOrganizationValidationRequest.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/InviteUserOrganizationValidationRequest.cs index a47252859c..e35b3f8628 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/InviteUserOrganizationValidationRequest.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/InviteUserOrganizationValidationRequest.cs @@ -6,9 +6,11 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUse public class InviteUserOrganizationValidationRequest { - public InviteUserOrganizationValidationRequest() { } + public InviteUserOrganizationValidationRequest() + { + } - public InviteUserOrganizationValidationRequest(InviteUserOrganizationValidationRequest request, PasswordManagerSubscriptionUpdate subscriptionUpdate, SecretsManagerSubscriptionUpdate smSubscriptionUpdate) + public InviteUserOrganizationValidationRequest(InviteUserOrganizationValidationRequest request) { Invites = request.Invites; InviteOrganization = request.InviteOrganization; @@ -16,6 +18,13 @@ public class InviteUserOrganizationValidationRequest PerformedAt = request.PerformedAt; OccupiedPmSeats = request.OccupiedPmSeats; OccupiedSmSeats = request.OccupiedSmSeats; + } + + public InviteUserOrganizationValidationRequest(InviteUserOrganizationValidationRequest request, + PasswordManagerSubscriptionUpdate subscriptionUpdate, + SecretsManagerSubscriptionUpdate smSubscriptionUpdate) + : this(request) + { PasswordManagerSubscriptionUpdate = subscriptionUpdate; SecretsManagerSubscriptionUpdate = smSubscriptionUpdate; } diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/OrganizationUserInvite.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/OrganizationUserInvite.cs index 5e183807e6..0b83680aa5 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/OrganizationUserInvite.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Models/OrganizationUserInvite.cs @@ -17,7 +17,7 @@ public class OrganizationUserInvite public bool AccessSecretsManager { get; private init; } public Guid[] Groups { get; private init; } - public OrganizationUserInvite(string email, string externalId, bool accessSecretsManager) : + public OrganizationUserInvite(string email, string externalId) : this( email: email, assignedCollections: [], @@ -25,10 +25,22 @@ public class OrganizationUserInvite type: OrganizationUserType.User, permissions: new Permissions(), externalId: externalId, - accessSecretsManager: accessSecretsManager) + false) { } + public OrganizationUserInvite(OrganizationUserInvite invite, bool accessSecretsManager) : + this(invite.Email, + invite.AssignedCollections, + invite.Groups, + invite.Type, + invite.Permissions, + invite.ExternalId, + accessSecretsManager) + { + + } + public OrganizationUserInvite(string email, IEnumerable assignedCollections, IEnumerable groups, diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Validation/InviteOrganizationUserValidator.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Validation/InviteOrganizationUserValidator.cs index 3adae0a8f0..e3f41d7c39 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Validation/InviteOrganizationUserValidator.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/InviteUsers/Validation/InviteOrganizationUserValidator.cs @@ -6,6 +6,9 @@ using Bit.Core.AdminConsole.Shared.Validation; using Bit.Core.Models.Business; using Bit.Core.OrganizationFeatures.OrganizationSubscriptions.Interface; using Bit.Core.Repositories; +using Bit.Core.Services; +using OrganizationUserInvite = Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Models.OrganizationUserInvite; + namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Validation; public interface IInviteUsersValidator : IValidator; @@ -13,7 +16,8 @@ public interface IInviteUsersValidator : IValidator> ValidateAsync(InviteUserOrganizationValidationRequest request) { @@ -26,6 +30,18 @@ public class InviteUsersValidator( return invalidSubscriptionUpdate.Map(request); } + // If the organization has the Secrets Manager Standalone Discount, all users are added to secrets manager. + // This is an expensive call, so we're doing it now to delay the check as long as possible. + if (await paymentService.HasSecretsManagerStandalone(request.InviteOrganization)) + { + request = new InviteUserOrganizationValidationRequest(request) + { + Invites = request.Invites + .Select(x => new OrganizationUserInvite(x, accessSecretsManager: true)) + .ToArray() + }; + } + if (request.InviteOrganization.UseSecretsManager && request.Invites.Any(x => x.AccessSecretsManager)) { return await ValidateSecretsManagerSubscriptionUpdateAsync(request, subscriptionUpdate);