Files
git.stella-ops.org/src/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardUserCredentialStoreTests.cs
2025-10-11 23:28:35 +03:00

103 lines
3.4 KiB
C#

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
using Mongo2Go;
using MongoDB.Driver;
using StellaOps.Authority.Plugins.Abstractions;
using StellaOps.Authority.Plugin.Standard.Security;
using StellaOps.Authority.Plugin.Standard.Storage;
namespace StellaOps.Authority.Plugin.Standard.Tests;
public class StandardUserCredentialStoreTests : IAsyncLifetime
{
private readonly MongoDbRunner runner;
private readonly IMongoDatabase database;
private readonly StandardPluginOptions options;
private readonly StandardUserCredentialStore store;
public StandardUserCredentialStoreTests()
{
runner = MongoDbRunner.Start(singleNodeReplSet: true);
var client = new MongoClient(runner.ConnectionString);
database = client.GetDatabase("authority-tests");
options = new StandardPluginOptions
{
PasswordPolicy = new PasswordPolicyOptions
{
MinimumLength = 8,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
RequireSymbol = false
},
Lockout = new LockoutOptions
{
Enabled = true,
MaxAttempts = 2,
WindowMinutes = 1
}
};
store = new StandardUserCredentialStore(
"standard",
database,
options,
new Pbkdf2PasswordHasher(),
NullLogger<StandardUserCredentialStore>.Instance);
}
[Fact]
public async Task VerifyPasswordAsync_ReturnsSuccess_ForValidCredentials()
{
var registration = new AuthorityUserRegistration(
"alice",
"Password1!",
"Alice",
null,
false,
new[] { "admin" },
new Dictionary<string, string?>());
var upsert = await store.UpsertUserAsync(registration, CancellationToken.None);
Assert.True(upsert.Succeeded);
var result = await store.VerifyPasswordAsync("alice", "Password1!", CancellationToken.None);
Assert.True(result.Succeeded);
Assert.Equal("alice", result.User?.Username);
}
[Fact]
public async Task VerifyPasswordAsync_EnforcesLockout_AfterRepeatedFailures()
{
await store.UpsertUserAsync(
new AuthorityUserRegistration(
"bob",
"Password1!",
"Bob",
null,
false,
new[] { "operator" },
new Dictionary<string, string?>()),
CancellationToken.None);
var first = await store.VerifyPasswordAsync("bob", "wrong", CancellationToken.None);
Assert.False(first.Succeeded);
Assert.Equal(AuthorityCredentialFailureCode.InvalidCredentials, first.FailureCode);
var second = await store.VerifyPasswordAsync("bob", "stillwrong", CancellationToken.None);
Assert.False(second.Succeeded);
Assert.Equal(AuthorityCredentialFailureCode.LockedOut, second.FailureCode);
Assert.NotNull(second.RetryAfter);
Assert.True(second.RetryAfter.Value > System.TimeSpan.Zero);
}
public Task InitializeAsync() => Task.CompletedTask;
public Task DisposeAsync()
{
runner.Dispose();
return Task.CompletedTask;
}
}