about summary refs log tree commit diff
path: root/MatrixUtils.Web/Pages/LoginPage.razor
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixUtils.Web/Pages/LoginPage.razor')
-rw-r--r--MatrixUtils.Web/Pages/LoginPage.razor160
1 files changed, 160 insertions, 0 deletions
diff --git a/MatrixUtils.Web/Pages/LoginPage.razor b/MatrixUtils.Web/Pages/LoginPage.razor
new file mode 100644
index 0000000..ec4f57d
--- /dev/null
+++ b/MatrixUtils.Web/Pages/LoginPage.razor
@@ -0,0 +1,160 @@
+@page "/Login"
+@using System.Text.Json
+@using System.Text.Json.Serialization
+@using LibMatrix
+@inject ILocalStorageService LocalStorage
+@inject IJSRuntime JsRuntime
+<h3>Login</h3>
+<hr/>
+
+<span style="display: block;">
+    <label>User ID:</label>
+    <span>@@</span><!--
+    --><FancyTextBox @bind-Value="@newRecordInput.Username"></FancyTextBox><!--
+    --><span>:</span><!--
+    --><FancyTextBox @bind-Value="@newRecordInput.Homeserver"></FancyTextBox>
+</span>
+<span style="display: block;">
+    <label>Password:</label>
+    <FancyTextBox @bind-Value="@newRecordInput.Password" IsPassword="true"></FancyTextBox>
+</span>
+<span style="display: block">
+    <label>Proxy (<a href="https://cgit.rory.gay/matrix/MxApiExtensions.git">MxApiExtensions</a> or similar):</label>
+    <FancyTextBox @bind-Value="@newRecordInput.Proxy"></FancyTextBox>
+</span>
+<br/>
+<LinkButton OnClick="@AddRecord">Add account to queue</LinkButton>
+<LinkButton OnClick="@(() => Login(newRecordInput))">Log in</LinkButton>
+<br/>
+<br/>
+
+<h4>Import from TSV</h4>
+<hr/>
+<span>Import credentials from a TSV (Tab Separated Values) file</span><br/>
+<span>Columns: username, homeserver, password, proxy</span><br/>
+<span>Keep in mind there is no column header!</span><br/>
+<br/>
+<InputFile OnChange="@FileChanged" accept=".tsv"></InputFile>
+<br/>
+<br/>
+
+<table border="1">
+    <thead style="border-bottom: 1px solid white;">
+        <th style="min-width: 150px; text-align: center; border-right: 1px solid white;">Username</th>
+        <th style="min-width: 150px; text-align: center; border-right: 1px solid white;">Homeserver</th>
+        <th style="min-width: 150px; text-align: center; border-right: 1px solid white;">Password</th>
+        <th style="min-width: 150px; text-align: center; border-right: 1px solid white;">Proxy</th>
+        <th style="min-width: 150px; text-align: center;">Actions</th>
+    </thead>
+    @foreach (var record in records) {
+        var r = record;
+        <tr style="background-color: @(LoggedInSessions.Any(x => x.UserId == $"@{r.Username}:{r.Homeserver}" && x.Proxy == r.Proxy) ? "green" : "unset")">
+            <td style="border-width: 1px;">
+                <FancyTextBox @bind-Value="@r.Username"></FancyTextBox>
+            </td>
+            <td style="border-width: 1px;">
+                <FancyTextBox @bind-Value="@r.Homeserver"></FancyTextBox>
+            </td>
+            <td style="border-width: 1px;">
+                <FancyTextBox @bind-Value="@r.Password" IsPassword="true"></FancyTextBox>
+            </td>
+            <td style="border-width: 1px;">
+                <FancyTextBox @bind-Value="@r.Proxy"></FancyTextBox>
+            </td>
+            <td style="border-width: 1px;">
+                <a role="button" @onclick="() => records.Remove(r)">Remove</a>
+            </td>
+        </tr>
+        @if (r.Exception is MatrixException me) {
+            <tr>
+                <td style="border-width: 1px;">Exception:</td>
+                <td style="border-width: 1px;">@me.ErrorCode</td>
+                <td style="border-width: 1px;" colspan="3">@me.Error</td>
+            </tr>
+        }
+        else if (r.Exception is { } e) {
+            <tr>
+                <td style="border-width: 1px;">Exception:</td>
+                <td style="border-width: 1px;" colspan="4">@e.Message</td>
+            </tr>
+        }
+    }
+</table>
+<br/>
+<LinkButton OnClick="@LoginAll">Log in</LinkButton>
+
+
+@code {
+    readonly List<LoginStruct> records = new();
+    private LoginStruct newRecordInput = new();
+
+    List<UserAuth>? LoggedInSessions { get; set; } = new();
+
+    async Task LoginAll() {
+        var loginTasks = records.Select(Login);
+        await Task.WhenAll(loginTasks);
+    }
+
+    async Task Login(LoginStruct record) {
+        if (!records.Contains(record)) 
+            records.Add(record);
+        if (LoggedInSessions.Any(x => x.UserId == $"@{record.Username}:{record.Homeserver}" && x.Proxy == record.Proxy)) return;
+        StateHasChanged();
+        try {
+            var result = new UserAuth(await hsProvider.Login(record.Homeserver, record.Username, record.Password, record.Proxy)) {
+                Proxy = record.Proxy
+            };
+            if (result == null) {
+                Console.WriteLine($"Failed to login to {record.Homeserver} as {record.Username}!");
+                return;
+            }
+
+            Console.WriteLine($"Obtained access token for {result.UserId}!");
+
+            await RMUStorage.AddToken(result);
+            LoggedInSessions = await RMUStorage.GetAllTokens();
+        }
+        catch (Exception e) {
+            Console.WriteLine($"Failed to login to {record.Homeserver} as {record.Username}!");
+            Console.WriteLine(e);
+            record.Exception = e;
+        }
+
+        StateHasChanged();
+    }
+
+    private async Task FileChanged(InputFileChangeEventArgs obj) {
+        LoggedInSessions = await RMUStorage.GetAllTokens();
+        Console.WriteLine(JsonSerializer.Serialize(obj, new JsonSerializerOptions {
+            WriteIndented = true
+        }));
+        await using var rs = obj.File.OpenReadStream();
+        using var sr = new StreamReader(rs);
+        var tsvData = await sr.ReadToEndAsync();
+        records.Clear();
+        foreach (var line in tsvData.Split('\n')) {
+            string?[] parts = line.Split('\t');
+            if (parts.Length < 3)
+                continue;
+            string? via = parts.Length > 3 ? parts[3] : null;
+            records.Add(new() { Homeserver = parts[0], Username = parts[1], Password = parts[2], Proxy = via });
+        }
+    }
+
+    private async Task AddRecord() {
+        LoggedInSessions = await RMUStorage.GetAllTokens();
+        records.Add(newRecordInput);
+        newRecordInput = new();
+    }
+
+    private class LoginStruct {
+        public string? Homeserver { get; set; } = "";
+        public string? Username { get; set; } = "";
+        public string? Password { get; set; } = "";
+        public string? Proxy { get; set; }
+        
+        [JsonIgnore]
+        internal Exception? Exception { get; set; }
+    }
+
+}
\ No newline at end of file