about summary refs log tree commit diff
diff options
context:
space:
mode:
m---------LibMatrix0
-rw-r--r--MatrixUtils.Web/Pages/HSAdmin/Synapse/Components/SynapseRoomShutdownWindowContent.razor3
-rw-r--r--MatrixUtils.Web/Pages/HSAdmin/Synapse/RoomQuery.razor205
-rw-r--r--MatrixUtils.Web/Pages/Index.razor1
4 files changed, 123 insertions, 86 deletions
diff --git a/LibMatrix b/LibMatrix
-Subproject 4b508fa6216c6682925a42b67936b068e6db8e6
+Subproject ae199156caae9384d575d384daae5690e0b28aa
diff --git a/MatrixUtils.Web/Pages/HSAdmin/Synapse/Components/SynapseRoomShutdownWindowContent.razor b/MatrixUtils.Web/Pages/HSAdmin/Synapse/Components/SynapseRoomShutdownWindowContent.razor

index 124d073..3b3acac 100644 --- a/MatrixUtils.Web/Pages/HSAdmin/Synapse/Components/SynapseRoomShutdownWindowContent.razor +++ b/MatrixUtils.Web/Pages/HSAdmin/Synapse/Components/SynapseRoomShutdownWindowContent.razor
@@ -1,5 +1,6 @@ @using LibMatrix.Homeservers.Extensions.NamedCaches @using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Requests +@using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Responses @if (string.IsNullOrWhiteSpace(Context.DeleteId)) { <span>Block room: </span> @@ -77,6 +78,8 @@ ForcePurge = false }; + public SynapseAdminRoomListResult.SynapseAdminRoomListResultRoom? RoomDetails { get; set; } + public class ExtraDeleteOptions { // room options public bool QuarantineLocalMedia { get; set; } diff --git a/MatrixUtils.Web/Pages/HSAdmin/Synapse/RoomQuery.razor b/MatrixUtils.Web/Pages/HSAdmin/Synapse/RoomQuery.razor
index 5c29909..3e38ee2 100644 --- a/MatrixUtils.Web/Pages/HSAdmin/Synapse/RoomQuery.razor +++ b/MatrixUtils.Web/Pages/HSAdmin/Synapse/RoomQuery.razor
@@ -1,6 +1,10 @@ @page "/HSAdmin/Synapse/RoomQuery" +@using System.Diagnostics.CodeAnalysis @using Microsoft.AspNetCore.WebUtilities @using ArcaneLibs.Extensions +@using LibMatrix +@using LibMatrix.EventTypes.Spec.State.RoomInfo +@using LibMatrix.Homeservers.Extensions.NamedCaches @using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Filters @using LibMatrix.Homeservers.ImplementationDetails.Synapse.Models.Responses @using MatrixUtils.Web.Pages.HSAdmin.Synapse.Components @@ -47,46 +51,33 @@ @* </details> *@ } -@foreach (var res in Results) { +@foreach (var room in Results) { <div class="room-list-item"> @* <RoomListItem RoomName="@res.Name" RoomId="@res.RoomId"></RoomListItem> *@ <p> - @if (!string.IsNullOrWhiteSpace(res.CanonicalAlias)) { - <span>@res.CanonicalAlias - </span> + @if (!string.IsNullOrWhiteSpace(room.CanonicalAlias)) { + <span>@room.CanonicalAlias - </span> } - <span>@res.RoomId</span> - @if (!string.IsNullOrWhiteSpace(res.Name)) { - <span> (@res.Name)</span> + <span>@room.RoomId</span> + @if (!string.IsNullOrWhiteSpace(room.Name)) { + <span> (@room.Name)</span> } <br/> - @if (!string.IsNullOrWhiteSpace(res.Creator)) { - <span>Created by @res.Creator</span> + @if (!string.IsNullOrWhiteSpace(room.Creator)) { + <span>Created by @room.Creator</span> <br/> } </p> <p> - <LinkButton OnClick="@(() => { - DeleteRequests.TryAdd(res.RoomId, new() { - RoomId = res.RoomId, - DeleteRequest = new() { - Block = true, - Purge = true, - ForcePurge = false - } - }); - StateHasChanged(); - - return Task.CompletedTask; - })">Delete room - </LinkButton> - <LinkButton target="_blank" href="@($"/HSAdmin/Synapse/ResyncState?roomId={res.RoomId}&via={res.RoomId.Split(':', 2)[1]}")">Resync state</LinkButton> + <LinkButton OnClick="@(() => DeleteRoom(room))">Delete room</LinkButton> + <LinkButton target="_blank" href="@($"/HSAdmin/Synapse/ResyncState?roomId={room.RoomId}&via={room.RoomId.Split(':', 2)[1]}")">Resync state</LinkButton> </p> @{ List<string?> flags = []; - if (res.JoinedLocalMembers > 0) { - flags.Add(res.JoinRules switch { + if (true || room.JoinedLocalMembers > 0) { + flags.Add(room.JoinRules switch { "public" => "Public", "invite" => "Invite only", "knock" => "Knock", @@ -95,12 +86,13 @@ // TODO: default? null => null, "" => null, - _ => "unknown join rule: " + res.JoinRules + _ => "unknown join rule: " + room.JoinRules }); - if (!string.IsNullOrWhiteSpace(res.Encryption)) flags.Add("encrypted"); - if (!res.Federatable) flags.Add("unfederated"); + + if (!string.IsNullOrWhiteSpace(room.Encryption)) flags.Add("encrypted"); + if (!room.Federatable) flags.Add("unfederated"); - flags.Add(res.HistoryVisibility switch { + flags.Add(room.HistoryVisibility switch { "world_readable" => "world readable history", "shared" => "shared history", "invited" => "history since invite", @@ -108,35 +100,43 @@ // TODO: default? null => null, "" => null, - _ => "unknown history setting: " + res.HistoryVisibility + _ => "unknown history setting: " + room.HistoryVisibility }); - flags.Add(res.GuestAccess switch { + flags.Add(room.GuestAccess switch { "can_join" => "guests allowed", "forbidden" => null, // TODO: default? null => null, "" => null, - _ => "unknown guest access: " + res.GuestAccess, + _ => "unknown guest access: " + room.GuestAccess, }); flags = flags.Where(x => x != null).ToList(); } } - <span>@string.Join(", ", flags)</span><br/> + <span>@string.Join(", ", flags)</span> + @if (room.JoinedLocalMembers == 0 && flags.Count > 0) { + <span> at the time of leaving</span> + } + <br/> - <span>@res.StateEvents state events, room version @(res.Version ?? "1")</span><br/> + <span>@room.StateEvents state events, room version @(room.Version ?? "1")</span><br/> + @if (room.TombstoneEvent is not null) { + var tombstoneContent = room.TombstoneEvent.ContentAs<RoomTombstoneEventContent>()!; + <span>Room is tombstoned! Target room: @tombstoneContent.ReplacementRoom, message: @tombstoneContent.Body</span><br/> + } @{ - var memberSummary = $"{res.JoinedMembers} members, of which {res.JoinedLocalMembers} are on this server"; - if (res.LocalMembers is not null) { - memberSummary += $": {string.Join(", ", res.LocalMembers)}"; + var memberSummary = room.MemberSummary; + if (room.LocalMembers is not null) { + memberSummary += $": {string.Join(", ", room.LocalMembers)}"; } } <span>@memberSummary</span> <details> <summary>Full result data</summary> - <pre>@res.ToJson(ignoreNull: true)</pre> + <pre>@room.ToJson(ignoreNull: true)</pre> </details> </div> } @@ -154,7 +154,10 @@ @* } *@ @foreach (var (roomId, deleteRequest) in DeleteRequests) { - <ModalWindow Title="@($"Delete room {roomId}")" OnCloseClicked="@(() => { DeleteRequests.Remove(roomId); StateHasChanged(); })"> + <ModalWindow Title="@($"Delete room {roomId}")" OnCloseClicked="@(() => { + DeleteRequests.Remove(roomId); + StateHasChanged(); + })"> <SynapseRoomShutdownWindowContent Context="deleteRequest" Homeserver="Homeserver"/> </ModalWindow> } @@ -171,7 +174,7 @@ [Parameter] [SupplyParameterFromQuery(Name = "name_search")] - public string SearchTerm { get; set; } + public string? SearchTerm { get; set; } [Parameter] [SupplyParameterFromQuery(Name = "ascending")] @@ -181,14 +184,27 @@ private AuthenticatedHomeserverSynapse Homeserver { get; set; } = null!; - private string Status { get; set; } - - public SynapseAdminLocalRoomQueryFilter Filter { get; set; } = new(); + private SynapseAdminLocalRoomQueryFilter Filter { get; set; } = new(); private Dictionary<string, SynapseRoomShutdownWindowContent.RoomShutdownContext> DeleteRequests { get; set; } = []; // private Dictionary<string, SynapseAdminRoomDeleteStatus> DeleteStatuses { get; set; } = new(); + private NamedCache<SynapseRoomShutdownWindowContent.RoomShutdownContext> TaskMap { get; set; } = null!; + + protected override async Task OnInitializedAsync() { + var hs = await sessionStore.GetCurrentHomeserver(navigateOnFailure: true); + if (hs is not AuthenticatedHomeserverSynapse synapse) { + NavigationManager.NavigateTo("/"); + return; + } + + Homeserver = synapse; + TaskMap = new NamedCache<SynapseRoomShutdownWindowContent.RoomShutdownContext>(Homeserver, "gay.rory.matrixutils.synapse_room_shutdown_tasks"); + DeleteRequests = (await TaskMap.ReadCacheMapAsync()).Where(x => x.Value.DeleteId is not null).ToDictionary(); + StateHasChanged(); + } + protected override Task OnParametersSetAsync() { OrderBy ??= "name"; @@ -266,54 +282,67 @@ private async Task Search() { Results.Clear(); - var hs = await sessionStore.GetCurrentHomeserver(navigateOnFailure: true); - if (hs is AuthenticatedHomeserverSynapse synapse) { - Homeserver = synapse; - var searchRooms = synapse.Admin.SearchRoomsAsync(orderBy: OrderBy!, dir: Ascending ? "f" : "b", searchTerm: SearchTerm, localFilter: Filter).GetAsyncEnumerator(); - while (await searchRooms.MoveNextAsync()) { - var room = searchRooms.Current; - - var roomInfo = new RoomInfo { - RoomId = room.RoomId, - Name = room.Name, - CanonicalAlias = room.CanonicalAlias, - Creator = room.Creator, - Version = room.Version, - Encryption = room.Encryption, - Federatable = room.Federatable, - Public = room.Public, - JoinRules = room.JoinRules, - GuestAccess = room.GuestAccess, - HistoryVisibility = room.HistoryVisibility, - StateEvents = room.StateEvents, - JoinedMembers = room.JoinedMembers, - JoinedLocalMembers = room.JoinedLocalMembers - }; - - Results.Add(roomInfo); - - if ((Results.Count <= 200 && Results.Count % 10 == 0) || Results.Count % 1000 == 0) { - StateHasChanged(); - await Task.Yield(); - await Task.Delay(1); - } + var searchRooms = Homeserver.Admin.SearchRoomsAsync(orderBy: OrderBy!, dir: Ascending ? "f" : "b", searchTerm: SearchTerm, localFilter: Filter).GetAsyncEnumerator(); + while (await searchRooms.MoveNextAsync()) { + var room = searchRooms.Current; + + var roomInfo = new RoomInfo { + RoomId = room.RoomId, + Name = room.Name, + CanonicalAlias = room.CanonicalAlias, + Creator = room.Creator, + Version = room.Version, + Encryption = room.Encryption, + Federatable = room.Federatable, + Public = room.Public, + JoinRules = room.JoinRules, + GuestAccess = room.GuestAccess, + HistoryVisibility = room.HistoryVisibility, + StateEvents = room.StateEvents, + JoinedMembers = room.JoinedMembers, + JoinedLocalMembers = room.JoinedLocalMembers + }; + + Results.Add(roomInfo); + + if ((Results.Count <= 200 && Results.Count % 10 == 0) || Results.Count % 1000 == 0) { + StateHasChanged(); + await Task.Yield(); + await Task.Delay(1); } - - StateHasChanged(); - - var tasks = Results - .Where(x => x.JoinedLocalMembers is > 0 and < 100) - .Select(async r => { - var members = (await synapse.Admin.GetRoomMembersAsync(r.RoomId)).Members.Where(x => x.EndsWith(":" + synapse.ServerName)).ToList(); - r.LocalMembers = members; - } - ); - await Task.WhenAll(tasks); - //Logger.LogWarning($"Found {tasks.Count} rooms with >0, <100 local members"); } StateHasChanged(); + + var getLocalMembersTasks = Results + .Where(x => x.JoinedLocalMembers is > 0 and < 100) + .Select(async r => { + var members = (await Homeserver.Admin.GetRoomMembersAsync(r.RoomId)).Members.Where(x => x.EndsWith(":" + Homeserver.ServerName)).ToList(); + r.LocalMembers = members; + } + ); + await Task.WhenAll(getLocalMembersTasks); + + var getTombstoneTasks = Results + .Select(async r => { + var state = await Homeserver.Admin.GetRoomStateAsync(r.RoomId, type: "m.room.tombstone"); + var tombstone = state.Events.FirstOrDefault(x => x is { StateKey: "", Type: "m.room.tombstone" }); + if (tombstone is { } tombstoneEvent) { + r.TombstoneEvent = tombstoneEvent; + } + }); + await Task.WhenAll(getTombstoneTasks); + + StateHasChanged(); + } + + Task DeleteRoom(RoomInfo room) { + DeleteRequests.TryAdd(room.RoomId, new() { RoomId = room.RoomId, RoomDetails = room, DeleteRequest = new() { Block = true, Purge = true, ForcePurge = false } }); + StateHasChanged(); + + return Task.CompletedTask; } + // // private async Task DeleteRoom() { // if (DeleteRequest is { } deleteRequest) { @@ -395,6 +424,10 @@ private class RoomInfo : SynapseAdminRoomListResult.SynapseAdminRoomListResultRoom { public List<string>? LocalMembers { get; set; } + public StateEventResponse? TombstoneEvent { get; set; } + + [field: AllowNull, MaybeNull] + public string MemberSummary => field ??= $"{JoinedMembers} members, of which {JoinedLocalMembers} are on this server"; } } diff --git a/MatrixUtils.Web/Pages/Index.razor b/MatrixUtils.Web/Pages/Index.razor
index fd38f28..509c634 100644 --- a/MatrixUtils.Web/Pages/Index.razor +++ b/MatrixUtils.Web/Pages/Index.razor
@@ -245,6 +245,7 @@ Small collection of tools to do not-so-everyday things. Busy = false; StateHasChanged(); + Console.WriteLine("Index.OnInitializedAsync finished"); } private class UserInfo {