From 75145ad2841f76bb6edca161262724421fd52118 Mon Sep 17 00:00:00 2001 From: Rhywden Date: Fri, 21 Aug 2026 17:03:29 +0200 Subject: [PATCH] Loading users to Fluxor state now with Redis caching. --- Wollmilchsau/Components/Pages/Home.razor | 28 ++++++------ Wollmilchsau/Store/AdminStore/AdminActions.cs | 7 ++- Wollmilchsau/Store/AdminStore/AdminEffects.cs | 43 ++++++++++++++++++- .../Store/AdminStore/AdminReducers.cs | 16 ++++++- Wollmilchsau/Store/AdminStore/AdminState.cs | 3 +- 5 files changed, 77 insertions(+), 20 deletions(-) diff --git a/Wollmilchsau/Components/Pages/Home.razor b/Wollmilchsau/Components/Pages/Home.razor index 81b9641..ba55375 100644 --- a/Wollmilchsau/Components/Pages/Home.razor +++ b/Wollmilchsau/Components/Pages/Home.razor @@ -1,17 +1,23 @@ @page "/" -@inject Wollmilchsau.Services.Ldap.ILdapService LdapService +@inherits Fluxor.Blazor.Web.Components.FluxorComponent +@inject Fluxor.IDispatcher Dispatcher +@inject Fluxor.IState AdminState @inject IJSRuntime JsRuntime LDAP Users - +

LDAP Users

-@if (users is null) +@if (!AdminState.Value.LdapUsersLoaded) {

Loading users...

} +else if (!Users.Any()) +{ +

No LDAP users found.

+} else { @@ -25,7 +31,7 @@ else - @foreach (var user in users) + @foreach (var user in Users) { @@ -40,21 +46,17 @@ else } @code { - private List? users; + private IEnumerable 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, diff --git a/Wollmilchsau/Store/AdminStore/AdminActions.cs b/Wollmilchsau/Store/AdminStore/AdminActions.cs index b74f90e..c7629b7 100644 --- a/Wollmilchsau/Store/AdminStore/AdminActions.cs +++ b/Wollmilchsau/Store/AdminStore/AdminActions.cs @@ -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 GetAllMsolUsers(); \ No newline at end of file +public sealed record SetLdapUsers(IReadOnlyCollection Users); +public sealed record GetAllMsolUsers(); diff --git a/Wollmilchsau/Store/AdminStore/AdminEffects.cs b/Wollmilchsau/Store/AdminStore/AdminEffects.cs index 7892e70..de96fcd 100644 --- a/Wollmilchsau/Store/AdminStore/AdminEffects.cs +++ b/Wollmilchsau/Store/AdminStore/AdminEffects.cs @@ -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 users; + + if (cachedUsers is not null) + { + users = JsonSerializer.Deserialize(cachedUsers) + ?? throw new InvalidOperationException("The cached LDAP users could not be deserialized."); + } + else + { + var loadedUsers = new List(); + 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)); + } } diff --git a/Wollmilchsau/Store/AdminStore/AdminReducers.cs b/Wollmilchsau/Store/AdminStore/AdminReducers.cs index e8bbd29..ea4641c 100644 --- a/Wollmilchsau/Store/AdminStore/AdminReducers.cs +++ b/Wollmilchsau/Store/AdminStore/AdminReducers.cs @@ -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 + }; + } } diff --git a/Wollmilchsau/Store/AdminStore/AdminState.cs b/Wollmilchsau/Store/AdminStore/AdminState.cs index 90a73d4..f34a6b3 100644 --- a/Wollmilchsau/Store/AdminStore/AdminState.cs +++ b/Wollmilchsau/Store/AdminStore/AdminState.cs @@ -10,6 +10,7 @@ public sealed record AdminState public AdminState() { } public ImmutableDictionary ElementUsers { get; init; } = []; public ImmutableDictionary MoodleUsers { get; init; } = []; - public ImmutableDictionary LdapUsers { get; init; } = []; + public ImmutableDictionary LdapUsers { get; init; } = []; + public bool LdapUsersLoaded { get; init; } public ImmutableDictionary MsolUsers { get; init; } = []; }
@user.Username