1
0
mirror of https://github.com/bitwarden/server synced 2025-12-28 14:13:48 +00:00

Cleaned up implementation of enforcement validator (for the user).

This commit is contained in:
Jared McCannon
2025-12-04 18:46:05 -06:00
parent 0602c3eaf7
commit e12fa708e7
10 changed files with 97 additions and 217 deletions

View File

@@ -270,7 +270,7 @@ public class AcceptOrgUserCommand : IAcceptOrgUserCommand
ICollection<OrganizationUser> allOrgUsers, User user)
{
var error = (await _automaticUserConfirmationPolicyEnforcementValidator.IsCompliantAsync(
new AutomaticUserConfirmationPolicyEnforcementRequest(orgUser.Id, allOrgUsers, user)))
new AutomaticUserConfirmationPolicyEnforcementRequest(orgUser.OrganizationId, allOrgUsers, user)))
.Match(
error => error.Message,
_ => string.Empty

View File

@@ -20,7 +20,6 @@ public class AutomaticallyConfirmOrganizationUsersValidator(
IPolicyRequirementQuery policyRequirementQuery,
IAutomaticUserConfirmationPolicyEnforcementValidator automaticUserConfirmationPolicyEnforcementValidator,
IUserService userService,
IProviderUserRepository providerUserRepository,
IPolicyRepository policyRepository) : IAutomaticallyConfirmOrganizationUsersValidator
{
public async Task<ValidationResult<AutomaticallyConfirmOrganizationUserValidationRequest>> ValidateAsync(
@@ -71,17 +70,9 @@ public class AutomaticallyConfirmOrganizationUsersValidator(
return Invalid(request, error);
}
if (await OrganizationUserIsProviderAsync(request))
{
return Invalid(request, new ProviderUsersCannotJoin());
}
return Valid(request);
}
private async Task<bool> OrganizationUserIsProviderAsync(AutomaticallyConfirmOrganizationUserValidationRequest request) =>
(await providerUserRepository.GetManyByUserAsync(request.OrganizationUser!.UserId!.Value)).Count != 0;
private async Task<bool> OrganizationHasAutomaticallyConfirmUsersPolicyEnabledAsync(AutomaticallyConfirmOrganizationUserValidationRequest request) =>
await policyRepository.GetByOrganizationIdTypeAsync(request.OrganizationId, PolicyType.AutomaticUserConfirmation) is { Enabled: true }
&& request.Organization is { UseAutomaticUserConfirmation: true };
@@ -112,7 +103,7 @@ public class AutomaticallyConfirmOrganizationUsersValidator(
return (await automaticUserConfirmationPolicyEnforcementValidator.IsCompliantAsync(
new AutomaticUserConfirmationPolicyEnforcementRequest(
request.OrganizationUser,
request.OrganizationId,
allOrganizationUsersForUser.Where(x => x.OrganizationId != request.OrganizationId),
user)))
.Match<Error?>(

View File

@@ -9,7 +9,7 @@ public record UserIsNotAccepted() : BadRequestError("Cannot confirm user that ha
public record OrganizationUserIdIsInvalid() : BadRequestError("Invalid organization user id.");
public record UserDoesNotHaveTwoFactorEnabled() : BadRequestError("User does not have two-step login enabled.");
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 OtherOrganizationDoesNotAllowOtherMembership() : 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("An organization the user is a part of has enabled Automatic User Confirmation policy and it does not support provider users joining.");
public record CurrentOrganizationUserIsNotPresentInRequest() : BadRequestError("The current organization user does not exist in the request.");

View File

@@ -198,8 +198,8 @@ public class ConfirmOrganizationUserCommand : IConfirmOrganizationUserCommand
{
var error = (await _automaticUserConfirmationPolicyEnforcementValidator.IsCompliantAsync(
new AutomaticUserConfirmationPolicyEnforcementRequest(
userOrgs.First(x => x.OrganizationId == organizationId),
userOrgs.Where(x => x.OrganizationId != organizationId),
organizationId,
userOrgs,
user)))
.Match(
error => error.Message,

View File

@@ -8,14 +8,15 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoCo
public record AutomaticUserConfirmationPolicyEnforcementRequest
{
/// <summary>
/// Organization user to be validated
/// Organization to be validated
/// </summary>
public Guid OrganizationUserId { get; }
public Guid OrganizationId { get; }
/// <summary>
/// All organization users that match the provided user.
/// </summary>
public IEnumerable<OrganizationUser> AllOrganizationUsers { get; }
/// <summary>
/// User associated with the organization user to be confirmed
/// </summary>
@@ -27,15 +28,15 @@ public record AutomaticUserConfirmationPolicyEnforcementRequest
/// <remarks>
/// This record is used to encapsulate the data required for handling the automatic confirmation policy enforcement.
/// </remarks>
/// <param name="organizationUserId">The organization user id to be validated.</param>
/// <param name="organizationId">The organization to be validated.</param>
/// <param name="organizationUsers">All organization users that match the provided user.</param>
/// <param name="user">The general user associated with the operation.</param>
/// <param name="user">The user entity connecting all org users provided.</param>
public AutomaticUserConfirmationPolicyEnforcementRequest(
Guid organizationUserId,
Guid organizationId,
IEnumerable<OrganizationUser> organizationUsers,
User user)
{
OrganizationUserId = organizationUserId;
OrganizationId = organizationId;
AllOrganizationUsers = organizationUsers;
User = user;
}

View File

@@ -18,23 +18,18 @@ public class AutomaticUserConfirmationPolicyEnforcementValidator(
.GetAsync<AutomaticUserConfirmationPolicyRequirement>(request.User.Id);
var currentOrganizationUser = request.AllOrganizationUsers
.FirstOrDefault(x => x.Id == request.OrganizationUserId);
.FirstOrDefault(x => x.OrganizationId == request.OrganizationId
&& x.UserId == request.User.Id);
if (currentOrganizationUser is null)
{
return Invalid(request, new CurrentOrganizationUserIsNotPresentInRequest());
}
if (automaticUserConfirmationPolicyRequirement.IsEnabled(currentOrganizationUser.OrganizationId)
&& automaticUserConfirmationPolicyRequirement.UserBelongsToOrganizationWithAutomaticUserConfirmationEnabled())
{
return Invalid(request, new OrganizationEnforcesSingleOrgPolicy());
}
if (automaticUserConfirmationPolicyRequirement
.IsEnabledForOrganizationsOtherThan(currentOrganizationUser.OrganizationId))
{
return Invalid(request, new OtherOrganizationEnforcesSingleOrgPolicy());
return Invalid(request, new OtherOrganizationDoesNotAllowOtherMembership());
}
if ((await providerUserRepository.GetManyByUserAsync(request.User.Id)).Count != 0)