Compare commits

...

4 Commits

14 changed files with 51 additions and 62 deletions

View File

@@ -11,5 +11,7 @@ namespace EnvelopeGenerator.Application.Contracts
Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null); Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null);
Task<bool> AccessCodeAlreadyRequested(int envelopeId, string userReference); Task<bool> AccessCodeAlreadyRequested(int envelopeId, string userReference);
Task<bool> IsSigned(int envelopeId, string userReference);
} }
} }

View File

@@ -5,8 +5,8 @@
int DocumentId, int DocumentId,
int ReceiverId, int ReceiverId,
int ElementType, int ElementType,
double PositionX, double X,
double PositionY, double Y,
double Width, double Width,
double Height, double Height,
int Page, int Page,

View File

@@ -4,10 +4,7 @@
( (
int Id, int Id,
int EnvelopeId, int EnvelopeId,
string Filename,
string Filepath,
DateTime AddedWhen, DateTime AddedWhen,
string FilenameOriginal,
IEnumerable<DocumentReceiverElementDto>? Elements IEnumerable<DocumentReceiverElementDto>? Elements
); );
} }

View File

@@ -1,6 +1,4 @@
using EnvelopeGenerator.Domain.Entities; namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs
{ {
public record EnvelopeReceiverDto( public record EnvelopeReceiverDto(
int EnvelopeId, int EnvelopeId,

View File

@@ -8,15 +8,15 @@ namespace EnvelopeGenerator.Application
{ {
public static void LogEnvelopeError(this ILogger logger, string envelopeEeceiverId, Exception? exception = null, string? message = null, params object?[] args) public static void LogEnvelopeError(this ILogger logger, string envelopeEeceiverId, Exception? exception = null, string? message = null, params object?[] args)
{ {
var sb = new StringBuilder(envelopeEeceiverId.DecodeEnvelopeReceiverId().ToTitle()); var sb = new StringBuilder().AppendLine(envelopeEeceiverId.DecodeEnvelopeReceiverId().ToTitle());
if (message is not null) if (message is not null)
sb.AppendLine().Append(message); sb.AppendLine(message);
if(exception is null) if(exception is null)
logger.Log(LogLevel.Error, sb.ToString(), args); logger.Log(LogLevel.Error, sb.ToString(), args);
else else
logger.Log(LogLevel.Error, exception, sb.ToString(), args); logger.Log(LogLevel.Error, exception, sb.AppendLine(exception.Message).ToString(), args);
} }
public static void LogEnvelopeError(this ILogger logger, string? uuid, string? signature = null, Exception? exception = null, string? message = null, params object?[] args) public static void LogEnvelopeError(this ILogger logger, string? uuid, string? signature = null, Exception? exception = null, string? message = null, params object?[] args)
@@ -37,7 +37,7 @@ namespace EnvelopeGenerator.Application
public static string ToTitle(this (string? UUID, string? Signature) envelopeReceiverTuple) public static string ToTitle(this (string? UUID, string? Signature) envelopeReceiverTuple)
{ {
return $"UUID is {envelopeReceiverTuple.UUID} and \n signature is {envelopeReceiverTuple.Signature}"; return $"UUID is {envelopeReceiverTuple.UUID} and signature is {envelopeReceiverTuple.Signature}";
} }
} }
} }

View File

@@ -19,6 +19,19 @@ namespace EnvelopeGenerator.Application.Services
public async Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null) => await _repository.CountAsync(envelopeId: envelopeId, userReference: userReference, status: status); public async Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null) => await _repository.CountAsync(envelopeId: envelopeId, userReference: userReference, status: status);
public async Task<bool> AccessCodeAlreadyRequested(int envelopeId, string userReference) => await _repository.CountAsync(envelopeId: envelopeId, userReference:userReference, status: (int) EnvelopeStatus.AccessCodeRequested) > 0; public async Task<bool> HasStatus(EnvelopeStatus status, int envelopeId, string userReference) => await _repository.CountAsync(
envelopeId: envelopeId,
userReference: userReference,
status: (int) status) > 0;
public async Task<bool> AccessCodeAlreadyRequested(int envelopeId, string userReference) => await _repository.CountAsync(
envelopeId: envelopeId,
userReference:userReference,
status: (int) EnvelopeStatus.AccessCodeRequested) > 0;
public async Task<bool> IsSigned(int envelopeId, string userReference) => await _repository.CountAsync(
envelopeId: envelopeId,
userReference: userReference,
status: (int) EnvelopeStatus.DocumentSigned) > 0;
} }
} }

View File

@@ -28,12 +28,12 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("POSITION_X")] [Column("POSITION_X")]
[DefaultValue(0)] [DefaultValue(0)]
public double PositionX { get; set; } public double X { get; set; }
[Required] [Required]
[Column("POSITION_Y")] [Column("POSITION_Y")]
[DefaultValue(0)] [DefaultValue(0)]
public double PositionY { get; set; } public double Y { get; set; }
[Required] [Required]
[Column("WIDTH")] [Column("WIDTH")]
@@ -83,9 +83,9 @@ namespace EnvelopeGenerator.Domain.Entities
public virtual Receiver? Receiver { get; set; } public virtual Receiver? Receiver { get; set; }
[NotMapped] [NotMapped]
public double Top => Math.Round(PositionY, 5); public double Top => Math.Round(Y, 5);
[NotMapped] [NotMapped]
public double Left => Math.Round(PositionX, 5); public double Left => Math.Round(X, 5);
} }
} }

View File

@@ -120,9 +120,7 @@
<Compile Include="frmFinalizePDF.Designer.vb"> <Compile Include="frmFinalizePDF.Designer.vb">
<DependentUpon>frmFinalizePDF.vb</DependentUpon> <DependentUpon>frmFinalizePDF.vb</DependentUpon>
</Compile> </Compile>
<Compile Include="frmFinalizePDF.vb"> <Compile Include="frmFinalizePDF.vb" />
<SubType>Form</SubType>
</Compile>
<Compile Include="frmReportViewer.Designer.vb"> <Compile Include="frmReportViewer.Designer.vb">
<DependentUpon>frmReportViewer.vb</DependentUpon> <DependentUpon>frmReportViewer.vb</DependentUpon>
</Compile> </Compile>

View File

@@ -22,8 +22,6 @@ namespace EnvelopeGenerator.Web.Controllers
} }
[NonAction] [NonAction]
[HttpGet]
[Route("api/document/{envelopeKey}")]
public async Task<IActionResult> Get([FromRoute] string envelopeKey, [FromQuery] int index) public async Task<IActionResult> Get([FromRoute] string envelopeKey, [FromQuery] int index)
{ {
try try
@@ -47,8 +45,8 @@ namespace EnvelopeGenerator.Web.Controllers
} }
} }
[HttpPost] [Authorize]
[Route("api/document/{envelopeKey}")] [HttpPost("api/document/{envelopeKey}")]
public async Task<IActionResult> Open(string envelopeKey) public async Task<IActionResult> Open(string envelopeKey)
{ {
try try

View File

@@ -22,7 +22,6 @@ namespace EnvelopeGenerator.Web.Controllers
} }
[NonAction] [NonAction]
[HttpGet("api/envelope/{envelopeKey}")]
public async Task<IActionResult> Get([FromRoute] string envelopeKey) public async Task<IActionResult> Get([FromRoute] string envelopeKey)
{ {
try try
@@ -48,6 +47,7 @@ namespace EnvelopeGenerator.Web.Controllers
} }
} }
[Authorize]
[HttpPost("api/envelope/{envelopeKey}")] [HttpPost("api/envelope/{envelopeKey}")]
public async Task<IActionResult> Update(string envelopeKey, int index) public async Task<IActionResult> Update(string envelopeKey, int index)
{ {

View File

@@ -14,11 +14,7 @@ using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Resources; using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Configuration;
using Ganss.Xss;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Web.Controllers namespace EnvelopeGenerator.Web.Controllers
{ {
@@ -54,9 +50,7 @@ namespace EnvelopeGenerator.Web.Controllers
{ {
EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId); EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId);
bool accessCodeAlreadyRequested = database.Models.receiverModel.AccessCodeAlreadyRequested(response.Receiver.Email, response.Envelope.Id); bool accessCodeAlreadyRequested = await _historyService.AccessCodeAlreadyRequested(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress);
accessCodeAlreadyRequested = await _historyService.AccessCodeAlreadyRequested(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress);
if (!accessCodeAlreadyRequested) if (!accessCodeAlreadyRequested)
{ {
// Send email with password // Send email with password
@@ -113,8 +107,8 @@ namespace EnvelopeGenerator.Web.Controllers
if(uuid is null || signature is null) if(uuid is null || signature is null)
{ {
_logger.LogEnvelopeError(uuid: uuid, signature: signature, message: _localizer[MessageKey.WrongEnvelopeReceiverId.ToString()]); _logger.LogEnvelopeError(uuid: uuid, signature: signature, message: _localizer[MessageKey.WrongEnvelopeReceiverId]);
return BadRequest(_localizer[MessageKey.WrongEnvelopeReceiverId]); return Unauthorized();
} }
_logger.LogInformation($"Envelope UUID: [{uuid}]\nReceiver Signature: [{signature}]"); _logger.LogInformation($"Envelope UUID: [{uuid}]\nReceiver Signature: [{signature}]");
@@ -125,19 +119,18 @@ namespace EnvelopeGenerator.Web.Controllers
EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId); EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId);
if (isVerified) 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 database.Services.actionService.EnterCorrectAccessCode(response.Envelope, response.Receiver); //for history
ViewData["EnvelopeKey"] = envelopeReceiverId; ViewData["EnvelopeKey"] = envelopeReceiverId;
ViewData["EnvelopeResponse"] = response;
return await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync<EnvelopeReceiverDto, IActionResult>( return await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync<EnvelopeReceiverDto, IActionResult>(
SuccessAsync: async er => 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) if (response.Envelope.Documents.Count() > 0)
{ {
var document = await envelopeOldService.GetDocument(response.Envelope.Documents[0].Id, envelopeReceiverId); var document = await envelopeOldService.GetDocument(response.Envelope.Documents[0].Id, envelopeReceiverId);
@@ -181,7 +174,7 @@ namespace EnvelopeGenerator.Web.Controllers
Fail: (messages, notices) => Fail: (messages, notices) =>
{ {
_logger.LogNotice(notices); _logger.LogNotice(notices);
return notices.HasFlag(Flag.SecurityBreach) ? Forbid() : StatusCode(StatusCodes.Status500InternalServerError, messages.Join()); return Unauthorized();
}); });
} }
catch(Exception ex) catch(Exception ex)
@@ -233,7 +226,7 @@ namespace EnvelopeGenerator.Web.Controllers
return Ok(new { EnvelopeUuid = envelopeUuid, ReceiverSignature = receiverSignature }); return Ok(new { EnvelopeUuid = envelopeUuid, ReceiverSignature = receiverSignature });
} }
[HttpGet("lang")] [NonAction]
public IActionResult GetLanguage() => Ok(UserLanguage); public IActionResult GetLanguage() => Ok(UserLanguage);
[HttpPost("lang")] [HttpPost("lang")]

View File

@@ -57,13 +57,11 @@
</script> </script>
@if (ViewData["DocumentBytes"] is byte[] documentBytes) @if (ViewData["DocumentBytes"] is byte[] documentBytes)
{ {
var envelopeResponse = ViewData["EnvelopeResponse"];
var settings = new Newtonsoft.Json.JsonSerializerSettings var settings = new Newtonsoft.Json.JsonSerializerSettings
{ {
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
}; };
var envelopeResponseJson = Newtonsoft.Json.JsonConvert.SerializeObject(envelopeResponse, settings); var envelopeReceiverJson = Newtonsoft.Json.JsonConvert.SerializeObject(Model, settings);
var documentBase64String = Convert.ToBase64String(documentBytes); var documentBase64String = Convert.ToBase64String(documentBytes);
var envelopeKey = ViewData["EnvelopeKey"] as string; var envelopeKey = ViewData["EnvelopeKey"] as string;
@@ -78,9 +76,8 @@
var byteArray = new Uint8Array(byteNumbers); var byteArray = new Uint8Array(byteNumbers);
var documentArrayBuffer = byteArray.buffer; var documentArrayBuffer = byteArray.buffer;
var envelopeResponse = @Html.Raw(envelopeResponseJson.TrySanitize(_sanitizer));
document.addEventListener("DOMContentLoaded", async () => { document.addEventListener("DOMContentLoaded", async () => {
const app = new App("#app", "@envelopeKey.TrySanitize(_sanitizer)", envelopeResponse, documentArrayBuffer, "@ViewData["PSPDFKitLicenseKey"]"); const app = new App("#app", "@envelopeKey.TrySanitize(_sanitizer)", @Html.Raw(envelopeReceiverJson.TrySanitize(_sanitizer)), documentArrayBuffer, "@ViewData["PSPDFKitLicenseKey"]");
await app.init(); await app.init();
}) })
</script> </script>

View File

@@ -50,14 +50,7 @@
"logger": "*", "logger": "*",
"level": "Fatal", "level": "Fatal",
"writeTo": "criticalLogs" "writeTo": "criticalLogs"
},
{
"logger": "EnvelopeGenerator.Web.Controllers.*",
"minLevel": "Error",
"writeTo": "errorLogs",
"final": true
} }
] ]
}, },
"AddTestControllers": true, "AddTestControllers": true,

View File

@@ -10,7 +10,7 @@ const ActionType = {
} }
class App { class App {
constructor(container, envelopeKey, envelopeResponse, documentBytes, licenseKey) { constructor(container, envelopeKey, envelopeReceiver, documentBytes, licenseKey) {
this.container = container this.container = container
this.envelopeKey = envelopeKey this.envelopeKey = envelopeKey
@@ -21,8 +21,8 @@ class App {
this.Instance = null this.Instance = null
this.currentDocument = null this.currentDocument = null
this.currentReceiver = null this.currentReceiver = null
this.signatureCount = 0 this.signatureCount = 0;
this.envelopeResponse = envelopeResponse; this.envelopeReceiver = envelopeReceiver;
this.documentBytes = documentBytes; this.documentBytes = documentBytes;
this.licenseKey = licenseKey; this.licenseKey = licenseKey;
} }
@@ -31,8 +31,8 @@ class App {
// and will trigger loading of the Editor Interface // and will trigger loading of the Editor Interface
async init() { async init() {
// Load the envelope from the database // Load the envelope from the database
this.currentDocument = this.envelopeResponse.envelope.documents[0] this.currentDocument = this.envelopeReceiver.envelope.documents[0]
this.currentReceiver = this.envelopeResponse.receiver this.currentReceiver = this.envelopeReceiver.receiver
// Load the document from the filestore // Load the document from the filestore
const documentResponse = this.documentBytes const documentResponse = this.documentBytes
@@ -109,7 +109,7 @@ class App {
const timestamp = new Date() const timestamp = new Date()
const imageUrl = await this.Annotation.createAnnotationFrameBlob( const imageUrl = await this.Annotation.createAnnotationFrameBlob(
this.currentReceiver.name, this.envelopeReceiver.name,
this.currentReceiver.signature, this.currentReceiver.signature,
timestamp, timestamp,
width, width,