Skip to content

Commit

Permalink
Use modern startup format (#137)
Browse files Browse the repository at this point in the history
* Remove global static logging singleton

* Use modern startup files

* Use common helper for configuring webapplicationbuilder

* Only use Serilog base logger during startup

* Use proper serilog registration call

* Remove redundant configuration source adds

* Create common application builder

* Clean up launch settings

* Specifically only add back whats needed for https in debug mode
  • Loading branch information
hhvrc authored Nov 27, 2024
1 parent 4e5363d commit 34cf939
Show file tree
Hide file tree
Showing 19 changed files with 397 additions and 609 deletions.
1 change: 0 additions & 1 deletion API/API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MiniValidation" Version="0.9.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.1" />
<PackageReference Include="OneOf" Version="3.0.271" />
<PackageReference Include="Redis.OM" Version="0.7.6" />
Expand Down
152 changes: 113 additions & 39 deletions API/Program.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,123 @@
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.EntityFrameworkCore;
using OpenShock.API;
using OpenShock.API.Realtime;
using OpenShock.API.Services;
using OpenShock.API.Services.Account;
using OpenShock.API.Services.Email.Mailjet;
using OpenShock.API.Services.Email.Smtp;
using OpenShock.Common;
using OpenShock.Common.Extensions;
using OpenShock.Common.Hubs;
using OpenShock.Common.JsonSerialization;
using OpenShock.Common.OpenShockDb;
using OpenShock.Common.Services.Device;
using OpenShock.Common.Services.LCGNodeProvisioner;
using OpenShock.Common.Services.Ota;
using OpenShock.Common.Services.Turnstile;
using OpenShock.Common.Utils;
using Scalar.AspNetCore;
using Serilog;

HostBuilder builder = new();
builder.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureHostConfiguration(config =>
{
config.AddEnvironmentVariables(prefix: "DOTNET_");
if (args is { Length: > 0 }) config.AddCommandLine(args);
})
.ConfigureAppConfiguration((context, config) =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
.AddJsonFile("appsettings.Custom.json", optional: true, reloadOnChange: false)
.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true,
reloadOnChange: false);
config.AddUserSecrets(typeof(Program).Assembly);
config.AddEnvironmentVariables();
if (args is { Length: > 0 }) config.AddCommandLine(args);
})
.UseDefaultServiceProvider((context, options) =>
var builder = OpenShockApplication.CreateDefaultBuilder<Program>(args, options =>
{
options.ListenAnyIP(80);
#if DEBUG
options.ListenAnyIP(443, options => options.UseHttps());
#endif
});

var config = builder.GetAndRegisterOpenShockConfig<ApiConfig>();
var commonServices = builder.Services.AddOpenShockServices(config);

builder.Services.AddSignalR()
.AddOpenShockStackExchangeRedis(options => { options.Configuration = commonServices.RedisConfig; })
.AddJsonProtocol(options =>
{
var isDevelopment = context.HostingEnvironment.IsDevelopment();
options.ValidateScopes = isDevelopment;
options.ValidateOnBuild = isDevelopment;
})
.UseSerilog((context, _, config) => { config.ReadFrom.Configuration(context.Configuration); })
.ConfigureWebHostDefaults(webBuilder =>
options.PayloadSerializerOptions.PropertyNameCaseInsensitive = true;
options.PayloadSerializerOptions.Converters.Add(new SemVersionJsonConverter());
});

builder.Services.AddScoped<IDeviceService, DeviceService>();
builder.Services.AddScoped<IOtaService, OtaService>();
builder.Services.AddScoped<IDeviceUpdateService, DeviceUpdateService>();
builder.Services.AddScoped<IAccountService, AccountService>();

builder.Services.AddSwaggerExt("OpenShock.API");

builder.Services.AddSingleton<ILCGNodeProvisioner, LCGNodeProvisioner>();

builder.Services.AddSingleton(x =>
{
return new CloudflareTurnstileOptions
{
webBuilder.UseKestrel();
webBuilder.ConfigureKestrel(serverOptions =>
SecretKey = config.Turnstile.SecretKey ?? string.Empty,
SiteKey = config.Turnstile.SiteKey ?? string.Empty
};
});
builder.Services.AddHttpClient<ICloudflareTurnstileService, CloudflareTurnstileService>();

// ----------------- MAIL SETUP -----------------
var emailConfig = config.Mail;
switch (emailConfig.Type)
{
case ApiConfig.MailConfig.MailType.Mailjet:
if (emailConfig.Mailjet == null)
throw new Exception("Mailjet config is null but mailjet is selected as mail type");
builder.Services.AddMailjetEmailService(emailConfig.Mailjet, emailConfig.Sender);
break;
case ApiConfig.MailConfig.MailType.Smtp:
if (emailConfig.Smtp == null)
throw new Exception("SMTP config is null but SMTP is selected as mail type");
builder.Services.AddSmtpEmailService(emailConfig.Smtp, emailConfig.Sender, new SmtpServiceTemplates
{
serverOptions.ListenAnyIP(80);
#if DEBUG
serverOptions.ListenAnyIP(443, options => { options.UseHttps(); });
#endif
serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMilliseconds(3000);
PasswordReset = SmtpTemplate.ParseFromFileThrow("SmtpTemplates/PasswordReset.liquid").Result,
EmailVerification = SmtpTemplate.ParseFromFileThrow("SmtpTemplates/EmailVerification.liquid").Result
});
webBuilder.UseStartup<Startup>();
});
try
break;
default:
throw new Exception("Unknown mail type");
}

builder.Services.ConfigureOptions<ConfigureSwaggerOptions>();
//services.AddHealthChecks().AddCheck<DatabaseHealthCheck>("database");

builder.Services.AddHostedService<RedisSubscriberService>();

var app = builder.Build();

app.UseCommonOpenShockMiddleware();

if (!config.Db.SkipMigration)
{
await builder.Build().RunAsync();
Log.Information("Running database migrations...");
using var scope = app.Services.CreateScope();
var openShockContext = scope.ServiceProvider.GetRequiredService<OpenShockContext>();
var pendingMigrations = openShockContext.Database.GetPendingMigrations().ToList();

if (pendingMigrations.Count > 0)
{
Log.Information("Found pending migrations, applying [{@Migrations}]", pendingMigrations);
openShockContext.Database.Migrate();
Log.Information("Applied database migrations... proceeding with startup");
}
else
{
Log.Information("No pending migrations found, proceeding with startup");
}
}
catch (Exception e)
else
{
Console.WriteLine(e);
}
Log.Warning("Skipping possible database migrations...");
}

app.UseSwaggerExt();

app.MapControllers();

app.MapHub<UserHub>("/1/hubs/user", options => options.Transports = HttpTransportType.WebSockets);
app.MapHub<ShareLinkHub>("/1/hubs/share/link/{id:guid}", options => options.Transports = HttpTransportType.WebSockets);

app.MapScalarApiReference(options => options.OpenApiRoutePattern = "/swagger/{documentName}/swagger.json");

app.Run();
12 changes: 2 additions & 10 deletions API/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
{
"profiles": {
"ShockLink": {
"API": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DB": "Host=docker-node;Port=1337;Database=root;Username=root;Password=root;Search Path=ShockLink",
"REDIS_HOST":"docker-node",
"REDIS_PASSWORD": "",
"CF_ACC_ID": "",
"CF_IMG_KEY": "",
"CF_IMG_URL": "",
"MAILJET_KEY": "",
"MAILJET_SECRET": ""
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
Expand Down
Loading

0 comments on commit 34cf939

Please sign in to comment.