Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
5abe9c3
Scaffolding for new User system
Weffuls Sep 16, 2026
5259007
Change JsonRequestHandler's CreateResponse to be async
Weffuls Sep 20, 2026
12b13a9
Add login and access token distributor
Weffuls Sep 21, 2026
753f26f
Fix GUID methods.
Weffuls Sep 21, 2026
4797542
edit TryCreateUser() to output Task<User?>
Weffuls Sep 21, 2026
558c6ac
Add token limit tests.
Weffuls Sep 21, 2026
be0615d
Add User removal
Weffuls Sep 21, 2026
55ecf96
Add UserReferenceTests
Weffuls Sep 21, 2026
77e69d8
remove random unused import???
Weffuls Sep 21, 2026
66badd1
remove GetUser in IUserIndexable
Weffuls Sep 21, 2026
1f686c0
Add IUserIndexable to GameServer and GameState
Weffuls Sep 21, 2026
a3068a9
read Authorization header on request
Weffuls Sep 21, 2026
7543308
Add "auth/who-am-i" endpoint.
Weffuls Sep 21, 2026
191b375
Add api/users/get-info endpoint
Weffuls Sep 22, 2026
3074954
Add User saving and loading.
Weffuls Sep 22, 2026
972ee79
Fix written file not being truncated.
Weffuls Sep 22, 2026
85a6329
Add UserConverterTests and return User in LoadAndAddUserJson
Weffuls Sep 22, 2026
df103c8
Add UserRole and UserPermission with tests
Weffuls Sep 26, 2026
5ee04eb
Disable default launch settings file
Weffuls Sep 26, 2026
83d896a
add "default" role creation method
Weffuls Sep 26, 2026
111e396
Trim test RoundTripWithSpecifiedPermissionKeepsValue()
Weffuls Sep 26, 2026
cf37d01
Add throw for trying to attach user while already attached
Weffuls Sep 28, 2026
ff4053f
Add UserRoleManager (no saving yet)
Weffuls Sep 28, 2026
4083fdd
Make Users.RoleManager accessable in GameState.Roles
Weffuls Sep 28, 2026
c1ede69
Add Role saving
Weffuls Oct 2, 2026
686b7c6
fix confusing exceptions in User
Weffuls Oct 2, 2026
7af959c
Add regions for functions in User
Weffuls Oct 2, 2026
7737451
Add RoleReference and Tests
Weffuls Oct 4, 2026
4772999
add role adding in User and tests
Weffuls Oct 5, 2026
0629f47
Add test for changing user names.
Weffuls Oct 5, 2026
90388ba
remove check for null non-nullable Manager
Weffuls Oct 5, 2026
ad67cd2
Split RevokeAccessToken into an internal and public function
Weffuls Oct 6, 2026
ddce3bb
Document everything in Server.Users
Weffuls Oct 6, 2026
4667d87
Check if token needs refresh before doing it
Weffuls Oct 6, 2026
5afdd30
Extract creation of UserInfoResponse into function
Weffuls Oct 6, 2026
d3bff4b
Add IRoleIndexable to GameServer and GameState
Weffuls Oct 6, 2026
a9c7a0f
Split UserTests between UserManagerTests
Weffuls Oct 7, 2026
e7b30c3
Add Admin users and Tests
Weffuls Oct 7, 2026
7570b09
Add default admin user. (For when files loaded with no users)
Weffuls Oct 7, 2026
f25ae0f
Create directories before writing files.
Weffuls Oct 7, 2026
ce22554
Add endpoint to setting user names.
Weffuls Oct 7, 2026
d8c9a0f
Allow SetPassword(string?) to take null.
Weffuls Oct 8, 2026
82f0fef
Add endpoints for changing password & handle.
Weffuls Oct 8, 2026
e700a88
Add endpoint to create users.
Weffuls Oct 8, 2026
2e354ff
Add endpoint to list users.
Weffuls Oct 8, 2026
f331b3f
Add endpoints to get/list roles
Weffuls Oct 8, 2026
e6d7f10
Add endpoint to create a role.
Weffuls Oct 9, 2026
93e49cc
Add IUserHierarchyComparable
Weffuls Oct 9, 2026
87580b0
Block lower users from editing higher users' info.
Weffuls Oct 9, 2026
fe42a2e
Add set role name endpoint
Weffuls Oct 9, 2026
71f0dba
Fix embarrassing loading issues
Weffuls Oct 10, 2026
aa162f6
Change direction of Hierarchy comparison
Weffuls Oct 10, 2026
8b775a8
Change typo of 'user' to 'role.'
Weffuls Oct 10, 2026
aa3ffe4
Add endpoint to set role permissions.
Weffuls Oct 10, 2026
e061b4d
Add endpoint to list all user permissions
Weffuls Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions PMDDesktop.Server.Users.Tests/PMDDesktop.Server.Users.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../PMDDesktop.Server.Users/PMDDesktop.Server.Users.csproj" />
<ProjectReference Include="../PMDDesktop/PMDDesktop.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

</Project>
51 changes: 51 additions & 0 deletions PMDDesktop.Server.Users.Tests/Roles/RoleReferenceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using PMDDesktop.Server.Users.Roles;
using System.Text.Json;

namespace PMDDesktop.Server.Users.Tests.Roles;

public class RoleReferenceTests
{

[Fact]
public async Task CanGetReference()
{

UserManager manager = new();
UserRoleManager roleManager = manager.RoleManager;
UserRole? role = await roleManager.TryCreateRole();
Assert.NotNull(role);

RoleReference reference = new(role);

Assert.True(reference.TryGetRole(manager, out UserRole? referRole));

Assert.Equal(role, referRole);

}

[Fact]
public async Task SerializationIsSimple()
{

UserManager manager = new();
UserRoleManager roleManager = manager.RoleManager;
UserRole? role = await roleManager.TryCreateRole();
Assert.NotNull(role);

RoleReference preReference = new(role);

JsonElement json = JsonSerializer.SerializeToElement(preReference, AppInfo.JSON_OPTIONS);

Assert.Equal(JsonValueKind.String, json.ValueKind);

RoleReference? postReference = JsonSerializer.Deserialize<RoleReference>(json);

Assert.NotNull(postReference);

Assert.True(postReference.TryGetRole(manager, out UserRole? referRole));

Assert.Equal(role, referRole);

}

}
18 changes: 18 additions & 0 deletions PMDDesktop.Server.Users.Tests/Roles/UserPermissionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using PMDDesktop.Server.Users.Roles;

namespace PMDDesktop.Server.Users.Tests.Roles;

public class UserPermissionTests
{

[Theory]
[InlineData("manage-users")]
[InlineData("manage-roles")]
public void UserPermissionAllIncludesPermissions(string dataName)
{

Assert.Contains(UserPermission.ALL, permission => permission.DataName == dataName);

}

}
94 changes: 94 additions & 0 deletions PMDDesktop.Server.Users.Tests/Roles/UserRoleConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using PMDDesktop.Server.Users.Roles;
using System.Text.Json;

namespace PMDDesktop.Server.Users.Tests.Roles;

public class UserRoleConverterTests
{

[Fact]
public async Task RoleJsonContainsNullsForUnspecified()
{

UserRole role = new();

await role.SetPermission(UserPermission.MANAGE_USERS, true);

JsonDocument document = JsonSerializer.SerializeToDocument(role);

JsonElement manageRolesElement = document.RootElement.GetProperty(UserRoleConverter.PERMISSIONS_PROPERTY).GetProperty(UserPermission.MANAGE_ROLES.DataName);

Assert.Equal(JsonValueKind.Null, manageRolesElement.ValueKind);

}

[Fact]
public async Task RoleJsonContainsTrueWhenSpecified()
{

UserRole role = new();

await role.SetPermission(UserPermission.MANAGE_USERS, true);

JsonDocument document = JsonSerializer.SerializeToDocument(role);

JsonElement manageRolesElement = document.RootElement.GetProperty(UserRoleConverter.PERMISSIONS_PROPERTY).GetProperty(UserPermission.MANAGE_USERS.DataName);

Assert.Equal(JsonValueKind.True, manageRolesElement.ValueKind);

}

[Fact]
public async Task RoleJsonContainsFalseWhenSpecified()
{

UserRole role = new();

await role.SetPermission(UserPermission.MANAGE_USERS, false);

JsonDocument document = JsonSerializer.SerializeToDocument(role);

JsonElement manageRolesElement = document.RootElement.GetProperty(UserRoleConverter.PERMISSIONS_PROPERTY).GetProperty(UserPermission.MANAGE_USERS.DataName);

Assert.Equal(JsonValueKind.False, manageRolesElement.ValueKind);

}

[Fact]
public async Task RoleJsonWithSpecifiedPermissionThenUnspecifiedContainsNull()
{

UserRole role = new();

await role.SetPermission(UserPermission.MANAGE_USERS, true);
await role.SetPermission(UserPermission.MANAGE_USERS, null);

JsonDocument document = JsonSerializer.SerializeToDocument(role);

JsonElement manageRolesElement = document.RootElement.GetProperty(UserRoleConverter.PERMISSIONS_PROPERTY).GetProperty(UserPermission.MANAGE_USERS.DataName);

Assert.Equal(JsonValueKind.Null, manageRolesElement.ValueKind);

}

[Theory]
[InlineData(true)]
[InlineData(false)]
[InlineData(null)]
public async Task RoundTripRoleWithSpecifiedPermissionKeepsValue(bool? value)
{

UserRole role = new();

await role.SetPermission(UserPermission.MANAGE_USERS, value);

JsonDocument document = JsonSerializer.SerializeToDocument(role);

UserRole? newRole = JsonSerializer.Deserialize<UserRole>(document);
Assert.NotNull(newRole);

Assert.Equal(value, newRole.GetPermission(UserPermission.MANAGE_USERS));

}

}
194 changes: 194 additions & 0 deletions PMDDesktop.Server.Users.Tests/Roles/UserRoleManagerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
using PMDDesktop.Server.Users.Roles;

namespace PMDDesktop.Server.Users.Tests.Roles;

public class UserRoleManagerTests
{

[Fact]
public void UserRoleManagerPointsBackAtUserManager()
{

UserManager manager = new();
UserRoleManager roleManager = manager.RoleManager;

Assert.NotNull(roleManager);

Assert.Equal(manager, roleManager.Manager);

Assert.Equal(roleManager, roleManager.Manager.RoleManager);

}

[Fact]
public void UserRoleManagerHasDefaultRole()
{

UserManager manager = new();
UserRoleManager roleManager = manager.RoleManager;

Assert.NotNull(roleManager.DefaultRole);

Assert.True(roleManager.DefaultRole.IsDefaultRole);

Assert.Equal(Guid.Empty, roleManager.DefaultRole.GUID);

// Seeing if that's what we get for Guid.Empty

Assert.True(roleManager.TryGetRole(Guid.Empty, out UserRole? tryEmptyRole));
Assert.NotNull(tryEmptyRole);
Assert.Equal(roleManager.DefaultRole, tryEmptyRole);

// Test comparing to mock default role.

UserRole exampleDefault = UserRole.CreateDefaultRole();
UserRole managerDefault = roleManager.DefaultRole;

Assert.All(UserPermission.ALL, perm => Assert.Equal(exampleDefault.GetPermission(perm), managerDefault.GetPermission(perm)));

}

[Fact]
public async Task NewRolesAreOrderedLastBeforeDefault()
{

UserManager manager = new();
UserRoleManager roleManager = manager.RoleManager;

// Role 0
UserRole role0 = roleManager.DefaultRole;
Assert.Equal(role0, roleManager.Skip(0).First());
Assert.Single(roleManager);
Assert.Equal(role0, roleManager.SkipLast(0).Last());

// Role 1

UserRole? role1 = await roleManager.TryCreateRole();
Assert.Equal(role1, roleManager.Skip(0).First());
Assert.Equal(role0, roleManager.Skip(1).First());
Assert.Equal(2, roleManager.Count());
Assert.Equal(role1, roleManager.SkipLast(1).Last());
Assert.Equal(role0, roleManager.SkipLast(0).Last());

// Role 2

UserRole? role2 = await roleManager.TryCreateRole();
Assert.Equal(role1, roleManager.Skip(0).First());
Assert.Equal(role2, roleManager.Skip(1).First());
Assert.Equal(role0, roleManager.Skip(2).First());
Assert.Equal(3, roleManager.Count());
Assert.Equal(role1, roleManager.SkipLast(2).Last());
Assert.Equal(role2, roleManager.SkipLast(1).Last());
Assert.Equal(role0, roleManager.SkipLast(0).Last());

// Role 3

UserRole? role3 = await roleManager.TryCreateRole();
Assert.Equal(role1, roleManager.Skip(0).First());
Assert.Equal(role2, roleManager.Skip(1).First());
Assert.Equal(role3, roleManager.Skip(2).First());
Assert.Equal(role0, roleManager.Skip(3).First());
Assert.Equal(4, roleManager.Count());
Assert.Equal(role1, roleManager.SkipLast(3).Last());
Assert.Equal(role2, roleManager.SkipLast(2).Last());
Assert.Equal(role3, roleManager.SkipLast(1).Last());
Assert.Equal(role0, roleManager.SkipLast(0).Last());

// Role 4

UserRole? role4 = await roleManager.TryCreateRole();
Assert.Equal(role1, roleManager.Skip(0).First());
Assert.Equal(role2, roleManager.Skip(1).First());
Assert.Equal(role3, roleManager.Skip(2).First());
Assert.Equal(role4, roleManager.Skip(3).First());
Assert.Equal(role0, roleManager.Skip(4).First());
Assert.Equal(5, roleManager.Count());
Assert.Equal(role1, roleManager.SkipLast(4).Last());
Assert.Equal(role2, roleManager.SkipLast(3).Last());
Assert.Equal(role3, roleManager.SkipLast(2).Last());
Assert.Equal(role4, roleManager.SkipLast(1).Last());
Assert.Equal(role0, roleManager.SkipLast(0).Last());

}

[Fact]
public async Task SortingAffectsEnumeration()
{

UserManager manager = new();
UserRoleManager roleManager = manager.RoleManager;

UserRole defaultRole = roleManager.DefaultRole;
UserRole? role1 = await roleManager.TryCreateRole();
UserRole? role2 = await roleManager.TryCreateRole();
UserRole? role3 = await roleManager.TryCreateRole();
UserRole? role4 = await roleManager.TryCreateRole();

Assert.NotNull(role1);
Assert.NotNull(role2);
Assert.NotNull(role3);
Assert.NotNull(role4);

UserRole[] array1 = [.. roleManager];

Assert.Equal(role1, array1[0]);
Assert.Equal(role2, array1[1]);
Assert.Equal(role3, array1[2]);
Assert.Equal(role4, array1[3]);
Assert.Equal(defaultRole, array1[4]);

UserRole[] newSort2 = [role3, role2, role1, role4];

await roleManager.SetOrder(newSort2.Select(role => role.GUID));

UserRole[] array2 = [.. roleManager];

Assert.Equal(newSort2[0], array2[0]);
Assert.Equal(newSort2[1], array2[1]);
Assert.Equal(newSort2[2], array2[2]);
Assert.Equal(newSort2[3], array2[3]);
Assert.Equal(defaultRole, array2[4]);

}

[Fact]
public async Task SortingAffectsEnumerationWithDefaultSpecified()
{

UserManager manager = new();
UserRoleManager roleManager = manager.RoleManager;

UserRole defaultRole = roleManager.DefaultRole;
UserRole? role1 = await roleManager.TryCreateRole();
UserRole? role2 = await roleManager.TryCreateRole();
UserRole? role3 = await roleManager.TryCreateRole();
UserRole? role4 = await roleManager.TryCreateRole();

Assert.NotNull(role1);
Assert.NotNull(role2);
Assert.NotNull(role3);
Assert.NotNull(role4);

UserRole[] array1 = [.. roleManager];

Assert.Equal(role1, array1[0]);
Assert.Equal(role2, array1[1]);
Assert.Equal(role3, array1[2]);
Assert.Equal(role4, array1[3]);
Assert.Equal(defaultRole, array1[4]);

UserRole[] newSort2 = [role3, role2, role1, role4, defaultRole];

await roleManager.SetOrder(newSort2.Select(role => role.GUID));

UserRole[] array2 = [.. roleManager];

Assert.Equal(newSort2[0], array2[0]);
Assert.Equal(newSort2[1], array2[1]);
Assert.Equal(newSort2[2], array2[2]);
Assert.Equal(newSort2[3], array2[3]);
Assert.Equal(newSort2[4], array2[4]);

}

}
Loading
Loading