ShiftScheduler/Server/Program.cs
Claudio Schaad 8c765e4d49 refactor: temporarily rename old IGoogleCalendarService to IOldGoogleCalendarService to avoid naming conflict with new marker interface
This temporary change is necessary because the new ICalendarService interfaces
(IGoogleCalendarService, INextcloudCalendarService) now exist as marker interfaces.
The old interface will be fully removed in Task 4 when GoogleCalendarService is
refactored to implement the new ICalendarService contract.
2026-04-10 22:41:01 +02:00

121 lines
4 KiB
C#

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using ShiftScheduler.Services;
using ShiftScheduler.Shared;
var builder = WebApplication.CreateBuilder(args);
// Load configurations from appsettings.json
var shifts = builder.Configuration.GetSection("Shifts").Get<List<Shift>>() ?? new();
var transportConfig = builder.Configuration.GetSection("Transport").Get<TransportConfiguration>() ?? new();
var authorizedEmails = builder.Configuration.GetSection("Authentication:AuthorizedEmails").Get<List<string>>() ?? new();
// Create application configuration
var appConfiguration = new ApplicationConfiguration
{
Transport = transportConfig,
Shifts = shifts
};
// Register services
builder.Services.AddSingleton(authorizedEmails);
builder.Services.AddSingleton<IConfigurationService>(new ConfigurationService(appConfiguration));
builder.Services.AddMemoryCache();
builder.Services.AddHttpClient<TransportApiService>();
builder.Services.AddSingleton<IcsExportService>();
builder.Services.AddSingleton<PdfExportService>();
builder.Services.AddSingleton<ITransportApiService, TransportApiService>();
builder.Services.AddSingleton<ITransportService, TransportService>();
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<IOldGoogleCalendarService, GoogleCalendarService>();
// Configure authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/api/auth/login";
options.LogoutPath = "/api/auth/logout";
options.AccessDeniedPath = "/";
options.ExpireTimeSpan = TimeSpan.FromDays(7);
options.SlidingExpiration = true;
options.Cookie.SameSite = SameSiteMode.Lax;
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
})
.AddGoogle(googleOptions =>
{
googleOptions.ClientId = builder.Configuration["Authentication:Google:ClientId"] ?? "";
googleOptions.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"] ?? "";
googleOptions.CallbackPath = "/signin-google";
googleOptions.SaveTokens = true;
googleOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
googleOptions.Events.OnTicketReceived = async context =>
{
var emailClaim = context.Principal?.FindFirst(ClaimTypes.Email) ??
context.Principal?.FindFirst("email");
if (emailClaim?.Value == null || !authorizedEmails.Contains(emailClaim.Value))
{
context.Fail("Email not authorized");
context.Response.Redirect("/?error=unauthorized");
return;
}
await Task.CompletedTask;
};
});
// Configure authorization policy for allowed emails
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("AllowedEmails", policy =>
policy.RequireAssertion(context =>
{
var emailClaim = context.User.FindFirst(ClaimTypes.Email) ??
context.User.FindFirst("email");
if (emailClaim?.Value != null)
{
return authorizedEmails.Contains(emailClaim.Value);
}
return false;
}));
});
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile("index.html");
app.Run();