From 6e1ea8bbff29e35ba721435e563e5911b050d139 Mon Sep 17 00:00:00 2001 From: jrmccannon Date: Wed, 26 Nov 2025 08:36:33 -0600 Subject: [PATCH] Added check for provider users to auto confirm validator. Broke out interface into separate file. --- .../AdminConsole/Services/ProviderService.cs | 4 +-- ...icallyConfirmOrganizationUsersValidator.cs | 11 +++++++ .../AutoConfirmUser/Errors.cs | 1 + ...cUserConfirmationPolicyEnforcementQuery.cs | 31 +++---------------- .../Enforcement/AutoConfirm/Errors.cs | 1 - ...cUserConfirmationPolicyEnforcementQuery.cs | 26 ++++++++++++++++ 6 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/IAutomaticUserConfirmationPolicyEnforcementQuery.cs diff --git a/bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs b/bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs index 566c9892e8..24bd77e11a 100644 --- a/bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs +++ b/bitwarden_license/src/Commercial.Core/AdminConsole/Services/ProviderService.cs @@ -9,8 +9,8 @@ using Bit.Core.AdminConsole.Enums.Provider; using Bit.Core.AdminConsole.Models.Business.Provider; using Bit.Core.AdminConsole.Models.Business.Tokenables; using Bit.Core.AdminConsole.OrganizationFeatures.Organizations; +using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser; using Bit.Core.AdminConsole.OrganizationFeatures.Policies; -using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm; using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements; using Bit.Core.AdminConsole.Repositories; using Bit.Core.AdminConsole.Services; @@ -425,7 +425,7 @@ public class ProviderService : IProviderService if (organizationAutoConfirmPolicyRequirement.Any()) { - throw new BadRequestException(new AutoConfirmDoesNotAllowProviderUsers().Message); + throw new BadRequestException(new ProviderUsersCannotJoin().Message); } } diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUsersValidator.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUsersValidator.cs index ba0c89aa6a..609f46461e 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUsersValidator.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/AutomaticallyConfirmOrganizationUsersValidator.cs @@ -20,6 +20,7 @@ public class AutomaticallyConfirmOrganizationUsersValidator( IPolicyRequirementQuery policyRequirementQuery, IAutomaticUserConfirmationPolicyEnforcementQuery automaticUserConfirmationPolicyEnforcementQuery, IUserService userService, + IProviderUserRepository providerUserRepository, IPolicyRepository policyRepository) : IAutomaticallyConfirmOrganizationUsersValidator { public async Task> ValidateAsync( @@ -70,9 +71,17 @@ public class AutomaticallyConfirmOrganizationUsersValidator( return Invalid(request, error); } + if (await OrganizationUserIsProviderAsync(request)) + { + return Invalid(request, new ProviderUsersCannotJoin()); + } + return Valid(request); } + private async Task OrganizationUserIsProviderAsync(AutomaticallyConfirmOrganizationUserValidationRequest request) => + (await providerUserRepository.GetManyByUserAsync(request.OrganizationUser!.UserId!.Value)).Count != 0; + private async Task OrganizationHasAutomaticallyConfirmUsersPolicyEnabledAsync( AutomaticallyConfirmOrganizationUserValidationRequest request) => await policyRepository.GetByOrganizationIdTypeAsync(request.OrganizationId, @@ -114,4 +123,6 @@ public class AutomaticallyConfirmOrganizationUsersValidator( _ => null ); } + + } diff --git a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/Errors.cs b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/Errors.cs index 1564daca6c..3727ac4109 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/Errors.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/OrganizationUsers/AutoConfirmUser/Errors.cs @@ -11,3 +11,4 @@ public record UserDoesNotHaveTwoFactorEnabled() : BadRequestError("User does not public record OrganizationEnforcesSingleOrgPolicy() : BadRequestError("Cannot confirm this member to the organization until they leave or remove all other organizations"); public record OtherOrganizationEnforcesSingleOrgPolicy() : BadRequestError("Cannot confirm this member to the organization because they are in another organization which forbids it."); public record AutomaticallyConfirmUsersPolicyIsNotEnabled() : BadRequestError("Cannot confirm this member because the Automatically Confirm Users policy is not enabled."); +public record ProviderUsersCannotJoin() : BadRequestError("Organization has enabled Automatic User Confirmation policy and it does not support provider users."); diff --git a/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/AutomaticUserConfirmationPolicyEnforcementQuery.cs b/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/AutomaticUserConfirmationPolicyEnforcementQuery.cs index 730de94931..4252cc35f9 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/AutomaticUserConfirmationPolicyEnforcementQuery.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/AutomaticUserConfirmationPolicyEnforcementQuery.cs @@ -1,31 +1,11 @@ -using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements; +using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser; +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements; using Bit.Core.AdminConsole.Utilities.v2.Validation; using Bit.Core.Repositories; using static Bit.Core.AdminConsole.Utilities.v2.Validation.ValidationResultHelpers; namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm; -/// -/// Used to enforce the Automatic User Confirmation policy. It uses the to retrieve -/// the . It is used to check to make sure the given user is -/// valid for the Automatic User Confirmation policy. It also validates that the given user is not a provider -/// or a member of another organization regardless of status or type. -/// -public interface IAutomaticUserConfirmationPolicyEnforcementQuery -{ - - /// - /// Checks if the given user is compliant with the Automatic User Confirmation policy. - /// - /// - /// - /// This uses the validation result pattern to avoid throwing exceptions. - /// - /// A validation result with the error message if applicable. - Task> IsCompliantAsync( - AutomaticUserConfirmationPolicyEnforcementRequest request); -} - public class AutomaticUserConfirmationPolicyEnforcementQuery( IPolicyRequirementQuery policyRequirementQuery, IOrganizationUserRepository organizationUserRepository) @@ -46,21 +26,20 @@ public class AutomaticUserConfirmationPolicyEnforcementQuery( if (automaticUserConfirmationPolicyRequirement.IsEnabledAndUserIsAProvider(organizationUser.OrganizationId)) { - return Invalid(request, new AutoConfirmDoesNotAllowProviderUsers()); + return Invalid(request, new ProviderUsersCannotJoin()); } - // This is a shortcut to potentially save a database call if (automaticUserConfirmationPolicyRequirement.IsEnabledForOrganizationsOtherThan(organizationUser .OrganizationId)) { - return Invalid(request, new AutoConfirmDoesNotAllowMembershipToOtherOrganizations()); + return Invalid(request, new OrganizationEnforcesSingleOrgPolicy()); } if (otherOrganizationsOrganizationUsers is { Count: > 0 } || (await organizationUserRepository.GetManyByUserAsync(user.Id)) .Any(x => x.OrganizationId != organizationUser.OrganizationId)) { - return Invalid(request, new AutoConfirmDoesNotAllowMembershipToOtherOrganizations()); + return Invalid(request, new OtherOrganizationEnforcesSingleOrgPolicy()); } return Valid(request); diff --git a/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/Errors.cs b/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/Errors.cs index ac9e7bbee1..b3ae1ede6f 100644 --- a/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/Errors.cs +++ b/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/Errors.cs @@ -2,5 +2,4 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm; -public record AutoConfirmDoesNotAllowProviderUsers() : BadRequestError("Organization has enabled Automatic User Confirmation policy and it does not support provider users."); public record AutoConfirmDoesNotAllowMembershipToOtherOrganizations() : BadRequestError("Automatic User Confirmation policy does not support membership to other organizations."); diff --git a/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/IAutomaticUserConfirmationPolicyEnforcementQuery.cs b/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/IAutomaticUserConfirmationPolicyEnforcementQuery.cs new file mode 100644 index 0000000000..2b8b2e92c0 --- /dev/null +++ b/src/Core/AdminConsole/OrganizationFeatures/Policies/Enforcement/AutoConfirm/IAutomaticUserConfirmationPolicyEnforcementQuery.cs @@ -0,0 +1,26 @@ +using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements; +using Bit.Core.AdminConsole.Utilities.v2.Validation; + +namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm; + +/// +/// Used to enforce the Automatic User Confirmation policy. It uses the to retrieve +/// the . It is used to check to make sure the given user is +/// valid for the Automatic User Confirmation policy. It also validates that the given user is not a provider +/// or a member of another organization regardless of status or type. +/// +public interface IAutomaticUserConfirmationPolicyEnforcementQuery +{ + + /// + /// Checks if the given user is compliant with the Automatic User Confirmation policy. To be compliant, the user must: + /// + /// + /// + /// + /// + /// This uses the validation result pattern to avoid throwing exceptions. + /// + /// A validation result with the error message if applicable. + Task> IsCompliantAsync(AutomaticUserConfirmationPolicyEnforcementRequest request); +}