yale-user-access/packages/backend/Program.cs

154 lines
5.0 KiB
C#
Raw Permalink Normal View History

2025-01-10 08:37:18 +11:00
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Serilog.Events;
using YaleAccess.Data;
using YaleAccess.Models.Options;
using YaleAccess.Services;
using YaleAccess.Services.Interfaces;
var builder = WebApplication.CreateBuilder(args);
// Create the bootstraper logger
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
try
{
// Add services to the container.
builder.Services.AddControllers();
// Add the database context
builder.Services.AddDbContext<YaleContext>(options =>
{
options.UseSqlite(builder.Configuration.GetConnectionString(nameof(YaleContext)));
});
// Configure the options
builder.Services.Configure<AuthenticationOptions>(builder.Configuration.GetSection(AuthenticationOptions.Authentication));
builder.Services.Configure<CodesOptions>(builder.Configuration.GetSection(CodesOptions.Codes));
builder.Services.Configure<DevicesOptions>(builder.Configuration.GetSection(DevicesOptions.Devices));
builder.Services.Configure<ZWaveOptions>(builder.Configuration.GetSection(ZWaveOptions.ZWave));
builder.Services.Configure<TwiloOptions>(builder.Configuration.GetSection(TwiloOptions.Twilio));
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Get a copy of the configuration
IConfiguration configuration = builder.Configuration;
string logLocation = configuration["LogLocation"] ?? "Log.txt";
// Setup the application logger
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Error)
.WriteTo.File(logLocation, rollingInterval: RollingInterval.Day)
.CreateLogger();
// Configure the DI services
builder.Services.AddScoped<SMSService>();
// If the environment is development and the mock option is set to true, use the mock service
if (builder.Environment.IsDevelopment() && configuration.GetValue<bool>("UseMockDevelopmentMode"))
{
builder.Services.AddSingleton<MockYaleData>();
builder.Services.AddScoped<IYaleAccessor, MockYaleAccessor>();
}
else
{
builder.Services.AddScoped<IYaleAccessor, YaleAccessor>();
}
// Setup CORS
string[] corsAllowedOrigins = (configuration["CorsAllowedOrigins"] ?? "http://localhost:3000").Split(",") ;
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins(corsAllowedOrigins)
.AllowCredentials()
.AllowAnyMethod()
.WithHeaders("Content-Type", "Authorization");
});
});
// Setup cookie authentication scheme
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
// Set HTTP only to true to prevent XSS attacks
options.Cookie.HttpOnly = true;
// Set secure policy to always to prevent sending cookies over HTTP for production use, for development set to None
if (builder.Environment.IsDevelopment())
options.Cookie.SecurePolicy = CookieSecurePolicy.None;
else
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
// Ensure that the API will return a 401 Unauthorized instead of redirecting to the login page
options.AccessDeniedPath = string.Empty;
options.LoginPath = string.Empty;
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
// Setup logging flow
builder.Host.UseSerilog();
var app = builder.Build();
// Create the database if it doesn't exist
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
var context = services.GetRequiredService<YaleContext>();
context.Database.Migrate();
}
// Configure the forwarded headers middleware
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
catch (Exception ex)
{
// Ignore host aborted exceptions caused by build checks
if (ex is not HostAbortedException)
{
Log.Fatal(ex, "Host terminated unexpectedly");
throw;
}
}
finally
{
Log.CloseAndFlush();
}