Loading users to Fluxor state now with Redis caching.
This commit is contained in:
@@ -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();
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; } = [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user