summary refs log tree commit diff
path: root/extra/admin-api/Spacebar.AdminAPI
diff options
context:
space:
mode:
authorEmma [it/its]@Rory& <root@rory.gay>2024-12-27 05:48:14 +0100
committerEmma [it/its]@Rory& <root@rory.gay>2025-10-05 21:33:50 +0200
commita632666203e7c6c67fdb3bcf1809a591b1d0edf1 (patch)
tree21059211df2229637a425089e4480b21cd6ffc1a /extra/admin-api/Spacebar.AdminAPI
parentUpdate dependencies (diff)
downloadserver-ts-a632666203e7c6c67fdb3bcf1809a591b1d0edf1.tar.xz
Rewrite access tokens, initial admin api
Diffstat (limited to 'extra/admin-api/Spacebar.AdminAPI')
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/Controllers/UserController.cs17
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/Extensions/DbExtensions.cs8
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/Middleware/AuthenticationMiddleware.cs53
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/Program.cs58
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/Properties/launchSettings.json23
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.csproj20
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.http6
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/appsettings.Development.json11
-rw-r--r--extra/admin-api/Spacebar.AdminAPI/appsettings.json9
9 files changed, 205 insertions, 0 deletions
diff --git a/extra/admin-api/Spacebar.AdminAPI/Controllers/UserController.cs b/extra/admin-api/Spacebar.AdminAPI/Controllers/UserController.cs
new file mode 100644

index 000000000..dbe497df6 --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/Controllers/UserController.cs
@@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Spacebar.Db.Contexts; +using Spacebar.Db.Models; + +namespace Spacebar.AdminAPI.Controllers; + +[ApiController] +[Route("/users")] +public class UserController(ILogger<UserController> logger, SpacebarDbContext db) : ControllerBase { + private readonly ILogger<UserController> _logger = logger; + + [HttpGet(Name = "/")] + public IAsyncEnumerable<User> Get() { + return db.Users.AsAsyncEnumerable(); + } +} \ No newline at end of file diff --git a/extra/admin-api/Spacebar.AdminAPI/Extensions/DbExtensions.cs b/extra/admin-api/Spacebar.AdminAPI/Extensions/DbExtensions.cs new file mode 100644
index 000000000..c97a15759 --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/Extensions/DbExtensions.cs
@@ -0,0 +1,8 @@ +using Microsoft.EntityFrameworkCore; +using Spacebar.Db.Models; + +namespace Spacebar.AdminAPI.Extensions; + +public static class DbExtensions { + public static string? GetString(this DbSet<Config> config, string key) => config.Find(key)?.Value; +} \ No newline at end of file diff --git a/extra/admin-api/Spacebar.AdminAPI/Middleware/AuthenticationMiddleware.cs b/extra/admin-api/Spacebar.AdminAPI/Middleware/AuthenticationMiddleware.cs new file mode 100644
index 000000000..400928e51 --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/Middleware/AuthenticationMiddleware.cs
@@ -0,0 +1,53 @@ +using System.Buffers.Text; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Cryptography; +using System.Text; +using ArcaneLibs.Extensions; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.IdentityModel.Tokens; +using Spacebar.AdminAPI.Extensions; +using Spacebar.Db.Contexts; + +namespace Spacebar.AdminAPI.Middleware; + +public class AuthenticationMiddleware(RequestDelegate next) { + public async Task Invoke(HttpContext context) { + if(Environment.GetEnvironmentVariable("SB_ADMIN_API_DISABLE_AUTH") == "true") { + await next(context); + return; + } + + if (!context.Request.Headers.ContainsKey("Authorization")) { + context.Response.StatusCode = 401; + await context.Response.WriteAsync("Authorization header is missing"); + return; + } + + var token = context.Request.Headers["Authorization"].ToString().Split(' ').Last(); + + var handler = new JwtSecurityTokenHandler(); + var secretFile = File.ReadAllText("../../../jwt.key.pub"); + var key = ECDsa.Create(ECCurve.NamedCurves.nistP256); + key.ImportFromPem(secretFile); + + var res = await handler.ValidateTokenAsync(token, new TokenValidationParameters { + IssuerSigningKey = new ECDsaSecurityKey(key), + ValidAlgorithms = new[] { "ES512" }, + LogValidationExceptions = true, + // These are required to be false for the token to be valid as they aren't provided by the token + ValidateIssuer = false, + ValidateLifetime = false, + ValidateAudience = false, + }); + + if (!res.IsValid) { + context.Response.StatusCode = 401; + await context.Response.WriteAsync("Invalid token"); + return; + } + + Console.WriteLine(res.ClaimsIdentity.Claims.Select(x => $"{x.Type} : {x.Value}").ToJson()); + + await next(context); + } +} \ No newline at end of file diff --git a/extra/admin-api/Spacebar.AdminAPI/Program.cs b/extra/admin-api/Spacebar.AdminAPI/Program.cs new file mode 100644
index 000000000..8e40e3c54 --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/Program.cs
@@ -0,0 +1,58 @@ +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Http.Timeouts; +using Microsoft.EntityFrameworkCore; +using Spacebar.AdminAPI.Middleware; +using Spacebar.Db.Contexts; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(options => { + options.MaxValidationDepth = null; + options.MaxIAsyncEnumerableBufferLimit = 100; +}).AddJsonOptions(options => { + options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; + options.JsonSerializerOptions.WriteIndented = true; +}); + +// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi +builder.Services.AddOpenApi(); +builder.Services.AddDbContextPool<SpacebarDbContext>(options => { + options + .UseNpgsql(builder.Configuration.GetConnectionString("Spacebar")) + .EnableDetailedErrors(); +}); + +builder.Services.AddRequestTimeouts(x => { + x.DefaultPolicy = new RequestTimeoutPolicy { + Timeout = TimeSpan.FromMinutes(10), + WriteTimeoutResponse = async context => { + context.Response.StatusCode = 504; + context.Response.ContentType = "application/json"; + await context.Response.StartAsync(); + await context.Response.WriteAsJsonAsync(new { error = "Unknown error" }); + await context.Response.CompleteAsync(); + } + }; +}); +builder.Services.AddCors(options => { + options.AddPolicy( + "Open", + policy => policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()); +}); + +var app = builder.Build(); +app.UseCors("Open"); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) { + app.MapOpenApi(); +} + +app.UseMiddleware<AuthenticationMiddleware>(); +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); \ No newline at end of file diff --git a/extra/admin-api/Spacebar.AdminAPI/Properties/launchSettings.json b/extra/admin-api/Spacebar.AdminAPI/Properties/launchSettings.json new file mode 100644
index 000000000..d362517ca --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/Properties/launchSettings.json
@@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "Development": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5112", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Local": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5112", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Local" + } + } + } +} diff --git a/extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.csproj b/extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.csproj new file mode 100644
index 000000000..8d14d79e9 --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.csproj
@@ -0,0 +1,20 @@ +<Project Sdk="Microsoft.NET.Sdk.Web"> + + <PropertyGroup> + <TargetFramework>net9.0</TargetFramework> + <Nullable>enable</Nullable> + <ImplicitUsings>enable</ImplicitUsings> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="ArcaneLibs" Version="1.0.0-preview.20241210-161342" /> + <PackageReference Include="ArcaneLibs.StringNormalisation" Version="1.0.0-preview.20241210-161342" /> + <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0"/> + <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.3.0" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\Spacebar.Db\Spacebar.Db.csproj" /> + </ItemGroup> + +</Project> diff --git a/extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.http b/extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.http new file mode 100644
index 000000000..707c9676d --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/Spacebar.AdminAPI.http
@@ -0,0 +1,6 @@ +@Spacebar.AdminAPI_HostAddress = http://localhost:5112 + +GET {{Spacebar.AdminAPI_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/extra/admin-api/Spacebar.AdminAPI/appsettings.Development.json b/extra/admin-api/Spacebar.AdminAPI/appsettings.Development.json new file mode 100644
index 000000000..5a367f27d --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/appsettings.Development.json
@@ -0,0 +1,11 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "ConnectionStrings": { + "Spacebar": "Host=127.0.0.1; Username=postgres; Database=spacebar" + } +} diff --git a/extra/admin-api/Spacebar.AdminAPI/appsettings.json b/extra/admin-api/Spacebar.AdminAPI/appsettings.json new file mode 100644
index 000000000..10f68b8c8 --- /dev/null +++ b/extra/admin-api/Spacebar.AdminAPI/appsettings.json
@@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +}