mirror of
https://github.com/bitwarden/server
synced 2026-01-01 08:03:23 +00:00
[PM-23249] Prevent log-out when changing KDF settings (#6349)
* Prevent log-out when changing KDF settings with feature flag. * validate salt unchanged for user to throw bad request (400), not internal server error (500) * change kdf integration tests * failing tests * iuncorrect tests wording * conditional logout * log out reason as enum * explicit naming
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
#nullable enable
|
||||
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.KeyManagement.Kdf.Implementations;
|
||||
using Bit.Core.KeyManagement.Models.Data;
|
||||
using Bit.Core.Platform.Push;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
@@ -21,16 +23,12 @@ public class ChangeKdfCommandTests
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_ChangesKdfAsync(SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().UpdatePasswordHash(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(IdentityResult.Success));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().UpdatePasswordHash(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(IdentityResult.Success));
|
||||
|
||||
var kdf = new KdfSettings
|
||||
{
|
||||
KdfType = Enums.KdfType.Argon2id,
|
||||
Iterations = 4,
|
||||
Memory = 512,
|
||||
Parallelism = 4
|
||||
};
|
||||
var kdf = new KdfSettings { KdfType = Enums.KdfType.Argon2id, Iterations = 4, Memory = 512, Parallelism = 4 };
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = kdf,
|
||||
@@ -59,13 +57,7 @@ public class ChangeKdfCommandTests
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_UserIsNull_ThrowsArgumentNullException(SutProvider<ChangeKdfCommand> sutProvider)
|
||||
{
|
||||
var kdf = new KdfSettings
|
||||
{
|
||||
KdfType = Enums.KdfType.Argon2id,
|
||||
Iterations = 4,
|
||||
Memory = 512,
|
||||
Parallelism = 4
|
||||
};
|
||||
var kdf = new KdfSettings { KdfType = Enums.KdfType.Argon2id, Iterations = 4, Memory = 512, Parallelism = 4 };
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = kdf,
|
||||
@@ -85,17 +77,13 @@ public class ChangeKdfCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_WrongPassword_ReturnsPasswordMismatch(SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
public async Task ChangeKdfAsync_WrongPassword_ReturnsPasswordMismatch(SutProvider<ChangeKdfCommand> sutProvider,
|
||||
User user)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(false));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(false));
|
||||
|
||||
var kdf = new KdfSettings
|
||||
{
|
||||
KdfType = Enums.KdfType.Argon2id,
|
||||
Iterations = 4,
|
||||
Memory = 512,
|
||||
Parallelism = 4
|
||||
};
|
||||
var kdf = new KdfSettings { KdfType = Enums.KdfType.Argon2id, Iterations = 4, Memory = 512, Parallelism = 4 };
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = kdf,
|
||||
@@ -116,7 +104,9 @@ public class ChangeKdfCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_WithAuthenticationAndUnlockData_UpdatesUserCorrectly(SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
public async Task
|
||||
ChangeKdfAsync_WithAuthenticationAndUnlockDataAndNoLogoutOnKdfChangeFeatureFlagOff_UpdatesUserCorrectlyAndLogsOut(
|
||||
SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
{
|
||||
var constantKdf = new KdfSettings
|
||||
{
|
||||
@@ -137,8 +127,12 @@ public class ChangeKdfCommandTests
|
||||
MasterKeyWrappedUserKey = "new-wrapped-key",
|
||||
Salt = user.GetMasterPasswordSalt()
|
||||
};
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().UpdatePasswordHash(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(IdentityResult.Success));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>()
|
||||
.UpdatePasswordHash(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<bool>())
|
||||
.Returns(Task.FromResult(IdentityResult.Success));
|
||||
sutProvider.GetDependency<IFeatureService>().IsEnabled(Arg.Any<string>()).Returns(false);
|
||||
|
||||
await sutProvider.Sut.ChangeKdfAsync(user, "masterPassword", authenticationData, unlockData);
|
||||
|
||||
@@ -150,17 +144,79 @@ public class ChangeKdfCommandTests
|
||||
&& u.KdfParallelism == constantKdf.Parallelism
|
||||
&& u.Key == "new-wrapped-key"
|
||||
));
|
||||
await sutProvider.GetDependency<IUserService>().Received(1).UpdatePasswordHash(user,
|
||||
authenticationData.MasterPasswordAuthenticationHash, validatePassword: true, refreshStamp: true);
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(1).PushLogOutAsync(user.Id);
|
||||
sutProvider.GetDependency<IFeatureService>().Received(1).IsEnabled(FeatureFlagKeys.NoLogoutOnKdfChange);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_KdfNotEqualBetweenAuthAndUnlock_ThrowsBadRequestException(SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
public async Task
|
||||
ChangeKdfAsync_WithAuthenticationAndUnlockDataAndNoLogoutOnKdfChangeFeatureFlagOn_UpdatesUserCorrectlyAndDoesNotLogOut(
|
||||
SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
var constantKdf = new KdfSettings
|
||||
{
|
||||
KdfType = Enums.KdfType.Argon2id,
|
||||
Iterations = 5,
|
||||
Memory = 1024,
|
||||
Parallelism = 4
|
||||
};
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = constantKdf,
|
||||
MasterPasswordAuthenticationHash = "new-auth-hash",
|
||||
Salt = user.GetMasterPasswordSalt()
|
||||
};
|
||||
var unlockData = new MasterPasswordUnlockData
|
||||
{
|
||||
Kdf = constantKdf,
|
||||
MasterKeyWrappedUserKey = "new-wrapped-key",
|
||||
Salt = user.GetMasterPasswordSalt()
|
||||
};
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>()
|
||||
.UpdatePasswordHash(Arg.Any<User>(), Arg.Any<string>(), Arg.Any<bool>(), Arg.Any<bool>())
|
||||
.Returns(Task.FromResult(IdentityResult.Success));
|
||||
sutProvider.GetDependency<IFeatureService>().IsEnabled(Arg.Any<string>()).Returns(true);
|
||||
|
||||
await sutProvider.Sut.ChangeKdfAsync(user, "masterPassword", authenticationData, unlockData);
|
||||
|
||||
await sutProvider.GetDependency<IUserRepository>().Received(1).ReplaceAsync(Arg.Is<User>(u =>
|
||||
u.Id == user.Id
|
||||
&& u.Kdf == constantKdf.KdfType
|
||||
&& u.KdfIterations == constantKdf.Iterations
|
||||
&& u.KdfMemory == constantKdf.Memory
|
||||
&& u.KdfParallelism == constantKdf.Parallelism
|
||||
&& u.Key == "new-wrapped-key"
|
||||
));
|
||||
await sutProvider.GetDependency<IUserService>().Received(1).UpdatePasswordHash(user,
|
||||
authenticationData.MasterPasswordAuthenticationHash, validatePassword: true, refreshStamp: false);
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(1)
|
||||
.PushLogOutAsync(user.Id, false, PushNotificationLogOutReason.KdfChange);
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(1).PushSyncSettingsAsync(user.Id);
|
||||
sutProvider.GetDependency<IFeatureService>().Received(1).IsEnabled(FeatureFlagKeys.NoLogoutOnKdfChange);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_KdfNotEqualBetweenAuthAndUnlock_ThrowsBadRequestException(
|
||||
SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = new KdfSettings { KdfType = Enums.KdfType.Argon2id, Iterations = 4, Memory = 512, Parallelism = 4 },
|
||||
Kdf = new KdfSettings
|
||||
{
|
||||
KdfType = Enums.KdfType.Argon2id,
|
||||
Iterations = 4,
|
||||
Memory = 512,
|
||||
Parallelism = 4
|
||||
},
|
||||
MasterPasswordAuthenticationHash = "new-auth-hash",
|
||||
Salt = user.GetMasterPasswordSalt()
|
||||
};
|
||||
@@ -176,9 +232,11 @@ public class ChangeKdfCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_AuthDataSaltMismatch_Throws(SutProvider<ChangeKdfCommand> sutProvider, User user, KdfSettings kdf)
|
||||
public async Task ChangeKdfAsync_AuthDataSaltMismatch_Throws(SutProvider<ChangeKdfCommand> sutProvider, User user,
|
||||
KdfSettings kdf)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
@@ -192,15 +250,17 @@ public class ChangeKdfCommandTests
|
||||
MasterKeyWrappedUserKey = "new-wrapped-key",
|
||||
Salt = user.GetMasterPasswordSalt()
|
||||
};
|
||||
await Assert.ThrowsAsync<ArgumentException>(async () =>
|
||||
await Assert.ThrowsAsync<BadRequestException>(async () =>
|
||||
await sutProvider.Sut.ChangeKdfAsync(user, "masterPassword", authenticationData, unlockData));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_UnlockDataSaltMismatch_Throws(SutProvider<ChangeKdfCommand> sutProvider, User user, KdfSettings kdf)
|
||||
public async Task ChangeKdfAsync_UnlockDataSaltMismatch_Throws(SutProvider<ChangeKdfCommand> sutProvider, User user,
|
||||
KdfSettings kdf)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
@@ -214,25 +274,22 @@ public class ChangeKdfCommandTests
|
||||
MasterKeyWrappedUserKey = "new-wrapped-key",
|
||||
Salt = "different-salt"
|
||||
};
|
||||
await Assert.ThrowsAsync<ArgumentException>(async () =>
|
||||
await Assert.ThrowsAsync<BadRequestException>(async () =>
|
||||
await sutProvider.Sut.ChangeKdfAsync(user, "masterPassword", authenticationData, unlockData));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_UpdatePasswordHashFails_ReturnsFailure(SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
public async Task ChangeKdfAsync_UpdatePasswordHashFails_ReturnsFailure(SutProvider<ChangeKdfCommand> sutProvider,
|
||||
User user)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
var failedResult = IdentityResult.Failed(new IdentityError { Code = "TestFail", Description = "Test fail" });
|
||||
sutProvider.GetDependency<IUserService>().UpdatePasswordHash(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(failedResult));
|
||||
sutProvider.GetDependency<IUserService>().UpdatePasswordHash(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(failedResult));
|
||||
|
||||
var kdf = new KdfSettings
|
||||
{
|
||||
KdfType = Enums.KdfType.Argon2id,
|
||||
Iterations = 4,
|
||||
Memory = 512,
|
||||
Parallelism = 4
|
||||
};
|
||||
var kdf = new KdfSettings { KdfType = Enums.KdfType.Argon2id, Iterations = 4, Memory = 512, Parallelism = 4 };
|
||||
var authenticationData = new MasterPasswordAuthenticationData
|
||||
{
|
||||
Kdf = kdf,
|
||||
@@ -253,9 +310,11 @@ public class ChangeKdfCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_InvalidKdfSettings_ThrowsBadRequestException(SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
public async Task ChangeKdfAsync_InvalidKdfSettings_ThrowsBadRequestException(
|
||||
SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
|
||||
// Create invalid KDF settings (iterations too low for PBKDF2)
|
||||
var invalidKdf = new KdfSettings
|
||||
@@ -287,9 +346,11 @@ public class ChangeKdfCommandTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task ChangeKdfAsync_InvalidArgon2Settings_ThrowsBadRequestException(SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
public async Task ChangeKdfAsync_InvalidArgon2Settings_ThrowsBadRequestException(
|
||||
SutProvider<ChangeKdfCommand> sutProvider, User user)
|
||||
{
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>()).Returns(Task.FromResult(true));
|
||||
sutProvider.GetDependency<IUserService>().CheckPasswordAsync(Arg.Any<User>(), Arg.Any<string>())
|
||||
.Returns(Task.FromResult(true));
|
||||
|
||||
// Create invalid Argon2 KDF settings (memory too high)
|
||||
var invalidKdf = new KdfSettings
|
||||
@@ -318,5 +379,4 @@ public class ChangeKdfCommandTests
|
||||
|
||||
Assert.Equal("KDF settings are invalid.", exception.Message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -358,20 +358,28 @@ public class AzureQueuePushEngineTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task PushLogOutAsync_SendsExpectedResponse(bool excludeCurrentContext)
|
||||
[InlineData(true, null)]
|
||||
[InlineData(true, PushNotificationLogOutReason.KdfChange)]
|
||||
[InlineData(false, null)]
|
||||
[InlineData(false, PushNotificationLogOutReason.KdfChange)]
|
||||
public async Task PushLogOutAsync_SendsExpectedResponse(bool excludeCurrentContext,
|
||||
PushNotificationLogOutReason? reason)
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
var payload = new JsonObject
|
||||
{
|
||||
["UserId"] = userId
|
||||
};
|
||||
if (reason != null)
|
||||
{
|
||||
payload["Reason"] = (int)reason;
|
||||
}
|
||||
|
||||
var expectedPayload = new JsonObject
|
||||
{
|
||||
["Type"] = 11,
|
||||
["Payload"] = new JsonObject
|
||||
{
|
||||
["UserId"] = userId,
|
||||
["Date"] = _fakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||
},
|
||||
["Payload"] = payload,
|
||||
};
|
||||
|
||||
if (excludeCurrentContext)
|
||||
@@ -380,7 +388,7 @@ public class AzureQueuePushEngineTests
|
||||
}
|
||||
|
||||
await VerifyNotificationAsync(
|
||||
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext),
|
||||
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext, reason),
|
||||
expectedPayload
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Text.Json.Nodes;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.Platform.Push.Internal;
|
||||
using Bit.Core.Tools.Entities;
|
||||
@@ -193,7 +194,8 @@ public class NotificationsApiPushEngineTests : PushTestBase
|
||||
};
|
||||
}
|
||||
|
||||
protected override JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext)
|
||||
protected override JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext,
|
||||
PushNotificationLogOutReason? reason)
|
||||
{
|
||||
JsonNode? contextId = excludeCurrentContext ? DeviceIdentifier : null;
|
||||
|
||||
@@ -203,7 +205,7 @@ public class NotificationsApiPushEngineTests : PushTestBase
|
||||
["Payload"] = new JsonObject
|
||||
{
|
||||
["UserId"] = userId,
|
||||
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||
["Reason"] = reason != null ? (int)reason : null
|
||||
},
|
||||
["ContextId"] = contextId,
|
||||
};
|
||||
|
||||
@@ -86,7 +86,8 @@ public abstract class PushTestBase
|
||||
protected abstract JsonNode GetPushSyncOrganizationsPayload(Guid userId);
|
||||
protected abstract JsonNode GetPushSyncOrgKeysPayload(Guid userId);
|
||||
protected abstract JsonNode GetPushSyncSettingsPayload(Guid userId);
|
||||
protected abstract JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext);
|
||||
protected abstract JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext,
|
||||
PushNotificationLogOutReason? reason);
|
||||
protected abstract JsonNode GetPushSendCreatePayload(Send send);
|
||||
protected abstract JsonNode GetPushSendUpdatePayload(Send send);
|
||||
protected abstract JsonNode GetPushSendDeletePayload(Send send);
|
||||
@@ -263,15 +264,18 @@ public abstract class PushTestBase
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task PushLogOutAsync_SendsExpectedResponse(bool excludeCurrentContext)
|
||||
[InlineData(true, null)]
|
||||
[InlineData(true, PushNotificationLogOutReason.KdfChange)]
|
||||
[InlineData(false, null)]
|
||||
[InlineData(false, PushNotificationLogOutReason.KdfChange)]
|
||||
public async Task PushLogOutAsync_SendsExpectedResponse(bool excludeCurrentContext,
|
||||
PushNotificationLogOutReason? reason)
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
await VerifyNotificationAsync(
|
||||
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext),
|
||||
GetPushLogOutPayload(userId, excludeCurrentContext)
|
||||
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext, reason),
|
||||
GetPushLogOutPayload(userId, excludeCurrentContext, reason)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Text.Json.Nodes;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.Auth.Entities;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.NotificationCenter.Entities;
|
||||
using Bit.Core.Platform.Push.Internal;
|
||||
using Bit.Core.Repositories;
|
||||
@@ -64,7 +65,7 @@ public class RelayPushNotificationServiceTests : PushTestBase
|
||||
["UserId"] = cipher.UserId,
|
||||
["OrganizationId"] = null,
|
||||
// Currently CollectionIds are not passed along from the method signature
|
||||
// to the request body.
|
||||
// to the request body.
|
||||
["CollectionIds"] = null,
|
||||
["RevisionDate"] = cipher.RevisionDate,
|
||||
},
|
||||
@@ -88,7 +89,7 @@ public class RelayPushNotificationServiceTests : PushTestBase
|
||||
["UserId"] = cipher.UserId,
|
||||
["OrganizationId"] = null,
|
||||
// Currently CollectionIds are not passed along from the method signature
|
||||
// to the request body.
|
||||
// to the request body.
|
||||
["CollectionIds"] = null,
|
||||
["RevisionDate"] = cipher.RevisionDate,
|
||||
},
|
||||
@@ -274,7 +275,8 @@ public class RelayPushNotificationServiceTests : PushTestBase
|
||||
};
|
||||
}
|
||||
|
||||
protected override JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext)
|
||||
protected override JsonNode GetPushLogOutPayload(Guid userId, bool excludeCurrentContext,
|
||||
PushNotificationLogOutReason? reason)
|
||||
{
|
||||
JsonNode? identifier = excludeCurrentContext ? DeviceIdentifier : null;
|
||||
|
||||
@@ -288,7 +290,7 @@ public class RelayPushNotificationServiceTests : PushTestBase
|
||||
["Payload"] = new JsonObject
|
||||
{
|
||||
["UserId"] = userId,
|
||||
["Date"] = FakeTimeProvider.GetUtcNow().UtcDateTime,
|
||||
["Reason"] = reason != null ? (int)reason : null
|
||||
},
|
||||
["ClientType"] = null,
|
||||
["InstallationId"] = null,
|
||||
|
||||
@@ -404,16 +404,18 @@ public class NotificationHubPushNotificationServiceTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task PushLogOutAsync_SendExpectedData(bool excludeCurrentContext)
|
||||
[InlineData(true, null)]
|
||||
[InlineData(true, PushNotificationLogOutReason.KdfChange)]
|
||||
[InlineData(false, null)]
|
||||
[InlineData(false, PushNotificationLogOutReason.KdfChange)]
|
||||
public async Task PushLogOutAsync_SendExpectedData(bool excludeCurrentContext, PushNotificationLogOutReason? reason)
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
|
||||
var expectedPayload = new JsonObject
|
||||
{
|
||||
["UserId"] = userId,
|
||||
["Date"] = _now,
|
||||
["Reason"] = reason != null ? (int)reason : null,
|
||||
};
|
||||
|
||||
var expectedTag = excludeCurrentContext
|
||||
@@ -421,7 +423,7 @@ public class NotificationHubPushNotificationServiceTests
|
||||
: $"(template:payload_userId:{userId})";
|
||||
|
||||
await VerifyNotificationAsync(
|
||||
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext),
|
||||
async sut => await sut.PushLogOutAsync(userId, excludeCurrentContext, reason),
|
||||
PushType.LogOut,
|
||||
expectedPayload,
|
||||
expectedTag
|
||||
|
||||
Reference in New Issue
Block a user