diff --git a/Foxchat.Chat/Database/ChatContext.cs b/Foxchat.Chat/Database/ChatContext.cs new file mode 100644 index 0000000..22ee6f2 --- /dev/null +++ b/Foxchat.Chat/Database/ChatContext.cs @@ -0,0 +1,52 @@ +using Foxchat.Core; +using Foxchat.Core.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace Foxchat.Chat.Database; + +public class ChatContext : IDatabaseContext +{ + private readonly string _connString; + + public override DbSet Instance { get; set; } + + public ChatContext(InstanceConfig config) + { + _connString = new Npgsql.NpgsqlConnectionStringBuilder(config.Database.Url) + { + Timeout = config.Database.Timeout ?? 5, + MaxPoolSize = config.Database.MaxPoolSize ?? 50, + }.ConnectionString; + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder + .UseNpgsql(_connString) + .UseSnakeCaseNamingConvention(); + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + // ULIDs are stored as UUIDs in the database + configurationBuilder.Properties().HaveConversion(); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + } +} + +public class DesignTimeIdentityContextFactory : IDesignTimeDbContextFactory +{ + public ChatContext CreateDbContext(string[] args) + { + // Read the configuration file + var config = new ConfigurationBuilder() + .AddConfiguration("identity.ini") + .Build() + // Get the configuration as our config class + .Get() ?? new(); + + return new ChatContext(config); + } +} diff --git a/Foxchat.Chat/Foxchat.Chat.csproj b/Foxchat.Chat/Foxchat.Chat.csproj new file mode 100644 index 0000000..9f5ee81 --- /dev/null +++ b/Foxchat.Chat/Foxchat.Chat.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + diff --git a/Foxchat.Chat/GlobalUsing.cs b/Foxchat.Chat/GlobalUsing.cs new file mode 100644 index 0000000..e9ade6a --- /dev/null +++ b/Foxchat.Chat/GlobalUsing.cs @@ -0,0 +1,3 @@ +global using ILogger = Serilog.ILogger; +global using Log = Serilog.Log; +global using NUlid; diff --git a/Foxchat.Chat/InstanceConfig.cs b/Foxchat.Chat/InstanceConfig.cs new file mode 100644 index 0000000..398eac6 --- /dev/null +++ b/Foxchat.Chat/InstanceConfig.cs @@ -0,0 +1,5 @@ +using Foxchat.Core; + +namespace Foxchat.Chat; + +public class InstanceConfig : CoreConfig; diff --git a/Foxchat.Chat/Program.cs b/Foxchat.Chat/Program.cs new file mode 100644 index 0000000..a7f939e --- /dev/null +++ b/Foxchat.Chat/Program.cs @@ -0,0 +1,53 @@ +using Newtonsoft.Json.Serialization; +using Serilog; +using Foxchat.Core; +using Foxchat.Chat; +using Foxchat.Chat.Database; + +var builder = WebApplication.CreateBuilder(args); + +var config = builder.AddConfiguration("chat.ini"); + +builder.Services.AddSerilog(config.LogEventLevel); + +await BuildInfo.ReadBuildInfo(); +Log.Information("Starting Foxchat.Chat {Version} ({Hash})", BuildInfo.Version, BuildInfo.Hash); + +builder.Services + .AddControllers() + .AddNewtonsoftJson(options => + options.SerializerSettings.ContractResolver = new DefaultContractResolver + { + NamingStrategy = new SnakeCaseNamingStrategy() + }); + +builder.Services + .AddCoreServices() + .AddEndpointsApiExplorer() + .AddSwaggerGen(); + +var app = builder.Build(); + +app.UseSerilogRequestLogging(); +app.UseRouting(); +app.UseSwagger(); +app.UseSwaggerUI(); +app.UseCors(); +app.UseAuthentication(); +app.UseAuthorization(); +app.MapControllers(); + +using (var scope = app.Services.CreateScope()) +using (var context = scope.ServiceProvider.GetRequiredService()) +{ + Log.Information("Initializing instance keypair..."); + if (await context.InitializeInstanceAsync()) + { + Log.Information("Initialized instance keypair"); + } +} + +app.Urls.Clear(); +app.Urls.Add(config.Address); + +app.Run(); diff --git a/Foxchat.Chat/chat.ini b/Foxchat.Chat/chat.ini new file mode 100644 index 0000000..21a32a0 --- /dev/null +++ b/Foxchat.Chat/chat.ini @@ -0,0 +1,15 @@ +Host = localhost +Port = 7610 +Domain = chat.fox.localhost + +; The level to log things at. Valid settings: Verbose, Debug, Information, Warning, Error, Fatal +LogEventLevel = Debug + +[Database] +; The database URL in ADO.NET format. +Url = "Host=localhost;Database=foxchat_cs_chat;Username=foxchat;Password=password" + +; The timeout for opening new connections. Defaults to 5. +Timeout = 5 +; The maximum number of open connections. Defaults to 50. +MaxPoolSize = 500 diff --git a/Foxchat.Core/GlobalUsing.cs b/Foxchat.Core/GlobalUsing.cs new file mode 100644 index 0000000..e9ade6a --- /dev/null +++ b/Foxchat.Core/GlobalUsing.cs @@ -0,0 +1,3 @@ +global using ILogger = Serilog.ILogger; +global using Log = Serilog.Log; +global using NUlid; diff --git a/Foxchat.Identity/InstanceConfig.cs b/Foxchat.Identity/InstanceConfig.cs index 30483c6..78001c7 100644 --- a/Foxchat.Identity/InstanceConfig.cs +++ b/Foxchat.Identity/InstanceConfig.cs @@ -2,6 +2,4 @@ using Foxchat.Core; namespace Foxchat.Identity; -public class InstanceConfig : CoreConfig -{ -} +public class InstanceConfig : CoreConfig; \ No newline at end of file diff --git a/Foxchat.sln b/Foxchat.sln index 7d8b9aa..4d7c109 100644 --- a/Foxchat.sln +++ b/Foxchat.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foxchat.Identity", "Foxchat EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foxchat.Core", "Foxchat.Core\Foxchat.Core.csproj", "{06352B8B-628C-4476-9F78-83F326B05B16}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Foxchat.Chat", "Foxchat.Chat\Foxchat.Chat.csproj", "{9DC99C95-55DD-4091-9F2B-92B6BCF9D980}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +26,9 @@ Global {06352B8B-628C-4476-9F78-83F326B05B16}.Debug|Any CPU.Build.0 = Debug|Any CPU {06352B8B-628C-4476-9F78-83F326B05B16}.Release|Any CPU.ActiveCfg = Release|Any CPU {06352B8B-628C-4476-9F78-83F326B05B16}.Release|Any CPU.Build.0 = Release|Any CPU + {9DC99C95-55DD-4091-9F2B-92B6BCF9D980}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DC99C95-55DD-4091-9F2B-92B6BCF9D980}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DC99C95-55DD-4091-9F2B-92B6BCF9D980}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DC99C95-55DD-4091-9F2B-92B6BCF9D980}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal