@page "/admin/users" @attribute [Microsoft.AspNetCore.Authorization.Authorize] @inject IUserService UserService @inject IUserContextAccessor UserContext @inject IAuditService Audit @inject NavigationManager Nav @inject TranslationSource T @rendermode InteractiveServer @using SharepointToolbox.Web.Core.Models @using SharepointToolbox.Web.Services.Audit @using SharepointToolbox.Web.Services.Auth @using SharepointToolbox.Web.Services.Session

@T["usermgmt.title"]

@T["usermgmt.subtitle"]

@if (!UserContext.IsAuthenticated || UserContext.Role != UserRole.Admin) {
@T["usermgmt.accessdenied"]
return; } @if (!string.IsNullOrEmpty(_message)) {
@_message
}

@T["usermgmt.create.title"]

@if (_users.Count == 0) {
@T["usermgmt.empty"]
} else {
@foreach (var user in _users) { }
@T["usermgmt.col.user"] @T["usermgmt.col.email"] @T["usermgmt.col.source"] @T["usermgmt.col.role"] @T["usermgmt.col.lastlogin"] @T["usermgmt.col.actions"]
@user.DisplayName @user.Email @(user.Provider == AuthProvider.Local ? T["usermgmt.source.local"] : T["usermgmt.source.entra"]) @(user.LastLogin?.ToString("yyyy-MM-dd HH:mm") ?? T["usermgmt.lastlogin.never"]) @if (user.Provider == AuthProvider.Local) { } @if (user.Email != UserContext.Email) { } else { @T["usermgmt.badge.you"] }
} @if (_resetUser is not null) {

@string.Format(T["usermgmt.reset.title"], _resetUser.DisplayName)

} @code { private List _users = new(); private string _message = string.Empty; private bool _isError; private string _newEmail = string.Empty; private string _newName = string.Empty; private UserRole _newRole = UserRole.TechN0; private string _newPassword = string.Empty; private AppUser? _resetUser; private string _resetPassword = string.Empty; protected override async Task OnInitializedAsync() { _users = (await UserService.GetAllAsync()).ToList(); } private async Task CreateLocalUserAsync() { try { var user = await UserService.CreateLocalUserAsync(_newEmail, _newName, _newRole, _newPassword); _users.Add(user); await Audit.LogAsync("UserCreated", "", Array.Empty(), $"Created local user {user.Email} ({user.DisplayName}) with role {user.Role}."); _message = string.Format(T["usermgmt.msg.created"], user.DisplayName); _isError = false; _newEmail = _newName = _newPassword = string.Empty; _newRole = UserRole.TechN0; } catch (Exception ex) { _message = string.Format(T["usermgmt.msg.error"], ex.Message); _isError = true; } } private void OpenReset(AppUser user) { _resetUser = user; _resetPassword = string.Empty; } private async Task ResetPasswordAsync() { if (_resetUser is null) return; try { await UserService.SetPasswordAsync(_resetUser.Id, _resetPassword); await Audit.LogAsync("PasswordReset", "", Array.Empty(), $"Reset password for local user {_resetUser.Email} ({_resetUser.DisplayName})."); _message = string.Format(T["usermgmt.msg.pwreset"], _resetUser.DisplayName); _isError = false; _resetUser = null; } catch (Exception ex) { _message = string.Format(T["usermgmt.msg.error"], ex.Message); _isError = true; } } // Bound via @bind:after, so user.Role already holds the newly-selected value when this runs. private async Task PersistRoleAsync(AppUser user) { try { 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 {user.Role}."); _message = string.Format(T["usermgmt.msg.roleupdated"], user.DisplayName); _isError = false; } catch (Exception ex) { _message = string.Format(T["usermgmt.msg.error"], ex.Message); _isError = true; } } private async Task DeleteUserAsync(AppUser user) { await UserService.DeleteAsync(user.Id); _users.Remove(user); await Audit.LogAsync("UserDeleted", "", Array.Empty(), $"Removed {user.Provider} user {user.Email} ({user.DisplayName}), role {user.Role}."); _message = string.Format(T["usermgmt.msg.removed"], user.DisplayName); _isError = false; } }