Loading users to Fluxor state now with Redis caching.
This commit is contained in:
@@ -1,17 +1,23 @@
|
|||||||
@page "/"
|
@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
|
@inject IJSRuntime JsRuntime
|
||||||
|
|
||||||
<PageTitle>LDAP Users</PageTitle>
|
<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>
|
<h1>LDAP Users</h1>
|
||||||
|
|
||||||
@if (users is null)
|
@if (!AdminState.Value.LdapUsersLoaded)
|
||||||
{
|
{
|
||||||
<p><em>Loading users...</em></p>
|
<p><em>Loading users...</em></p>
|
||||||
}
|
}
|
||||||
|
else if (!Users.Any())
|
||||||
|
{
|
||||||
|
<p>No LDAP users found.</p>
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<table class="table">
|
<table class="table">
|
||||||
@@ -25,7 +31,7 @@ else
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach (var user in users)
|
@foreach (var user in Users)
|
||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>@user.Username</td>
|
<td>@user.Username</td>
|
||||||
@@ -40,21 +46,17 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@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 = [];
|
base.OnInitialized();
|
||||||
|
Dispatcher.Dispatch(new Wollmilchsau.Store.AdminStore.GetAllLdapUsers());
|
||||||
await foreach (var user in LdapService.GetAllUsers())
|
|
||||||
{
|
|
||||||
users.Add(user);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task DownloadCsvAsync()
|
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.GivenName ?? string.Empty,
|
||||||
user.Surname ?? string.Empty,
|
user.Surname ?? string.Empty,
|
||||||
user.Classroom ?? 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 GetAllMoodleUsers();
|
||||||
public sealed record GetAllElementUsers();
|
public sealed record GetAllElementUsers();
|
||||||
public sealed record GetAllLdapUsers();
|
public sealed record GetAllLdapUsers();
|
||||||
|
public sealed record SetLdapUsers(IReadOnlyCollection<LdapUser> Users);
|
||||||
public sealed record GetAllMsolUsers();
|
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 AdminState() { }
|
||||||
public ImmutableDictionary<Guid, ElementUser> ElementUsers { get; init; } = [];
|
public ImmutableDictionary<Guid, ElementUser> ElementUsers { get; init; } = [];
|
||||||
public ImmutableDictionary<Guid, MoodleUser> MoodleUsers { 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; } = [];
|
public ImmutableDictionary<Guid, MsolUser> MsolUsers { get; init; } = [];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user