using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
namespace EnvelopeGenerator.API.Extensions
{
///
/// Provides extension methods for extracting user information from a .
///
public static class SenderClaimExtensions
{
private static string GetRequiredClaimOfSender(this ClaimsPrincipal user, string claimType)
{
var value = user.FindFirstValue(claimType);
if (value is not null)
{
return value;
}
var identity = user.Identity;
var principalName = identity?.Name ?? "(anonymous)";
var authType = identity?.AuthenticationType ?? "(none)";
var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}"));
var message = $"Required claim '{claimType}' is missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}].";
throw new InvalidOperationException(message);
}
///
/// Retrieves the user's ID from the claims. Throws an exception if the ID is missing or invalid.
///
/// The representing the user.
/// The user's ID as an integer.
/// Thrown if the user ID claim is missing or invalid.
public static int GetId(this ClaimsPrincipal user)
{
var idValue = user.FindFirstValue(ClaimTypes.NameIdentifier) ?? user.FindFirstValue("sub");
idValue ??= user.GetRequiredClaimOfSender(ClaimTypes.NameIdentifier);
if (!int.TryParse(idValue, out var result))
{
throw new InvalidOperationException("User ID claim is missing or invalid. This may indicate a misconfigured or forged JWT token.");
}
return result;
}
///
/// Retrieves the username from the claims.
///
/// The representing the user.
/// The username as a string.
public static string GetUsername(this ClaimsPrincipal user)
=> user.GetRequiredClaimOfSender(ClaimTypes.Name);
///
/// Retrieves the user's surname (last name) from the claims.
///
/// The representing the user.
/// The surname as a string.
public static string GetName(this ClaimsPrincipal user)
=> user.GetRequiredClaimOfSender(ClaimTypes.Surname);
///
/// Retrieves the user's given name (first name) from the claims.
///
/// The representing the user.
/// The given name as a string.
public static string GetPrename(this ClaimsPrincipal user)
=> user.GetRequiredClaimOfSender(ClaimTypes.GivenName);
///
/// Retrieves the user's email address from the claims.
///
/// The representing the user.
/// The email address as a string.
public static string GetEmail(this ClaimsPrincipal user)
=> user.GetRequiredClaimOfSender(ClaimTypes.Email);
}
}