Compare commits
107 Commits
web-multi-
...
6b34b55c4f
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b34b55c4f | |||
| 4a5608249e | |||
|
|
965838513f | ||
|
|
9c4766518e | ||
|
|
292b6b2ccf | ||
|
|
6f9b5d4b13 | ||
|
|
8459706c45 | ||
|
|
972c63388e | ||
|
|
cde9ed06a1 | ||
|
|
d94f885e92 | ||
|
|
028785a8c9 | ||
|
|
e6285f13f7 | ||
| 35b7b1a080 | |||
| 67d0980c63 | |||
| c6a99b56a2 | |||
| 31f5d1f340 | |||
| a2df5d7691 | |||
| f8c586dd31 | |||
| 8aea3c8301 | |||
| 495adb8c31 | |||
| 86c0a65540 | |||
| d2e8f1fc5e | |||
| f8369e350f | |||
| b8a2ad97ef | |||
| ffffc2d470 | |||
| 36b03da084 | |||
| defa53fa26 | |||
| 6134b58a4c | |||
| 5299016b43 | |||
| 55c20e83d8 | |||
| f1a140faa7 | |||
| b20d25e5b9 | |||
| e21eb2c0d6 | |||
| d237b4ab95 | |||
| dff99b163d | |||
| 70fbf31b14 | |||
| 339e0e81cd | |||
| a386ad72bb | |||
| 02c5f286ec | |||
| 5fa358ca79 | |||
| 7233d2ce98 | |||
| 5784cc7a97 | |||
| f31f680f91 | |||
| e7c2d46ef0 | |||
| 85d70c1db4 | |||
| fb340fb08a | |||
| 7d3959ae51 | |||
| 9d4890b10d | |||
| b64f4d71f5 | |||
| b7d146ddb5 | |||
| 6a5c9a3489 | |||
|
|
15f6ee7be0 | ||
|
|
1051c5356f | ||
|
|
7b13350fbf | ||
|
|
2bada327d8 | ||
|
|
a47729ebca | ||
|
|
fcfed963b7 | ||
|
|
b2ace61cd4 | ||
|
|
77cdc83a4e | ||
|
|
a611df4914 | ||
|
|
1341f69ab1 | ||
|
|
0480513288 | ||
|
|
9dbd1b16b5 | ||
|
|
c649c93921 | ||
|
|
1843119b1b | ||
|
|
bc4371cb99 | ||
|
|
05130d6163 | ||
| 567b9c9565 | |||
| b798181f91 | |||
| 7e8fc25ec9 | |||
| db76162697 | |||
| 2b4573ea73 | |||
| 4a043ed247 | |||
| a62a035ec6 | |||
| 1713a65014 | |||
| 695d7c83e0 | |||
| 428f71863d | |||
| cce2f8f90e | |||
|
|
86c9fdfcd7 | ||
|
|
89ec887510 | ||
|
|
7d5b988842 | ||
|
|
3c456562cc | ||
|
|
4d6b01030c | ||
|
|
75e7e9925b | ||
|
|
0a175b9e9d | ||
|
|
f611e74de1 | ||
|
|
08ca116628 | ||
|
|
4997f7d75c | ||
| b5cd42b6fa | |||
| 187f4a42fc | |||
| 23d4b2f31e | |||
| 8e71e5b4bb | |||
| b693615561 | |||
| 36dc9266bc | |||
| 9aabe270b4 | |||
| b303b7be06 | |||
| 02937360ea | |||
| c2735b92e0 | |||
| 568f43186c | |||
| 3bc5439b5a | |||
| 22b494a262 | |||
| 209785dda5 | |||
| 44ea893f05 | |||
| b4aa7984aa | |||
| 7c5a505ad1 | |||
| bd6d57e1e8 | |||
| 8403ce2c6a |
@@ -1,118 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.DTO;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
|
||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
||||
using EnvelopeGenerator.Application.Histories.Queries;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.API.Extensions;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Manages annotations and signature lifecycle for envelopes.
|
||||
/// </summary>
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AnnotationController : ControllerBase
|
||||
{
|
||||
[Obsolete("Use MediatR")]
|
||||
private readonly IEnvelopeHistoryService _historyService;
|
||||
|
||||
[Obsolete("Use MediatR")]
|
||||
private readonly IEnvelopeReceiverService _envelopeReceiverService;
|
||||
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
private readonly ILogger<AnnotationController> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="AnnotationController"/>.
|
||||
/// </summary>
|
||||
[Obsolete("Use MediatR")]
|
||||
public AnnotationController(
|
||||
ILogger<AnnotationController> logger,
|
||||
IEnvelopeHistoryService envelopeHistoryService,
|
||||
IEnvelopeReceiverService envelopeReceiverService,
|
||||
IMediator mediator)
|
||||
{
|
||||
_historyService = envelopeHistoryService;
|
||||
_envelopeReceiverService = envelopeReceiverService;
|
||||
_mediator = mediator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates or updates annotations for the authenticated envelope receiver.
|
||||
/// </summary>
|
||||
/// <param name="psPdfKitAnnotation">Annotation payload.</param>
|
||||
/// <param name="cancel">Cancellation token.</param>
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost]
|
||||
[Obsolete("PSPDF Kit will no longer be used.")]
|
||||
public async Task<IActionResult> CreateOrUpdate([FromBody] PsPdfKitAnnotation? psPdfKitAnnotation = null, CancellationToken cancel = default)
|
||||
{
|
||||
var signature = User.GetReceiverSignatureOfReceiver();
|
||||
var uuid = User.GetEnvelopeUuidOfReceiver();
|
||||
|
||||
var envelopeReceiver = await _mediator.ReadEnvelopeReceiverAsync(uuid, signature, cancel).ThrowIfNull(Exceptions.NotFound);
|
||||
|
||||
if (!envelopeReceiver.Envelope!.ReadOnly && psPdfKitAnnotation is null)
|
||||
return BadRequest();
|
||||
|
||||
if (await _mediator.IsSignedAsync(uuid, signature, cancel))
|
||||
return Problem(statusCode: StatusCodes.Status409Conflict);
|
||||
else if (await _mediator.AnyHistoryAsync(uuid, new[] { EnvelopeStatus.EnvelopeRejected, EnvelopeStatus.DocumentRejected }, cancel))
|
||||
return Problem(statusCode: StatusCodes.Status423Locked);
|
||||
|
||||
var docSignedNotification = await _mediator
|
||||
.ReadEnvelopeReceiverAsync(uuid, signature, cancel)
|
||||
.ToDocSignedNotification(psPdfKitAnnotation)
|
||||
?? throw new NotFoundException("Envelope receiver is not found.");
|
||||
|
||||
await _mediator.PublishSafely(docSignedNotification, cancel);
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rejects the document for the current receiver.
|
||||
/// </summary>
|
||||
/// <param name="reason">Optional rejection reason.</param>
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost("reject")]
|
||||
[Obsolete("Use MediatR")]
|
||||
public async Task<IActionResult> Reject([FromBody] string? reason = null)
|
||||
{
|
||||
var signature = User.GetReceiverSignatureOfReceiver();
|
||||
var uuid = User.GetEnvelopeUuidOfReceiver();
|
||||
var mail = User.GetReceiverMailOfReceiver();
|
||||
|
||||
var envRcvRes = await _envelopeReceiverService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature);
|
||||
|
||||
if (envRcvRes.IsFailed)
|
||||
{
|
||||
_logger.LogNotice(envRcvRes.Notices);
|
||||
return Unauthorized("you are not authorized");
|
||||
}
|
||||
|
||||
var histRes = await _historyService.RecordAsync(envRcvRes.Data.EnvelopeId, userReference: mail, EnvelopeStatus.DocumentRejected, comment: reason);
|
||||
if (histRes.IsSuccess)
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
_logger.LogEnvelopeError(uuid: uuid, signature: signature, message: "Unexpected error happened in api/envelope/reject");
|
||||
_logger.LogNotice(histRes.Notices);
|
||||
return StatusCode(500, histRes.Messages);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
using EnvelopeGenerator.API.Controllers.Interfaces;
|
||||
using EnvelopeGenerator.API.Models;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus.
|
||||
/// </summary>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public partial class AuthController(IOptions<AuthTokenKeys> authTokenKeyOptions, IAuthorizationService authService) : ControllerBase, IAuthController
|
||||
{
|
||||
private readonly AuthTokenKeys authTokenKeys = authTokenKeyOptions.Value;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IAuthorizationService AuthService { get; } = authService;
|
||||
|
||||
/// <summary>
|
||||
/// Entfernt das Authentifizierungs-Cookie des Benutzers (AuthCookie)
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Gibt eine HTTP 200 oder 401.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
///
|
||||
/// POST /api/auth/logout
|
||||
///
|
||||
/// </remarks>
|
||||
/// <response code="200">Erfolgreich gelöscht, wenn der Benutzer ein berechtigtes Cookie hat.</response>
|
||||
/// <response code="401">Wenn es kein zugelassenes Cookie gibt, wird „nicht zugelassen“ zurückgegeben.</response>
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
||||
[Authorize(Policy = AuthPolicy.SenderOrReceiver)]
|
||||
[HttpPost("logout")]
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
if (await this.IsUserInPolicyAsync(AuthPolicy.Sender))
|
||||
Response.Cookies.Delete(authTokenKeys.Cookie);
|
||||
else if (await this.IsUserInPolicyAsync(AuthPolicy.ReceiverOrReceiverTFA))
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
else
|
||||
return Unauthorized();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prüft, ob der Benutzer ein autorisiertes Token hat.
|
||||
/// </summary>
|
||||
/// <returns>Wenn ein autorisiertes Token vorhanden ist HTTP 200 asynchron 401</returns>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
///
|
||||
/// GET /api/auth
|
||||
///
|
||||
/// </remarks>
|
||||
/// <response code="200">Wenn es einen autorisierten Cookie gibt.</response>
|
||||
/// <response code="401">Wenn kein Cookie vorhanden ist oder nicht autorisierte.</response>
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
||||
[HttpGet("check")]
|
||||
[Authorize]
|
||||
public IActionResult Check(string? role = null)
|
||||
=> role is not null && !User.IsInRole(role)
|
||||
? Unauthorized()
|
||||
: Ok();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes configuration data required by the client applications.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of <see cref="ConfigController"/>.
|
||||
/// </remarks>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ConfigController(IOptionsMonitor<AnnotationParams> annotationParamsOptions) : ControllerBase
|
||||
{
|
||||
private readonly AnnotationParams _annotationParams = annotationParamsOptions.CurrentValue;
|
||||
|
||||
/// <summary>
|
||||
/// Returns annotation configuration that was previously rendered by MVC.
|
||||
/// </summary>
|
||||
[HttpGet("Annotations")]
|
||||
[Obsolete("PSPDF Kit will no longer be used.")]
|
||||
public IActionResult GetAnnotationParams()
|
||||
{
|
||||
return Ok(_annotationParams.AnnotationJSObject);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using EnvelopeGenerator.API.Controllers.Interfaces;
|
||||
using EnvelopeGenerator.API.Extensions;
|
||||
using EnvelopeGenerator.Application.Documents.Queries;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to envelope documents for authenticated receivers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initializes a new instance of the <see cref="DocumentController"/> class.
|
||||
/// </remarks>
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class DocumentController(IMediator mediator, IAuthorizationService authService) : ControllerBase, IAuthController
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IAuthorizationService AuthService => authService;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the document bytes receiver.
|
||||
/// </summary>
|
||||
/// <param name="query">Encoded envelope key.</param>
|
||||
/// <param name="cancel">Cancellation token.</param>
|
||||
[HttpGet]
|
||||
[Authorize(Policy = AuthPolicy.SenderOrReceiver)]
|
||||
public async Task<IActionResult> GetDocument(CancellationToken cancel, [FromQuery] ReadDocumentQuery? query = null)
|
||||
{
|
||||
// Sender: expects query with envelope key
|
||||
if (await this.IsUserInPolicyAsync(AuthPolicy.Sender))
|
||||
{
|
||||
if (query is null)
|
||||
return BadRequest("Missing document query.");
|
||||
|
||||
var senderDoc = await mediator.Send(query, cancel);
|
||||
return senderDoc.ByteData is byte[] senderDocByte
|
||||
? File(senderDocByte, "application/octet-stream")
|
||||
: NotFound("Document is empty.");
|
||||
}
|
||||
|
||||
// Receiver: resolve envelope id from claims
|
||||
if (await this.IsUserInPolicyAsync(AuthPolicy.Receiver))
|
||||
{
|
||||
if (query is not null)
|
||||
return BadRequest("Query parameters are not allowed for receiver role.");
|
||||
|
||||
var envelopeId = User.GetEnvelopeIdOfReceiver();
|
||||
var receiverDoc = await mediator.Send(new ReadDocumentQuery { EnvelopeId = envelopeId }, cancel);
|
||||
return receiverDoc.ByteData is byte[] receiverDocByte
|
||||
? File(receiverDocByte, "application/octet-stream")
|
||||
: NotFound("Document is empty.");
|
||||
}
|
||||
|
||||
return Unauthorized();
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Commands;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Queries;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller for managing temp templates.
|
||||
/// Steuerung zur Verwaltung von E-Mail-Vorlagen.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </remarks>
|
||||
/// <param name="mediator">
|
||||
/// Die Mediator-Instanz, die zum Senden von Befehlen und Abfragen verwendet wird.
|
||||
/// </param>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize(Policy = AuthPolicy.Sender)]
|
||||
public class EmailTemplateController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Ruft E-Mail-Vorlagen basierend auf der angegebenen Abfrage ab.
|
||||
/// Gibt alles zurück, wenn keine Id- oder Typ-Informationen eingegeben wurden.
|
||||
/// </summary>
|
||||
/// <param name="emailTemplate">Die Abfrageparameter zum Abrufen von E-Mail-Vorlagen.</param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns>Gibt HTTP-Antwort zurück</returns>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
/// GET /api/EmailTemplate?emailTemplateId=123
|
||||
/// </remarks>
|
||||
/// <response code="200">Wenn die E-Mail-Vorlagen erfolgreich abgerufen werden.</response>
|
||||
/// <response code="400">Wenn die Abfrageparameter ungültig sind.</response>
|
||||
/// <response code="401">Wenn der Benutzer nicht authentifiziert ist.</response>
|
||||
/// <response code="404">Wenn die gesuchte Abfrage nicht gefunden wird.</response>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadEmailTemplateQuery emailTemplate, CancellationToken cancel)
|
||||
{
|
||||
var result = await mediator.Send(emailTemplate, cancel);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an temp template or resets it if no update command is provided.
|
||||
/// Aktualisiert eine E-Mail-Vorlage oder setzt sie zurück, wenn kein Aktualisierungsbefehl angegeben ist.
|
||||
/// </summary>
|
||||
/// <param name="update"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <response code="200">Wenn die E-Mail-Vorlage erfolgreich aktualisiert oder zurückgesetzt wird.</response>
|
||||
/// <response code="400">Wenn die Abfrage ohne einen String gesendet wird.</response>
|
||||
/// <response code="401">Wenn der Benutzer nicht authentifiziert ist.</response>
|
||||
/// <response code="404">Wenn die gesuchte Abfrage nicht gefunden wird.</response>
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> Update([FromBody] UpdateEmailTemplateCommand update, CancellationToken cancel)
|
||||
{
|
||||
await mediator.Send(update, cancel);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using EnvelopeGenerator.API.Extensions;
|
||||
using EnvelopeGenerator.Application.Envelopes.Commands;
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Dieser Controller stellt Endpunkte für die Verwaltung von Umschlägen bereit.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Die API ermöglicht das Abrufen und Verwalten von Umschlägen basierend auf Benutzerinformationen und Statusfiltern.
|
||||
///
|
||||
/// Mögliche Antworten:
|
||||
/// - 200 OK: Die Anfrage war erfolgreich, und die angeforderten Daten werden zurückgegeben.
|
||||
/// - 400 Bad Request: Die Anfrage war fehlerhaft oder unvollständig.
|
||||
/// - 401 Unauthorized: Der Benutzer ist nicht authentifiziert.
|
||||
/// - 403 Forbidden: Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen.
|
||||
/// - 404 Not Found: Die angeforderte Ressource wurde nicht gefunden.
|
||||
/// - 500 Internal Server Error: Ein unerwarteter Fehler ist aufgetreten.
|
||||
/// </remarks>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class EnvelopeController : ControllerBase
|
||||
{
|
||||
private readonly ILogger<EnvelopeController> _logger;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
/// <summary>
|
||||
/// Erstellt eine neue Instanz des EnvelopeControllers.
|
||||
/// </summary>
|
||||
/// <param name="logger">Der Logger, der für das Protokollieren von Informationen verwendet wird.</param>
|
||||
/// <param name="mediator"></param>
|
||||
public EnvelopeController(ILogger<EnvelopeController> logger, IMediator mediator)
|
||||
{
|
||||
_logger = logger;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft eine Liste von Umschlägen basierend auf dem Benutzer und den angegebenen Statusfiltern ab.
|
||||
/// </summary>
|
||||
/// <param name="envelope"></param>
|
||||
/// <returns>Eine IActionResult-Instanz, die die abgerufenen Umschläge oder einen Fehlerstatus enthält.</returns>
|
||||
/// <response code="200">Die Anfrage war erfolgreich, und die Umschläge werden zurückgegeben.</response>
|
||||
/// <response code="400">Die Anfrage war fehlerhaft oder unvollständig.</response>
|
||||
/// <response code="401">Der Benutzer ist nicht authentifiziert.</response>
|
||||
/// <response code="403">Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen.</response>
|
||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||
[Authorize]
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAsync([FromQuery] ReadEnvelopeQuery envelope)
|
||||
{
|
||||
var result = await _mediator.Send(envelope.Authorize(User.GetId()));
|
||||
return result.Any() ? Ok(result) : NotFound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft das Ergebnis eines Dokuments basierend auf der ID ab.
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="view">Gibt an, ob das Dokument inline angezeigt werden soll (true) oder als Download bereitgestellt wird (false).</param>
|
||||
/// <returns>Eine IActionResult-Instanz, die das Dokument oder einen Fehlerstatus enthält.</returns>
|
||||
/// <response code="200">Das Dokument wurde erfolgreich abgerufen.</response>
|
||||
/// <response code="404">Das Dokument wurde nicht gefunden oder ist nicht verfügbar.</response>
|
||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||
[HttpGet("doc-result")]
|
||||
public async Task<IActionResult> GetDocResultAsync([FromQuery] ReadEnvelopeQuery query, [FromQuery] bool view = false)
|
||||
{
|
||||
var envelopes = await _mediator.Send(query.Authorize(User.GetId()));
|
||||
var envelope = envelopes.FirstOrDefault();
|
||||
|
||||
if (envelope is null)
|
||||
return NotFound("Envelope not available.");
|
||||
if (envelope.DocResult is null)
|
||||
return NotFound("The document has not been fully signed or the result has not yet been released.");
|
||||
|
||||
if (view)
|
||||
{
|
||||
Response.Headers.Append("Content-Disposition", "inline; filename=\"" + envelope.Uuid + ".pdf\"");
|
||||
return File(envelope.DocResult, "application/pdf");
|
||||
}
|
||||
|
||||
return File(envelope.DocResult, "application/pdf", $"{envelope.Uuid}.pdf");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
[Authorize]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateAsync([FromBody] CreateEnvelopeCommand command)
|
||||
{
|
||||
var res = await _mediator.Send(command.Authorize(User.GetId()));
|
||||
|
||||
if (res is null)
|
||||
{
|
||||
_logger.LogError("Failed to create envelope. Envelope details: {EnvelopeDetails}", JsonConvert.SerializeObject(command));
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
else
|
||||
return Ok(res);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Application.EnvelopeTypes.Queries;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EnvelopeTypeController : ControllerBase
|
||||
{
|
||||
private readonly ILogger<EnvelopeTypeController> _logger;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="mediator"></param>
|
||||
public EnvelopeTypeController(ILogger<EnvelopeTypeController> logger, IMediator mediator)
|
||||
{
|
||||
_logger = logger;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAllAsync()
|
||||
{
|
||||
var result = await _mediator.Send(new ReadEnvelopeTypesQuery());
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface IAuthController
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
IAuthorizationService AuthService { get; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
ClaimsPrincipal User { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class AuthControllerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="controller"></param>
|
||||
/// <param name="policyName"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> IsUserInPolicyAsync(this IAuthController controller, string policyName)
|
||||
{
|
||||
var result = await controller.AuthService.AuthorizeAsync(controller.User, policyName);
|
||||
return result.Succeeded;
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.DTO;
|
||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiverReadOnly;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.API.Extensions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Manages read-only envelope sharing flows.
|
||||
/// </summary>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ReadOnlyController : ControllerBase
|
||||
{
|
||||
private readonly ILogger<ReadOnlyController> _logger;
|
||||
private readonly IEnvelopeReceiverReadOnlyService _readOnlyService;
|
||||
private readonly IEnvelopeMailService _mailService;
|
||||
private readonly IEnvelopeHistoryService _historyService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReadOnlyController"/> class.
|
||||
/// </summary>
|
||||
public ReadOnlyController(ILogger<ReadOnlyController> logger, IEnvelopeReceiverReadOnlyService readOnlyService, IEnvelopeMailService mailService, IEnvelopeHistoryService historyService)
|
||||
{
|
||||
_logger = logger;
|
||||
_readOnlyService = readOnlyService;
|
||||
_mailService = mailService;
|
||||
_historyService = historyService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new read-only receiver for the current envelope.
|
||||
/// </summary>
|
||||
/// <param name="createDto">Creation payload.</param>
|
||||
[HttpPost]
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[Obsolete("Use MediatR")]
|
||||
public async Task<IActionResult> CreateAsync([FromBody] EnvelopeReceiverReadOnlyCreateDto createDto)
|
||||
{
|
||||
var authReceiverMail = User.GetReceiverMailOfReceiver();
|
||||
if (authReceiverMail is null)
|
||||
{
|
||||
_logger.LogError("EmailAddress claim is not found in envelope-receiver-read-only creation process. Create DTO is:\n {dto}", JsonConvert.SerializeObject(createDto));
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
var envelopeId = User.GetEnvelopeIdOfReceiver();
|
||||
|
||||
createDto.AddedWho = authReceiverMail;
|
||||
createDto.EnvelopeId = envelopeId;
|
||||
|
||||
var creationRes = await _readOnlyService.CreateAsync(createDto: createDto);
|
||||
|
||||
if (creationRes.IsFailed)
|
||||
{
|
||||
_logger.LogNotice(creationRes);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
|
||||
var readRes = await _readOnlyService.ReadByIdAsync(creationRes.Data.Id);
|
||||
if (readRes.IsFailed)
|
||||
{
|
||||
_logger.LogNotice(creationRes);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
|
||||
var newReadOnly = readRes.Data;
|
||||
|
||||
return await _mailService.SendAsync(newReadOnly).ThenAsync<int, IActionResult>(SuccessAsync: async _ =>
|
||||
{
|
||||
var histRes = await _historyService.RecordAsync((int)createDto.EnvelopeId, createDto.AddedWho, EnvelopeStatus.EnvelopeShared);
|
||||
if (histRes.IsFailed)
|
||||
{
|
||||
_logger.LogError("Although the envelope was sent as read-only, the EnvelopeShared history could not be saved. Create DTO:\n{createDto}", JsonConvert.SerializeObject(createDto));
|
||||
_logger.LogNotice(histRes.Notices);
|
||||
}
|
||||
|
||||
return Ok();
|
||||
},
|
||||
|
||||
Fail: (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Application.Receivers.Queries;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller für die Verwaltung von Empfängern.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dieser Controller bietet Endpunkte für das Abrufen von Empfängern basierend auf E-Mail-Adresse oder Signatur.
|
||||
/// </remarks>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ReceiverController : ControllerBase
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz des <see cref="ReceiverController"/>-Controllers.
|
||||
/// </summary>
|
||||
/// <param name="mediator">Mediator für Anfragen.</param>
|
||||
public ReceiverController(IMediator mediator)
|
||||
{
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft eine Liste von Empfängern ab, basierend auf den angegebenen Abfrageparametern.
|
||||
/// </summary>
|
||||
/// <param name="receiver">Die Abfrageparameter, einschließlich E-Mail-Adresse und Signatur.</param>
|
||||
/// <returns>Eine Liste von Empfängern oder ein Fehlerstatus.</returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadReceiverQuery receiver)
|
||||
{
|
||||
if (!receiver.HasAnyCriteria)
|
||||
{
|
||||
var all = await _mediator.Send(new ReadReceiverQuery());
|
||||
return Ok(all);
|
||||
}
|
||||
|
||||
var result = await _mediator.Send(receiver);
|
||||
return result is null ? NotFound() : Ok(result);
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.DTO;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.API.Models;
|
||||
using Ganss.Xss;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace EnvelopeGenerator.API.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes endpoints for registering and managing two-factor authentication for envelope receivers.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/tfa")]
|
||||
public class TfaRegistrationController : ControllerBase
|
||||
{
|
||||
private readonly ILogger<TfaRegistrationController> _logger;
|
||||
private readonly IEnvelopeReceiverService _envelopeReceiverService;
|
||||
private readonly IAuthenticator _authenticator;
|
||||
private readonly IReceiverService _receiverService;
|
||||
private readonly TFARegParams _parameters;
|
||||
private readonly IStringLocalizer<Resource> _localizer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TfaRegistrationController"/> class.
|
||||
/// </summary>
|
||||
public TfaRegistrationController(
|
||||
ILogger<TfaRegistrationController> logger,
|
||||
IEnvelopeReceiverService envelopeReceiverService,
|
||||
IAuthenticator authenticator,
|
||||
IReceiverService receiverService,
|
||||
IOptions<TFARegParams> tfaRegParamsOptions,
|
||||
IStringLocalizer<Resource> localizer)
|
||||
{
|
||||
_logger = logger;
|
||||
_envelopeReceiverService = envelopeReceiverService;
|
||||
_authenticator = authenticator;
|
||||
_receiverService = receiverService;
|
||||
_parameters = tfaRegParamsOptions.Value;
|
||||
_localizer = localizer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates registration metadata (QR code and deadline) for a receiver.
|
||||
/// </summary>
|
||||
/// <param name="envelopeReceiverId">Encoded envelope receiver id.</param>
|
||||
[Authorize]
|
||||
[HttpGet("{envelopeReceiverId}")]
|
||||
public async Task<IActionResult> RegisterAsync(string envelopeReceiverId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (uuid, signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
|
||||
|
||||
if (uuid is null || signature is null)
|
||||
{
|
||||
_logger.LogEnvelopeError(uuid: uuid, signature: signature, message: _localizer.WrongEnvelopeReceiverId());
|
||||
return Unauthorized(new { message = _localizer.WrongEnvelopeReceiverId() });
|
||||
}
|
||||
|
||||
var secretResult = await _envelopeReceiverService.ReadWithSecretByUuidSignatureAsync(uuid: uuid, signature: signature);
|
||||
if (secretResult.IsFailed)
|
||||
{
|
||||
_logger.LogNotice(secretResult.Notices);
|
||||
return NotFound(new { message = _localizer.WrongEnvelopeReceiverId() });
|
||||
}
|
||||
|
||||
var envelopeReceiver = secretResult.Data;
|
||||
|
||||
if (!envelopeReceiver.Envelope!.TFAEnabled)
|
||||
return Unauthorized(new { message = _localizer.WrongAccessCode() });
|
||||
|
||||
var receiver = envelopeReceiver.Receiver;
|
||||
receiver!.TotpSecretkey = _authenticator.GenerateTotpSecretKey();
|
||||
await _receiverService.UpdateAsync(receiver);
|
||||
var totpQr64 = _authenticator.GenerateTotpQrCode(userEmail: receiver.EmailAddress, secretKey: receiver.TotpSecretkey).ToBase64String();
|
||||
|
||||
if (receiver.TfaRegDeadline is null)
|
||||
{
|
||||
receiver.TfaRegDeadline = _parameters.Deadline;
|
||||
await _receiverService.UpdateAsync(receiver);
|
||||
}
|
||||
else if (receiver.TfaRegDeadline <= DateTime.Now)
|
||||
{
|
||||
return StatusCode(StatusCodes.Status410Gone, new { message = _localizer.WrongAccessCode() });
|
||||
}
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
envelopeReceiver.EnvelopeId,
|
||||
envelopeReceiver.Envelope!.Uuid,
|
||||
envelopeReceiver.Receiver!.Signature,
|
||||
receiver.TfaRegDeadline,
|
||||
TotpQR64 = totpQr64
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, exception: ex, message: _localizer.WrongEnvelopeReceiverId());
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, new { message = _localizer.UnexpectedError() });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs out the envelope receiver from cookie authentication.
|
||||
/// </summary>
|
||||
[Authorize(Policy = AuthPolicy.Receiver)]
|
||||
[HttpPost("auth/logout")]
|
||||
public async Task<IActionResult> LogOutAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, new { message = _localizer.UnexpectedError() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using EnvelopeGenerator.API.Models;
|
||||
using Microsoft.OpenApi.Any;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace EnvelopeGenerator.API.Documentation;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public sealed class AuthProxyDocumentFilter : IDocumentFilter
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="swaggerDoc"></param>
|
||||
/// <param name="context"></param>
|
||||
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
|
||||
{
|
||||
const string path = "/api/auth";
|
||||
|
||||
var loginSchema = context.SchemaGenerator.GenerateSchema(typeof(Login), context.SchemaRepository);
|
||||
var loginExample = new OpenApiObject
|
||||
{
|
||||
["password"] = new OpenApiString(""),
|
||||
["username"] = new OpenApiString("")
|
||||
};
|
||||
|
||||
var operation = new OpenApiOperation
|
||||
{
|
||||
Summary = "Proxy login (auth-hub)",
|
||||
Description = "Proxies the request to the auth service. Add query parameter `cookie=true|false`.",
|
||||
Tags = [new() { Name = "Auth" }],
|
||||
Parameters =
|
||||
{
|
||||
new OpenApiParameter
|
||||
{
|
||||
Name = "cookie",
|
||||
In = ParameterLocation.Query,
|
||||
Required = false,
|
||||
Schema = new OpenApiSchema { Type = "boolean", Default = new OpenApiBoolean(true) },
|
||||
Example = new OpenApiBoolean(true),
|
||||
Description = "If true, auth service sets the auth cookie."
|
||||
}
|
||||
},
|
||||
RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Content =
|
||||
{
|
||||
["application/json"] = new OpenApiMediaType { Schema = loginSchema, Example = loginExample },
|
||||
["multipart/form-data"] = new OpenApiMediaType { Schema = loginSchema, Example = loginExample }
|
||||
}
|
||||
},
|
||||
Responses =
|
||||
{
|
||||
["200"] = new OpenApiResponse { Description = "OK (proxied response)" },
|
||||
["401"] = new OpenApiResponse { Description = "Unauthorized" }
|
||||
}
|
||||
};
|
||||
|
||||
swaggerDoc.Paths[path] = new OpenApiPathItem
|
||||
{
|
||||
Operations =
|
||||
{
|
||||
[OperationType.Post] = operation
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace EnvelopeGenerator.API;
|
||||
|
||||
/// <summary>
|
||||
/// Provides custom claim types for envelope-related information.
|
||||
/// </summary>
|
||||
public static class EnvelopeClaimTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Claim type for the title of an envelope.
|
||||
/// </summary>
|
||||
public static readonly string Title = $"Envelope{nameof(Title)}";
|
||||
|
||||
/// <summary>
|
||||
/// Claim type for the ID of an envelope.
|
||||
/// </summary>
|
||||
public static readonly string Id = $"Envelope{nameof(Id)}";
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
|
||||
namespace EnvelopeGenerator.API.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Provides helper methods for working with envelope-specific authentication claims.
|
||||
/// </summary>
|
||||
public static class ReceiverClaimExtensions
|
||||
{
|
||||
private static string GetRequiredClaimOfReceiver(this ClaimsPrincipal user, string claimType)
|
||||
{
|
||||
var value = user.FindFirstValue(claimType);
|
||||
if (value is not null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
var identity = user.Identity;
|
||||
var principalName = identity?.Name ?? "(anonymous)";
|
||||
var authType = identity?.AuthenticationType ?? "(none)";
|
||||
var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}"));
|
||||
var message = $"Required claim '{claimType}' is missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}].";
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated envelope UUID from the claims.
|
||||
/// </summary>
|
||||
public static string GetEnvelopeUuidOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.NameIdentifier);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated receiver signature from the claims.
|
||||
/// </summary>
|
||||
public static string GetReceiverSignatureOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.Hash);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated receiver display name from the claims.
|
||||
/// </summary>
|
||||
public static string GetReceiverNameOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.Name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated receiver email address from the claims.
|
||||
/// </summary>
|
||||
public static string GetReceiverMailOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(ClaimTypes.Email);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated envelope title from the claims.
|
||||
/// </summary>
|
||||
public static string GetEnvelopeTitleOfReceiver(this ClaimsPrincipal user) => user.GetRequiredClaimOfReceiver(EnvelopeClaimTypes.Title);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the authenticated envelope identifier from the claims.
|
||||
/// </summary>
|
||||
public static int GetEnvelopeIdOfReceiver(this ClaimsPrincipal user)
|
||||
{
|
||||
var envIdStr = user.GetRequiredClaimOfReceiver(EnvelopeClaimTypes.Id);
|
||||
if (!int.TryParse(envIdStr, out var envId))
|
||||
{
|
||||
throw new InvalidOperationException($"Claim '{EnvelopeClaimTypes.Id}' is not a valid integer.");
|
||||
}
|
||||
|
||||
return envId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signs in an envelope receiver using cookie authentication and attaches envelope claims.
|
||||
/// </summary>
|
||||
/// <param name="context">The current HTTP context.</param>
|
||||
/// <param name="envelopeReceiver">Envelope receiver DTO to extract claims from.</param>
|
||||
/// <param name="receiverRole">Role to attach to the authentication ticket.</param>
|
||||
public static async Task SignInEnvelopeAsync(this HttpContext context, EnvelopeReceiverDto envelopeReceiver, string receiverRole)
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.NameIdentifier, envelopeReceiver.Envelope!.Uuid),
|
||||
new(ClaimTypes.Hash, envelopeReceiver.Receiver!.Signature),
|
||||
new(ClaimTypes.Name, envelopeReceiver.Name ?? string.Empty),
|
||||
new(ClaimTypes.Email, envelopeReceiver.Receiver.EmailAddress),
|
||||
new(EnvelopeClaimTypes.Title, envelopeReceiver.Envelope.Title),
|
||||
new(EnvelopeClaimTypes.Id, envelopeReceiver.Envelope.Id.ToString()),
|
||||
new(ClaimTypes.Role, receiverRole)
|
||||
};
|
||||
|
||||
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
|
||||
var authProperties = new AuthenticationProperties
|
||||
{
|
||||
AllowRefresh = false,
|
||||
IsPersistent = false
|
||||
};
|
||||
|
||||
await context.SignInAsync(
|
||||
CookieAuthenticationDefaults.AuthenticationScheme,
|
||||
new ClaimsPrincipal(claimsIdentity),
|
||||
authProperties);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace EnvelopeGenerator.API.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for extracting user information from a <see cref="ClaimsPrincipal"/>.
|
||||
/// </summary>
|
||||
public static class SenderClaimExtensions
|
||||
{
|
||||
private static string GetRequiredClaimOfSender(this ClaimsPrincipal user, string claimType)
|
||||
{
|
||||
var value = user.FindFirstValue(claimType);
|
||||
if (value is not null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
var identity = user.Identity;
|
||||
var principalName = identity?.Name ?? "(anonymous)";
|
||||
var authType = identity?.AuthenticationType ?? "(none)";
|
||||
var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}"));
|
||||
var message = $"Required claim '{claimType}' is missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}].";
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
private static string GetRequiredClaimOfSender(this ClaimsPrincipal user, params string[] claimTypes)
|
||||
{
|
||||
string? value = null;
|
||||
|
||||
foreach (var claimType in claimTypes)
|
||||
{
|
||||
value = user.FindFirstValue(claimType);
|
||||
if (value is not null)
|
||||
return value;
|
||||
}
|
||||
|
||||
var identity = user.Identity;
|
||||
var principalName = identity?.Name ?? "(anonymous)";
|
||||
var authType = identity?.AuthenticationType ?? "(none)";
|
||||
var availableClaims = string.Join(", ", user.Claims.Select(c => $"{c.Type}={c.Value}"));
|
||||
var message = $"Required claim among [{string.Join(", ", claimTypes)}] is missing for user '{principalName}' (auth: {authType}). Available claims: [{availableClaims}].";
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user's ID from the claims. Throws an exception if the ID is missing or invalid.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="ClaimsPrincipal"/> representing the user.</param>
|
||||
/// <returns>The user's ID as an integer.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown if the user ID claim is missing or invalid.</exception>
|
||||
public static int GetId(this ClaimsPrincipal user)
|
||||
{
|
||||
var idValue = user.GetRequiredClaimOfSender(ClaimTypes.NameIdentifier, "sub");
|
||||
|
||||
if (!int.TryParse(idValue, out var result))
|
||||
{
|
||||
throw new InvalidOperationException("User ID claim is missing or invalid. This may indicate a misconfigured or forged JWT token.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the username from the claims.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="ClaimsPrincipal"/> representing the user.</param>
|
||||
/// <returns>The username as a string.</returns>
|
||||
public static string GetUsername(this ClaimsPrincipal user)
|
||||
=> user.GetRequiredClaimOfSender(ClaimTypes.Name);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user's surname (last name) from the claims.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="ClaimsPrincipal"/> representing the user.</param>
|
||||
/// <returns>The surname as a string.</returns>
|
||||
public static string GetName(this ClaimsPrincipal user)
|
||||
=> user.GetRequiredClaimOfSender(ClaimTypes.Surname);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user's given name (first name) from the claims.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="ClaimsPrincipal"/> representing the user.</param>
|
||||
/// <returns>The given name as a string.</returns>
|
||||
public static string GetPrename(this ClaimsPrincipal user)
|
||||
=> user.GetRequiredClaimOfSender(ClaimTypes.GivenName);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the user's email address from the claims.
|
||||
/// </summary>
|
||||
/// <param name="user">The <see cref="ClaimsPrincipal"/> representing the user.</param>
|
||||
/// <returns>The email address as a string.</returns>
|
||||
public static string GetEmail(this ClaimsPrincipal user)
|
||||
=> user.GetRequiredClaimOfSender(ClaimTypes.Email);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
public record Auth(string? AccessCode = null, string? SmsCode = null, string? AuthenticatorCode = null, bool UserSelectSMS = default)
|
||||
{
|
||||
public bool HasAccessCode => AccessCode is not null;
|
||||
|
||||
public bool HasSmsCode => SmsCode is not null;
|
||||
|
||||
public bool HasAuthenticatorCode => AuthenticatorCode is not null;
|
||||
|
||||
public bool HasMulti => new[] { HasAccessCode, HasSmsCode, HasAuthenticatorCode }.Count(state => state) > 1;
|
||||
|
||||
public bool HasNone => !(HasAccessCode || HasSmsCode || HasAuthenticatorCode);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a hyperlink for contact purposes with various HTML attributes.
|
||||
/// </summary>
|
||||
public class ContactLink
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the label of the hyperlink.
|
||||
/// </summary>
|
||||
public string Label { get; init; } = "Contact";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the URL that the hyperlink points to.
|
||||
/// </summary>
|
||||
public string Href { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target where the hyperlink should open.
|
||||
/// Commonly used values are "_blank", "_self", "_parent", "_top".
|
||||
/// </summary>
|
||||
public string Target { get; set; } = "_blank";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the relationship of the linked URL as space-separated link types.
|
||||
/// Examples include "nofollow", "noopener", "noreferrer".
|
||||
/// </summary>
|
||||
public string Rel { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the filename that should be downloaded when clicking the hyperlink.
|
||||
/// This attribute will only have an effect if the href attribute is set.
|
||||
/// </summary>
|
||||
public string Download { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the language of the linked resource. Useful when linking to
|
||||
/// content in another language.
|
||||
/// </summary>
|
||||
public string HrefLang { get; set; } = "en";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the MIME type of the linked URL. Helps browsers to handle
|
||||
/// the type correctly when the link is clicked.
|
||||
/// </summary>
|
||||
public string Type { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets additional information about the hyperlink, typically viewed
|
||||
/// as a tooltip when the mouse hovers over the link.
|
||||
/// </summary>
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an identifier for the hyperlink, unique within the HTML document.
|
||||
/// </summary>
|
||||
public string Id { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
public class Culture
|
||||
{
|
||||
private string _language = string.Empty;
|
||||
public string Language { get => _language;
|
||||
init {
|
||||
_language = value;
|
||||
Info = new(value);
|
||||
}
|
||||
}
|
||||
public string FIClass { get; init; } = string.Empty;
|
||||
|
||||
public CultureInfo? Info { get; init; }
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
public class Cultures : List<Culture>
|
||||
{
|
||||
public IEnumerable<string> Languages => this.Select(c => c.Language);
|
||||
|
||||
public IEnumerable<string> FIClasses => this.Select(c => c.FIClass);
|
||||
|
||||
public Culture Default => this.First();
|
||||
|
||||
public Culture? this[string? language] => language is null ? null : this.Where(c => c.Language == language).FirstOrDefault();
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
public class CustomImages : Dictionary<string, Image>
|
||||
{
|
||||
public new Image this[string key] => TryGetValue(key, out var img) && img is not null ? img : new();
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
public class ErrorViewModel
|
||||
{
|
||||
public string Title { get; init; } = "404";
|
||||
|
||||
public string Subtitle { get; init; } = "Hmmm...";
|
||||
|
||||
public string Body { get; init; } = "It looks like one of the developers fell asleep";
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
public class Image
|
||||
{
|
||||
public string Src { get; init; } = string.Empty;
|
||||
|
||||
public Dictionary<string, string> Classes { get; init; } = new();
|
||||
|
||||
public string GetClassIn(string page) => Classes.TryGetValue(page, out var cls) && cls is not null ? cls : string.Empty;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
public class MainViewModel
|
||||
{
|
||||
public string? Title { get; init; }
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
using EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
|
||||
public record Annotation : IAnnotation
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
|
||||
#region Bound Annotation
|
||||
[JsonIgnore]
|
||||
public string? HorBoundAnnotName { get; init; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string? VerBoundAnnotName { get; init; }
|
||||
#endregion
|
||||
|
||||
#region Layout
|
||||
[JsonIgnore]
|
||||
public double? MarginLeft { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public double MarginLeftRatio { get; init; } = 1;
|
||||
|
||||
[JsonIgnore]
|
||||
public double? MarginTop { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public double MarginTopRatio { get; init; } = 1;
|
||||
|
||||
public double? Width { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public double WidthRatio { get; init; } = 1;
|
||||
|
||||
public double? Height { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public double HeightRatio { get; init; } = 1;
|
||||
#endregion
|
||||
|
||||
#region Position
|
||||
public double Left => (MarginLeft ?? 0) + (HorBoundAnnot?.HorBoundary ?? 0);
|
||||
|
||||
public double Top => (MarginTop ?? 0) + (VerBoundAnnot?.VerBoundary ?? 0);
|
||||
#endregion
|
||||
|
||||
#region Boundary
|
||||
[JsonIgnore]
|
||||
public double HorBoundary => Left + (Width ?? 0);
|
||||
|
||||
[JsonIgnore]
|
||||
public double VerBoundary => Top + (Height ?? 0);
|
||||
#endregion
|
||||
|
||||
#region BoundAnnot
|
||||
[JsonIgnore]
|
||||
public Annotation? HorBoundAnnot { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Annotation? VerBoundAnnot { get; set; }
|
||||
#endregion
|
||||
|
||||
public Color? BackgroundColor { get; init; }
|
||||
|
||||
#region Border
|
||||
public Color? BorderColor { get; init; }
|
||||
|
||||
public string? BorderStyle { get; init; }
|
||||
|
||||
public int? BorderWidth { get; set; }
|
||||
#endregion
|
||||
|
||||
[JsonIgnore]
|
||||
internal Annotation Default
|
||||
{
|
||||
set
|
||||
{
|
||||
// To set null value, annotation must have null (0) value but null must has non-null value
|
||||
if (MarginLeft == null && value.MarginLeft != null)
|
||||
MarginLeft = value.MarginLeft * MarginLeftRatio;
|
||||
|
||||
if (MarginTop == null && value.MarginTop != null)
|
||||
MarginTop = value.MarginTop * MarginTopRatio;
|
||||
|
||||
if (Width == null && value.Width != null)
|
||||
Width = value.Width * WidthRatio;
|
||||
|
||||
if (Height == null && value.Height != null)
|
||||
Height = value.Height * HeightRatio;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,80 +0,0 @@
|
||||
using EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
|
||||
public class AnnotationParams
|
||||
{
|
||||
public AnnotationParams()
|
||||
{
|
||||
_AnnotationJSObjectInitor = new(CreateAnnotationJSObject);
|
||||
}
|
||||
|
||||
public Background? Background { get; init; }
|
||||
|
||||
#region Annotation
|
||||
[JsonIgnore]
|
||||
public Annotation? DefaultAnnotation { get; init; }
|
||||
|
||||
private readonly List<Annotation> _annots = new List<Annotation>();
|
||||
|
||||
public bool TryGet(string name, out Annotation annotation)
|
||||
{
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
annotation = _annots.FirstOrDefault(a => a.Name == name);
|
||||
#pragma warning restore CS8601 // Possible null reference assignment.
|
||||
return annotation is not null;
|
||||
}
|
||||
|
||||
public required IEnumerable<Annotation> Annotations
|
||||
{
|
||||
get => _annots;
|
||||
init
|
||||
{
|
||||
_annots = value.ToList();
|
||||
|
||||
if (DefaultAnnotation is not null)
|
||||
foreach (var annot in _annots)
|
||||
annot.Default = DefaultAnnotation;
|
||||
|
||||
for (int i = 0; i < _annots.Count; i++)
|
||||
{
|
||||
#region set bound annotations
|
||||
// horizontal
|
||||
if (_annots[i].HorBoundAnnotName is string horBoundAnnotName)
|
||||
if (TryGet(horBoundAnnotName, out var horBoundAnnot))
|
||||
_annots[i].HorBoundAnnot = horBoundAnnot;
|
||||
else
|
||||
throw new InvalidOperationException($"{horBoundAnnotName} added as bound anotation. However, it is not defined.");
|
||||
|
||||
// vertical
|
||||
if (_annots[i].VerBoundAnnotName is string verBoundAnnotName)
|
||||
if (TryGet(verBoundAnnotName, out var verBoundAnnot))
|
||||
_annots[i].VerBoundAnnot = verBoundAnnot;
|
||||
else
|
||||
throw new InvalidOperationException($"{verBoundAnnotName} added as bound anotation. However, it is not defined.");
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AnnotationJSObject
|
||||
private Dictionary<string, IAnnotation> CreateAnnotationJSObject()
|
||||
{
|
||||
var dict = _annots.ToDictionary(a => a.Name.ToLower(), a => a as IAnnotation);
|
||||
|
||||
if (Background is not null)
|
||||
{
|
||||
Background.Locate(_annots);
|
||||
dict.Add(Background.Name.ToLower(), Background);
|
||||
}
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
private readonly Lazy<Dictionary<string, IAnnotation>> _AnnotationJSObjectInitor;
|
||||
|
||||
public Dictionary<string, IAnnotation> AnnotationJSObject => _AnnotationJSObjectInitor.Value;
|
||||
#endregion
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
|
||||
/// <summary>
|
||||
/// The Background is an annotation for the PSPDF Kit. However, it has no function.
|
||||
/// It is only the first annotation as a background for other annotations.
|
||||
/// </summary>
|
||||
public record Background : IAnnotation
|
||||
{
|
||||
[JsonIgnore]
|
||||
public double Margin { get; init; }
|
||||
|
||||
public string Name { get; } = "Background";
|
||||
|
||||
public double? Width { get; set; }
|
||||
|
||||
public double? Height { get; set; }
|
||||
|
||||
public double Left { get; set; }
|
||||
|
||||
public double Top { get; set; }
|
||||
|
||||
public Color? BackgroundColor { get; init; }
|
||||
|
||||
#region Border
|
||||
public Color? BorderColor { get; init; }
|
||||
|
||||
public string? BorderStyle { get; init; }
|
||||
|
||||
public int? BorderWidth { get; set; }
|
||||
#endregion
|
||||
|
||||
public void Locate(IEnumerable<IAnnotation> annotations)
|
||||
{
|
||||
// set Top
|
||||
if (annotations.MinBy(a => a.Top)?.Top is double minTop)
|
||||
Top = minTop;
|
||||
|
||||
// set Left
|
||||
if (annotations.MinBy(a => a.Left)?.Left is double minLeft)
|
||||
Left = minLeft;
|
||||
|
||||
// set Width
|
||||
if(annotations.MaxBy(a => a.GetRight())?.GetRight() is double maxRight)
|
||||
Width = maxRight - Left;
|
||||
|
||||
// set Height
|
||||
if (annotations.MaxBy(a => a.GetBottom())?.GetBottom() is double maxBottom)
|
||||
Height = maxBottom - Top;
|
||||
|
||||
// add margins
|
||||
Top -= Margin;
|
||||
Left -= Margin;
|
||||
Width += Margin * 2;
|
||||
Height += Margin * 2;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
|
||||
public record Color
|
||||
{
|
||||
public int R { get; init; } = 0;
|
||||
|
||||
public int G { get; init; } = 0;
|
||||
|
||||
public int B { get; init; } = 0;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
|
||||
public static class Extensions
|
||||
{
|
||||
public static double GetRight(this IAnnotation annotation) => annotation.Left + annotation?.Width ?? 0;
|
||||
|
||||
public static double GetBottom(this IAnnotation annotation) => annotation.Top + annotation?.Height ?? 0;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models.PsPdfKitAnnotation;
|
||||
|
||||
public interface IAnnotation
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
double? Width { get; }
|
||||
|
||||
double? Height { get; }
|
||||
|
||||
double Left { get; }
|
||||
|
||||
double Top { get; }
|
||||
|
||||
Color? BackgroundColor { get; }
|
||||
|
||||
Color? BorderColor { get; }
|
||||
|
||||
string? BorderStyle { get; }
|
||||
|
||||
int? BorderWidth { get; }
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace EnvelopeGenerator.API.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the parameters for two-factor authentication (2FA) registration.
|
||||
/// </summary>
|
||||
public class TFARegParams
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum allowed time for completing the registration process.
|
||||
/// </summary>
|
||||
public TimeSpan TimeLimit { get; init; } = new(0, 30, 0);
|
||||
|
||||
/// <summary>
|
||||
/// The deadline for registration, calculated as the current time plus the <see cref="TimeLimit"/>.
|
||||
/// </summary>
|
||||
public DateTime Deadline => DateTime.Now.AddTicks(TimeLimit.Ticks);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"ReverseProxy": {
|
||||
"Routes": {
|
||||
"auth-login": {
|
||||
"ClusterId": "auth-hub",
|
||||
"Match": {
|
||||
"Path": "/api/auth",
|
||||
"Methods": [ "POST" ]
|
||||
},
|
||||
"Transforms": [
|
||||
{ "PathSet": "/api/auth/sign-flow" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"Clusters": {
|
||||
"auth-hub": {
|
||||
"Destinations": {
|
||||
"primary": {
|
||||
"Address": "http://172.24.12.39:9090"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>EnvelopeGenerator.Application.VB</RootNamespace>
|
||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DevExpress.Data" Version="25.1.6" />
|
||||
<PackageReference Include="DevExpress.Reporting.Core" Version="25.1.6" />
|
||||
<PackageReference Include="DevExpress.Win" Version="25.1.6" />
|
||||
<PackageReference Include="DevExpress.Xpo" Version="25.1.6" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Reports\rptEnvelopeHistory.vb">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
730
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.Designer.vb
generated
Normal file
730
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.Designer.vb
generated
Normal file
@@ -0,0 +1,730 @@
|
||||
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
|
||||
Partial Public Class rptEnvelopeHistory
|
||||
Inherits DevExpress.XtraReports.UI.XtraReport
|
||||
|
||||
'XtraReport overrides dispose to clean up the component list.
|
||||
<System.Diagnostics.DebuggerNonUserCode()> _
|
||||
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
|
||||
If disposing AndAlso components IsNot Nothing Then
|
||||
components.Dispose()
|
||||
End If
|
||||
MyBase.Dispose(disposing)
|
||||
End Sub
|
||||
|
||||
'Required by the Designer
|
||||
Private components As System.ComponentModel.IContainer
|
||||
|
||||
'NOTE: The following procedure is required by the Designer
|
||||
'It can be modified using the Designer.
|
||||
'Do not modify it using the code editor.
|
||||
<System.Diagnostics.DebuggerStepThrough()> _
|
||||
Private Sub InitializeComponent()
|
||||
Me.components = New System.ComponentModel.Container()
|
||||
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(rptEnvelopeHistory))
|
||||
Me.TopMargin = New DevExpress.XtraReports.UI.TopMarginBand()
|
||||
Me.BottomMargin = New DevExpress.XtraReports.UI.BottomMarginBand()
|
||||
Me.XrLabel1 = New DevExpress.XtraReports.UI.XRLabel()
|
||||
Me.pageInfo1 = New DevExpress.XtraReports.UI.XRPageInfo()
|
||||
Me.pageInfo2 = New DevExpress.XtraReports.UI.XRPageInfo()
|
||||
Me.ReportHeader = New DevExpress.XtraReports.UI.ReportHeaderBand()
|
||||
Me.label1 = New DevExpress.XtraReports.UI.XRLabel()
|
||||
Me.XrTable3 = New DevExpress.XtraReports.UI.XRTable()
|
||||
Me.XrTableRow8 = New DevExpress.XtraReports.UI.XRTableRow()
|
||||
Me.XrTableCell13 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell15 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableRow9 = New DevExpress.XtraReports.UI.XRTableRow()
|
||||
Me.XrTableCell14 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell17 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell16 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell18 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableRow10 = New DevExpress.XtraReports.UI.XRTableRow()
|
||||
Me.XrTableCell19 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell20 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell21 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell22 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableRow11 = New DevExpress.XtraReports.UI.XRTableRow()
|
||||
Me.XrTableCell23 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell24 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell25 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.XrTableCell26 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.GroupHeader1 = New DevExpress.XtraReports.UI.GroupHeaderBand()
|
||||
Me.table1 = New DevExpress.XtraReports.UI.XRTable()
|
||||
Me.tableRow1 = New DevExpress.XtraReports.UI.XRTableRow()
|
||||
Me.tableCell1 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.tableCell2 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.tableCell3 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.Detail = New DevExpress.XtraReports.UI.DetailBand()
|
||||
Me.table2 = New DevExpress.XtraReports.UI.XRTable()
|
||||
Me.tableRow2 = New DevExpress.XtraReports.UI.XRTableRow()
|
||||
Me.tableCell4 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.tableCell5 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.tableCell6 = New DevExpress.XtraReports.UI.XRTableCell()
|
||||
Me.Title = New DevExpress.XtraReports.UI.XRControlStyle()
|
||||
Me.DetailCaption1 = New DevExpress.XtraReports.UI.XRControlStyle()
|
||||
Me.DetailData1 = New DevExpress.XtraReports.UI.XRControlStyle()
|
||||
Me.DetailData3_Odd = New DevExpress.XtraReports.UI.XRControlStyle()
|
||||
Me.PageInfo = New DevExpress.XtraReports.UI.XRControlStyle()
|
||||
Me.GalleryDropDown1 = New DevExpress.XtraBars.Ribbon.GalleryDropDown(Me.components)
|
||||
Me.ObjectDataSource1 = New DevExpress.DataAccess.ObjectBinding.ObjectDataSource(Me.components)
|
||||
CType(Me.XrTable3, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.table1, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.table2, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.GalleryDropDown1, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me.ObjectDataSource1, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
CType(Me, System.ComponentModel.ISupportInitialize).BeginInit()
|
||||
'
|
||||
'TopMargin
|
||||
'
|
||||
Me.TopMargin.Dpi = 254.0!
|
||||
Me.TopMargin.HeightF = 190.6042!
|
||||
Me.TopMargin.Name = "TopMargin"
|
||||
'
|
||||
'BottomMargin
|
||||
'
|
||||
Me.BottomMargin.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.XrLabel1, Me.pageInfo1, Me.pageInfo2})
|
||||
Me.BottomMargin.Dpi = 254.0!
|
||||
Me.BottomMargin.Name = "BottomMargin"
|
||||
'
|
||||
'XrLabel1
|
||||
'
|
||||
Me.XrLabel1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.XrLabel1.Borders = DevExpress.XtraPrinting.BorderSide.Top
|
||||
Me.XrLabel1.Dpi = 254.0!
|
||||
Me.XrLabel1.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold)
|
||||
Me.XrLabel1.LocationFloat = New DevExpress.Utils.PointFloat(896.5417!, 0!)
|
||||
Me.XrLabel1.Name = "XrLabel1"
|
||||
Me.XrLabel1.Padding = New DevExpress.XtraPrinting.PaddingInfo(0, 0, 0, 0, 254.0!)
|
||||
Me.XrLabel1.SizeF = New System.Drawing.SizeF(645.5836!, 58.0!)
|
||||
Me.XrLabel1.StyleName = "Title"
|
||||
Me.XrLabel1.StylePriority.UseBorderColor = False
|
||||
Me.XrLabel1.StylePriority.UseBorders = False
|
||||
Me.XrLabel1.StylePriority.UseFont = False
|
||||
Me.XrLabel1.StylePriority.UsePadding = False
|
||||
Me.XrLabel1.Text = "Erstellt mit SignFlow"
|
||||
'
|
||||
'pageInfo1
|
||||
'
|
||||
Me.pageInfo1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.pageInfo1.Borders = DevExpress.XtraPrinting.BorderSide.Top
|
||||
Me.pageInfo1.Dpi = 254.0!
|
||||
Me.pageInfo1.LocationFloat = New DevExpress.Utils.PointFloat(0!, 0!)
|
||||
Me.pageInfo1.Name = "pageInfo1"
|
||||
Me.pageInfo1.PageInfo = DevExpress.XtraPrinting.PageInfo.DateTime
|
||||
Me.pageInfo1.SizeF = New System.Drawing.SizeF(896.5417!, 58.0!)
|
||||
Me.pageInfo1.StyleName = "PageInfo"
|
||||
Me.pageInfo1.StylePriority.UseBorderColor = False
|
||||
Me.pageInfo1.StylePriority.UseBorders = False
|
||||
Me.pageInfo1.TextFormatString = "{0:dddd, d. MMMM yyyy HH:mm}"
|
||||
'
|
||||
'pageInfo2
|
||||
'
|
||||
Me.pageInfo2.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.pageInfo2.Borders = DevExpress.XtraPrinting.BorderSide.Top
|
||||
Me.pageInfo2.Dpi = 254.0!
|
||||
Me.pageInfo2.LocationFloat = New DevExpress.Utils.PointFloat(1542.125!, 0!)
|
||||
Me.pageInfo2.Name = "pageInfo2"
|
||||
Me.pageInfo2.SizeF = New System.Drawing.SizeF(357.875!, 58.0!)
|
||||
Me.pageInfo2.StyleName = "PageInfo"
|
||||
Me.pageInfo2.StylePriority.UseBorderColor = False
|
||||
Me.pageInfo2.StylePriority.UseBorders = False
|
||||
Me.pageInfo2.TextAlignment = DevExpress.XtraPrinting.TextAlignment.TopRight
|
||||
Me.pageInfo2.TextFormatString = "Seite {0} von {1}"
|
||||
'
|
||||
'ReportHeader
|
||||
'
|
||||
Me.ReportHeader.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.label1, Me.XrTable3})
|
||||
Me.ReportHeader.Dpi = 254.0!
|
||||
Me.ReportHeader.HeightF = 406.0843!
|
||||
Me.ReportHeader.Name = "ReportHeader"
|
||||
'
|
||||
'label1
|
||||
'
|
||||
Me.label1.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
|
||||
Me.label1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.label1.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
|
||||
Me.label1.BorderWidth = 2.0!
|
||||
Me.label1.Dpi = 254.0!
|
||||
Me.label1.Font = New System.Drawing.Font("Segoe UI", 14.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.label1.ForeColor = System.Drawing.Color.Black
|
||||
Me.label1.LocationFloat = New DevExpress.Utils.PointFloat(0.0002422333!, 0!)
|
||||
Me.label1.Name = "label1"
|
||||
Me.label1.Padding = New DevExpress.XtraPrinting.PaddingInfo(10, 10, 5, 5, 254.0!)
|
||||
Me.label1.SizeF = New System.Drawing.SizeF(1900.0!, 77.32857!)
|
||||
Me.label1.StyleName = "Title"
|
||||
Me.label1.StylePriority.UseBackColor = False
|
||||
Me.label1.StylePriority.UseBorderColor = False
|
||||
Me.label1.StylePriority.UseBorders = False
|
||||
Me.label1.StylePriority.UseBorderWidth = False
|
||||
Me.label1.StylePriority.UseFont = False
|
||||
Me.label1.StylePriority.UseForeColor = False
|
||||
Me.label1.StylePriority.UsePadding = False
|
||||
Me.label1.Text = "Signierungszertifikat"
|
||||
'
|
||||
'XrTable3
|
||||
'
|
||||
Me.XrTable3.Dpi = 254.0!
|
||||
Me.XrTable3.LocationFloat = New DevExpress.Utils.PointFloat(0.0002422333!, 96.60422!)
|
||||
Me.XrTable3.Name = "XrTable3"
|
||||
Me.XrTable3.OddStyleName = "DetailData3_Odd"
|
||||
Me.XrTable3.Rows.AddRange(New DevExpress.XtraReports.UI.XRTableRow() {Me.XrTableRow8, Me.XrTableRow9, Me.XrTableRow10, Me.XrTableRow11})
|
||||
Me.XrTable3.SizeF = New System.Drawing.SizeF(1900.0!, 284.4801!)
|
||||
'
|
||||
'XrTableRow8
|
||||
'
|
||||
Me.XrTableRow8.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell13, Me.XrTableCell15})
|
||||
Me.XrTableRow8.Dpi = 254.0!
|
||||
Me.XrTableRow8.Name = "XrTableRow8"
|
||||
Me.XrTableRow8.Weight = 1.0R
|
||||
'
|
||||
'XrTableCell13
|
||||
'
|
||||
Me.XrTableCell13.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
|
||||
Me.XrTableCell13.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.XrTableCell13.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
|
||||
Me.XrTableCell13.BorderWidth = 1.0!
|
||||
Me.XrTableCell13.Dpi = 254.0!
|
||||
Me.XrTableCell13.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell13.Name = "XrTableCell13"
|
||||
Me.XrTableCell13.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell13.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell13.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell13.StylePriority.UseBorders = False
|
||||
Me.XrTableCell13.StylePriority.UseBorderWidth = False
|
||||
Me.XrTableCell13.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell13.Text = "Ersteller"
|
||||
Me.XrTableCell13.Weight = 0.38139956730411484R
|
||||
'
|
||||
'XrTableCell15
|
||||
'
|
||||
Me.XrTableCell15.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
|
||||
Me.XrTableCell15.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.XrTableCell15.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
|
||||
Me.XrTableCell15.BorderWidth = 1.0!
|
||||
Me.XrTableCell15.Dpi = 254.0!
|
||||
Me.XrTableCell15.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell15.Name = "XrTableCell15"
|
||||
Me.XrTableCell15.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell15.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell15.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell15.StylePriority.UseBorders = False
|
||||
Me.XrTableCell15.StylePriority.UseBorderWidth = False
|
||||
Me.XrTableCell15.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell15.Text = "Umschlag"
|
||||
Me.XrTableCell15.Weight = 0.49859081604996847R
|
||||
'
|
||||
'XrTableRow9
|
||||
'
|
||||
Me.XrTableRow9.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell14, Me.XrTableCell17, Me.XrTableCell16, Me.XrTableCell18})
|
||||
Me.XrTableRow9.Dpi = 254.0!
|
||||
Me.XrTableRow9.Name = "XrTableRow9"
|
||||
Me.XrTableRow9.Weight = 1.0R
|
||||
'
|
||||
'XrTableCell14
|
||||
'
|
||||
Me.XrTableCell14.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell14.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell14.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell14.Dpi = 254.0!
|
||||
Me.XrTableCell14.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell14.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell14.Multiline = True
|
||||
Me.XrTableCell14.Name = "XrTableCell14"
|
||||
Me.XrTableCell14.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell14.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell14.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell14.StylePriority.UseBorders = False
|
||||
Me.XrTableCell14.StylePriority.UseFont = False
|
||||
Me.XrTableCell14.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell14.Text = "Name"
|
||||
Me.XrTableCell14.Weight = 0.11578820509129036R
|
||||
'
|
||||
'XrTableCell17
|
||||
'
|
||||
Me.XrTableCell17.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell17.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell17.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell17.Dpi = 254.0!
|
||||
Me.XrTableCell17.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[User].[FullName]")})
|
||||
Me.XrTableCell17.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell17.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell17.Multiline = True
|
||||
Me.XrTableCell17.Name = "XrTableCell17"
|
||||
Me.XrTableCell17.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell17.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell17.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell17.StylePriority.UseBorders = False
|
||||
Me.XrTableCell17.StylePriority.UseFont = False
|
||||
Me.XrTableCell17.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell17.Text = "XrTableCell17"
|
||||
Me.XrTableCell17.Weight = 0.2656113622128245R
|
||||
'
|
||||
'XrTableCell16
|
||||
'
|
||||
Me.XrTableCell16.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell16.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell16.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell16.Dpi = 254.0!
|
||||
Me.XrTableCell16.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell16.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell16.Multiline = True
|
||||
Me.XrTableCell16.Name = "XrTableCell16"
|
||||
Me.XrTableCell16.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell16.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell16.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell16.StylePriority.UseBorders = False
|
||||
Me.XrTableCell16.StylePriority.UseFont = False
|
||||
Me.XrTableCell16.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell16.Text = "Titel"
|
||||
Me.XrTableCell16.Weight = 0.11578821158083684R
|
||||
'
|
||||
'XrTableCell18
|
||||
'
|
||||
Me.XrTableCell18.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell18.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell18.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell18.Dpi = 254.0!
|
||||
Me.XrTableCell18.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[Title]")})
|
||||
Me.XrTableCell18.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell18.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell18.Multiline = True
|
||||
Me.XrTableCell18.Name = "XrTableCell18"
|
||||
Me.XrTableCell18.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell18.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell18.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell18.StylePriority.UseBorders = False
|
||||
Me.XrTableCell18.StylePriority.UseFont = False
|
||||
Me.XrTableCell18.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell18.Text = "XrTableCell18"
|
||||
Me.XrTableCell18.Weight = 0.38280260446913167R
|
||||
'
|
||||
'XrTableRow10
|
||||
'
|
||||
Me.XrTableRow10.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell19, Me.XrTableCell20, Me.XrTableCell21, Me.XrTableCell22})
|
||||
Me.XrTableRow10.Dpi = 254.0!
|
||||
Me.XrTableRow10.Name = "XrTableRow10"
|
||||
Me.XrTableRow10.Weight = 1.0R
|
||||
'
|
||||
'XrTableCell19
|
||||
'
|
||||
Me.XrTableCell19.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell19.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell19.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell19.Dpi = 254.0!
|
||||
Me.XrTableCell19.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell19.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell19.Multiline = True
|
||||
Me.XrTableCell19.Name = "XrTableCell19"
|
||||
Me.XrTableCell19.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell19.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell19.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell19.StylePriority.UseBorders = False
|
||||
Me.XrTableCell19.StylePriority.UseFont = False
|
||||
Me.XrTableCell19.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell19.Text = "EmailAddress"
|
||||
Me.XrTableCell19.Weight = 0.11578820509129036R
|
||||
'
|
||||
'XrTableCell20
|
||||
'
|
||||
Me.XrTableCell20.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell20.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell20.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell20.Dpi = 254.0!
|
||||
Me.XrTableCell20.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[User].[EmailAddress]")})
|
||||
Me.XrTableCell20.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell20.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell20.Multiline = True
|
||||
Me.XrTableCell20.Name = "XrTableCell20"
|
||||
Me.XrTableCell20.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell20.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell20.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell20.StylePriority.UseBorders = False
|
||||
Me.XrTableCell20.StylePriority.UseFont = False
|
||||
Me.XrTableCell20.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell20.Text = "XrTableCell20"
|
||||
Me.XrTableCell20.Weight = 0.2656113622128245R
|
||||
'
|
||||
'XrTableCell21
|
||||
'
|
||||
Me.XrTableCell21.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell21.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell21.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell21.Dpi = 254.0!
|
||||
Me.XrTableCell21.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell21.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell21.Multiline = True
|
||||
Me.XrTableCell21.Name = "XrTableCell21"
|
||||
Me.XrTableCell21.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell21.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell21.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell21.StylePriority.UseBorders = False
|
||||
Me.XrTableCell21.StylePriority.UseFont = False
|
||||
Me.XrTableCell21.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell21.Text = "Umschlag-ID"
|
||||
Me.XrTableCell21.Weight = 0.11578821158083684R
|
||||
'
|
||||
'XrTableCell22
|
||||
'
|
||||
Me.XrTableCell22.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell22.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell22.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell22.Dpi = 254.0!
|
||||
Me.XrTableCell22.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[Uuid]")})
|
||||
Me.XrTableCell22.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell22.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell22.Multiline = True
|
||||
Me.XrTableCell22.Name = "XrTableCell22"
|
||||
Me.XrTableCell22.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell22.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell22.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell22.StylePriority.UseBorders = False
|
||||
Me.XrTableCell22.StylePriority.UseFont = False
|
||||
Me.XrTableCell22.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell22.Text = "XrTableCell22"
|
||||
Me.XrTableCell22.Weight = 0.38280260446913167R
|
||||
'
|
||||
'XrTableRow11
|
||||
'
|
||||
Me.XrTableRow11.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.XrTableCell23, Me.XrTableCell24, Me.XrTableCell25, Me.XrTableCell26})
|
||||
Me.XrTableRow11.Dpi = 254.0!
|
||||
Me.XrTableRow11.Name = "XrTableRow11"
|
||||
Me.XrTableRow11.Weight = 1.0R
|
||||
'
|
||||
'XrTableCell23
|
||||
'
|
||||
Me.XrTableCell23.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell23.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell23.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell23.Dpi = 254.0!
|
||||
Me.XrTableCell23.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell23.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell23.Multiline = True
|
||||
Me.XrTableCell23.Name = "XrTableCell23"
|
||||
Me.XrTableCell23.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell23.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell23.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell23.StylePriority.UseBorders = False
|
||||
Me.XrTableCell23.StylePriority.UseFont = False
|
||||
Me.XrTableCell23.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell23.Weight = 0.11578820509129036R
|
||||
'
|
||||
'XrTableCell24
|
||||
'
|
||||
Me.XrTableCell24.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell24.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell24.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell24.Dpi = 254.0!
|
||||
Me.XrTableCell24.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell24.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell24.Multiline = True
|
||||
Me.XrTableCell24.Name = "XrTableCell24"
|
||||
Me.XrTableCell24.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell24.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell24.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell24.StylePriority.UseBorders = False
|
||||
Me.XrTableCell24.StylePriority.UseFont = False
|
||||
Me.XrTableCell24.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell24.Weight = 0.2656113622128245R
|
||||
'
|
||||
'XrTableCell25
|
||||
'
|
||||
Me.XrTableCell25.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell25.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell25.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell25.Dpi = 254.0!
|
||||
Me.XrTableCell25.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell25.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell25.Multiline = True
|
||||
Me.XrTableCell25.Name = "XrTableCell25"
|
||||
Me.XrTableCell25.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell25.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell25.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell25.StylePriority.UseBorders = False
|
||||
Me.XrTableCell25.StylePriority.UseFont = False
|
||||
Me.XrTableCell25.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell25.Text = "Zertifizierung"
|
||||
Me.XrTableCell25.Weight = 0.11578821158083684R
|
||||
'
|
||||
'XrTableCell26
|
||||
'
|
||||
Me.XrTableCell26.BackColor = System.Drawing.Color.White
|
||||
Me.XrTableCell26.BorderColor = System.Drawing.Color.Empty
|
||||
Me.XrTableCell26.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.XrTableCell26.Dpi = 254.0!
|
||||
Me.XrTableCell26.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[Envelope].[CertificationType]")})
|
||||
Me.XrTableCell26.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
|
||||
Me.XrTableCell26.ForeColor = System.Drawing.Color.Black
|
||||
Me.XrTableCell26.Multiline = True
|
||||
Me.XrTableCell26.Name = "XrTableCell26"
|
||||
Me.XrTableCell26.StyleName = "DetailCaption1"
|
||||
Me.XrTableCell26.StylePriority.UseBackColor = False
|
||||
Me.XrTableCell26.StylePriority.UseBorderColor = False
|
||||
Me.XrTableCell26.StylePriority.UseBorders = False
|
||||
Me.XrTableCell26.StylePriority.UseFont = False
|
||||
Me.XrTableCell26.StylePriority.UseForeColor = False
|
||||
Me.XrTableCell26.Text = "XrTableCell26"
|
||||
Me.XrTableCell26.Weight = 0.38280260446913161R
|
||||
'
|
||||
'GroupHeader1
|
||||
'
|
||||
Me.GroupHeader1.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.table1})
|
||||
Me.GroupHeader1.Dpi = 254.0!
|
||||
Me.GroupHeader1.GroupUnion = DevExpress.XtraReports.UI.GroupUnion.WithFirstDetail
|
||||
Me.GroupHeader1.HeightF = 71.12!
|
||||
Me.GroupHeader1.Name = "GroupHeader1"
|
||||
'
|
||||
'table1
|
||||
'
|
||||
Me.table1.Dpi = 254.0!
|
||||
Me.table1.LocationFloat = New DevExpress.Utils.PointFloat(0!, 0!)
|
||||
Me.table1.Name = "table1"
|
||||
Me.table1.Rows.AddRange(New DevExpress.XtraReports.UI.XRTableRow() {Me.tableRow1})
|
||||
Me.table1.SizeF = New System.Drawing.SizeF(1900.0!, 71.12!)
|
||||
'
|
||||
'tableRow1
|
||||
'
|
||||
Me.tableRow1.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.tableCell1, Me.tableCell2, Me.tableCell3})
|
||||
Me.tableRow1.Dpi = 254.0!
|
||||
Me.tableRow1.Name = "tableRow1"
|
||||
Me.tableRow1.Weight = 1.0R
|
||||
'
|
||||
'tableCell1
|
||||
'
|
||||
Me.tableCell1.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
|
||||
Me.tableCell1.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.tableCell1.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
|
||||
Me.tableCell1.BorderWidth = 1.0!
|
||||
Me.tableCell1.Dpi = 254.0!
|
||||
Me.tableCell1.ForeColor = System.Drawing.Color.Black
|
||||
Me.tableCell1.Name = "tableCell1"
|
||||
Me.tableCell1.StyleName = "DetailCaption1"
|
||||
Me.tableCell1.StylePriority.UseBackColor = False
|
||||
Me.tableCell1.StylePriority.UseBorderColor = False
|
||||
Me.tableCell1.StylePriority.UseBorders = False
|
||||
Me.tableCell1.StylePriority.UseBorderWidth = False
|
||||
Me.tableCell1.StylePriority.UseForeColor = False
|
||||
Me.tableCell1.Text = "Ereignis"
|
||||
Me.tableCell1.Weight = 0.51726482588176181R
|
||||
'
|
||||
'tableCell2
|
||||
'
|
||||
Me.tableCell2.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
|
||||
Me.tableCell2.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.tableCell2.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
|
||||
Me.tableCell2.BorderWidth = 1.0!
|
||||
Me.tableCell2.Dpi = 254.0!
|
||||
Me.tableCell2.ForeColor = System.Drawing.Color.Black
|
||||
Me.tableCell2.Name = "tableCell2"
|
||||
Me.tableCell2.StyleName = "DetailCaption1"
|
||||
Me.tableCell2.StylePriority.UseBackColor = False
|
||||
Me.tableCell2.StylePriority.UseBorderColor = False
|
||||
Me.tableCell2.StylePriority.UseBorders = False
|
||||
Me.tableCell2.StylePriority.UseBorderWidth = False
|
||||
Me.tableCell2.StylePriority.UseForeColor = False
|
||||
Me.tableCell2.Text = "Benutzer"
|
||||
Me.tableCell2.Weight = 0.45140669898958585R
|
||||
'
|
||||
'tableCell3
|
||||
'
|
||||
Me.tableCell3.BackColor = System.Drawing.Color.FromArgb(CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer), CType(CType(224, Byte), Integer))
|
||||
Me.tableCell3.BorderColor = System.Drawing.Color.FromArgb(CType(CType(165, Byte), Integer), CType(CType(36, Byte), Integer), CType(CType(49, Byte), Integer))
|
||||
Me.tableCell3.Borders = DevExpress.XtraPrinting.BorderSide.Bottom
|
||||
Me.tableCell3.BorderWidth = 1.0!
|
||||
Me.tableCell3.Dpi = 254.0!
|
||||
Me.tableCell3.ForeColor = System.Drawing.Color.Black
|
||||
Me.tableCell3.Name = "tableCell3"
|
||||
Me.tableCell3.StyleName = "DetailCaption1"
|
||||
Me.tableCell3.StylePriority.UseBackColor = False
|
||||
Me.tableCell3.StylePriority.UseBorderColor = False
|
||||
Me.tableCell3.StylePriority.UseBorders = False
|
||||
Me.tableCell3.StylePriority.UseBorderWidth = False
|
||||
Me.tableCell3.StylePriority.UseForeColor = False
|
||||
Me.tableCell3.Text = "Zeitstempel"
|
||||
Me.tableCell3.Weight = 0.22479583469004233R
|
||||
'
|
||||
'Detail
|
||||
'
|
||||
Me.Detail.Controls.AddRange(New DevExpress.XtraReports.UI.XRControl() {Me.table2})
|
||||
Me.Detail.Dpi = 254.0!
|
||||
Me.Detail.HeightF = 86.174!
|
||||
Me.Detail.HierarchyPrintOptions.Indent = 50.8!
|
||||
Me.Detail.Name = "Detail"
|
||||
'
|
||||
'table2
|
||||
'
|
||||
Me.table2.Dpi = 254.0!
|
||||
Me.table2.LocationFloat = New DevExpress.Utils.PointFloat(0!, 0!)
|
||||
Me.table2.Name = "table2"
|
||||
Me.table2.Rows.AddRange(New DevExpress.XtraReports.UI.XRTableRow() {Me.tableRow2})
|
||||
Me.table2.SizeF = New System.Drawing.SizeF(1900.0!, 63.42!)
|
||||
'
|
||||
'tableRow2
|
||||
'
|
||||
Me.tableRow2.Cells.AddRange(New DevExpress.XtraReports.UI.XRTableCell() {Me.tableCell4, Me.tableCell5, Me.tableCell6})
|
||||
Me.tableRow2.Dpi = 254.0!
|
||||
Me.tableRow2.Name = "tableRow2"
|
||||
Me.tableRow2.Weight = 11.683999633789062R
|
||||
'
|
||||
'tableCell4
|
||||
'
|
||||
Me.tableCell4.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.tableCell4.Dpi = 254.0!
|
||||
Me.tableCell4.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[ItemStatusTranslated]")})
|
||||
Me.tableCell4.Name = "tableCell4"
|
||||
Me.tableCell4.StyleName = "DetailData1"
|
||||
Me.tableCell4.StylePriority.UseBorders = False
|
||||
Me.tableCell4.Weight = 0.51726482142156094R
|
||||
'
|
||||
'tableCell5
|
||||
'
|
||||
Me.tableCell5.Dpi = 254.0!
|
||||
Me.tableCell5.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[ItemUserReference]")})
|
||||
Me.tableCell5.Name = "tableCell5"
|
||||
Me.tableCell5.StyleName = "DetailData1"
|
||||
Me.tableCell5.Weight = 0.45140669932916544R
|
||||
'
|
||||
'tableCell6
|
||||
'
|
||||
Me.tableCell6.Dpi = 254.0!
|
||||
Me.tableCell6.ExpressionBindings.AddRange(New DevExpress.XtraReports.UI.ExpressionBinding() {New DevExpress.XtraReports.UI.ExpressionBinding("BeforePrint", "Text", "[ItemDate]")})
|
||||
Me.tableCell6.Name = "tableCell6"
|
||||
Me.tableCell6.StyleName = "DetailData1"
|
||||
Me.tableCell6.StylePriority.UseTextAlignment = False
|
||||
Me.tableCell6.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleRight
|
||||
Me.tableCell6.Weight = 0.22479581593269077R
|
||||
'
|
||||
'Title
|
||||
'
|
||||
Me.Title.BackColor = System.Drawing.Color.Transparent
|
||||
Me.Title.BorderColor = System.Drawing.Color.Black
|
||||
Me.Title.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.Title.BorderWidth = 1.0!
|
||||
Me.Title.Font = New System.Drawing.Font("Arial", 14.25!)
|
||||
Me.Title.ForeColor = System.Drawing.Color.FromArgb(CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer))
|
||||
Me.Title.Name = "Title"
|
||||
Me.Title.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
|
||||
'
|
||||
'DetailCaption1
|
||||
'
|
||||
Me.DetailCaption1.BackColor = System.Drawing.Color.FromArgb(CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer))
|
||||
Me.DetailCaption1.BorderColor = System.Drawing.Color.White
|
||||
Me.DetailCaption1.Borders = DevExpress.XtraPrinting.BorderSide.Left
|
||||
Me.DetailCaption1.BorderWidth = 2.0!
|
||||
Me.DetailCaption1.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold)
|
||||
Me.DetailCaption1.ForeColor = System.Drawing.Color.White
|
||||
Me.DetailCaption1.Name = "DetailCaption1"
|
||||
Me.DetailCaption1.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
|
||||
Me.DetailCaption1.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
|
||||
'
|
||||
'DetailData1
|
||||
'
|
||||
Me.DetailData1.BorderColor = System.Drawing.Color.Transparent
|
||||
Me.DetailData1.Borders = DevExpress.XtraPrinting.BorderSide.Left
|
||||
Me.DetailData1.BorderWidth = 2.0!
|
||||
Me.DetailData1.Font = New System.Drawing.Font("Arial", 8.25!)
|
||||
Me.DetailData1.ForeColor = System.Drawing.Color.Black
|
||||
Me.DetailData1.Name = "DetailData1"
|
||||
Me.DetailData1.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
|
||||
Me.DetailData1.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
|
||||
'
|
||||
'DetailData3_Odd
|
||||
'
|
||||
Me.DetailData3_Odd.BackColor = System.Drawing.Color.FromArgb(CType(CType(231, Byte), Integer), CType(CType(231, Byte), Integer), CType(CType(231, Byte), Integer))
|
||||
Me.DetailData3_Odd.BorderColor = System.Drawing.Color.Transparent
|
||||
Me.DetailData3_Odd.Borders = DevExpress.XtraPrinting.BorderSide.None
|
||||
Me.DetailData3_Odd.BorderWidth = 1.0!
|
||||
Me.DetailData3_Odd.Font = New System.Drawing.Font("Arial", 8.25!)
|
||||
Me.DetailData3_Odd.ForeColor = System.Drawing.Color.Black
|
||||
Me.DetailData3_Odd.Name = "DetailData3_Odd"
|
||||
Me.DetailData3_Odd.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
|
||||
Me.DetailData3_Odd.TextAlignment = DevExpress.XtraPrinting.TextAlignment.MiddleLeft
|
||||
'
|
||||
'PageInfo
|
||||
'
|
||||
Me.PageInfo.Font = New System.Drawing.Font("Arial", 8.25!, System.Drawing.FontStyle.Bold)
|
||||
Me.PageInfo.ForeColor = System.Drawing.Color.FromArgb(CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer), CType(CType(75, Byte), Integer))
|
||||
Me.PageInfo.Name = "PageInfo"
|
||||
Me.PageInfo.Padding = New DevExpress.XtraPrinting.PaddingInfo(15, 15, 0, 0, 254.0!)
|
||||
'
|
||||
'GalleryDropDown1
|
||||
'
|
||||
Me.GalleryDropDown1.Manager = Nothing
|
||||
Me.GalleryDropDown1.Name = "GalleryDropDown1"
|
||||
'
|
||||
'ObjectDataSource1
|
||||
'
|
||||
Me.ObjectDataSource1.DataMember = "Items"
|
||||
'Me.ObjectDataSource1.DataSource = GetType(EnvelopeGenerator.CommonServices.ReportSource)
|
||||
Me.ObjectDataSource1.Name = "ObjectDataSource1"
|
||||
'
|
||||
'rptEnvelopeHistory
|
||||
'
|
||||
Me.Bands.AddRange(New DevExpress.XtraReports.UI.Band() {Me.TopMargin, Me.BottomMargin, Me.ReportHeader, Me.GroupHeader1, Me.Detail})
|
||||
Me.ComponentStorage.AddRange(New System.ComponentModel.IComponent() {Me.ObjectDataSource1})
|
||||
Me.DataSource = Me.ObjectDataSource1
|
||||
Me.Dpi = 254.0!
|
||||
Me.Font = New System.Drawing.Font("Arial", 9.75!)
|
||||
Me.Margins = New System.Drawing.Printing.Margins(100, 100, 191, 100)
|
||||
Me.PageHeight = 2970
|
||||
Me.PageWidth = 2100
|
||||
Me.PaperKind = System.Drawing.Printing.PaperKind.A4
|
||||
Me.ReportUnit = DevExpress.XtraReports.UI.ReportUnit.TenthsOfAMillimeter
|
||||
Me.SnapGridSize = 25.0!
|
||||
Me.StyleSheet.AddRange(New DevExpress.XtraReports.UI.XRControlStyle() {Me.Title, Me.DetailCaption1, Me.DetailData1, Me.DetailData3_Odd, Me.PageInfo})
|
||||
Me.Version = "21.2"
|
||||
Me.Watermark.ImageSource = New DevExpress.XtraPrinting.Drawing.ImageSource("img", resources.GetString("rptEnvelopeHistory.Watermark.ImageSource"))
|
||||
Me.Watermark.ImageTransparency = 220
|
||||
CType(Me.XrTable3, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
CType(Me.table1, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
CType(Me.table2, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
CType(Me.GalleryDropDown1, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
CType(Me.ObjectDataSource1, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
CType(Me, System.ComponentModel.ISupportInitialize).EndInit()
|
||||
|
||||
End Sub
|
||||
|
||||
Friend WithEvents TopMargin As DevExpress.XtraReports.UI.TopMarginBand
|
||||
Friend WithEvents BottomMargin As DevExpress.XtraReports.UI.BottomMarginBand
|
||||
Friend WithEvents pageInfo1 As DevExpress.XtraReports.UI.XRPageInfo
|
||||
Friend WithEvents pageInfo2 As DevExpress.XtraReports.UI.XRPageInfo
|
||||
Friend WithEvents ReportHeader As DevExpress.XtraReports.UI.ReportHeaderBand
|
||||
Friend WithEvents label1 As DevExpress.XtraReports.UI.XRLabel
|
||||
Friend WithEvents GroupHeader1 As DevExpress.XtraReports.UI.GroupHeaderBand
|
||||
Friend WithEvents table1 As DevExpress.XtraReports.UI.XRTable
|
||||
Friend WithEvents tableRow1 As DevExpress.XtraReports.UI.XRTableRow
|
||||
Friend WithEvents tableCell1 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents tableCell2 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents tableCell3 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents Detail As DevExpress.XtraReports.UI.DetailBand
|
||||
Friend WithEvents table2 As DevExpress.XtraReports.UI.XRTable
|
||||
Friend WithEvents tableRow2 As DevExpress.XtraReports.UI.XRTableRow
|
||||
Friend WithEvents tableCell4 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents tableCell5 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents tableCell6 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents ObjectDataSource1 As DevExpress.DataAccess.ObjectBinding.ObjectDataSource
|
||||
Friend WithEvents Title As DevExpress.XtraReports.UI.XRControlStyle
|
||||
Friend WithEvents DetailCaption1 As DevExpress.XtraReports.UI.XRControlStyle
|
||||
Friend WithEvents DetailData1 As DevExpress.XtraReports.UI.XRControlStyle
|
||||
Friend WithEvents DetailData3_Odd As DevExpress.XtraReports.UI.XRControlStyle
|
||||
Friend WithEvents PageInfo As DevExpress.XtraReports.UI.XRControlStyle
|
||||
Friend WithEvents XrLabel1 As DevExpress.XtraReports.UI.XRLabel
|
||||
Friend WithEvents XrTable3 As DevExpress.XtraReports.UI.XRTable
|
||||
Friend WithEvents XrTableRow8 As DevExpress.XtraReports.UI.XRTableRow
|
||||
Friend WithEvents XrTableCell13 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell15 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableRow9 As DevExpress.XtraReports.UI.XRTableRow
|
||||
Friend WithEvents XrTableCell14 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell17 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell16 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell18 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableRow10 As DevExpress.XtraReports.UI.XRTableRow
|
||||
Friend WithEvents XrTableCell19 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell20 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell21 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell22 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableRow11 As DevExpress.XtraReports.UI.XRTableRow
|
||||
Friend WithEvents XrTableCell23 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell24 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell25 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents XrTableCell26 As DevExpress.XtraReports.UI.XRTableCell
|
||||
Friend WithEvents GalleryDropDown1 As DevExpress.XtraBars.Ribbon.GalleryDropDown
|
||||
End Class
|
||||
129
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.resx
Normal file
129
EnvelopeGenerator.Application.VB/Reports/rptEnvelopeHistory.resx
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
Public Class rptEnvelopeHistory
|
||||
|
||||
End Class
|
||||
@@ -1,36 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Commands;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand"></typeparam>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public class CreateCommandHandler<TCommand, TEntity> : IRequestHandler<TCommand, TEntity>
|
||||
where TCommand : class, IRequest<TEntity>
|
||||
where TEntity : class
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected readonly IRepository<TEntity> Repository;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public CreateCommandHandler(IRepository<TEntity> repository)
|
||||
{
|
||||
Repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public Task<TEntity> Handle(TCommand request, CancellationToken cancel) => Repository.CreateAsync(request, cancel);
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using MediatR;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Commands;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="TUpdateDto"></typeparam>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public abstract record UpdateCommand<TUpdateDto, TEntity> : IRequest where TUpdateDto : class where TEntity : class
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public TUpdateDto Update { get; init; } = null!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract Expression<Func<TEntity, bool>> BuildQueryExpression();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="TCommand"></typeparam>
|
||||
/// <typeparam name="TUpdateDto"></typeparam>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public class UpdateCommandHandler<TCommand, TUpdateDto, TEntity> : IRequestHandler<TCommand>
|
||||
where TUpdateDto : class
|
||||
where TEntity : class
|
||||
where TCommand : UpdateCommand<TUpdateDto, TEntity>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected readonly IRepository<TEntity> Repository;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public UpdateCommandHandler(IRepository<TEntity> repository)
|
||||
{
|
||||
Repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public Task Handle(TCommand request, CancellationToken cancel)
|
||||
=> Repository.UpdateAsync(request.Update, request.BuildQueryExpression(), cancel);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class GdPictureParams
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string License { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class PDFBurnerParams : ITextStyle
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ConcurrencyLimit { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<string> IgnoredLabels { get; set; } = new List<string>
|
||||
{
|
||||
"Date", "Datum", "ZIP", "PLZ", "Place", "Ort", "Position", "Stellung"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
||||
public double TopMargin { get; set; } = 0.1;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public double YOffset { get; set; } = -0.3;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string FontName { get; set; } = "Arial";
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int FontSize { get; set; } = 8;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public FontStyle FontStyle { get; set; } = FontStyle.Italic;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Dictionary<string, int> IndexOfAnnot { get; init; } = new()
|
||||
{
|
||||
{ string.Empty, 0 },
|
||||
{ "seal", 0 },
|
||||
{ "position", 1 },
|
||||
{ "city", 2 },
|
||||
{ "date", 3 }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int DefaultIndexOfAnnot { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public int GetAnnotationIndex(string name) => IndexOfAnnot.TryGetValue(name, out var value) ? value : DefaultIndexOfAnnot;
|
||||
}
|
||||
@@ -1,42 +1,31 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record EmailTemplateDto
|
||||
namespace EnvelopeGenerator.Application.Common.Dto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EmailTemplateDto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Id{ get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name { get; set; } = null!;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required string Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage hinzugefügt wurde.
|
||||
/// </summary>
|
||||
public DateTime AddedWhen { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required string Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Inhalt (Body) der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Betreff der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Subject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Sprachcode der E-Mail-Vorlage.
|
||||
/// </summary>
|
||||
public string LangCode { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage zuletzt geändert wurde. Kann null sein.
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
};
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required string Subject { get; set; }
|
||||
};
|
||||
}
|
||||
@@ -74,11 +74,6 @@ public record EnvelopeDto
|
||||
/// </summary>
|
||||
public int? EnvelopeTypeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool ReadOnly => EnvelopeTypeId == 2;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -87,7 +82,7 @@ public record EnvelopeDto
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool UseAccessCode { get; set; } = true;
|
||||
public bool? UseAccessCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record EnvelopeReportDto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int EnvelopeId { get; set; }
|
||||
|
||||
// --- HEAD ---
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string HeadUuid { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string EnvelopeTitle { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string HeadMessage { get; set; } = null!;
|
||||
|
||||
// --- POSITIONS ---
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ItemStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime? ItemDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ItemUserReference { get; set; } = null!;
|
||||
}
|
||||
@@ -28,14 +28,16 @@ public class MappingProfile : Profile
|
||||
CreateMap<EmailTemplate, EmailTemplateDto>();
|
||||
CreateMap<Envelope, EnvelopeDto>();
|
||||
CreateMap<Document, DocumentDto>();
|
||||
CreateMap<Domain.Entities.History, HistoryDto>().ForMember(dest => dest.ActionDate, opt => opt.MapFrom(src => src.ChangedWhen));
|
||||
CreateMap<Domain.Entities.History, HistoryCreateDto>().ForMember(dest => dest.ActionDate, opt => opt.MapFrom(src => src.ChangedWhen));
|
||||
CreateMap<Domain.Entities.History, HistoryDto>();
|
||||
CreateMap<Domain.Entities.History, HistoryCreateDto>();
|
||||
CreateMap<Domain.Entities.EnvelopeReceiver, EnvelopeReceiverDto>();
|
||||
CreateMap<Domain.Entities.EnvelopeReceiver, EnvelopeReceiverSecretDto>();
|
||||
CreateMap<EnvelopeType, EnvelopeTypeDto>();
|
||||
CreateMap<Domain.Entities.Receiver, ReceiverDto>();
|
||||
CreateMap<Domain.Entities.EnvelopeReceiverReadOnly, EnvelopeReceiverReadOnlyDto>();
|
||||
CreateMap<ElementAnnotation, AnnotationDto>();
|
||||
CreateMap<ThirdPartyModule, ThirdPartyModuleDto>();
|
||||
CreateMap<EnvelopeReport, EnvelopeReportDto>();
|
||||
|
||||
// DTO to Entity mappings
|
||||
CreateMap<ConfigDto, Config>();
|
||||
@@ -44,15 +46,15 @@ public class MappingProfile : Profile
|
||||
CreateMap<EmailTemplateDto, EmailTemplate>();
|
||||
CreateMap<EnvelopeDto, Envelope>();
|
||||
CreateMap<DocumentDto, Document>();
|
||||
CreateMap<HistoryDto, Domain.Entities.History>().ForMember(dest => dest.ChangedWhen, opt => opt.MapFrom(src => src.ActionDate));
|
||||
CreateMap<HistoryCreateDto, Domain.Entities.History>().ForMember(dest => dest.ChangedWhen, opt => opt.MapFrom(src => src.ActionDate));
|
||||
CreateMap<HistoryDto, Domain.Entities.History>();
|
||||
CreateMap<HistoryCreateDto, Domain.Entities.History>();
|
||||
CreateMap<EnvelopeReceiverDto, Domain.Entities.EnvelopeReceiver>();
|
||||
CreateMap<EnvelopeTypeDto, EnvelopeType>();
|
||||
CreateMap<ReceiverDto, Domain.Entities.Receiver>().ForMember(rcv => rcv.EnvelopeReceivers, rcvReadDto => rcvReadDto.Ignore());
|
||||
CreateMap<EnvelopeReceiverReadOnlyCreateDto, Domain.Entities.EnvelopeReceiverReadOnly>();
|
||||
CreateMap<EnvelopeReceiverReadOnlyUpdateDto, Domain.Entities.EnvelopeReceiverReadOnly>();
|
||||
CreateMap<AnnotationCreateDto, ElementAnnotation>()
|
||||
.MapAddedWhen();
|
||||
.ForMember(dest => dest.AddedWhen, opt => opt.MapFrom(_ => DateTime.UtcNow));
|
||||
|
||||
// Messaging mappings
|
||||
// for GTX messaging
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Annotation
|
||||
{
|
||||
private string? _id;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int EnvelopeId { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ReceiverId { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Index { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string EgName { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool HasStructuredID { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool IsLabel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(EgName))
|
||||
return false;
|
||||
|
||||
var parts = EgName.Split('_');
|
||||
return parts.Length > 1 && parts[1] == "label";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Id
|
||||
{
|
||||
get => _id;
|
||||
set
|
||||
{
|
||||
_id = value;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
throw new BurnAnnotationException("The identifier of annotation is null or empty.");
|
||||
|
||||
var parts = value.Split('#');
|
||||
|
||||
if (parts.Length != 4)
|
||||
return;
|
||||
// throw new BurnAnnotationException($"The identifier of annotation has more or less than 4 sub-part. Id: {_id}");
|
||||
|
||||
if (!int.TryParse(parts[0], out int envelopeId))
|
||||
throw new BurnAnnotationException($"The envelope ID of annotation is not integer. Id: {_id}");
|
||||
EnvelopeId = envelopeId;
|
||||
|
||||
if (!int.TryParse(parts[1], out int receiverId))
|
||||
throw new BurnAnnotationException($"The receiver ID of annotation is not integer. Id: {_id}");
|
||||
ReceiverId = receiverId;
|
||||
|
||||
if (!int.TryParse(parts[2], out int index))
|
||||
throw new BurnAnnotationException($"The index of annotation is not integer. Id: {_id}");
|
||||
Index = index;
|
||||
|
||||
EgName = parts[3];
|
||||
HasStructuredID = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<double>? Bbox { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool IsSignature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? ImageAttachmentId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Lines? Lines { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int PageIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? StrokeColor { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Binary"></param>
|
||||
/// <param name="ContentType"></param>
|
||||
public record Attachment(string Binary, string ContentType);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Name"></param>
|
||||
/// <param name="Value"></param>
|
||||
public record FormFieldValue(string Name, string? Value = null);
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Lines"></param>
|
||||
/// <param name="StrokeColor"></param>
|
||||
public record Ink(Lines Lines, string? StrokeColor = null);
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class InstantData
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<Annotation>? Annotations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<List<Annotation>>? AnnotationsByReceiver
|
||||
{
|
||||
get
|
||||
{
|
||||
return Annotations?
|
||||
.Where(a => a.HasStructuredID)
|
||||
.GroupBy(a => a.ReceiverId)
|
||||
.Select(g => g.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IEnumerable<List<Annotation>>? UnstructuredAnnotations
|
||||
{
|
||||
get
|
||||
{
|
||||
return Annotations?
|
||||
.Where(a => !a.HasStructuredID)
|
||||
.GroupBy(a => a.ReceiverId)
|
||||
.Select(g => g.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Dictionary<string, Attachment>? Attachments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<FormFieldValue>? FormFieldValues { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Points"></param>
|
||||
public record Lines(List<List<List<float>>> Points);
|
||||
@@ -0,0 +1,57 @@
|
||||
namespace EnvelopeGenerator.Application.Common.Dto;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ThirdPartyModuleDto
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool Active { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Name { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Description { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string License { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Version { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? AddedWho { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime? AddedWhen { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? ChangedWho { get; init; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; init; }
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Domain.Interfaces.Auditing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for applying auditing timestamps during AutoMapper mappings.
|
||||
/// </summary>
|
||||
public static class AutoMapperAuditingExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps <see cref="IHasAddedWhen.AddedWhen"/> to the current UTC time.
|
||||
/// </summary>
|
||||
public static IMappingExpression<TSource, TDestination> MapAddedWhen<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
|
||||
where TDestination : IHasAddedWhen
|
||||
=> expression.ForMember(dest => dest.AddedWhen, opt => opt.MapFrom(_ => DateTime.UtcNow));
|
||||
|
||||
/// <summary>
|
||||
/// Maps <see cref="IHasChangedWhen.ChangedWhen"/> to the current UTC time.
|
||||
/// </summary>
|
||||
public static IMappingExpression<TSource, TDestination> MapChangedWhen<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
|
||||
where TDestination : IHasChangedWhen
|
||||
=> expression.ForMember(dest => dest.ChangedWhen, opt => opt.MapFrom(_ => DateTime.UtcNow));
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
using EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using GdPicture14;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using SixLabors.ImageSharp;
|
||||
using System.Drawing;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class GdPictureExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="textStyle"></param>
|
||||
public static void AddFormFieldValue(this AnnotationManager manager, double x, double y, double width, double height, int page, string value, ITextStyle textStyle)
|
||||
{
|
||||
manager.SelectPage(page);
|
||||
|
||||
// Add the text annotation
|
||||
var ant = manager.AddTextAnnot((float)x, (float)y, (float)width, (float)height, value);
|
||||
|
||||
// Set the font properties
|
||||
ant.FontName = textStyle.FontName;
|
||||
ant.FontSize = textStyle.FontSize;
|
||||
ant.FontStyle = textStyle.FontStyle;
|
||||
|
||||
manager.SaveAnnotationsToPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
/// <param name="formFieldValue"></param>
|
||||
/// <param name="options"></param>
|
||||
public static void AddFormFieldValue(this AnnotationManager manager, Annotation pAnnotation, FormFieldValue formFieldValue, PDFBurnerParams options)
|
||||
{
|
||||
var ffIndex = options.GetAnnotationIndex(pAnnotation.EgName);
|
||||
|
||||
// Convert pixels to Inches
|
||||
var oBounds = pAnnotation.Bbox?.Select(points => points.ToInches()).ToList();
|
||||
|
||||
if (oBounds is null || oBounds.Count < 4)
|
||||
return;
|
||||
|
||||
double oX = oBounds[0];
|
||||
double oY = oBounds[1] + options.YOffset * ffIndex + options.TopMargin;
|
||||
double oWidth = oBounds[2];
|
||||
double oHeight = oBounds[3];
|
||||
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
|
||||
// Add the text annotation
|
||||
var ant = manager.AddTextAnnot((float)oX, (float)oY, (float)oWidth, (float)oHeight, formFieldValue.Value);
|
||||
|
||||
// Set the font properties
|
||||
ant.FontName = options.FontName;
|
||||
ant.FontSize = options.FontSize;
|
||||
ant.FontStyle = options.FontStyle;
|
||||
|
||||
manager.SaveAnnotationsToPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="base64"></param>
|
||||
public static void AddImageAnnotation(this AnnotationManager manager, double x, double y, double width, double height, int page, string base64)
|
||||
{
|
||||
manager.SelectPage(page);
|
||||
manager.AddEmbeddedImageAnnotFromBase64(base64, (float)x, (float)y, (float)width, (float)height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
/// <param name="pAttachments"></param>
|
||||
public static void AddImageAnnotation(this AnnotationManager manager, Annotation pAnnotation, Dictionary<string, Attachment> pAttachments)
|
||||
{
|
||||
var oAttachment = pAttachments
|
||||
.Where(a => a.Key == pAnnotation.ImageAttachmentId)
|
||||
.SingleOrDefault();
|
||||
|
||||
if (oAttachment.Value == null)
|
||||
return;
|
||||
|
||||
// Convert pixels to Inches
|
||||
var oBounds = pAnnotation.Bbox?.Select(post => post.ToInches()).ToList();
|
||||
|
||||
if (oBounds is null || oBounds.Count < 4)
|
||||
return;
|
||||
|
||||
var oX = oBounds[0];
|
||||
var oY = oBounds[1];
|
||||
var oWidth = oBounds[2];
|
||||
var oHeight = oBounds[3];
|
||||
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
manager.AddEmbeddedImageAnnotFromBase64(oAttachment.Value.Binary, (float)oX, (float)oY, (float)oWidth, (float)oHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="page"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void AddInkAnnotation(this AnnotationManager manager, int page, string value)
|
||||
{
|
||||
var ink = JsonConvert.DeserializeObject<Ink>(value);
|
||||
|
||||
var oSegments = ink?.Lines.Points;
|
||||
var oColor = ColorTranslator.FromHtml(ink?.StrokeColor ?? "#000000");
|
||||
manager.SelectPage(page);
|
||||
|
||||
if (oSegments is null)
|
||||
return;
|
||||
|
||||
foreach (var oSegment in oSegments)
|
||||
{
|
||||
var oPoints = oSegment
|
||||
.Select(points => points.ToPointF())
|
||||
.ToArray();
|
||||
|
||||
manager.AddFreeHandAnnot(oColor, oPoints);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="pAnnotation"></param>
|
||||
public static void AddInkAnnotation(this AnnotationManager manager, Annotation pAnnotation)
|
||||
{
|
||||
var oSegments = pAnnotation.Lines?.Points;
|
||||
var oColor = ColorTranslator.FromHtml(pAnnotation.StrokeColor ?? "#000000");
|
||||
manager.SelectPage(pAnnotation.PageIndex + 1);
|
||||
|
||||
if (oSegments is null)
|
||||
return;
|
||||
|
||||
foreach (var oSegment in oSegments)
|
||||
{
|
||||
var oPoints = oSegment
|
||||
.Select(points => points.ToPointF())
|
||||
.ToArray();
|
||||
|
||||
manager.AddFreeHandAnnot(oColor, oPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,8 @@ using System.Text;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="envelopeReceiverId"></param>
|
||||
/// <param name="exception"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="args"></param>
|
||||
public static void LogEnvelopeError(this ILogger logger, string envelopeReceiverId, Exception? exception = null, string? message = null, params object?[] args)
|
||||
{
|
||||
var sb = new StringBuilder().AppendLine(envelopeReceiverId.DecodeEnvelopeReceiverId().ToTitle());
|
||||
@@ -29,15 +18,6 @@ namespace EnvelopeGenerator.Application.Common.Extensions
|
||||
logger.Log(LogLevel.Error, exception, sb.AppendLine(exception.Message).ToString(), args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="uuid"></param>
|
||||
/// <param name="signature"></param>
|
||||
/// <param name="exception"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="args"></param>
|
||||
public static void LogEnvelopeError(this ILogger logger, string? uuid, string? signature = null, Exception? exception = null, string? message = null, params object?[] args)
|
||||
{
|
||||
var sb = new StringBuilder($"Envelope Uuid: {uuid}");
|
||||
@@ -54,11 +34,6 @@ namespace EnvelopeGenerator.Application.Common.Extensions
|
||||
logger.Log(LogLevel.Error, exception, sb.ToString(), args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="envelopeReceiverTuple"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToTitle(this (string? UUID, string? Signature) envelopeReceiverTuple)
|
||||
{
|
||||
return $"UUID is {envelopeReceiverTuple.UUID} and signature is {envelopeReceiverTuple.Signature}";
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class MathematExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="points"></param>
|
||||
/// <returns></returns>
|
||||
public static PointF ToPointF(this List<float> points)
|
||||
{
|
||||
var pointsInch = points.Select(ToInches).ToList();
|
||||
return new PointF(pointsInch[0], pointsInch[1]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static double ToInches(this double value)
|
||||
{
|
||||
return value / 72.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static float ToInches(this float value)
|
||||
{
|
||||
return value / 72f;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
/// <summary>
|
||||
/// Extension methods for tasks
|
||||
/// </summary>
|
||||
[Obsolete("Implement Mediator behaviors in the Osolete .NET project.")]
|
||||
public static class TaskExtensions
|
||||
{
|
||||
/// <summary>
|
||||
@@ -18,7 +17,6 @@ public static class TaskExtensions
|
||||
/// <param name="factory">Exception provider</param>
|
||||
/// <returns>The awaited result if not <c>null</c>.</returns>
|
||||
/// <exception>Thrown if the result is <c>null</c>.</exception>
|
||||
[Obsolete("Implement Mediator behaviors in the Osolete .NET project.")]
|
||||
public static async Task<T> ThrowIfNull<T, TException>(this Task<T?> task, Func<TException> factory) where TException : Exception
|
||||
{
|
||||
var result = await task;
|
||||
@@ -35,7 +33,6 @@ public static class TaskExtensions
|
||||
/// <param name="factory">Exception provider</param>
|
||||
/// <returns>The awaited collection if it is not <c>null</c> or empty.</returns>
|
||||
/// <exception cref="NotFoundException">Thrown if the result is <c>null</c> or empty.</exception>
|
||||
[Obsolete("Implement Mediator behaviors in the Osolete .NET project.")]
|
||||
public static async Task<IEnumerable<T>> ThrowIfEmpty<T, TException>(this Task<IEnumerable<T>> task, Func<TException> factory) where TException : Exception
|
||||
{
|
||||
var result = await task;
|
||||
@@ -50,33 +47,11 @@ public static class TaskExtensions
|
||||
/// <param name="task"></param>
|
||||
/// <param name="act"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Implement Mediator behaviors in the Osolete .NET project.")]
|
||||
public static async Task<I> Then<T, I>(this Task<T> task, Func<T, I> act)
|
||||
{
|
||||
var res = await task;
|
||||
return act(res);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="task"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Implement Mediator behaviors in the Osolete .NET project.")]
|
||||
public static Task<T?> FirstOrDefaultAsync<T>(this Task<IEnumerable<T>> task) => task.Then(t => t.FirstOrDefault());
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TException"></typeparam>
|
||||
/// <param name="task"></param>
|
||||
/// <param name="factory"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<T> FirstAsync<T, TException>(this Task<IEnumerable<T>> task, Func<TException> factory)
|
||||
where TException : Exception
|
||||
=> task.Then(t => t.FirstOrDefault() ?? throw factory());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -93,13 +68,11 @@ public static class Exceptions
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Implement Mediator behaviors in the Osolete .NET project.")]
|
||||
public static BadRequestException BadRequest() => new();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Implement Mediator behaviors in the Osolete .NET project.")]
|
||||
public static ForbiddenException Forbidden() => new();
|
||||
}
|
||||
@@ -2,42 +2,16 @@
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Text.Encodings.Web;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class XSSExtensions
|
||||
namespace EnvelopeGenerator.Application.Common.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="encoder"></param>
|
||||
/// <returns></returns>
|
||||
public static string? TryEncode(this string? value, UrlEncoder encoder) => value is null ? value : encoder.Encode(value);
|
||||
public static class XSSExtensions
|
||||
{
|
||||
public static string? TryEncode(this string? value, UrlEncoder encoder) => value is null ? value : encoder.Encode(value);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="encoder"></param>
|
||||
/// <returns></returns>
|
||||
public static string? TryEncode(this LocalizedString? value, UrlEncoder encoder) => value is null ? null : encoder.Encode(value);
|
||||
public static string? TryEncode(this LocalizedString? value, UrlEncoder encoder) => value is null ? null : encoder.Encode(value);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="html"></param>
|
||||
/// <param name="sanitizer"></param>
|
||||
/// <returns></returns>
|
||||
public static string? TrySanitize(this string? html, HtmlSanitizer sanitizer) => html is null ? html : sanitizer.Sanitize(html);
|
||||
public static string? TrySanitize(this string? html, HtmlSanitizer sanitizer) => html is null ? html : sanitizer.Sanitize(html);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="html"></param>
|
||||
/// <param name="sanitizer"></param>
|
||||
/// <returns></returns>
|
||||
public static string? TrySanitize(this LocalizedString? html, HtmlSanitizer sanitizer) => html is null ? null : sanitizer.Sanitize(html);
|
||||
public static string? TrySanitize(this LocalizedString? html, HtmlSanitizer sanitizer) => html is null ? null : sanitizer.Sanitize(html);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Interfaces.Model;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface ITextStyle
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string FontName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int FontSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>")]
|
||||
public FontStyle FontStyle { get; set; }
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public record DocSignedNotification(EnvelopeReceiverDto Original) : EnvelopeRece
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public PsPdfKitAnnotation? PsPdfKitAnnotation { get; init; }
|
||||
public PsPdfKitAnnotation PsPdfKitAnnotation { get; init; } = null!;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
@@ -59,7 +59,7 @@ public static class DocSignedNotificationExtensions
|
||||
/// <param name="dtoTask"></param>
|
||||
/// <param name="psPdfKitAnnotation"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<DocSignedNotification?> ToDocSignedNotification(this Task<EnvelopeReceiverDto?> dtoTask, PsPdfKitAnnotation? psPdfKitAnnotation)
|
||||
public static async Task<DocSignedNotification?> ToDocSignedNotification(this Task<EnvelopeReceiverDto?> dtoTask, PsPdfKitAnnotation psPdfKitAnnotation)
|
||||
=> await dtoTask is EnvelopeReceiverDto dto ? new(dto) { PsPdfKitAnnotation = psPdfKitAnnotation } : null;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -29,9 +29,6 @@ public class AnnotationHandler : INotificationHandler<DocSignedNotification>
|
||||
/// <param name="notification"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public async Task Handle(DocSignedNotification notification, CancellationToken cancel)
|
||||
{
|
||||
if (notification.PsPdfKitAnnotation is PsPdfKitAnnotation annot)
|
||||
await _repo.CreateAsync(annot.Structured, cancel);
|
||||
}
|
||||
public Task Handle(DocSignedNotification notification, CancellationToken cancel)
|
||||
=> _repo.CreateAsync(notification.PsPdfKitAnnotation.Structured, cancel);
|
||||
}
|
||||
@@ -10,8 +10,6 @@ namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
|
||||
/// </summary>
|
||||
public class DocStatusHandler : INotificationHandler<DocSignedNotification>
|
||||
{
|
||||
private const string BlankAnnotationJson = "{}";
|
||||
|
||||
private readonly ISender _sender;
|
||||
|
||||
/// <summary>
|
||||
@@ -35,9 +33,7 @@ public class DocStatusHandler : INotificationHandler<DocSignedNotification>
|
||||
{
|
||||
Envelope = new() { Id = notification.EnvelopeId },
|
||||
Receiver = new() { Id = notification.ReceiverId},
|
||||
Value = notification.PsPdfKitAnnotation is PsPdfKitAnnotation annot
|
||||
? JsonSerializer.Serialize(annot.Instant, Format.Json.ForAnnotations)
|
||||
: BlankAnnotationJson
|
||||
Value = JsonSerializer.Serialize(notification.PsPdfKitAnnotation.Instant, Format.Json.ForAnnotations)
|
||||
}, cancel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Common.Notifications.RemoveSignature.Handlers;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class RemoveDocResult : INotificationHandler<RemoveSignatureNotification>
|
||||
{
|
||||
private readonly IRepository<Envelope> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public RemoveDocResult(IRepository<Envelope> repository)
|
||||
{
|
||||
_repo = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="notification"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public Task Handle(RemoveSignatureNotification notification, CancellationToken cancel)
|
||||
{
|
||||
if(notification.EnvelopeId is null && notification.EnvelopeUuid is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return _repo.UpdateAsync(
|
||||
envelope => envelope.DocResult = null,
|
||||
query => {
|
||||
if (notification.EnvelopeId is int envelopeId)
|
||||
query = query.Where(envelope => envelope.Id == envelopeId);
|
||||
|
||||
if (notification.EnvelopeUuid is string uuid)
|
||||
query = query.Where(envelope => envelope.Uuid == uuid);
|
||||
|
||||
return query;
|
||||
}, cancel);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,16 @@
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Services;
|
||||
using EnvelopeGenerator.Application.Services;
|
||||
using EnvelopeGenerator.Application.ThirdPartyModules.Queries;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using QRCoder;
|
||||
using System.Reflection;
|
||||
using GdPicture14;
|
||||
using EnvelopeGenerator.Application.Pdf.Behaviors;
|
||||
|
||||
namespace EnvelopeGenerator.Application;
|
||||
|
||||
@@ -20,9 +25,10 @@ public static class DependencyInjection
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="usePdfBurner"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use MediatR")]
|
||||
public static IServiceCollection AddEnvelopeGeneratorServices(this IServiceCollection services, IConfiguration config)
|
||||
public static IServiceCollection AddEnvelopeGeneratorServices(this IServiceCollection services, IConfiguration config, bool usePdfBurner = false)
|
||||
{
|
||||
//Inject CRUD Service and repositoriesad
|
||||
services.TryAddScoped<IConfigService, ConfigService>();
|
||||
@@ -47,6 +53,31 @@ public static class DependencyInjection
|
||||
services.Configure<AuthenticatorParams>(config.GetSection(nameof(AuthenticatorParams)));
|
||||
services.Configure<TotpSmsParams>(config.GetSection(nameof(TotpSmsParams)));
|
||||
|
||||
if (usePdfBurner)
|
||||
{
|
||||
services.Configure<PDFBurnerParams>(config.GetSection(nameof(PDFBurnerParams)));
|
||||
services.AddOptions<GdPictureParams>()
|
||||
.Configure((GdPictureParams opt, IServiceProvider provider) =>
|
||||
{
|
||||
opt.License = config["GdPictureLicenseKey"]
|
||||
?? provider.GetRequiredService<IMediator>().ReadThirdPartyModuleLicenseAsync("GDPICTURE").GetAwaiter().GetResult()
|
||||
?? throw new InvalidOperationException($"License record not found for key: {"GDPICTURE"}");
|
||||
});
|
||||
services.AddSingleton(provider =>
|
||||
{
|
||||
var license = provider.GetRequiredService<IOptions<GdPictureParams>>().Value.License;
|
||||
var licenseManager = new LicenseManager();
|
||||
licenseManager.RegisterKEY(license);
|
||||
return licenseManager;
|
||||
});
|
||||
services.AddTransient(provider =>
|
||||
{
|
||||
// Ensure LicenseManager is resolved so that its constructor is called
|
||||
_ = provider.GetRequiredService<LicenseManager>();
|
||||
return new AnnotationManager();
|
||||
});
|
||||
}
|
||||
|
||||
services.AddHttpClientService<GtxMessagingParams>(config.GetSection(nameof(GtxMessagingParams)));
|
||||
services.TryAddSingleton<ISmsSender, GTXSmsSender>();
|
||||
services.TryAddSingleton<IEnvelopeSmsHandler, EnvelopeSmsHandler>();
|
||||
@@ -56,8 +87,15 @@ public static class DependencyInjection
|
||||
services.AddMediatR(cfg =>
|
||||
{
|
||||
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
|
||||
cfg.AddOpenBehaviors(new Type[] { typeof(AddReportBehavior), typeof(SavePdfBehavior) });
|
||||
});
|
||||
|
||||
// Add memory cache
|
||||
services.AddMemoryCache();
|
||||
|
||||
// Register mail services
|
||||
services.AddScoped<IEnvelopeMailService, EnvelopeMailService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,12 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Commands;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DocStatus.Commands;
|
||||
namespace EnvelopeGenerator.Application.DocStatus.Commands;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record CreateDocStatusCommand : ModifyDocStatusCommandBase, IRequest<DocumentStatus>
|
||||
public record CreateDocStatusCommand : ModifyDocStatusCommandBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets timestamp when this record was added. Returns the StatusChangedWhen value.
|
||||
/// </summary>
|
||||
public DateTime AddedWhen => StatusChangedWhen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CreateDocStatusCommandHandler : CreateCommandHandler<CreateDocStatusCommand, DocumentStatus>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public CreateDocStatusCommandHandler(IRepository<DocumentStatus> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.DocStatus.Commands;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
|
||||
@@ -17,12 +16,10 @@ public class MappingProfile : Profile
|
||||
{
|
||||
CreateMap<CreateDocStatusCommand, DocumentStatus>()
|
||||
.ForMember(dest => dest.Envelope, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Receiver, opt => opt.Ignore())
|
||||
.MapAddedWhen();
|
||||
.ForMember(dest => dest.Receiver, opt => opt.Ignore());
|
||||
|
||||
CreateMap<UpdateDocStatusCommand, DocumentStatus>()
|
||||
.ForMember(dest => dest.Envelope, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.Receiver, opt => opt.Ignore())
|
||||
.MapChangedWhen();
|
||||
.ForMember(dest => dest.Receiver, opt => opt.Ignore());
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using DigitalData.Core.Exceptions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Documents.Queries;
|
||||
|
||||
@@ -13,14 +12,14 @@ namespace EnvelopeGenerator.Application.Documents.Queries;
|
||||
/// </summary>
|
||||
/// <param name="Id">The unique identifier of the document. Optional.</param>
|
||||
/// <param name="EnvelopeId">The identifier of the envelope associated with the document. Optional.</param>
|
||||
public record ReadDocumentQuery(int? Id = null, int? EnvelopeId = null) : IRequest<DocumentDto>
|
||||
public record ReadDocumentQuery(int? Id = null, int? EnvelopeId = null) : IRequest<DocumentDto?>
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles queries for reading <see cref="Document"/> data based on either the document ID or the envelope ID.
|
||||
/// </summary>
|
||||
public class ReadDocumentQueryHandler : IRequestHandler<ReadDocumentQuery, DocumentDto>
|
||||
public class ReadDocumentQueryHandler : IRequestHandler<ReadDocumentQuery, DocumentDto?>
|
||||
{
|
||||
/// <summary>
|
||||
/// TempRepo for accessing <see cref="Document"/> entities.
|
||||
@@ -51,19 +50,20 @@ public class ReadDocumentQueryHandler : IRequestHandler<ReadDocumentQuery, Docum
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown when neither <see cref="ReadDocumentQuery.Id"/> nor <see cref="ReadDocumentQuery.EnvelopeId"/> is provided.
|
||||
/// </exception>
|
||||
public async Task<DocumentDto> Handle(ReadDocumentQuery query, CancellationToken cancel)
|
||||
public async Task<DocumentDto?> Handle(ReadDocumentQuery query, CancellationToken cancel)
|
||||
{
|
||||
if (query.Id is not null)
|
||||
{
|
||||
var doc = await _repo.Query.Where(d => d.Id == query.Id).FirstOrDefaultAsync(cancel);
|
||||
var doc = await _repo.ReadOnly().Where(d => d.Id == query.Id).FirstOrDefaultAsync(cancel);
|
||||
return _mapper.Map<DocumentDto>(doc);
|
||||
}
|
||||
else if (query.EnvelopeId is not null)
|
||||
{
|
||||
var doc = await _repo.Query.Where(d => d.EnvelopeId == query.EnvelopeId).FirstOrDefaultAsync(cancel);
|
||||
var doc = await _repo.ReadOnly().Where(d => d.EnvelopeId == query.EnvelopeId).FirstOrDefaultAsync(cancel);
|
||||
return _mapper.Map<DocumentDto>(doc);
|
||||
}
|
||||
|
||||
throw new NotFoundException();
|
||||
throw new InvalidOperationException(
|
||||
$"Invalid {nameof(ReadDocumentQuery)}: either {nameof(query.Id)} or {nameof(query.EnvelopeId)} must be provided.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using EnvelopeGenerator.Domain;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
|
||||
|
||||
/// <summary>
|
||||
/// Ein Befehl zum Zurücksetzen einer E-Mail-Vorlage auf die Standardwerte.
|
||||
/// Erbt von <see cref="EmailTemplateQuery"/> und ermöglicht die Angabe einer optionalen ID und eines Typs der E-Mail-Vorlage.<br/><br/>
|
||||
/// Beispiele:<br/>
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.<br/>
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.<br/>
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.<br/>
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.<br/>
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.<br/>
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.<br/>
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.<br/>
|
||||
/// 7 - DocumentRejected_ADM (Für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.<br/>
|
||||
/// </summary>
|
||||
public record ResetEmailTemplateCommand : EmailTemplateQuery, IRequest
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="orginal"></param>
|
||||
public ResetEmailTemplateCommand(EmailTemplateQuery? orginal = null) : base(orginal ?? new())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Id">Die optionale ID der E-Mail-Vorlage, die zurückgesetzt werden soll.</param>
|
||||
/// <param name="Type">Der Typ der E-Mail-Vorlage, z. B. <see cref="EmailTemplateType"/> (optional).</param>
|
||||
public ResetEmailTemplateCommand(int? Id = null, EmailTemplateType? Type = null) : base(Id, Type)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -1,38 +1,11 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Ein Befehl zum Zurücksetzen einer E-Mail-Vorlage auf die Standardwerte.
|
||||
/// Erbt von <see cref="IEmailTemplateQuery"/> und ermöglicht die Angabe einer optionalen ID und eines Typs der E-Mail-Vorlage.<br/><br/>
|
||||
/// </summary>
|
||||
public record ResetEmailTemplateCommand : IEmailTemplateQuery, IRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung der E-Mail-Vorlage (optional).
|
||||
/// </summary>
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Typ der E-Mail-Vorlage, z. B. <see cref="EmailTemplateType"/> (optional). Beispiele:<br/>
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.<br/>
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.<br/>
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.<br/>
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.<br/>
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.<br/>
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.<br/>
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.<br/>
|
||||
/// 7 - DocumentRejected_ADM (für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 8 - DocumentRejected_REC (für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 9 - DocumentRejected_REC_2 (für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </summary>
|
||||
public EmailTemplateType? Type { get; set; }
|
||||
}
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
@@ -68,7 +41,7 @@ public class ResetEmailTemplateCommandHandler : IRequestHandler<ResetEmailTempla
|
||||
foreach (var temp in temps)
|
||||
{
|
||||
var def = Defaults.Where(t => t.Name == temp.Name).FirstOrDefault();
|
||||
if (def is not null)
|
||||
if(def is not null)
|
||||
await _repository.UpdateAsync(def, t => t.Id == temp.Id, cancel);
|
||||
}
|
||||
}
|
||||
@@ -140,4 +113,4 @@ public class ResetEmailTemplateCommandHandler : IRequestHandler<ResetEmailTempla
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using MediatR;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Update;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Befehl zum Aktualisieren einer E-Mail-Vorlage.
|
||||
/// </summary>
|
||||
/// <param name="Body">
|
||||
/// (Optional)Der neue Inhalt des E-Mail-Textkörpers. Wenn null, bleibt der vorhandene Inhalt unverändert.
|
||||
/// </param>
|
||||
/// <param name="Subject">
|
||||
/// (Optional) Der neue Betreff der E-Mail. Wenn null, bleibt der vorhandene Betreff unverändert.
|
||||
/// </param>
|
||||
public record UpdateEmailTemplateCommand(string? Body = null, string? Subject = null) : IRequest
|
||||
{
|
||||
/// <param>
|
||||
/// Die Abfrage, die die E-Mail-Vorlage darstellt, die aktualisiert werden soll.
|
||||
/// </param>
|
||||
[JsonIgnore]
|
||||
public EmailTemplateQuery? EmailTemplateQuery { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public DateTime ChangedWhen { get; init; } = DateTime.Now;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Update;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class UpdateEmailTemplateCommandHandler : IRequestHandler<UpdateEmailTemplateCommand>
|
||||
{
|
||||
private readonly IRepository<EmailTemplate> _repository;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public UpdateEmailTemplateCommandHandler(IRepository<EmailTemplate> repository, IMapper mapper)
|
||||
{
|
||||
_repository = repository;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
|
||||
public async Task Handle(UpdateEmailTemplateCommand request, CancellationToken cancel)
|
||||
{
|
||||
EmailTemplateDto? tempDto;
|
||||
|
||||
if (request.EmailTemplateQuery?.Id is int id)
|
||||
{
|
||||
var temp = await _repository.ReadOnly().Where(t => t.Id == id).FirstOrDefaultAsync(cancel);
|
||||
tempDto = _mapper.Map<EmailTemplateDto>(temp);
|
||||
}
|
||||
else if (request!.EmailTemplateQuery!.Type is EmailTemplateType type)
|
||||
{
|
||||
var temp = await _repository.ReadOnly().Where(t => t.Name == type.ToString()).FirstOrDefaultAsync(cancel);
|
||||
tempDto = _mapper.Map<EmailTemplateDto>(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Both id and type is null. Id: " + request.EmailTemplateQuery.Id +". Type: " + request.EmailTemplateQuery.Type.ToString());
|
||||
}
|
||||
|
||||
if (tempDto == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (request.Body is not null)
|
||||
tempDto.Body = request.Body;
|
||||
|
||||
if (request.Subject is not null)
|
||||
tempDto.Subject = request.Subject;
|
||||
|
||||
await _repository.UpdateAsync(tempDto, t => t.Id == tempDto.Id, cancel);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Commands;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Body"></param>
|
||||
/// <param name="Subject"></param>
|
||||
public record EmailTemplateUpdateDto(string Body, string Subject);
|
||||
|
||||
/// <summary>
|
||||
/// Befehl zum Aktualisieren einer E-Mail-Vorlage.
|
||||
/// </summary>
|
||||
public record UpdateEmailTemplateCommand : UpdateCommand<EmailTemplateUpdateDto, EmailTemplate>, IEmailTemplateQuery
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung der E-Mail-Vorlage (optional).
|
||||
/// </summary>
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Typ der E-Mail-Vorlage, z. B. <see cref="EmailTemplateType"/> (optional). Beispiele:<br/>
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.<br/>
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.<br/>
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.<br/>
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.<br/>
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.<br/>
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.<br/>
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.<br/>
|
||||
/// 7 - DocumentRejected_ADM (für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 8 - DocumentRejected_REC (für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 9 - DocumentRejected_REC_2 (für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </summary>
|
||||
public EmailTemplateType? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override Expression<Func<EmailTemplate, bool>> BuildQueryExpression()
|
||||
=> Id is int id
|
||||
? temp => temp.Id == id
|
||||
: temp => temp!.Name == Type.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class UpdateEmailTemplateCommandHandler : UpdateCommandHandler<UpdateEmailTemplateCommand, EmailTemplateUpdateDto, EmailTemplate>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
public UpdateEmailTemplateCommandHandler(IRepository<EmailTemplate> repository) : base(repository)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für E-Mail-Vorlagen, die für Absender und Empfänger von Umschlägen verwendet werden.
|
||||
/// Die Standardkultur ist "de-DE".
|
||||
/// </summary>
|
||||
/// <param name="Id">Die eindeutige Kennung der E-Mail-Vorlage (optional).</param>
|
||||
/// <param name="Type">Der Typ der E-Mail-Vorlage, z. B. <see cref="EmailTemplateType"/> (optional). Beispiele:
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.
|
||||
/// 7 - DocumentRejected_ADM (Für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.
|
||||
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.
|
||||
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </param>
|
||||
public record EmailTemplateQuery(int? Id = null, EmailTemplateType? Type = null)
|
||||
{
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Schnittstelle für Abfragen von E-Mail-Vorlagen dar, die für Absender und Empfänger von Umschlägen verwendet werden.
|
||||
/// Die Standardkultur ist "de-DE".
|
||||
/// </summary>
|
||||
public interface IEmailTemplateQuery
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung der E-Mail-Vorlage (optional).
|
||||
/// </summary>
|
||||
int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Typ der E-Mail-Vorlage, z. B. <see cref="EmailTemplateType"/> (optional). Beispiele:<br/>
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.<br/>
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.<br/>
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.<br/>
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.<br/>
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.<br/>
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.<br/>
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.<br/>
|
||||
/// 7 - DocumentRejected_ADM (für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 8 - DocumentRejected_REC (für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 9 - DocumentRejected_REC_2 (für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </summary>
|
||||
EmailTemplateType? Type { get; set; }
|
||||
}
|
||||
@@ -1,24 +1,24 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Commands;
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
///
|
||||
/// </summary>
|
||||
public class MappingProfile : Profile
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
///
|
||||
/// </summary>
|
||||
public MappingProfile()
|
||||
{
|
||||
CreateMap<EmailTemplate, EmailTemplateDto>();
|
||||
|
||||
CreateMap<EmailTemplateUpdateDto, EmailTemplate>()
|
||||
.MapChangedWhen();
|
||||
CreateMap<EmailTemplate, ReadEmailTemplateResponse>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage dar, um eine E-Mail-Vorlage zu lesen.
|
||||
/// Diese Klasse erbt von <see cref="EmailTemplateQuery"/>.
|
||||
/// </summary>
|
||||
public record ReadEmailTemplateQuery : EmailTemplateQuery, IRequest<ReadEmailTemplateResponse?>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQuery, ReadEmailTemplateResponse?>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
|
||||
private readonly IEmailTemplateRepository _repository;
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </summary>
|
||||
/// <param name="mapper">
|
||||
/// <param name="repository">
|
||||
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
|
||||
/// </param>
|
||||
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
|
||||
public ReadEmailTemplateQueryHandler(IMapper mapper, IEmailTemplateRepository repository)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
[Obsolete("Use IRepository")]
|
||||
public async Task<ReadEmailTemplateResponse?> Handle(ReadEmailTemplateQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var temp = request.Id is int id
|
||||
? await _repository.ReadByIdAsync(id)
|
||||
: request.Type is EmailTemplateType type
|
||||
? await _repository.ReadByNameAsync(type)
|
||||
: throw new InvalidOperationException("Either a valid integer ID or a valid EmailTemplateType must be provided in the request.");
|
||||
|
||||
var res = _mapper.Map<ReadEmailTemplateResponse>(temp);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt die Antwort für eine Abfrage von E-Mail-Vorlagen bereit.
|
||||
/// </summary>
|
||||
public class ReadEmailTemplateResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung der E-Mail-Vorlage.
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name des Typs
|
||||
/// </summary>
|
||||
public required string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage hinzugefügt wurde.
|
||||
/// </summary>
|
||||
public DateTime AddedWhen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Inhalt (Body) der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Betreff der E-Mail-Vorlage. Kann null sein.
|
||||
/// </summary>
|
||||
public string? Subject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann die Vorlage zuletzt geändert wurde. Kann null sein.
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
using AutoMapper;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage dar, um eine E-Mail-Vorlage zu lesen.
|
||||
/// Diese Klasse erbt von <see cref="IEmailTemplateQuery"/>.
|
||||
/// </summary>
|
||||
public record ReadEmailTemplateQuery : IEmailTemplateQuery, IRequest<IEnumerable<EmailTemplateDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung der E-Mail-Vorlage (optional).
|
||||
/// </summary>
|
||||
public int? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Typ der E-Mail-Vorlage, z. B. <see cref="EmailTemplateType"/> (optional). Beispiele:<br/>
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.<br/>
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.<br/>
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.<br/>
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.<br/>
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.<br/>
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.<br/>
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.<br/>
|
||||
/// 7 - DocumentRejected_ADM (für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 8 - DocumentRejected_REC (für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.<br/>
|
||||
/// 9 - DocumentRejected_REC_2 (für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </summary>
|
||||
public EmailTemplateType? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? LangCode { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class ReadEmailTemplateQueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="langCode"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<EmailTemplateDto?> ReadEmailTemplateAsync(this ISender sender, int id, string langCode, CancellationToken cancel = default)
|
||||
{
|
||||
var result = await sender.Send(new ReadEmailTemplateQuery { Id = id, LangCode = langCode }, cancel);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="langCode"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<EmailTemplateDto?> ReadEmailTemplateAsync(this ISender sender, EmailTemplateType type, string langCode, CancellationToken cancel = default)
|
||||
{
|
||||
var result = await sender.Send(new ReadEmailTemplateQuery { Type = type, LangCode = langCode }, cancel);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEmailTemplateQueryHandler : IRequestHandler<ReadEmailTemplateQuery, IEnumerable<EmailTemplateDto>>
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<EmailTemplate> _repo;
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </summary>
|
||||
/// <param name="mapper">
|
||||
/// <param name="repo">
|
||||
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
|
||||
/// </param>
|
||||
public ReadEmailTemplateQueryHandler(IMapper mapper, IRepository<EmailTemplate> repo)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
public async Task<IEnumerable<EmailTemplateDto>> Handle(ReadEmailTemplateQuery request, CancellationToken cancel)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if (request.Id is int id)
|
||||
query = query.Where(temp => temp.Id == id);
|
||||
|
||||
if (request.Type is EmailTemplateType type)
|
||||
query = query.Where(temp => temp.Name == type.ToString());
|
||||
|
||||
if (request.LangCode is string langCode)
|
||||
query = query.Where(temp => temp.LangCode == langCode);
|
||||
|
||||
var entity = await query.ToListAsync(cancel);
|
||||
|
||||
return _mapper.Map<IEnumerable<EmailTemplateDto>>(entity);
|
||||
}
|
||||
}
|
||||
@@ -14,38 +14,46 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.6.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.5.0" />
|
||||
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
|
||||
<PackageReference Include="DigitalData.Core.Client" Version="2.1.0" />
|
||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="9.0.892" />
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
|
||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.82.1" />
|
||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="10.0.3" />
|
||||
<PackageReference Include="System.Security.AccessControl" Version="6.0.1" />
|
||||
<PackageReference Include="UserManager" Version="1.1.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="8.0.2" />
|
||||
<PackageReference Include="GdPicture" Version="14.3.19.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="9.0.10" />
|
||||
<PackageReference Include="GdPicture" Version="14.3.19.1" />
|
||||
<PackageReference Include="GdPicture.runtimes.windows" Version="14.3.19.1" />
|
||||
<PackageReference Include="GdPicture.runtimes.linux" Version="14.3.19.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
||||
<PackageReference Include="System.Formats.Asn1" Version="9.0.10" />
|
||||
<PackageReference Include="GdPicture" Version="14.3.19.1" />
|
||||
<PackageReference Include="GdPicture.runtimes.windows" Version="14.3.19.1" />
|
||||
<PackageReference Include="GdPicture.runtimes.linux" Version="14.3.19.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.PdfEditor\EnvelopeGenerator.PdfEditor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -67,9 +75,6 @@
|
||||
<LastGenOutput>Model.Designer.cs</LastGenOutput>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\Resource.fr-FR.resx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\Resource.de-DE.resx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
@@ -80,7 +85,7 @@
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.4" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.3" />
|
||||
<PackageReference Include="CommandDotNet">
|
||||
<Version>7.0.5</Version>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using AutoMapper;
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
@@ -47,13 +47,7 @@ namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
||||
/// Die Antwort enthält Details wie den Include, die Zuordnung zwischen Umschlag und Empfänger
|
||||
/// sowie zusätzliche Metadaten.
|
||||
/// </remarks>
|
||||
public record ReadEnvelopeReceiverQuery : EnvelopeReceiverQueryBase<ReadEnvelopeQuery, ReadReceiverQuery>, IRequest<IEnumerable<EnvelopeReceiverDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Optionaler Benutzernamefilter, um Ergebnisse auf Umschläge eines bestimmten Besitzers einzuschränken.
|
||||
/// </summary>
|
||||
public string? Username { get; init; }
|
||||
}
|
||||
public record ReadEnvelopeReceiverQuery : EnvelopeReceiverQueryBase<ReadEnvelopeQuery, ReadReceiverQuery>, IRequest<IEnumerable<EnvelopeReceiverDto>>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
@@ -67,11 +61,10 @@ public static class Extensions
|
||||
/// <param name="key"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<EnvelopeReceiverDto?> ReadEnvelopeReceiverAsync(this IMediator mediator, string key, CancellationToken cancel = default)
|
||||
public static Task<EnvelopeReceiverDto?> ReadEnvelopeReceiverAsync(this IMediator mediator, string key, CancellationToken cancel = default)
|
||||
{
|
||||
var q = new ReadEnvelopeReceiverQuery() { Key = key };
|
||||
var envRcvs = await mediator.Send(q, cancel);
|
||||
return envRcvs.FirstOrDefault();
|
||||
return mediator.Send(q, cancel).Then(envRcvs => envRcvs.FirstOrDefault());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -82,82 +75,80 @@ public static class Extensions
|
||||
/// <param name="signature"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<EnvelopeReceiverDto?> ReadEnvelopeReceiverAsync(this IMediator mediator, string uuid, string signature, CancellationToken cancel = default)
|
||||
public static Task<EnvelopeReceiverDto?> ReadEnvelopeReceiverAsync(this IMediator mediator, string uuid, string signature, CancellationToken cancel = default)
|
||||
{
|
||||
var q = new ReadEnvelopeReceiverQuery();
|
||||
q.Envelope.Uuid = uuid;
|
||||
q.Receiver.Signature = signature;
|
||||
var envRcvs = await mediator.Send(q, cancel);
|
||||
return envRcvs.FirstOrDefault();
|
||||
return mediator.Send(q, cancel).Then(envRcvs => envRcvs.FirstOrDefault());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeReceiverQuery, IEnumerable<EnvelopeReceiverDto>>
|
||||
{
|
||||
private readonly IRepository<EnvelopeReceiver> _repo;
|
||||
|
||||
private readonly IRepository<Receiver> _rcvRepo;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
/// Verarbeitet <see cref="ReadEnvelopeReceiverQuery"/> und liefert passende <see cref="EnvelopeReceiverDto"/>-Ergebnisse.
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeReceiverQuery, IEnumerable<EnvelopeReceiverDto>>
|
||||
/// <param name="envelopeReceiver"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadEnvelopeReceiverQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiver, IRepository<Receiver> rcvRepo, IMapper mapper)
|
||||
{
|
||||
private readonly IRepository<EnvelopeReceiver> _repo;
|
||||
private readonly IRepository<Receiver> _rcvRepo;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="envelopeReceiver"></param>
|
||||
/// <param name="rcvRepo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadEnvelopeReceiverQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiver, IRepository<Receiver> rcvRepo, IMapper mapper)
|
||||
{
|
||||
_repo = envelopeReceiver;
|
||||
_mapper = mapper;
|
||||
_rcvRepo = rcvRepo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BadRequestException"></exception>
|
||||
public async Task<IEnumerable<EnvelopeReceiverDto>> Handle(ReadEnvelopeReceiverQuery request, CancellationToken cancel)
|
||||
{
|
||||
var q = _repo.Query.Where(request, notnull: false);
|
||||
|
||||
if (request.Username is string username)
|
||||
q = q.Where(er => er.Envelope!.User.Username == username);
|
||||
|
||||
if (request.Envelope.Status is not null)
|
||||
{
|
||||
var status = request.Envelope.Status;
|
||||
if (status.Min is not null)
|
||||
q = q.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
q = q.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Length > 0)
|
||||
q = q.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
q = q.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
var envRcvs = await q
|
||||
.Include(er => er.Envelope).ThenInclude(e => e!.Documents!).ThenInclude(d => d.Elements)
|
||||
.Include(er => er.Envelope).ThenInclude(e => e!.Histories)
|
||||
.Include(er => er.Envelope).ThenInclude(e => e!.User)
|
||||
.Include(er => er.Receiver)
|
||||
.ToListAsync(cancel);
|
||||
|
||||
if (request.Receiver.HasAnyCriteria && envRcvs.Count != 0)
|
||||
{
|
||||
var receiver = await _rcvRepo.Query.Where(request.Receiver).FirstAsync(cancel);
|
||||
|
||||
foreach (var envRcv in envRcvs)
|
||||
envRcv.Envelope?.Documents?.FirstOrDefault()?.Elements?.RemoveAll(s => s.ReceiverId != receiver.Id);
|
||||
}
|
||||
|
||||
return _mapper.Map<List<EnvelopeReceiverDto>>(envRcvs);
|
||||
}
|
||||
_repo = envelopeReceiver;
|
||||
_mapper = mapper;
|
||||
_rcvRepo = rcvRepo;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="BadRequestException"></exception>
|
||||
public async Task<IEnumerable<EnvelopeReceiverDto>> Handle(ReadEnvelopeReceiverQuery request, CancellationToken cancel)
|
||||
{
|
||||
var q = _repo.ReadOnly().Where(request, notnull: false);
|
||||
|
||||
if (request.Envelope.Status is not null)
|
||||
{
|
||||
var status = request.Envelope.Status;
|
||||
if (status.Min is not null)
|
||||
q = q.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
q = q.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Length > 0)
|
||||
q = q.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
q = q.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
var envRcvs = await q
|
||||
.Include(er => er.Envelope).ThenInclude(e => e!.Documents!).ThenInclude(d => d.Elements)
|
||||
.Include(er => er.Envelope).ThenInclude(e => e!.Histories)
|
||||
.Include(er => er.Envelope).ThenInclude(e => e!.User)
|
||||
.Include(er => er.Receiver)
|
||||
.ToListAsync(cancel);
|
||||
|
||||
if (request.Receiver.HasAnyCriteria && envRcvs.Any())
|
||||
{
|
||||
var receiver = await _rcvRepo.ReadOnly().Where(request.Receiver).FirstAsync(cancel);
|
||||
|
||||
foreach (var envRcv in envRcvs)
|
||||
envRcv.Envelope?.Documents?.First().Elements.RemoveAll(s => s.ReceiverId != receiver.Id);
|
||||
}
|
||||
|
||||
return _mapper.Map<List<EnvelopeReceiverDto>>(envRcvs);
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,6 @@ public class ReceiverAlreadySignedQueryHandler : IRequestHandler<ReceiverAlready
|
||||
/// <returns></returns>
|
||||
public async Task<bool> Handle(ReceiverAlreadySignedQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
return await _repo.Query.Where(request).Where(h => h.Status == EnvelopeStatus.DocumentSigned).AnyAsync(cancel);
|
||||
return await _repo.ReadOnly().Where(request).Where(h => h.Status == EnvelopeStatus.DocumentSigned).AnyAsync(cancel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EnvelopeReports;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ReadEnvelopeReportQuery(int EnvelopeId) : IRequest<IEnumerable<EnvelopeReport>>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[NotMapped]
|
||||
public bool ThrowIfNotFound { get; init; } = true;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class ReadEnvelopeReportQueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="envelopeId"></param>
|
||||
/// <param name="throwIfNotFound"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<IEnumerable<EnvelopeReport>> ReadEnvelopeReportAsync(this ISender sender, int envelopeId, bool throwIfNotFound = true, CancellationToken cancel = default)
|
||||
=> sender.Send(new ReadEnvelopeReportQuery(envelopeId)
|
||||
{
|
||||
ThrowIfNotFound = throwIfNotFound
|
||||
}, cancel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEnvelopeReportQueryHandler : IRequestHandler<ReadEnvelopeReportQuery, IEnumerable<EnvelopeReport>>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private readonly IRepository<EnvelopeReport> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadEnvelopeReportQueryHandler(IRepository<EnvelopeReport> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IEnumerable<EnvelopeReport>> Handle(ReadEnvelopeReportQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var reports = await _repo.Where(r => r.EnvelopeId == request.EnvelopeId).ToListAsync(cancel);
|
||||
var reportDtos = _mapper.Map<IEnumerable<EnvelopeReport>>(reports);
|
||||
|
||||
if(request.ThrowIfNotFound && !reportDtos.Any())
|
||||
throw new NotFoundException($"EnvelopeReport with EnvelopeId '{request.EnvelopeId}' was not found.");
|
||||
|
||||
return reportDtos;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using MediatR;
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EnvelopeTypes.Queries;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record ReadEnvelopeTypesQuery : IRequest<IEnumerable<EnvelopeTypeDto>>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEnvelopeTypesQueryHandler : IRequestHandler<ReadEnvelopeTypesQuery, IEnumerable<EnvelopeTypeDto>>
|
||||
{
|
||||
private readonly IRepository<EnvelopeType> _repository;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadEnvelopeTypesQueryHandler(IRepository<EnvelopeType> repository, IMapper mapper)
|
||||
{
|
||||
_repository = repository;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IEnumerable<EnvelopeTypeDto>> Handle(ReadEnvelopeTypesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var types = await _repository.Query.ToListAsync(cancellationToken);
|
||||
return _mapper.Map<IEnumerable<EnvelopeTypeDto>>(types);
|
||||
}
|
||||
}
|
||||
@@ -33,18 +33,7 @@ public record CreateEnvelopeCommand : IRequest<EnvelopeDto?>
|
||||
/// <summary>
|
||||
/// ID des Absenders
|
||||
/// </summary>
|
||||
internal int UserId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
public bool Authorize(int userId)
|
||||
{
|
||||
UserId = userId;
|
||||
return true;
|
||||
}
|
||||
public int UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines which component is used for envelope processing.
|
||||
|
||||
@@ -4,6 +4,7 @@ using EnvelopeGenerator.Application.Common.Query;
|
||||
using EnvelopeGenerator.Application.Common.Dto;
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@@ -20,14 +21,9 @@ public record ReadEnvelopeQuery : EnvelopeQueryBase, IRequest<IEnumerable<Envelo
|
||||
public EnvelopeStatusQuery? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optionaler Benutzerfilter; wenn gesetzt, werden nur Umschläge des Benutzers geladen.
|
||||
///
|
||||
/// </summary>
|
||||
public int? UserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Setzt den Benutzerkontext für die Abfrage.
|
||||
/// </summary>
|
||||
public ReadEnvelopeQuery Authorize(int userId) => this with { UserId = userId };
|
||||
public bool? HasDocResult { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -83,22 +79,23 @@ public record EnvelopeStatusQuery
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verarbeitet <see cref="ReadEnvelopeQuery"/> und liefert passende <see cref="EnvelopeDto"/>-Ergebnisse.
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnumerable<EnvelopeDto>>
|
||||
{
|
||||
private readonly IRepository<Envelope> _repository;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly IRepository<Envelope> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadEnvelopeQueryHandler(IRepository<Envelope> repository, IMapper mapper)
|
||||
/// <param name="repo"></param>
|
||||
public ReadEnvelopeQueryHandler(IMapper mapper, IRepository<Envelope> repo)
|
||||
{
|
||||
_repository = repository;
|
||||
_mapper = mapper;
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,34 +104,24 @@ public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnum
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<IEnumerable<EnvelopeDto>> Handle(ReadEnvelopeQuery request, CancellationToken cancel)
|
||||
{
|
||||
var query = _repository.Query;
|
||||
var envelopesQ = _repo.Query.Where(request, notnull: false);
|
||||
|
||||
if (request.UserId is int userId)
|
||||
query = query.Where(e => e.UserId == userId);
|
||||
EnvelopeStatusQuery? statusQ = request.Status;
|
||||
bool? hasDocResult = request.HasDocResult;
|
||||
|
||||
if (request.Id is int id)
|
||||
query = query.Where(e => e.Id == id);
|
||||
var filtered =
|
||||
from envelope in envelopesQ
|
||||
where (statusQ == null || statusQ.Include == null || statusQ.Include.Contains(envelope.Status))
|
||||
&& (statusQ == null || statusQ.Ignore == null || !statusQ.Ignore.Contains(envelope.Status))
|
||||
&& (statusQ == null || statusQ.Min == null || envelope.Status > statusQ.Min)
|
||||
&& (statusQ == null || statusQ.Max == null || envelope.Status < statusQ.Max)
|
||||
&& (!hasDocResult.HasValue || (hasDocResult.Value ? envelope.DocResult != null : envelope.DocResult == null))
|
||||
select envelope;
|
||||
|
||||
if (request.Uuid is string uuid)
|
||||
query = query.Where(e => e.Uuid == uuid);
|
||||
|
||||
if (request.Status is { } status)
|
||||
{
|
||||
if (status.Min is not null)
|
||||
query = query.Where(e => e.Status >= status.Min);
|
||||
if (status.Max is not null)
|
||||
query = query.Where(e => e.Status <= status.Max);
|
||||
if (status.Include?.Length > 0)
|
||||
query = query.Where(e => status.Include.Contains(e.Status));
|
||||
if (status.Ignore?.Length > 0)
|
||||
query = query.Where(e => !status.Ignore.Contains(e.Status));
|
||||
}
|
||||
|
||||
var envelopes = await query
|
||||
.Include(e => e.Documents)
|
||||
.ToListAsync(cancel);
|
||||
var envelopes = await filtered.ToListAsync(cancel);
|
||||
|
||||
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EnvelopeGenerator.Application.Receivers.Queries;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
|
||||
@@ -10,54 +6,6 @@ namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
||||
/// Eine Abfrage, um die zuletzt verwendete Anrede eines Empfängers zu ermitteln,
|
||||
/// damit diese für zukünftige Umschläge wiederverwendet werden kann.
|
||||
/// </summary>
|
||||
public record ReadReceiverNameQuery() : ReceiverQueryBase, IRequest<string?>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadReceiverNameQueryHandler : IRequestHandler<ReadReceiverNameQuery, string?>
|
||||
public record ReadReceiverNameQuery() : ReadReceiverQuery
|
||||
{
|
||||
private readonly IRepository<EnvelopeReceiver> _envelopeReceiverRepository;
|
||||
private readonly IRepository<Receiver> _receiverRepository;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="envelopeReceiverRepository"></param>
|
||||
/// <param name="receiverRepository"></param>
|
||||
public ReadReceiverNameQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiverRepository, IRepository<Receiver> receiverRepository)
|
||||
{
|
||||
_envelopeReceiverRepository = envelopeReceiverRepository;
|
||||
_receiverRepository = receiverRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<string?> Handle(ReadReceiverNameQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var receiverQuery = _receiverRepository.Query.AsNoTracking();
|
||||
|
||||
if (request.Id is int id)
|
||||
receiverQuery = receiverQuery.Where(r => r.Id == id);
|
||||
if (request.EmailAddress is string email)
|
||||
receiverQuery = receiverQuery.Where(r => r.EmailAddress == email);
|
||||
if (request.Signature is string signature)
|
||||
receiverQuery = receiverQuery.Where(r => r.Signature == signature);
|
||||
|
||||
var receiver = await receiverQuery.FirstOrDefaultAsync(cancellationToken);
|
||||
if (receiver is null)
|
||||
return null;
|
||||
|
||||
var erName = await _envelopeReceiverRepository.Query
|
||||
.Where(er => er.ReceiverId == receiver.Id)
|
||||
.OrderByDescending(er => er.AddedWhen)
|
||||
.Select(er => er.Name)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
return erName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BurnAnnotationException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BurnAnnotationException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BurnAnnotationException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CreateReportException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public CreateReportException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public CreateReportException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ExportDocumentException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public ExportDocumentException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public ExportDocumentException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace EnvelopeGenerator.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class MergeDocumentException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public MergeDocumentException(string message)
|
||||
: base(message) { }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="innerException"></param>
|
||||
public MergeDocumentException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public record CreateHistoryCommand : EnvelopeReceiverQueryBase, IRequest<History
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public DateTime AddedWhen { get; } = DateTime.Now;
|
||||
public DateTime AddedWhen { get; } = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
@@ -82,7 +82,7 @@ public class CreateHistoryCommandHandler : IRequestHandler<CreateHistoryCommand,
|
||||
if(request.UserReference is null)
|
||||
{
|
||||
var receivers = await _erRepo
|
||||
.Query
|
||||
.ReadOnly()
|
||||
.Where(request)
|
||||
.Include(er => er.Receiver)
|
||||
.ToListAsync(cancel);
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
//TODO: Add sender query
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||
/// </summary>
|
||||
public record CountHistoryQuery : HistoryQueryBase, IRequest<int>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class CountHistoryQueryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="uuid"></param>
|
||||
/// <param name="statuses"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<bool> AnyHistoryAsync(this ISender sender, string uuid, IEnumerable<EnvelopeStatus> statuses, CancellationToken cancel = default)
|
||||
{
|
||||
var count = await sender.Send(new CountHistoryQuery
|
||||
{
|
||||
Envelope = new() { Uuid = uuid },
|
||||
Statuses = new() { Include = statuses }
|
||||
}, cancel);
|
||||
return count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CountHistoryQueryHandler : IRequestHandler<CountHistoryQuery, int>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
public CountHistoryQueryHandler(IRepository<History> repo)
|
||||
{
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public Task<int> Handle(CountHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if (request.Envelope.Id is int envId)
|
||||
query = query.Where(e => e.Id == envId);
|
||||
else if (request.Envelope.Uuid is string uuid)
|
||||
query = query.Where(e => e.Envelope!.Uuid == uuid);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
else if (request.EnvelopeId is not null)
|
||||
query = query.Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
else
|
||||
throw new BadRequestException("Invalid request: An Envelope object or a valid EnvelopeId/UUID must be supplied.");
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
if (request.Statuses is not null)
|
||||
{
|
||||
var status = request.Statuses;
|
||||
if (status.Min is not null)
|
||||
query = query.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
query = query.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Count() > 0)
|
||||
query = query.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
query = query.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
return query.CountAsync(cancel);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
//TODO: Add sender query
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record HistoryQueryBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des Umschlags.
|
||||
/// </summary>
|
||||
[Obsolete("Use Envelope property")]
|
||||
public int? EnvelopeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.
|
||||
/// </summary>
|
||||
[Obsolete("Use statuses")]
|
||||
public EnvelopeStatus? Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public EnvelopeStatusQuery Statuses { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public EnvelopeQueryBase Envelope { get; set; } = new EnvelopeQueryBase();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record EnvelopeStatusQuery
|
||||
{
|
||||
/// <summary>
|
||||
/// Der minimale Statuswert, der berücksichtigt werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Min { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der maximale Statuswert, der berücksichtigt werden.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Max { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Eine Liste von Statuswerten, die einbezogen werden.
|
||||
/// </summary>
|
||||
public IEnumerable<EnvelopeStatus>? Include { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Eine Liste von Statuswerten, die ignoriert werden werden.
|
||||
/// </summary>
|
||||
public IEnumerable<EnvelopeStatus>? Ignore { get; init; }
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
@@ -12,81 +9,21 @@ namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||
/// </summary>
|
||||
public record ReadHistoryQuery : HistoryQueryBase, IRequest<IEnumerable<HistoryDto>>
|
||||
public record ReadHistoryQuery : IRequest<IEnumerable<HistoryDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des Umschlags.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int EnvelopeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.
|
||||
/// </summary>
|
||||
public EnvelopeStatus? Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Abfrage zur Steuerung, ob nur der aktuelle Include oder der gesamte Datensatz zurückgegeben wird.
|
||||
/// </summary>
|
||||
public bool OnlyLast { get; init; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<HistoryDto>>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadHistoryQueryHandler(IRepository<History> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public async Task<IEnumerable<HistoryDto>> Handle(ReadHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.Query;
|
||||
|
||||
if (request.Envelope.Id is int envId)
|
||||
query = query.Where(e => e.Id == envId);
|
||||
else if (request.Envelope.Uuid is string uuid)
|
||||
query = query.Where(e => e.Envelope!.Uuid == uuid);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
else if (request.EnvelopeId is not null)
|
||||
query = query.Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
else
|
||||
throw new BadRequestException("Invalid request: An Envelope object or a valid EnvelopeId/UUID must be supplied.");
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
if (request.Statuses is not null)
|
||||
{
|
||||
var status = request.Statuses;
|
||||
if (status.Min is not null)
|
||||
query = query.Where(er => er.Envelope!.Status >= status.Min);
|
||||
|
||||
if (status.Max is not null)
|
||||
query = query.Where(er => er.Envelope!.Status <= status.Max);
|
||||
|
||||
if (status.Include?.Count() > 0)
|
||||
query = query.Where(er => status.Include.Contains(er.Envelope!.Status));
|
||||
|
||||
if (status.Ignore is not null)
|
||||
query = query.Where(er => !status.Ignore.Contains(er.Envelope!.Status));
|
||||
}
|
||||
|
||||
if (request.OnlyLast)
|
||||
query = query.OrderByDescending(x => x.AddedWhen);
|
||||
|
||||
var hists = await query.ToListAsync(cancel);
|
||||
return _mapper.Map<List<HistoryDto>>(hists);
|
||||
}
|
||||
public bool? OnlyLast { get; init; } = true;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Dto.History;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<HistoryDto>>
|
||||
{
|
||||
private readonly IRepository<History> _repo;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadHistoryQueryHandler(IRepository<History> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
public async Task<IEnumerable<HistoryDto>> Handle(ReadHistoryQuery request, CancellationToken cancel = default)
|
||||
{
|
||||
var query = _repo.ReadOnly().Where(h => h.EnvelopeId == request.EnvelopeId);
|
||||
if (request.Status is not null)
|
||||
query = query.Where(h => h.Status == request.Status);
|
||||
|
||||
var hists = await query.ToListAsync(cancel);
|
||||
return _mapper.Map<List<HistoryDto>>(hists);
|
||||
}
|
||||
}
|
||||
107
EnvelopeGenerator.Application/Pdf/Behaviors/AddReportBehavior.cs
Normal file
107
EnvelopeGenerator.Application/Pdf/Behaviors/AddReportBehavior.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Application.Histories.Commands;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Application.EnvelopeReports;
|
||||
using EnvelopeGenerator.Application.Exceptions;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class AddReportBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
|
||||
{
|
||||
private readonly ISender _sender;
|
||||
|
||||
private readonly ILogger<AddReportBehavior> _logger;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="logger"></param>
|
||||
public AddReportBehavior(ISender sender, ILogger<AddReportBehavior> logger)
|
||||
{
|
||||
_sender = sender;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
|
||||
{
|
||||
var docResult = await next(cancel);
|
||||
var base64 = Convert.ToBase64String(docResult);
|
||||
|
||||
if (!request.Debug)
|
||||
await _sender.Send(new CreateHistoryCommand()
|
||||
{
|
||||
EnvelopeId = request.EnvelopeId,
|
||||
UserReference = "System",
|
||||
Status = EnvelopeStatus.EnvelopeReportCreated,
|
||||
}, cancel);
|
||||
|
||||
docResult = await CreateReport(request.Envelope!, cancel);
|
||||
|
||||
return docResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="envelope"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="CreateReportException"></exception>
|
||||
public async Task<byte[]> CreateReport(Envelope envelope, CancellationToken cancel)
|
||||
{
|
||||
var oItems = await _sender.ReadEnvelopeReportAsync(envelope.Id, cancel: cancel);
|
||||
|
||||
if (!oItems.Any())
|
||||
{
|
||||
throw new CreateReportException("No report data found!");
|
||||
}
|
||||
|
||||
var oBuffer = DoCreateReport(oItems);
|
||||
|
||||
return oBuffer;
|
||||
}
|
||||
|
||||
private byte[] DoCreateReport(IEnumerable<EnvelopeReport> oItems)
|
||||
{
|
||||
var oSource = new ReportSource { Items = oItems };
|
||||
var oReport = new rptEnvelopeHistory
|
||||
{
|
||||
DataSource = oSource,
|
||||
DataMember = "Items"
|
||||
};
|
||||
|
||||
// Creating report in memory
|
||||
oReport.CreateDocument();
|
||||
|
||||
// Exporting report to stream
|
||||
using var oStream = new MemoryStream();
|
||||
oReport.ExportToPdf(oStream);
|
||||
|
||||
// Writing report to buffer
|
||||
return oStream.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReportSource
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public required IEnumerable<EnvelopeReport> Items { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Pdf.Behaviors;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class SavePdfBehavior : IPipelineBehavior<BurnPdfCommand, byte[]>
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="next"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> Handle(BurnPdfCommand request, RequestHandlerDelegate<byte[]> next, CancellationToken cancel)
|
||||
{
|
||||
var docResult = await next(cancel);
|
||||
var base64 = Convert.ToBase64String(docResult);
|
||||
return docResult;
|
||||
}
|
||||
}
|
||||
299
EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs
Normal file
299
EnvelopeGenerator.Application/Pdf/BurnPdfCommand.cs
Normal file
@@ -0,0 +1,299 @@
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using DigitalData.Core.Exceptions;
|
||||
using EnvelopeGenerator.Application.Common.Configurations;
|
||||
using EnvelopeGenerator.Application.Common.Dto.PSPDFKitInstant;
|
||||
using EnvelopeGenerator.Application.Common.Extensions;
|
||||
using EnvelopeGenerator.Application.Exceptions;
|
||||
using EnvelopeGenerator.Domain.Constants;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using GdPicture14;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Pdf;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public record BurnPdfCommand(int? EnvelopeId = null, string? EnvelopeUuid = null) : IRequest<byte[]>
|
||||
{
|
||||
internal bool Debug { get; set; }
|
||||
|
||||
internal Envelope? Envelope { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static class BurnPdfCommandExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="envelopeId"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<byte[]> BurnPdf(this ISender sender, int envelopeId, CancellationToken cancel = default)
|
||||
=> sender.Send(new BurnPdfCommand(EnvelopeId: envelopeId), cancel);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="envelopeUuid"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
public static Task<byte[]> BurnPdf(this ISender sender, string envelopeUuid, CancellationToken cancel = default)
|
||||
=> sender.Send(new BurnPdfCommand(EnvelopeUuid: envelopeUuid), cancel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class BurnPdfCommandHandler : IRequestHandler<BurnPdfCommand, byte[]>
|
||||
{
|
||||
private readonly PDFBurnerParams _options;
|
||||
|
||||
private readonly AnnotationManager _manager;
|
||||
|
||||
private readonly ILogger<BurnPdfCommandHandler> _logger;
|
||||
|
||||
private readonly IRepository<Envelope> _envRepo;
|
||||
|
||||
private readonly IRepository<Domain.Entities.DocumentStatus> _docStatusRepo;
|
||||
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="pdfBurnerParams"></param>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="envRepo"></param>
|
||||
/// <param name="docStatusRepo"></param>
|
||||
/// <param name="config"></param>
|
||||
public BurnPdfCommandHandler(IOptions<PDFBurnerParams> pdfBurnerParams, AnnotationManager manager, ILogger<BurnPdfCommandHandler> logger, IRepository<Envelope> envRepo, IRepository<Domain.Entities.DocumentStatus> docStatusRepo, IConfiguration config)
|
||||
{
|
||||
_options = pdfBurnerParams.Value;
|
||||
_manager = manager;
|
||||
_docStatusRepo = docStatusRepo;
|
||||
_logger = logger;
|
||||
_envRepo = envRepo;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancel"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
public async Task<byte[]> Handle(BurnPdfCommand request, CancellationToken cancel)
|
||||
{
|
||||
request.Debug = _config.GetValue<bool>("Debug");
|
||||
var envQuery =
|
||||
request.EnvelopeId is not null ? _envRepo.Where(env => env.Id == request.EnvelopeId) :
|
||||
request.EnvelopeUuid is not null ? _envRepo.Where(env => env.Uuid == request.EnvelopeUuid) :
|
||||
throw new BadRequestException("Request validation failed: Either Envelope Id or Envelope Uuid must be provided.");
|
||||
|
||||
request.Envelope = await envQuery
|
||||
.Include(env => env.Documents!).ThenInclude(doc => doc.Elements!).ThenInclude(element => element.Annotations)
|
||||
.FirstOrDefaultAsync(cancel)
|
||||
?? throw new BadRequestException($"Envelope could not be found. Request details:\n" +
|
||||
request.ToJson(Format.Json.ForDiagnostics));
|
||||
|
||||
var doc = request.Envelope.Documents?.FirstOrDefault()
|
||||
?? throw new NotFoundException($"Document could not be located within the specified envelope. Request details:\n" +
|
||||
request.ToJson(Format.Json.ForDiagnostics));
|
||||
|
||||
if (doc.ByteData is null)
|
||||
throw new InvalidOperationException($"Document byte data is missing, indicating a potential data integrity issue. Request details:\n" +
|
||||
request.ToJson(Format.Json.ForDiagnostics));
|
||||
|
||||
return doc.Elements?.SelectMany(e => e.Annotations ?? Enumerable.Empty<ElementAnnotation>()).Where(annot => annot is not null).Any() ?? false
|
||||
? BurnElementAnnotsToPDF(doc.ByteData, doc.Elements)
|
||||
: BurnInstantJSONAnnotsToPDF(doc.ByteData, await _docStatusRepo
|
||||
.Where(status => status.EnvelopeId == request.Envelope.Id)
|
||||
.Select(status => status.Value)
|
||||
.ToListAsync(cancel));
|
||||
}
|
||||
|
||||
private byte[] BurnElementAnnotsToPDF(byte[] pSourceBuffer, List<Signature> elements)
|
||||
{
|
||||
// Add background
|
||||
using var doc = PdfEditor.Pdf.FromMemory(pSourceBuffer);
|
||||
// TODO: take the length from the largest y
|
||||
pSourceBuffer = doc.Background(elements, 1.9500000000000002 * 0.93, 2.52 * 0.67)
|
||||
.ExportStream()
|
||||
.ToArray();
|
||||
|
||||
GdPictureStatus oResult;
|
||||
using var oSourceStream = new MemoryStream(pSourceBuffer);
|
||||
// Open PDF
|
||||
oResult = _manager.InitFromStream(oSourceStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
throw new BurnAnnotationException($"Could not open document for burning: [{oResult}]");
|
||||
|
||||
// Imported from background (add to configuration)
|
||||
var margin = 0.2;
|
||||
var inchFactor = 72;
|
||||
|
||||
// Y offset of form fields
|
||||
var keys = new[] { "position", "city", "date" }; // add to configuration
|
||||
var unitYOffsets = 0.2;
|
||||
|
||||
var yOffsetsOfFF = keys
|
||||
.Select((k, i) => new { Key = k, Value = unitYOffsets * i + 1 })
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
|
||||
// Add annotations
|
||||
foreach (var element in elements)
|
||||
{
|
||||
var frameX = element.Left - 0.7 - margin;
|
||||
|
||||
var frame = element.Annotations?.FirstOrDefault(a => a.Name == "frame");
|
||||
var frameY = element.Top - 0.5 - margin;
|
||||
var frameYShift = (frame!.Y ?? default) - frameY * inchFactor;
|
||||
var frameXShift = (frame.X ?? default) - frameX * inchFactor;
|
||||
|
||||
foreach (var annot in element.Annotations!)
|
||||
{
|
||||
if (!yOffsetsOfFF.TryGetValue(annot.Name, out var yOffsetofFF))
|
||||
yOffsetofFF = 0;
|
||||
|
||||
var y = frameY + yOffsetofFF;
|
||||
|
||||
if (annot.Type == AnnotationType.PSPDFKit.FormField)
|
||||
{
|
||||
_manager.AddFormFieldValue(
|
||||
(annot.X ?? default) / inchFactor,
|
||||
y,
|
||||
(annot.Width ?? default) / inchFactor,
|
||||
(annot.Height ?? default) / inchFactor,
|
||||
element.Page,
|
||||
annot.Value,
|
||||
_options
|
||||
);
|
||||
}
|
||||
else if (annot.Type == AnnotationType.PSPDFKit.Image)
|
||||
{
|
||||
_manager.AddImageAnnotation(
|
||||
(annot.X ?? default) / inchFactor,
|
||||
annot.Name == "signature" ? ((annot.Y ?? default) - frameYShift) / inchFactor : y,
|
||||
(annot.Width ?? default) / inchFactor,
|
||||
(annot.Height ?? default) / inchFactor,
|
||||
element.Page,
|
||||
annot.Value
|
||||
);
|
||||
}
|
||||
else if (annot.Type == AnnotationType.PSPDFKit.Ink)
|
||||
{
|
||||
_manager.AddInkAnnotation(element.Page, annot.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save PDF
|
||||
using var oNewStream = new MemoryStream();
|
||||
oResult = _manager.SaveDocumentToPDF(oNewStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
throw new BurnAnnotationException($"Could not save document to stream: [{oResult}]");
|
||||
|
||||
_manager.Close();
|
||||
|
||||
return oNewStream.ToArray();
|
||||
}
|
||||
|
||||
private byte[] BurnInstantJSONAnnotsToPDF(byte[] pSourceBuffer, List<string> pInstantJSONList)
|
||||
{
|
||||
GdPictureStatus oResult;
|
||||
|
||||
using var oSourceStream = new MemoryStream(pSourceBuffer);
|
||||
// Open PDF
|
||||
oResult = _manager.InitFromStream(oSourceStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
{
|
||||
throw new BurnAnnotationException($"Could not open document for burning: [{oResult}]");
|
||||
}
|
||||
|
||||
// Add annotation to PDF
|
||||
foreach (var oJSON in pInstantJSONList)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (oJSON is string json)
|
||||
AddInstantJsonAnnotationToPdf(json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning("Error in AddInstantJSONAnnotationToPDF - oJson: ");
|
||||
_logger.LogWarning(oJSON);
|
||||
throw new BurnAnnotationException("Adding Annotation failed", ex);
|
||||
}
|
||||
}
|
||||
|
||||
oResult = _manager.BurnAnnotationsToPage(RemoveInitialAnnots: true, VectorMode: true);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
{
|
||||
throw new BurnAnnotationException($"Could not burn annotations to file: [{oResult}]");
|
||||
}
|
||||
|
||||
// Save PDF
|
||||
using var oNewStream = new MemoryStream();
|
||||
oResult = _manager.SaveDocumentToPDF(oNewStream);
|
||||
if (oResult != GdPictureStatus.OK)
|
||||
{
|
||||
throw new BurnAnnotationException($"Could not save document to stream: [{oResult}]");
|
||||
}
|
||||
|
||||
_manager.Close();
|
||||
|
||||
return oNewStream.ToArray();
|
||||
}
|
||||
|
||||
private void AddInstantJsonAnnotationToPdf(string instantJson)
|
||||
{
|
||||
var annotationData = JsonConvert.DeserializeObject<InstantData>(instantJson);
|
||||
|
||||
annotationData?.Annotations?.Reverse();
|
||||
|
||||
if (annotationData?.Annotations is null)
|
||||
return;
|
||||
|
||||
foreach (var annotation in annotationData.Annotations)
|
||||
{
|
||||
_logger.LogDebug("Adding AnnotationID: {id}", annotation.Id);
|
||||
|
||||
switch (annotation.Type)
|
||||
{
|
||||
case AnnotationType.PSPDFKit.Image:
|
||||
if (annotationData?.Attachments is not null)
|
||||
_manager.AddImageAnnotation(annotation, annotationData.Attachments);
|
||||
break;
|
||||
|
||||
case AnnotationType.PSPDFKit.Ink:
|
||||
_manager.AddInkAnnotation(annotation);
|
||||
break;
|
||||
|
||||
case AnnotationType.PSPDFKit.Widget:
|
||||
// Add form field values
|
||||
var formFieldValue = annotationData?.FormFieldValues?
|
||||
.FirstOrDefault(fv => fv.Name == annotation.Id);
|
||||
|
||||
if (formFieldValue != null && !_options.IgnoredLabels.Contains(formFieldValue.Value))
|
||||
{
|
||||
_manager.AddFormFieldValue(annotation, formFieldValue, _options);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,6 @@ public class CreateReceiverCommandHandler : IRequestHandler<CreateReceiverComman
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repo"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public CreateReceiverCommandHandler(IRepository<Receiver> repo, IMapper mapper)
|
||||
{
|
||||
_repo = repo;
|
||||
@@ -82,7 +81,7 @@ public class CreateReceiverCommandHandler : IRequestHandler<CreateReceiverComman
|
||||
/// <returns></returns>
|
||||
public async Task<(ReceiverDto Receiver, bool AlreadyExists)> Handle(CreateReceiverCommand request, CancellationToken cancel)
|
||||
{
|
||||
var receiver = await _repo.Query
|
||||
var receiver = await _repo.ReadOnly()
|
||||
.Where(r => r.EmailAddress == request.EmailAddress)
|
||||
.SingleOrDefaultAsync(cancel);
|
||||
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstraction.Application.Repository;
|
||||
using EnvelopeGenerator.Application.Common.Dto.Receiver;
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
using MediatR;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using EnvelopeGenerator.Application.Common.Query;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Receivers.Queries;
|
||||
|
||||
@@ -12,53 +6,4 @@ namespace EnvelopeGenerator.Application.Receivers.Queries;
|
||||
/// Stellt eine Abfrage dar, um die Details eines Empfängers zu lesen.
|
||||
/// um spezifische Informationen über einen Empfänger abzurufen.
|
||||
/// </summary>
|
||||
public record ReadReceiverQuery : ReceiverQueryBase, IRequest<IEnumerable<ReceiverDto>>;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class ReadReceiverQueryHandler : IRequestHandler<ReadReceiverQuery, IEnumerable<ReceiverDto>>
|
||||
{
|
||||
private readonly IRepository<Receiver> _repository;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="repository"></param>
|
||||
/// <param name="mapper"></param>
|
||||
public ReadReceiverQueryHandler(IRepository<Receiver> repository, IMapper mapper)
|
||||
{
|
||||
_repository = repository;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IEnumerable<ReceiverDto>> Handle(ReadReceiverQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _repository.Query;
|
||||
|
||||
if (request.Id is int id)
|
||||
{
|
||||
query = query.Where(r => r.Id == id);
|
||||
}
|
||||
|
||||
if (request.EmailAddress is string email)
|
||||
{
|
||||
query = query.Where(r => r.EmailAddress == email);
|
||||
}
|
||||
|
||||
if (request.Signature is string signature)
|
||||
{
|
||||
query = query.Where(r => r.Signature == signature);
|
||||
}
|
||||
|
||||
var receiver = await query.ToListAsync(cancellationToken);
|
||||
return _mapper.Map<IEnumerable<ReceiverDto>>(receiver);
|
||||
}
|
||||
}
|
||||
public record ReadReceiverQuery : ReceiverQueryBase;
|
||||
@@ -123,9 +123,6 @@
|
||||
<data name="Back" xml:space="preserve">
|
||||
<value>Zurück</value>
|
||||
</data>
|
||||
<data name="AuthenticatorSetup_Prefix" xml:space="preserve">
|
||||
<value>Klicken Sie auf den</value>
|
||||
</data>
|
||||
<data name="Complete" xml:space="preserve">
|
||||
<value>Abschließen</value>
|
||||
</data>
|
||||
@@ -147,9 +144,6 @@
|
||||
<data name="DocSigned" xml:space="preserve">
|
||||
<value>Dokument unterschrieben</value>
|
||||
</data>
|
||||
<data name="DocumentSharingPeriodExpired" xml:space="preserve">
|
||||
<value>Der Zeitraum für die gemeinsame Nutzung von Dokumenten ist abgelaufen.</value>
|
||||
</data>
|
||||
<data name="en-US" xml:space="preserve">
|
||||
<value>Englisch</value>
|
||||
</data>
|
||||
@@ -159,9 +153,6 @@
|
||||
<data name="EnvelopeInfo2" xml:space="preserve">
|
||||
<value>Erstellt am {0} von {1}. Sie können den Absender über <span class="highlight highlight-envelope-info-2"><a class="mail-link" href="mailto:{2}?subject={3}&body=Sehr%20geehrter%20{4}%20{5},%0A%0A%0A">{6}</a></span> kontaktieren.</value>
|
||||
</data>
|
||||
<data name="Expired" xml:space="preserve">
|
||||
<value>Abgelaufen</value>
|
||||
</data>
|
||||
<data name="FiClass" xml:space="preserve">
|
||||
<value>fi-de</value>
|
||||
</data>
|
||||
@@ -174,9 +165,6 @@
|
||||
<data name="HomePageDescription" xml:space="preserve">
|
||||
<value>Das digitale Unterschriftenportal ist eine Plattform, die entwickelt wurde, um Ihre Dokumente sicher zu unterschreiben und zu verwalten. Mit seiner benutzerfreundlichen Oberfläche können Sie Ihre Dokumente schnell hochladen, die Unterschriftsprozesse verfolgen und Ihre digitalen Unterschriftenanwendungen einfach durchführen. Dieses Portal beschleunigt Ihren Arbeitsablauf mit rechtlich gültigen Unterschriften und erhöht gleichzeitig die Sicherheit Ihrer Dokumente.</value>
|
||||
</data>
|
||||
<data name="AuthenticatorSetup_Link" xml:space="preserve">
|
||||
<value>Link</value>
|
||||
</data>
|
||||
<data name="LocationWarning" xml:space="preserve">
|
||||
<value>Bitte überprüfen Sie die Standortinformationen. Wenn sie falsch sind, korrigieren Sie diese bitte.</value>
|
||||
</data>
|
||||
@@ -276,175 +264,4 @@
|
||||
<data name="WrongAccessCode" xml:space="preserve">
|
||||
<value>Ungültiger Zugangscode.</value>
|
||||
</data>
|
||||
<data name="AuthenticatorSetup_Suffix" xml:space="preserve">
|
||||
<value>um Ihre Authenticator-App einzurichten.</value>
|
||||
</data>
|
||||
<data name="DocumentSuccessfullySigned" xml:space="preserve">
|
||||
<value>Dokument erfolgreich signiert!</value>
|
||||
</data>
|
||||
<data name="DocumentSignedConfirmationMessage" xml:space="preserve">
|
||||
<value>Sie haben das Dokument signiert. Im Anschluss erhalten Sie eine schriftliche Bestätigung.</value>
|
||||
</data>
|
||||
<data name="Signatures" xml:space="preserve">
|
||||
<value>Unterschriften</value>
|
||||
</data>
|
||||
<data name="EnterRecipientToShareDocument" xml:space="preserve">
|
||||
<value>Geben Sie hier den Empfänger ein, mit welchem Sie das Dokument teilen wollen</value>
|
||||
</data>
|
||||
<data name="Email" xml:space="preserve">
|
||||
<value>E-Mail</value>
|
||||
</data>
|
||||
<data name="ValidUntil" xml:space="preserve">
|
||||
<value>Gültig bis</value>
|
||||
</data>
|
||||
<data name="ShrEnvInvalidEmailTitle" xml:space="preserve">
|
||||
<value>Falsche Email</value>
|
||||
</data>
|
||||
<data name="ShrEnvInvalidEmailText" xml:space="preserve">
|
||||
<value>Die E-Mail-Adresse ist ungültig. Bitte verwenden Sie das richtige Format, z. B.: user@mail.com.</value>
|
||||
</data>
|
||||
<data name="ShrEnvSentTitle" xml:space="preserve">
|
||||
<value>Gesendet</value>
|
||||
</data>
|
||||
<data name="ShrEnvErrorTitle" xml:space="preserve">
|
||||
<value>Fehler</value>
|
||||
</data>
|
||||
<data name="InvalidDateTitle" xml:space="preserve">
|
||||
<value>Falsches Datum</value>
|
||||
</data>
|
||||
<data name="ShrEnvInvalidDateText" xml:space="preserve">
|
||||
<value>Die E-Mail-Adresse ist ungültig. Bitte verwenden Sie das richtige Format, z. B.: user@mail.com.</value>
|
||||
</data>
|
||||
<data name="UnexpectedErrorTitle" xml:space="preserve">
|
||||
<value>Unerwarteter Fehler</value>
|
||||
</data>
|
||||
<data name="ShrEnvOperationFailedText" xml:space="preserve">
|
||||
<value>Der Vorgang ist fehlgeschlagen. Bitte wenden Sie sich an das IT-Team.</value>
|
||||
</data>
|
||||
<data name="PrivacyNotice" xml:space="preserve">
|
||||
<value>Datenschutzhinweis</value>
|
||||
</data>
|
||||
<data name="CookieConsentMessage" xml:space="preserve">
|
||||
<value>Wir verwenden technisch notwendige Session Cookies. Diese Cookies sind für den ordnungsgemäßen Betrieb dieser Webseite von nöten und können aus diesm Grund nicht abgewählt werden. Es findet keine Übermittlung an Dritte statt.</value>
|
||||
</data>
|
||||
<data name="Accept" xml:space="preserve">
|
||||
<value>Akzeptieren</value>
|
||||
</data>
|
||||
<data name="ConnectionValidityExpired" xml:space="preserve">
|
||||
<value>Die Gültigkeitsdauer der Verbindung ist abgelaufen.</value>
|
||||
</data>
|
||||
<data name="Creator" xml:space="preserve">
|
||||
<value>Ersteller</value>
|
||||
</data>
|
||||
<data name="Date" xml:space="preserve">
|
||||
<value>Datum</value>
|
||||
</data>
|
||||
<data name="DocumentProtected" xml:space="preserve">
|
||||
<value>Dokument geschützt</value>
|
||||
</data>
|
||||
<data name="Password" xml:space="preserve">
|
||||
<value>Passwort</value>
|
||||
</data>
|
||||
<data name="Open" xml:space="preserve">
|
||||
<value>Öffnen</value>
|
||||
</data>
|
||||
<data name="TfaRegistration" xml:space="preserve">
|
||||
<value>2FA Registrierung</value>
|
||||
</data>
|
||||
<data name="Registration" xml:space="preserve">
|
||||
<value>Registrierung</value>
|
||||
</data>
|
||||
<data name="PageVisibleUntil" xml:space="preserve">
|
||||
<value>Diese Seite ist bis {0} sichtbar.</value>
|
||||
</data>
|
||||
<data name="Step1Download2faApplication" xml:space="preserve">
|
||||
<value>Schritt 1 - Download einer 2FA Applikation</value>
|
||||
</data>
|
||||
<data name="Download2faAppInstruction" xml:space="preserve">
|
||||
<value>Bitte nehmen Sie Ihr Smartphone zur Hand und laden eine Applikation herunter, die zur Zwei-Faktor-Authentifizierung (2FA) benutzt werden kann.</value>
|
||||
</data>
|
||||
<data name="Recommended2faApplications" xml:space="preserve">
|
||||
<value>Folgende Applikationen empfehlen wir</value>
|
||||
</data>
|
||||
<data name="Step2ScanQrCode" xml:space="preserve">
|
||||
<value>Schritt 2 - Scannen des QR-Codes</value>
|
||||
</data>
|
||||
<data name="ScanQrCodeInstruction" xml:space="preserve">
|
||||
<value>Sobald Sie eine Zwei-Faktor-Authentifizierung App installiert haben, können Sie fortfahren und innerhalb der Applikation die Option zum Scannen eines QR-Codes suchen und bestätigen. Im Anschluss, sobald die Kamera freigegeben wurde, können Sie den QR-Code von uns scannen.</value>
|
||||
</data>
|
||||
<data name="Step3VerifyTheCode" xml:space="preserve">
|
||||
<value>Schritt 3 - Verifizierung des Codes</value>
|
||||
</data>
|
||||
<data name="VerifyCodeInstructionMain" xml:space="preserve">
|
||||
<value>Sie können nun in der Zwei-Faktor-Authentifizierung App einen Zahlencode zur Verifizierung des Vorganges ablesen. Bitte tragen Sie diesen Code in das unten aufgeführte Eingabefeld ein und Klicken auf</value>
|
||||
</data>
|
||||
<data name="VerifyCodeInstructionSubmit" xml:space="preserve">
|
||||
<value>Senden</value>
|
||||
</data>
|
||||
<data name="CopyLink" xml:space="preserve">
|
||||
<value>Link kopieren</value>
|
||||
</data>
|
||||
<data name="CityFormatInvalid" xml:space="preserve">
|
||||
<value>Bitte überprüfen Sie die eingegebene Ortsangabe "{0}" auf korrekte Formatierung. Beispiele für richtige Formate sind: München, Île-de-France, Sauðárkrókur, San Francisco, St. Catharines usw.</value>
|
||||
</data>
|
||||
<data name="CopyLinkSuccess" xml:space="preserve">
|
||||
<value>Kopiert</value>
|
||||
</data>
|
||||
<data name="Logout" xml:space="preserve">
|
||||
<value>Abmelden</value>
|
||||
</data>
|
||||
<data name="ViewAllPages" xml:space="preserve">
|
||||
<value>Bitte sehen Sie sich alle Seiten an.</value>
|
||||
</data>
|
||||
<data name="Reset" xml:space="preserve">
|
||||
<value>Zurücksetzen</value>
|
||||
</data>
|
||||
<data name="ViewRemainingPages" xml:space="preserve">
|
||||
<value>Bitte sehen Sie sich die folgenden Seiten an: {0}</value>
|
||||
</data>
|
||||
<data name="City" xml:space="preserve">
|
||||
<value>Ort</value>
|
||||
</data>
|
||||
<data name="EnvelopeRejectedRedirect" xml:space="preserve">
|
||||
<value>Dokument wurde von einem Empfänger abgelehnt. Sie werden weitergeleitet...</value>
|
||||
</data>
|
||||
<data name="MissingSignatures" xml:space="preserve">
|
||||
<value>Es wurden nicht alle Signaturfelder ausgefüllt!</value>
|
||||
</data>
|
||||
<data name="ResetConfirmText" xml:space="preserve">
|
||||
<value>Wollen Sie das Dokument und alle erstellten Signaturen zurücksetzen?</value>
|
||||
</data>
|
||||
<data name="EnvelopeSignError" xml:space="preserve">
|
||||
<value>Umschlag konnte nicht signiert werden!</value>
|
||||
</data>
|
||||
<data name="SignedBy" xml:space="preserve">
|
||||
<value>Signiert von</value>
|
||||
</data>
|
||||
<data name="Warning" xml:space="preserve">
|
||||
<value>Warnung</value>
|
||||
</data>
|
||||
<data name="Position" xml:space="preserve">
|
||||
<value>Position</value>
|
||||
</data>
|
||||
<data name="Share" xml:space="preserve">
|
||||
<value>Teilen</value>
|
||||
</data>
|
||||
<data name="CopyLinkFailure" xml:space="preserve">
|
||||
<value>Unerwarteter Fehler</value>
|
||||
</data>
|
||||
<data name="LocationFieldsRequired" xml:space="preserve">
|
||||
<value>Bitte füllen Sie alle Standortinformationen vollständig aus!</value>
|
||||
</data>
|
||||
<data name="ResetConfirmTitle" xml:space="preserve">
|
||||
<value>Sind Sie sicher?</value>
|
||||
</data>
|
||||
<data name="EnvelopeUnavailable" xml:space="preserve">
|
||||
<value>Umschlag ist nicht mehr verfügbar.</value>
|
||||
</data>
|
||||
<data name="Success" xml:space="preserve">
|
||||
<value>Erfolg</value>
|
||||
</data>
|
||||
<data name="DocumentReset" xml:space="preserve">
|
||||
<value>Dokument wurde zurückgesetzt.</value>
|
||||
</data>
|
||||
</root>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user