1
0
mirror of https://github.com/bitwarden/server synced 2026-03-01 10:51:26 +00:00

[PM-27145] - Block Auto Confirm Enable Admin Portal (#6981)

* Extracted policy compliance checking for the organization out and added a check when attempting to enable auto user confirm via Admin Portal

* Moved injection order. Fixed error message.
This commit is contained in:
Jared McCannon
2026-02-11 09:59:18 -06:00
committed by GitHub
parent 946a03233b
commit 0566de90d6
10 changed files with 863 additions and 385 deletions

View File

@@ -10,8 +10,10 @@ using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Enums.Provider;
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Enforcement.AutoConfirm;
using Bit.Core.AdminConsole.Providers.Interfaces;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.AdminConsole.Utilities.v2;
using Bit.Core.Billing.Enums;
using Bit.Core.Billing.Extensions;
using Bit.Core.Billing.Organizations.Services;
@@ -59,6 +61,7 @@ public class OrganizationsController : Controller
private readonly IPricingClient _pricingClient;
private readonly IResendOrganizationInviteCommand _resendOrganizationInviteCommand;
private readonly IOrganizationBillingService _organizationBillingService;
private readonly IAutomaticUserConfirmationOrganizationPolicyComplianceValidator _automaticUserConfirmationOrganizationPolicyComplianceValidator;
public OrganizationsController(
IOrganizationRepository organizationRepository,
@@ -84,7 +87,8 @@ public class OrganizationsController : Controller
IOrganizationInitiateDeleteCommand organizationInitiateDeleteCommand,
IPricingClient pricingClient,
IResendOrganizationInviteCommand resendOrganizationInviteCommand,
IOrganizationBillingService organizationBillingService)
IOrganizationBillingService organizationBillingService,
IAutomaticUserConfirmationOrganizationPolicyComplianceValidator automaticUserConfirmationOrganizationPolicyComplianceValidator)
{
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
@@ -110,6 +114,7 @@ public class OrganizationsController : Controller
_pricingClient = pricingClient;
_resendOrganizationInviteCommand = resendOrganizationInviteCommand;
_organizationBillingService = organizationBillingService;
_automaticUserConfirmationOrganizationPolicyComplianceValidator = automaticUserConfirmationOrganizationPolicyComplianceValidator;
}
[RequirePermission(Permission.Org_List_View)]
@@ -250,7 +255,8 @@ public class OrganizationsController : Controller
BillingEmail = organization.BillingEmail,
Status = organization.Status,
PlanType = organization.PlanType,
Seats = organization.Seats
Seats = organization.Seats,
UseAutomaticUserConfirmation = organization.UseAutomaticUserConfirmation
};
if (model.PlanType.HasValue)
@@ -285,6 +291,13 @@ public class OrganizationsController : Controller
return RedirectToAction("Edit", new { id });
}
if (await CheckOrganizationPolicyComplianceAsync(existingOrganizationData, organization) is { } error)
{
TempData["Error"] = error.Message;
return RedirectToAction("Edit", new { id });
}
await HandlePotentialProviderSeatScalingAsync(
existingOrganizationData,
model);
@@ -312,6 +325,19 @@ public class OrganizationsController : Controller
return RedirectToAction("Edit", new { id });
}
private async Task<Error> CheckOrganizationPolicyComplianceAsync(Organization existingOrganizationData, Organization updatedOrganization)
{
if (!existingOrganizationData.UseAutomaticUserConfirmation && updatedOrganization.UseAutomaticUserConfirmation)
{
var validationResult = await _automaticUserConfirmationOrganizationPolicyComplianceValidator.IsOrganizationCompliantAsync(
new AutomaticUserConfirmationOrganizationPolicyComplianceValidatorRequest(existingOrganizationData.Id));
return validationResult.Match(error => error, _ => null);
}
return null;
}
[HttpPost]
[ValidateAntiForgeryToken]
[RequirePermission(Permission.Org_Delete)]