using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver; using EnvelopeGenerator.Application.Common.Dto.Receiver; using EnvelopeGenerator.Web.Models; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc; using System.Globalization; using System.Security.Claims; namespace EnvelopeGenerator.Web.Extensions; public static class WebExtensions { #region Auth public static string? GetClaimValue(this ClaimsPrincipal user, string claimType) => user.FindFirstValue(claimType); public static string? GetAuthEnvelopeUuid(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.NameIdentifier); public static string? GetAuthReceiverSignature(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.Hash); public static string? GetAuthReceiverName(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.Name); public static string? GetAuthReceiverMail(this ClaimsPrincipal user) => user.FindFirstValue(ClaimTypes.Email); public static string? GetAuthEnvelopeTitle(this ClaimsPrincipal user) => user.FindFirstValue(EnvelopeClaimTypes.Title); public static int? GetAuthEnvelopeId(this ClaimsPrincipal user) { var env_id_str = user.FindFirstValue(EnvelopeClaimTypes.Id); return int.TryParse(env_id_str, out int env_id) ? env_id : null; } public static async Task SignInEnvelopeAsync(this HttpContext context, EnvelopeReceiverDto er, string receiverRole) { var claims = new List { new(ClaimTypes.NameIdentifier, er.Envelope!.Uuid), new(ClaimTypes.Hash, er.Receiver!.Signature), new(ClaimTypes.Name, er.Name ?? string.Empty), new(ClaimTypes.Email, er.Receiver.EmailAddress), new(EnvelopeClaimTypes.Title, er.Envelope.Title), new(EnvelopeClaimTypes.Id, er.Envelope.Id.ToString()), new(ClaimTypes.Role, receiverRole) }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties { AllowRefresh = false, IsPersistent = false }; await context.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); } #endregion #region Cookie public static string GetCulture(this IRequestCookieCollection cookies) { var cookieValue = cookies[CookieRequestCultureProvider.DefaultCookieName]; if (!string.IsNullOrEmpty(cookieValue)) { var culture = CookieRequestCultureProvider.ParseCookieValue(cookieValue)?.Cultures.FirstOrDefault().Value; if (!string.IsNullOrEmpty(culture)) return culture; } return CultureInfo.CurrentUICulture.Name; } public static void SetCulture(this IResponseCookies cookies, string culture) { var cookieOptions = new CookieOptions { Secure = false, SameSite = SameSiteMode.Strict, HttpOnly = true }; cookies.Append( CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)), cookieOptions); } #endregion #region View error //TODO: integrate localizer for ready-to-use views //TODO: integrate to global exception handler middleware public static ViewResult ViewError(this Controller controller, ErrorViewModel errorViewModel) => controller.View("_Error", errorViewModel); public static ViewResult ViewError404(this Controller controller) => controller.ViewError(new() { Title = "404", Subtitle = "Die von Ihnen gesuchte Seite ist nicht verfügbar", Body = "Sie können derzeit nur an Sie gerichtete Briefe einsehen und unterschreiben.", }); public static ViewResult ViewEnvelopeNotFound(this Controller controller) => controller.ViewError(new() { Title = "404", Subtitle = "Document not found", Body = "Wenn Sie diese URL in Ihrer E-Mail erhalten haben, wenden Sie sich bitte an das IT-Team." }); public static ViewResult ViewDocumentNotFound(this Controller controller) => controller.ViewError(new() { Title = "404", Subtitle = "Umschlag nicht gefunden", Body = "Wenn Sie diese URL in Ihrer E-Mail erhalten haben, wenden Sie sich bitte an das IT-Team." }); public static ViewResult ViewAccessCodeNotSent(this Controller controller) => controller.ViewError(new() { Title = "500", Subtitle = "Der Zugangscode konnte nicht gesendet werden", Body = "Bitte kontaktieren Sie das IT-Team." }); public static ViewResult ViewInnerServiceError(this Controller controller) => controller.ViewError(new() { Title = "500", Subtitle = "Ein unerwarteter Fehler ist aufgetreten", Body = "Bitte kontaktieren Sie das IT-Team." }); #endregion #region HttpContext public static CultureInfo? GetCultureByAcceptLanguage(this HttpContext context) { var acceptLanguage = context.Request.Headers.AcceptLanguage.ToString(); if (string.IsNullOrWhiteSpace(acceptLanguage)) return null; foreach (var value in acceptLanguage.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) { var cultureName = value.Split(';', 2)[0]; if (string.IsNullOrWhiteSpace(cultureName)) continue; try { return new CultureInfo(cultureName); } catch (CultureNotFoundException) { // ignore invalid cultures and continue } } return null; } #endregion }