mirror of
https://github.com/bitwarden/server.git
synced 2024-11-24 12:35:25 +01:00
[PM-13722] Refactor ValidateOrganizationsDomainAsync
(#4905)
Refactored ValidateOrganizationsDomainAsync to use VerifyOrganizationDomainAsync
This commit is contained in:
parent
1d3188d3f5
commit
4fec7cadb7
@ -101,7 +101,7 @@ public class OrganizationDomainController : Controller
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
organizationDomain = await _verifyOrganizationDomainCommand.VerifyOrganizationDomainAsync(organizationDomain);
|
||||
organizationDomain = await _verifyOrganizationDomainCommand.UserVerifyOrganizationDomainAsync(organizationDomain);
|
||||
|
||||
return new OrganizationDomainResponseModel(organizationDomain);
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Bit.Core.Utilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains;
|
||||
|
||||
@ -14,21 +13,15 @@ public class CreateOrganizationDomainCommand : ICreateOrganizationDomainCommand
|
||||
{
|
||||
private readonly IOrganizationDomainRepository _organizationDomainRepository;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IDnsResolverService _dnsResolverService;
|
||||
private readonly ILogger<VerifyOrganizationDomainCommand> _logger;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public CreateOrganizationDomainCommand(
|
||||
IOrganizationDomainRepository organizationDomainRepository,
|
||||
IEventService eventService,
|
||||
IDnsResolverService dnsResolverService,
|
||||
ILogger<VerifyOrganizationDomainCommand> logger,
|
||||
IGlobalSettings globalSettings)
|
||||
{
|
||||
_organizationDomainRepository = organizationDomainRepository;
|
||||
_eventService = eventService;
|
||||
_dnsResolverService = dnsResolverService;
|
||||
_logger = logger;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
|
||||
|
@ -4,5 +4,6 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfa
|
||||
|
||||
public interface IVerifyOrganizationDomainCommand
|
||||
{
|
||||
Task<OrganizationDomain> VerifyOrganizationDomainAsync(OrganizationDomain organizationDomain);
|
||||
Task<OrganizationDomain> UserVerifyOrganizationDomainAsync(OrganizationDomain organizationDomain);
|
||||
Task<OrganizationDomain> SystemVerifyOrganizationDomainAsync(OrganizationDomain organizationDomain);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains;
|
||||
@ -13,34 +14,85 @@ public class VerifyOrganizationDomainCommand : IVerifyOrganizationDomainCommand
|
||||
private readonly IOrganizationDomainRepository _organizationDomainRepository;
|
||||
private readonly IDnsResolverService _dnsResolverService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly ILogger<VerifyOrganizationDomainCommand> _logger;
|
||||
|
||||
public VerifyOrganizationDomainCommand(
|
||||
IOrganizationDomainRepository organizationDomainRepository,
|
||||
IDnsResolverService dnsResolverService,
|
||||
IEventService eventService,
|
||||
IGlobalSettings globalSettings,
|
||||
ILogger<VerifyOrganizationDomainCommand> logger)
|
||||
{
|
||||
_organizationDomainRepository = organizationDomainRepository;
|
||||
_dnsResolverService = dnsResolverService;
|
||||
_eventService = eventService;
|
||||
_globalSettings = globalSettings;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<OrganizationDomain> VerifyOrganizationDomainAsync(OrganizationDomain domain)
|
||||
|
||||
public async Task<OrganizationDomain> UserVerifyOrganizationDomainAsync(OrganizationDomain organizationDomain)
|
||||
{
|
||||
if (domain.VerifiedDate is not null)
|
||||
var domainVerificationResult = await VerifyOrganizationDomainAsync(organizationDomain);
|
||||
|
||||
await _eventService.LogOrganizationDomainEventAsync(domainVerificationResult,
|
||||
domainVerificationResult.VerifiedDate != null
|
||||
? EventType.OrganizationDomain_Verified
|
||||
: EventType.OrganizationDomain_NotVerified);
|
||||
|
||||
await _organizationDomainRepository.ReplaceAsync(domainVerificationResult);
|
||||
|
||||
return domainVerificationResult;
|
||||
}
|
||||
|
||||
public async Task<OrganizationDomain> SystemVerifyOrganizationDomainAsync(OrganizationDomain organizationDomain)
|
||||
{
|
||||
organizationDomain.SetJobRunCount();
|
||||
|
||||
var domainVerificationResult = await VerifyOrganizationDomainAsync(organizationDomain);
|
||||
|
||||
if (domainVerificationResult.VerifiedDate is not null)
|
||||
{
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "Successfully validated domain");
|
||||
|
||||
await _eventService.LogOrganizationDomainEventAsync(domainVerificationResult,
|
||||
EventType.OrganizationDomain_Verified,
|
||||
EventSystemUser.DomainVerification);
|
||||
}
|
||||
else
|
||||
{
|
||||
domainVerificationResult.SetNextRunDate(_globalSettings.DomainVerification.VerificationInterval);
|
||||
|
||||
await _eventService.LogOrganizationDomainEventAsync(domainVerificationResult,
|
||||
EventType.OrganizationDomain_NotVerified,
|
||||
EventSystemUser.DomainVerification);
|
||||
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId,
|
||||
"Verification for organization {OrgId} with domain {Domain} failed",
|
||||
domainVerificationResult.OrganizationId, domainVerificationResult.DomainName);
|
||||
}
|
||||
|
||||
await _organizationDomainRepository.ReplaceAsync(domainVerificationResult);
|
||||
|
||||
return domainVerificationResult;
|
||||
}
|
||||
|
||||
private async Task<OrganizationDomain> VerifyOrganizationDomainAsync(OrganizationDomain domain)
|
||||
{
|
||||
domain.SetLastCheckedDate();
|
||||
|
||||
if (domain.VerifiedDate is not null)
|
||||
{
|
||||
await _organizationDomainRepository.ReplaceAsync(domain);
|
||||
throw new ConflictException("Domain has already been verified.");
|
||||
}
|
||||
|
||||
var claimedDomain =
|
||||
await _organizationDomainRepository.GetClaimedDomainsByDomainNameAsync(domain.DomainName);
|
||||
if (claimedDomain.Any())
|
||||
|
||||
if (claimedDomain.Count > 0)
|
||||
{
|
||||
domain.SetLastCheckedDate();
|
||||
await _organizationDomainRepository.ReplaceAsync(domain);
|
||||
throw new ConflictException("The domain is not available to be claimed.");
|
||||
}
|
||||
@ -58,11 +110,6 @@ public class VerifyOrganizationDomainCommand : IVerifyOrganizationDomainCommand
|
||||
domain.DomainName, e.Message);
|
||||
}
|
||||
|
||||
domain.SetLastCheckedDate();
|
||||
await _organizationDomainRepository.ReplaceAsync(domain);
|
||||
|
||||
await _eventService.LogOrganizationDomainEventAsync(domain,
|
||||
domain.VerifiedDate != null ? EventType.OrganizationDomain_Verified : EventType.OrganizationDomain_NotVerified);
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Settings;
|
||||
@ -10,26 +11,29 @@ public class OrganizationDomainService : IOrganizationDomainService
|
||||
{
|
||||
private readonly IOrganizationDomainRepository _domainRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IDnsResolverService _dnsResolverService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IMailService _mailService;
|
||||
private readonly IVerifyOrganizationDomainCommand _verifyOrganizationDomainCommand;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
private readonly ILogger<OrganizationDomainService> _logger;
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
|
||||
public OrganizationDomainService(
|
||||
IOrganizationDomainRepository domainRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IDnsResolverService dnsResolverService,
|
||||
IEventService eventService,
|
||||
IMailService mailService,
|
||||
IVerifyOrganizationDomainCommand verifyOrganizationDomainCommand,
|
||||
TimeProvider timeProvider,
|
||||
ILogger<OrganizationDomainService> logger,
|
||||
IGlobalSettings globalSettings)
|
||||
{
|
||||
_domainRepository = domainRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_dnsResolverService = dnsResolverService;
|
||||
_eventService = eventService;
|
||||
_mailService = mailService;
|
||||
_verifyOrganizationDomainCommand = verifyOrganizationDomainCommand;
|
||||
_timeProvider = timeProvider;
|
||||
_logger = logger;
|
||||
_globalSettings = globalSettings;
|
||||
}
|
||||
@ -37,7 +41,7 @@ public class OrganizationDomainService : IOrganizationDomainService
|
||||
public async Task ValidateOrganizationsDomainAsync()
|
||||
{
|
||||
//Date should be set 1 hour behind to ensure it selects all domains that should be verified
|
||||
var runDate = DateTime.UtcNow.AddHours(-1);
|
||||
var runDate = _timeProvider.GetUtcNow().UtcDateTime.AddHours(-1);
|
||||
|
||||
var verifiableDomains = await _domainRepository.GetManyByNextRunDateAsync(runDate);
|
||||
|
||||
@ -45,43 +49,17 @@ public class OrganizationDomainService : IOrganizationDomainService
|
||||
|
||||
foreach (var domain in verifiableDomains)
|
||||
{
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId,
|
||||
"Attempting verification for organization {OrgId} with domain {Domain}",
|
||||
domain.OrganizationId,
|
||||
domain.DomainName);
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "Attempting verification for organization {OrgId} with domain {Domain}", domain.OrganizationId, domain.DomainName);
|
||||
|
||||
var status = await _dnsResolverService.ResolveAsync(domain.DomainName, domain.Txt);
|
||||
if (status)
|
||||
{
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "Successfully validated domain");
|
||||
|
||||
// Update entry on OrganizationDomain table
|
||||
domain.SetLastCheckedDate();
|
||||
domain.SetVerifiedDate();
|
||||
domain.SetJobRunCount();
|
||||
await _domainRepository.ReplaceAsync(domain);
|
||||
|
||||
await _eventService.LogOrganizationDomainEventAsync(domain, EventType.OrganizationDomain_Verified,
|
||||
EventSystemUser.DomainVerification);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update entry on OrganizationDomain table
|
||||
domain.SetLastCheckedDate();
|
||||
domain.SetJobRunCount();
|
||||
domain.SetNextRunDate(_globalSettings.DomainVerification.VerificationInterval);
|
||||
await _domainRepository.ReplaceAsync(domain);
|
||||
|
||||
await _eventService.LogOrganizationDomainEventAsync(domain, EventType.OrganizationDomain_NotVerified,
|
||||
EventSystemUser.DomainVerification);
|
||||
_logger.LogInformation(Constants.BypassFiltersEventId, "Verification for organization {OrgId} with domain {Domain} failed",
|
||||
domain.OrganizationId, domain.DomainName);
|
||||
}
|
||||
_ = await _verifyOrganizationDomainCommand.SystemVerifyOrganizationDomainAsync(domain);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Update entry on OrganizationDomain table
|
||||
domain.SetLastCheckedDate();
|
||||
domain.SetJobRunCount();
|
||||
domain.SetNextRunDate(_globalSettings.DomainVerification.VerificationInterval);
|
||||
await _domainRepository.ReplaceAsync(domain);
|
||||
|
||||
|
@ -229,13 +229,13 @@ public class OrganizationDomainControllerTests
|
||||
sutProvider.GetDependency<IOrganizationDomainRepository>()
|
||||
.GetDomainByIdOrganizationIdAsync(organizationDomain.Id, organizationDomain.OrganizationId)
|
||||
.Returns(organizationDomain);
|
||||
sutProvider.GetDependency<IVerifyOrganizationDomainCommand>().VerifyOrganizationDomainAsync(organizationDomain)
|
||||
sutProvider.GetDependency<IVerifyOrganizationDomainCommand>().UserVerifyOrganizationDomainAsync(organizationDomain)
|
||||
.Returns(new OrganizationDomain());
|
||||
|
||||
var result = await sutProvider.Sut.Verify(organizationDomain.OrganizationId, organizationDomain.Id);
|
||||
|
||||
await sutProvider.GetDependency<IVerifyOrganizationDomainCommand>().Received(1)
|
||||
.VerifyOrganizationDomainAsync(organizationDomain);
|
||||
.UserVerifyOrganizationDomainAsync(organizationDomain);
|
||||
Assert.IsType<OrganizationDomainResponseModel>(result);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationDomains;
|
||||
public class VerifyOrganizationDomainCommandTests
|
||||
{
|
||||
[Theory, BitAutoData]
|
||||
public async Task VerifyOrganizationDomain_ShouldThrowConflict_WhenDomainHasBeenClaimed(Guid id,
|
||||
public async Task UserVerifyOrganizationDomain_ShouldThrowConflict_WhenDomainHasBeenClaimed(Guid id,
|
||||
SutProvider<VerifyOrganizationDomainCommand> sutProvider)
|
||||
{
|
||||
var expected = new OrganizationDomain
|
||||
@ -30,14 +30,14 @@ public class VerifyOrganizationDomainCommandTests
|
||||
.GetByIdAsync(id)
|
||||
.Returns(expected);
|
||||
|
||||
var requestAction = async () => await sutProvider.Sut.VerifyOrganizationDomainAsync(expected);
|
||||
var requestAction = async () => await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<ConflictException>(requestAction);
|
||||
Assert.Contains("Domain has already been verified.", exception.Message);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task VerifyOrganizationDomain_ShouldThrowConflict_WhenDomainHasBeenClaimedByAnotherOrganization(Guid id,
|
||||
public async Task UserVerifyOrganizationDomain_ShouldThrowConflict_WhenDomainHasBeenClaimedByAnotherOrganization(Guid id,
|
||||
SutProvider<VerifyOrganizationDomainCommand> sutProvider)
|
||||
{
|
||||
var expected = new OrganizationDomain
|
||||
@ -54,14 +54,14 @@ public class VerifyOrganizationDomainCommandTests
|
||||
.GetClaimedDomainsByDomainNameAsync(expected.DomainName)
|
||||
.Returns(new List<OrganizationDomain> { expected });
|
||||
|
||||
var requestAction = async () => await sutProvider.Sut.VerifyOrganizationDomainAsync(expected);
|
||||
var requestAction = async () => await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<ConflictException>(requestAction);
|
||||
Assert.Contains("The domain is not available to be claimed.", exception.Message);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task VerifyOrganizationDomain_ShouldVerifyDomainUpdateAndLogEvent_WhenTxtRecordExists(Guid id,
|
||||
public async Task UserVerifyOrganizationDomain_ShouldVerifyDomainUpdateAndLogEvent_WhenTxtRecordExists(Guid id,
|
||||
SutProvider<VerifyOrganizationDomainCommand> sutProvider)
|
||||
{
|
||||
var expected = new OrganizationDomain
|
||||
@ -81,7 +81,7 @@ public class VerifyOrganizationDomainCommandTests
|
||||
.ResolveAsync(expected.DomainName, Arg.Any<string>())
|
||||
.Returns(true);
|
||||
|
||||
var result = await sutProvider.Sut.VerifyOrganizationDomainAsync(expected);
|
||||
var result = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected);
|
||||
|
||||
Assert.NotNull(result.VerifiedDate);
|
||||
await sutProvider.GetDependency<IOrganizationDomainRepository>().Received(1)
|
||||
@ -91,7 +91,7 @@ public class VerifyOrganizationDomainCommandTests
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task VerifyOrganizationDomain_ShouldNotSetVerifiedDate_WhenTxtRecordDoesNotExist(Guid id,
|
||||
public async Task UserVerifyOrganizationDomain_ShouldNotSetVerifiedDate_WhenTxtRecordDoesNotExist(Guid id,
|
||||
SutProvider<VerifyOrganizationDomainCommand> sutProvider)
|
||||
{
|
||||
var expected = new OrganizationDomain
|
||||
@ -111,10 +111,30 @@ public class VerifyOrganizationDomainCommandTests
|
||||
.ResolveAsync(expected.DomainName, Arg.Any<string>())
|
||||
.Returns(false);
|
||||
|
||||
var result = await sutProvider.Sut.VerifyOrganizationDomainAsync(expected);
|
||||
var result = await sutProvider.Sut.UserVerifyOrganizationDomainAsync(expected);
|
||||
|
||||
Assert.Null(result.VerifiedDate);
|
||||
await sutProvider.GetDependency<IEventService>().Received(1)
|
||||
.LogOrganizationDomainEventAsync(Arg.Any<OrganizationDomain>(), EventType.OrganizationDomain_NotVerified);
|
||||
}
|
||||
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task SystemVerifyOrganizationDomain_CallsEventServiceWithUpdatedJobRunCount(SutProvider<VerifyOrganizationDomainCommand> sutProvider)
|
||||
{
|
||||
var domain = new OrganizationDomain()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
OrganizationId = Guid.NewGuid(),
|
||||
CreationDate = DateTime.UtcNow,
|
||||
DomainName = "test.com",
|
||||
Txt = "btw+12345",
|
||||
};
|
||||
|
||||
_ = await sutProvider.Sut.SystemVerifyOrganizationDomainAsync(domain);
|
||||
|
||||
await sutProvider.GetDependency<IEventService>().ReceivedWithAnyArgs(1)
|
||||
.LogOrganizationDomainEventAsync(default, EventType.OrganizationDomain_NotVerified,
|
||||
EventSystemUser.DomainVerification);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
using Bit.Core.AdminConsole.Services.Implementations;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationDomains.Interfaces;
|
||||
using Bit.Core.AdminConsole.Services.Implementations;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
@ -36,18 +35,14 @@ public class OrganizationDomainServiceTests
|
||||
Txt = "btw+6789"
|
||||
}
|
||||
};
|
||||
|
||||
sutProvider.GetDependency<IOrganizationDomainRepository>().GetManyByNextRunDateAsync(default)
|
||||
.ReturnsForAnyArgs(domains);
|
||||
|
||||
await sutProvider.Sut.ValidateOrganizationsDomainAsync();
|
||||
|
||||
await sutProvider.GetDependency<IDnsResolverService>().ReceivedWithAnyArgs(2)
|
||||
.ResolveAsync(default, default);
|
||||
await sutProvider.GetDependency<IOrganizationDomainRepository>().ReceivedWithAnyArgs(2)
|
||||
.ReplaceAsync(default);
|
||||
await sutProvider.GetDependency<IEventService>().ReceivedWithAnyArgs(2)
|
||||
.LogOrganizationDomainEventAsync(default, EventType.OrganizationDomain_NotVerified,
|
||||
EventSystemUser.DomainVerification);
|
||||
await sutProvider.GetDependency<IVerifyOrganizationDomainCommand>().ReceivedWithAnyArgs(2)
|
||||
.SystemVerifyOrganizationDomainAsync(default);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
|
Loading…
Reference in New Issue
Block a user