void.cat/VoidCat/Program.cs

239 lines
6.9 KiB
C#
Raw Normal View History

2022-06-06 21:51:25 +00:00
using System.Data;
2022-03-08 13:47:42 +00:00
using System.Reflection;
2022-02-16 16:33:00 +00:00
using System.Text;
2022-06-06 21:51:25 +00:00
using FluentMigrator.Runner;
2022-02-16 16:33:00 +00:00
using Microsoft.AspNetCore.Authentication.JwtBearer;
2022-03-08 22:15:28 +00:00
using Microsoft.AspNetCore.HttpLogging;
2022-02-16 16:33:00 +00:00
using Microsoft.IdentityModel.Tokens;
2022-03-08 13:47:42 +00:00
using Microsoft.OpenApi.Models;
2022-02-21 09:39:59 +00:00
using Newtonsoft.Json;
2022-06-06 21:51:25 +00:00
using Npgsql;
2022-02-10 16:36:53 +00:00
using Prometheus;
2022-02-16 23:19:31 +00:00
using StackExchange.Redis;
2022-01-25 17:57:07 +00:00
using VoidCat.Model;
using VoidCat.Services;
2022-02-16 16:33:00 +00:00
using VoidCat.Services.Abstractions;
using VoidCat.Services.Background;
2022-03-11 15:59:08 +00:00
using VoidCat.Services.Captcha;
2022-02-22 14:20:31 +00:00
using VoidCat.Services.Files;
2022-02-21 09:39:59 +00:00
using VoidCat.Services.InMemory;
2022-02-17 15:52:49 +00:00
using VoidCat.Services.Migrations;
2022-02-21 12:54:57 +00:00
using VoidCat.Services.Paywall;
2022-02-21 09:39:59 +00:00
using VoidCat.Services.Redis;
2022-02-21 22:35:06 +00:00
using VoidCat.Services.Stats;
using VoidCat.Services.Users;
2022-03-07 13:38:53 +00:00
using VoidCat.Services.VirusScanner;
2022-01-25 16:17:48 +00:00
2022-02-27 13:54:25 +00:00
// setup JsonConvert default settings
JsonSerializerSettings ConfigJsonSettings(JsonSerializerSettings s)
{
s.NullValueHandling = NullValueHandling.Ignore;
s.ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor;
s.MissingMemberHandling = MissingMemberHandling.Ignore;
return s;
}
JsonConvert.DefaultSettings = () => ConfigJsonSettings(new());
2022-01-25 16:17:48 +00:00
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
2022-01-28 10:32:00 +00:00
var configuration = builder.Configuration;
var voidSettings = configuration.GetSection("Settings").Get<VoidSettings>();
services.AddSingleton(voidSettings);
2022-02-21 12:54:57 +00:00
services.AddSingleton(voidSettings.Strike ?? new());
2022-01-28 10:32:00 +00:00
2022-01-28 11:14:39 +00:00
var seqSettings = configuration.GetSection("Seq");
builder.Logging.AddSeq(seqSettings);
2022-01-28 10:32:00 +00:00
2022-02-16 23:19:31 +00:00
var useRedis = !string.IsNullOrEmpty(voidSettings.Redis);
if (useRedis)
{
var cx = await ConnectionMultiplexer.ConnectAsync(voidSettings.Redis);
services.AddSingleton(cx);
services.AddSingleton(cx.GetDatabase());
}
2022-03-08 22:15:28 +00:00
services.AddHttpLogging((o) =>
{
2022-03-11 15:59:08 +00:00
o.LoggingFields = HttpLoggingFields.RequestPropertiesAndHeaders | HttpLoggingFields.ResponsePropertiesAndHeaders;
2022-03-08 22:15:28 +00:00
o.RequestBodyLogLimit = 4096;
o.ResponseBodyLogLimit = 4096;
2022-06-06 21:51:25 +00:00
2022-03-11 15:59:08 +00:00
o.MediaTypeOptions.Clear();
2022-03-11 14:59:31 +00:00
o.MediaTypeOptions.AddText("application/json");
2022-06-06 21:51:25 +00:00
2022-03-11 15:59:08 +00:00
foreach (var h in voidSettings.RequestHeadersLog ?? Enumerable.Empty<string>())
{
o.RequestHeaders.Add(h);
}
2022-03-08 22:15:28 +00:00
});
2022-03-07 16:29:52 +00:00
services.AddHttpClient();
2022-03-08 13:47:42 +00:00
services.AddSwaggerGen(c =>
{
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please insert JWT with Bearer into field",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});
var path = Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml");
c.IncludeXmlComments(path);
});
2022-02-26 14:22:22 +00:00
services.AddCors(opt =>
{
2022-02-26 23:16:33 +00:00
opt.AddDefaultPolicy(p =>
2022-02-26 14:22:22 +00:00
{
p.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins(voidSettings.CorsOrigins.Select(a => a.OriginalString).ToArray());
});
});
services.AddRazorPages();
2022-01-25 16:17:48 +00:00
services.AddRouting();
services.AddControllers()
.AddNewtonsoftJson((opt) => { ConfigJsonSettings(opt.SerializerSettings); });
2022-02-21 22:35:06 +00:00
2022-02-16 16:33:00 +00:00
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = voidSettings.JwtSettings.Issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(voidSettings.JwtSettings.Key))
};
});
2022-01-28 00:18:27 +00:00
2022-03-08 13:47:42 +00:00
services.AddAuthorization((opt) =>
{
opt.AddPolicy(Policies.RequireAdmin, (auth) => { auth.RequireRole(Roles.Admin); });
});
2022-02-21 22:35:06 +00:00
2022-02-17 15:52:49 +00:00
// void.cat services
2022-02-21 12:54:57 +00:00
//
services.AddTransient<RazorPartialToStringRenderer>();
2022-06-08 16:17:53 +00:00
services.AddTransient<IMigration, PopulateMetadataId>();
2022-02-21 12:54:57 +00:00
// file storage
2022-03-01 16:48:42 +00:00
services.AddStorage(voidSettings);
2022-02-21 12:54:57 +00:00
// stats
services.AddTransient<IAggregateStatsCollector, AggregateStatsCollector>();
services.AddTransient<IStatsCollector, PrometheusStatsCollector>();
// paywall
services.AddVoidPaywall();
2022-02-21 22:35:06 +00:00
// users
2022-06-06 21:51:25 +00:00
services.AddUserServices(voidSettings);
2022-02-21 22:35:06 +00:00
// background services
services.AddHostedService<DeleteUnverifiedAccounts>();
2022-03-07 13:38:53 +00:00
// virus scanner
services.AddVirusScanner(voidSettings);
2022-03-11 15:59:08 +00:00
// captcha
services.AddCaptcha(voidSettings);
2022-06-06 21:51:25 +00:00
// postgres
if (!string.IsNullOrEmpty(voidSettings.Postgres))
{
services.AddScoped<OpenDatabase>();
services.AddScoped((_) => new NpgsqlConnection(voidSettings.Postgres));
services.AddScoped<IDbConnection>((svc) => svc.GetRequiredService<NpgsqlConnection>());
// fluent migrations
services.AddTransient<IMigration, FluentMigrationRunner>();
services.AddFluentMigratorCore()
.ConfigureRunner(r =>
r.AddPostgres11_0()
.WithGlobalConnectionString(voidSettings.Postgres)
2022-06-08 16:17:53 +00:00
.ScanIn(typeof(Program).Assembly).For.Migrations());
2022-06-06 21:51:25 +00:00
}
2022-02-16 23:19:31 +00:00
if (useRedis)
{
2022-02-21 22:35:06 +00:00
services.AddTransient<ICache, RedisCache>();
2022-02-21 12:54:57 +00:00
services.AddTransient<RedisStatsController>();
services.AddTransient<IStatsCollector>(svc => svc.GetRequiredService<RedisStatsController>());
services.AddTransient<IStatsReporter>(svc => svc.GetRequiredService<RedisStatsController>());
2022-06-06 21:51:25 +00:00
2022-05-19 22:27:49 +00:00
// redis specific migrations
services.AddTransient<IMigration, UserLookupKeyHashMigration>();
2022-02-16 23:19:31 +00:00
}
else
{
services.AddMemoryCache();
2022-02-21 22:35:06 +00:00
services.AddTransient<ICache, InMemoryCache>();
2022-02-21 12:54:57 +00:00
services.AddTransient<InMemoryStatsController>();
services.AddTransient<IStatsReporter>(svc => svc.GetRequiredService<InMemoryStatsController>());
services.AddTransient<IStatsCollector>(svc => svc.GetRequiredService<InMemoryStatsController>());
2022-02-16 23:19:31 +00:00
}
2022-01-25 16:17:48 +00:00
var app = builder.Build();
2022-02-17 15:52:49 +00:00
// run migrations
2022-06-06 21:51:25 +00:00
using (var migrationScope = app.Services.CreateScope())
2022-02-17 15:52:49 +00:00
{
2022-06-06 21:51:25 +00:00
var migrations = migrationScope.ServiceProvider.GetServices<IMigration>();
2022-06-08 16:17:53 +00:00
var logger = migrationScope.ServiceProvider.GetRequiredService<ILogger<IMigration>>();
2022-06-06 21:51:25 +00:00
foreach (var migration in migrations)
{
2022-06-08 16:17:53 +00:00
logger.LogInformation("Running migration: {Migration}", migration.GetType().Name);
var res = await migration.Migrate(args);
logger.LogInformation("== Result: {Result}", res.ToString());
if (res == IMigration.MigrationResult.ExitCompleted)
2022-06-06 21:51:25 +00:00
{
return;
}
}
2022-02-17 15:52:49 +00:00
}
2022-02-26 12:11:47 +00:00
#if HostSPA
2022-01-25 16:17:48 +00:00
app.UseStaticFiles();
2022-02-26 12:11:47 +00:00
#endif
2022-02-22 14:20:31 +00:00
2022-03-11 15:59:08 +00:00
app.UseHttpLogging();
2022-01-25 16:17:48 +00:00
app.UseRouting();
2022-02-26 23:16:33 +00:00
app.UseCors();
2022-03-08 13:47:42 +00:00
app.UseSwagger();
app.UseSwaggerUI();
2022-02-22 14:20:31 +00:00
app.UseAuthentication();
2022-02-16 16:33:00 +00:00
app.UseAuthorization();
2022-02-22 14:20:31 +00:00
2022-06-06 21:51:25 +00:00
if (!string.IsNullOrEmpty(voidSettings.Postgres))
{
app.UseMiddleware<OpenDatabase>();
}
2022-01-25 16:17:48 +00:00
app.UseEndpoints(ep =>
{
ep.MapControllers();
2022-02-10 16:36:53 +00:00
ep.MapMetrics();
ep.MapRazorPages();
2022-02-26 12:11:47 +00:00
#if HostSPA
2022-01-25 16:17:48 +00:00
ep.MapFallbackToFile("index.html");
2022-02-26 12:11:47 +00:00
#endif
2022-01-25 16:17:48 +00:00
});
2022-03-08 13:47:42 +00:00
app.Run();