Updated the method name in EnvelopeReceiverPageDataService to clarify its purpose of retrieving documents for a receiver. Refactored all references in Razor pages (ReceiverPage.razor, ReceiverSignedPage.razor, EnvelopeReceiverPage.razor) to use the new method name. No changes were made to the method's logic or functionality. This improves code clarity and consistency.
127 lines
5.3 KiB
C#
127 lines
5.3 KiB
C#
using System.Security.Claims;
|
|
using System.Text.Json;
|
|
using EnvelopeGenerator.Application.Common.Dto;
|
|
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
|
using EnvelopeGenerator.Application.Documents.Queries;
|
|
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
|
using EnvelopeGenerator.Application.Receivers.Queries;
|
|
using EnvelopeGenerator.Server.Client.Models;
|
|
using EnvelopeGenerator.Server.Client.Models.Constants;
|
|
using EnvelopeGenerator.Server.Extensions;
|
|
using EnvelopeGenerator.Server.Options;
|
|
using MediatR;
|
|
using Microsoft.Extensions.Caching.Distributed;
|
|
using Microsoft.Extensions.Caching.Memory;
|
|
using Microsoft.Extensions.Options;
|
|
using ApplicationEnvelopeReceiverDto = EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver.EnvelopeReceiverDto;
|
|
|
|
namespace EnvelopeGenerator.Server.Services;
|
|
|
|
/// <summary>
|
|
/// Loads receiver page data directly from MediatR and distributed cache.
|
|
/// </summary>
|
|
public class EnvelopeReceiverPageDataService(
|
|
IMediator mediator,
|
|
IDistributedCache cache,
|
|
IOptions<CacheOptions> cacheOptions,
|
|
IMemoryCache memoryCache)
|
|
{
|
|
private const string SignatureCacheKeyPrefix = "envelope-generator.receiver-ui.signature:";
|
|
|
|
/// <summary>
|
|
/// Loads the PDF document bytes for the authenticated receiver.
|
|
/// </summary>
|
|
public async Task<byte[]?> GetDocumentOfReceiverAsync(ClaimsPrincipal user, CancellationToken cancellationToken = default)
|
|
{
|
|
var document = await mediator.Send(new ReadDocumentQuery(EnvelopeId: user.EnvelopeId()), cancellationToken);
|
|
return document.ByteData;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the current receiver's signature placeholders.
|
|
/// </summary>
|
|
public async Task<IReadOnlyList<SignatureDto>> GetSignaturesAsync(ClaimsPrincipal user, CancellationToken cancellationToken = default)
|
|
{
|
|
var receiverId = user.ReceiverId();
|
|
var document = await mediator.Send(new ReadDocumentQuery(EnvelopeId: user.EnvelopeId()), cancellationToken);
|
|
|
|
if (document.Elements is not IEnumerable<DocReceiverElementDto> elements)
|
|
return [];
|
|
|
|
var signatures = elements
|
|
.Where(element => element.ReceiverId == receiverId)
|
|
.Select(MapSignature)
|
|
.ToList();
|
|
|
|
return signatures.Convert(UnitOfLength.Point);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the envelope receiver data for the specified envelope key.
|
|
/// </summary>
|
|
public async Task<ApplicationEnvelopeReceiverDto?> GetEnvelopeReceiverAsync(string envelopeKey, CancellationToken cancellationToken = default)
|
|
{
|
|
var result = await mediator.Send(new ReadEnvelopeReceiverQuery { Key = envelopeKey }, cancellationToken);
|
|
return result.SingleOrDefault();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads the cached signature for the authenticated receiver.
|
|
/// </summary>
|
|
public async Task<SignatureCaptureDto?> GetCachedSignatureAsync(ClaimsPrincipal user, CancellationToken cancellationToken = default)
|
|
{
|
|
var json = await cache.GetStringAsync(GetSignatureCacheKey(user), cancellationToken);
|
|
return json is null ? null : JsonSerializer.Deserialize<SignatureCaptureDto>(json);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves the cached signature for the authenticated receiver.
|
|
/// </summary>
|
|
public async Task SaveCachedSignatureAsync(ClaimsPrincipal user, SignatureCaptureDto signature, CancellationToken cancellationToken = default)
|
|
{
|
|
var json = JsonSerializer.Serialize(signature);
|
|
var options = cacheOptions.Value.SignatureCacheExpiration.HasValue
|
|
? new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = cacheOptions.Value.SignatureCacheExpiration.Value }
|
|
: new DistributedCacheEntryOptions();
|
|
|
|
await cache.SetStringAsync(GetSignatureCacheKey(user), json, options, cancellationToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deletes the cached signature for the authenticated receiver.
|
|
/// </summary>
|
|
public Task DeleteCachedSignatureAsync(ClaimsPrincipal user, CancellationToken cancellationToken = default)
|
|
=> cache.RemoveAsync(GetSignatureCacheKey(user), cancellationToken);
|
|
|
|
private static string GetSignatureCacheKey(ClaimsPrincipal user)
|
|
=> $"{SignatureCacheKeyPrefix}{user.ReceiverSignature()}";
|
|
|
|
private static SignatureDto MapSignature(DocReceiverElementDto element) => new()
|
|
{
|
|
Id = element.Id,
|
|
X = element.X,
|
|
Y = element.Y,
|
|
Page = element.Page,
|
|
SenderAppType = (EnvelopeGenerator.Server.Client.Models.Constants.SenderAppType)element.SenderAppType
|
|
};
|
|
|
|
private static readonly string ReceiverEmailSearchCacheKey = Guid.NewGuid().ToString();
|
|
|
|
public async Task<IEnumerable<string>> SearchReceiverEMailsAsync(string emailSearchTerm, CancellationToken cancellationToken = default)
|
|
{
|
|
|
|
return await memoryCache.GetOrCreateAsync(ReceiverEmailSearchCacheKey + emailSearchTerm, async entry =>
|
|
{
|
|
var query = new ReadReceiverQuery { EmailAddressSearch = emailSearchTerm };
|
|
var receivers = await mediator.Send(query, cancellationToken);
|
|
|
|
if(receivers.Any())
|
|
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30);
|
|
else
|
|
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(10);
|
|
|
|
return receivers.Select(r => r.EmailAddress);
|
|
}) ?? [];
|
|
}
|
|
}
|