1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 16:42:50 -05:00

Merge branch 'master' into feature/flexible-collections

This commit is contained in:
Vincent Salucci
2023-09-12 10:32:23 -05:00
21 changed files with 270 additions and 59 deletions

View File

@ -142,15 +142,19 @@ public class AuthRequestServiceTests
}
[Theory, BitAutoData]
public async Task CreateAuthRequestAsync_NoUser_ThrowsNotFound(
public async Task CreateAuthRequestAsync_NoUser_ThrowsBadRequest(
SutProvider<AuthRequestService> sutProvider,
AuthRequestCreateRequestModel createModel)
{
sutProvider.GetDependency<ICurrentContext>()
.DeviceType
.Returns(DeviceType.Android);
sutProvider.GetDependency<IUserRepository>()
.GetByEmailAsync(createModel.Email)
.Returns((User?)null);
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.CreateAuthRequestAsync(createModel));
await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.CreateAuthRequestAsync(createModel));
}
[Theory, BitAutoData]
@ -253,7 +257,7 @@ public class AuthRequestServiceTests
/// <summary>
/// Story: If a user happens to exist to more than one organization, we will send the device approval request to
/// each of them.
/// each of them.
/// </summary>
[Theory, BitAutoData]
public async Task CreateAuthRequestAsync_AdminApproval_CreatesForEachOrganization(
@ -627,8 +631,8 @@ public class AuthRequestServiceTests
}
/// <summary>
/// Story: An admin approves a request for one of their org users. For auditing purposes we need to
/// log an event that correlates the action for who the request was approved for. On approval we also need to
/// Story: An admin approves a request for one of their org users. For auditing purposes we need to
/// log an event that correlates the action for who the request was approved for. On approval we also need to
/// push the notification to the user.
/// </summary>
[Theory, BitAutoData]

View File

@ -10,6 +10,7 @@ using Bit.Core.Models.Data;
using Bit.Core.Utilities;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Microsoft.AspNetCore.DataProtection;
namespace Bit.Core.Test.AutoFixture.OrganizationFixtures;
@ -187,3 +188,31 @@ internal class SecretsManagerOrganizationCustomizeAttribute : BitCustomizeAttrib
public override ICustomization GetCustomization() =>
new SecretsManagerOrganizationCustomization();
}
internal class EphemeralDataProtectionCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new EphemeralDataProtectionProviderBuilder());
}
private class EphemeralDataProtectionProviderBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var type = request as Type;
if (type == null || type != typeof(IDataProtectionProvider))
{
return new NoSpecimen();
}
return new EphemeralDataProtectionProvider();
}
}
}
internal class EphemeralDataProtectionAutoDataAttribute : CustomAutoDataAttribute
{
public EphemeralDataProtectionAutoDataAttribute() : base(new SutProviderCustomization(), new EphemeralDataProtectionCustomization())
{ }
}

View File

@ -28,6 +28,7 @@ using Bit.Core.Tools.Services;
using Bit.Core.Utilities;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using Microsoft.AspNetCore.DataProtection;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using Xunit;
@ -1835,6 +1836,42 @@ public class OrganizationServiceTests
sutProvider.Sut.ValidateSecretsManagerPlan(plan, signup);
}
[Theory]
[EphemeralDataProtectionAutoData]
public async Task AcceptUserAsync_Success([OrganizationUser(OrganizationUserStatusType.Invited)] OrganizationUser organizationUser,
User user, SutProvider<OrganizationService> sutProvider)
{
var token = SetupAcceptUserAsyncTest(sutProvider, user, organizationUser);
var userService = Substitute.For<IUserService>();
await sutProvider.Sut.AcceptUserAsync(organizationUser.Id, user, token, userService);
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).ReplaceAsync(
Arg.Is<OrganizationUser>(ou => ou.Id == organizationUser.Id && ou.Status == OrganizationUserStatusType.Accepted));
await sutProvider.GetDependency<IUserRepository>().Received(1).ReplaceAsync(
Arg.Is<User>(u => u.Id == user.Id && u.Email == user.Email && user.EmailVerified == true));
}
private string SetupAcceptUserAsyncTest(SutProvider<OrganizationService> sutProvider, User user,
OrganizationUser organizationUser)
{
user.Email = organizationUser.Email;
user.EmailVerified = false;
var dataProtector = sutProvider.GetDependency<IDataProtectionProvider>()
.CreateProtector("OrganizationServiceDataProtector");
// Token matching the format used in OrganizationService.InviteUserAsync
var token = dataProtector.Protect(
$"OrganizationUserInvite {organizationUser.Id} {organizationUser.Email} {CoreHelpers.ToEpocMilliseconds(DateTime.UtcNow)}");
sutProvider.GetDependency<IGlobalSettings>().OrganizationInviteExpirationHours.Returns(24);
sutProvider.GetDependency<IOrganizationUserRepository>().GetByIdAsync(organizationUser.Id)
.Returns(organizationUser);
return token;
}
[Theory]
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Owner,