mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 03:43:11 +00:00
248 lines
8.5 KiB
C#
248 lines
8.5 KiB
C#
using Data.SeaHavenIndustries.Enums;
|
|
using FluentAssertions;
|
|
using SeaHaven.Services.Constants;
|
|
using SeaHaven.Services.Implementation;
|
|
using Xunit;
|
|
|
|
namespace SeaHaven.Services.Tests;
|
|
|
|
public class TeamPermissionPolicyTests
|
|
{
|
|
private static readonly string[] DispatcherKeys =
|
|
{
|
|
TeamPermissionKeys.CreateVendors,
|
|
TeamPermissionKeys.EditVendors,
|
|
TeamPermissionKeys.DeactivateVendors,
|
|
TeamPermissionKeys.CreateSites,
|
|
TeamPermissionKeys.EditSites,
|
|
TeamPermissionKeys.CreateWorkOrders,
|
|
TeamPermissionKeys.EditOthersWorkOrders,
|
|
TeamPermissionKeys.CancelWorkOrders,
|
|
TeamPermissionKeys.RequestUplifts,
|
|
TeamPermissionKeys.AutoApproveUplifts
|
|
};
|
|
|
|
private static readonly string[] SchedulerOnlyKeys =
|
|
{
|
|
TeamPermissionKeys.DeleteSites,
|
|
TeamPermissionKeys.CreateServices,
|
|
TeamPermissionKeys.EditServices,
|
|
TeamPermissionKeys.CreateCompletionDocTemplates,
|
|
TeamPermissionKeys.EditCompletionDocTemplates,
|
|
TeamPermissionKeys.ViewAllDispatchersOnDashboard
|
|
};
|
|
|
|
private static readonly string[] AdminOnlyKeys =
|
|
{
|
|
TeamPermissionKeys.ManageTeamMembers,
|
|
TeamPermissionKeys.ChangeTeamMemberRole,
|
|
TeamPermissionKeys.DeactivateServices,
|
|
TeamPermissionKeys.DeleteCompletionDocTemplates,
|
|
TeamPermissionKeys.DeleteWorkOrders,
|
|
TeamPermissionKeys.ReviewUplifts
|
|
};
|
|
|
|
private static IReadOnlyDictionary<string, UserPermissionState> Overrides(
|
|
string key, UserPermissionState state) =>
|
|
new Dictionary<string, UserPermissionState>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
[key] = state
|
|
};
|
|
|
|
[Fact]
|
|
public void Registry_Exposes_Exactly_The_22_Prototype_Keys()
|
|
{
|
|
TeamPermissionKeys.All.Should().HaveCount(22);
|
|
TeamPermissionKeys.KnownKeys.Should().HaveCount(22);
|
|
TeamPermissionKeys.All.Should().OnlyHaveUniqueItems();
|
|
TeamPermissionKeys.All.Should().OnlyContain(key => !string.IsNullOrWhiteSpace(key));
|
|
TeamPermissionKeys.All.Should().BeEquivalentTo(new[]
|
|
{
|
|
"manageTeamMembers",
|
|
"changeTeamMemberRole",
|
|
"createVendors",
|
|
"editVendors",
|
|
"deactivateVendors",
|
|
"createSites",
|
|
"editSites",
|
|
"deleteSites",
|
|
"createServices",
|
|
"editServices",
|
|
"deactivateServices",
|
|
"createCompletionDocTemplates",
|
|
"editCompletionDocTemplates",
|
|
"deleteCompletionDocTemplates",
|
|
"createWorkOrders",
|
|
"editOthersWorkOrders",
|
|
"cancelWorkOrders",
|
|
"deleteWorkOrders",
|
|
"requestUplifts",
|
|
"autoApproveUplifts",
|
|
"reviewUplifts",
|
|
"viewAllDispatchersOnDashboard"
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void Registry_IsKnown_Is_Case_Insensitive_And_Rejects_Unknown_Keys()
|
|
{
|
|
TeamPermissionKeys.IsKnown("CREATEVENDORS").Should().BeTrue();
|
|
TeamPermissionKeys.IsKnown("autoApproveUplifts").Should().BeTrue();
|
|
TeamPermissionKeys.IsKnown("nope.unknown").Should().BeFalse();
|
|
TeamPermissionKeys.IsKnown("").Should().BeFalse();
|
|
TeamPermissionKeys.IsKnown(null).Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void Dispatcher_Gets_Exactly_Prototype_Defaults()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
foreach (var key in TeamPermissionKeys.All)
|
|
{
|
|
var expected = DispatcherKeys.Contains(key, StringComparer.Ordinal);
|
|
policy.IsAllowed("Dispatcher", key).Should().Be(expected,
|
|
$"Dispatcher default for '{key}' should be {expected}");
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Scheduler_Gets_Exactly_Prototype_Defaults()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
foreach (var key in TeamPermissionKeys.All)
|
|
{
|
|
var expected = SchedulerOnlyKeys.Contains(key, StringComparer.Ordinal)
|
|
|| DispatcherKeys.Contains(key, StringComparer.Ordinal)
|
|
&& key is not TeamPermissionKeys.RequestUplifts
|
|
&& key is not TeamPermissionKeys.AutoApproveUplifts;
|
|
|
|
policy.IsAllowed("Scheduler", key).Should().Be(expected,
|
|
$"Scheduler default for '{key}' should be {expected}");
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Admin_Has_Effective_Access_To_Every_Key()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
foreach (var key in TeamPermissionKeys.All)
|
|
policy.IsAllowed("Admin", key).Should().BeTrue($"Admin should hold '{key}'");
|
|
}
|
|
|
|
[Fact]
|
|
public void Role_Recognition_Is_Case_Insensitive()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
policy.IsAllowed("dIsPaTcHeR", TeamPermissionKeys.CreateVendors).Should().BeTrue();
|
|
policy.IsAllowed("SCHEDULER", TeamPermissionKeys.DeleteSites).Should().BeTrue();
|
|
policy.IsAllowed("admin", TeamPermissionKeys.ReviewUplifts).Should().BeTrue();
|
|
|
|
policy.IsAllowed("dIsPaTcHeR", TeamPermissionKeys.DeleteSites).Should().BeFalse();
|
|
policy.IsAllowed("SCHEDULER", TeamPermissionKeys.AutoApproveUplifts).Should().BeFalse();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("Manager")]
|
|
[InlineData("OfficeAdmin")]
|
|
[InlineData("")]
|
|
[InlineData(null)]
|
|
public void Unknown_And_Legacy_Roles_Receive_No_Permissions(string? role)
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
foreach (var key in TeamPermissionKeys.All)
|
|
policy.IsAllowed(role, key).Should().BeFalse(
|
|
$"unknown/legacy role '{role}' must not hold '{key}'");
|
|
}
|
|
|
|
[Fact]
|
|
public void Unknown_Role_Gains_Nothing_Even_With_Allow_Overrides()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
foreach (var key in TeamPermissionKeys.All)
|
|
policy.IsAllowed("Manager", key, Overrides(key, UserPermissionState.Allow))
|
|
.Should().BeFalse($"an unknown role must not be elevated via '{key}'");
|
|
}
|
|
|
|
[Fact]
|
|
public void Allow_Override_Grants_Key_Outside_Role_Default()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
policy.IsAllowed("Scheduler", TeamPermissionKeys.RequestUplifts)
|
|
.Should().BeFalse();
|
|
policy.IsAllowed(
|
|
"Scheduler",
|
|
TeamPermissionKeys.RequestUplifts,
|
|
Overrides(TeamPermissionKeys.RequestUplifts, UserPermissionState.Allow))
|
|
.Should().BeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void Deny_Override_Removes_Key_Inside_Role_Default()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
policy.IsAllowed("Dispatcher", TeamPermissionKeys.CreateVendors)
|
|
.Should().BeTrue();
|
|
policy.IsAllowed(
|
|
"Dispatcher",
|
|
TeamPermissionKeys.CreateVendors,
|
|
Overrides(TeamPermissionKeys.CreateVendors, UserPermissionState.Deny))
|
|
.Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void Unset_Override_And_Missing_Row_Fall_Back_To_Role_Default()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
policy.IsAllowed(
|
|
"Dispatcher",
|
|
TeamPermissionKeys.CreateWorkOrders,
|
|
Overrides(TeamPermissionKeys.CreateWorkOrders, UserPermissionState.Unset))
|
|
.Should().BeTrue();
|
|
|
|
policy.IsAllowed(
|
|
"Scheduler",
|
|
TeamPermissionKeys.RequestUplifts,
|
|
Overrides(TeamPermissionKeys.RequestUplifts, UserPermissionState.Unset))
|
|
.Should().BeFalse();
|
|
|
|
policy.IsAllowed(
|
|
"Scheduler",
|
|
TeamPermissionKeys.RequestUplifts,
|
|
new Dictionary<string, UserPermissionState>())
|
|
.Should().BeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void Admin_Is_Immune_To_Overrides()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
foreach (var key in TeamPermissionKeys.All)
|
|
{
|
|
policy.IsAllowed("Admin", key, Overrides(key, UserPermissionState.Deny))
|
|
.Should().BeTrue($"Admin must keep '{key}' despite a Deny override");
|
|
policy.IsAllowed("ADMIN", key, Overrides(key, UserPermissionState.Unset))
|
|
.Should().BeTrue();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Unknown_Permission_Key_Is_Denied_For_Every_Role()
|
|
{
|
|
var policy = new TeamPermissionPolicy();
|
|
|
|
policy.IsAllowed("Admin", "nope.unknown").Should().BeFalse();
|
|
policy.IsAllowed("Dispatcher", "nope.unknown").Should().BeFalse();
|
|
policy.IsAllowed("Admin", "nope.unknown", Overrides("nope.unknown", UserPermissionState.Allow))
|
|
.Should().BeFalse();
|
|
}
|
|
}
|