Add user preferences management via distributed cache

Introduced `UserPreferencesDto` to represent UI preferences,
including theme, dark mode, and grid layouts. Added the
`IUserPreferencesService` interface and implemented it in
`UserPreferencesService` to manage preferences stored in
the distributed cache (`dbo.TBDD_CACHE`).

Registered `UserPreferencesService` in dependency injection
and added a NuGet reference for `Microsoft.Extensions.Caching.Abstractions`.

Created `UserPreferencesController` with `GET` and `PUT`
endpoints to retrieve and save user preferences. Validated
theme names in the `PUT` endpoint.

Updated `Program.cs` to ensure proper service registration.
This commit is contained in:
2026-09-02 12:35:19 +02:00
parent 60ebebc0d8
commit 2e634361c5
7 changed files with 153 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Server.Extensions;
using EnvelopeGenerator.Application.Common.Dto;
using EnvelopeGenerator.Application.Common.Interfaces.Services;
namespace EnvelopeGenerator.Server.Controllers;
/// <summary>
/// Manages per-user UI preferences (theme, dark mode, grid layouts).
/// Preferences are stored in the distributed cache (dbo.TBDD_CACHE).
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Authorize(Policy = AuthPolicy.Sender)]
public class UserPreferencesController(IUserPreferencesService preferencesService) : ControllerBase
{
private static readonly HashSet<string> AllowedThemes =
["blazing-berry", "fluent", "purple"];
/// <summary>
/// Returns the current user's UI preferences.
/// Always returns 200 with defaults if no preferences have been saved yet.
/// </summary>
[HttpGet]
public async Task<ActionResult<UserPreferencesDto>> Get(CancellationToken ct)
{
var username = User.GetUsername();
var prefs = await preferencesService.GetAsync(username, ct);
return Ok(prefs);
}
/// <summary>
/// Saves (full replace) the current user's UI preferences.
/// </summary>
[HttpPut]
public async Task<ActionResult<UserPreferencesDto>> Put(
[FromBody] UserPreferencesDto dto,
CancellationToken ct)
{
if (!AllowedThemes.Contains(dto.ThemeName))
return BadRequest($"Invalid theme '{dto.ThemeName}'. Allowed: {string.Join(", ", AllowedThemes)}.");
var username = User.GetUsername();
await preferencesService.SaveAsync(username, dto, ct);
return Ok(dto);
}
}

View File

@@ -318,6 +318,9 @@ try
.AddEnvelopeGeneratorServices(config);
#pragma warning restore CS0618
// User Preferences (theme, dark mode, grid layouts — stored in TBDD_CACHE)
// Registration handled by Infrastructure DependencyInjection (AddEnvelopeGeneratorInfrastructureServices)
// Business Services (Server specific)
builder.Services.AddScoped<DocumentService>();
builder.Services.AddScoped<AuthService>();