39 lines
1.6 KiB
C#
39 lines
1.6 KiB
C#
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using SIFinance.Shared.Entities;
|
|
|
|
namespace SIFinance.Shared;
|
|
|
|
public class CurrentUserService(IHttpContextAccessor httpContextAccessor)
|
|
{
|
|
public Task<int> GetOrCreateCurrentUserIdAsync(CancellationToken ct = default)
|
|
{
|
|
var principal = httpContextAccessor.HttpContext?.User
|
|
?? throw new InvalidOperationException("Aucun contexte HTTP disponible pour résoudre l'utilisateur courant.");
|
|
|
|
var idClaim = principal.FindFirst("id")?.Value
|
|
?? throw new UnauthorizedAccessException("Le jeton ne contient pas de claim 'id' — utilisateur non identifiable.");
|
|
|
|
return Task.FromResult(int.Parse(idClaim));
|
|
}
|
|
|
|
// Vérifie si l'utilisateur courant possède le rôle donné (ex. "FINANCE").
|
|
// Passe par une jointure utilisateurs <-> utilisateur_roles via azure_oid, car
|
|
// le JWT ne porte que l'Id interne, pas l'azure_oid.
|
|
public async Task<bool> HasRoleAsync(string role, SIFinanceDbContext db, CancellationToken ct = default)
|
|
{
|
|
var userId = await GetOrCreateCurrentUserIdAsync(ct);
|
|
|
|
// Les habilitations fonctionnelles viennent exclusivement de
|
|
// core.utilisateur_roles. Un profil Entra ou le statut Responsable ne donne
|
|
// jamais à lui seul l'accès aux écrans ou actions Finance.
|
|
return await db.UtilisateurRoles
|
|
.AsNoTracking()
|
|
.Join(db.Utilisateurs.AsNoTracking(),
|
|
ur => ur.AzureOid,
|
|
u => u.AzureOid,
|
|
(ur, u) => new { u.Id, ur.Role })
|
|
.AnyAsync(x => x.Id == userId && x.Role == role, ct);
|
|
}
|
|
}
|