1
0
mirror of https://github.com/bitwarden/server synced 2026-01-15 06:53:26 +00:00
Files
server/test/Core.Test/Tools/Services/SendOwnerQueryTests.cs
John Harrington fa845a4753 [Tools] Update SendAuthenticationQuery, add new non-anonymous endpoints, and add PutRemoveAuth endpoint (#6786)
* update send api models to support new `email` field

* normalize authentication field evaluation order

* document send response converters

* add FIXME to remove unused constructor argument

* add FIXME to remove unused constructor argument

* introduce `tools-send-email-otp-listing` feature flag

* add `ISendOwnerQuery` to dependency graph

* fix broken tests

* added AuthType prop to send related models with test coverage and debt cleanup

* dotnet format

* add migrations

* dotnet format

* make SendsController null safe (tech debt)

* add AuthType col to Sends table, change Emails col length to 4000, and run migrations

* dotnet format

* update SPs to expect AuthType

* include SP updates in migrations

* remove migrations not intended for merge

* Revert "remove migrations not intended for merge"

This reverts commit 7df56e346a.

undo migrations removal

* extract AuthType inference to util method and remove SQLite file

* fix lints

* address review comments

* fix incorrect assignment and adopt SQL conventions

* fix column assignment order in Send_Update.sql

* remove space added to email list

* assign SQL default value of NULL to AuthType

* update SPs to match migration changes

* remove FF, update SendAuthQuery, and update tests

* new endpoints added but lack test coverage

* dotnet format

* add PutRemoveAuth endpoint with test coverage and tests for new non-anon endpoints

* update RequireFeatureFlag comment for clarity

* respond to Claude's findings

* add additional validation logic to new auth endpoints

* enforce auth policies on individual action methods

* remove JsonConverter directive for AuthType

* remove tools-send-email-otp-listing feature flag

---------

Co-authored-by:  Audrey  <audrey@audreyality.com>
Co-authored-by:  Audrey  <ajensen@bitwarden.com>
Co-authored-by: Daniel James Smith <2670567+djsmith85@users.noreply.github.com>
Co-authored-by: Alex Dragovich <46065570+itsadrago@users.noreply.github.com>
2026-01-14 14:07:46 -07:00

144 lines
4.6 KiB
C#

using System.Security.Claims;
using Bit.Core.Exceptions;
using Bit.Core.Services;
using Bit.Core.Tools.Entities;
using Bit.Core.Tools.Repositories;
using Bit.Core.Tools.SendFeatures.Queries;
using NSubstitute;
using Xunit;
namespace Bit.Core.Test.Tools.Services;
public class SendOwnerQueryTests
{
private readonly ISendRepository _sendRepository;
private readonly IUserService _userService;
private readonly SendOwnerQuery _sendOwnerQuery;
private readonly Guid _currentUserId = Guid.NewGuid();
private readonly ClaimsPrincipal _user;
public SendOwnerQueryTests()
{
_sendRepository = Substitute.For<ISendRepository>();
_userService = Substitute.For<IUserService>();
_user = new ClaimsPrincipal();
_userService.GetProperUserId(_user).Returns(_currentUserId);
_sendOwnerQuery = new SendOwnerQuery(_sendRepository, _userService);
}
[Fact]
public async Task Get_WithValidSendOwnedByUser_ReturnsExpectedSend()
{
// Arrange
var sendId = Guid.NewGuid();
var expectedSend = CreateSend(sendId, _currentUserId);
_sendRepository.GetByIdAsync(sendId).Returns(expectedSend);
// Act
var result = await _sendOwnerQuery.Get(sendId, _user);
// Assert
Assert.Same(expectedSend, result);
await _sendRepository.Received(1).GetByIdAsync(sendId);
}
[Fact]
public async Task Get_WithNonExistentSend_ThrowsNotFoundException()
{
// Arrange
var sendId = Guid.NewGuid();
_sendRepository.GetByIdAsync(sendId).Returns((Send?)null);
// Act & Assert
await Assert.ThrowsAsync<NotFoundException>(() => _sendOwnerQuery.Get(sendId, _user));
}
[Fact]
public async Task Get_WithSendOwnedByDifferentUser_ThrowsNotFoundException()
{
// Arrange
var sendId = Guid.NewGuid();
var differentUserId = Guid.NewGuid();
var send = CreateSend(sendId, differentUserId);
_sendRepository.GetByIdAsync(sendId).Returns(send);
// Act & Assert
await Assert.ThrowsAsync<NotFoundException>(() => _sendOwnerQuery.Get(sendId, _user));
}
[Fact]
public async Task Get_WithNullCurrentUserId_ThrowsBadRequestException()
{
// Arrange
var sendId = Guid.NewGuid();
var send = CreateSend(sendId, _currentUserId);
_sendRepository.GetByIdAsync(sendId).Returns(send);
var nullUser = new ClaimsPrincipal();
_userService.GetProperUserId(nullUser).Returns((Guid?)null);
// Act & Assert
var exception = await Assert.ThrowsAsync<BadRequestException>(() => _sendOwnerQuery.Get(sendId, nullUser));
Assert.Equal("invalid user.", exception.Message);
}
[Fact]
public async Task GetOwned_ReturnsAllSendsIncludingEmailOTP()
{
// Arrange
var sends = new List<Send>
{
CreateSend(Guid.NewGuid(), _currentUserId, emails: null),
CreateSend(Guid.NewGuid(), _currentUserId, emails: "test@example.com"),
CreateSend(Guid.NewGuid(), _currentUserId, emails: "other@example.com")
};
_sendRepository.GetManyByUserIdAsync(_currentUserId).Returns(sends);
// Act
var result = await _sendOwnerQuery.GetOwned(_user);
// Assert
Assert.Equal(3, result.Count);
Assert.Contains(sends[0], result);
Assert.Contains(sends[1], result);
Assert.Contains(sends[2], result);
await _sendRepository.Received(1).GetManyByUserIdAsync(_currentUserId);
}
[Fact]
public async Task GetOwned_WithNullCurrentUserId_ThrowsBadRequestException()
{
// Arrange
var nullUser = new ClaimsPrincipal();
_userService.GetProperUserId(nullUser).Returns((Guid?)null);
// Act & Assert
var exception = await Assert.ThrowsAsync<BadRequestException>(() => _sendOwnerQuery.GetOwned(nullUser));
Assert.Equal("invalid user.", exception.Message);
}
[Fact]
public async Task GetOwned_WithEmptyCollection_ReturnsEmptyCollection()
{
// Arrange
var emptySends = new List<Send>();
_sendRepository.GetManyByUserIdAsync(_currentUserId).Returns(emptySends);
// Act
var result = await _sendOwnerQuery.GetOwned(_user);
// Assert
Assert.Empty(result);
await _sendRepository.Received(1).GetManyByUserIdAsync(_currentUserId);
}
private static Send CreateSend(Guid id, Guid userId, string? emails = null)
{
return new Send
{
Id = id,
UserId = userId,
Emails = emails
};
}
}