Remove StartupOptions, generate version from assembly info

This commit is contained in:
Laura Hausmann 2024-01-13 18:22:28 +01:00
parent eace0cb0de
commit 7130df87ae
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
9 changed files with 51 additions and 41 deletions

View file

@ -12,7 +12,7 @@ namespace Iceshrimp.Backend.Controllers;
[ApiController] [ApiController]
[MediaTypeRouteFilter("application/activity+json", "application/ld+json")] [MediaTypeRouteFilter("application/activity+json", "application/ld+json")]
[Produces("application/activity+json", "application/ld+json")] [Produces("application/activity+json", "application/ld+json")]
public class ActivityPubController(ILogger<ActivityPubController> logger, DatabaseContext db) : Controller { public class ActivityPubController(ILogger<ActivityPubController> logger, DatabaseContext db, APUserRenderer userRenderer) : Controller {
/* /*
[HttpGet("/notes/{id}")] [HttpGet("/notes/{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Note))] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Note))]
@ -31,7 +31,7 @@ public class ActivityPubController(ILogger<ActivityPubController> logger, Databa
public async Task<IActionResult> GetUser(string id) { public async Task<IActionResult> GetUser(string id) {
var user = await db.Users.FirstOrDefaultAsync(p => p.Id == id); var user = await db.Users.FirstOrDefaultAsync(p => p.Id == id);
if (user == null) return NotFound(); if (user == null) return NotFound();
var rendered = await ActivityPubUserRenderer.Render(user); var rendered = await userRenderer.Render(user);
var compacted = LDHelpers.Compact(rendered); var compacted = LDHelpers.Compact(rendered);
return Ok(compacted); return Ok(compacted);
} }

View file

@ -4,17 +4,20 @@ using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Database.Tables; using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types; using Iceshrimp.Backend.Core.Federation.ActivityStreams.Types;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace Iceshrimp.Backend.Controllers.Renderers.ActivityPub; namespace Iceshrimp.Backend.Controllers.Renderers.ActivityPub;
public static class ActivityPubUserRenderer { public class APUserRenderer(
public static async Task<ASActor> Render(User user) { IOptions<Config.InstanceSection> config,
ILogger<APUserRenderer> logger,
DatabaseContext db) {
public async Task<ASActor> Render(User user) {
if (user.Host != null) throw new Exception(); if (user.Host != null) throw new Exception();
var db = new DatabaseContext();
var profile = await db.UserProfiles.FirstOrDefaultAsync(p => p.UserId == user.Id); var profile = await db.UserProfiles.FirstOrDefaultAsync(p => p.UserId == user.Id);
var id = $"https://{Config.StartupConfig.Instance.WebDomain}/users/{user.Id}"; var id = $"https://{config.Value.WebDomain}/users/{user.Id}";
var type = Constants.SystemUsers.Contains(user.UsernameLower) var type = Constants.SystemUsers.Contains(user.UsernameLower)
? "Application" ? "Application"
: user.IsBot : user.IsBot
@ -30,7 +33,7 @@ public static class ActivityPubUserRenderer {
//Following = $"{id}/following", //Following = $"{id}/following",
//SharedInbox = $"{Config.Instance.Url}/inbox", //SharedInbox = $"{Config.Instance.Url}/inbox",
//Endpoints = new Dictionary<string, string> { { "SharedInbox", $"{Config.Instance.Url}/inbox" } }, //Endpoints = new Dictionary<string, string> { { "SharedInbox", $"{Config.Instance.Url}/inbox" } },
Url = new ASLink($"https://{Config.StartupConfig.Instance.WebDomain}/@{user.Username}"), Url = new ASLink($"https://{config.Value.WebDomain}/@{user.Username}"),
Username = user.Username, Username = user.Username,
DisplayName = user.Name ?? user.Username, DisplayName = user.Name ?? user.Username,
Summary = profile?.Description != null ? "Not implemented" : null, //TODO: convert to html Summary = profile?.Description != null ? "Not implemented" : null, //TODO: convert to html

View file

@ -1,19 +1,31 @@
using System.Reflection;
namespace Iceshrimp.Backend.Core.Configuration; namespace Iceshrimp.Backend.Core.Configuration;
public sealed class Config { public sealed class Config {
// FIXME: This doesn't reflect config updates.
public static Config StartupConfig { get; set; } = null!;
public required InstanceSection Instance { get; set; } public required InstanceSection Instance { get; set; }
public required DatabaseSection Database { get; set; } public required DatabaseSection Database { get; set; }
public StaticSection Static = new();
public sealed class StaticSection {
public string Version = "0.0.1";
public string UserAgent => $"Iceshrimp.NET/{Version} (https://{StartupConfig.Instance.WebDomain})";
}
public sealed class InstanceSection { public sealed class InstanceSection {
public readonly string Version;
public string UserAgent => $"Iceshrimp.NET/{Version} (https://{WebDomain})";
public InstanceSection() {
// Get version information from assembly
var version = Assembly.GetEntryAssembly()!
.GetCustomAttributes().OfType<AssemblyInformationalVersionAttribute>()
.First().InformationalVersion;
// If we have a git revision, limit it to 10 characters
if (version.Split('+') is { Length: 2 } split) {
split[1] = split[1][..Math.Min(split[1].Length, 10)];
Version = string.Join('+', split);
}
else {
Version = version;
}
}
public required int ListenPort { get; set; } = 3000; public required int ListenPort { get; set; } = 3000;
public required string WebDomain { get; set; } public required string WebDomain { get; set; }
public required string AccountDomain { get; set; } public required string AccountDomain { get; set; }

View file

@ -9,16 +9,8 @@ namespace Iceshrimp.Backend.Core.Database;
[SuppressMessage("ReSharper", "StringLiteralTypo")] [SuppressMessage("ReSharper", "StringLiteralTypo")]
[SuppressMessage("ReSharper", "IdentifierTypo")] [SuppressMessage("ReSharper", "IdentifierTypo")]
public class DatabaseContext : DbContext { public class DatabaseContext(DbContextOptions<DatabaseContext> options, IOptions<Config.DatabaseSection> config)
private readonly IOptions<Config.DatabaseSection>? _config; : DbContext(options) {
public DatabaseContext() { }
public DatabaseContext(DbContextOptions<DatabaseContext> options, IOptions<Config.DatabaseSection> config)
: base(options) {
_config = config;
}
public virtual DbSet<AbuseUserReport> AbuseUserReports { get; init; } = null!; public virtual DbSet<AbuseUserReport> AbuseUserReports { get; init; } = null!;
public virtual DbSet<AccessToken> AccessTokens { get; init; } = null!; public virtual DbSet<AccessToken> AccessTokens { get; init; } = null!;
public virtual DbSet<Announcement> Announcements { get; init; } = null!; public virtual DbSet<Announcement> Announcements { get; init; } = null!;
@ -90,13 +82,13 @@ public class DatabaseContext : DbContext {
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
var dataSourceBuilder = new NpgsqlDataSourceBuilder(); var dataSourceBuilder = new NpgsqlDataSourceBuilder();
if (_config == null) if (config == null)
throw new Exception("Failed to initialize database: Failed to load configuration"); throw new Exception("Failed to initialize database: Failed to load configuration");
dataSourceBuilder.ConnectionStringBuilder.Host = _config.Value.Host; dataSourceBuilder.ConnectionStringBuilder.Host = config.Value.Host;
dataSourceBuilder.ConnectionStringBuilder.Username = _config.Value.Username; dataSourceBuilder.ConnectionStringBuilder.Username = config.Value.Username;
dataSourceBuilder.ConnectionStringBuilder.Password = _config.Value.Password; dataSourceBuilder.ConnectionStringBuilder.Password = config.Value.Password;
dataSourceBuilder.ConnectionStringBuilder.Database = _config.Value.Database; dataSourceBuilder.ConnectionStringBuilder.Database = config.Value.Database;
dataSourceBuilder.MapEnum<Antenna.AntennaSource>(); dataSourceBuilder.MapEnum<Antenna.AntennaSource>();
dataSourceBuilder.MapEnum<Note.NoteVisibility>(); dataSourceBuilder.MapEnum<Note.NoteVisibility>();

View file

@ -32,8 +32,7 @@ public class Fetch {
//notes?.ForEach(p => Console.WriteLine(p.PublishedAt)); //notes?.ForEach(p => Console.WriteLine(p.PublishedAt));
} }
public static void PerformActivity(ASNote note) { public static void PerformActivity(ASNote note, DatabaseContext db) {
var db = new DatabaseContext();
var actorUri = note.AttributedTo?.FirstOrDefault()?.Id; var actorUri = note.AttributedTo?.FirstOrDefault()?.Id;
if (actorUri == null) return; if (actorUri == null) return;
var user = db.Users.FirstOrDefault(p => p.Uri == actorUri) ?? FetchUser(actorUri); var user = db.Users.FirstOrDefault(p => p.Uri == actorUri) ?? FetchUser(actorUri);

View file

@ -1,3 +1,4 @@
using Iceshrimp.Backend.Controllers.Renderers.ActivityPub;
using Iceshrimp.Backend.Core.Configuration; using Iceshrimp.Backend.Core.Configuration;
using Iceshrimp.Backend.Core.Federation; using Iceshrimp.Backend.Core.Federation;
using Iceshrimp.Backend.Core.Federation.Services; using Iceshrimp.Backend.Core.Federation.Services;
@ -15,6 +16,7 @@ public static class ServiceExtensions {
services.AddScoped<UserResolver>(); services.AddScoped<UserResolver>();
services.AddScoped<UserService>(); services.AddScoped<UserService>();
services.AddScoped<NoteService>(); services.AddScoped<NoteService>();
services.AddScoped<APUserRenderer>();
// Singleton = instantiated once across application lifetime // Singleton = instantiated once across application lifetime
services.AddSingleton<HttpClient>(); services.AddSingleton<HttpClient>();
@ -24,11 +26,8 @@ public static class ServiceExtensions {
public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration) { public static void ConfigureServices(this IServiceCollection services, IConfiguration configuration) {
//TODO: fail if config doesn't parse correctly / required things are missing //TODO: fail if config doesn't parse correctly / required things are missing
services.Configure<Config>(configuration);
services.Configure<Config.InstanceSection>(configuration.GetSection("Instance")); services.Configure<Config.InstanceSection>(configuration.GetSection("Instance"));
services.Configure<Config.DatabaseSection>(configuration.GetSection("Database")); services.Configure<Config.DatabaseSection>(configuration.GetSection("Database"));
services.AddScoped<Config.InstanceSection>();
services.AddScoped<Config.DatabaseSection>();
Config.StartupConfig = configuration.Get<Config>()!;
} }
} }

View file

@ -4,7 +4,7 @@ using Microsoft.Extensions.Options;
namespace Iceshrimp.Backend.Core.Services; namespace Iceshrimp.Backend.Core.Services;
public class HttpRequestService(IOptions<Config.StaticSection> options) { public class HttpRequestService(IOptions<Config.InstanceSection> options) {
private HttpRequestMessage GenerateRequest(string url, IEnumerable<string>? accept, HttpMethod method) { private HttpRequestMessage GenerateRequest(string url, IEnumerable<string>? accept, HttpMethod method) {
var message = new HttpRequestMessage { var message = new HttpRequestMessage {
RequestUri = new Uri(url), RequestUri = new Uri(url),

View file

@ -5,6 +5,8 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<VersionPrefix>2024.1</VersionPrefix>
<VersionSuffix>prealpha</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -38,8 +38,11 @@ builder.Services.AddServices();
builder.Services.ConfigureServices(builder.Configuration); builder.Services.ConfigureServices(builder.Configuration);
var app = builder.Build(); var app = builder.Build();
var instanceConfig = app.Configuration.GetSection("Instance").Get<Config.InstanceSection>() ??
throw new Exception("Failed to read Instance config section");
app.Logger.LogInformation("Iceshrimp.NET v{version} ({domain})", instanceConfig.Version, instanceConfig.AccountDomain);
app.Logger.LogInformation("Initializing, please wait..."); app.Logger.LogInformation("Initializing, please wait...");
app.Logger.LogInformation("Account domain: {AccountDomain}", Config.StartupConfig.Instance.AccountDomain);
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(options => { options.DocumentTitle = "Iceshrimp API documentation"; }); app.UseSwaggerUI(options => { options.DocumentTitle = "Iceshrimp API documentation"; });
@ -53,6 +56,6 @@ app.MapFallbackToPage("/Shared/FrontendSPA");
if (app.Environment.IsDevelopment()) app.UseViteDevMiddleware(); if (app.Environment.IsDevelopment()) app.UseViteDevMiddleware();
app.Urls.Clear(); app.Urls.Clear();
app.Urls.Add($"http://{Config.StartupConfig.Instance.WebDomain}:{Config.StartupConfig.Instance.ListenPort}"); app.Urls.Add($"http://{instanceConfig.WebDomain}:{instanceConfig.ListenPort}");
app.Run(); app.Run();