diff --git a/Components/Pages/Admin/UserManagement.razor b/Components/Pages/Admin/UserManagement.razor
index 6949a43..c95360e 100644
--- a/Components/Pages/Admin/UserManagement.razor
+++ b/Components/Pages/Admin/UserManagement.razor
@@ -86,12 +86,11 @@ else
|
@@ -193,16 +192,14 @@ else
}
}
- private async Task OnRoleChange(AppUser user, ChangeEventArgs e)
+ // Bound via @bind:after, so user.Role already holds the newly-selected value when this runs.
+ private async Task PersistRoleAsync(AppUser user)
{
- if (!Enum.TryParse(e.Value?.ToString(), out var newRole)) return;
try
{
- var oldRole = user.Role;
- await UserService.UpdateRoleAsync(user.Id, newRole);
- user.Role = newRole;
+ var oldRole = await UserService.UpdateRoleAsync(user.Id, user.Role);
await Audit.LogAsync("RoleChanged", "", Array.Empty(),
- $"Changed role for {user.Email} ({user.DisplayName}) from {oldRole} to {newRole}.");
+ $"Changed role for {user.Email} ({user.DisplayName}) from {oldRole} to {user.Role}.");
_message = string.Format(T["usermgmt.msg.roleupdated"], user.DisplayName);
_isError = false;
}
diff --git a/Services/Auth/IUserService.cs b/Services/Auth/IUserService.cs
index 1dbbb29..c6efc59 100644
--- a/Services/Auth/IUserService.cs
+++ b/Services/Auth/IUserService.cs
@@ -11,7 +11,9 @@ public interface IUserService
Task GetByEmailAsync(string email);
Task> GetAllAsync();
- Task UpdateRoleAsync(string userId, UserRole role);
+ /// Persist a new role for the user. Returns the previous role (read from the store).
+ /// No user matches .
+ Task UpdateRoleAsync(string userId, UserRole role);
Task DeleteAsync(string userId);
/// Create a local password-based account. First user ever becomes Admin.
diff --git a/Services/Auth/UserService.cs b/Services/Auth/UserService.cs
index b289d2b..f5172a1 100644
--- a/Services/Auth/UserService.cs
+++ b/Services/Auth/UserService.cs
@@ -1,5 +1,6 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
+using Microsoft.Extensions.Logging;
using SharepointToolbox.Web.Core.Models;
using SharepointToolbox.Web.Infrastructure.Persistence;
@@ -9,11 +10,13 @@ public class UserService : IUserService
{
private readonly UserRepository _repo;
private readonly IPasswordHasher _hasher;
+ private readonly ILogger _logger;
- public UserService(UserRepository repo, IPasswordHasher hasher)
+ public UserService(UserRepository repo, IPasswordHasher hasher, ILogger logger)
{
_repo = repo;
_hasher = hasher;
+ _logger = logger;
}
public async Task ProvisionAsync(ClaimsPrincipal principal)
@@ -56,13 +59,23 @@ public class UserService : IUserService
public Task> GetAllAsync() => _repo.LoadAsync();
- public async Task UpdateRoleAsync(string userId, UserRole role)
+ public async Task UpdateRoleAsync(string userId, UserRole role)
{
var users = (await _repo.LoadAsync()).ToList();
var user = users.FirstOrDefault(u => u.Id == userId)
- ?? throw new KeyNotFoundException($"User {userId} not found.");
+ ?? throw new KeyNotFoundException($"User '{userId}' not found among {users.Count} stored users.");
+
+ var oldRole = user.Role;
user.Role = role;
await _repo.UpsertAsync(user);
+
+ // Verify the write landed by re-reading the row from disk.
+ var persisted = (await _repo.LoadAsync()).FirstOrDefault(u => u.Id == user.Id)?.Role;
+ _logger.LogInformation(
+ "UpdateRoleAsync: {Email} (id {Id}) {OldRole} → {NewRole}; persisted value now {Persisted}.",
+ user.Email, user.Id, oldRole, role, persisted);
+
+ return oldRole;
}
public Task DeleteAsync(string userId) => _repo.DeleteAsync(userId);