140 lines
5.3 KiB
C#
140 lines
5.3 KiB
C#
using Omika.Diagnostics.Security;
|
|
|
|
namespace Omika.Diagnostics.Tests;
|
|
|
|
/// <summary>
|
|
/// T23 — Règles de validation des utilisateurs (username/password/rôle) + protections
|
|
/// d'administration (dernier Admin, auto-désactivation, auto-rétrogradation) + hash factice.
|
|
/// </summary>
|
|
public class DiagnosticUserPolicyTests
|
|
{
|
|
// -------------------------------------------------- username ----
|
|
[Theory]
|
|
[InlineData("jean.dupont")]
|
|
[InlineData("admin-local")]
|
|
[InlineData("a_b-c.d")]
|
|
[InlineData("ABC123")]
|
|
public void Username_Valid(string username) =>
|
|
Assert.True(DiagnosticUserRules.IsValidUsername(username));
|
|
|
|
[Theory]
|
|
[InlineData("")]
|
|
[InlineData(" ")]
|
|
[InlineData("avec espace")]
|
|
[InlineData("accentué")]
|
|
[InlineData("a/b")]
|
|
[InlineData("a@b")]
|
|
[InlineData("a;b")]
|
|
public void Username_Invalid(string username) =>
|
|
Assert.False(DiagnosticUserRules.IsValidUsername(username));
|
|
|
|
[Fact]
|
|
public void Username_TooLong_Rejected()
|
|
{
|
|
string tooLong = new string('a', DiagnosticUserRules.MaxUsernameLength + 1);
|
|
Assert.False(DiagnosticUserRules.IsValidUsername(tooLong));
|
|
Assert.True(DiagnosticUserRules.IsValidUsername(new string('a', DiagnosticUserRules.MaxUsernameLength)));
|
|
}
|
|
|
|
[Fact]
|
|
public void NormalizeUsername_Trims()
|
|
{
|
|
Assert.Equal("jean", DiagnosticUserRules.NormalizeUsername(" jean "));
|
|
Assert.Null(DiagnosticUserRules.NormalizeUsername(" "));
|
|
Assert.Null(DiagnosticUserRules.NormalizeUsername(null));
|
|
}
|
|
|
|
// -------------------------------------------------- password ----
|
|
[Fact]
|
|
public void Password_Minimum12()
|
|
{
|
|
Assert.True(DiagnosticUserRules.IsValidPassword("123456789012"));
|
|
Assert.True(DiagnosticUserRules.IsValidPassword("abcdefghijkl"));
|
|
Assert.False(DiagnosticUserRules.IsValidPassword("12345678901")); // 11
|
|
Assert.False(DiagnosticUserRules.IsValidPassword(""));
|
|
Assert.False(DiagnosticUserRules.IsValidPassword(null));
|
|
}
|
|
|
|
// -------------------------------------------------- role ----
|
|
[Fact]
|
|
public void Role_OnlySupportOrAdmin()
|
|
{
|
|
Assert.True(DiagnosticUserRules.IsValidRole("Support"));
|
|
Assert.True(DiagnosticUserRules.IsValidRole("Admin"));
|
|
Assert.True(DiagnosticUserRules.IsValidRole("admin"));
|
|
Assert.False(DiagnosticUserRules.IsValidRole("Owner"));
|
|
Assert.False(DiagnosticUserRules.IsValidRole(""));
|
|
Assert.False(DiagnosticUserRules.IsValidRole(null));
|
|
}
|
|
|
|
// -------------------------------------------------- guard : dernier Admin ----
|
|
[Fact]
|
|
public void Guard_Disable_LastActiveAdmin_Refused()
|
|
{
|
|
bool ok = DiagnosticUserGuard.CanDisable("admin1", "admin2", targetIsActiveAdmin: true, activeAdminCount: 1, out string? error);
|
|
Assert.False(ok);
|
|
Assert.Equal(DiagnosticUserGuard.LastAdminMessage, error);
|
|
}
|
|
|
|
[Fact]
|
|
public void Guard_Disable_NonLastAdmin_Allowed()
|
|
{
|
|
bool ok = DiagnosticUserGuard.CanDisable("admin1", "admin2", targetIsActiveAdmin: true, activeAdminCount: 2, out string? error);
|
|
Assert.True(ok);
|
|
Assert.Null(error);
|
|
}
|
|
|
|
[Fact]
|
|
public void Guard_Disable_SupportUser_Allowed()
|
|
{
|
|
bool ok = DiagnosticUserGuard.CanDisable("admin1", "support1", targetIsActiveAdmin: false, activeAdminCount: 1, out string? error);
|
|
Assert.True(ok);
|
|
Assert.Null(error);
|
|
}
|
|
|
|
// -------------------------------------------------- guard : auto-désactivation ----
|
|
[Fact]
|
|
public void Guard_Disable_Self_Refused()
|
|
{
|
|
bool ok = DiagnosticUserGuard.CanDisable("admin1", "admin1", targetIsActiveAdmin: true, activeAdminCount: 2, out string? error);
|
|
Assert.False(ok);
|
|
Assert.Equal(DiagnosticUserGuard.SelfDisableMessage, error);
|
|
}
|
|
|
|
// -------------------------------------------------- guard : auto-rétrogradation ----
|
|
[Fact]
|
|
public void Guard_Demote_LastActiveAdmin_Refused()
|
|
{
|
|
bool ok = DiagnosticUserGuard.CanDemoteFromAdmin("admin1", "admin2", activeAdminCount: 1, out string? error);
|
|
Assert.False(ok);
|
|
Assert.Equal(DiagnosticUserGuard.LastAdminMessage, error);
|
|
}
|
|
|
|
[Fact]
|
|
public void Guard_Demote_Self_Refused()
|
|
{
|
|
bool ok = DiagnosticUserGuard.CanDemoteFromAdmin("admin1", "admin1", activeAdminCount: 2, out string? error);
|
|
Assert.False(ok);
|
|
Assert.Equal(DiagnosticUserGuard.SelfDemoteMessage, error);
|
|
}
|
|
|
|
[Fact]
|
|
public void Guard_Demote_NonLastAdmin_Allowed()
|
|
{
|
|
bool ok = DiagnosticUserGuard.CanDemoteFromAdmin("admin1", "admin2", activeAdminCount: 2, out string? error);
|
|
Assert.True(ok);
|
|
Assert.Null(error);
|
|
}
|
|
|
|
// -------------------------------------------------- hash factice ----
|
|
[Fact]
|
|
public void DummyHash_ValidFormatAndDoesNotMatchArbitraryPassword()
|
|
{
|
|
Assert.False(DiagnosticPasswordHasher.Verify("un-mot-de-passe-arbitraire", DiagnosticPasswordHasher.DummyHash));
|
|
// Format valide : 3 parties, itérations positives (compatible Verify).
|
|
string[] parts = DiagnosticPasswordHasher.DummyHash.Split('.');
|
|
Assert.Equal(3, parts.Length);
|
|
Assert.True(int.TryParse(parts[0], out int iterations) && iterations > 0);
|
|
}
|
|
}
|