Initial Blazor birth registry app, theming, and services
Build and Push Docker Image / build-and-push (push) Failing after 10s

Implemented a Blazor Web App (.NET 8) for a public-by-link birth registry platform, following project guidelines. Added domain entities, EF Core context, and Blazor components for authentication, registry management, and public views. Introduced core services for registries, theming, user context, platform owner bootstrapping, and SMTP email. Included static assets (Bootstrap, favicon), launch settings, Dockerfile, CI workflow, and deployment configs. Added bootstrap.min.css.map for improved CSS debugging.
This commit is contained in:
Arne Moerman
2026-05-14 11:48:15 +02:00
commit 0878405e9d
107 changed files with 6503 additions and 0 deletions
@@ -0,0 +1,47 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using BirthList.Web.Data;
namespace BirthList.Web.Components.Account;
// This is a server-side AuthenticationStateProvider that revalidates the security stamp for the connected user
// every 30 minutes an interactive circuit is connected.
internal sealed class IdentityRevalidatingAuthenticationStateProvider(
ILoggerFactory loggerFactory,
IServiceScopeFactory scopeFactory,
IOptions<IdentityOptions> options)
: RevalidatingServerAuthenticationStateProvider(loggerFactory)
{
protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30);
protected override async Task<bool> ValidateAuthenticationStateAsync(
AuthenticationState authenticationState, CancellationToken cancellationToken)
{
// Get the user manager from a new scope to ensure it fetches fresh data
await using var scope = scopeFactory.CreateAsyncScope();
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
return await ValidateSecurityStampAsync(userManager, authenticationState.User);
}
private async Task<bool> ValidateSecurityStampAsync(UserManager<ApplicationUser> userManager, ClaimsPrincipal principal)
{
var user = await userManager.GetUserAsync(principal);
if (user is null)
{
return false;
}
else if (!userManager.SupportsUserSecurityStamp)
{
return true;
}
else
{
var principalStamp = principal.FindFirstValue(options.Value.ClaimsIdentity.SecurityStampClaimType);
var userStamp = await userManager.GetSecurityStampAsync(user);
return principalStamp == userStamp;
}
}
}