Loading users to Fluxor state now with Redis caching.

This commit is contained in:
Rhywden
2026-08-21 17:03:29 +02:00
parent b1a62e83f5
commit 75145ad284
5 changed files with 77 additions and 20 deletions
+15 -13
View File
@@ -1,17 +1,23 @@
@page "/"
@inject Wollmilchsau.Services.Ldap.ILdapService LdapService
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@inject Fluxor.IDispatcher Dispatcher
@inject Fluxor.IState<Wollmilchsau.Store.AdminStore.AdminState> AdminState
@inject IJSRuntime JsRuntime
<PageTitle>LDAP Users</PageTitle>
<button class="btn btn-primary" @onclick="DownloadCsvAsync" disabled="@(users is null)">Export CSV</button>
<button class="btn btn-primary" @onclick="DownloadCsvAsync" disabled="@(!Users.Any())">Export CSV</button>
<h1>LDAP Users</h1>
@if (users is null)
@if (!AdminState.Value.LdapUsersLoaded)
{
<p><em>Loading users...</em></p>
}
else if (!Users.Any())
{
<p>No LDAP users found.</p>
}
else
{
<table class="table">
@@ -25,7 +31,7 @@ else
</tr>
</thead>
<tbody>
@foreach (var user in users)
@foreach (var user in Users)
{
<tr>
<td>@user.Username</td>
@@ -40,21 +46,17 @@ else
}
@code {
private List<Wollmilchsau.Models.LdapUser>? users;
private IEnumerable<Wollmilchsau.Models.LdapUser> Users => AdminState.Value.LdapUsers.Values;
protected override async Task OnInitializedAsync()
protected override void OnInitialized()
{
users = [];
await foreach (var user in LdapService.GetAllUsers())
{
users.Add(user);
}
base.OnInitialized();
Dispatcher.Dispatch(new Wollmilchsau.Store.AdminStore.GetAllLdapUsers());
}
private Task DownloadCsvAsync()
{
var csv = string.Join("\r\n", users!.Select(user => string.Join(';',
var csv = string.Join("\r\n", Users.Select(user => string.Join(';',
user.GivenName ?? string.Empty,
user.Surname ?? string.Empty,
user.Classroom ?? string.Empty,
@@ -1,6 +1,9 @@
namespace Wollmilchsau.Store.AdminStore;
using Wollmilchsau.Models;
namespace Wollmilchsau.Store.AdminStore;
public sealed record GetAllMoodleUsers();
public sealed record GetAllElementUsers();
public sealed record GetAllLdapUsers();
public sealed record SetLdapUsers(IReadOnlyCollection<LdapUser> Users);
public sealed record GetAllMsolUsers();
+41 -2
View File
@@ -1,5 +1,44 @@
namespace Wollmilchsau.Store.AdminStore;
using System.Text.Json;
using Fluxor;
using Microsoft.Extensions.Caching.Distributed;
using Wollmilchsau.Models;
using Wollmilchsau.Services.Ldap;
public class AdminEffects
namespace Wollmilchsau.Store.AdminStore;
public sealed class AdminEffects(ILdapService ldapService, IDistributedCache cache)
{
private const string LdapUsersCacheKey = "admin:ldap-users";
[EffectMethod]
public async Task HandleGetAllLdapUsers(GetAllLdapUsers action, IDispatcher dispatcher)
{
var cachedUsers = await cache.GetStringAsync(LdapUsersCacheKey);
IReadOnlyCollection<LdapUser> users;
if (cachedUsers is not null)
{
users = JsonSerializer.Deserialize<LdapUser[]>(cachedUsers)
?? throw new InvalidOperationException("The cached LDAP users could not be deserialized.");
}
else
{
var loadedUsers = new List<LdapUser>();
await foreach (var user in ldapService.GetAllUsers())
{
loadedUsers.Add(user);
}
users = loadedUsers;
await cache.SetStringAsync(
LdapUsersCacheKey,
JsonSerializer.Serialize(users),
new DistributedCacheEntryOptions
{
SlidingExpiration = TimeSpan.FromMinutes(10)
});
}
dispatcher.Dispatch(new SetLdapUsers(users));
}
}
+14 -2
View File
@@ -1,5 +1,17 @@
namespace Wollmilchsau.Store.AdminStore;
using System.Collections.Immutable;
using Fluxor;
public class AdminReducers
namespace Wollmilchsau.Store.AdminStore;
public static class AdminReducers
{
[ReducerMethod]
public static AdminState ReduceSetLdapUsers(AdminState state, SetLdapUsers action)
{
return state with
{
LdapUsers = action.Users.ToImmutableDictionary(user => user.Username, StringComparer.OrdinalIgnoreCase),
LdapUsersLoaded = true
};
}
}
+2 -1
View File
@@ -10,6 +10,7 @@ public sealed record AdminState
public AdminState() { }
public ImmutableDictionary<Guid, ElementUser> ElementUsers { get; init; } = [];
public ImmutableDictionary<Guid, MoodleUser> MoodleUsers { get; init; } = [];
public ImmutableDictionary<Guid, LdapUser> LdapUsers { get; init; } = [];
public ImmutableDictionary<string, LdapUser> LdapUsers { get; init; } = [];
public bool LdapUsersLoaded { get; init; }
public ImmutableDictionary<Guid, MsolUser> MsolUsers { get; init; } = [];
}