diff --git a/.idea/runConfigurations/Start_API.xml b/.idea/runConfigurations/Start_API.xml new file mode 100644 index 00000000..edb214cf --- /dev/null +++ b/.idea/runConfigurations/Start_API.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/jetbrains-mono.css b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/jetbrains-mono.css new file mode 100644 index 00000000..78aedd2b --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/jetbrains-mono.css @@ -0,0 +1,118 @@ +/* source: https://gist.github.com/aasmpro/95776294ecf48bd7d0562504bad848ea */ + +/* normal fonts */ + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 100; + src: url("./ttf/JetBrainsMono-Thin.ttf") format("truetype"); + src: url("./webfonts/JetBrainsMono-Thin.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 200; + src: url("./webfonts/JetBrainsMono-ExtraLight.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 300; + src: url("./webfonts/JetBrainsMono-Light.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 400; + src: url("./webfonts/JetBrainsMono-Regular.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 500; + src: url("./webfonts/JetBrainsMono-Medium.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 600; + src: url("./webfonts/JetBrainsMono-SemiBold.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 700; + src: url("./webfonts/JetBrainsMono-Bold.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: normal; + font-weight: 800; + src: url("./webfonts/JetBrainsMono-ExtraBold.woff2") format("woff2"); +} + +/* italic fonts */ + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 100; + src: url("./webfonts/JetBrainsMono-ThinItalic.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 200; + src: url("./webfonts/JetBrainsMono-ExtraLightItalic.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 300; + src: url("./webfonts/JetBrainsMono-LightItalic.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 400; + src: url("./webfonts/JetBrainsMono-Italic.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 500; + src: url("./webfonts/JetBrainsMono-MediumItalic.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 600; + src: url("./webfonts/JetBrainsMono-SemiBoldItalic.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 700; + src: url("./webfonts/JetBrainsMono-BoldItalic.woff2") format("woff2"); +} + +@font-face { + font-family: JetBrainsMono; + font-style: italic; + font-weight: 800; + src: url("./webfonts/JetBrainsMono-ExtraBoldItalic.woff2") format("woff2"); +} \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Bold.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Bold.woff2 new file mode 100644 index 00000000..4917f434 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Bold.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-BoldItalic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-BoldItalic.woff2 new file mode 100644 index 00000000..536d3f71 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-BoldItalic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraBold.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraBold.woff2 new file mode 100644 index 00000000..8f88c546 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraBold.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraBoldItalic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraBoldItalic.woff2 new file mode 100644 index 00000000..d1478bac Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraBoldItalic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraLight.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraLight.woff2 new file mode 100644 index 00000000..b97239f3 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraLight.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraLightItalic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraLightItalic.woff2 new file mode 100644 index 00000000..be01aaca Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ExtraLightItalic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Italic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Italic.woff2 new file mode 100644 index 00000000..d60c270e Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Italic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Light.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Light.woff2 new file mode 100644 index 00000000..65384987 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Light.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-LightItalic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-LightItalic.woff2 new file mode 100644 index 00000000..66ca3d2b Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-LightItalic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Medium.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Medium.woff2 new file mode 100644 index 00000000..669d04cd Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Medium.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-MediumItalic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-MediumItalic.woff2 new file mode 100644 index 00000000..80cfd15e Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-MediumItalic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Regular.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Regular.woff2 new file mode 100644 index 00000000..40da4276 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Regular.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-SemiBold.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-SemiBold.woff2 new file mode 100644 index 00000000..5ead7b0d Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-SemiBold.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-SemiBoldItalic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-SemiBoldItalic.woff2 new file mode 100644 index 00000000..c5dd294b Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-SemiBoldItalic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Thin.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Thin.woff2 new file mode 100644 index 00000000..17270e45 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-Thin.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ThinItalic.woff2 b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ThinItalic.woff2 new file mode 100644 index 00000000..a6432151 Binary files /dev/null and b/extra/admin-api/Utilities/Spacebar.AdminAPI.TestClient/wwwroot/lib/jetbrains-mono/webfonts/JetBrainsMono-ThinItalic.woff2 differ diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPITest/Program.cs b/extra/admin-api/Utilities/Spacebar.AdminAPITest/Program.cs new file mode 100644 index 00000000..00900e0a --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminAPITest/Program.cs @@ -0,0 +1,12 @@ +// See https://aka.ms/new-console-template for more information + +using System.Net.Http.Json; +using ArcaneLibs.Extensions; + +Console.WriteLine("Hello, World!"); +using var hc = new HttpClient(); +var response = hc.GetFromJsonAsAsyncEnumerable("http://localhost:5112/users/1183568750931099679/deactivate"); +await foreach (var item in response) { + Console.WriteLine(item.ToJson(indent: false)); +} + \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.AdminAPITest/Spacebar.AdminAPITest.csproj b/extra/admin-api/Utilities/Spacebar.AdminAPITest/Spacebar.AdminAPITest.csproj new file mode 100644 index 00000000..d9a0370a --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminAPITest/Spacebar.AdminAPITest.csproj @@ -0,0 +1,18 @@ + + + + Exe + net9.0 + preview + enable + enable + true + + + + + ..\..\..\..\..\..\..\.nuget\packages\arcanelibs\1.0.0-preview.20241210-161342\lib\net9.0\ArcaneLibs.dll + + + + diff --git a/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Program.cs b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Program.cs new file mode 100644 index 00000000..4bfb037a --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Program.cs @@ -0,0 +1,24 @@ +// See https://aka.ms/new-console-template for more information + +using ArcaneLibs; +using Spacebar.AdminApi.PrepareTestData.TestDataTypes; + +Console.WriteLine("Hello, World!"); +var tests = ClassCollector.ResolveFromAllAccessibleAssemblies(); +foreach (var test in tests) { + Console.WriteLine(test.Name); +} + +Console.Write("Enter test type to run: "); +var testType = Console.ReadLine(); +var testToRun = tests.FirstOrDefault(t => t.Name == testType); +var runMethod = testToRun?.GetMethod("Run"); + +if (runMethod != null) { + Console.WriteLine($"Running test {testToRun.FullName}..."); + var task = runMethod.Invoke(testToRun, null) as Task; + await task!; + Console.WriteLine($"Test {testToRun.FullName} completed."); +} else { + Console.WriteLine("Test not found."); +} \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Spacebar.AdminApi.PrepareTestData.csproj b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Spacebar.AdminApi.PrepareTestData.csproj new file mode 100644 index 00000000..de3115ae --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Spacebar.AdminApi.PrepareTestData.csproj @@ -0,0 +1,16 @@ + + + + Exe + net9.0 + preview + enable + enable + true + + + + + + + diff --git a/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/TestDataTypes/ITestData.cs b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/TestDataTypes/ITestData.cs new file mode 100644 index 00000000..4c667c65 --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/TestDataTypes/ITestData.cs @@ -0,0 +1,5 @@ +namespace Spacebar.AdminApi.PrepareTestData.TestDataTypes; + +public interface ITestData { + +} \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/TestDataTypes/MessageSpamTestData.cs b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/TestDataTypes/MessageSpamTestData.cs new file mode 100644 index 00000000..5ac792ad --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/TestDataTypes/MessageSpamTestData.cs @@ -0,0 +1,87 @@ +using System.Net.Http.Json; +using System.Text.Json.Nodes; + +namespace Spacebar.AdminApi.PrepareTestData.TestDataTypes; + +public class MessageSpamTestData : ITestData { + public static async Task Run() { + using var hc = new HttpClient(); + var token = await Utils.CreateUser(); + hc.DefaultRequestHeaders.Authorization = new("Bearer", token); + + int guildCount = 1; + int channelCount = 100; // per guild + int messageCount = 1000; // per channel + + for (int guild = 0; guild < guildCount; guild++) { + var guildId = await Utils.CreateGuild(token); + // for (int channel = 0; channel < channelCount; channel++) { + // Console.WriteLine($"> Creating channel {channel} in guild {guild}..."); + // var channelRequest = await hc.PostAsJsonAsync($"http://localhost:3001/api/v9/guilds/{guildId}/channels", new { + // name = Guid.NewGuid().ToString()[0..30], + // type = 0 + // }); + // var channelResponse = await channelRequest.Content.ReadFromJsonAsync(); + // var channelId = channelResponse!["id"]!.ToString(); + // await SendMessages(hc, channelId, messageCount); + // } + + var ss = new SemaphoreSlim(16,16); + var tasks = Enumerable.Range(0, channelCount).Select(async channel => { + await ss.WaitAsync(); + Console.WriteLine($"> Creating channel {channel} in guild {guildId}..."); + var channelRequest = await hc.PostAsJsonAsync($"http://localhost:3001/api/v9/guilds/{guildId}/channels", new { + name = Guid.NewGuid().ToString()[0..30], + type = 0 + }); + var channelResponse = await channelRequest.Content.ReadFromJsonAsync(); + var channelId = channelResponse!["id"]!.ToString(); + await SendMessages(hc, channelId, messageCount); + ss.Release(); + }); + await Task.WhenAll(tasks); + } + } + + private static async Task CreateChannels(HttpClient hc, string guildId, int channelCount) { + var tasks = Enumerable.Range(0, channelCount).Select(async channel => { + Console.WriteLine($"> Creating channel {channel} in guild {guildId}..."); + var channelRequest = await hc.PostAsJsonAsync($"http://localhost:3001/api/v9/guilds/{guildId}/channels", new { + name = Guid.NewGuid().ToString()[0..30], + type = 0 + }); + var channelResponse = await channelRequest.Content.ReadFromJsonAsync(); + }); + await Task.WhenAll(tasks); + } + + private static async Task SendMessages(HttpClient hc, string channelId, int maxMessageCount) { + // var ss = new SemaphoreSlim(32, 32); + // var tasks = Enumerable.Range(0, Random.Shared.Next((int)(0.75 * maxMessageCount), maxMessageCount)).Select(async message => { + // var success = false; + // while (!success) { + // await ss.WaitAsync(); + // Console.WriteLine($"> Sending message {message} in channel {channelId}..."); + // var messageReq = await hc.PostAsJsonAsync($"http://localhost:3001/api/v9/channels/{channelId}/messages", new { + // content = Guid.NewGuid().ToString() + // }); + // var messageResponse = await messageReq.Content.ReadFromJsonAsync(); + // if (messageResponse.ContainsKey("id")) { + // success = true; + // Console.WriteLine(messageResponse!["id"]!.ToString()); + // } + // } + // + // ss.Release(); + // }); + // await Task.WhenAll(tasks); + + var messageReq = await hc.PostAsJsonAsync($"http://localhost:3001/api/v9/channels/{channelId}/messages", new { + content = Guid.NewGuid().ToString() + }); + var messageResponse = await messageReq.Content.ReadFromJsonAsync(); + if (messageResponse.ContainsKey("id")) { + await hc.GetAsync($"http://localhost:5112/Users/duplicate/{messageResponse!["id"]!.ToString()}?count={maxMessageCount}"); + } + } +} \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Utils.cs b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Utils.cs new file mode 100644 index 00000000..143f50a4 --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.AdminApi.PrepareTestData/Utils.cs @@ -0,0 +1,35 @@ +using System.Net.Http.Json; +using System.Text.Json.Nodes; +using ArcaneLibs.Extensions; + +namespace Spacebar.AdminApi.PrepareTestData; + +public static class Utils { + public static async Task CreateUser() { + Console.WriteLine("> Creating user..."); + using var hc = new HttpClient(); + var registerRequest = await hc.PostAsJsonAsync("http://localhost:3001/api/v9/auth/register", new { + username = Guid.NewGuid().ToString()[0..30], + password = "password", + email = $"{Guid.NewGuid()}@example.com", + consent = true, + date_of_birth = "2000-01-01", + }); + var registerResponse = await registerRequest.Content.ReadFromJsonAsync(); + return registerResponse!["token"]!.ToString(); + } + + public static async Task CreateGuild(string token) { + using var hc = new HttpClient(); + hc.DefaultRequestHeaders.Authorization = new("Bearer", token); + + Console.WriteLine("> Creating guild..."); + var guildRequest = await hc.PostAsJsonAsync("http://localhost:3001/api/v9/guilds", new { + name = Guid.NewGuid().ToString()[0..30] + }); + + var guildResponse = await guildRequest.Content.ReadFromJsonAsync(); + var guildId = guildResponse!["id"]!.ToString(); + return guildId; + } +} \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/RabbitMQConfiguration.cs b/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/RabbitMQConfiguration.cs new file mode 100644 index 00000000..e31e8c36 --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/RabbitMQConfiguration.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Configuration; + +namespace Spacebar.RabbitMqUtilities; + +public class RabbitMQConfiguration { + public RabbitMQConfiguration(IConfiguration configuration) { + configuration.GetRequiredSection("RabbitMQ").Bind(this); + } + public required string Host { get; set; } + public required string Username { get; set; } + public required string Password { get; set; } +} \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/RabbitMQService.cs b/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/RabbitMQService.cs new file mode 100644 index 00000000..22255942 --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/RabbitMQService.cs @@ -0,0 +1,21 @@ +using RabbitMQ.Client; + +namespace Spacebar.RabbitMqUtilities; + +public interface IRabbitMQService { + IConnection CreateChannel(); +} + +public class RabbitMQService(RabbitMQConfiguration config) : IRabbitMQService { + public IConnection CreateChannel() { + var connection = new ConnectionFactory { + UserName = config.Username, + Password = config.Password, + HostName = config.Host, + // DispatchConsumersAsync = true + }; + + var channel = connection.CreateConnection(); + return channel; + } +} \ No newline at end of file diff --git a/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/Spacebar.RabbitMqUtilities.csproj b/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/Spacebar.RabbitMqUtilities.csproj new file mode 100644 index 00000000..be1f4a77 --- /dev/null +++ b/extra/admin-api/Utilities/Spacebar.RabbitMqUtilities/Spacebar.RabbitMqUtilities.csproj @@ -0,0 +1,17 @@ + + + + net9.0 + preview + enable + enable + + + + + + + + + + diff --git a/extra/admin-api/result-man b/extra/admin-api/result-man deleted file mode 120000 index 0f21db9c..00000000 --- a/extra/admin-api/result-man +++ /dev/null @@ -1 +0,0 @@ -/nix/store/0q9yki1d9czy7i7mly8gy3ffjvc3hkqv-postgresql-16.5-man \ No newline at end of file diff --git a/src/api/middlewares/CORS.ts b/src/api/middlewares/CORS.ts index 3e7452fc..ca6abb82 100644 --- a/src/api/middlewares/CORS.ts +++ b/src/api/middlewares/CORS.ts @@ -36,5 +36,9 @@ export function CORS(req: Request, res: Response, next: NextFunction) { req.header("Access-Control-Request-Methods") || "*", ); + if (req.method === "OPTIONS") { + res.status(204).end(); + return; + } next(); } diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts index 3f3164fc..09e8805f 100644 --- a/src/gateway/opcodes/Identify.ts +++ b/src/gateway/opcodes/Identify.ts @@ -64,10 +64,17 @@ import { PreloadedUserSettings } from "discord-protos"; // TODO: user sharding // TODO: check privileged intents, if defined in the config +function logAuth(message: string) { + if (process.env.LOG_AUTH != "true") return; + console.log(`[Gateway/Auth] ${message}`); +} + const tryGetUserFromToken = async (...args: Parameters) => { + logAuth("Checking token"); try { return (await checkToken(...args)).user; } catch (e) { + console.log("[Gateway] Error when identifying: ", e); return null; } }; @@ -96,7 +103,10 @@ export async function onIdentify(this: WebSocket, data: Payload) { relations: ["relationships", "relationships.to", "settings"], select: [...PrivateUserProjection, "relationships"], }); - if (!user) return this.close(CLOSECODES.Authentication_failed); + if (!user) { + console.log("[Gateway] Failed to identify user"); + return this.close(CLOSECODES.Authentication_failed); + } this.user_id = user.id; const userQueryTime = taskSw.getElapsedAndReset(); diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts index 844d21ac..3de05aa2 100644 --- a/src/util/util/Token.ts +++ b/src/util/util/Token.ts @@ -36,6 +36,16 @@ export type UserTokenData = { decoded: { id: string; iat: number }; }; +function logAuth(text: string) { + if(process.env.LOG_AUTH !== "true") return; + console.log(`[AUTH] ${text}`); +} + +function rejectAndLog(rejectFunction: (reason?: any) => void, reason: any) { + console.error(reason); + rejectFunction(reason); +} + export const checkToken = ( token: string, opts?: { @@ -49,12 +59,16 @@ export const checkToken = ( const validateUser: jwt.VerifyCallback = async (err, out) => { const decoded = out as UserTokenData["decoded"]; - if (err || !decoded) return reject("Invalid Token meow " + err); + if (err || !decoded) { + logAuth("validateUser rejected: " + err); + return rejectAndLog(reject, "Invalid Token meow " + err); + } const user = await User.findOne({ where: { id: decoded.id }, select: [ ...(opts?.select || []), + "id", "bot", "disabled", "deleted", @@ -64,23 +78,36 @@ export const checkToken = ( relations: opts?.relations, }); - if (!user) return reject("User not found"); + if (!user) { + logAuth("validateUser rejected: User not found"); + return rejectAndLog(reject, "User not found"); + } // we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds if ( decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0) - ) - return reject("Invalid Token"); + ) { + logAuth("validateUser rejected: Token not yet valid"); + return rejectAndLog(reject, "Invalid Token"); + } - if (user.disabled) return reject("User disabled"); - if (user.deleted) return reject("User not found"); + if (user.disabled) { + logAuth("validateUser rejected: User disabled"); + return rejectAndLog(reject, "User disabled"); + } + if (user.deleted) { + logAuth("validateUser rejected: User deleted"); + return rejectAndLog(reject, "User not found"); + } + logAuth("validateUser success: " + JSON.stringify({ decoded, user })); return resolve({ decoded, user }); }; const dec = jwt.decode(token, { complete: true }); if (!dec) return reject("Could not parse token"); + logAuth("Decoded token: " + JSON.stringify(dec)); if (dec.header.alg == "HS256") { jwt.verify(