SF-74: Server — UserPreferencesController, claim extensions, DI registration, App.razor
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
<script src="_content/DevExpress.Blazor.Resources/js/preload-script.js"></script>
|
||||
<script src="js/typed.umd.js"></script>
|
||||
<script src="js/receiver-signature.js?v=9"></script>
|
||||
<script src="js/signflow-theme.js"></script>
|
||||
<script src="_framework/blazor.web.js"></script>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -10,24 +10,37 @@ 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).
|
||||
/// Accessible by both Sender and Receiver roles.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize(Policy = AuthPolicy.Sender)]
|
||||
[Authorize(Policy = AuthPolicy.SenderOrReceiver)]
|
||||
public class UserPreferencesController(IUserPreferencesService preferencesService) : ControllerBase
|
||||
{
|
||||
private static readonly HashSet<string> AllowedThemes =
|
||||
["blazing-berry", "fluent", "purple"];
|
||||
["blazing-berry", "blazing-dark", "purple"];
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current user's UI preferences.
|
||||
/// Always returns 200 with defaults if no preferences have been saved yet.
|
||||
/// DisplayName is populated from JWT claims for senders only.
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<UserPreferencesDto>> Get(CancellationToken ct)
|
||||
{
|
||||
var username = User.GetUsername();
|
||||
var prefs = await preferencesService.GetAsync(username, ct);
|
||||
bool isReceiver = User.IsReceiver();
|
||||
|
||||
var userId = isReceiver ? User.ReceiverMail() : User.GetUsername();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var prefs = await preferencesService.GetOrCreateAsync(userId, ct);
|
||||
|
||||
// Populate DisplayName for sender only (receiver has no given/surname claims)
|
||||
if (!isReceiver)
|
||||
prefs.DisplayName = $"{User.GetPrename()} {User.GetName()}".Trim();
|
||||
|
||||
return Ok(prefs);
|
||||
}
|
||||
|
||||
@@ -42,8 +55,12 @@ public class UserPreferencesController(IUserPreferencesService preferencesServic
|
||||
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);
|
||||
var userId = User.IsReceiver() ? User.ReceiverMail() : User.GetUsername();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
await preferencesService.SaveAsync(userId, dto, ct);
|
||||
return Ok(dto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using DigitalData.Auth.Claims;
|
||||
using DigitalData.UserManager.Domain.Entities;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using Microsoft.IdentityModel.JsonWebTokens;
|
||||
using System.Security.Claims;
|
||||
|
||||
@@ -93,4 +95,14 @@ public static class ReceiverClaimExtensions
|
||||
else
|
||||
throw new InvalidOperationException($"Claim '{EnvelopeClaimNames.ReceiverId}' is not a valid integer.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsReceiver(this ClaimsPrincipal user)
|
||||
{
|
||||
return Role.Receiver.Authorized.Any(user.IsInRole);
|
||||
}
|
||||
}
|
||||
@@ -271,7 +271,12 @@ try
|
||||
.AddAuthenticationSchemes(AuthScheme.Receiver)
|
||||
.RequireAuthenticatedUser()
|
||||
.RequireRole(Role.Receiver.Full, "receiver"))
|
||||
.AddPolicy(AuthPolicy.ReceiverTFA, policy => policy.RequireRole(Role.Receiver.TFA));
|
||||
.AddPolicy(AuthPolicy.ReceiverTFA, policy => policy.RequireRole(Role.Receiver.TFA))
|
||||
// Combined policy: accepts both Sender and Receiver tokens.
|
||||
// Used by endpoints accessible to both roles (e.g. UserPreferences).
|
||||
.AddPolicy(AuthPolicy.SenderOrReceiver, policy => policy
|
||||
.AddAuthenticationSchemes(AuthScheme.Sender, AuthScheme.Receiver)
|
||||
.RequireAuthenticatedUser());
|
||||
|
||||
// User Manager
|
||||
#pragma warning disable CS0618
|
||||
|
||||
Reference in New Issue
Block a user