about summary refs log tree commit diff
path: root/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixUtils.Web/Pages/Rooms/PolicyLists.razor')
-rw-r--r--MatrixUtils.Web/Pages/Rooms/PolicyLists.razor176
1 files changed, 176 insertions, 0 deletions
diff --git a/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor b/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor
new file mode 100644

index 0000000..2903ab8 --- /dev/null +++ b/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor
@@ -0,0 +1,176 @@ +@page "/PolicyLists" +@using ArcaneLibs.Extensions +@using LibMatrix +@using LibMatrix.EventTypes +@using LibMatrix.EventTypes.Common +@using LibMatrix.EventTypes.Spec.State.Policy +@using LibMatrix.RoomTypes +@inject ILogger<Index> logger +<h3>Policy lists </h3> @* <LinkButton href="/Rooms/Create">Create new policy list</LinkButton> *@ + +@if (!string.IsNullOrWhiteSpace(Status)) { + <p>@Status</p> +} +@if (!string.IsNullOrWhiteSpace(Status2)) { + <p>@Status2</p> +} +<hr/> + +<table> + <thead> + <tr> + <th/> + <th>Room name</th> + <th>Policies</th> + </tr> + </thead> + <tbody> + @foreach (var room in Rooms.OrderByDescending(x => x.PolicyCounts.Sum(y => y.Value))) { + <tr> + <td> + <LinkButton href="@($"/Rooms/{room.Room.RoomId}/Policies")"> + <span class="oi oi-pencil" aria-hidden="true"></span> + </LinkButton> + </td> + <td style="padding-right: 24px;"> + <span>@room.RoomName</span> + @if (room.IsLegacy) { + <span style="color: red;"> (legacy)</span> + } + <br/> + @if (!string.IsNullOrWhiteSpace(room.Shortcode)) { + <span style="font-size: 0.8em;">@room.Shortcode</span> + } + else { + <span style="color: red;">(no shortcode)</span> + } + </td> + <td> + <span>@(room.PolicyCounts.GetValueOrDefault(RoomInfo.PolicyType.User) ?? 0) user policies</span><br/> + <span>@(room.PolicyCounts.GetValueOrDefault(RoomInfo.PolicyType.Server) ?? 0) server policies</span><br/> + <span>@(room.PolicyCounts.GetValueOrDefault(RoomInfo.PolicyType.Room) ?? 0) room policies</span><br/> + </td> + </tr> + } + </tbody> +</table> + +@code { + + private List<RoomInfo> Rooms { get; } = []; + + private AuthenticatedHomeserverGeneric? Homeserver { get; set; } + + protected override async Task OnInitializedAsync() { + Homeserver = await sessionStore.GetCurrentHomeserver(navigateOnFailure: true); + if (Homeserver is null) return; + + Status = "Fetching rooms..."; + + var userEventTypes = EventContent.GetMatchingEventTypes<UserPolicyRuleEventContent>(); + var serverEventTypes = EventContent.GetMatchingEventTypes<ServerPolicyRuleEventContent>(); + var roomEventTypes = EventContent.GetMatchingEventTypes<RoomPolicyRuleEventContent>(); + var knownPolicyTypes = (List<string>) [..userEventTypes, ..serverEventTypes, ..roomEventTypes]; + + List<GenericRoom> roomsByType = []; + await foreach (var room in Homeserver.GetJoinedRoomsByType("support.feline.policy.lists.msc.v1")) { + roomsByType.Add(room); + Status2 = $"Found {room.RoomId} (MSC3784)..."; + } + + List<Task<RoomInfo>> tasks = roomsByType.Select(async room => { + Status2 = $"Fetching room {room.RoomId}..."; + return await RoomInfo.FromRoom(room); + }).ToList(); + + var results = tasks.ToAsyncEnumerable(); + await foreach (var result in results) { + Rooms.Add(result); + StateHasChanged(); + } + + Status = "Searching for legacy lists..."; + + var rooms = (await Homeserver.GetJoinedRooms()) + .Where(x => !Rooms.Any(y => y.Room.RoomId == x.RoomId)) + .Select(async room => { + var state = await room.GetFullStateAsListAsync(); + var policies = state + .Where(x => knownPolicyTypes.Contains(x.Type)) + .ToList(); + if (policies.Count == 0) return null; + Status2 = $"Found legacy list {room.RoomId}..."; + return await RoomInfo.FromRoom(room, state, true); + }) + .ToAsyncEnumerable(); + + await foreach (var room in rooms) { + if (room is not null) { + Rooms.Add(room); + StateHasChanged(); + } + } + + Status = ""; + Status2 = ""; + await base.OnInitializedAsync(); + } + + private string _status; + + public string Status { + get => _status; + set { + _status = value; + StateHasChanged(); + } + } + + private string _status2; + + public string Status2 { + get => _status2; + set { + _status2 = value; + StateHasChanged(); + } + } + + private class RoomInfo { + public GenericRoom Room { get; set; } + public string RoomName { get; set; } + public string? Shortcode { get; set; } + public Dictionary<PolicyType, int?> PolicyCounts { get; set; } + public bool IsLegacy { get; set; } + + public enum PolicyType { + User, + Room, + Server + } + + private static readonly List<string> userEventTypes = EventContent.GetMatchingEventTypes<UserPolicyRuleEventContent>(); + private static readonly List<string> serverEventTypes = EventContent.GetMatchingEventTypes<ServerPolicyRuleEventContent>(); + private static readonly List<string> roomEventTypes = EventContent.GetMatchingEventTypes<RoomPolicyRuleEventContent>(); + private static readonly List<string> allKnownPolicyTypes = [..userEventTypes, ..serverEventTypes, ..roomEventTypes]; + + public static async Task<RoomInfo> FromRoom(GenericRoom room, List<StateEventResponse>? state = null, bool legacy = false) { + state ??= await room.GetFullStateAsListAsync(); + return new RoomInfo() { + Room = room, + IsLegacy = legacy, + RoomName = await room.GetNameAsync() + ?? (await room.GetCanonicalAliasAsync())?.Alias + ?? (await room.GetStateOrNullAsync<MjolnirShortcodeEventContent>(MjolnirShortcodeEventContent.EventId))?.Shortcode + ?? room.RoomId, + Shortcode = (await room.GetStateOrNullAsync<MjolnirShortcodeEventContent>(MjolnirShortcodeEventContent.EventId))?.Shortcode, + PolicyCounts = new() { + { PolicyType.User, state.Count(x => userEventTypes.Contains(x.Type)) }, + { PolicyType.Server, state.Count(x => serverEventTypes.Contains(x.Type)) }, + { PolicyType.Room, state.Count(x => roomEventTypes.Contains(x.Type)) } + } + }; + } + } + +} \ No newline at end of file