From df9031c47f8e97d8e2df3177093271a458f27267 Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Mon, 1 May 2023 02:43:32 +0200 Subject: Initial commit --- MatrixRoomUtils.Web/Pages/DataExportPage.razor | 83 ++++++++ MatrixRoomUtils.Web/Pages/Index.razor | 33 +++ MatrixRoomUtils.Web/Pages/LoginPage.razor | 46 ++++ .../Pages/PolicyListEditorPage.razor | 232 +++++++++++++++++++++ MatrixRoomUtils.Web/Pages/PolicyListRoomList.razor | 84 ++++++++ MatrixRoomUtils.Web/Pages/UserImportPage.razor | 74 +++++++ 6 files changed, 552 insertions(+) create mode 100644 MatrixRoomUtils.Web/Pages/DataExportPage.razor create mode 100644 MatrixRoomUtils.Web/Pages/Index.razor create mode 100644 MatrixRoomUtils.Web/Pages/LoginPage.razor create mode 100644 MatrixRoomUtils.Web/Pages/PolicyListEditorPage.razor create mode 100644 MatrixRoomUtils.Web/Pages/PolicyListRoomList.razor create mode 100644 MatrixRoomUtils.Web/Pages/UserImportPage.razor (limited to 'MatrixRoomUtils.Web/Pages') diff --git a/MatrixRoomUtils.Web/Pages/DataExportPage.razor b/MatrixRoomUtils.Web/Pages/DataExportPage.razor new file mode 100644 index 0000000..a7c6f6b --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/DataExportPage.razor @@ -0,0 +1,83 @@ +@page "/export" +@using MatrixRoomUtils.Web.Classes +@using MatrixRoomUtils.Web.Shared.IndexComponents +@using Blazored.LocalStorage +@using MatrixRoomUtils.Authentication +@using System.Text.Json +@using Microsoft.AspNetCore.Components.Rendering +@inject NavigationManager NavigationManager +@inject ILocalStorageService LocalStorage + +Export + +

Data export

+ +

+
Signed in accounts - Add new account or Import from TSV
+
+@if (_isLoaded) +{ +@foreach (var (token, user) in RuntimeStorage.UsersCache) +{ + +
+@user.LoginResponse.UserId[1..].Split(":")[0]\auth\access_token=@token
+@user.LoginResponse.UserId[1..].Split(":")[0]\auth\device_id=@user.LoginResponse.DeviceId
+@user.LoginResponse.UserId[1..].Split(":")[0]\auth\home_server=@(RuntimeStorage.HomeserverResolutionCache.ContainsKey(user.LoginResponse.HomeServer) ? RuntimeStorage.HomeserverResolutionCache[user.LoginResponse.HomeServer].Result : "loading...")
+@user.LoginResponse.UserId[1..].Split(":")[0]\auth\user_id=@@@user.LoginResponse.UserId
+@user.LoginResponse.UserId[1..].Split(":")[0]\user\automatically_share_keys_with_trusted_users=true
+@user.LoginResponse.UserId[1..].Split(":")[0]\user\muted_tags=global
+@user.LoginResponse.UserId[1..].Split(":")[0]\user\online_key_backup=true
+@user.LoginResponse.UserId[1..].Split(":")[0]\user\only_share_keys_with_verified_users=false
+    
+} +} +else +{ +

Loading...

+

@resolvedHomeservers/@totalHomeservers homeservers resolved...

+} + +@code { + private bool _isLoaded; + private int resolvedHomeservers; + private int totalHomeservers; + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); + if (!RuntimeStorage.WasLoaded) + { + Console.WriteLine("[INDEX] !!! LOCALSTORAGE WAS NOT LOADED !!!"); + await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + + Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); + + var homeservers = RuntimeStorage.UsersCache.Values.Select(x => x.LoginResponse.HomeServer).Distinct(); + totalHomeservers = homeservers.Count(); + StateHasChanged(); + foreach (var hs in homeservers) + { + if (RuntimeStorage.HomeserverResolutionCache.ContainsKey(hs)) continue; + var resolvedHomeserver = await MatrixAccount.ResolveHomeserverFromWellKnown(hs); + + if (RuntimeStorage.HomeserverResolutionCache.ContainsKey(hs)) + RuntimeStorage.HomeserverResolutionCache.Remove(hs); + RuntimeStorage.HomeserverResolutionCache.Add(hs, new(){Result = resolvedHomeserver, ResolutionTime = DateTime.Now}); + await RuntimeStorage.SaveToLocalStorage(LocalStorage); + + Console.WriteLine("Saved to local storage:"); + Console.WriteLine(JsonSerializer.Serialize(RuntimeStorage.HomeserverResolutionCache, new JsonSerializerOptions() + { + WriteIndented = true + })); + resolvedHomeservers++; + StateHasChanged(); + } + StateHasChanged(); + } + _isLoaded = true; + } + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor new file mode 100644 index 0000000..7e9facf --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/Index.razor @@ -0,0 +1,33 @@ +@page "/" +@using MatrixRoomUtils.Web.Classes +@using MatrixRoomUtils.Web.Shared.IndexComponents +@using Blazored.LocalStorage +@inject NavigationManager NavigationManager +@inject ILocalStorageService LocalStorage + +Index + +

Rory&::MatrixUtils

+Small collection of tools to do not-so-everyday things. + +

+
Signed in accounts - Add new account or Import from TSV
+
+@{ + Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); + if (!RuntimeStorage.WasLoaded) + { + Console.WriteLine("[INDEX] !!! LOCALSTORAGE WAS NOT LOADED !!!"); + RuntimeStorage.LoadFromLocalStorage(LocalStorage).GetAwaiter().OnCompleted(() => + { + Console.WriteLine("Users in cache: " + RuntimeStorage.UsersCache.Count); + StateHasChanged(); + }); + } +} +
+ @foreach (var (token, user) in RuntimeStorage.UsersCache) + { + + } + \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/LoginPage.razor b/MatrixRoomUtils.Web/Pages/LoginPage.razor new file mode 100644 index 0000000..d193f95 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/LoginPage.razor @@ -0,0 +1,46 @@ +@page "/Login" +@using MatrixRoomUtils.Authentication +@using MatrixRoomUtils.Web.Classes +@using Blazored.LocalStorage +@inject ILocalStorageService LocalStorage +

Login

+ + + +
+ + +
+ + +
+ +
+
+ + +@code { + string homeserver = ""; + string username = ""; + string password = ""; + async Task Login() + { + var result = await MatrixAccount.Login(homeserver, username, password); + Console.WriteLine($"Obtained access token for {result.UserId}!"); + + RuntimeStorage.AccessToken = result.AccessToken; + + var userinfo = new UserInfo() + { + LoginResponse = result + }; + userinfo.Profile = await MatrixAccount.GetProfile(result.HomeServer, result.UserId); + + RuntimeStorage.UsersCache.Add(result.AccessToken, userinfo); + RuntimeStorage.CurrentHomeserver = await MatrixAccount.ResolveHomeserverFromWellKnown(result.HomeServer); + + + await RuntimeStorage.SaveToLocalStorage(LocalStorage); + + } +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyListEditorPage.razor new file mode 100644 index 0000000..cedaf32 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/PolicyListEditorPage.razor @@ -0,0 +1,232 @@ +@page "/PolicyListEditor/{RoomId}" +@using MatrixRoomUtils.Authentication +@using MatrixRoomUtils.Web.Classes +@using Blazored.LocalStorage +@using System.Net.Http.Headers +@using System.Text.Json +@using MatrixRoomUtils.Extensions +@using MatrixRoomUtils.StateEventTypes +@inject ILocalStorageService LocalStorage +@inject NavigationManager NavigationManager +

Policy list editor

+ +

+ This policy list contains @PolicyEvents.Count(x => x.type == "m.policy.rule.server") server bans, + @PolicyEvents.Count(x => x.type == "m.policy.rule.room") room bans and + @PolicyEvents.Count(x => x.type == "m.policy.rule.user") user bans. +

+ + +@if (!PolicyEvents.Any(x => x.type == "m.policy.rule.server")) +{ +

No server policies

+} +else +{ +

Server policies

+
+ + + + + + + + + + + @foreach (var policyEvent in PolicyEvents.Where(x => x.type == "m.policy.rule.server" && x.content.Entity != null)) + { + + + + + + + } + +
ServerReasonExpiresActions
Entity: @policyEvent.content.Entity
State: @policyEvent.state_key
@policyEvent.content.Reason + @policyEvent.content.ExpiryDateTime + + +
+
+ Invalid events + + + + + + + + + @foreach (var policyEvent in PolicyEvents.Where(x => x.type == "m.policy.rule.server" && x.content.Entity == null)) + { + + + + + } + +
State keySerialised contents
@policyEvent.state_key@policyEvent.content.ToJson(indent: false, ignoreNull: true)
+
+} +@if (!PolicyEvents.Any(x => x.type == "m.policy.rule.room")) +{ +

No room policies

+} +else +{ +

Room policies

+
+ + + + + + + + + + + @foreach (var policyEvent in PolicyEvents.Where(x => x.type == "m.policy.rule.room" && x.content.Entity != null)) + { + + + + + + + } + +
RoomReasonExpiresActions
Entity: @policyEvent.content.Entity
State: @policyEvent.state_key
@policyEvent.content.Reason + @policyEvent.content.ExpiryDateTime + + +
+
+ Invalid events + + + + + + + + + @foreach (var policyEvent in PolicyEvents.Where(x => x.type == "m.policy.rule.room" && x.content.Entity == null)) + { + + + + + } + +
State keySerialised contents
@policyEvent.state_key@policyEvent.content.ToJson(indent: false, ignoreNull: true)
+
+} +@if (!PolicyEvents.Any(x => x.type == "m.policy.rule.user")) +{ +

No user policies

+} +else +{ +

User policies

+
+ + + + + + + + + + + @foreach (var policyEvent in PolicyEvents.Where(x => x.type == "m.policy.rule.user" && x.content.Entity != null)) + { + + + + + + + } + +
UserReasonExpiresActions
Entity: @string.Join("", policyEvent.content.Entity.Take(64))
State: @string.Join("",policyEvent.state_key.Take(64))
@policyEvent.content.Reason + @policyEvent.content.ExpiryDateTime + + +
+
+ Invalid events + + + + + + + + + @foreach (var policyEvent in PolicyEvents.Where(x => x.type == "m.policy.rule.user" && x.content.Entity == null)) + { + + + + + } + +
State keySerialised contents
@policyEvent.state_key@policyEvent.content.ToJson(indent: false, ignoreNull: true)
+
+} + + + +@code { + //get room list + // - sync withroom list filter + // type = support.feline.msc3784 + //support.feline.policy.lists.msc.v1 + + [Parameter] + public string? RoomId { get; set; } + + public List> PolicyEvents { get; set; } = new(); + + protected override async Task OnInitializedAsync() + { + if (!RuntimeStorage.WasLoaded) await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + await base.OnInitializedAsync(); + if(RuntimeStorage.AccessToken == null || RuntimeStorage.CurrentHomeserver == null) + { + NavigationManager.NavigateTo("/Login"); + return; + } + RoomId = RoomId.Replace('~', '.'); + await LoadStatesAsync(); + Console.WriteLine("Policy list editor initialized!"); + } + + private async Task LoadStatesAsync() + { + using var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeStorage.AccessToken); + var response = await client.GetAsync($"{RuntimeStorage.CurrentHomeserver}/_matrix/client/r0/rooms/{RoomId}/state"); + var content = await response.Content.ReadAsStringAsync(); + // Console.WriteLine(JsonSerializer.Deserialize(content).ToJson()); + var stateEvents = JsonSerializer.Deserialize>(content); + PolicyEvents = stateEvents.Where(x => x.type.StartsWith("m.policy.rule")) + .Select(x => JsonSerializer.Deserialize>(JsonSerializer.Serialize(x))).ToList(); + StateHasChanged(); + // foreach (var stateEvent in PolicyEvents.Where(x => x.replaces_state != "" && x.replaces_state != null)) + // { + // Console.WriteLine($"{stateEvent.replaces_state} -> {PolicyEvents.Any(x => x.state_key == stateEvent.replaces_state)}"); + // } + // foreach (var policyEvent in PolicyEvents) + // { + // Console.WriteLine(policyEvent.ToJson()); + // } + } + +} + diff --git a/MatrixRoomUtils.Web/Pages/PolicyListRoomList.razor b/MatrixRoomUtils.Web/Pages/PolicyListRoomList.razor new file mode 100644 index 0000000..39b7087 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/PolicyListRoomList.razor @@ -0,0 +1,84 @@ +@page "/PolicyListEditor" +@using MatrixRoomUtils.Authentication +@using MatrixRoomUtils.Web.Classes +@using Blazored.LocalStorage +@using System.Net.Http.Headers +@using System.Text.Json +@using MatrixRoomUtils.Extensions +@using MatrixRoomUtils.StateEventTypes +@inject ILocalStorageService LocalStorage +@inject NavigationManager NavigationManager +

Policy list editor

+ +
Room list
+
+@if (PolicyRoomList.Count == 0) +{ +

No policy rooms found.

+} +else +{ + foreach (var s in PolicyRoomList) + { + @s +
+ } +
+} + + + +@code { + //get room list + // - sync withroom list filter + // type = support.feline.msc3784 + //support.feline.policy.lists.msc.v1 + + public List PolicyRoomList { get; set; } = new(); + public List> PolicyEvents { get; set; } = new(); + + protected override async Task OnInitializedAsync() + { + if (!RuntimeStorage.WasLoaded) await RuntimeStorage.LoadFromLocalStorage(LocalStorage); + await base.OnInitializedAsync(); + if(RuntimeStorage.AccessToken == null || RuntimeStorage.CurrentHomeserver == null) + { + NavigationManager.NavigateTo("/Login"); + return; + } + await EnumeratePolicyRooms(); + Console.WriteLine("Policy list editor initialized!"); + } + + private async Task EnumeratePolicyRooms() + { + using HttpClient wc = new(); + wc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeStorage.AccessToken); + + //get room list + //temporary hack until rooms get enumerated... + string[] rooms = { "!fTjMjIzNKEsFlUIiru:neko.dev" }; + + foreach (string room in rooms) + { + Console.WriteLine($"Checking if {room} is a policy room..."); + var sk = await wc.GetAsync($"{RuntimeStorage.CurrentHomeserver}/_matrix/client/v3/rooms/{room}/state/org.matrix.mjolnir.shortcode"); + if (sk.IsSuccessStatusCode) + { + Console.WriteLine($"Got success..."); + var sko = await sk.Content.ReadFromJsonAsync(); + if (sko.TryGetProperty("shortcode", out JsonElement shortcode)) + { + Console.WriteLine($"Room {room} has a shortcode: {shortcode.GetString()}!"); + PolicyRoomList.Add(room); + StateHasChanged(); + } + else Console.WriteLine("No record found..."); + } + else Console.WriteLine($"Got failure {sk.StatusCode}..."); + } + + //print to console + Console.WriteLine($"Detected policy lists: {PolicyRoomList.ToJson()}"); + } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/UserImportPage.razor b/MatrixRoomUtils.Web/Pages/UserImportPage.razor new file mode 100644 index 0000000..ca0a213 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/UserImportPage.razor @@ -0,0 +1,74 @@ +@page "/ImportUsers" +@using MatrixRoomUtils.Authentication +@using MatrixRoomUtils.Web.Classes +@using Blazored.LocalStorage +@using System.Text.Json +@inject ILocalStorageService LocalStorage +

Login

+ + +
+ +

+

Parsed records

+
+ + @foreach (var (homeserver, username, password) in records) + { + + + + + + } +
@username@homeserver@password.Length chars
+
+
+ + +@code { + List<(string homeserver, string username, string password)> records = new(); + + async Task Login() + { + foreach (var (homeserver, username, password) in records) + { + if(RuntimeStorage.UsersCache.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}")) continue; + var result = await MatrixAccount.Login(homeserver, username, password); + Console.WriteLine($"Obtained access token for {result.UserId}!"); + + RuntimeStorage.AccessToken = result.AccessToken; + + var userinfo = new UserInfo() + { + LoginResponse = result + }; + userinfo.Profile = await MatrixAccount.GetProfile(result.HomeServer, result.UserId); + + RuntimeStorage.UsersCache.Add(result.AccessToken, userinfo); + StateHasChanged(); + } + + await RuntimeStorage.SaveToLocalStorage(LocalStorage); + } + + private async Task FileChanged(InputFileChangeEventArgs obj) + { + Console.WriteLine(JsonSerializer.Serialize(obj, new JsonSerializerOptions() + { + WriteIndented = true + })); + await using var rs = obj.File.OpenReadStream(); + using var sr = new StreamReader(rs); + string TsvData = await sr.ReadToEndAsync(); + records.Clear(); + foreach (var line in TsvData.Split('\n')) + { + var parts = line.Split('\t'); + if (parts.Length != 3) + continue; + records.Add((parts[0], parts[1], parts[2])); + } + } + +} \ No newline at end of file -- cgit 1.5.1