mirror of
https://github.com/bitwarden/server
synced 2026-01-04 17:43:53 +00:00
Merge branch 'refs/heads/main' into km/pm-10600
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||
|
||||
public interface IOrganizationHasVerifiedDomainsQuery
|
||||
{
|
||||
Task<bool> HasVerifiedDomainsAsync(Guid orgId);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||
using Bit.Core.Repositories;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains;
|
||||
|
||||
public class OrganizationHasVerifiedDomainsQuery(IOrganizationDomainRepository domainRepository) : IOrganizationHasVerifiedDomainsQuery
|
||||
{
|
||||
public async Task<bool> HasVerifiedDomainsAsync(Guid orgId) =>
|
||||
(await domainRepository.GetDomainsByOrganizationIdAsync(orgId)).Any(od => od.VerifiedDate is not null);
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
@@ -15,6 +18,9 @@ public class VerifyOrganizationDomainCommand : IVerifyOrganizationDomainCommand
|
||||
private readonly IDnsResolverService _dnsResolverService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly IPolicyService _policyService;
|
||||
private readonly IFeatureService _featureService;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly ILogger<VerifyOrganizationDomainCommand> _logger;
|
||||
|
||||
public VerifyOrganizationDomainCommand(
|
||||
@@ -22,12 +28,18 @@ public class VerifyOrganizationDomainCommand : IVerifyOrganizationDomainCommand
|
||||
IDnsResolverService dnsResolverService,
|
||||
IEventService eventService,
|
||||
IGlobalSettings globalSettings,
|
||||
IPolicyService policyService,
|
||||
IFeatureService featureService,
|
||||
IOrganizationService organizationService,
|
||||
ILogger<VerifyOrganizationDomainCommand> logger)
|
||||
{
|
||||
_organizationDomainRepository = organizationDomainRepository;
|
||||
_dnsResolverService = dnsResolverService;
|
||||
_eventService = eventService;
|
||||
_globalSettings = globalSettings;
|
||||
_policyService = policyService;
|
||||
_featureService = featureService;
|
||||
_organizationService = organizationService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -102,6 +114,8 @@ public class VerifyOrganizationDomainCommand : IVerifyOrganizationDomainCommand
|
||||
if (await _dnsResolverService.ResolveAsync(domain.DomainName, domain.Txt))
|
||||
{
|
||||
domain.SetVerifiedDate();
|
||||
|
||||
await EnableSingleOrganizationPolicyAsync(domain.OrganizationId);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -112,4 +126,13 @@ public class VerifyOrganizationDomainCommand : IVerifyOrganizationDomainCommand
|
||||
|
||||
return domain;
|
||||
}
|
||||
|
||||
private async Task EnableSingleOrganizationPolicyAsync(Guid organizationId)
|
||||
{
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning))
|
||||
{
|
||||
await _policyService.SaveAsync(
|
||||
new Policy { OrganizationId = organizationId, Type = PolicyType.SingleOrg, Enabled = true }, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#nullable enable
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Authorization;
|
||||
@@ -10,12 +9,10 @@ public class OrganizationUserUserDetailsAuthorizationHandler
|
||||
: AuthorizationHandler<OrganizationUserUserDetailsOperationRequirement, OrganizationScope>
|
||||
{
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IFeatureService _featureService;
|
||||
|
||||
public OrganizationUserUserDetailsAuthorizationHandler(ICurrentContext currentContext, IFeatureService featureService)
|
||||
public OrganizationUserUserDetailsAuthorizationHandler(ICurrentContext currentContext)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_featureService = featureService;
|
||||
}
|
||||
|
||||
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
|
||||
@@ -37,29 +34,6 @@ public class OrganizationUserUserDetailsAuthorizationHandler
|
||||
}
|
||||
|
||||
private async Task<bool> CanReadAllAsync(Guid organizationId)
|
||||
{
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.Pm3478RefactorOrganizationUserApi))
|
||||
{
|
||||
return await CanReadAllAsync_vNext(organizationId);
|
||||
}
|
||||
|
||||
return await CanReadAllAsync_vCurrent(organizationId);
|
||||
}
|
||||
|
||||
private async Task<bool> CanReadAllAsync_vCurrent(Guid organizationId)
|
||||
{
|
||||
// All users of an organization can read all other users of that organization for collection access management
|
||||
var org = _currentContext.GetOrganization(organizationId);
|
||||
if (org is not null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow provider users to read all organization users if they are a provider for the target organization
|
||||
return await _currentContext.ProviderUserForOrgAsync(organizationId);
|
||||
}
|
||||
|
||||
private async Task<bool> CanReadAllAsync_vNext(Guid organizationId)
|
||||
{
|
||||
// Admins can access this for general user management
|
||||
var organization = _currentContext.GetOrganization(organizationId);
|
||||
|
||||
@@ -22,8 +22,7 @@ public interface IOrganizationUserRepository : IRepository<OrganizationUser, Gui
|
||||
Task<OrganizationUser?> GetByOrganizationAsync(Guid organizationId, Guid userId);
|
||||
Task<Tuple<OrganizationUser?, ICollection<CollectionAccessSelection>>> GetByIdWithCollectionsAsync(Guid id);
|
||||
Task<OrganizationUserUserDetails?> GetDetailsByIdAsync(Guid id);
|
||||
Task<Tuple<OrganizationUserUserDetails?, ICollection<CollectionAccessSelection>>>
|
||||
GetDetailsByIdWithCollectionsAsync(Guid id);
|
||||
Task<(OrganizationUserUserDetails? OrganizationUser, ICollection<CollectionAccessSelection> Collections)> GetDetailsByIdWithCollectionsAsync(Guid id);
|
||||
Task<ICollection<OrganizationUserUserDetails>> GetManyDetailsByOrganizationAsync(Guid organizationId, bool includeGroups = false, bool includeCollections = false);
|
||||
Task<ICollection<OrganizationUserOrganizationDetails>> GetManyDetailsByUserAsync(Guid userId,
|
||||
OrganizationUserStatusType? status = null);
|
||||
|
||||
@@ -4,8 +4,4 @@ public interface IOrganizationDomainService
|
||||
{
|
||||
Task ValidateOrganizationsDomainAsync();
|
||||
Task OrganizationDomainMaintenanceAsync();
|
||||
/// <summary>
|
||||
/// Indicates if the organization has any verified domains.
|
||||
/// </summary>
|
||||
Task<bool> HasVerifiedDomainsAsync(Guid orgId);
|
||||
}
|
||||
|
||||
@@ -106,12 +106,6 @@ public class OrganizationDomainService : IOrganizationDomainService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> HasVerifiedDomainsAsync(Guid orgId)
|
||||
{
|
||||
var orgDomains = await _domainRepository.GetDomainsByOrganizationIdAsync(orgId);
|
||||
return orgDomains.Any(od => od.VerifiedDate != null);
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetAdminEmailsAsync(Guid organizationId)
|
||||
{
|
||||
var orgUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(organizationId);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.Models;
|
||||
@@ -32,6 +33,7 @@ public class PolicyService : IPolicyService
|
||||
private readonly IFeatureService _featureService;
|
||||
private readonly ISavePolicyCommand _savePolicyCommand;
|
||||
private readonly IRemoveOrganizationUserCommand _removeOrganizationUserCommand;
|
||||
private readonly IOrganizationHasVerifiedDomainsQuery _organizationHasVerifiedDomainsQuery;
|
||||
|
||||
public PolicyService(
|
||||
IApplicationCacheService applicationCacheService,
|
||||
@@ -45,7 +47,8 @@ public class PolicyService : IPolicyService
|
||||
ITwoFactorIsEnabledQuery twoFactorIsEnabledQuery,
|
||||
IFeatureService featureService,
|
||||
ISavePolicyCommand savePolicyCommand,
|
||||
IRemoveOrganizationUserCommand removeOrganizationUserCommand)
|
||||
IRemoveOrganizationUserCommand removeOrganizationUserCommand,
|
||||
IOrganizationHasVerifiedDomainsQuery organizationHasVerifiedDomainsQuery)
|
||||
{
|
||||
_applicationCacheService = applicationCacheService;
|
||||
_eventService = eventService;
|
||||
@@ -59,6 +62,7 @@ public class PolicyService : IPolicyService
|
||||
_featureService = featureService;
|
||||
_savePolicyCommand = savePolicyCommand;
|
||||
_removeOrganizationUserCommand = removeOrganizationUserCommand;
|
||||
_organizationHasVerifiedDomainsQuery = organizationHasVerifiedDomainsQuery;
|
||||
}
|
||||
|
||||
public async Task SaveAsync(Policy policy, Guid? savingUserId)
|
||||
@@ -239,6 +243,7 @@ public class PolicyService : IPolicyService
|
||||
case PolicyType.SingleOrg:
|
||||
if (!policy.Enabled)
|
||||
{
|
||||
await HasVerifiedDomainsAsync(org);
|
||||
await RequiredBySsoAsync(org);
|
||||
await RequiredByVaultTimeoutAsync(org);
|
||||
await RequiredByKeyConnectorAsync(org);
|
||||
@@ -279,6 +284,15 @@ public class PolicyService : IPolicyService
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HasVerifiedDomainsAsync(Organization org)
|
||||
{
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning)
|
||||
&& await _organizationHasVerifiedDomainsQuery.HasVerifiedDomainsAsync(org.Id))
|
||||
{
|
||||
throw new BadRequestException("Organization has verified domains.");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetPolicyConfiguration(Policy policy)
|
||||
{
|
||||
await _policyRepository.UpsertAsync(policy);
|
||||
|
||||
@@ -87,7 +87,9 @@ public record EnterprisePlan : Plan
|
||||
AdditionalStoragePricePerGb = 4;
|
||||
StripeStoragePlanId = "storage-gb-annually";
|
||||
StripeSeatPlanId = "2023-enterprise-org-seat-annually";
|
||||
StripeProviderPortalSeatPlanId = "password-manager-provider-portal-enterprise-annually-2024";
|
||||
SeatPrice = 72;
|
||||
ProviderPortalSeatPrice = 72;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -141,7 +141,6 @@ public static class FeatureFlagKeys
|
||||
public const string EnableNewCardCombinedExpiryAutofill = "enable-new-card-combined-expiry-autofill";
|
||||
public const string StorageReseedRefactor = "storage-reseed-refactor";
|
||||
public const string TrialPayment = "PM-8163-trial-payment";
|
||||
public const string Pm3478RefactorOrganizationUserApi = "pm-3478-refactor-organizationuser-api";
|
||||
public const string RemoveServerVersionHeader = "remove-server-version-header";
|
||||
public const string AccessIntelligence = "pm-13227-access-intelligence";
|
||||
public const string VerifiedSsoDomainEndpoint = "pm-12337-refactor-sso-details-endpoint";
|
||||
@@ -149,6 +148,7 @@ public static class FeatureFlagKeys
|
||||
public const string Pm13322AddPolicyDefinitions = "pm-13322-add-policy-definitions";
|
||||
public const string LimitCollectionCreationDeletionSplit = "pm-10863-limit-collection-creation-deletion-split";
|
||||
public const string GeneratorToolsModernization = "generator-tools-modernization";
|
||||
public const string NewDeviceVerification = "new-device-verification";
|
||||
|
||||
public static List<string> GetAllKeys()
|
||||
{
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCoreRateLimit.Redis" Version="2.0.0" />
|
||||
<PackageReference Include="AWSSDK.SimpleEmail" Version="3.7.401.24" />
|
||||
<PackageReference Include="AWSSDK.SQS" Version="3.7.400.34" />
|
||||
<PackageReference Include="AWSSDK.SimpleEmail" Version="3.7.401.30" />
|
||||
<PackageReference Include="AWSSDK.SQS" Version="3.7.400.40" />
|
||||
<PackageReference Include="Azure.Data.Tables" Version="12.9.0" />
|
||||
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Blobs" Version="1.3.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="8.0.8" />
|
||||
@@ -36,7 +36,7 @@
|
||||
<PackageReference Include="Handlebars.Net" Version="2.1.6" />
|
||||
<PackageReference Include="MailKit" Version="4.8.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.44.0" />
|
||||
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.45.0" />
|
||||
<PackageReference Include="Microsoft.Azure.NotificationHubs" Version="4.2.0" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Cosmos" Version="1.6.1" />
|
||||
@@ -59,7 +59,7 @@
|
||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
||||
<PackageReference Include="YubicoDotNetClient" Version="1.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.8" />
|
||||
<PackageReference Include="LaunchDarkly.ServerSdk" Version="8.5.2" />
|
||||
<PackageReference Include="LaunchDarkly.ServerSdk" Version="8.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -130,6 +130,7 @@ public static class OrganizationServiceCollectionExtensions
|
||||
services.AddScoped<IGetOrganizationDomainByIdOrganizationIdQuery, GetOrganizationDomainByIdOrganizationIdQuery>();
|
||||
services.AddScoped<IGetOrganizationDomainByOrganizationIdQuery, GetOrganizationDomainByOrganizationIdQuery>();
|
||||
services.AddScoped<IDeleteOrganizationDomainCommand, DeleteOrganizationDomainCommand>();
|
||||
services.AddScoped<IOrganizationHasVerifiedDomainsQuery, OrganizationHasVerifiedDomainsQuery>();
|
||||
}
|
||||
|
||||
private static void AddOrganizationAuthCommands(this IServiceCollection services)
|
||||
|
||||
Reference in New Issue
Block a user