Compare commits
5 Commits
65618e5df9
...
d077a66796
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d077a66796 | ||
|
|
f16a8bcdb9 | ||
|
|
33f161a5fe | ||
|
|
7697939d7e | ||
|
|
34b3c46720 |
@@ -15,10 +15,10 @@ namespace EnvelopeGenerator.Application.Contracts
|
|||||||
|
|
||||||
Task<bool> IsSigned(int envelopeId, string userReference);
|
Task<bool> IsSigned(int envelopeId, string userReference);
|
||||||
|
|
||||||
Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, int? status = null);
|
Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null);
|
||||||
|
|
||||||
Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null);
|
Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null);
|
||||||
|
|
||||||
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status);
|
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
using DigitalData.UserManager.Application.DTOs.User;
|
||||||
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
||||||
{
|
{
|
||||||
public record EnvelopeHistoryDto(
|
public record EnvelopeHistoryDto(
|
||||||
long Id,
|
long Id,
|
||||||
@@ -7,6 +10,8 @@
|
|||||||
int Status,
|
int Status,
|
||||||
DateTime AddedWhen,
|
DateTime AddedWhen,
|
||||||
DateTime? ActionDate,
|
DateTime? ActionDate,
|
||||||
|
UserCreateDto? Sender,
|
||||||
ReceiverDto? Receiver,
|
ReceiverDto? Receiver,
|
||||||
|
ReferenceType ReferenceType,
|
||||||
string? Comment = null);
|
string? Comment = null);
|
||||||
}
|
}
|
||||||
@@ -117,6 +117,9 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="and" xml:space="preserve">
|
||||||
|
<value>und</value>
|
||||||
|
</data>
|
||||||
<data name="Back" xml:space="preserve">
|
<data name="Back" xml:space="preserve">
|
||||||
<value>Zurück</value>
|
<value>Zurück</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -144,6 +147,9 @@
|
|||||||
<data name="Finalize" xml:space="preserve">
|
<data name="Finalize" xml:space="preserve">
|
||||||
<value>Abschließen</value>
|
<value>Abschließen</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Hello" xml:space="preserve">
|
||||||
|
<value>Hallo</value>
|
||||||
|
</data>
|
||||||
<data name="LocakedOpen" xml:space="preserve">
|
<data name="LocakedOpen" xml:space="preserve">
|
||||||
<value>Öffnen</value>
|
<value>Öffnen</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -165,6 +171,12 @@
|
|||||||
<data name="Reject" xml:space="preserve">
|
<data name="Reject" xml:space="preserve">
|
||||||
<value>Ablehnen</value>
|
<value>Ablehnen</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Rejection" xml:space="preserve">
|
||||||
|
<value>Ablehnung</value>
|
||||||
|
</data>
|
||||||
|
<data name="RejectionReasonQ" xml:space="preserve">
|
||||||
|
<value>Warum lehnen Sie den Vertrag ab?</value>
|
||||||
|
</data>
|
||||||
<data name="SigAgree" xml:space="preserve">
|
<data name="SigAgree" xml:space="preserve">
|
||||||
<value>Durch Klick auf Abschließen stimme ich zu, dass die abgebildete und übermittelte Signatur als elektronische Darstellung meiner Signatur in den Fällen gelten, in denen ich sie auf Dokumenten, einschließlich rechtsgültiger Verträge verwende.</value>
|
<value>Durch Klick auf Abschließen stimme ich zu, dass die abgebildete und übermittelte Signatur als elektronische Darstellung meiner Signatur in den Fällen gelten, in denen ich sie auf Dokumenten, einschließlich rechtsgültiger Verträge verwende.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -117,6 +117,9 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
|
<data name="and" xml:space="preserve">
|
||||||
|
<value>and</value>
|
||||||
|
</data>
|
||||||
<data name="Back" xml:space="preserve">
|
<data name="Back" xml:space="preserve">
|
||||||
<value>Back</value>
|
<value>Back</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -144,6 +147,9 @@
|
|||||||
<data name="Finalize" xml:space="preserve">
|
<data name="Finalize" xml:space="preserve">
|
||||||
<value>Finalize</value>
|
<value>Finalize</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Hello" xml:space="preserve">
|
||||||
|
<value>Hello</value>
|
||||||
|
</data>
|
||||||
<data name="LocakedOpen" xml:space="preserve">
|
<data name="LocakedOpen" xml:space="preserve">
|
||||||
<value>Open</value>
|
<value>Open</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -165,6 +171,12 @@
|
|||||||
<data name="Reject" xml:space="preserve">
|
<data name="Reject" xml:space="preserve">
|
||||||
<value>Reject</value>
|
<value>Reject</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Rejection" xml:space="preserve">
|
||||||
|
<value>Rejection</value>
|
||||||
|
</data>
|
||||||
|
<data name="RejectionReasonQ" xml:space="preserve">
|
||||||
|
<value>Why do you reject the contract?</value>
|
||||||
|
</data>
|
||||||
<data name="SigAgree" xml:space="preserve">
|
<data name="SigAgree" xml:space="preserve">
|
||||||
<value>By clicking on Finalize, I agree that the signature shown and submitted is an electronic representation of my signature in cases where I use it on documents, including legally binding contracts.</value>
|
<value>By clicking on Finalize, I agree that the signature shown and submitted is an electronic representation of my signature in cases where I use it on documents, including legally binding contracts.</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -50,17 +50,21 @@ namespace EnvelopeGenerator.Application.Services
|
|||||||
status: (int)EnvelopeStatus.DocumentRejected) > 0;
|
status: (int)EnvelopeStatus.DocumentRejected) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, int? status = null) => _mapper.MapOrThrow<IEnumerable<EnvelopeHistoryDto>>(
|
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null)
|
||||||
await _repository.ReadAsync(
|
{
|
||||||
envelopeId: envelopeId,
|
var histDTOs = _mapper.MapOrThrow<IEnumerable<EnvelopeHistoryDto>>(
|
||||||
userReference: userReference,
|
await _repository.ReadAsync(
|
||||||
status: status));
|
envelopeId: envelopeId,
|
||||||
|
userReference: userReference,
|
||||||
|
status: status));
|
||||||
|
return referenceType is null ? histDTOs : histDTOs.Where(h => h.ReferenceType == referenceType);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null) =>
|
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null) =>
|
||||||
await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: (int)EnvelopeStatus.DocumentRejected);
|
await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: (int)EnvelopeStatus.DocumentRejected);
|
||||||
|
|
||||||
public async Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status) =>
|
public async Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null) =>
|
||||||
await CreateAsync(new (EnvelopeId: envelopeId, UserReference: userReference, Status: (int)status, ActionDate: DateTime.Now))
|
await CreateAsync(new (EnvelopeId: envelopeId, UserReference: userReference, Status: (int)status, ActionDate: DateTime.Now, Comment: comment))
|
||||||
.ThenAsync(
|
.ThenAsync(
|
||||||
Success: id => Result.Success(id),
|
Success: id => Result.Success(id),
|
||||||
Fail: (mssg, ntc) => Result.Fail<long>().Message(mssg).Notice(ntc)
|
Fail: (mssg, ntc) => Result.Fail<long>().Message(mssg).Notice(ntc)
|
||||||
|
|||||||
@@ -26,6 +26,13 @@
|
|||||||
MessageCompletionSent = 3005
|
MessageCompletionSent = 3005
|
||||||
End Enum
|
End Enum
|
||||||
|
|
||||||
|
Public Enum ReferenceType
|
||||||
|
Receiver
|
||||||
|
Sender
|
||||||
|
System
|
||||||
|
Unknown
|
||||||
|
End Enum
|
||||||
|
|
||||||
Public Enum ElementStatus
|
Public Enum ElementStatus
|
||||||
Created = 0
|
Created = 0
|
||||||
End Enum
|
End Enum
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using DigitalData.UserManager.Domain.Entities;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Domain.Entities
|
namespace EnvelopeGenerator.Domain.Entities
|
||||||
{
|
{
|
||||||
@@ -34,10 +36,18 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
[Column("COMMENT", TypeName = "nvarchar(max)")]
|
[Column("COMMENT", TypeName = "nvarchar(max)")]
|
||||||
public string? Comment { get; set; }
|
public string? Comment { get; set; }
|
||||||
|
|
||||||
//[ForeignKey("UserReference")]
|
[ForeignKey("UserReference")]
|
||||||
//public virtual DigitalData.UserManager.Domain.Entities.User? Sender { get; set; }
|
public virtual User? Sender { get; set; }
|
||||||
|
|
||||||
[ForeignKey("UserReference")]
|
[ForeignKey("UserReference")]
|
||||||
public virtual Receiver? Receiver { get; set; }
|
public virtual Receiver? Receiver { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public ReferenceType ReferenceType => (Status / 3) switch
|
||||||
|
{
|
||||||
|
1 => ReferenceType.Sender,
|
||||||
|
2 or 3 => ReferenceType.Receiver,
|
||||||
|
_ => ReferenceType.Unknown,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,6 @@ namespace EnvelopeGenerator.Infrastructure.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<IEnumerable<EnvelopeHistory>> ReadAsync(int? envelopeId = null, string? userReference = null, int? status = null, bool withReceiver = true);
|
Task<IEnumerable<EnvelopeHistory>> ReadAsync(int? envelopeId = null, string? userReference = null, int? status = null, bool withSender = false, bool withReceiver = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,6 +54,12 @@ namespace DigitalData.UserManager.Infrastructure.Repositories
|
|||||||
.HasForeignKey(eh => eh.UserReference)
|
.HasForeignKey(eh => eh.UserReference)
|
||||||
.HasPrincipalKey(e => e.EmailAddress);
|
.HasPrincipalKey(e => e.EmailAddress);
|
||||||
|
|
||||||
|
modelBuilder.Entity<EnvelopeHistory>()
|
||||||
|
.HasOne(eh => eh.Sender)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(eh => eh.UserReference)
|
||||||
|
.HasPrincipalKey(e => e.Email);
|
||||||
|
|
||||||
// Configure entities to handle database triggers
|
// Configure entities to handle database triggers
|
||||||
modelBuilder.Entity<Envelope>().ToTable(tb => tb.HasTrigger("TBSIG_ENVELOPE_HISTORY_AFT_INS"));
|
modelBuilder.Entity<Envelope>().ToTable(tb => tb.HasTrigger("TBSIG_ENVELOPE_HISTORY_AFT_INS"));
|
||||||
modelBuilder.Entity<EnvelopeHistory>().ToTable(tb => tb.HasTrigger("TBSIG_ENVELOPE_HISTORY_AFT_INS"));
|
modelBuilder.Entity<EnvelopeHistory>().ToTable(tb => tb.HasTrigger("TBSIG_ENVELOPE_HISTORY_AFT_INS"));
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace EnvelopeGenerator.Infrastructure.Repositories
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQueryable<EnvelopeHistory> By(int? envelopeId = null, string? userReference = null, int? status = null, bool withReceiver = false)
|
private IQueryable<EnvelopeHistory> By(int? envelopeId = null, string? userReference = null, int? status = null, bool withSender = false, bool withReceiver = false)
|
||||||
{
|
{
|
||||||
var query = _dbSet.AsQueryable();
|
var query = _dbSet.AsQueryable();
|
||||||
|
|
||||||
@@ -25,7 +25,10 @@ namespace EnvelopeGenerator.Infrastructure.Repositories
|
|||||||
if (status is not null)
|
if (status is not null)
|
||||||
query = query.Where(eh => eh.Status == status);
|
query = query.Where(eh => eh.Status == status);
|
||||||
|
|
||||||
if(withReceiver)
|
if (withSender)
|
||||||
|
query = query.Include(eh => eh.Sender);
|
||||||
|
|
||||||
|
if (withReceiver)
|
||||||
query = query.Include(eh => eh.Receiver);
|
query = query.Include(eh => eh.Receiver);
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
@@ -36,10 +39,12 @@ namespace EnvelopeGenerator.Infrastructure.Repositories
|
|||||||
userReference: userReference,
|
userReference: userReference,
|
||||||
status: status).CountAsync();
|
status: status).CountAsync();
|
||||||
|
|
||||||
public async Task<IEnumerable<EnvelopeHistory>> ReadAsync(int? envelopeId = null, string? userReference = null, int? status = null, bool withReceiver = true) => await By(
|
public async Task<IEnumerable<EnvelopeHistory>> ReadAsync(int? envelopeId = null, string? userReference = null, int? status = null, bool withSender = false, bool withReceiver = false)
|
||||||
|
=> await By(
|
||||||
envelopeId: envelopeId,
|
envelopeId: envelopeId,
|
||||||
userReference: userReference,
|
userReference: userReference,
|
||||||
status: status,
|
status: status,
|
||||||
|
withSender: withSender,
|
||||||
withReceiver: withReceiver).ToListAsync();
|
withReceiver: withReceiver).ToListAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,39 +6,17 @@ namespace EnvelopeGenerator.Web.Controllers
|
|||||||
{
|
{
|
||||||
public static class ControllerBaseExtensions
|
public static class ControllerBaseExtensions
|
||||||
{
|
{
|
||||||
public static (string EnvelopeUuid, string ReceiverSignature)? GetAuthenticatedEnvelopeDetails(this ControllerBase controller)
|
public static string? GetClaimValue(this ControllerBase controller, string claimType) => controller.User.FindFirstValue(claimType);
|
||||||
{
|
|
||||||
if(controller?.User?.Identity?.IsAuthenticated ?? false)
|
|
||||||
{
|
|
||||||
var envelopeUuid = controller.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
||||||
var receiverSignature = controller.User.FindFirst(ClaimTypes.Hash)?.Value;
|
|
||||||
if (!string.IsNullOrEmpty(envelopeUuid) && !string.IsNullOrEmpty(receiverSignature))
|
|
||||||
return (EnvelopeUuid: envelopeUuid, ReceiverSignature: receiverSignature);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string? GetAuthenticatedEnvelopeUuid(this ControllerBase controller)
|
public static string? GetAuthEnvelopeUuid(this ControllerBase controller) => controller.User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||||
{
|
|
||||||
if (controller?.User?.Identity?.IsAuthenticated ?? false)
|
|
||||||
{
|
|
||||||
var envelopeUuid = controller.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
||||||
if (!string.IsNullOrEmpty(envelopeUuid))
|
|
||||||
return envelopeUuid;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string? GetAuthenticatedReceiverSignature(this ControllerBase controller)
|
public static string? GetAuthReceiverSignature(this ControllerBase controller) => controller.User.FindFirstValue(ClaimTypes.Hash);
|
||||||
{
|
|
||||||
if (controller?.User?.Identity?.IsAuthenticated ?? false)
|
public static string? GetAuthReceiverName(this ControllerBase controller) => controller.User.FindFirstValue(ClaimTypes.Name);
|
||||||
{
|
|
||||||
var receiverSignature = controller.User.FindFirst(ClaimTypes.Hash)?.Value;
|
public static string? GetAuthReceiverMail(this ControllerBase controller) => controller.User.FindFirstValue(ClaimTypes.Email);
|
||||||
if (!string.IsNullOrEmpty(receiverSignature))
|
|
||||||
return receiverSignature;
|
public static string? GetAuthEnvelopeTitle(this ControllerBase controller) => controller.User.FindFirstValue(EnvelopeClaimTypes.Title);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: integrate localizer for ready-to-use views
|
//TODO: integrate localizer for ready-to-use views
|
||||||
public static ViewResult ViewError(this Controller controller, ErrorViewModel errorViewModel) => controller.View("_Error", errorViewModel);
|
public static ViewResult ViewError(this Controller controller, ErrorViewModel errorViewModel) => controller.View("_Error", errorViewModel);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace EnvelopeGenerator.Web.Controllers
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var authSignature = this.GetAuthenticatedReceiverSignature();
|
var authSignature = this.GetAuthReceiverSignature();
|
||||||
|
|
||||||
if (authSignature != envelopeKey.GetReceiverSignature())
|
if (authSignature != envelopeKey.GetReceiverSignature())
|
||||||
return Forbid();
|
return Forbid();
|
||||||
|
|||||||
@@ -1,24 +1,43 @@
|
|||||||
using EnvelopeGenerator.Application;
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application;
|
||||||
|
using EnvelopeGenerator.Application.Contracts;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
using EnvelopeGenerator.Common;
|
using EnvelopeGenerator.Common;
|
||||||
using EnvelopeGenerator.Web.Services;
|
using EnvelopeGenerator.Web.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
|
||||||
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Web.Controllers
|
namespace EnvelopeGenerator.Web.Controllers
|
||||||
{
|
{
|
||||||
[Authorize]
|
[Authorize]
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
public class EnvelopeController : BaseController
|
public class EnvelopeController : BaseController
|
||||||
{
|
{
|
||||||
private readonly EnvelopeOldService envelopeService;
|
private readonly EnvelopeOldService envelopeService;
|
||||||
private readonly ActionService? actionService;
|
private readonly ActionService? actionService;
|
||||||
private readonly UrlEncoder _urlEncoder;
|
private readonly UrlEncoder _urlEncoder;
|
||||||
|
private readonly IEnvelopeHistoryService _histService;
|
||||||
|
private readonly IReceiverService _receiverService;
|
||||||
|
private readonly IEnvelopeReceiverService _envRcvService;
|
||||||
|
|
||||||
public EnvelopeController(DatabaseService database, EnvelopeOldService envelope, ILogger<EnvelopeController> logger, UrlEncoder urlEncoder) : base(database, logger)
|
|
||||||
|
public EnvelopeController(DatabaseService database,
|
||||||
|
EnvelopeOldService envelope,
|
||||||
|
ILogger<EnvelopeController> logger, UrlEncoder urlEncoder,
|
||||||
|
IEnvelopeHistoryService envelopeHistoryService,
|
||||||
|
IReceiverService receiverService,
|
||||||
|
IEnvelopeReceiverService envelopeReceiverService) : base(database, logger)
|
||||||
{
|
{
|
||||||
envelopeService = envelope;
|
envelopeService = envelope;
|
||||||
actionService = database?.Services?.actionService;
|
actionService = database?.Services?.actionService;
|
||||||
_urlEncoder = urlEncoder;
|
_urlEncoder = urlEncoder;
|
||||||
|
_histService = envelopeHistoryService;
|
||||||
|
_receiverService = receiverService;
|
||||||
|
_envRcvService = envelopeReceiverService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NonAction]
|
[NonAction]
|
||||||
@@ -49,17 +68,17 @@ namespace EnvelopeGenerator.Web.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpPost("api/envelope/{envelopeKey}")]
|
[HttpPost("{envelopeKey}")]
|
||||||
public async Task<IActionResult> Update(string envelopeKey, int index)
|
public async Task<IActionResult> Update(string envelopeKey, int index)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
envelopeKey = _urlEncoder.Encode(envelopeKey);
|
envelopeKey = _urlEncoder.Encode(envelopeKey);
|
||||||
|
|
||||||
var authSignature = this.GetAuthenticatedReceiverSignature();
|
var authSignature = this.GetAuthReceiverSignature();
|
||||||
|
|
||||||
if (authSignature != envelopeKey.GetReceiverSignature())
|
if (authSignature != envelopeKey.GetReceiverSignature())
|
||||||
return Forbid();
|
return Unauthorized();
|
||||||
|
|
||||||
// Validate Envelope Key and load envelope
|
// Validate Envelope Key and load envelope
|
||||||
envelopeService.EnsureValidEnvelopeKey(envelopeKey);
|
envelopeService.EnsureValidEnvelopeKey(envelopeKey);
|
||||||
@@ -75,7 +94,7 @@ namespace EnvelopeGenerator.Web.Controllers
|
|||||||
|
|
||||||
string? annotationData = await envelopeService.EnsureValidAnnotationData(Request);
|
string? annotationData = await envelopeService.EnsureValidAnnotationData(Request);
|
||||||
|
|
||||||
envelopeService.InsertDocumentStatus(new DocumentStatus()
|
envelopeService.InsertDocumentStatus(new Common.DocumentStatus()
|
||||||
{
|
{
|
||||||
EnvelopeId = response.Envelope.Id,
|
EnvelopeId = response.Envelope.Id,
|
||||||
ReceiverId = response.Receiver.Id,
|
ReceiverId = response.Receiver.Id,
|
||||||
@@ -93,5 +112,45 @@ namespace EnvelopeGenerator.Web.Controllers
|
|||||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
|
[HttpPost("reject")]
|
||||||
|
public async Task<IActionResult> Reject([FromBody] string? reason = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var signature = this.GetAuthReceiverSignature();
|
||||||
|
var uuid = this.GetAuthEnvelopeUuid();
|
||||||
|
var mail = this.GetAuthReceiverMail();
|
||||||
|
if(uuid is null || signature is null || mail is null)
|
||||||
|
{
|
||||||
|
_logger.LogEnvelopeError(uuid: uuid, signature: signature,
|
||||||
|
message: @$"Unauthorized POST request in api\envelope\reject. One of claims, Envelope, signature or mail ({mail}) is null.");
|
||||||
|
return Unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
var envRcvRes = await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature);
|
||||||
|
|
||||||
|
if (envRcvRes.IsFailed)
|
||||||
|
{
|
||||||
|
_logger.LogNotice(envRcvRes.Notices);
|
||||||
|
return Unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _histService.RecordAsync(envRcvRes.Data.EnvelopeId, userReference: mail, EnvelopeStatus.DocumentRejected, comment: reason).ThenAsync(
|
||||||
|
Success: id => NoContent(),
|
||||||
|
Fail: IActionResult (mssg, ntc) =>
|
||||||
|
{
|
||||||
|
_logger.LogEnvelopeError(uuid: uuid, signature: signature, message: "Unexpected error happend in api/envelope/reject");
|
||||||
|
_logger.LogNotice(ntc);
|
||||||
|
return this.ViewInnerServiceError();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError(e, "{Message}", e.Message);
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,12 +95,12 @@ try
|
|||||||
builder.Services.AddScoped<IConfigService, ConfigService>();
|
builder.Services.AddScoped<IConfigService, ConfigService>();
|
||||||
builder.Services.AddScoped<IDocumentReceiverElementService, DocumentReceiverElementService>();
|
builder.Services.AddScoped<IDocumentReceiverElementService, DocumentReceiverElementService>();
|
||||||
builder.Services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
builder.Services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
||||||
|
builder.Services.AddScoped<IEnvelopeHistoryService, EnvelopeHistoryService>();
|
||||||
builder.Services.AddScoped<IDocumentStatusService, DocumentStatusService>();
|
builder.Services.AddScoped<IDocumentStatusService, DocumentStatusService>();
|
||||||
builder.Services.AddScoped<IEmailTemplateService, EmailTemplateService>();
|
builder.Services.AddScoped<IEmailTemplateService, EmailTemplateService>();
|
||||||
builder.Services.AddScoped<IEnvelopeService, EnvelopeService>();
|
builder.Services.AddScoped<IEnvelopeService, EnvelopeService>();
|
||||||
builder.Services.AddScoped<IEnvelopeCertificateService, EnvelopeCertificateService>();
|
builder.Services.AddScoped<IEnvelopeCertificateService, EnvelopeCertificateService>();
|
||||||
builder.Services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
builder.Services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
||||||
builder.Services.AddScoped<IEnvelopeHistoryService, EnvelopeHistoryService>();
|
|
||||||
builder.Services.AddScoped<IEnvelopeReceiverService, EnvelopeReceiverService>();
|
builder.Services.AddScoped<IEnvelopeReceiverService, EnvelopeReceiverService>();
|
||||||
builder.Services.AddScoped<IEnvelopeTypeService, EnvelopeTypeService>();
|
builder.Services.AddScoped<IEnvelopeTypeService, EnvelopeTypeService>();
|
||||||
builder.Services.AddScoped<IReceiverService, ReceiverService>();
|
builder.Services.AddScoped<IReceiverService, ReceiverService>();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
var sender = Model.Envelope?.User;
|
var sender = Model.Envelope?.User;
|
||||||
var pages = document?.Elements?.Select(e => e.Page) ?? Array.Empty<int>();
|
var pages = document?.Elements?.Select(e => e.Page) ?? Array.Empty<int>();
|
||||||
var stPageIndexes = string.Join(pages.Count() > 1 ? ", " : "", pages.Take(pages.Count() - 1))
|
var stPageIndexes = string.Join(pages.Count() > 1 ? ", " : "", pages.Take(pages.Count() - 1))
|
||||||
+ (pages.Count() > 1 ? " und " : "") + pages.LastOrDefault();
|
+ (pages.Count() > 1 ? $" {_localizer[WebKey.and].TrySanitize(_sanitizer)} " : "") + pages.LastOrDefault();
|
||||||
}
|
}
|
||||||
<div class="d-flex flex-column min-vh-100">
|
<div class="d-flex flex-column min-vh-100">
|
||||||
<nav class="navbar navbar-light bg-light">
|
<nav class="navbar navbar-light bg-light">
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="navbar-brand me-auto ms-5 envelope-message">@($"Hallo {Model.Name.TrySanitize(_sanitizer)}, {@envelope?.Message.TrySanitize(_sanitizer)}")</div>
|
<div class="navbar-brand me-auto ms-5 envelope-message">@($"{_localizer[WebKey.Hello]} {Model.Name}, {@envelope?.Message}".TrySanitize(_sanitizer))</div>
|
||||||
<div class="col-1 p-0 m-0 me-3 d-flex">
|
<div class="col-1 p-0 m-0 me-3 d-flex">
|
||||||
<img src="~/img/digital_data.svg" alt="...">
|
<img src="~/img/digital_data.svg" alt="...">
|
||||||
</div>
|
</div>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
envelope?.Title.TryEncode(_encoder),
|
envelope?.Title.TryEncode(_encoder),
|
||||||
sender?.Prename.TryEncode(_encoder),
|
sender?.Prename.TryEncode(_encoder),
|
||||||
sender?.Name.TryEncode(_encoder),
|
sender?.Name.TryEncode(_encoder),
|
||||||
sender?.Email.TryEncode(_encoder)))</small></p>
|
sender?.Email.TryEncode(_encoder)).TrySanitize(_sanitizer))</small></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@using DigitalData.Core.API
|
@using DigitalData.Core.API
|
||||||
@using Newtonsoft.Json
|
@using Newtonsoft.Json
|
||||||
|
@using Newtonsoft.Json.Serialization
|
||||||
@{
|
@{
|
||||||
var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string;
|
var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string;
|
||||||
}
|
}
|
||||||
@@ -27,19 +28,23 @@
|
|||||||
<script src="~/lib/pspdfkit/pspdfkit.js" asp-append-version="true"></script>
|
<script src="~/lib/pspdfkit/pspdfkit.js" asp-append-version="true"></script>
|
||||||
<script src="~/lib/bootstrap-cookie-consent-settings-main/bootstrap-cookie-consent-settings.js" asp-append-version="true"></script>
|
<script src="~/lib/bootstrap-cookie-consent-settings-main/bootstrap-cookie-consent-settings.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/util.js" asp-append-version="true"></script>
|
<script src="~/js/util.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/api.js" asp-append-version="true"></script>
|
<script src="~/js/api-service.js" asp-append-version="true"></script>
|
||||||
@await RenderSectionAsync("Scripts", required: false)
|
@await RenderSectionAsync("Scripts", required: false)
|
||||||
@{
|
@{
|
||||||
var lStrsJson = JsonConvert.SerializeObject(_localizer.ToDictionary()).TrySanitize(_sanitizer);
|
var settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||||
|
};
|
||||||
|
var lStrsJson = JsonConvert.SerializeObject(_localizer.ToDictionary(), settings).TrySanitize(_sanitizer);
|
||||||
}
|
}
|
||||||
<script nonce="@nonce">
|
<script nonce="@nonce">
|
||||||
var localized = @Html.Raw(lStrsJson)
|
var localized = @Html.Raw(lStrsJson)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main role="main">
|
<main role="main">
|
||||||
<partial name="_CookieConsentPartial" />
|
<partial name="_CookieConsentPartial" />
|
||||||
@RenderBody()
|
@RenderBody()
|
||||||
</main>
|
</main>
|
||||||
|
<script src="~/js/event-binder.js" asp-append-version="true"></script>
|
||||||
@Html.AntiForgeryToken()
|
@Html.AntiForgeryToken()
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -24,5 +24,7 @@
|
|||||||
public static readonly string EnvelopeInfo2 = nameof(EnvelopeInfo2);
|
public static readonly string EnvelopeInfo2 = nameof(EnvelopeInfo2);
|
||||||
public static readonly string SigAgree = nameof(SigAgree);
|
public static readonly string SigAgree = nameof(SigAgree);
|
||||||
public static readonly string Reject = nameof(Reject);
|
public static readonly string Reject = nameof(Reject);
|
||||||
|
public static readonly string and = nameof(and);
|
||||||
|
public static readonly string Hello = nameof(Hello);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
41
EnvelopeGenerator.Web/wwwroot/js/api-service.js
Normal file
41
EnvelopeGenerator.Web/wwwroot/js/api-service.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
class Content {
|
||||||
|
static get JSON () {
|
||||||
|
return 'application/json';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class API {
|
||||||
|
static get REJECT_URL () {
|
||||||
|
return `/api/envelope/reject`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __XSRF_TOKEN
|
||||||
|
static get XSRF_TOKEN() {
|
||||||
|
API.__XSRF_TOKEN ??= document.getElementsByName('__RequestVerificationToken')[0].value;
|
||||||
|
return API.__XSRF_TOKEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitForm = async form => await fetch(form.action, {
|
||||||
|
method: form.method,
|
||||||
|
body: new FormData(form),
|
||||||
|
headers: {
|
||||||
|
"X-Requested-With": "XMLHttpRequest"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const createRequest = async (method, url, body, contentType) => {
|
||||||
|
return fetch(url, {
|
||||||
|
credentials: 'include',
|
||||||
|
method: method,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': contentType,
|
||||||
|
'X-XSRF-TOKEN': API.XSRF_TOKEN
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const createPost = (url, body, contentType) => createRequest('POST', url, body, contentType);
|
||||||
|
|
||||||
|
const rejectEnvelope = (reason) => createPost(API.REJECT_URL, reason, Content.JSON);
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
const submitForm = async form => await fetch(form.action, {
|
|
||||||
method: form.method,
|
|
||||||
body: new FormData(form),
|
|
||||||
headers: {
|
|
||||||
"X-Requested-With": "XMLHttpRequest"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -180,14 +180,14 @@ class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Swal.fire({
|
return Swal.fire({
|
||||||
title: localized.Confirmation,
|
title: localized.confirmation,
|
||||||
html: `<div class="text-start fs-6 p-0 m-0">${localized.SigAgree}</div>`,
|
html: `<div class="text-start fs-6 p-0 m-0">${localized.sigAgree}</div>`,
|
||||||
icon: "question",
|
icon: "question",
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
confirmButtonColor: "#3085d6",
|
confirmButtonColor: "#3085d6",
|
||||||
cancelButtonColor: "#d33",
|
cancelButtonColor: "#d33",
|
||||||
confirmButtonText: localized.Finalize,
|
confirmButtonText: localized.finalize,
|
||||||
cancelButtonText: localized.Back
|
cancelButtonText: localized.back
|
||||||
}).then(async (result) => {
|
}).then(async (result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
//---
|
//---
|
||||||
|
|||||||
37
EnvelopeGenerator.Web/wwwroot/js/event-binder.js
Normal file
37
EnvelopeGenerator.Web/wwwroot/js/event-binder.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
$('.btn_reject').click(_ =>
|
||||||
|
Swal.fire({
|
||||||
|
title: localized.rejection,
|
||||||
|
html: `<div class="text-start fs-6 p-0 m-0">${localized.rejectionReasonQ}</div>`,
|
||||||
|
icon: "question",
|
||||||
|
input: "text",
|
||||||
|
inputAttributes: {
|
||||||
|
autocapitalize: "off"
|
||||||
|
},
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: localized.complete,
|
||||||
|
cancelButtonText: localized.back,
|
||||||
|
showLoaderOnConfirm: true,
|
||||||
|
preConfirm: async (reason) => {
|
||||||
|
try {
|
||||||
|
var res = await rejectEnvelope(reason);
|
||||||
|
return res;
|
||||||
|
} catch (error) {
|
||||||
|
Swal.showValidationMessage(`
|
||||||
|
Request failed: ${error}
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
allowOutsideClick: () => !Swal.isLoading()
|
||||||
|
}).then((result) => {
|
||||||
|
if (!result.isConfirmed)
|
||||||
|
return;
|
||||||
|
const res = result.value;
|
||||||
|
console.log(res)
|
||||||
|
if (res.ok) {
|
||||||
|
alert('rejected')
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alert('fail')
|
||||||
|
}));
|
||||||
Reference in New Issue
Block a user