Compare commits
8 Commits
f34770931f
...
feat/locat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46f1633f79 | ||
|
|
1af07f0df8 | ||
|
|
55c9dfb9c2 | ||
|
|
1a230306a3 | ||
|
|
28022bc669 | ||
|
|
ad5843b7c9 | ||
|
|
173b691e56 | ||
|
|
8a0fe70a88 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -363,5 +363,3 @@ MigrationBackup/
|
|||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
/EnvelopeGenerator.Web/.config/dotnet-tools.json
|
/EnvelopeGenerator.Web/.config/dotnet-tools.json
|
||||||
/EnvelopeGenerator.GeneratorAPI/ClientApp/envelope-generator-ui/.vscode
|
/EnvelopeGenerator.GeneratorAPI/ClientApp/envelope-generator-ui/.vscode
|
||||||
/EnvelopeGenerator.Tests.Application/Services/BugFixTests.cs
|
|
||||||
/EnvelopeGenerator.Tests.Application/annotations.json
|
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.Application.Configurations;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class AuthenticatorParams
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789'
|
|
||||||
/// </summary>
|
|
||||||
public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789";
|
|
||||||
|
|
||||||
//TODO: Increase the DefaultTotpSecretKeyLength (e.g. to 32) but make sure that the QR code is generated correctly and can be scanned by the authenticator.
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 20
|
|
||||||
/// </summary>
|
|
||||||
public int DefaultTotpSecretKeyLength { get; init; } = 20;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is
|
|
||||||
/// </summary>
|
|
||||||
public string TotpIssuer { get; init; } = "signFlow";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 0 is user email, 1 is secret key and 2 is issuer.
|
|
||||||
/// </summary>
|
|
||||||
public string TotpUrlFormat { get; init; } = "otpauth://totp/{0}?secret={1}&issuer={2}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 20.
|
|
||||||
/// </summary>
|
|
||||||
public int TotpQRPixelsPerModule { get; init; } = 20;
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.Application.Configurations;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class DbTriggerParams : Dictionary<string, ICollection<string>>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
namespace EnvelopeGenerator.Application.Configurations
|
||||||
|
{
|
||||||
|
public class DispatcherConfig
|
||||||
|
{
|
||||||
|
public int SendingProfile { get; init; } = 1;
|
||||||
|
|
||||||
|
public string AddedWho { get; init; } = "DDEnvelopGenerator";
|
||||||
|
|
||||||
|
public int ReminderTypeId { get; init; } = 202377;
|
||||||
|
|
||||||
|
public string EmailAttmt1 { get; init; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.Application.Configurations;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class DispatcherParams
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 1
|
|
||||||
/// </summary>
|
|
||||||
public int SendingProfile { get; init; } = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defalt value is 'DDEnvelopGenerator'
|
|
||||||
/// </summary>
|
|
||||||
public string AddedWho { get; init; } = "DDEnvelopGenerator";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 202377
|
|
||||||
/// </summary>
|
|
||||||
public int ReminderTypeId { get; init; } = 202377;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is string.Empty
|
|
||||||
/// </summary>
|
|
||||||
public string EmailAttmt1 { get; init; } = string.Empty;
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using DigitalData.Core.Client.Interface;
|
|
||||||
namespace EnvelopeGenerator.Application.Configurations;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://www.gtx-messaging.com/en/api-docs/sms-rest-api/
|
|
||||||
/// </summary>
|
|
||||||
public class GtxMessagingParams : IHttpClientOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required string Uri { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? Path { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, object>? Headers { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, object?>? QueryParams { get; init; }
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'to'
|
|
||||||
/// </summary>
|
|
||||||
public string RecipientQueryParamName { get; init; } = "to";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'text'
|
|
||||||
/// </summary>
|
|
||||||
public string MessageQueryParamName { get; init; } = "text";
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace EnvelopeGenerator.Application.Configurations
|
||||||
|
{
|
||||||
|
public class MailConfig
|
||||||
|
{
|
||||||
|
public required Dictionary<string, string> Placeholders { get; init; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.Application.Configurations;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class MailParams
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required Dictionary<string, string> Placeholders { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
using OtpNet;
|
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Configurations;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class TotpSmsParams
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The unit is second.
|
|
||||||
/// </summary>
|
|
||||||
public int TotpStep { get; init; } = 90;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'Ihr 2FA-Passwort lautet {0}. Gültig bis {1}'
|
|
||||||
/// </summary>
|
|
||||||
public string Format { get; init; } = "Ihr 2FA-Passwort lautet {0}. Gültig bis {1}";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public ExpirationHandler Expiration { get; init; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is VerificationWindow.RfcSpecifiedNetworkDelay
|
|
||||||
/// </summary>
|
|
||||||
public VerificationWindow? TotpVerificationWindow { get; private init; } = VerificationWindow.RfcSpecifiedNetworkDelay;
|
|
||||||
|
|
||||||
private IEnumerable<int>? _tvwParams;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<int>? TotpVerificationWindowParams
|
|
||||||
{
|
|
||||||
get => _tvwParams;
|
|
||||||
init
|
|
||||||
{
|
|
||||||
_tvwParams = value;
|
|
||||||
if(_tvwParams is not null)
|
|
||||||
TotpVerificationWindow = new(previous: _tvwParams.ElementAtOrDefault(0), future: _tvwParams.ElementAtOrDefault(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class ExpirationHandler
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'e{0}_r{1}_sms_code_expiration'
|
|
||||||
/// </summary>
|
|
||||||
public string CacheKeyFormat { get; init; } = "e{0}_r{1}_sms_code_expiration";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is HH:mm:ss
|
|
||||||
/// </summary>
|
|
||||||
public string Format { get; init; } = "HH:mm:ss";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'de-DE'
|
|
||||||
/// </summary>
|
|
||||||
public string CultureName
|
|
||||||
{
|
|
||||||
get => _cultureInfo.Name;
|
|
||||||
init => _cultureInfo = new(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'de-DE'
|
|
||||||
/// </summary>
|
|
||||||
private CultureInfo _cultureInfo = new("de-DE");
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'de-DE'
|
|
||||||
/// </summary>
|
|
||||||
public CultureInfo CultureInfo => _cultureInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
EnvelopeGenerator.Application/Contracts/IConfigService.cs
Normal file
17
EnvelopeGenerator.Application/Contracts/IConfigService.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IConfigService : IReadService<ConfigDto, Config, int>
|
||||||
|
{
|
||||||
|
Task<DataResult<ConfigDto>> ReadFirstAsync();
|
||||||
|
|
||||||
|
Task<ConfigDto> ReadDefaultAsync();
|
||||||
|
|
||||||
|
Task<string> ReadDefaultSignatureHost();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IDocumentReceiverElementService : IBasicCRUDService<DocumentReceiverElementDto, DocumentReceiverElement, int>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IDocumentStatusService : IBasicCRUDService<DocumentStatusDto, DocumentStatus, int>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEmailTemplateService : IBasicCRUDService<EmailTemplateDto, EmailTemplate, int>
|
||||||
|
{
|
||||||
|
Task<DataResult<EmailTemplateDto>> ReadByNameAsync(EmailTemplateType type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeCertificateService : IBasicCRUDService<EnvelopeCertificateDto, EnvelopeCertificate, int>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeDocumentService : IBasicCRUDService<EnvelopeDocumentDto, EnvelopeDocument, int>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeHistoryService : ICRUDService<EnvelopeHistoryCreateDto, EnvelopeHistoryDto, EnvelopeHistoryDto, EnvelopeHistory, long>
|
||||||
|
{
|
||||||
|
Task<int> CountAsync(int? envelopeId = null, string? userReference = null, int? status = null);
|
||||||
|
|
||||||
|
Task<bool> AccessCodeAlreadyRequested(int envelopeId, string userReference);
|
||||||
|
|
||||||
|
Task<bool> IsSigned(int envelopeId, string userReference);
|
||||||
|
|
||||||
|
Task<bool> IsRejected(int envelopeId, string? userReference = null);
|
||||||
|
|
||||||
|
Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false);
|
||||||
|
|
||||||
|
Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null);
|
||||||
|
|
||||||
|
Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId);
|
||||||
|
|
||||||
|
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
|
||||||
|
using EnvelopeGenerator.Common;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeMailService : IEmailOutService
|
||||||
|
{
|
||||||
|
Task<DataResult<int>> SendAsync(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType);
|
||||||
|
|
||||||
|
Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto);
|
||||||
|
|
||||||
|
Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeReceiverReadOnlyService : ICRUDService<EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnlyDto, EnvelopeReceiverReadOnlyUpdateDto, EnvelopeReceiverReadOnly, long>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>
|
||||||
|
{
|
||||||
|
|
||||||
|
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false);
|
||||||
|
|
||||||
|
Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadSecretByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true);
|
||||||
|
|
||||||
|
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true);
|
||||||
|
|
||||||
|
Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true);
|
||||||
|
|
||||||
|
Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true);
|
||||||
|
|
||||||
|
Task<DataResult<string>> ReadAccessCodeByIdAsync(int envelopeId, int receiverId);
|
||||||
|
|
||||||
|
Task<DataResult<bool>> VerifyAccessCodeAsync(string uuid, string signature, string accessCode);
|
||||||
|
|
||||||
|
Task<DataResult<bool>> VerifyAccessCodeAsync(string envelopeReceiverId, string accessCode);
|
||||||
|
|
||||||
|
Task<DataResult<bool>> IsExisting(string envelopeReceiverId);
|
||||||
|
|
||||||
|
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
|
||||||
|
|
||||||
|
Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
EnvelopeGenerator.Application/Contracts/IEnvelopeService.cs
Normal file
16
EnvelopeGenerator.Application/Contracts/IEnvelopeService.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeService : IBasicCRUDService<EnvelopeDto, Envelope, int>
|
||||||
|
{
|
||||||
|
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false);
|
||||||
|
|
||||||
|
Task<DataResult<EnvelopeDto>> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false);
|
||||||
|
|
||||||
|
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[]ignore_statuses);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IEnvelopeTypeService : IBasicCRUDService<EnvelopeTypeDto, EnvelopeType, int>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
24
EnvelopeGenerator.Application/Contracts/IJWTService.cs
Normal file
24
EnvelopeGenerator.Application/Contracts/IJWTService.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IJWTService<TClaimValue>
|
||||||
|
{
|
||||||
|
public static SymmetricSecurityKey GenerateSecurityKey(int byteSize = 32)
|
||||||
|
{
|
||||||
|
using var rng = RandomNumberGenerator.Create();
|
||||||
|
var randomBytes = new byte[byteSize];
|
||||||
|
rng.GetBytes(randomBytes);
|
||||||
|
var securityKey = new SymmetricSecurityKey(randomBytes);
|
||||||
|
|
||||||
|
return securityKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GenerateToken(TClaimValue claimValue);
|
||||||
|
|
||||||
|
JwtSecurityToken? ReadSecurityToken(string token);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
EnvelopeGenerator.Application/Contracts/IReceiverService.cs
Normal file
14
EnvelopeGenerator.Application/Contracts/IReceiverService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IReceiverService : ICRUDService<ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
|
||||||
|
{
|
||||||
|
public Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null);
|
||||||
|
|
||||||
|
public Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using EnvelopeGenerator.Application.DTOs;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Contracts
|
||||||
|
{
|
||||||
|
public interface IUserReceiverService : IBasicCRUDService<UserReceiverDto, UserReceiver, int>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
63
EnvelopeGenerator.Application/DIExtensions.cs
Normal file
63
EnvelopeGenerator.Application/DIExtensions.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using DigitalData.UserManager.Application.MappingProfiles;
|
||||||
|
using EnvelopeGenerator.Application.Contracts;
|
||||||
|
using EnvelopeGenerator.Application.MappingProfiles;
|
||||||
|
using EnvelopeGenerator.Application.Configurations;
|
||||||
|
using EnvelopeGenerator.Application.Services;
|
||||||
|
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||||
|
using EnvelopeGenerator.Infrastructure.Repositories;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application
|
||||||
|
{
|
||||||
|
public static class DIExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration dispatcherConfigSection, IConfiguration mailConfigSection)
|
||||||
|
{
|
||||||
|
//Inject CRUD Service and repositoriesad
|
||||||
|
services.AddScoped<IConfigRepository, ConfigRepository>();
|
||||||
|
services.AddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
||||||
|
services.AddScoped<IEnvelopeDocumentRepository, EnvelopeDocumentRepository>();
|
||||||
|
services.AddScoped<IConfigRepository, ConfigRepository>();
|
||||||
|
services.AddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
||||||
|
services.AddScoped<IDocumentStatusRepository, DocumentStatusRepository>();
|
||||||
|
services.AddScoped<IEmailTemplateRepository, EmailTemplateRepository>();
|
||||||
|
services.AddScoped<IEnvelopeRepository, EnvelopeRepository>();
|
||||||
|
services.AddScoped<IEnvelopeCertificateRepository, EnvelopeCertificateRepository>();
|
||||||
|
services.AddScoped<IEnvelopeDocumentRepository, EnvelopeDocumentRepository>();
|
||||||
|
services.AddScoped<IEnvelopeHistoryRepository, EnvelopeHistoryRepository>();
|
||||||
|
services.AddScoped<IEnvelopeReceiverRepository, EnvelopeReceiverRepository>();
|
||||||
|
services.AddScoped<IEnvelopeTypeRepository, EnvelopeTypeRepository>();
|
||||||
|
services.AddScoped<IReceiverRepository, ReceiverRepository>();
|
||||||
|
services.AddScoped<IUserReceiverRepository, UserReceiverRepository>();
|
||||||
|
services.AddScoped<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyRepository>();
|
||||||
|
services.AddScoped<IConfigService, ConfigService>();
|
||||||
|
services.AddScoped<IDocumentReceiverElementService, DocumentReceiverElementService>();
|
||||||
|
services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
||||||
|
services.AddScoped<IEnvelopeHistoryService, EnvelopeHistoryService>();
|
||||||
|
services.AddScoped<IDocumentStatusService, DocumentStatusService>();
|
||||||
|
services.AddScoped<IEmailTemplateService, EmailTemplateService>();
|
||||||
|
services.AddScoped<IEnvelopeService, EnvelopeService>();
|
||||||
|
services.AddScoped<IEnvelopeCertificateService, EnvelopeCertificateService>();
|
||||||
|
services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
||||||
|
services.AddScoped<IEnvelopeReceiverService, EnvelopeReceiverService>();
|
||||||
|
services.AddScoped<IEnvelopeTypeService, EnvelopeTypeService>();
|
||||||
|
services.AddScoped<IReceiverService, ReceiverService>();
|
||||||
|
services.AddScoped<IUserReceiverService, UserReceiverService>();
|
||||||
|
services.AddScoped<IEnvelopeReceiverReadOnlyService, EnvelopeReceiverReadOnlyService>();
|
||||||
|
|
||||||
|
//Auto mapping profiles
|
||||||
|
services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly);
|
||||||
|
services.AddAutoMapper(typeof(UserMappingProfile).Assembly);
|
||||||
|
|
||||||
|
services.Configure<DispatcherConfig>(dispatcherConfigSection);
|
||||||
|
services.Configure<MailConfig>(mailConfigSection);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration config) => services.AddEnvelopeGenerator(
|
||||||
|
dispatcherConfigSection: config.GetSection("DispatcherConfig"),
|
||||||
|
mailConfigSection: config.GetSection("MailConfig"));
|
||||||
|
}
|
||||||
|
}
|
||||||
20
EnvelopeGenerator.Application/DTOs/ConfigDto.cs
Normal file
20
EnvelopeGenerator.Application/DTOs/ConfigDto.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record ConfigDto(
|
||||||
|
string DocumentPath,
|
||||||
|
int SendingProfile,
|
||||||
|
string SignatureHost,
|
||||||
|
string ExternalProgramName,
|
||||||
|
string ExportPath,
|
||||||
|
string DocumentPathDmz,
|
||||||
|
string ExportPathDmz,
|
||||||
|
string DocumentPathMoveAftsend) : IUnique<int>
|
||||||
|
{
|
||||||
|
[JsonIgnore]
|
||||||
|
[Obsolete("Configuration does not have an ID; it represents a single table in the database.")]
|
||||||
|
public int Id => throw new InvalidOperationException("This configuration does not support an ID as it represents a single row in the database.");
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record DocumentReceiverElementDto(
|
||||||
|
int Id,
|
||||||
|
int DocumentId,
|
||||||
|
int ReceiverId,
|
||||||
|
int ElementType,
|
||||||
|
double X,
|
||||||
|
double Y,
|
||||||
|
double Width,
|
||||||
|
double Height,
|
||||||
|
int Page,
|
||||||
|
bool Required,
|
||||||
|
string? Tooltip,
|
||||||
|
bool ReadOnly,
|
||||||
|
int AnnotationIndex,
|
||||||
|
DateTime AddedWhen,
|
||||||
|
DateTime? ChangedWhen,
|
||||||
|
double Top,
|
||||||
|
double Left
|
||||||
|
): IUnique<int>;
|
||||||
|
}
|
||||||
14
EnvelopeGenerator.Application/DTOs/DocumentStatusDto.cs
Normal file
14
EnvelopeGenerator.Application/DTOs/DocumentStatusDto.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record DocumentStatusDto(
|
||||||
|
int Id,
|
||||||
|
int EnvelopeId,
|
||||||
|
int ReceiverId,
|
||||||
|
int Status,
|
||||||
|
DateTime? StatusChangedWhen,
|
||||||
|
string Value,
|
||||||
|
DateTime AddedWhen,
|
||||||
|
DateTime? ChangedWhen) : IUnique<int>;
|
||||||
|
}
|
||||||
10
EnvelopeGenerator.Application/DTOs/EmailTemplateDto.cs
Normal file
10
EnvelopeGenerator.Application/DTOs/EmailTemplateDto.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record EmailTemplateDto(
|
||||||
|
int Id,
|
||||||
|
string Name,
|
||||||
|
string Body,
|
||||||
|
string Subject) : IUnique<int>;
|
||||||
|
}
|
||||||
14
EnvelopeGenerator.Application/DTOs/EnvelopeCertificateDto.cs
Normal file
14
EnvelopeGenerator.Application/DTOs/EnvelopeCertificateDto.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record EnvelopeCertificateDto(
|
||||||
|
int Id,
|
||||||
|
int EnvelopeId,
|
||||||
|
string EnvelopeUuid,
|
||||||
|
string EnvelopeSubject,
|
||||||
|
int CreatorId,
|
||||||
|
string CreatorName,
|
||||||
|
string CreatorEmail,
|
||||||
|
int EnvelopeStatus) : IUnique<int>;
|
||||||
|
}
|
||||||
13
EnvelopeGenerator.Application/DTOs/EnvelopeDocumentDto.cs
Normal file
13
EnvelopeGenerator.Application/DTOs/EnvelopeDocumentDto.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record EnvelopeDocumentDto
|
||||||
|
(
|
||||||
|
int Id,
|
||||||
|
int EnvelopeId,
|
||||||
|
DateTime AddedWhen,
|
||||||
|
byte[]? ByteData = null,
|
||||||
|
IEnumerable<DocumentReceiverElementDto>? Elements = null
|
||||||
|
) : IUnique<int>;
|
||||||
|
}
|
||||||
67
EnvelopeGenerator.Application/DTOs/EnvelopeDto.cs
Normal file
67
EnvelopeGenerator.Application/DTOs/EnvelopeDto.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||||
|
using DigitalData.UserManager.Application.DTOs.User;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record EnvelopeDto() : IUnique<int>
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int UserId { get; set; }
|
||||||
|
|
||||||
|
public int Status { get; set; }
|
||||||
|
|
||||||
|
public string StatusName { get; set; }
|
||||||
|
|
||||||
|
public string Uuid { get; set; }
|
||||||
|
|
||||||
|
[TemplatePlaceholder("[MESSAGE]")]
|
||||||
|
public string Message { get; set; }
|
||||||
|
public DateTime? ExpiresWhen { get; set; }
|
||||||
|
public DateTime? ExpiresWarningWhen { get; set; }
|
||||||
|
public DateTime AddedWhen { get; set; }
|
||||||
|
public DateTime? ChangedWhen { get; set; }
|
||||||
|
|
||||||
|
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public int? ContractType { get; set; }
|
||||||
|
|
||||||
|
public string Language { get; set; }
|
||||||
|
|
||||||
|
public bool? SendReminderEmails { get; set; }
|
||||||
|
|
||||||
|
public int? FirstReminderDays { get; set; }
|
||||||
|
|
||||||
|
public int? ReminderIntervalDays { get; set; }
|
||||||
|
|
||||||
|
public int? EnvelopeTypeId { get; set; }
|
||||||
|
|
||||||
|
public int? CertificationType { get; set; }
|
||||||
|
|
||||||
|
public bool? UseAccessCode { get; set; }
|
||||||
|
|
||||||
|
public int? FinalEmailToCreator { get; set; }
|
||||||
|
|
||||||
|
public int? FinalEmailToReceivers { get; set; }
|
||||||
|
|
||||||
|
public int? ExpiresWhenDays { get; set; }
|
||||||
|
|
||||||
|
public int? ExpiresWarningWhenDays { get; set; }
|
||||||
|
|
||||||
|
public bool DmzMoved { get; set; }
|
||||||
|
public UserReadDto? User { get; set; }
|
||||||
|
public EnvelopeType? EnvelopeType { get; set; }
|
||||||
|
|
||||||
|
public string? EnvelopeTypeTitle { get; set; }
|
||||||
|
|
||||||
|
public bool IsAlreadySent { get; set; }
|
||||||
|
|
||||||
|
public string? StatusTranslated { get; set; }
|
||||||
|
|
||||||
|
public string? ContractTypeTranslated { get; set; }
|
||||||
|
public IEnumerable<EnvelopeDocumentDto>? Documents { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
||||||
|
{
|
||||||
|
public record EnvelopeHistoryCreateDto(
|
||||||
|
int EnvelopeId,
|
||||||
|
string UserReference,
|
||||||
|
int Status,
|
||||||
|
DateTime? ActionDate,
|
||||||
|
string? Comment = null);
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using DigitalData.UserManager.Application.DTOs.User;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||||
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
||||||
|
{
|
||||||
|
public record EnvelopeHistoryDto(
|
||||||
|
long Id,
|
||||||
|
int EnvelopeId,
|
||||||
|
string UserReference,
|
||||||
|
int Status,
|
||||||
|
string? StatusName,
|
||||||
|
DateTime AddedWhen,
|
||||||
|
DateTime? ActionDate,
|
||||||
|
UserCreateDto? Sender,
|
||||||
|
ReceiverReadDto? Receiver,
|
||||||
|
ReferenceType ReferenceType,
|
||||||
|
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||||
|
{
|
||||||
|
public record EnvelopeReceiverBasicDto() : IUnique<(int Envelope, int Receiver)>
|
||||||
|
{
|
||||||
|
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
|
||||||
|
|
||||||
|
public int EnvelopeId { get; init; }
|
||||||
|
|
||||||
|
public int ReceiverId { get; init; }
|
||||||
|
|
||||||
|
public int Sequence { get; init; }
|
||||||
|
|
||||||
|
[TemplatePlaceholder("[NAME_RECEIVER]")]
|
||||||
|
public string? Name { get; init; }
|
||||||
|
|
||||||
|
public string? JobTitle { get; init; }
|
||||||
|
|
||||||
|
public string? CompanyName { get; init; }
|
||||||
|
|
||||||
|
public string? PrivateMessage { get; init; }
|
||||||
|
|
||||||
|
public DateTime AddedWhen { get; init; }
|
||||||
|
|
||||||
|
public DateTime? ChangedWhen { get; init; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||||
|
{
|
||||||
|
public record EnvelopeReceiverDto() : EnvelopeReceiverBasicDto()
|
||||||
|
{
|
||||||
|
public EnvelopeDto? Envelope { get; set; }
|
||||||
|
|
||||||
|
public ReceiverReadDto? Receiver { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||||
|
{
|
||||||
|
public record EnvelopeReceiverSecretDto(string? AccessCode) : EnvelopeReceiverDto;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
|
||||||
|
{
|
||||||
|
public record EnvelopeReceiverReadOnlyCreateDto(
|
||||||
|
DateTime DateValid)
|
||||||
|
{
|
||||||
|
[EmailAddress]
|
||||||
|
[Required]
|
||||||
|
public required string ReceiverMail { get; init; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public long? EnvelopeId { get; set; } = null;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string? AddedWho { get; set; }
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public DateTime AddedWhen { get; } = DateTime.Now;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
|
||||||
|
{
|
||||||
|
public record EnvelopeReceiverReadOnlyDto(
|
||||||
|
long Id,
|
||||||
|
long EnvelopeId,
|
||||||
|
string ReceiverMail,
|
||||||
|
DateTime DateValid,
|
||||||
|
DateTime AddedWhen,
|
||||||
|
string AddedWho,
|
||||||
|
EnvelopeDto? Envelope = null,
|
||||||
|
string? ChangedWho = null,
|
||||||
|
DateTime? ChangedWhen = null,
|
||||||
|
ReceiverReadDto? Receiver = null);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
|
||||||
|
{
|
||||||
|
public record EnvelopeReceiverReadOnlyUpdateDto(
|
||||||
|
long Id,
|
||||||
|
DateTime DateValid,
|
||||||
|
string ChangedWho) : IUnique<long>
|
||||||
|
{
|
||||||
|
public DateTime ChangedWhen { get; } = DateTime.Now;
|
||||||
|
};
|
||||||
|
}
|
||||||
21
EnvelopeGenerator.Application/DTOs/EnvelopeTypeDto.cs
Normal file
21
EnvelopeGenerator.Application/DTOs/EnvelopeTypeDto.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record EnvelopeTypeDto(
|
||||||
|
int Id,
|
||||||
|
string Title,
|
||||||
|
string Language,
|
||||||
|
int? ExpiresDays,
|
||||||
|
int? CertificationType,
|
||||||
|
bool? UseAccessCode,
|
||||||
|
int? FinalEmailToCreator,
|
||||||
|
int? FinalEmailToReceivers,
|
||||||
|
DateTime AddedWhen,
|
||||||
|
DateTime? ChangedWhen,
|
||||||
|
int? ExpiresWarningDays,
|
||||||
|
bool? SendReminderEmails,
|
||||||
|
int? FirstReminderDays,
|
||||||
|
int? ReminderIntervalDays,
|
||||||
|
int? ContractType) : IUnique<int>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||||
|
{
|
||||||
|
public record ReceiverCreateDto([EmailAddress] string EmailAddress)
|
||||||
|
{
|
||||||
|
public string Signature => sha256HexOfMail.Value;
|
||||||
|
|
||||||
|
private readonly Lazy<string> sha256HexOfMail = new(() =>
|
||||||
|
{
|
||||||
|
var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress.ToUpper());
|
||||||
|
var hash_arr = SHA256.HashData(bytes_arr);
|
||||||
|
var hexa_str = BitConverter.ToString(hash_arr);
|
||||||
|
return hexa_str.Replace("-", string.Empty);
|
||||||
|
});
|
||||||
|
|
||||||
|
public DateTime AddedWhen { get; } = DateTime.Now;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using DigitalData.Core.DTO;
|
||||||
|
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||||
|
{
|
||||||
|
public record ReceiverReadDto(
|
||||||
|
int Id,
|
||||||
|
string EmailAddress,
|
||||||
|
string Signature,
|
||||||
|
DateTime AddedWhen
|
||||||
|
) : BaseDTO<int>(Id)
|
||||||
|
{
|
||||||
|
[JsonIgnore]
|
||||||
|
public IEnumerable<EnvelopeReceiverBasicDto>? EnvelopeReceivers { get; init; }
|
||||||
|
|
||||||
|
public string? LastUsedName => EnvelopeReceivers?.LastOrDefault()?.Name;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||||
|
{
|
||||||
|
public record ReceiverUpdateDto(int Id) : IUnique<int>;
|
||||||
|
}
|
||||||
13
EnvelopeGenerator.Application/DTOs/UserReceiverDto.cs
Normal file
13
EnvelopeGenerator.Application/DTOs/UserReceiverDto.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using DigitalData.Core.Abstractions;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.DTOs
|
||||||
|
{
|
||||||
|
public record UserReceiverDto(
|
||||||
|
int Id,
|
||||||
|
int UserId,
|
||||||
|
int ReceiverId,
|
||||||
|
string Name,
|
||||||
|
string CompanyName,
|
||||||
|
string JobTitle,
|
||||||
|
DateTime AddedWhen) : IUnique<int>;
|
||||||
|
}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Configurations;
|
|
||||||
using EnvelopeGenerator.Application.Services;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
||||||
using DigitalData.Core.Client;
|
|
||||||
using QRCoder;
|
|
||||||
using EnvelopeGenerator.Application.Interfaces.Services;
|
|
||||||
using System.Reflection;
|
|
||||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Commands;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extensions method for dependency injection
|
|
||||||
/// </summary>
|
|
||||||
public static class DependencyInjection
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds all required services for envelope generator application
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="services"></param>
|
|
||||||
/// <param name="config"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Obsolete("Use MediatR")]
|
|
||||||
public static IServiceCollection AddEnvelopeGeneratorServices(this IServiceCollection services, IConfiguration config)
|
|
||||||
{
|
|
||||||
//Inject CRUD Service and repositoriesad
|
|
||||||
services.TryAddScoped<IConfigService, ConfigService>();
|
|
||||||
services.TryAddScoped<IDocumentReceiverElementService, DocumentReceiverElementService>();
|
|
||||||
services.TryAddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
|
||||||
services.TryAddScoped<IEnvelopeHistoryService, EnvelopeHistoryService>();
|
|
||||||
services.TryAddScoped<IDocumentStatusService, DocumentStatusService>();
|
|
||||||
services.TryAddScoped<IEmailTemplateService, EmailTemplateService>();
|
|
||||||
services.TryAddScoped<IEnvelopeService, EnvelopeService>();
|
|
||||||
services.TryAddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
|
||||||
services.TryAddScoped<IEnvelopeReceiverService, EnvelopeReceiverService>();
|
|
||||||
services.TryAddScoped<IEnvelopeTypeService, EnvelopeTypeService>();
|
|
||||||
services.TryAddScoped<IReceiverService, ReceiverService>();
|
|
||||||
services.TryAddScoped<IEnvelopeReceiverReadOnlyService, EnvelopeReceiverReadOnlyService>();
|
|
||||||
|
|
||||||
//Auto mapping profiles
|
|
||||||
services.AddAutoMapper(Assembly.GetExecutingAssembly());
|
|
||||||
services.AddAutoMapper(typeof(DigitalData.UserManager.Application.DIExtensions));
|
|
||||||
|
|
||||||
services.Configure<DispatcherParams>(config.GetSection(nameof(DispatcherParams)));
|
|
||||||
services.Configure<MailParams>(config.GetSection(nameof(MailParams)));
|
|
||||||
services.Configure<AuthenticatorParams>(config.GetSection(nameof(AuthenticatorParams)));
|
|
||||||
services.Configure<TotpSmsParams>(config.GetSection(nameof(TotpSmsParams)));
|
|
||||||
services.Configure<DbTriggerParams>(config.GetSection(nameof(DbTriggerParams)));
|
|
||||||
|
|
||||||
services.AddHttpClientService<GtxMessagingParams>(config.GetSection(nameof(GtxMessagingParams)));
|
|
||||||
services.TryAddSingleton<ISmsSender, GTXSmsSender>();
|
|
||||||
services.TryAddSingleton<IEnvelopeSmsHandler, EnvelopeSmsHandler>();
|
|
||||||
services.TryAddSingleton<IAuthenticator, Authenticator>();
|
|
||||||
services.TryAddSingleton<QRCodeGenerator>();
|
|
||||||
|
|
||||||
services.AddMediatR(cfg =>
|
|
||||||
{
|
|
||||||
cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly());
|
|
||||||
cfg.RegisterServicesFromAssembly(typeof(CreateEnvelopeReceiverCommandHandler).Assembly);
|
|
||||||
});
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
namespace EnvelopeGenerator.Application.DocStatus.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record CreateDocStatusCommand : ModifyDocStatusCommandBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets timestamp when this record was added. Returns the StatusChangedWhen value.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen => StatusChangedWhen;
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Domain;
|
|
||||||
using EnvelopeGenerator.Extensions;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocStatus.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record ModifyDocStatusCommandBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? Key
|
|
||||||
{
|
|
||||||
get => Envelope?.Uuid is string uuid && Receiver?.Signature is string signature
|
|
||||||
? (uuid, signature).EncodeEnvelopeReceiverId()
|
|
||||||
: null;
|
|
||||||
init
|
|
||||||
{
|
|
||||||
if (value is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
(string? EnvelopeUuid, string? ReceiverSignature) = value.DecodeEnvelopeReceiverId();
|
|
||||||
if (string.IsNullOrEmpty(EnvelopeUuid) || string.IsNullOrEmpty(ReceiverSignature))
|
|
||||||
{
|
|
||||||
throw new BadRequestException("Der EnvelopeReceiverKey muss ein gültiger Base64-kodierter String sein, der die EnvelopeUuid und die ReceiverSignature enthält.");
|
|
||||||
}
|
|
||||||
Envelope.Uuid = EnvelopeUuid;
|
|
||||||
Receiver.Signature = ReceiverSignature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Der Umschlag, der mit dem Empfänger verknüpft ist.
|
|
||||||
/// </summary>
|
|
||||||
public EnvelopeQuery Envelope { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Der Empfänger, der mit dem Umschlag verknüpft ist.
|
|
||||||
/// </summary>
|
|
||||||
public ReceiverQuery Receiver { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current status code.
|
|
||||||
/// </summary>
|
|
||||||
public Constants.DocumentStatus Status => Value is null ? Constants.DocumentStatus.Created : Constants.DocumentStatus.Signed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the display value associated with the status.
|
|
||||||
/// </summary>
|
|
||||||
public string? Value { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets timestamp when this record was added.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime StatusChangedWhen { get; } = DateTime.Now;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maps the current command to a new instance of the specified type.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TDest"></typeparam>
|
|
||||||
/// <returns></returns>
|
|
||||||
public TDest To<TDest>() where TDest : ModifyDocStatusCommandBase, new()
|
|
||||||
=> new()
|
|
||||||
{
|
|
||||||
Key = Key,
|
|
||||||
Envelope = Envelope,
|
|
||||||
Receiver = Receiver,
|
|
||||||
Value = Value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Queries
|
|
||||||
/// <summary>
|
|
||||||
/// Repräsentiert eine Abfrage für Umschläge.
|
|
||||||
/// </summary>
|
|
||||||
public record EnvelopeQuery
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Die eindeutige Kennung des Umschlags.
|
|
||||||
/// </summary>
|
|
||||||
public int? Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Die universell eindeutige Kennung des Umschlags.
|
|
||||||
/// </summary>
|
|
||||||
public string? Uuid { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stellt eine Abfrage dar, um die Details eines Empfängers zu lesen.
|
|
||||||
/// um spezifische Informationen über einen Empfänger abzurufen.
|
|
||||||
/// </summary>
|
|
||||||
public record ReceiverQuery
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// ID des Empfängers
|
|
||||||
/// </summary>
|
|
||||||
public int? Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// E-Mail Adresse des Empfängers
|
|
||||||
/// </summary>
|
|
||||||
public string? EmailAddress { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Eindeutige Signatur des Empfängers
|
|
||||||
/// </summary>
|
|
||||||
public string? Signature { get; set; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocStatus.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a command to save the status of a document, either by creating a new status or updating an existing one based on the provided envelope and receiver identifiers.
|
|
||||||
/// It returns the identifier of the saved document status.
|
|
||||||
/// </summary>
|
|
||||||
public record SaveDocStatusCommand : ModifyDocStatusCommandBase, IRequest<int?>;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mediator"></param>
|
|
||||||
/// <param name="uuid"></param>
|
|
||||||
/// <param name="signature"></param>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Task<int?> SignDocAsync(this IMediator mediator, string uuid, string signature, string value, CancellationToken cancel = default)
|
|
||||||
=> mediator.Send(new SaveDocStatusCommand()
|
|
||||||
{
|
|
||||||
Envelope = new() { Uuid = uuid },
|
|
||||||
Receiver = new() { Signature = signature },
|
|
||||||
Value = value
|
|
||||||
}, cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class SaveDocStatusCommandHandler : IRequestHandler<SaveDocStatusCommand, int?>
|
|
||||||
{
|
|
||||||
private readonly IRepository<DocumentStatus> _repo;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="repo"></param>
|
|
||||||
public SaveDocStatusCommandHandler(IRepository<DocumentStatus> repo)
|
|
||||||
{
|
|
||||||
_repo = repo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<int?> Handle(SaveDocStatusCommand request, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
// envelope filter
|
|
||||||
Expression<Func<DocumentStatus, bool>>? eExp =
|
|
||||||
request.Envelope.Id is not null
|
|
||||||
? ds => ds.EnvelopeId == request.Envelope.Id
|
|
||||||
: !string.IsNullOrWhiteSpace(request.Envelope.Uuid)
|
|
||||||
? ds => ds.Envelope.Uuid == request.Envelope.Uuid
|
|
||||||
: throw new BadRequestException();
|
|
||||||
|
|
||||||
// receiver filter
|
|
||||||
Expression<Func<DocumentStatus, bool>>? rExp =
|
|
||||||
request.Receiver.Id is not null
|
|
||||||
? ds => ds.ReceiverId == request.Receiver.Id
|
|
||||||
: request.Receiver.EmailAddress is not null
|
|
||||||
? ds => ds.Receiver.EmailAddress == request.Receiver.EmailAddress
|
|
||||||
: !string.IsNullOrWhiteSpace(request.Receiver.Signature) ? ds => ds.Receiver.Signature == request.Receiver.Signature
|
|
||||||
: throw new BadRequestException();
|
|
||||||
|
|
||||||
// ceck if exists
|
|
||||||
bool isExists = await _repo.ReadOnly().Where(eExp).Where(rExp).AnyAsync(cancel);
|
|
||||||
|
|
||||||
if (isExists)
|
|
||||||
{
|
|
||||||
var uReq = request.To<UpdateDocStatusCommand>();
|
|
||||||
await _repo.UpdateAsync(uReq, q => q.Where(eExp).Where(rExp), cancel);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var cReq = request.To<CreateDocStatusCommand>();
|
|
||||||
await _repo.CreateAsync(cReq, cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
var docStatus = await _repo.ReadOnly().Where(eExp).Where(rExp).SingleOrDefaultAsync(cancel);
|
|
||||||
return docStatus?.Id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using EnvelopeGenerator.Domain;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocStatus.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record UpdateDocStatusCommand : ModifyDocStatusCommandBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets timestamp when this record was added. Returns the StatusChangedWhen value.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ChangedWhen => StatusChangedWhen;
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.DocStatus.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DocStatus;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class MappingProfile : Profile
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public MappingProfile()
|
|
||||||
{
|
|
||||||
CreateMap<CreateDocStatusCommand, DocumentStatus>();
|
|
||||||
CreateMap<UpdateDocStatusCommand, DocumentStatus>();
|
|
||||||
CreateMap<EnvelopeQuery, Envelope>();
|
|
||||||
CreateMap<ReceiverQuery, Receiver>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using EnvelopeGenerator.Application.Dto;
|
|
||||||
using MediatR;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using AutoMapper;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Documents.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a query to read a document based on its unique identifier or associated envelope identifier.
|
|
||||||
/// </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<EnvelopeDocumentDto?>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles queries for reading <see cref="EnvelopeDocument"/> data based on either the document ID or the envelope ID.
|
|
||||||
/// </summary>
|
|
||||||
public class ReadDocumentQueryHandler : IRequestHandler<ReadDocumentQuery, EnvelopeDocumentDto?>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Repository for accessing <see cref="EnvelopeDocument"/> entities.
|
|
||||||
/// </summary>
|
|
||||||
private readonly IRepository<EnvelopeDocument> _repo;
|
|
||||||
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ReadDocumentQueryHandler"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeDocumentRepository">The repository used to access <see cref="EnvelopeDocument"/> entities.</param>
|
|
||||||
public ReadDocumentQueryHandler(IRepository<EnvelopeDocument> envelopeDocumentRepository, IMapper mapper)
|
|
||||||
{
|
|
||||||
_repo = envelopeDocumentRepository;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the <see cref="ReadDocumentQuery"/> and returns a <see cref="EnvelopeDocumentDto"/> based on the provided identifiers.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="query">The query containing the document ID or envelope ID to search for.</param>
|
|
||||||
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
|
|
||||||
/// <returns>
|
|
||||||
/// A <see cref="EnvelopeDocumentDto"/> if a matching document is found; otherwise, <c>null</c>.
|
|
||||||
/// </returns>
|
|
||||||
/// <exception cref="InvalidOperationException">
|
|
||||||
/// Thrown when neither <see cref="ReadDocumentQuery.Id"/> nor <see cref="ReadDocumentQuery.EnvelopeId"/> is provided.
|
|
||||||
/// </exception>
|
|
||||||
[Obsolete("Use MediatR")]
|
|
||||||
public async Task<EnvelopeDocumentDto?> Handle(ReadDocumentQuery query, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (query.Id is not null)
|
|
||||||
{
|
|
||||||
var doc = await _repo.ReadOnly().Where(d => d.Id == query.Id).FirstOrDefaultAsync();
|
|
||||||
return _mapper.Map<EnvelopeDocumentDto>(doc);
|
|
||||||
}
|
|
||||||
else if (query.EnvelopeId is not null)
|
|
||||||
{
|
|
||||||
var doc = await _repo.ReadOnly().Where(d => d.EnvelopeId == query.EnvelopeId).FirstOrDefaultAsync();
|
|
||||||
return _mapper.Map<EnvelopeDocumentDto>(doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
$"Invalid {nameof(ReadDocumentQuery)}: either {nameof(query.Id)} or {nameof(query.EnvelopeId)} must be provided.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object representing configuration settings.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class ConfigDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the sending profile identifier.
|
|
||||||
/// </summary>
|
|
||||||
public int SendingProfile { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the signature host URL or name.
|
|
||||||
/// </summary>
|
|
||||||
public required string SignatureHost { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the name of the external program.
|
|
||||||
/// </summary>
|
|
||||||
public string? ExternalProgramName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the path where exports will be saved.
|
|
||||||
/// </summary>
|
|
||||||
public string? ExportPath { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object representing a positioned element assigned to a document receiver.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class DocumentReceiverElementDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the unique identifier of the element.
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the identifier of the associated document.
|
|
||||||
/// </summary>
|
|
||||||
public int DocumentId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the identifier of the receiver.
|
|
||||||
/// </summary>
|
|
||||||
public int ReceiverId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the type of the element.
|
|
||||||
/// </summary>
|
|
||||||
public int ElementType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the X coordinate of the element.
|
|
||||||
/// </summary>
|
|
||||||
public double X { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the Y coordinate of the element.
|
|
||||||
/// </summary>
|
|
||||||
public double Y { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the width of the element.
|
|
||||||
/// </summary>
|
|
||||||
public double Width { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the height of the element.
|
|
||||||
/// </summary>
|
|
||||||
public double Height { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the page number where the element appears.
|
|
||||||
/// </summary>
|
|
||||||
public int Page { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether the element is required.
|
|
||||||
/// </summary>
|
|
||||||
public bool Required { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the tooltip text for the element.
|
|
||||||
/// </summary>
|
|
||||||
public string? Tooltip { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether the element is read-only.
|
|
||||||
/// </summary>
|
|
||||||
public bool ReadOnly { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the annotation index for ordering or reference.
|
|
||||||
/// </summary>
|
|
||||||
public int AnnotationIndex { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the timestamp when the element was added.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the timestamp when the element was last changed, if applicable.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ChangedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the top position of the element (in layout terms).
|
|
||||||
/// </summary>
|
|
||||||
public double Top { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the left position of the element (in layout terms).
|
|
||||||
/// </summary>
|
|
||||||
public double Left { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object representing the status of a document for a specific receiver.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class DocumentStatusDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the unique identifier of the document status entry.
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the ID of the associated envelope.
|
|
||||||
/// </summary>
|
|
||||||
public int EnvelopeId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the ID of the receiver associated with this status.
|
|
||||||
/// </summary>
|
|
||||||
public int ReceiverId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the current status code.
|
|
||||||
/// </summary>
|
|
||||||
public int Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the timestamp when the status was changed.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? StatusChangedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the timestamp when this record was added.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the timestamp when this record was last changed.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ChangedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the display value associated with the status.
|
|
||||||
/// </summary>
|
|
||||||
public string? Value { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record EmailTemplateDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int Id{ get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required string Name { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required string Body { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required string Subject { get; set; }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object representing a document within an envelope, including optional binary data and form elements.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class EnvelopeDocumentDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the unique identifier of the document.
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the envelope ID to which the document belongs.
|
|
||||||
/// </summary>
|
|
||||||
public int EnvelopeId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the date and time when the document was added.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the binary data of the document, if available.
|
|
||||||
/// </summary>
|
|
||||||
public byte[]? ByteData { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the collection of elements associated with the document for receiver interactions, if any.
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<DocumentReceiverElementDto>? Elements { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
|
||||||
using DigitalData.UserManager.Application.DTOs.User;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record EnvelopeDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int UserId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is string.Empty
|
|
||||||
/// </summary>
|
|
||||||
public string StatusName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is string.Empty
|
|
||||||
/// </summary>
|
|
||||||
public string Uuid { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is string.Empty
|
|
||||||
/// </summary>
|
|
||||||
[TemplatePlaceholder("[MESSAGE]")]
|
|
||||||
public string Message { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ChangedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is string.Empty
|
|
||||||
/// </summary>
|
|
||||||
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
|
|
||||||
public string Title { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int? ContractType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is 'de-DE'
|
|
||||||
/// </summary>
|
|
||||||
public string Language { get; set; } = "de-DE";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int? EnvelopeTypeId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int? CertificationType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public bool? UseAccessCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public bool TFAEnabled { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public UserReadDto? User { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public EnvelopeType? EnvelopeType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? EnvelopeTypeTitle { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public bool IsAlreadySent { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public byte[]? DocResult { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<EnvelopeDocumentDto>? Documents { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeHistory;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object for creating a new envelope history record.
|
|
||||||
/// </summary>
|
|
||||||
public class EnvelopeHistoryCreateDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the identifier of the envelope.
|
|
||||||
/// </summary>
|
|
||||||
public int EnvelopeId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the user reference associated with the action.
|
|
||||||
/// </summary>
|
|
||||||
public required string UserReference { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the status of the envelope at the time of the action.
|
|
||||||
/// </summary>
|
|
||||||
public int Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the date and time when the action occurred.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ActionDate { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets an optional comment related to the action.
|
|
||||||
/// </summary>
|
|
||||||
public string? Comment { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
using DigitalData.UserManager.Application.DTOs.User;
|
|
||||||
using EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
using static EnvelopeGenerator.Domain.Constants;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeHistory;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object representing the history of an envelope, including status, sender, receiver, and related metadata.
|
|
||||||
/// </summary>
|
|
||||||
public record EnvelopeHistoryDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unique identifier for the envelope history entry.
|
|
||||||
/// </summary>
|
|
||||||
public long Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Identifier of the associated envelope.
|
|
||||||
/// </summary>
|
|
||||||
public int EnvelopeId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reference string for the user related to this history entry.
|
|
||||||
/// </summary>
|
|
||||||
public required string UserReference { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Include code of the envelope at this history point.
|
|
||||||
/// </summary>
|
|
||||||
public int Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Human-readable name of the status.
|
|
||||||
/// </summary>
|
|
||||||
public string? StatusName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Date and time when this history entry was added.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Date and time when an action was performed, if applicable.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ActionDate { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Information about the sender associated with this history entry.
|
|
||||||
/// </summary>
|
|
||||||
public UserCreateDto? Sender { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Information about the receiver associated with this history entry.
|
|
||||||
/// </summary>
|
|
||||||
public ReceiverReadDto? Receiver { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type of reference for this history entry.
|
|
||||||
/// </summary>
|
|
||||||
public ReferenceType ReferenceType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Optional comment related to this history entry.
|
|
||||||
/// </summary>
|
|
||||||
public string? Comment { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public override int GetHashCode() => Id.GetHashCode();
|
|
||||||
};
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record EnvelopeReceiverBasicDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int EnvelopeId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int ReceiverId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int Sequence { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[TemplatePlaceholder("[NAME_RECEIVER]")]
|
|
||||||
public string? Name { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? JobTitle { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? CompanyName { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? PrivateMessage { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ChangedWhen { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public bool HasPhoneNumber { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record EnvelopeReceiverDto() : EnvelopeReceiverBasicDto()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public EnvelopeDto? Envelope { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public ReceiverReadDto? Receiver { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record EnvelopeReceiverSecretDto : EnvelopeReceiverDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? AccessCode { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? PhoneNumber { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeReceiverReadOnly;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="DateValid"></param>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record EnvelopeReceiverReadOnlyCreateDto(
|
|
||||||
DateTime DateValid)
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[EmailAddress]
|
|
||||||
[Required]
|
|
||||||
public required string ReceiverMail { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is null
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public long? EnvelopeId { get; set; } = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public string? AddedWho { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is DateTime.Now
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public DateTime AddedWhen { get; } = DateTime.Now;
|
|
||||||
};
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeReceiverReadOnly;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a read-only Data Transfer Object (DTO) for an envelope receiver.
|
|
||||||
/// Contains information about the receiver, associated envelope, and audit details.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class EnvelopeReceiverReadOnlyDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the unique identifier of the envelope receiver.
|
|
||||||
/// </summary>
|
|
||||||
public long Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the identifier of the associated envelope.
|
|
||||||
/// </summary>
|
|
||||||
public long EnvelopeId { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the email address of the receiver.
|
|
||||||
/// </summary>
|
|
||||||
public required string ReceiverMail { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the date until which the receiver is valid.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime DateValid { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the date and time when the receiver was added.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the user who added the receiver.
|
|
||||||
/// Default value is 'unknown'.
|
|
||||||
/// </summary>
|
|
||||||
public string AddedWho { get; init; } = "Unknown";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the associated envelope details.
|
|
||||||
/// </summary>
|
|
||||||
public EnvelopeDto? Envelope { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the user who last changed the receiver, if any.
|
|
||||||
/// </summary>
|
|
||||||
public string? ChangedWho { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the date and time when the receiver was last changed, if any.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ChangedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or inits the associated receiver details.
|
|
||||||
/// </summary>
|
|
||||||
public ReceiverReadDto? Receiver { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.EnvelopeReceiverReadOnly;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object for updating a read-only envelope receiver.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class EnvelopeReceiverReadOnlyUpdateDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the unique identifier of the envelope receiver.
|
|
||||||
/// </summary>
|
|
||||||
public long Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the date when the envelope receiver becomes valid.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime DateValid { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the name of the user who made the change.
|
|
||||||
/// Default value is unknown.
|
|
||||||
/// </summary>
|
|
||||||
public string ChangedWho { get; set; } = "Unknown";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the date and time when the change was made.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime ChangedWhen { get; set; } = DateTime.Now;
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object representing a type of envelope with its configuration settings.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class EnvelopeTypeDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the unique identifier of the envelope type.
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the title of the envelope type.
|
|
||||||
/// </summary>
|
|
||||||
public string Title { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the language code used in this envelope type.
|
|
||||||
/// </summary>
|
|
||||||
public string Language { get; set; } = "de-DE";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the number of days after which the envelope expires.
|
|
||||||
/// </summary>
|
|
||||||
public int? ExpiresDays { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the certification type identifier.
|
|
||||||
/// </summary>
|
|
||||||
public int? CertificationType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether an access code is required.
|
|
||||||
/// </summary>
|
|
||||||
public bool? UseAccessCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the final email template ID to be sent to the creator.
|
|
||||||
/// </summary>
|
|
||||||
public int? FinalEmailToCreator { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the final email template ID to be sent to the receivers.
|
|
||||||
/// </summary>
|
|
||||||
public int? FinalEmailToReceivers { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the timestamp when this envelope type was added.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the timestamp when this envelope type was last changed.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? ChangedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the number of days before expiry when a warning should be sent.
|
|
||||||
/// </summary>
|
|
||||||
public int? ExpiresWarningDays { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether reminder emails should be sent.
|
|
||||||
/// </summary>
|
|
||||||
public bool? SendReminderEmails { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the number of days before the first reminder is sent.
|
|
||||||
/// </summary>
|
|
||||||
public int? FirstReminderDays { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the interval in days between reminder emails.
|
|
||||||
/// </summary>
|
|
||||||
public int? ReminderIntervalDays { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the contract type associated with the envelope type.
|
|
||||||
/// </summary>
|
|
||||||
public int? ContractType { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.Dto.EnvelopeHistory;
|
|
||||||
using EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
|
|
||||||
using EnvelopeGenerator.Application.Dto.EnvelopeReceiverReadOnly;
|
|
||||||
using EnvelopeGenerator.Application.Dto.Messaging;
|
|
||||||
using EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
using EnvelopeGenerator.Application.Extensions;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents the AutoMapper profile configuration for mapping between
|
|
||||||
/// domain entities and data transfer objects (DTOs) used within the EnvelopeGenerator application.
|
|
||||||
/// </summary>
|
|
||||||
public class MappingProfile : Profile
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="MappingProfile"/> class.
|
|
||||||
/// Configures the mappings between entities and DTOs used throughout the application.
|
|
||||||
/// </summary>
|
|
||||||
public MappingProfile()
|
|
||||||
{
|
|
||||||
// Entity to DTO mappings
|
|
||||||
CreateMap<Config, ConfigDto>();
|
|
||||||
CreateMap<DocumentReceiverElement, DocumentReceiverElementDto>();
|
|
||||||
CreateMap<DocumentStatus, DocumentStatusDto>();
|
|
||||||
CreateMap<EmailTemplate, EmailTemplateDto>();
|
|
||||||
CreateMap<Envelope, EnvelopeDto>();
|
|
||||||
CreateMap<EnvelopeDocument, EnvelopeDocumentDto>();
|
|
||||||
CreateMap<Domain.Entities.EnvelopeHistory, EnvelopeHistoryDto>();
|
|
||||||
CreateMap<Domain.Entities.EnvelopeHistory, EnvelopeHistoryCreateDto>();
|
|
||||||
CreateMap<Domain.Entities.EnvelopeReceiver, EnvelopeReceiverDto>();
|
|
||||||
CreateMap<Domain.Entities.EnvelopeReceiver, EnvelopeReceiverSecretDto>();
|
|
||||||
CreateMap<EnvelopeType, EnvelopeTypeDto>();
|
|
||||||
CreateMap<Domain.Entities.Receiver, ReceiverReadDto>();
|
|
||||||
CreateMap<Domain.Entities.Receiver, ReceiverCreateDto>();
|
|
||||||
CreateMap<Domain.Entities.Receiver, ReceiverUpdateDto>();
|
|
||||||
CreateMap<Domain.Entities.EnvelopeReceiverReadOnly, EnvelopeReceiverReadOnlyDto>();
|
|
||||||
|
|
||||||
// DTO to Entity mappings
|
|
||||||
CreateMap<ConfigDto, Config>();
|
|
||||||
CreateMap<DocumentReceiverElementDto, DocumentReceiverElement>();
|
|
||||||
CreateMap<DocumentStatusDto, DocumentStatus>();
|
|
||||||
CreateMap<EmailTemplateDto, EmailTemplate>();
|
|
||||||
CreateMap<EnvelopeDto, Envelope>();
|
|
||||||
CreateMap<EnvelopeDocumentDto, EnvelopeDocument>();
|
|
||||||
CreateMap<EnvelopeHistoryDto, Domain.Entities.EnvelopeHistory>();
|
|
||||||
CreateMap<EnvelopeHistoryCreateDto, Domain.Entities.EnvelopeHistory>();
|
|
||||||
CreateMap<EnvelopeReceiverDto, Domain.Entities.EnvelopeReceiver>();
|
|
||||||
CreateMap<EnvelopeTypeDto, EnvelopeType>();
|
|
||||||
CreateMap<ReceiverReadDto, Domain.Entities.Receiver>().ForMember(rcv => rcv.EnvelopeReceivers, rcvReadDto => rcvReadDto.Ignore());
|
|
||||||
CreateMap<ReceiverCreateDto, Domain.Entities.Receiver>();
|
|
||||||
CreateMap<ReceiverUpdateDto, Domain.Entities.Receiver>();
|
|
||||||
CreateMap<Domain.Entities.EnvelopeReceiver, EnvelopeReceiverBasicDto>();
|
|
||||||
CreateMap<EnvelopeReceiverReadOnlyCreateDto, Domain.Entities.EnvelopeReceiverReadOnly>();
|
|
||||||
CreateMap<EnvelopeReceiverReadOnlyUpdateDto, Domain.Entities.EnvelopeReceiverReadOnly>();
|
|
||||||
|
|
||||||
// Messaging mappings
|
|
||||||
// for GTX messaging
|
|
||||||
CreateMap<GtxMessagingResponse, SmsResponse>()
|
|
||||||
.ConstructUsing(gtxRes => gtxRes.Ok()
|
|
||||||
? new SmsResponse() { Ok = true }
|
|
||||||
: new SmsResponse() { Ok = false, Errors = gtxRes });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.Messaging;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class GtxMessagingResponse : Dictionary<string, object?> { }
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.Messaging;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record SmsResponse
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required bool Ok { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns !Ok
|
|
||||||
/// </summary>
|
|
||||||
public bool Failed => !Ok;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public dynamic? Errors { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public record ReceiverCreateDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public ReceiverCreateDto()
|
|
||||||
{
|
|
||||||
_sha256HexOfMail = new(() =>
|
|
||||||
{
|
|
||||||
var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress!.ToUpper());
|
|
||||||
var hash_arr = SHA256.HashData(bytes_arr);
|
|
||||||
var hexa_str = BitConverter.ToString(hash_arr);
|
|
||||||
return hexa_str.Replace("-", string.Empty);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[EmailAddress]
|
|
||||||
public required string EmailAddress { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? TotpSecretkey { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress.ToUpper());<br/>
|
|
||||||
/// var hash_arr = SHA256.HashData(bytes_arr);
|
|
||||||
/// var hexa_str = BitConverter.ToString(hash_arr);
|
|
||||||
/// return hexa_str.Replace("-", string.Empty);
|
|
||||||
/// </summary>
|
|
||||||
public string Signature => _sha256HexOfMail.Value;
|
|
||||||
|
|
||||||
private readonly Lazy<string> _sha256HexOfMail;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default value is DateTime.Now
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; } = DateTime.Now;
|
|
||||||
};
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class ReceiverReadDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required string EmailAddress { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public required string Signature { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
public IEnumerable<EnvelopeReceiverBasicDto>? EnvelopeReceivers { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? LastUsedName => EnvelopeReceivers?.LastOrDefault()?.Name;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? TotpSecretkey { get; set; } = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? TfaRegDeadline { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return Id.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Data Transfer Object for updating a receiver's information.
|
|
||||||
/// </summary>
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public class ReceiverUpdateDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the unique identifier of the receiver.
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the TOTP (Time-based One-Time Password) secret key.
|
|
||||||
/// Optional.
|
|
||||||
/// </summary>
|
|
||||||
public string? TotpSecretkey { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the deadline for two-factor authentication registration.
|
|
||||||
/// Optional.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? TfaRegDeadline { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using EnvelopeGenerator.Domain;
|
|
||||||
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="Constants.EmailTemplateType"/> (optional).</param>
|
|
||||||
public ResetEmailTemplateCommand(int? Id = null, Constants.EmailTemplateType? Type = null) : base(Id, Type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using EnvelopeGenerator.Application.Dto;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class ResetEmailTemplateCommandHandler : IRequestHandler<ResetEmailTemplateCommand>
|
|
||||||
{
|
|
||||||
private readonly IRepository<EmailTemplate> _repository;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="repository"></param>
|
|
||||||
public ResetEmailTemplateCommandHandler(IRepository<EmailTemplate> repository)
|
|
||||||
{
|
|
||||||
_repository = repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[Obsolete("Use Read-method returning IReadQuery<TEntity> instead.")]
|
|
||||||
public async Task Handle(ResetEmailTemplateCommand request, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
var temps = request.Id is not null
|
|
||||||
? await _repository.ReadOnly().Where(t => t.Id == request.Id).ToListAsync(cancel)
|
|
||||||
: request.Type is not null
|
|
||||||
? await _repository.ReadOnly().Where(t => t.Name == request.Type.ToString()).ToListAsync(cancel)
|
|
||||||
: await _repository.ReadOnly().ToListAsync(cancel);
|
|
||||||
|
|
||||||
foreach (var temp in temps)
|
|
||||||
{
|
|
||||||
var def = Defaults.Where(t => t.Name == temp.Name).FirstOrDefault();
|
|
||||||
if(def is not null)
|
|
||||||
await _repository.UpdateAsync(def, t => t.Id == temp.Id, cancel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static readonly IEnumerable<EmailTemplateDto> Defaults = new List<EmailTemplateDto>()
|
|
||||||
{
|
|
||||||
new(){
|
|
||||||
Id = 1,
|
|
||||||
Name = "DocumentReceived",
|
|
||||||
Body = "Guten Tag [NAME_RECEIVER],<br />\r\n<br /><B><I>\r\n[NAME_SENDER]</I></B> hat Ihnen ein Dokument zum [SIGNATURE_TYPE] gesendet.<br />\r\n<br />\r\nÜber den folgenden Link können Sie das Dokument einsehen und elektronisch unterschreiben: <a href=\"[LINK_TO_DOCUMENT]\">[LINK_TO_DOCUMENT_TEXT]</a><br />\r\n<br />\r\n[MESSAGE]<br />\r\n<br />\r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "Dokument erhalten: '[DOCUMENT_TITLE]'"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 2,
|
|
||||||
Name = "DocumentDeleted",
|
|
||||||
Body = "Guten Tag [NAME_RECEIVER],<br />\r\n<br /><B><I>\r\n[NAME_SENDER]</I></B> hat den Umschlag <B><I>'[DOCUMENT_TITLE]'</I></B> gelöscht/zurückgezogen.<br /><p>\rBegründung: <br /> <I>[REASON]</I> <p>\r\n<br />\r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "Umschlag zurückgezogen: '[DOCUMENT_TITLE]'"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 3,
|
|
||||||
Name = "DocumentSigned",
|
|
||||||
Body = "Guten Tag [NAME_RECEIVER],<br />\r\n<br />\r\nhiermit bestätigen wir Ihnen die erfolgreiche Signatur für den Vorgang <B><I>'[DOCUMENT_TITLE]'</I></B>.<br />\r\nWenn alle Vertragspartner unterzeichnet haben, erhalten Sie ebenfalls per email ein unterschriebenes Exemplar mit dem Signierungszertifikat!\r\n<br />\r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "Dokument unterschrieben: '[DOCUMENT_TITLE]'"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 4,
|
|
||||||
Name = "DocumentCompleted",
|
|
||||||
Body = "Guten Tag [NAME_RECEIVER],<br />\r\n<br />\r\nDer Signaturvorgang <B><I>'[DOCUMENT_TITLE]'</I></B> wurde erfolgreich abgeschlossen.<br />\r\n<br />\r\nSie erhalten das Dokument mit einem detaillierten Ergebnisbericht als Anhang zu dieser EmailAddress.<br />\r\n<br />\r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "Umschlag abgeschlossen: '[DOCUMENT_TITLE]'"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 5,
|
|
||||||
Name = "DocumentAccessCodeReceived",
|
|
||||||
Body = "Guten Tag [NAME_RECEIVER],<br />\r\n<br /><B><I>\r\n[NAME_SENDER]</I></B> hat Ihnen ein Dokument zum [SIGNATURE_TYPE] gesendet. <br />\r\n<br />\r\nVerwenden Sie den folgenden Zugriffscode, um das Dokument einzusehen:<br />\r\n<br />\r\n[DOCUMENT_ACCESS_CODE]<br />\r\n<br />\r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "Zugriffscode für Dokument erhalten: '[DOCUMENT_TITLE]'"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 6,
|
|
||||||
Name = "DocumentRejected_ADM",
|
|
||||||
Body = "Guten Tag [NAME_SENDER],<p><B><I>[NAME_RECEIVER]</I></B> hat den Umschlag <B><I>'[DOCUMENT_TITLE]'</I></B> mit folgendem Grund abgelehnt: <p>\r\n[REASON] \r\n<p>Der Umschlag wurde auf den Include Rejected gesetzt. <p> \r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "'[DOCUMENT_TITLE]' - Unterzeichnungsvorgang zurückgezogen"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 9,
|
|
||||||
Name = "DocumentRejected_REC",
|
|
||||||
Body = "Guten Tag [NAME_RECEIVER],\r\n<p>Hiermit bestätigen wir Ihnen die Ablehnung des Unterzeichnungsvorganges <B><I>'[DOCUMENT_TITLE]'</I></B>!<p>Der Vertragsinhaber <B><I>[NAME_SENDER]</I></B> wurde über die Ablehnung informiert. <p> \r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "'[DOCUMENT_TITLE]' - Bestätigung Ablehnung"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 10,
|
|
||||||
Name = "DocumentRejected_REC_2",
|
|
||||||
Body = "Guten Tag [NAME_RECEIVER],\r\n<p>Der Unterzeichnungsvorganges <B><I>'[DOCUMENT_TITLE]'</I></B> wurde durch einen anderen Vertragspartner abgelehnt! Ihre notwendige Unterzeichnung wurde verworfen.<p> Der Vertragsinhaber <B><I>[NAME_SENDER]</I></B> wird sich bei Bedarf mit Ihnen in Verbindung setzen. <p> \r\nMit freundlichen Grüßen<br />\r\n<br />\r\n[NAME_PORTAL]",
|
|
||||||
Subject = "'[DOCUMENT_TITLE]' - Unterzeichnungsvorgang abgelehnt."
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 11,
|
|
||||||
Name = "DocumentShared",
|
|
||||||
Body = "Guten Tag,<br /> <br /><B><I> [NAME_RECEIVER]</I></B> hat Ihnen ein Dokument zum Ansehen gesendet.<br /> <br /> Über den folgenden Link können Sie das Dokument einsehen: <a href=\"[LINK_TO_DOCUMENT]\">[LINK_TO_DOCUMENT_TEXT]</a><br /> <br /> <br /> Mit freundlichen Grüßen<br /> <br /> [NAME_PORTAL]",
|
|
||||||
Subject = "Dokument geteilt: '[DOCUMENT_TITLE]'"
|
|
||||||
},
|
|
||||||
new(){
|
|
||||||
Id = 12,
|
|
||||||
Name = "TotpSecret",
|
|
||||||
Body = "Guten Tag,<br /> <br />Sie können auf Ihren Zwei-Faktor-Authentifizierungscode zugreifen, indem Sie den unten stehenden QR-Code mit einer beliebigen Authentifizierungs-App auf Ihrem Telefon scannen (Google Authenticator, Microsoft Authenticator usw.). Dieser Code ist bis zum [TFA_EXPIRATION] gültig.<br /> <br /> <img src=\"data:image/png;base64,[TFA_QR_CODE]\" style=\"width: 13rem; height: 13rem;\"><br /> <br />\r\n<br /> Mit freundlichen Grüßen<br /> <br /> [NAME_PORTAL]",
|
|
||||||
Subject = "2-Faktor-Verifizierung QR-Code"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using EnvelopeGenerator.Application.Dto;
|
|
||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Domain;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
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 Constants.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,24 +0,0 @@
|
|||||||
using EnvelopeGenerator.Domain;
|
|
||||||
|
|
||||||
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="Constants.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, Constants.EmailTemplateType? Type = null)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
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, ReadEmailTemplateResponse>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
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?>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.Interfaces.Repositories;
|
|
||||||
using EnvelopeGenerator.Domain;
|
|
||||||
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 Constants.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
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,98 +1,56 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
</PropertyGroup>
|
||||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Resources\Model.Designer.vb" />
|
<None Remove="Resources\Model.Designer.vb" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapper" Version="2.1.66" />
|
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||||
<PackageReference Include="DigitalData.Core.Abstraction.Application" Version="1.2.1" />
|
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.0.0" />
|
||||||
<PackageReference Include="DigitalData.Core.Application" Version="3.4.0" />
|
<PackageReference Include="DigitalData.Core.Application" Version="2.0.0" />
|
||||||
<PackageReference Include="DigitalData.Core.Client" Version="2.1.0" />
|
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.0" />
|
||||||
<PackageReference Include="DigitalData.Core.Exceptions" Version="1.1.0" />
|
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="2.0.0" />
|
||||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
|
||||||
<PackageReference Include="MediatR" Version="12.5.0" />
|
<PackageReference Include="UserManager.Application" Version="2.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
|
<PackageReference Include="UserManager.Infrastructure" Version="2.0.0" />
|
||||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
</ItemGroup>
|
||||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
|
||||||
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
|
|
||||||
<PackageReference Include="UserManager" Version="1.1.3" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
|
||||||
</ItemGroup>
|
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
<Compile Update="Resources\Model.Designer.cs">
|
||||||
</ItemGroup>
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Model.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
<EmbeddedResource Update="Resources\Model.en.resx">
|
||||||
</ItemGroup>
|
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||||
|
<LastGenOutput>Model.en.Designer.vb</LastGenOutput>
|
||||||
<ItemGroup>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
|
</EmbeddedResource>
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
|
<EmbeddedResource Update="Resources\Model.resx">
|
||||||
</ItemGroup>
|
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||||
|
<LastGenOutput>Model.Designer.cs</LastGenOutput>
|
||||||
<ItemGroup>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
<Compile Update="Resources\Model.Designer.cs">
|
</EmbeddedResource>
|
||||||
<DesignTime>True</DesignTime>
|
<EmbeddedResource Update="Resources\Resource.de-DE.resx">
|
||||||
<AutoGen>True</AutoGen>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<DependentUpon>Model.resx</DependentUpon>
|
</EmbeddedResource>
|
||||||
</Compile>
|
<EmbeddedResource Update="Resources\Resource.en-US.resx">
|
||||||
</ItemGroup>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</EmbeddedResource>
|
||||||
<ItemGroup>
|
</ItemGroup>
|
||||||
<EmbeddedResource Update="Resources\Model.en.resx">
|
|
||||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
|
||||||
<LastGenOutput>Model.en.Designer.vb</LastGenOutput>
|
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<EmbeddedResource Update="Resources\Model.resx">
|
|
||||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
|
||||||
<LastGenOutput>Model.Designer.cs</LastGenOutput>
|
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<EmbeddedResource Update="Resources\Resource.de-DE.resx">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<EmbeddedResource Update="Resources\Resource.en-US.resx">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
|
|
||||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.3" />
|
|
||||||
<PackageReference Include="CommandDotNet">
|
|
||||||
<Version>7.0.5</Version>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
|
||||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
|
||||||
<PackageReference Include="CommandDotNet">
|
|
||||||
<Version>8.1.1</Version>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
|
||||||
<PackageReference Include="AutoMapper" Version="14.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
|
||||||
<PackageReference Include="CommandDotNet">
|
|
||||||
<Version>8.1.1</Version>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Envelopes.Commands;
|
|
||||||
using MediatR;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Befehl zur Erstellung eines Umschlags.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Title">Der Titel des Umschlags. Dies ist ein Pflichtfeld.</param>
|
|
||||||
/// <param name="Message">Die Nachricht, die im Umschlag enthalten sein soll. Dies ist ein Pflichtfeld.</param>
|
|
||||||
/// <param name="Document">Das mit dem Umschlag verknüpfte Dokument. Dies ist ein Pflichtfeld.</param>
|
|
||||||
/// <param name="Receivers">Eine Sammlung von Empfängern, die den Umschlag erhalten. Dies ist ein Pflichtfeld.</param>
|
|
||||||
/// <param name="TFAEnabled">Gibt an, ob die Zwei-Faktor-Authentifizierung für den Umschlag aktiviert ist. Standardmäßig false.</param>
|
|
||||||
public record CreateEnvelopeReceiverCommand(
|
|
||||||
[Required] string Title,
|
|
||||||
[Required] string Message,
|
|
||||||
[Required] DocumentCreateCommand Document,
|
|
||||||
[Required] IEnumerable<ReceiverGetOrCreateCommand> Receivers,
|
|
||||||
bool TFAEnabled = false
|
|
||||||
) : CreateEnvelopeCommand(Title, Message, TFAEnabled), IRequest<CreateEnvelopeReceiverResponse>;
|
|
||||||
|
|
||||||
#region Subcommands
|
|
||||||
/// <summary>
|
|
||||||
/// Signaturposition auf einem Dokument.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="X">X-Position</param>
|
|
||||||
/// <param name="Y">Y-Position</param>
|
|
||||||
/// <param name="Page">Seite, auf der sie sich befindet</param>
|
|
||||||
public record Signature([Required] double X, [Required] double Y, [Required] int Page);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DTO für Empfänger, die erstellt oder abgerufen werden sollen.
|
|
||||||
/// Wenn nicht, wird sie erstellt und mit einer Signatur versehen.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Signatures">Unterschriften auf Dokumenten.</param>
|
|
||||||
/// <param name="Salution">Der Name, mit dem der Empfänger angesprochen werden soll. Bei Null oder keinem Wert wird der zuletzt verwendete Name verwendet.</param>
|
|
||||||
/// <param name="PhoneNumber">Sollte mit Vorwahl geschrieben werden</param>
|
|
||||||
public record ReceiverGetOrCreateCommand([Required] IEnumerable<Signature> Signatures, string? Salution = null, string? PhoneNumber = null)
|
|
||||||
{
|
|
||||||
private string _emailAddress = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// E-Mail-Adresse des Empfängers.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public string EmailAddress { get => _emailAddress.ToLower(); init => _emailAddress = value.ToLower(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// DTO zum Erstellen eines Dokuments.
|
|
||||||
/// </summary>
|
|
||||||
public record DocumentCreateCommand()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Die Dokumentdaten im Base64-String-Format. Wird verwendet, wenn das Dokument als Base64-codierter String bereitgestellt wird.
|
|
||||||
/// </summary>
|
|
||||||
[Required]
|
|
||||||
public required string DataAsBase64 { get; init; }
|
|
||||||
};
|
|
||||||
#endregion
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
|
|
||||||
using EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the creation of an envelope along with its associated document and recipients.
|
|
||||||
/// This command processes the envelope data, including title, message, document content,
|
|
||||||
/// recipient list, and optional two-factor authentication settings.
|
|
||||||
/// </summary>
|
|
||||||
public class CreateEnvelopeReceiverCommandHandler : IRequestHandler<CreateEnvelopeReceiverCommand, CreateEnvelopeReceiverResponse>
|
|
||||||
{
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
private readonly IEnvelopeExecutor _envelopeExecutor;
|
|
||||||
|
|
||||||
private readonly IEnvelopeReceiverExecutor _erExecutor;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mapper"></param>
|
|
||||||
/// <param name="envelopeExecutor"></param>
|
|
||||||
/// <param name="erExecutor"></param>
|
|
||||||
public CreateEnvelopeReceiverCommandHandler(IMapper mapper, IEnvelopeExecutor envelopeExecutor, IEnvelopeReceiverExecutor erExecutor)
|
|
||||||
{
|
|
||||||
_mapper = mapper;
|
|
||||||
_envelopeExecutor = envelopeExecutor;
|
|
||||||
_erExecutor = erExecutor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the execution of the <see cref="CreateEnvelopeReceiverCommand"/>.
|
|
||||||
/// Responsible for validating input data, creating or retrieving recipients, associating signatures,
|
|
||||||
/// and storing the envelope and document details.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request">The command containing all necessary information to create an envelope.</param>
|
|
||||||
/// <param name="cancel">Token to observe while waiting for the task to complete.</param>
|
|
||||||
/// <returns>A task representing the asynchronous operation.</returns>
|
|
||||||
public async Task<CreateEnvelopeReceiverResponse> Handle(CreateEnvelopeReceiverCommand request, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
int userId = request.UserId ?? throw new InvalidOperationException("UserId cannot be null when creating an envelope.");
|
|
||||||
|
|
||||||
var envelope = await _envelopeExecutor.CreateEnvelopeAsync(userId, request.Title, request.Message, request.TFAEnabled, cancel);
|
|
||||||
|
|
||||||
List<EnvelopeReceiver> sentRecipients = new();
|
|
||||||
List<ReceiverGetOrCreateCommand> unsentRecipients = new();
|
|
||||||
|
|
||||||
foreach (var receiver in request.Receivers)
|
|
||||||
{
|
|
||||||
var envelopeReceiver = await _erExecutor.AddEnvelopeReceiverAsync(envelope.Uuid, receiver.EmailAddress, receiver.Salution, receiver.PhoneNumber, cancel);
|
|
||||||
|
|
||||||
if (envelopeReceiver is null)
|
|
||||||
unsentRecipients.Add(receiver);
|
|
||||||
else
|
|
||||||
sentRecipients.Add(envelopeReceiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
var res = _mapper.Map<CreateEnvelopeReceiverResponse>(envelope);
|
|
||||||
res.UnsentReceivers = unsentRecipients;
|
|
||||||
res.SentReceiver = _mapper.Map<IEnumerable<ReceiverReadDto>>(sentRecipients);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Dto;
|
|
||||||
using EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record CreateEnvelopeReceiverResponse : EnvelopeDto
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<ReceiverReadDto> SentReceiver { get; set; } = new List<ReceiverReadDto>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public IEnumerable<ReceiverGetOrCreateCommand> UnsentReceivers { get; set; } = new List<ReceiverGetOrCreateCommand>();
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.Dto.Receiver;
|
|
||||||
using EnvelopeGenerator.Application.Envelopes.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class MappingProfile : Profile
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public MappingProfile()
|
|
||||||
{
|
|
||||||
CreateMap<Receiver, ReceiverReadDto>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
|
|
||||||
using EnvelopeGenerator.Application.Envelopes.Queries;
|
|
||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Application.Extensions;
|
|
||||||
using EnvelopeGenerator.Application.Receivers.Queries;
|
|
||||||
using EnvelopeGenerator.Extensions;
|
|
||||||
using MediatR;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Repräsentiert eine Abfrage zum Lesen eines Envelope-Empfängers.
|
|
||||||
/// Invalid (0): Ungültiger Include.
|
|
||||||
/// EnvelopeCreated (1001): Der Umschlag wurde erstellt.
|
|
||||||
/// EnvelopeSaved (1002): Der Umschlag wurde gespeichert.
|
|
||||||
/// EnvelopeQueued (1003): Der Umschlag wurde zur Verarbeitung eingeplant.
|
|
||||||
/// EnvelopeSent (1004): Der Umschlag wurde versendet. (Nicht verwendet)
|
|
||||||
/// EnvelopePartlySigned (1005): Der Umschlag wurde teilweise unterschrieben.
|
|
||||||
/// EnvelopeCompletelySigned (1006): Der Umschlag wurde vollständig unterschrieben.
|
|
||||||
/// EnvelopeReportCreated (1007): Ein Abschlussbericht wurde für den Umschlag erstellt.
|
|
||||||
/// EnvelopeArchived (1008): Der Umschlag wurde archiviert.
|
|
||||||
/// EnvelopeDeleted (1009): Der Umschlag wurde gelöscht.
|
|
||||||
/// AccessCodeRequested (2001): Der Zugriffscode wurde angefordert.
|
|
||||||
/// AccessCodeCorrect (2002): Der Zugriffscode war korrekt.
|
|
||||||
/// AccessCodeIncorrect (2003): Der Zugriffscode war falsch.
|
|
||||||
/// DocumentOpened (2004): Das Dokument wurde geöffnet.
|
|
||||||
/// DocumentSigned (2005): Ein Dokument wurde unterschrieben.
|
|
||||||
/// SignatureConfirmed (2006): Die Signatur wurde bestätigt.
|
|
||||||
/// DocumentRejected (2007): Ein Dokument wurde abgelehnt.
|
|
||||||
/// EnvelopeShared (2008): Der Umschlag wurde geteilt.
|
|
||||||
/// EnvelopeViewed (2009): Der Umschlag wurde angesehen.
|
|
||||||
/// DocumentForwarded (4001): Das Dokument wurde weitergeleitet.
|
|
||||||
/// MessageInvitationSent (3001): Einladung wurde gesendet (vom Trigger verwendet).
|
|
||||||
/// MessageAccessCodeSent (3002): Zugriffscode wurde gesendet.
|
|
||||||
/// MessageConfirmationSent (3003): Bestätigungsnachricht wurde gesendet.
|
|
||||||
/// MessageDeletionSent (3004): Löschbenachrichtigung wurde gesendet.
|
|
||||||
/// MessageCompletionSent (3005): Abschlussbenachrichtigung wurde gesendet.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Diese Abfrage kombiniert Informationen über einen Umschlag (<see cref="ReadEnvelopeQuery"/>)
|
|
||||||
/// und einen Empfänger (<see cref="ReadReceiverQuery"/>), um eine vollständige Antwort
|
|
||||||
/// (<see cref="EnvelopeReceiverDto"/>) zu generieren.
|
|
||||||
/// Die Antwort enthält Details wie den Include, die Zuordnung zwischen Umschlag und Empfänger
|
|
||||||
/// sowie zusätzliche Metadaten.
|
|
||||||
/// </remarks>
|
|
||||||
public record ReadEnvelopeReceiverQuery : IRequest<IEnumerable<EnvelopeReceiverDto>>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? Key
|
|
||||||
{
|
|
||||||
get => Envelope?.Uuid is string uuid && Receiver?.Signature is string signature
|
|
||||||
? (uuid, signature).EncodeEnvelopeReceiverId()
|
|
||||||
: null;
|
|
||||||
init
|
|
||||||
{
|
|
||||||
if (value is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
(string? EnvelopeUuid, string? ReceiverSignature) = value.DecodeEnvelopeReceiverId();
|
|
||||||
if(string.IsNullOrEmpty(EnvelopeUuid) || string.IsNullOrEmpty(ReceiverSignature))
|
|
||||||
{
|
|
||||||
throw new BadRequestException("Der EnvelopeReceiverKey muss ein gültiger Base64-kodierter String sein, der die EnvelopeUuid und die ReceiverSignature enthält.");
|
|
||||||
}
|
|
||||||
Envelope = new ReadEnvelopeQuery()
|
|
||||||
{
|
|
||||||
Uuid = EnvelopeUuid
|
|
||||||
};
|
|
||||||
Receiver = new ReadReceiverQuery()
|
|
||||||
{
|
|
||||||
Signature = ReceiverSignature
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Der Umschlag, der mit dem Empfänger verknüpft ist.
|
|
||||||
/// </summary>
|
|
||||||
public ReadEnvelopeQuery? Envelope { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Der Empfänger, der mit dem Umschlag verknüpft ist.
|
|
||||||
/// </summary>
|
|
||||||
public ReadReceiverQuery? Receiver { get; set; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mediator"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Task<EnvelopeReceiverDto?> ReadEnvelopeReceiverAsync(this IMediator mediator, string key, CancellationToken cancel = default)
|
|
||||||
{
|
|
||||||
var q = new ReadEnvelopeReceiverQuery() { Key = key };
|
|
||||||
return mediator.Send(q, cancel).Then(envRcvs => envRcvs.FirstOrDefault());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using EnvelopeGenerator.Application.Dto.EnvelopeReceiver;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeReceiverQuery, IEnumerable<EnvelopeReceiverDto>>
|
|
||||||
{
|
|
||||||
private readonly IRepository<EnvelopeReceiver> _repo;
|
|
||||||
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeReceiver"></param>
|
|
||||||
/// <param name="mapper"></param>
|
|
||||||
public ReadEnvelopeReceiverQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiver, IMapper mapper)
|
|
||||||
{
|
|
||||||
_repo = envelopeReceiver;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
|
||||||
public async Task<IEnumerable<EnvelopeReceiverDto>> Handle(ReadEnvelopeReceiverQuery request, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
var q = _repo.Read();
|
|
||||||
|
|
||||||
if(request.Envelope is not null)
|
|
||||||
{
|
|
||||||
var env = request.Envelope;
|
|
||||||
if (env.Id is not null)
|
|
||||||
q = q.Where(er => er.EnvelopeId == env.Id);
|
|
||||||
|
|
||||||
if (env.Status is not null)
|
|
||||||
{
|
|
||||||
if(env.Status.Min is not null)
|
|
||||||
q = q.Where(er => er.Envelope.Status >= env.Status.Min);
|
|
||||||
|
|
||||||
if(env.Status.Max is not null)
|
|
||||||
q = q.Where(er => er.Envelope.Status <= env.Status.Max);
|
|
||||||
|
|
||||||
if(env.Status .Include?.Length > 0)
|
|
||||||
q = q.Where(er => env.Status.Include.Contains(er.Envelope.Status));
|
|
||||||
|
|
||||||
if(env.Status.Ignore is not null)
|
|
||||||
q = q.Where(er => !env.Status.Ignore.Contains(er.Envelope.Status));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env.Uuid is not null)
|
|
||||||
q = q.Where(er => er.Envelope.Uuid == env.Uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.Receiver is not null)
|
|
||||||
{
|
|
||||||
var rcv = request.Receiver;
|
|
||||||
if (rcv.Id is not null)
|
|
||||||
q = q.Where(r => r.ReceiverId == rcv.Id);
|
|
||||||
|
|
||||||
if (rcv.EmailAddress is not null)
|
|
||||||
q = q.Where(r => r.Receiver.EmailAddress == rcv.EmailAddress);
|
|
||||||
|
|
||||||
if (rcv.Signature is not null)
|
|
||||||
q = q.Where(er => er.Receiver.Signature == rcv.Signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
var envRcvs = await q.Include(er => er.Envelope).ThenInclude(e => e.Documents).ThenInclude(d => d.Elements)
|
|
||||||
.Include(er => er.Envelope).ThenInclude(e => e.History)
|
|
||||||
.Include(er => er.Envelope).ThenInclude(e => e.User)
|
|
||||||
.Include(er => er.Receiver)
|
|
||||||
.ToListAsync(cancel);
|
|
||||||
|
|
||||||
return _mapper.Map<IEnumerable<EnvelopeReceiverDto>>(envRcvs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using DigitalData.Core.Exceptions;
|
|
||||||
using EnvelopeGenerator.Domain;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using EnvelopeGenerator.Extensions;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record ReceiverAlreadySignedQuery : IRequest<bool>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Key
|
|
||||||
{
|
|
||||||
get => (Envelope.Uuid, Receiver.Signature).EncodeEnvelopeReceiverId();
|
|
||||||
init
|
|
||||||
{
|
|
||||||
(string? EnvelopeUuid, string? ReceiverSignature) = value.DecodeEnvelopeReceiverId();
|
|
||||||
if (string.IsNullOrEmpty(EnvelopeUuid) || string.IsNullOrEmpty(ReceiverSignature))
|
|
||||||
{
|
|
||||||
throw new BadRequestException("Der EnvelopeReceiverKey muss ein gültiger Base64-kodierter String sein, der die EnvelopeUuid und die ReceiverSignature enthält.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public EnvelopeQuery Envelope { get; set; } = new EnvelopeQuery();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public ReceiverQuery Receiver { get; set; } = new ReceiverQuery();
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Queries
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record EnvelopeQuery()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Uuid { get; set; } = null!;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record ReceiverQuery()
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string Signature { get; set; } = null!;
|
|
||||||
};
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class ReceiverAlreadySignedQueryExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mediator"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Task<bool> IsSignedAsync(this IMediator mediator, string key, CancellationToken cancel = default)
|
|
||||||
=> mediator.Send(new ReceiverAlreadySignedQuery { Key = key }, cancel);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="mediator"></param>
|
|
||||||
/// <param name="uuid"></param>
|
|
||||||
/// <param name="signature"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Task<bool> IsSignedAsync(this IMediator mediator, string uuid, string signature, CancellationToken cancel = default)
|
|
||||||
=> mediator.Send(new ReceiverAlreadySignedQuery
|
|
||||||
{
|
|
||||||
Envelope = new() { Uuid = uuid },
|
|
||||||
Receiver = new() { Signature = signature }
|
|
||||||
}, cancel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class ReceiverAlreadySignedQueryHandler : IRequestHandler<ReceiverAlreadySignedQuery, bool>
|
|
||||||
{
|
|
||||||
private readonly IRepository<EnvelopeReceiver> _repo;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="repo"></param>
|
|
||||||
public ReceiverAlreadySignedQueryHandler(IRepository<EnvelopeReceiver> repo)
|
|
||||||
{
|
|
||||||
_repo = repo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> Handle(ReceiverAlreadySignedQuery request, CancellationToken cancel = default)
|
|
||||||
{
|
|
||||||
return await _repo.Read()
|
|
||||||
.Where(er => er.Envelope.Uuid == request.Envelope.Uuid)
|
|
||||||
.Where(er => er.Receiver.Signature == request.Receiver.Signature)
|
|
||||||
.Where(er => er.Envelope.History.Any(hist => hist.Status == Constants.EnvelopeStatus.DocumentSigned))
|
|
||||||
.AnyAsync(cancel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Dto;
|
|
||||||
using EnvelopeGenerator.Application.Envelopes.Queries;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Envelopes.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Befehl zur Erstellung eines Umschlags.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Title">Der Titel des Umschlags. Dies ist ein Pflichtfeld.</param>
|
|
||||||
/// <param name="Message">Die Nachricht, die im Umschlag enthalten sein soll. Dies ist ein Pflichtfeld.</param>
|
|
||||||
/// <param name="TFAEnabled">Gibt an, ob die Zwei-Faktor-Authentifizierung für den Umschlag aktiviert ist. Standardmäßig false.</param>
|
|
||||||
public record CreateEnvelopeCommand(
|
|
||||||
[Required] string Title,
|
|
||||||
[Required] string Message,
|
|
||||||
bool TFAEnabled = false
|
|
||||||
) : IRequest<EnvelopeDto?>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Id of receiver
|
|
||||||
/// </summary>
|
|
||||||
[JsonIgnore]
|
|
||||||
[BindNever]
|
|
||||||
public int? UserId { get; set; }
|
|
||||||
};
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.Interfaces.SQLExecutor;
|
|
||||||
using EnvelopeGenerator.Application.Dto;
|
|
||||||
using MediatR;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Envelopes.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class CreateEnvelopeCommandHandler : IRequestHandler<CreateEnvelopeCommand, EnvelopeDto?>
|
|
||||||
{
|
|
||||||
private readonly IEnvelopeExecutor _envelopeExecutor;
|
|
||||||
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="envelopeExecutor"></param>
|
|
||||||
/// <param name="mapper"></param>
|
|
||||||
public CreateEnvelopeCommandHandler(IEnvelopeExecutor envelopeExecutor, IMapper mapper)
|
|
||||||
{
|
|
||||||
_envelopeExecutor = envelopeExecutor;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancellationToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<EnvelopeDto?> Handle(CreateEnvelopeCommand request, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
int userId = request.UserId ?? throw new InvalidOperationException("UserId cannot be null when creating an envelope.");
|
|
||||||
|
|
||||||
var envelope = await _envelopeExecutor.CreateEnvelopeAsync(userId, request.Title, request.Message, request.TFAEnabled, cancellationToken);
|
|
||||||
|
|
||||||
return _mapper.Map<EnvelopeDto>(envelope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Commands;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Envelopes;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class MappingProfile : Profile
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public MappingProfile()
|
|
||||||
{
|
|
||||||
CreateMap<Envelope, CreateEnvelopeReceiverResponse>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
using MediatR;
|
|
||||||
using EnvelopeGenerator.Domain;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Repräsentiert eine Abfrage für Umschläge.
|
|
||||||
/// </summary>
|
|
||||||
public class ReadEnvelopeQuery : IRequest
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Die eindeutige Kennung des Umschlags.
|
|
||||||
/// </summary>
|
|
||||||
public int? Id { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Die universell eindeutige Kennung des Umschlags.
|
|
||||||
/// </summary>
|
|
||||||
public string? Uuid { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Abfrage des Include des Umschlags
|
|
||||||
/// </summary>
|
|
||||||
public EnvelopeStatus? Status { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Repräsentiert den Include eines Umschlags und dessen Beziehung zum Empfänger. (vgl. auch <see cref="Constants.EnvelopeStatus"/>
|
|
||||||
/// Invalid (0): Ungültiger Include.
|
|
||||||
/// EnvelopeCreated (1001): Der Umschlag wurde erstellt.
|
|
||||||
/// EnvelopeSaved (1002): Der Umschlag wurde gespeichert.
|
|
||||||
/// EnvelopeQueued (1003): Der Umschlag wurde zur Verarbeitung eingeplant.
|
|
||||||
/// EnvelopeSent (1004): Der Umschlag wurde versendet. (Nicht verwendet)
|
|
||||||
/// EnvelopePartlySigned (1005): Der Umschlag wurde teilweise unterschrieben.
|
|
||||||
/// EnvelopeCompletelySigned (1006): Der Umschlag wurde vollständig unterschrieben.
|
|
||||||
/// EnvelopeReportCreated (1007): Ein Abschlussbericht wurde für den Umschlag erstellt.
|
|
||||||
/// EnvelopeArchived (1008): Der Umschlag wurde archiviert.
|
|
||||||
/// EnvelopeDeleted (1009): Der Umschlag wurde gelöscht.
|
|
||||||
/// AccessCodeRequested (2001): Der Zugriffscode wurde angefordert.
|
|
||||||
/// AccessCodeCorrect (2002): Der Zugriffscode war korrekt.
|
|
||||||
/// AccessCodeIncorrect (2003): Der Zugriffscode war falsch.
|
|
||||||
/// DocumentOpened (2004): Das Dokument wurde geöffnet.
|
|
||||||
/// DocumentSigned (2005): Ein Dokument wurde unterschrieben.
|
|
||||||
/// SignatureConfirmed (2006): Die Signatur wurde bestätigt.
|
|
||||||
/// DocumentRejected (2007): Ein Dokument wurde abgelehnt.
|
|
||||||
/// EnvelopeShared (2008): Der Umschlag wurde geteilt.
|
|
||||||
/// EnvelopeViewed (2009): Der Umschlag wurde angesehen.
|
|
||||||
/// DocumentForwarded (4001): Das Dokument wurde weitergeleitet.
|
|
||||||
/// MessageInvitationSent (3001): Einladung wurde gesendet (vom Trigger verwendet).
|
|
||||||
/// MessageAccessCodeSent (3002): Zugriffscode wurde gesendet.
|
|
||||||
/// MessageConfirmationSent (3003): Bestätigungsnachricht wurde gesendet.
|
|
||||||
/// MessageDeletionSent (3004): Löschbenachrichtigung wurde gesendet.
|
|
||||||
/// MessageCompletionSent (3005): Abschlussbenachrichtigung wurde gesendet.
|
|
||||||
/// </summary>
|
|
||||||
public record EnvelopeStatus
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Der minimale Statuswert, der berücksichtigt werden.
|
|
||||||
/// </summary>
|
|
||||||
public Constants.EnvelopeStatus? Min { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Der maximale Statuswert, der berücksichtigt werden.
|
|
||||||
/// </summary>
|
|
||||||
public Constants.EnvelopeStatus? Max { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Eine Liste von Statuswerten, die einbezogen werden.
|
|
||||||
/// </summary>
|
|
||||||
public Constants.EnvelopeStatus[]? Include { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Eine Liste von Statuswerten, die ignoriert werden werden.
|
|
||||||
/// </summary>
|
|
||||||
public Constants.EnvelopeStatus[]? Ignore { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Receivers.Queries;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Envelopes.Queries;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 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() : ReadReceiverQuery
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
using Microsoft.Extensions.Caching.Distributed;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class CacheExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Task SetLongAsync(this IDistributedCache cache, string key, long value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
|
|
||||||
=> options is null
|
|
||||||
? cache.SetAsync(key, BitConverter.GetBytes(value), token: cToken)
|
|
||||||
: cache.SetAsync(key, BitConverter.GetBytes(value), options: options, token: cToken);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<long?> GetLongAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
|
|
||||||
{
|
|
||||||
var value = await cache.GetAsync(key, cToken);
|
|
||||||
return value is null ? null : BitConverter.ToInt64(value, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Task SetDateTimeAsync(this IDistributedCache cache, string key, DateTime value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
|
|
||||||
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options, cToken: cToken);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<DateTime?> GetDateTimeAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
|
|
||||||
{
|
|
||||||
var value = await cache.GetAsync(key, cToken);
|
|
||||||
return value is null ? null : new(BitConverter.ToInt64(value, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Task SetTimeSpanAsync(this IDistributedCache cache, string key, TimeSpan value, DistributedCacheEntryOptions? options = null, CancellationToken cToken = default)
|
|
||||||
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options, cToken);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<TimeSpan?> GetTimeSpanAsync(this IDistributedCache cache, string key, CancellationToken cToken = default)
|
|
||||||
{
|
|
||||||
var value = await cache.GetAsync(key, cToken);
|
|
||||||
return value is null ? null : new(BitConverter.ToInt64(value, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: use code generator
|
|
||||||
#region GetOrSetAsync
|
|
||||||
|
|
||||||
#region string
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="factory"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="cacheInBackground"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<string> GetOrSetAsync(this IDistributedCache cache, string key, Func<string> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
|
|
||||||
{
|
|
||||||
var value = await cache.GetStringAsync(key, cToken);
|
|
||||||
if (value is null)
|
|
||||||
{
|
|
||||||
// create new and save
|
|
||||||
value = factory();
|
|
||||||
|
|
||||||
Task CacheAsync() => options is null
|
|
||||||
? cache.SetStringAsync(key, value, cToken)
|
|
||||||
: cache.SetStringAsync(key, value, options, cToken);
|
|
||||||
|
|
||||||
if (cacheInBackground)
|
|
||||||
_ = Task.Run(async () => await CacheAsync(), cToken);
|
|
||||||
else
|
|
||||||
await CacheAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="factoryAsync"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="cacheInBackground"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<string> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<string>> factoryAsync, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
|
|
||||||
{
|
|
||||||
var value = await cache.GetStringAsync(key, cToken);
|
|
||||||
if(value is null)
|
|
||||||
{
|
|
||||||
// create new and save
|
|
||||||
value = await factoryAsync();
|
|
||||||
|
|
||||||
Task CacheAsync() => options is null
|
|
||||||
? cache.SetStringAsync(key: key, value: value, token: cToken)
|
|
||||||
: cache.SetStringAsync(key: key, value: value, options: options, token: cToken);
|
|
||||||
|
|
||||||
if (cacheInBackground)
|
|
||||||
_ = Task.Run(async () => await CacheAsync(), cToken);
|
|
||||||
else
|
|
||||||
await CacheAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region DateTime
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="factory"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="cacheInBackground"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<DateTime> GetOrSetAsync(this IDistributedCache cache, string key, Func<DateTime> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
|
|
||||||
{
|
|
||||||
if (await cache.GetDateTimeAsync(key, cToken) is DateTime dateTimeValue)
|
|
||||||
return dateTimeValue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create new and save
|
|
||||||
var newValue = factory();
|
|
||||||
|
|
||||||
Task CacheAsync() => options is null
|
|
||||||
? cache.SetDateTimeAsync(key, newValue, cToken: cToken)
|
|
||||||
: cache.SetDateTimeAsync(key, newValue, options, cToken);
|
|
||||||
|
|
||||||
if (cacheInBackground)
|
|
||||||
_ = Task.Run(async () => await CacheAsync(), cToken);
|
|
||||||
else
|
|
||||||
await CacheAsync();
|
|
||||||
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cache"></param>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="factory"></param>
|
|
||||||
/// <param name="options"></param>
|
|
||||||
/// <param name="cacheInBackground"></param>
|
|
||||||
/// <param name="cToken"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<DateTime> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<DateTime>> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken cToken = default)
|
|
||||||
{
|
|
||||||
if (await cache.GetDateTimeAsync(key, cToken) is DateTime dateTimeValue)
|
|
||||||
return dateTimeValue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// create new and save
|
|
||||||
var newValue = await factory();
|
|
||||||
|
|
||||||
Task CacheAsync() => options is null
|
|
||||||
? cache.SetDateTimeAsync(key, newValue, cToken: cToken)
|
|
||||||
: cache.SetDateTimeAsync(key, newValue, options, cToken);
|
|
||||||
|
|
||||||
if (cacheInBackground)
|
|
||||||
_ = Task.Run(async () => await CacheAsync(), cToken);
|
|
||||||
else
|
|
||||||
await CacheAsync();
|
|
||||||
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using EnvelopeGenerator.Application.Dto.Messaging;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides extension methods for common mapping and conversion operations.
|
|
||||||
/// </summary>
|
|
||||||
public static class MappingExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether the response indicates a successful "OK" message status.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="gtxMessagingResponse">The response object to evaluate.</param>
|
|
||||||
/// <returns><see langword="true"/> if the response contains a "message-status" key with a value of "ok" (case-insensitive);
|
|
||||||
/// otherwise, <see langword="false"/>.</returns>
|
|
||||||
public static bool Ok(this GtxMessagingResponse gtxMessagingResponse)
|
|
||||||
=> gtxMessagingResponse.TryGetValue("message-status", out var status)
|
|
||||||
&& status?.ToString()?.ToLower() == "ok";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts the specified byte array to its equivalent string representation encoded in base-64.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bytes">The byte array to encode.</param>
|
|
||||||
/// <returns>A base-64 encoded string representation of the input byte array.</returns>
|
|
||||||
public static string ToBase64String(this byte[] bytes)
|
|
||||||
=> Convert.ToBase64String(bytes);
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
using DigitalData.Core.Exceptions;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for tasks
|
|
||||||
/// </summary>
|
|
||||||
public static class TaskExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Awaits the specified task and ensures that the result is not <c>null</c>.
|
|
||||||
/// If the result is <c>null</c>, the exception created by factory-method is thrown.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The type of the result.</typeparam>
|
|
||||||
/// <typeparam name="TException">The type of the exception.</typeparam>
|
|
||||||
/// <param name="task">The task to await.</param>
|
|
||||||
/// <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>
|
|
||||||
public static async Task<T> ThrowIfNull<T, TException>(this Task<T?> task, Func<TException> factory) where TException : Exception
|
|
||||||
{
|
|
||||||
var result = await task;
|
|
||||||
return result ?? throw factory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Awaits the specified task and ensures that the result is not <c>empty</c>.
|
|
||||||
/// If the result contains no elements, the exception created by factory-method is thrown.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The element type of the collection.</typeparam>
|
|
||||||
/// <typeparam name="TException">The type of the exception.</typeparam>
|
|
||||||
/// <param name="task">The task to await.</param>
|
|
||||||
/// <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>
|
|
||||||
public static async Task<IEnumerable<T>> ThrowIfNull<T, TException>(this Task<IEnumerable<T>> task, Func<TException> factory) where TException : Exception
|
|
||||||
{
|
|
||||||
var result = await task;
|
|
||||||
return result?.Any() ?? false ? result : throw factory();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
/// <typeparam name="I"></typeparam>
|
|
||||||
/// <param name="task"></param>
|
|
||||||
/// <param name="act"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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>
|
|
||||||
public static class Exceptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static NotFoundException NotFound() => new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static BadRequestException BadRequest() => new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static ForbiddenException Forbidden() => new();
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
using DigitalData.Core.Abstraction.Application.Repository;
|
|
||||||
using EnvelopeGenerator.Domain;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Histories.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public record CreateHistoryCommand : IRequest<long?>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public int EnvelopeId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string UserReference { get; set; } = null!;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public Constants.EnvelopeStatus Status { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime AddedWhen { get; } = DateTime.Now;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public DateTime ActionDate => AddedWhen;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public string? Comment { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class CreateHistoryCommandHandler : IRequestHandler<CreateHistoryCommand, long?>
|
|
||||||
{
|
|
||||||
private readonly IRepository<EnvelopeHistory> _repo;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="repo"></param>
|
|
||||||
public CreateHistoryCommandHandler(IRepository<EnvelopeHistory> repo)
|
|
||||||
{
|
|
||||||
_repo = repo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="request"></param>
|
|
||||||
/// <param name="cancel"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<long?> Handle(CreateHistoryCommand request, CancellationToken cancel)
|
|
||||||
{
|
|
||||||
// create entitiy
|
|
||||||
await _repo.CreateAsync(request, cancel);
|
|
||||||
|
|
||||||
// check if created
|
|
||||||
var record = await _repo.ReadOnly()
|
|
||||||
.Where(h => h.EnvelopeId == request.EnvelopeId)
|
|
||||||
.Where(h => h.UserReference == request.UserReference)
|
|
||||||
.Where(h => h.ActionDate == request.ActionDate)
|
|
||||||
.SingleOrDefaultAsync(cancel);
|
|
||||||
|
|
||||||
return record?.Id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using EnvelopeGenerator.Application.Histories.Commands;
|
|
||||||
using EnvelopeGenerator.Application.Histories.Queries.Read;
|
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Histories;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class MappingProfile: Profile
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public MappingProfile()
|
|
||||||
{
|
|
||||||
CreateMap<EnvelopeHistory, ReadHistoryResponse>();
|
|
||||||
CreateMap<CreateHistoryCommand, EnvelopeHistory>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user