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; namespace EnvelopeGenerator.Web.Controllers { public class HomeController : BaseController { private readonly EnvelopeOldService envelopeOldService; private readonly IEnvelopeReceiverService _envRcvService; private readonly IEnvelopeService _envelopeService; private readonly IEnvelopeHistoryService _historyService; private readonly IStringLocalizer _localizer; public HomeController(DatabaseService databaseService, EnvelopeOldService envelopeOldService, ILogger logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeService envelopeService, IEnvelopeHistoryService historyService, IStringLocalizer localizer) : base(databaseService, logger) { this.envelopeOldService = envelopeOldService; _envRcvService = envelopeReceiverService; _envelopeService = envelopeService; _historyService = historyService; _localizer = localizer; } [HttpGet("/EnvelopeKey/{envelopeReceiverId}")] public async Task SendAccessCode([FromRoute] string envelopeReceiverId) { ViewData["EnvelopeKey"] = envelopeReceiverId; try { return await _envRcvService.ReadByEnvelopeReceiverIdAsync(envelopeReceiverId: envelopeReceiverId).ThenAsync( SuccessAsync: async er => { EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId); bool accessCodeAlreadyRequested = database.Models.receiverModel.AccessCodeAlreadyRequested(response.Receiver.Email, response.Envelope.Id); 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 EnvelopeLocked([FromRoute] string envelopeReceiverId) { try { 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 LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] string access_code) { try { (string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId(); if(uuid is null || signature is null) { _logger.LogEnvelopeError(uuid: uuid, signature: signature, message: _localizer[MessageKey.WrongEnvelopeReceiverId.ToString()]); 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) { //todo: write using crud-service (mostlikely history-service) to make it async if (envelopeOldService.ReceiverAlreadySigned(response.Envelope, response.Receiver.Id)) { return View("EnvelopeSigned"); } database.Services.actionService.EnterCorrectAccessCode(response.Envelope, response.Receiver); //for history ViewData["EnvelopeKey"] = envelopeReceiverId; ViewData["EnvelopeResponse"] = response; return await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync( SuccessAsync: async er => { 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 { 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); 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 EnvelopeSigned(string envelopeReceiverId) { try { 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 }); } [HttpPost("{language}")] public IActionResult SetLanguage([FromRoute] string language) { Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(language)), new CookieOptions() { Expires = DateTimeOffset.UtcNow.AddYears(1) }); return Redirect(Request.Headers["Referer"].ToString()); } public IActionResult Error404() => this.ViewError404(); } }