Premier commit

This commit is contained in:
2026-09-11 14:55:41 +02:00
commit 8ed04aae89
134 changed files with 36627 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
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);
}
}