summary refs log tree commit diff
path: root/ModAS.Server/Services
diff options
context:
space:
mode:
authorTheArcaneBrony <myrainbowdash949@gmail.com>2023-12-23 08:54:55 +0100
committerTheArcaneBrony <myrainbowdash949@gmail.com>2023-12-23 08:54:55 +0100
commite051007ecdb3097bc9942fd9db369101a9568a0d (patch)
tree8227a254a69ad7227cc230127ef4052dff9a08d1 /ModAS.Server/Services
downloadModAS-e051007ecdb3097bc9942fd9db369101a9568a0d.tar.xz
Basic test
Diffstat (limited to '')
-rw-r--r--ModAS.Server/Services/AuthenticatedHomeserverProviderService.cs47
-rw-r--r--ModAS.Server/Services/AuthenticationService.cs79
-rw-r--r--ModAS.Server/Services/ModASConfiguration.cs10
-rw-r--r--ModAS.Server/Services/UserContextService.cs32
4 files changed, 168 insertions, 0 deletions
diff --git a/ModAS.Server/Services/AuthenticatedHomeserverProviderService.cs b/ModAS.Server/Services/AuthenticatedHomeserverProviderService.cs
new file mode 100644

index 0000000..fa8e00a --- /dev/null +++ b/ModAS.Server/Services/AuthenticatedHomeserverProviderService.cs
@@ -0,0 +1,47 @@ +using ArcaneLibs.Extensions; +using LibMatrix; +using LibMatrix.Homeservers; +using LibMatrix.Services; +using MxApiExtensions.Services; + +namespace ModAS.Server.Services; + +public class AuthenticatedHomeserverProviderService( + AuthenticationService authenticationService, + HomeserverProviderService homeserverProviderService, + IHttpContextAccessor request, + ModASConfiguration config, + AppServiceRegistration asRegistration + ) { + public HttpContext? _context = request.HttpContext; + public Dictionary<string, AuthenticatedHomeserverGeneric> KnownUsers { get; set; } = new(); + + public async Task<AuthenticatedHomeserverGeneric> GetImpersonatedHomeserver(string mxid) { + if (KnownUsers.TryGetValue(mxid, out var homeserver)) return homeserver; + var hs = await homeserverProviderService.GetAuthenticatedWithToken(config.ServerName, asRegistration.AsToken, config.HomeserverUrl); + await hs.SetImpersonate(mxid); + KnownUsers.TryAdd(mxid, hs); + return hs; + } + + public async Task<AuthenticatedHomeserverGeneric> GetHomeserver() { + var token = authenticationService.GetToken(); + if (token == null) { + throw new MatrixException { + ErrorCode = "M_MISSING_TOKEN", + Error = "Missing access token" + }; + } + + var mxid = await authenticationService.GetMxidFromToken(token); + if (mxid == "@anonymous:*") { + throw new MatrixException { + ErrorCode = "M_MISSING_TOKEN", + Error = "Missing access token" + }; + } + + var hsCanonical = string.Join(":", mxid.Split(':').Skip(1)); + return await homeserverProviderService.GetAuthenticatedWithToken(hsCanonical, token); + } +} \ No newline at end of file diff --git a/ModAS.Server/Services/AuthenticationService.cs b/ModAS.Server/Services/AuthenticationService.cs new file mode 100644
index 0000000..27e12ad --- /dev/null +++ b/ModAS.Server/Services/AuthenticationService.cs
@@ -0,0 +1,79 @@ +using LibMatrix; +using LibMatrix.Services; +using MxApiExtensions.Services; + +namespace ModAS.Server.Services; + +public class AuthenticationService(ILogger<AuthenticationService> logger, ModASConfiguration config, IHttpContextAccessor request, HomeserverProviderService homeserverProviderService) { + private readonly HttpRequest _request = request.HttpContext!.Request; + + private static Dictionary<string, string> _tokenMap = new(); + + internal string? GetToken(bool fail = true) { + string? token; + if (_request.Headers.TryGetValue("Authorization", out var tokens)) { + token = tokens.FirstOrDefault()?[7..]; + } + else { + token = _request.Query["access_token"]; + } + + if (string.IsNullOrWhiteSpace(token) && fail) { + throw new MatrixException() { + ErrorCode = "M_MISSING_TOKEN", + Error = "Missing access token" + }; + } + + return token; + } + + public async Task<string> GetMxidFromToken(string? token = null, bool fail = true) { + token ??= GetToken(fail); + if (string.IsNullOrWhiteSpace(token)) { + if (fail) { + throw new MatrixException() { + ErrorCode = "M_MISSING_TOKEN", + Error = "Missing access token" + }; + } + + return "@anonymous:*"; + } + + if (_tokenMap is not { Count: > 0 } && File.Exists("token_map")) { + _tokenMap = (await File.ReadAllLinesAsync("token_map")) + .Select(l => l.Split('\t')) + .ToDictionary(l => l[0], l => l[1]); + } + + + if (_tokenMap.TryGetValue(token, out var mxid)) return mxid; + + var lookupTasks = new Dictionary<string, Task<string?>>(); + + + logger.LogInformation("Looking up mxid for token {}", token); + var hs = await homeserverProviderService.GetAuthenticatedWithToken(config.ServerName, token, config.HomeserverUrl); + try { + var res = hs.WhoAmI.UserId; + logger.LogInformation("Got mxid {} for token {}", res, token); + await SaveMxidForToken(token, mxid); + + return res; + } + catch (MatrixException e) { + if (e.ErrorCode == "M_UNKNOWN_TOKEN") { + return null; + } + + throw; + } + } + + + public async Task SaveMxidForToken(string token, string mxid) { + _tokenMap.Add(token, mxid); + await File.AppendAllLinesAsync("token_map", new[] { $"{token}\t{mxid}" }); + } +} diff --git a/ModAS.Server/Services/ModASConfiguration.cs b/ModAS.Server/Services/ModASConfiguration.cs new file mode 100644
index 0000000..dc7c552 --- /dev/null +++ b/ModAS.Server/Services/ModASConfiguration.cs
@@ -0,0 +1,10 @@ +namespace MxApiExtensions.Services; + + +public class ModASConfiguration { + public ModASConfiguration(IConfiguration configuration) { + configuration.GetRequiredSection("ModAS").Bind(this); + } + public string ServerName { get; set; } + public string HomeserverUrl { get; set; } +} \ No newline at end of file diff --git a/ModAS.Server/Services/UserContextService.cs b/ModAS.Server/Services/UserContextService.cs new file mode 100644
index 0000000..23969cc --- /dev/null +++ b/ModAS.Server/Services/UserContextService.cs
@@ -0,0 +1,32 @@ +// using System.Collections.Concurrent; +// using System.Text.Json.Serialization; +// using ArcaneLibs.Extensions; +// using LibMatrix.Homeservers; +// using MxApiExtensions.Services; +// +// namespace ModAS.Server.Services; +// +// public class UserContextService(ModASConfiguration config, AuthenticatedHomeserverProviderService hsProvider) { +// internal static ConcurrentDictionary<string, UserContext> UserContextStore { get; set; } = new(); +// public readonly int SessionCount = UserContextStore.Count; +// +// public class UserContext { +// [JsonIgnore] +// public AuthenticatedHomeserverGeneric Homeserver { get; set; } +// } +// +// private readonly SemaphoreSlim _getUserContextSemaphore = new SemaphoreSlim(1, 1); +// public async Task<UserContext> GetCurrentUserContext() { +// var hs = await hsProvider.GetHomeserver(); +// // await _getUserContextSemaphore.WaitAsync(); +// var ucs = await UserContextStore.GetOrCreateAsync($"{hs.WhoAmI.UserId}/{hs.WhoAmI.DeviceId}/{hs.ServerName}:{hs.AccessToken}", async x => { +// var userContext = new UserContext() { +// Homeserver = hs +// }; +// +// return userContext; +// }, _getUserContextSemaphore); +// // _getUserContextSemaphore.Release(); +// return ucs; +// } +// }