1
0
mirror of https://github.com/bitwarden/server synced 2025-12-26 13:13:24 +00:00

feat(auth-validator): [PM-22975] Client Version Validator - initial implementation

This commit is contained in:
Patrick Pimentel
2025-11-17 15:46:02 -05:00
parent d1fecc2a0f
commit 1c4fd6ca24
20 changed files with 769 additions and 31 deletions

View File

@@ -0,0 +1,34 @@
using Bit.Core.Entities;
using Bit.Core.KeyManagement.Queries;
using Bit.Core.KeyManagement.Queries.Interfaces;
using Xunit;
namespace Bit.Core.Test.KeyManagement.Queries;
public class GetMinimumClientVersionForUserQueryTests
{
private class FakeIsV2Query : IIsV2EncryptionUserQuery
{
private readonly bool _isV2;
public FakeIsV2Query(bool isV2) { _isV2 = isV2; }
public Task<bool> Run(User user) => Task.FromResult(_isV2);
}
[Fact]
public async Task Run_ReturnsMinVersion_ForV2User()
{
var sut = new GetMinimumClientVersionForUserQuery(new FakeIsV2Query(true));
var version = await sut.Run(new User());
Assert.Equal(Core.KeyManagement.Constants.MinimumClientVersion, version);
}
[Fact]
public async Task Run_ReturnsNull_ForV1User()
{
var sut = new GetMinimumClientVersionForUserQuery(new FakeIsV2Query(false));
var version = await sut.Run(new User());
Assert.Null(version);
}
}

View File

@@ -0,0 +1,65 @@
using Bit.Core.Entities;
using Bit.Core.KeyManagement.Entities;
using Bit.Core.KeyManagement.Enums;
using Bit.Core.KeyManagement.Models.Data;
using Bit.Core.KeyManagement.Queries;
using Bit.Core.KeyManagement.Repositories;
using Bit.Core.KeyManagement.UserKey;
using Xunit;
namespace Bit.Core.Test.KeyManagement.Queries;
public class IsV2EncryptionUserQueryTests
{
private class FakeSigRepo : IUserSignatureKeyPairRepository
{
private readonly bool _hasKeys;
public FakeSigRepo(bool hasKeys) { _hasKeys = hasKeys; }
public Task<SignatureKeyPairData?> GetByUserIdAsync(Guid userId)
=> Task.FromResult(_hasKeys ? new SignatureKeyPairData(SignatureAlgorithm.Ed25519, "7.cose_signing", "vk") : null);
// Unused in tests
public Task<IEnumerable<UserSignatureKeyPair>> GetManyAsync(IEnumerable<Guid> ids) => throw new NotImplementedException();
public Task<UserSignatureKeyPair> GetByIdAsync(Guid id) => throw new NotImplementedException();
public Task<UserSignatureKeyPair> CreateAsync(UserSignatureKeyPair obj) => throw new NotImplementedException();
public Task ReplaceAsync(UserSignatureKeyPair obj) => throw new NotImplementedException();
public Task UpsertAsync(UserSignatureKeyPair obj) => throw new NotImplementedException();
public Task DeleteAsync(UserSignatureKeyPair obj) => throw new NotImplementedException();
public Task DeleteAsync(Guid id) => throw new NotImplementedException();
public UpdateEncryptedDataForKeyRotation UpdateForKeyRotation(Guid grantorId, SignatureKeyPairData signatureKeyPair) => throw new NotImplementedException();
public UpdateEncryptedDataForKeyRotation SetUserSignatureKeyPair(Guid userId, SignatureKeyPairData signatureKeyPair) => throw new NotImplementedException();
}
[Fact]
public async Task Run_ReturnsTrue_ForV2State()
{
var user = new User { Id = Guid.NewGuid(), PrivateKey = "7.cose" };
var sut = new IsV2EncryptionUserQuery(new FakeSigRepo(true));
var result = await sut.Run(user);
Assert.True(result);
}
[Fact]
public async Task Run_ReturnsFalse_ForV1State()
{
var user = new User { Id = Guid.NewGuid(), PrivateKey = "2.iv|ct|mac" };
var sut = new IsV2EncryptionUserQuery(new FakeSigRepo(false));
var result = await sut.Run(user);
Assert.False(result);
}
[Fact]
public async Task Run_ThrowsForInvalidMixedState()
{
var user = new User { Id = Guid.NewGuid(), PrivateKey = "7.cose" };
var sut = new IsV2EncryptionUserQuery(new FakeSigRepo(false));
await Assert.ThrowsAsync<InvalidOperationException>(async () => await sut.Run(user));
}
}