Compare commits
2 Commits
223017006b
...
940d129c11
| Author | SHA1 | Date | |
|---|---|---|---|
| 940d129c11 | |||
| 44bbdbb835 |
@@ -86,6 +86,18 @@ public class AuthService(IHttpClientFactory httpClientFactory)
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shares the current envelope in read-only mode for the specified receiver and expiration date.
|
||||
/// Calls POST /api/readonly/{envelopeKey}.
|
||||
/// </summary>
|
||||
public async Task<bool> ShareEnvelopeReadOnlyAsync(string envelopeKey, string receiverMail, DateTime dateValid, CancellationToken cancel = default)
|
||||
{
|
||||
using var http = CreateDefaultClient();
|
||||
var payload = new { receiverMail, dateValid };
|
||||
var response = await http.PostAsJsonAsync($"/api/readonly/{Uri.EscapeDataString(envelopeKey)}", payload, cancel);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the per-envelope receiver cookie for the given envelope key.
|
||||
/// Calls POST /api/auth/logout/envelope/{envelopeKey}.
|
||||
|
||||
@@ -5,12 +5,18 @@
|
||||
@using EnvelopeGenerator.Server.Client.Models
|
||||
@using EnvelopeGenerator.Server.Client.Models.Constants
|
||||
@using EnvelopeGenerator.Server.Client.Services
|
||||
@using EnvelopeGenerator.Application.Common.Extensions
|
||||
@using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver
|
||||
@using EnvelopeGenerator.Application.EnvelopeReceivers.Queries
|
||||
@using EnvelopeGenerator.Domain.Constants
|
||||
@using Microsoft.JSInterop
|
||||
@using DevExpress.Blazor
|
||||
@using System.Drawing
|
||||
@using System.Security.Claims
|
||||
@using System.ComponentModel.DataAnnotations
|
||||
@using Microsoft.Extensions.Caching.Memory
|
||||
@using MediatR
|
||||
@using EnvelopeGenerator.Server.Extensions
|
||||
@inject NavigationManager Navigation
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService
|
||||
@@ -19,6 +25,7 @@
|
||||
@inject AppVersionService AppVersion
|
||||
@inject IMemoryCache MemoryCache
|
||||
@inject ILogger<ReceiverPage> Logger
|
||||
@inject IMediator Mediator
|
||||
@implements IDisposable
|
||||
|
||||
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
||||
@@ -125,6 +132,32 @@
|
||||
<span class="pdf-toolbar__btn-text">Unterschreiben</span>
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (!(_envelopeReceiver?.Envelope?.ReadOnly ?? false))
|
||||
{
|
||||
<button class="pdf-toolbar__btn"
|
||||
@onclick="OpenSharePopup"
|
||||
title="Dokument teilen"
|
||||
style="flex-shrink: 0;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M13.5 1a1.5 1.5 0 1 0 1.415 2H15a1.5 1.5 0 0 0-1.5-2zm-11 5a1.5 1.5 0 1 0 1.415 2H4a1.5 1.5 0 0 0-1.5-2zm11 5a1.5 1.5 0 1 0 1.415 2H15a1.5 1.5 0 0 0-1.5-2z"/>
|
||||
<path d="M2.854 7.646a.5.5 0 0 1 .0-.707l9-5a.5.5 0 1 1 .486.874l-9 5a.5.5 0 0 1-.486-.167zm0 .708a.5.5 0 0 1 .486-.167l9 5a.5.5 0 0 1-.486.874l-9-5a.5.5 0 0 1 0-.707z"/>
|
||||
</svg>
|
||||
<span class="pdf-toolbar__btn-text">Teilen</span>
|
||||
</button>
|
||||
}
|
||||
|
||||
<button class="pdf-toolbar__btn"
|
||||
@onclick="LogoutAsync"
|
||||
disabled="@_isLoggingOut"
|
||||
title="Abmelden"
|
||||
style="flex-shrink: 0;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M10 15a1 1 0 0 0 1-1v-2a.5.5 0 0 1 1 0v2a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v2a.5.5 0 0 1-1 0V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h7z" />
|
||||
<path fill-rule="evenodd" d="M15.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L14.293 7.5H6.5a.5.5 0 0 0 0 1h7.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z" />
|
||||
</svg>
|
||||
<span class="pdf-toolbar__btn-text">@(_isLoggingOut ? "Abmelden..." : "Abmelden")</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -342,6 +375,57 @@
|
||||
</FooterContentTemplate>
|
||||
</DxPopup>
|
||||
|
||||
<DxPopup @bind-Visible="_sharePopupVisible"
|
||||
HeaderText="Dokument teilen"
|
||||
Width="520px"
|
||||
MaxWidth="95vw"
|
||||
ShowFooter="true"
|
||||
CloseOnOutsideClick="true">
|
||||
<BodyContentTemplate>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="rp-share-mail" style="font-size: 0.9rem; font-weight: 500;">E-Mail</label>
|
||||
<input id="rp-share-mail"
|
||||
class="form-control"
|
||||
placeholder="user@mail.com"
|
||||
value="@_shareReceiverMail"
|
||||
@oninput="args => _shareReceiverMail = args.Value?.ToString() ?? string.Empty" />
|
||||
</div>
|
||||
|
||||
<div class="mb-1">
|
||||
<label class="form-label" for="rp-share-date" style="font-size: 0.9rem; font-weight: 500;">Gultig bis</label>
|
||||
<input id="rp-share-date"
|
||||
class="form-control"
|
||||
type="date"
|
||||
min="@DateTime.Today.AddDays(1).ToString("yyyy-MM-dd")"
|
||||
max="@DateTime.Today.AddDays(90).ToString("yyyy-MM-dd")"
|
||||
value="@_shareDateValid.ToString("yyyy-MM-dd")"
|
||||
@oninput="OnShareDateChanged" />
|
||||
</div>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(_shareMessage))
|
||||
{
|
||||
<div class="mt-3 alert @(_shareMessageIsError ? "alert-danger" : "alert-success") mb-0" role="alert">
|
||||
@_shareMessage
|
||||
</div>
|
||||
}
|
||||
</BodyContentTemplate>
|
||||
<FooterContentTemplate>
|
||||
<div class="d-flex justify-content-end gap-2 w-100">
|
||||
<button class="btn btn-outline-secondary"
|
||||
@onclick="CloseSharePopup"
|
||||
disabled="@_isSharing">
|
||||
Schliessen
|
||||
</button>
|
||||
<button class="btn btn-primary"
|
||||
@onclick="ShareEnvelopeAsync"
|
||||
disabled="@_isSharing"
|
||||
style="background: linear-gradient(135deg, #4F46E5 0%, #4338CA 100%); border: none;">
|
||||
@(_isSharing ? "Senden..." : "Senden")
|
||||
</button>
|
||||
</div>
|
||||
</FooterContentTemplate>
|
||||
</DxPopup>
|
||||
|
||||
@code {
|
||||
// ----- Constants -----
|
||||
const string SignatureTabDraw = "draw";
|
||||
@@ -386,6 +470,114 @@
|
||||
string _signerFullName = string.Empty;
|
||||
string _signerPosition = string.Empty;
|
||||
string _signaturePlace = string.Empty;
|
||||
bool _isLoggingOut = false;
|
||||
|
||||
// ----- Share popup state -----
|
||||
bool _sharePopupVisible = false;
|
||||
bool _isSharing = false;
|
||||
string _shareReceiverMail = string.Empty;
|
||||
DateTime _shareDateValid = DateTime.Today.AddDays(7);
|
||||
string? _shareMessage;
|
||||
bool _shareMessageIsError = false;
|
||||
|
||||
async Task LogoutAsync()
|
||||
{
|
||||
if (_isLoggingOut || string.IsNullOrWhiteSpace(EnvelopeKey))
|
||||
return;
|
||||
|
||||
_isLoggingOut = true;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
try
|
||||
{
|
||||
await AuthService.LogoutEnvelopeReceiverAsync(EnvelopeKey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Receiver logout failed for {EnvelopeKey}", EnvelopeKey);
|
||||
}
|
||||
|
||||
Navigation.NavigateTo($"/envelope/login/{Uri.EscapeDataString(EnvelopeKey)}", forceLoad: true);
|
||||
}
|
||||
|
||||
void OpenSharePopup()
|
||||
{
|
||||
_shareReceiverMail = string.Empty;
|
||||
_shareDateValid = DateTime.Today.AddDays(7);
|
||||
_shareMessage = null;
|
||||
_shareMessageIsError = false;
|
||||
_sharePopupVisible = true;
|
||||
}
|
||||
|
||||
void CloseSharePopup()
|
||||
{
|
||||
if (_isSharing)
|
||||
return;
|
||||
|
||||
_sharePopupVisible = false;
|
||||
}
|
||||
|
||||
void OnShareDateChanged(Microsoft.AspNetCore.Components.ChangeEventArgs args)
|
||||
{
|
||||
if (DateTime.TryParse(args.Value?.ToString(), out var parsedDate))
|
||||
_shareDateValid = parsedDate.Date;
|
||||
}
|
||||
|
||||
async Task ShareEnvelopeAsync()
|
||||
{
|
||||
if (_isSharing)
|
||||
return;
|
||||
|
||||
var email = _shareReceiverMail.Trim();
|
||||
if (string.IsNullOrWhiteSpace(email) || !new EmailAddressAttribute().IsValid(email))
|
||||
{
|
||||
_shareMessage = "Bitte geben Sie eine gultige E-Mail-Adresse ein.";
|
||||
_shareMessageIsError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var minDate = DateTime.Today.AddDays(1);
|
||||
var maxDate = DateTime.Today.AddDays(90);
|
||||
if (_shareDateValid.Date < minDate || _shareDateValid.Date > maxDate)
|
||||
{
|
||||
_shareMessage = "Bitte wahlen Sie ein Datum zwischen morgen und 90 Tagen.";
|
||||
_shareMessageIsError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_isSharing = true;
|
||||
_shareMessage = null;
|
||||
_shareMessageIsError = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
try
|
||||
{
|
||||
var shared = await AuthService.ShareEnvelopeReadOnlyAsync(EnvelopeKey!, email, _shareDateValid.Date);
|
||||
if (shared)
|
||||
{
|
||||
_shareMessage = "Dokument wurde erfolgreich als Nur-Lesen freigegeben.";
|
||||
_shareMessageIsError = false;
|
||||
_shareReceiverMail = string.Empty;
|
||||
_shareDateValid = DateTime.Today.AddDays(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
_shareMessage = "Freigabe fehlgeschlagen. Bitte versuchen Sie es erneut.";
|
||||
_shareMessageIsError = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Failed to share envelope in read-only mode for {EnvelopeKey}", EnvelopeKey);
|
||||
_shareMessage = "Freigabe fehlgeschlagen. Bitte versuchen Sie es erneut.";
|
||||
_shareMessageIsError = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isSharing = false;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
// ----- Lifecycle -----
|
||||
protected override async Task OnInitializedAsync()
|
||||
@@ -397,6 +589,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (EnvelopeKey.TryDecode(out var decodedKeys) && decodedKeys.GetEncodeType() == EncodeType.EnvelopeReceiverReadOnly)
|
||||
{
|
||||
Navigation.NavigateTo($"/envelope/readonly/{Uri.EscapeDataString(EnvelopeKey)}", forceLoad: true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Authorization — same pattern as EnvelopeReceiverPage
|
||||
_receiverUser = await ReceiverAuthorizationService.AuthorizeAsync(EnvelopeKey);
|
||||
if (_receiverUser is null)
|
||||
@@ -405,6 +603,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (await Mediator.IsSignedAsync(_receiverUser.EnvelopeUuid(), _receiverUser.ReceiverSignature()))
|
||||
{
|
||||
Navigation.NavigateTo("/envelope/signed-result", forceLoad: true);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Load PDF bytes via MediatR (uses authenticated user's claims)
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
@page "/envelope/readonly/{ReadOnlyKey}"
|
||||
@rendermode InteractiveServer
|
||||
@using DevExpress.Blazor.Reporting
|
||||
@using DevExpress.XtraReports.UI
|
||||
@using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiverReadOnly
|
||||
@using EnvelopeGenerator.Application.Common.Extensions
|
||||
@using EnvelopeGenerator.Application.Common.Interfaces.Services
|
||||
@using EnvelopeGenerator.Domain.Constants
|
||||
@inject EnvelopeGenerator.Server.Client.Services.AppVersionService AppVersion
|
||||
@inject ILogger<ReceiverReadOnlyPage> Logger
|
||||
@inject IEnvelopeReceiverReadOnlyService ReadOnlyService
|
||||
@inject IEnvelopeReceiverService EnvelopeReceiverService
|
||||
@inject IEnvelopeHistoryService HistoryService
|
||||
@implements IDisposable
|
||||
|
||||
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
||||
<link href="_content/DevExpress.Blazor.Reporting.Viewer/css/dx-blazor-reporting-components.bs5.css" rel="stylesheet" />
|
||||
<link href="@AppVersion.GetVersionedUrl("css/envelope-viewer.css")" rel="stylesheet" />
|
||||
|
||||
<div class="envelope-viewer-layout">
|
||||
<div class="envelope-action-bar">
|
||||
<div class="envelope-action-bar__inner" style="padding: 0.5rem 1.25rem;">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:1rem;">
|
||||
<div style="font-weight:600; color:#1f2937;">Dokumentansicht (Nur Lesen)</div>
|
||||
@if (_readOnly is not null)
|
||||
{
|
||||
<div style="font-size:0.8rem; color:#6b7280;">Gultig bis: @_readOnly.DateValid.ToString("dd.MM.yyyy")</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="envelope-content" style="padding:0; overflow:hidden;">
|
||||
@if (_isLoading)
|
||||
{
|
||||
<div class="d-flex justify-content-center align-items-center h-100">
|
||||
<div class="text-center">
|
||||
<div class="spinner-border text-white mb-3" style="width:3.5rem; height:3.5rem;" role="status"></div>
|
||||
<p class="text-white fw-semibold">Dokument wird geladen...</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(_errorMessage))
|
||||
{
|
||||
<div class="error-container">
|
||||
<div class="alert alert-danger shadow-lg mb-0">
|
||||
<h5 class="mb-2">Dokument nicht verfugbar</h5>
|
||||
<p class="mb-0">@_errorMessage</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (_isExpired)
|
||||
{
|
||||
<div class="error-container">
|
||||
<div class="alert alert-warning shadow-lg mb-0">
|
||||
<h5 class="mb-2">Freigabe abgelaufen</h5>
|
||||
<p class="mb-0">Der Zeitraum fur diese Nur-Lesen-Freigabe ist abgelaufen.</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else if (_report is not null)
|
||||
{
|
||||
<DxReportViewer @ref="_reportViewer"
|
||||
Report="_report"
|
||||
RootCssClasses="w-100 h-100" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public string? ReadOnlyKey { get; set; }
|
||||
|
||||
bool _isLoading = true;
|
||||
bool _isExpired = false;
|
||||
string? _errorMessage;
|
||||
EnvelopeReceiverReadOnlyDto? _readOnly;
|
||||
|
||||
DxReportViewer? _reportViewer;
|
||||
XtraReport? _report;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ReadOnlyKey))
|
||||
{
|
||||
_errorMessage = "Freigabe-Schlussel fehlt.";
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ReadOnlyKey.TryDecode(out var decodedKeys) || decodedKeys.GetEncodeType() != EncodeType.EnvelopeReceiverReadOnly)
|
||||
{
|
||||
_errorMessage = "Ungultiger Freigabe-Link.";
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var readOnlyId = decodedKeys.ParseReadOnlyId();
|
||||
var readOnlyRes = await ReadOnlyService.ReadByIdAsync(readOnlyId);
|
||||
if (readOnlyRes.IsFailed)
|
||||
{
|
||||
_errorMessage = "Freigabe konnte nicht geladen werden.";
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_readOnly = readOnlyRes.Data;
|
||||
|
||||
if (DateTime.Now > _readOnly.DateValid)
|
||||
{
|
||||
_isExpired = true;
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (_readOnly.Envelope is null || _readOnly.Receiver is null)
|
||||
{
|
||||
_errorMessage = "Freigabe ist unvollstandig.";
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var erRes = await EnvelopeReceiverService.ReadByUuidSignatureAsync(_readOnly.Envelope.Uuid, _readOnly.Receiver.Signature);
|
||||
if (erRes.IsFailed)
|
||||
{
|
||||
_errorMessage = "Dokument wurde nicht gefunden.";
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var envelopeReceiver = erRes.Data;
|
||||
var documentBytes = envelopeReceiver.Envelope?.Documents?.FirstOrDefault()?.ByteData;
|
||||
if (documentBytes is not { Length: > 0 })
|
||||
{
|
||||
_errorMessage = "Dokumentdaten konnten nicht geladen werden.";
|
||||
_isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_report = BuildReport(documentBytes);
|
||||
|
||||
try
|
||||
{
|
||||
var historyResult = await HistoryService.RecordAsync((int)_readOnly.EnvelopeId, _readOnly.AddedWho, EnvelopeStatus.EnvelopeViewed);
|
||||
if (historyResult.IsFailed)
|
||||
Logger.LogWarning("Failed to record EnvelopeViewed history for read-only key {ReadOnlyKey}", ReadOnlyKey);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Failed to record read-only history for {ReadOnlyKey}", ReadOnlyKey);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Unexpected error in read-only page for {ReadOnlyKey}", ReadOnlyKey);
|
||||
_errorMessage = "Beim Laden ist ein unerwarteter Fehler aufgetreten.";
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
}
|
||||
|
||||
static XtraReport BuildReport(byte[] pdfBytes)
|
||||
{
|
||||
var report = new XtraReport
|
||||
{
|
||||
PaperKind = DevExpress.Drawing.Printing.DXPaperKind.A4,
|
||||
Landscape = false,
|
||||
Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0)
|
||||
};
|
||||
|
||||
var detail = new DetailBand { HeightF = 0f };
|
||||
report.Bands.Add(detail);
|
||||
|
||||
detail.Controls.Add(new XRPdfContent
|
||||
{
|
||||
Source = pdfBytes,
|
||||
GenerateOwnPages = true
|
||||
});
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_report?.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Server.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Redirects legacy envelope key links to Blazor routes.
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
[Route("EnvelopeKey")]
|
||||
public class EnvelopeKeyRedirectController : Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Redirects /EnvelopeKey/{*path} links to /envelope/{path}.
|
||||
/// </summary>
|
||||
[HttpGet("{*path}")]
|
||||
public IActionResult RedirectToEnvelopePath([FromRoute] string path)
|
||||
=> Redirect($"/envelope/{path}");
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
using DigitalData.Core.Abstraction.Application.DTO;
|
||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiverReadOnly;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Server.Extensions;
|
||||
using MediatR;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
@@ -33,24 +35,36 @@ public class ReadOnlyController : ControllerBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new read-only receiver for the current envelope.
|
||||
/// Creates a new read-only receiver for an envelope.
|
||||
/// </summary>
|
||||
/// <param name="envelopeKey">Envelope key (uuid+signature encoded).</param>
|
||||
/// <param name="createDto">Creation payload.</param>
|
||||
[HttpPost]
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost("{envelopeKey}")]
|
||||
[Authorize(Policy = AuthPolicy.SenderOrReceiver)]
|
||||
[Obsolete("Use MediatR")]
|
||||
public async Task<IActionResult> CreateAsync([FromBody] EnvelopeReceiverReadOnlyCreateDto createDto)
|
||||
public async Task<IActionResult> CreateAsync(
|
||||
[FromRoute] string envelopeKey,
|
||||
[FromBody] EnvelopeReceiverReadOnlyCreateDto createDto,
|
||||
[FromServices] IMediator mediator,
|
||||
CancellationToken cancel)
|
||||
{
|
||||
var authReceiverMail = User.ReceiverMail();
|
||||
if (authReceiverMail is null)
|
||||
var envelopeReceiver = await mediator.Send(new ReadEnvelopeReceiverQuery { Key = envelopeKey }, cancel);
|
||||
var authEnvelopeReceiver = envelopeReceiver.FirstOrDefault();
|
||||
|
||||
if (authEnvelopeReceiver?.Envelope is null)
|
||||
return NotFound();
|
||||
|
||||
var addedWho = User.FindFirstValue(ClaimTypes.Email)
|
||||
?? authEnvelopeReceiver.Receiver?.EmailAddress;
|
||||
if (string.IsNullOrWhiteSpace(addedWho))
|
||||
{
|
||||
_logger.LogError("EmailAddress claim is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
|
||||
return Unauthorized();
|
||||
_logger.LogError("Receiver e-mail is missing in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
|
||||
var envelopeId = User.EnvelopeId();
|
||||
var envelopeId = authEnvelopeReceiver.EnvelopeId;
|
||||
|
||||
createDto.AddedWho = authReceiverMail;
|
||||
createDto.AddedWho = addedWho;
|
||||
createDto.EnvelopeId = envelopeId;
|
||||
|
||||
var creationRes = await _readOnlyService.CreateAsync(createDto: createDto);
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
<Authors>Digital Data GmbH</Authors>
|
||||
<Company>Digital Data GmbH</Company>
|
||||
<Product>EnvelopeGenerator.Server</Product>
|
||||
<Version>1.2.0-beta</Version>
|
||||
<FileVersion>1.2.0.0</FileVersion>
|
||||
<AssemblyVersion>1.2.0.0</AssemblyVersion>
|
||||
<Version>1.4.0-beta</Version>
|
||||
<FileVersion>1.4.0.0</FileVersion>
|
||||
<AssemblyVersion>1.4.0.0</AssemblyVersion>
|
||||
<Copyright>Copyright © 2026 Digital Data GmbH. All rights reserved.</Copyright>
|
||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
Reference in New Issue
Block a user