2024-05-08 15:55:51 +02:00

278 lines
13 KiB
C#

using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.Services;
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Web.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using DigitalData.Core.API;
using EnvelopeGenerator.Application;
using Microsoft.Extensions.Localization;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Application.DTOs;
using Microsoft.AspNetCore.Localization;
using System.Text.Encodings.Web;
namespace EnvelopeGenerator.Web.Controllers
{
public class HomeController : BaseController
{
private readonly EnvelopeOldService envelopeOldService;
private readonly IEnvelopeReceiverService _envRcvService;
private readonly IEnvelopeHistoryService _historyService;
private readonly IStringLocalizer<Resource> _localizer;
private readonly IConfiguration _configuration;
private readonly UrlEncoder _urlEncoder;
public HomeController(DatabaseService databaseService, EnvelopeOldService envelopeOldService, ILogger<HomeController> logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeHistoryService historyService, IStringLocalizer<Resource> localizer, IConfiguration configuration, UrlEncoder urlEncoder) : base(databaseService, logger)
{
this.envelopeOldService = envelopeOldService;
_envRcvService = envelopeReceiverService;
_historyService = historyService;
_localizer = localizer;
_configuration = configuration;
_urlEncoder = urlEncoder;
}
[HttpGet("/EnvelopeKey/{envelopeReceiverId}")]
public async Task<IActionResult> SendAccessCode([FromRoute] string envelopeReceiverId)
{
try
{
envelopeReceiverId = _urlEncoder.Encode(envelopeReceiverId);
ViewData["EnvelopeKey"] = envelopeReceiverId;
return await _envRcvService.ReadByEnvelopeReceiverIdAsync(envelopeReceiverId: envelopeReceiverId).ThenAsync<EnvelopeReceiverDto, IActionResult>(
SuccessAsync: async er =>
{
EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId);
bool accessCodeAlreadyRequested = await _historyService.AccessCodeAlreadyRequested(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress);
if (!accessCodeAlreadyRequested)
{
// Send email with password
bool actionResult = database.Services.actionService.RequestAccessCode(response.Envelope, response.Receiver);
bool result = database.Services.emailService.SendDocumentAccessCodeReceivedEmail(response.Envelope, response.Receiver);
}
return Redirect($"{envelopeReceiverId}/Locked");
},
Fail: (messages, notices) =>
{
_logger.LogNotice(notices);
return this.ViewEnvelopeNotFound();
});
}
catch(Exception ex)
{
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception:ex, message: _localizer[MessageKey.UnexpectedError]);
return this.ViewInnerServiceError();
}
}
[HttpGet("EnvelopeKey/{envelopeReceiverId}/Locked")]
public async Task<IActionResult> EnvelopeLocked([FromRoute] string envelopeReceiverId)
{
try
{
envelopeReceiverId = _urlEncoder.Encode(envelopeReceiverId);
ViewData["Languages"] = _configuration.GetSection("Languages").Get<string[]>()!;
ViewData["UserLanguage"] = UserLanguage;
return await _envRcvService.IsExisting(envelopeReceiverId: envelopeReceiverId).ThenAsync(
Success: isExisting => isExisting ? View().WithData("EnvelopeKey", envelopeReceiverId) : this.ViewEnvelopeNotFound(),
Fail: IActionResult (messages,notices) =>
{
_logger.LogNotice(notices);
return this.ViewEnvelopeNotFound();
});
}
catch(Exception ex)
{
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception: ex);
return this.ViewInnerServiceError();
}
}
[HttpPost("/EnvelopeKey/{envelopeReceiverId}/Locked")]
public async Task<IActionResult> LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] string access_code)
{
try
{
envelopeReceiverId = _urlEncoder.Encode(envelopeReceiverId);
(string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
if(uuid is null || signature is null)
{
_logger.LogEnvelopeError(uuid: uuid, signature: signature, message: _localizer[MessageKey.WrongEnvelopeReceiverId]);
return BadRequest(_localizer[MessageKey.WrongEnvelopeReceiverId]);
}
_logger.LogInformation($"Envelope UUID: [{uuid}]\nReceiver Signature: [{signature}]");
return await _envRcvService.VerifyAccessCodeAsync(uuid: uuid, signature: signature, accessCode: access_code).ThenAsync(
SuccessAsync: async isVerified =>
{
EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId);
if (isVerified)
{
database.Services.actionService.EnterCorrectAccessCode(response.Envelope, response.Receiver); //for history
ViewData["EnvelopeKey"] = envelopeReceiverId;
return await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync<EnvelopeReceiverDto, IActionResult>(
SuccessAsync: async er =>
{
if(await _historyService.IsSigned(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress))
return View("EnvelopeSigned");
database.Services.actionService.EnterCorrectAccessCode(response.Envelope, response.Receiver); //for history
ViewData["EnvelopeKey"] = envelopeReceiverId;
if (response.Envelope.Documents.Count() > 0)
{
var document = await envelopeOldService.GetDocument(response.Envelope.Documents[0].Id, envelopeReceiverId);
byte[] bytes = await envelopeOldService.GetDocumentContents(document);
ViewData["DocumentBytes"] = bytes;
}
else
{
return this.ViewDocumentNotFound();
}
var claims = new List<Claim> { new(ClaimTypes.NameIdentifier, uuid), new(ClaimTypes.Hash, signature) };
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties { };
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
//add PSPDFKit licence key
ViewData["PSPDFKitLicenseKey"] = _configuration["PSPDFKitLicenseKey"];
return View("ShowEnvelope", er);
},
Fail: (messages, notices) =>
{
_logger.LogNotice(notices);
return this.ViewEnvelopeNotFound();
}
);
}
else
{
database.Services.actionService.EnterIncorrectAccessCode(response.Envelope, response.Receiver); //for history
return Unauthorized();
}
},
Fail: (messages, notices) =>
{
_logger.LogNotice(notices);
return notices.HasFlag(Flag.SecurityBreach) ? Forbid() : StatusCode(StatusCodes.Status500InternalServerError, messages.Join());
});
}
catch(Exception ex)
{
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception: ex);
return this.ViewInnerServiceError();
}
}
[HttpGet("/EnvelopeKey/{envelopeReceiverId}/Success")]
public async Task<IActionResult> EnvelopeSigned(string envelopeReceiverId)
{
try
{
envelopeReceiverId = _urlEncoder.Encode(envelopeReceiverId);
return await _envRcvService.IsExisting(envelopeReceiverId: envelopeReceiverId).ThenAsync(
SuccessAsync: async isExisting =>
{
if(!isExisting)
return this.ViewEnvelopeNotFound();
EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId);
if (!envelopeOldService.ReceiverAlreadySigned(response.Envelope, response.Receiver.Id))
return Redirect($"/EnvelopeKey/{envelopeReceiverId}/Locked");
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
ViewData["EnvelopeKey"] = envelopeReceiverId;
return View();
},
Fail: IActionResult (messages, notices) =>
{
_logger.LogNotice(notices);
return this.ViewEnvelopeNotFound();
});
}
catch (Exception ex)
{
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception: ex);
return this.ViewInnerServiceError();
}
}
[Authorize]
[HttpGet("IsAuthenticated")]
public IActionResult IsAuthenticated()
{
var envelopeUuid = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var receiverSignature = User.FindFirst(ClaimTypes.Hash)?.Value;
return Ok(new { EnvelopeUuid = envelopeUuid, ReceiverSignature = receiverSignature });
}
[HttpGet("lang")]
public IActionResult GetLanguage() => Ok(UserLanguage);
[HttpPost("lang")]
public IActionResult SetLanguage([FromForm] string language)
{
try
{
language = _urlEncoder.Encode(language);
var cookieOptions = new CookieOptions()
{
Expires = DateTimeOffset.UtcNow.AddYears(1),
Secure = false,
Path = "/",
SameSite = SameSiteMode.Strict,
HttpOnly = true
};
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(language)),
cookieOptions);
return Redirect(Request.Headers["Referer"].ToString());
}
catch(Exception ex)
{
_logger.LogError(ex, ex.Message);
return this.ViewEnvelopeNotFound();
}
}
private string UserLanguage
{
get
{
return Request.Cookies[CookieRequestCultureProvider.DefaultCookieName] ?? _configuration.GetSection("Languages").Get<string[]>()![0];
}
set
{
Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(value)), new CookieOptions()
{
Expires = DateTimeOffset.UtcNow.AddYears(1),
});
}
}
public IActionResult Error404() => this.ViewError404();
}
}