mirror of
https://github.com/bitwarden/server.git
synced 2025-06-07 19:50:32 -05:00
test: adding tests for AuthRequestsController; docs: added comments for the AuthRequestService.
This commit is contained in:
parent
ca711cd57e
commit
ab4cb18145
@ -20,14 +20,12 @@ public class AuthRequestsController(
|
|||||||
IUserService userService,
|
IUserService userService,
|
||||||
IAuthRequestRepository authRequestRepository,
|
IAuthRequestRepository authRequestRepository,
|
||||||
IGlobalSettings globalSettings,
|
IGlobalSettings globalSettings,
|
||||||
IAuthRequestService authRequestService,
|
IAuthRequestService authRequestService) : Controller
|
||||||
IFeatureService featureService) : Controller
|
|
||||||
{
|
{
|
||||||
private readonly IUserService _userService = userService;
|
private readonly IUserService _userService = userService;
|
||||||
private readonly IAuthRequestRepository _authRequestRepository = authRequestRepository;
|
private readonly IAuthRequestRepository _authRequestRepository = authRequestRepository;
|
||||||
private readonly IGlobalSettings _globalSettings = globalSettings;
|
private readonly IGlobalSettings _globalSettings = globalSettings;
|
||||||
private readonly IAuthRequestService _authRequestService = authRequestService;
|
private readonly IAuthRequestService _authRequestService = authRequestService;
|
||||||
private readonly IFeatureService _featureService = featureService;
|
|
||||||
|
|
||||||
[HttpGet("")]
|
[HttpGet("")]
|
||||||
public async Task<ListResponseModel<AuthRequestResponseModel>> Get()
|
public async Task<ListResponseModel<AuthRequestResponseModel>> Get()
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
using Bit.Core.Auth.Entities;
|
using Bit.Core.Auth.Entities;
|
||||||
|
using Bit.Core.Auth.Exceptions;
|
||||||
using Bit.Core.Auth.Models.Api.Request.AuthRequest;
|
using Bit.Core.Auth.Models.Api.Request.AuthRequest;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Settings;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
@ -8,8 +11,24 @@ namespace Bit.Core.Auth.Services;
|
|||||||
|
|
||||||
public interface IAuthRequestService
|
public interface IAuthRequestService
|
||||||
{
|
{
|
||||||
Task<AuthRequest?> GetAuthRequestAsync(Guid id, Guid userId);
|
/// <summary>
|
||||||
Task<AuthRequest?> GetValidatedAuthRequestAsync(Guid id, string code);
|
/// fetches an authRequest by Id. Returns AuthRequest if AuthRequest.UserId mateches
|
||||||
|
/// userId. Returns null if the user doesn't match or if the AuthRequest is not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authRequestId">Authrequest Id being fetched</param>
|
||||||
|
/// <param name="userId">user who owns AuthRequest</param>
|
||||||
|
/// <returns>An AuthRequest or null</returns>
|
||||||
|
Task<AuthRequest?> GetAuthRequestAsync(Guid authRequestId, Guid userId);
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches the authrequest from the database with the id provided. Then checks
|
||||||
|
/// the accessCode against the AuthRequest.AccessCode from the database. accessCodes
|
||||||
|
/// must match the found authRequest, and the AuthRequest must not be expired. Expiration
|
||||||
|
/// is configured in <see cref="GlobalSettings"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authRequestId">AuthRequest being acted on</param>
|
||||||
|
/// <param name="accessCode">Access code of the authrequest, must match saved database value</param>
|
||||||
|
/// <returns>A valid AuthRequest or null</returns>
|
||||||
|
Task<AuthRequest?> GetValidatedAuthRequestAsync(Guid authRequestId, string accessCode);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Validates and Creates an <see cref="AuthRequest" /> in the database, as well as pushes it through notifications services
|
/// Validates and Creates an <see cref="AuthRequest" /> in the database, as well as pushes it through notifications services
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -17,5 +36,16 @@ public interface IAuthRequestService
|
|||||||
/// This method can only be called inside of an HTTP call because of it's reliance on <see cref="ICurrentContext" />
|
/// This method can only be called inside of an HTTP call because of it's reliance on <see cref="ICurrentContext" />
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
Task<AuthRequest> CreateAuthRequestAsync(AuthRequestCreateRequestModel model);
|
Task<AuthRequest> CreateAuthRequestAsync(AuthRequestCreateRequestModel model);
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the AuthRequest per the AuthRequestUpdateRequestModel context. This approves
|
||||||
|
/// or rejects the login request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="authRequestId">AuthRequest being acted on.</param>
|
||||||
|
/// <param name="userId">User acting on AuthRequest</param>
|
||||||
|
/// <param name="model">Update context for the AuthRequest</param>
|
||||||
|
/// <returns>retuns an AuthRequest or throws an exception</returns>
|
||||||
|
/// <exception cref="DuplicateAuthRequestException">Thows if the AuthRequest has already been Approved/Rejected</exception>
|
||||||
|
/// <exception cref="NotFoundException">Throws if the AuthRequest as expired or the userId doesn't match</exception>
|
||||||
|
/// <exception cref="BadRequestException">Throws if the device isn't associated with the UserId</exception>
|
||||||
Task<AuthRequest> UpdateAuthRequestAsync(Guid authRequestId, Guid userId, AuthRequestUpdateRequestModel model);
|
Task<AuthRequest> UpdateAuthRequestAsync(Guid authRequestId, Guid userId, AuthRequestUpdateRequestModel model);
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,9 @@ public class AuthRequestService : IAuthRequestService
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AuthRequest?> GetAuthRequestAsync(Guid id, Guid userId)
|
public async Task<AuthRequest?> GetAuthRequestAsync(Guid authRequestId, Guid userId)
|
||||||
{
|
{
|
||||||
var authRequest = await _authRequestRepository.GetByIdAsync(id);
|
var authRequest = await _authRequestRepository.GetByIdAsync(authRequestId);
|
||||||
if (authRequest == null || authRequest.UserId != userId)
|
if (authRequest == null || authRequest.UserId != userId)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -69,10 +69,10 @@ public class AuthRequestService : IAuthRequestService
|
|||||||
return authRequest;
|
return authRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AuthRequest?> GetValidatedAuthRequestAsync(Guid id, string code)
|
public async Task<AuthRequest?> GetValidatedAuthRequestAsync(Guid authRequestId, string accessCode)
|
||||||
{
|
{
|
||||||
var authRequest = await _authRequestRepository.GetByIdAsync(id);
|
var authRequest = await _authRequestRepository.GetByIdAsync(authRequestId);
|
||||||
if (authRequest == null || !CoreHelpers.FixedTimeEquals(authRequest.AccessCode, code))
|
if (authRequest == null || !CoreHelpers.FixedTimeEquals(authRequest.AccessCode, accessCode))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,4 @@
|
|||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
<ProjectReference Include="..\Common\Common.csproj" />
|
||||||
<ProjectReference Include="..\Core.Test\Core.Test.csproj" />
|
<ProjectReference Include="..\Core.Test\Core.Test.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Auth\" />
|
|
||||||
<Folder Include="Auth\Controllers\" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
257
test/Api.Test/Auth/Controllers/AuthRequestsControllerTests.cs
Normal file
257
test/Api.Test/Auth/Controllers/AuthRequestsControllerTests.cs
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
using System.Security.Claims;
|
||||||
|
using Bit.Api.Auth.Controllers;
|
||||||
|
using Bit.Api.Auth.Models.Response;
|
||||||
|
using Bit.Api.Models.Response;
|
||||||
|
using Bit.Core.Auth.Entities;
|
||||||
|
using Bit.Core.Auth.Enums;
|
||||||
|
using Bit.Core.Auth.Models.Api.Request.AuthRequest;
|
||||||
|
using Bit.Core.Auth.Services;
|
||||||
|
using Bit.Core.Entities;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
using Bit.Core.Settings;
|
||||||
|
using Bit.Test.Common.AutoFixture;
|
||||||
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
|
using NSubstitute;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Bit.Api.Test.Auth.Controllers;
|
||||||
|
|
||||||
|
[ControllerCustomize(typeof(AuthRequestsController))]
|
||||||
|
[SutProviderCustomize]
|
||||||
|
public class AuthRequestsControllerTests
|
||||||
|
{
|
||||||
|
const string _testGlobalSettingsBaseUri = "https://vault.test.dev";
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task Get_ReturnsExpectedResult(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
User user,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetBaseServiceUri(sutProvider);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetProperUserId(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user.Id);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IAuthRequestRepository>()
|
||||||
|
.GetManyByUserIdAsync(user.Id)
|
||||||
|
.Returns([authRequest]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.Get();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
var expectedCount = 1;
|
||||||
|
Assert.Equal(result.Data.Count(), expectedCount);
|
||||||
|
Assert.IsType<ListResponseModel<AuthRequestResponseModel>>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task GetById_ThrowsNotFoundException(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
User user,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetProperUserId(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user.Id);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IAuthRequestService>()
|
||||||
|
.GetAuthRequestAsync(authRequest.Id, user.Id)
|
||||||
|
.Returns((AuthRequest)null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
var exception = await Assert.ThrowsAsync<NotFoundException>(
|
||||||
|
() => sutProvider.Sut.Get(authRequest.Id));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task GetById_ReturnsAuthRequest(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
User user,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetBaseServiceUri(sutProvider);
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetProperUserId(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user.Id);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IAuthRequestService>()
|
||||||
|
.GetAuthRequestAsync(authRequest.Id, user.Id)
|
||||||
|
.Returns(authRequest);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.Get(authRequest.Id);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.IsType<AuthRequestResponseModel>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task GetPending_ReturnsExpectedResult(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
User user,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetBaseServiceUri(sutProvider);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetProperUserId(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user.Id);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IAuthRequestRepository>()
|
||||||
|
.GetManyPendingAuthRequestByUserId(user.Id)
|
||||||
|
.Returns([authRequest]);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.GetPendingAuthRequestsAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
var expectedCount = 1;
|
||||||
|
Assert.Equal(result.Data.Count(), expectedCount);
|
||||||
|
Assert.IsType<ListResponseModel<AuthRequestResponseModel>>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task GetResponseById_ThrowsNotFoundException(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
sutProvider.GetDependency<IAuthRequestService>()
|
||||||
|
.GetValidatedAuthRequestAsync(authRequest.Id, authRequest.AccessCode)
|
||||||
|
.Returns((AuthRequest)null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
var exception = await Assert.ThrowsAsync<NotFoundException>(
|
||||||
|
() => sutProvider.Sut.GetResponse(authRequest.Id, authRequest.AccessCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task GetResponseById_ReturnsAuthRequest(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetBaseServiceUri(sutProvider);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IAuthRequestService>()
|
||||||
|
.GetValidatedAuthRequestAsync(authRequest.Id, authRequest.AccessCode)
|
||||||
|
.Returns(authRequest);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.GetResponse(authRequest.Id, authRequest.AccessCode);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.IsType<AuthRequestResponseModel>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task Post_AdminApprovalRequest_ThrowsBadRequestException(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
AuthRequestCreateRequestModel authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
authRequest.Type = AuthRequestType.AdminApproval;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||||
|
() => sutProvider.Sut.Post(authRequest));
|
||||||
|
|
||||||
|
var expectedMessage = "You must be authenticated to create a request of that type.";
|
||||||
|
Assert.Equal(exception.Message, expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task Post_ReturnsAuthRequest(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
AuthRequestCreateRequestModel requestModel,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetBaseServiceUri(sutProvider);
|
||||||
|
|
||||||
|
requestModel.Type = AuthRequestType.AuthenticateAndUnlock;
|
||||||
|
sutProvider.GetDependency<IAuthRequestService>()
|
||||||
|
.CreateAuthRequestAsync(requestModel)
|
||||||
|
.Returns(authRequest);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.Post(requestModel);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.IsType<AuthRequestResponseModel>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task PostAdminRequest_ReturnsAuthRequest(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
AuthRequestCreateRequestModel requestModel,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetBaseServiceUri(sutProvider);
|
||||||
|
|
||||||
|
requestModel.Type = AuthRequestType.AuthenticateAndUnlock;
|
||||||
|
sutProvider.GetDependency<IAuthRequestService>()
|
||||||
|
.CreateAuthRequestAsync(requestModel)
|
||||||
|
.Returns(authRequest);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.PostAdminRequest(requestModel);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.IsType<AuthRequestResponseModel>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory, BitAutoData]
|
||||||
|
public async Task Put_ReturnsAuthRequest(
|
||||||
|
SutProvider<AuthRequestsController> sutProvider,
|
||||||
|
User user,
|
||||||
|
AuthRequestUpdateRequestModel requestModel,
|
||||||
|
AuthRequest authRequest)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
SetBaseServiceUri(sutProvider);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserService>()
|
||||||
|
.GetProperUserId(Arg.Any<ClaimsPrincipal>())
|
||||||
|
.Returns(user.Id);
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IAuthRequestService>()
|
||||||
|
.UpdateAuthRequestAsync(authRequest.Id, user.Id, requestModel)
|
||||||
|
.Returns(authRequest);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut
|
||||||
|
.Put(authRequest.Id, requestModel);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
Assert.IsType<AuthRequestResponseModel>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetBaseServiceUri(SutProvider<AuthRequestsController> sutProvider)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IGlobalSettings>()
|
||||||
|
.BaseServiceUri
|
||||||
|
.Vault
|
||||||
|
.Returns(_testGlobalSettingsBaseUri);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user