Compare commits
298 Commits
customer/C
...
c41d5c4a76
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c41d5c4a76 | ||
|
|
27db664b4d | ||
|
|
ba2518cdd2 | ||
|
|
72a0cb78c7 | ||
|
|
e82d7552c2 | ||
|
|
4b50b6c35d | ||
|
|
103d8da6b2 | ||
|
|
15f3bd1bbd | ||
|
|
10a5adeeee | ||
|
|
3b5c6086a9 | ||
|
|
abda0d14e8 | ||
|
|
569ebc87cc | ||
|
|
6b6c8e407c | ||
|
|
556d02870e | ||
|
|
c6fc665002 | ||
|
|
030fd0e45b | ||
|
|
31e647d3e5 | ||
|
|
6dfdd48ec0 | ||
|
|
85cacc822d | ||
|
|
535ca23c86 | ||
|
|
7f1009e402 | ||
|
|
ea4b35f4b4 | ||
|
|
8e1b4e0832 | ||
|
|
4f5b8f9d76 | ||
|
|
f06b41492e | ||
|
|
f0f1275e75 | ||
|
|
085f37de16 | ||
|
|
1657a99aa6 | ||
|
|
ff6d27df8e | ||
|
|
76bd1a102f | ||
|
|
6a6da39bc4 | ||
|
|
137d8e09d4 | ||
|
|
bed51992d2 | ||
|
|
a371abaabe | ||
|
|
90c6e87224 | ||
|
|
4af1534194 | ||
|
|
f39ac57009 | ||
|
|
88d01e4ac7 | ||
|
|
85c33eb0f8 | ||
|
|
1bc31fe0ee | ||
|
|
2e790b4e4c | ||
|
|
19485860a5 | ||
|
|
e33d859603 | ||
|
|
46b8bde162 | ||
|
|
a6468c2ff1 | ||
|
|
40a21a0b89 | ||
|
|
fa44b82493 | ||
|
|
cdec5485c6 | ||
|
|
2a963a1861 | ||
|
|
9d1a2e7254 | ||
|
|
b779ef6f0b | ||
|
|
0c81a86610 | ||
|
|
b11f32bd3c | ||
|
|
b8d9963fac | ||
|
|
e77532ebfd | ||
|
|
ec37518245 | ||
|
|
a1618fc8d0 | ||
|
|
6b65fc28fd | ||
|
|
a763fd6a24 | ||
|
|
28a8e20b63 | ||
|
|
155f80e8b3 | ||
|
|
d8f74971f3 | ||
|
|
44dc7185c6 | ||
|
|
551ba595b6 | ||
|
|
4b77713df4 | ||
|
|
f1ca1e9067 | ||
|
|
0469f057c9 | ||
|
|
b4a97abe6b | ||
|
|
423b293197 | ||
|
|
27618a343e | ||
|
|
fe106c5a8c | ||
|
|
941b98b1a4 | ||
|
|
168c33bfea | ||
|
|
40c25ee111 | ||
|
|
608d79d35b | ||
|
|
62d396932d | ||
|
|
62dcb41526 | ||
|
|
360bb9b3d8 | ||
|
|
1f57914f9e | ||
|
|
9c431ddf56 | ||
|
|
61ff2f8cde | ||
|
|
f2ee509727 | ||
|
|
da06daf776 | ||
|
|
d3104500d4 | ||
|
|
d23b8b9187 | ||
|
|
ec206ab33a | ||
|
|
de6d4b9dd8 | ||
|
|
2943fe0e2d | ||
|
|
33e99f584a | ||
|
|
4a62ab0c56 | ||
|
|
132acd35cc | ||
|
|
ed80839777 | ||
|
|
2114615584 | ||
|
|
6e6f3fd2ed | ||
|
|
5da306acd3 | ||
|
|
18ef1d19b5 | ||
|
|
b76ebd2abc | ||
|
|
d55233061d | ||
|
|
949001791c | ||
|
|
30f93f2439 | ||
|
|
36ffb9511c | ||
|
|
bf84d5c63a | ||
|
|
57f8d0e398 | ||
|
|
bb8bd8ed40 | ||
|
|
ba832acad3 | ||
|
|
6490a3cb82 | ||
|
|
4c077c90db | ||
|
|
9bd5e63128 | ||
|
|
15ce7c9384 | ||
|
|
8707a5cdb5 | ||
|
|
47c7070700 | ||
|
|
fcc3223eb1 | ||
|
|
c4114a3800 | ||
|
|
977486bb7d | ||
|
|
6ccc0d2e0a | ||
|
|
084a9b7db4 | ||
|
|
826844cf46 | ||
|
|
39cff26f2d | ||
|
|
1619801526 | ||
|
|
5a1263ee3a | ||
|
|
bc91baa4fa | ||
|
|
a4882a7bfa | ||
|
|
c254b5b8df | ||
|
|
66718a3fd8 | ||
|
|
99fc2aecd9 | ||
|
|
a41d03aed5 | ||
|
|
6d14b79c43 | ||
|
|
faeac8f290 | ||
|
|
d172faacf3 | ||
|
|
35d6beb3cb | ||
|
|
7ff787ec28 | ||
|
|
f6fc850a20 | ||
|
|
04b8d0ef5d | ||
|
|
891f6368f1 | ||
|
|
e6011b6201 | ||
|
|
8b86114998 | ||
|
|
c20b115faf | ||
|
|
2c8ccd3e7c | ||
|
|
b1f771c320 | ||
|
|
425645a610 | ||
|
|
24e6ffc5ef | ||
|
|
1dd9ce6bbc | ||
|
|
e528fa6409 | ||
|
|
6440dd09d1 | ||
|
|
869493bd97 | ||
|
|
1cb9042736 | ||
|
|
c9410a1e2e | ||
|
|
683ff03a0f | ||
|
|
c9ba7eeaf9 | ||
|
|
c4f0ce7d4b | ||
|
|
dc83486032 | ||
|
|
2a64091c87 | ||
|
|
f65f749208 | ||
|
|
0b6ed00062 | ||
|
|
e87c976e19 | ||
|
|
f31ece3a59 | ||
|
|
cfd08602ab | ||
|
|
4b7152b272 | ||
|
|
5117a66c81 | ||
|
|
83794d4bbc | ||
|
|
76f74778b4 | ||
|
|
ded3425e31 | ||
|
|
738b379fe5 | ||
|
|
cf8b28441f | ||
|
|
0eb5897185 | ||
|
|
25cd1601a6 | ||
|
|
42e4d110ad | ||
|
|
2538f34892 | ||
|
|
3ce11f4cc7 | ||
|
|
f2cd34a79e | ||
|
|
5f923ad485 | ||
|
|
8f70f085d3 | ||
|
|
d6c09ed31a | ||
|
|
7d3ee1331d | ||
|
|
cd5b90a1e2 | ||
|
|
ac861f5fa0 | ||
|
|
c1d8f817bb | ||
|
|
da28a7332b | ||
|
|
bfd4e6a8ed | ||
|
|
b4e0e4b6b2 | ||
|
|
e37caf5c8f | ||
|
|
e95cf24af7 | ||
|
|
524a72caa0 | ||
|
|
1919c562cc | ||
|
|
62b54d6e75 | ||
|
|
efa9160c04 | ||
|
|
bc6955055a | ||
|
|
dc997d5ff2 | ||
|
|
a32f495038 | ||
|
|
210466883c | ||
|
|
728385b70a | ||
|
|
792aa0b922 | ||
|
|
6847b74095 | ||
|
|
54e86b421c | ||
|
|
370666cb0e | ||
|
|
e17f7df930 | ||
|
|
0e91df7acc | ||
|
|
ad26230da5 | ||
|
|
a103f34230 | ||
|
|
806bd3b248 | ||
|
|
c69c39fa44 | ||
|
|
b6badb44af | ||
|
|
b2195ce13f | ||
|
|
f3cb9b8510 | ||
|
|
8edfecb9dc | ||
|
|
c123d103bb | ||
|
|
b92d9da387 | ||
|
|
8841698aab | ||
|
|
6f140f16cd | ||
|
|
8bfd31997b | ||
|
|
4a1459d708 | ||
|
|
361bdeb2b2 | ||
|
|
9ce5af7cd0 | ||
|
|
84fa9e6e7c | ||
|
|
36916ed5c8 | ||
|
|
fb366d3e0b | ||
|
|
6e7670f667 | ||
|
|
e82be8b6a5 | ||
|
|
07320af4ee | ||
|
|
73eb270237 | ||
|
|
222684cfc8 | ||
|
|
3974d2123e | ||
|
|
b837a63b34 | ||
|
|
461316713a | ||
|
|
185af3210b | ||
|
|
e4620b5469 | ||
|
|
5c4acd17a0 | ||
|
|
fc171e5b89 | ||
|
|
662faf2512 | ||
|
|
2fb8af9a4f | ||
|
|
017d03713b | ||
|
|
5f5180d937 | ||
|
|
6b3e6cd6f5 | ||
|
|
f95f3c7b1b | ||
|
|
316b62083c | ||
|
|
530b63f299 | ||
|
|
2f228de163 | ||
|
|
e5e64b25fe | ||
|
|
2d5dde177c | ||
|
|
ce0ad4ba61 | ||
|
|
ebd7c5d6a4 | ||
|
|
341da273c9 | ||
|
|
73d2a43a95 | ||
|
|
eee18889d6 | ||
|
|
590d7fb717 | ||
|
|
dd28ef7ab6 | ||
|
|
36fb033adc | ||
|
|
4275f25f4a | ||
|
|
30b5633498 | ||
|
|
00545fdc50 | ||
|
|
d80e511b08 | ||
|
|
7313355a83 | ||
|
|
66466dc865 | ||
|
|
8cd8df4b02 | ||
|
|
d6bcb8c43d | ||
|
|
2aa2064a67 | ||
|
|
f403d12073 | ||
|
|
b66c2f67da | ||
|
|
d084a4cd81 | ||
|
|
5d2bf56493 | ||
|
|
cd88f5c833 | ||
|
|
ab41e25071 | ||
|
|
eb775da7d4 | ||
|
|
7bc2695da4 | ||
|
|
75fff426bc | ||
|
|
4172df4d78 | ||
|
|
01856b61ef | ||
|
|
2e32559132 | ||
|
|
9adb49df78 | ||
|
|
18e21b0a8e | ||
|
|
e1d7d0e141 | ||
|
|
cfa40e640b | ||
|
|
cb0a45bc17 | ||
|
|
c7b6e5bf24 | ||
|
|
a9ca1b71eb | ||
|
|
97f07bc72d | ||
|
|
8753875d93 | ||
|
|
3692aa80a4 | ||
|
|
b8b09ded5d | ||
|
|
5b8d8b9e55 | ||
|
|
e3fbf4fc77 | ||
|
|
8d680992b7 | ||
|
|
01247f73f4 | ||
|
|
6a7a3dcb90 | ||
|
|
2fbfbb4eb6 | ||
|
|
f88b5d2733 | ||
|
|
363358aaa1 | ||
|
|
7444eeba2a | ||
|
|
e9d686a4c1 | ||
|
|
939ba1bb47 | ||
|
|
d5de868eb9 | ||
|
|
6e3bb6c3a0 | ||
|
|
d347ec420c | ||
|
|
a011b677ea | ||
|
|
8831436809 | ||
|
|
1ededc1f64 | ||
|
|
183c94fd0a | ||
|
|
a0a5568d93 |
@@ -0,0 +1,19 @@
|
||||
namespace EnvelopeGenerator.Application.Configurations
|
||||
{
|
||||
public class CodeGeneratorParams
|
||||
{
|
||||
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.
|
||||
public int DefaultTotpSecretKeyLength { get; init; } = 20;
|
||||
|
||||
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}";
|
||||
|
||||
public int TotpQRPixelsPerModule { get; init; } = 20;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace EnvelopeGenerator.Application.Configurations
|
||||
{
|
||||
public class EnvelopeReceiverCacheParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the cache key format for SMS codes.
|
||||
/// The placeholder {0} represents the envelopeReceiverId.
|
||||
/// </summary>
|
||||
public string CodeCacheKeyFormat { get; init; } = "sms-code-{0}";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cache expiration key format for SMS codes.
|
||||
/// The placeholder {0} represents the envelopeReceiverId.
|
||||
/// </summary>
|
||||
public string CodeExpirationCacheKeyFormat { get; init; } = "sms-code-expiration-{0}";
|
||||
|
||||
public TimeSpan CodeCacheValidityPeriod { get; init; } = new(0, 5, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using DigitalData.Core.Abstractions.Client;
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Configurations.GtxMessaging
|
||||
{
|
||||
/// <summary>
|
||||
/// https://www.gtx-messaging.com/en/api-docs/sms-rest-api/
|
||||
/// </summary>
|
||||
public class SmsParams : IHttpClientOptions
|
||||
{
|
||||
public required string Uri { get; init; }
|
||||
|
||||
public string? Path { get; init; }
|
||||
|
||||
public Dictionary<string, object>? Headers { get; init; }
|
||||
|
||||
public Dictionary<string, object?>? QueryParams { get; init; }
|
||||
|
||||
public string RecipientQueryParamName { get; init; } = "to";
|
||||
|
||||
public string MessageQueryParamName { get; init; } = "text";
|
||||
|
||||
public int CodeLength { get; init; } = 5;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace EnvelopeGenerator.Application.Configurations
|
||||
{
|
||||
public class MailConfig
|
||||
{
|
||||
public required Dictionary<string, string> Placeholders { get; init; }
|
||||
}
|
||||
}
|
||||
13
EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs
Normal file
13
EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
public interface ICodeGenerator
|
||||
{
|
||||
string GenerateCode(int length);
|
||||
|
||||
public string GenerateTotpSecretKey(int? length = null);
|
||||
|
||||
public byte[] GenerateTotpQrCode(string userEmail, string secretKey, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null);
|
||||
|
||||
public byte[] GenerateTotpQrCode(string userEmail, int? length = null, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using EnvelopeGenerator.Domain.Entities;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
public interface IConfigService : IBasicCRUDService<ConfigDto, Config, int>
|
||||
public interface IConfigService : IReadService<ConfigDto, Config, int>
|
||||
{
|
||||
Task<DataResult<ConfigDto>> ReadFirstAsync();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
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(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType, Dictionary<string, object>? optionalPlaceholders = null);
|
||||
|
||||
Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary<string, object>? optionalPlaceholders = null);
|
||||
|
||||
Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto);
|
||||
|
||||
Task<DataResult<int>> SendTFAQrCodeAsync(EnvelopeReceiverDto envelopeReceiverDto);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
public interface IEnvelopeReceiverCache
|
||||
{
|
||||
Task<string?> GetSmsCodeAsync(string envelopeReceiverId);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously stores an SMS verification code in the cache and returns the expiration date of the code.
|
||||
/// </summary>
|
||||
/// <param name="envelopeReceiverId">The unique identifier for the recipient of the envelope to associate with the SMS code.</param>
|
||||
/// <param name="code">The SMS verification code to be stored.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains the expiration date and time of the stored SMS code.</returns>
|
||||
Task<DateTime> SetSmsCodeAsync(string envelopeReceiverId, string code);
|
||||
|
||||
Task<DateTime?> GetSmsCodeExpirationAsync(string envelopeReceiverId);
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,25 @@
|
||||
using DigitalData.Core.Abstractions.Application;
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||
using EnvelopeGenerator.Application.DTOs.Messaging;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDto, EnvelopeReceiver, object>
|
||||
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<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true);
|
||||
|
||||
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true);
|
||||
Task<DataResult<IEnumerable<string?>>> ReadAccessCodeByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true);
|
||||
|
||||
Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true);
|
||||
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true);
|
||||
|
||||
Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true);
|
||||
Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true);
|
||||
|
||||
Task<DataResult<EnvelopeReceiverSecretDto>> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true);
|
||||
|
||||
Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true);
|
||||
|
||||
Task<DataResult<string>> ReadAccessCodeByIdAsync(int envelopeId, int receiverId);
|
||||
|
||||
@@ -25,5 +30,9 @@ namespace EnvelopeGenerator.Application.Contracts
|
||||
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);
|
||||
|
||||
Task<DataResult<SmsResponse>> SendSmsAsync(string envelopeReceiverId, string message);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
@@ -11,5 +10,7 @@ namespace EnvelopeGenerator.Application.Contracts
|
||||
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);
|
||||
}
|
||||
}
|
||||
13
EnvelopeGenerator.Application/Contracts/IMessagingService.cs
Normal file
13
EnvelopeGenerator.Application/Contracts/IMessagingService.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using EnvelopeGenerator.Application.DTOs.Messaging;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
public interface IMessagingService
|
||||
{
|
||||
string ServiceProvider { get; }
|
||||
|
||||
Task<SmsResponse> SendSmsAsync(string recipient, string message);
|
||||
|
||||
Task<SmsResponse> SendSmsCodeAsync(string recipient, string envelopeReceiverId);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using DigitalData.Core.Abstractions.Application;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using DigitalData.Core.Abstractions.Application;
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
@@ -7,8 +8,10 @@ namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
public interface IReceiverService : ICRUDService<ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
|
||||
{
|
||||
public Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null);
|
||||
Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null);
|
||||
|
||||
public Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null);
|
||||
Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null);
|
||||
|
||||
Task<Result> UpdateAsync<TUpdateDto>(TUpdateDto updateDto) where TUpdateDto : IUnique<int>;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using DigitalData.Core.Abstractions.Application;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Contracts
|
||||
{
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
using DigitalData.UserManager.Application.MappingProfiles;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.MappingProfiles;
|
||||
using EnvelopeGenerator.Application.Services;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using EnvelopeGenerator.Infrastructure.Repositories;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EnvelopeGenerator.Application
|
||||
{
|
||||
public static class DIExtensions
|
||||
{
|
||||
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services)
|
||||
{
|
||||
//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<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>();
|
||||
|
||||
//Auto mapping profiles
|
||||
services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly);
|
||||
services.AddAutoMapper(typeof(UserMappingProfile).Assembly);
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
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);
|
||||
string ExportPath) : IUnique<int>
|
||||
{
|
||||
[NotMapped]
|
||||
[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.");
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record DocumentReceiverElementDto(
|
||||
int Id,
|
||||
@@ -18,5 +20,5 @@
|
||||
DateTime? ChangedWhen,
|
||||
double Top,
|
||||
double Left
|
||||
);
|
||||
): IUnique<int>;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record DocumentStatusDto(
|
||||
int Id,
|
||||
@@ -8,5 +10,5 @@
|
||||
DateTime? StatusChangedWhen,
|
||||
string Value,
|
||||
DateTime AddedWhen,
|
||||
DateTime? ChangedWhen);
|
||||
DateTime? ChangedWhen) : IUnique<int>;
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record EmailTemplateDto(
|
||||
int Id,
|
||||
string Name,
|
||||
string Body,
|
||||
string Subject);
|
||||
string Subject) : IUnique<int>;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record EnvelopeCertificateDto(
|
||||
int Id,
|
||||
@@ -8,5 +10,5 @@
|
||||
int CreatorId,
|
||||
string CreatorName,
|
||||
string CreatorEmail,
|
||||
int EnvelopeStatus);
|
||||
int EnvelopeStatus) : IUnique<int>;
|
||||
}
|
||||
@@ -1,10 +1,13 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record EnvelopeDocumentDto
|
||||
(
|
||||
int Id,
|
||||
int EnvelopeId,
|
||||
DateTime AddedWhen,
|
||||
IEnumerable<DocumentReceiverElementDto>? Elements
|
||||
);
|
||||
byte[]? ByteData = null,
|
||||
IEnumerable<DocumentReceiverElementDto>? Elements = null
|
||||
) : IUnique<int>;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
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()
|
||||
public record EnvelopeDto() : IUnique<int>
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.UserManager.Application.DTOs.User;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
@@ -10,10 +11,11 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
||||
int EnvelopeId,
|
||||
string UserReference,
|
||||
int Status,
|
||||
string? StatusName,
|
||||
DateTime AddedWhen,
|
||||
DateTime? ActionDate,
|
||||
UserCreateDto? Sender,
|
||||
ReceiverReadDto? Receiver,
|
||||
ReferenceType ReferenceType,
|
||||
string? Comment = null) : BaseDTO<long>(Id);
|
||||
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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; }
|
||||
|
||||
public bool HasPhoneNumber { get; init; }
|
||||
|
||||
public bool TFAEnabled { 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,9 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||
{
|
||||
public record EnvelopeReceiverSecretDto() : EnvelopeReceiverDto()
|
||||
{
|
||||
public string? AccessCode { get; init; }
|
||||
|
||||
public string? PhoneNumber { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record EnvelopeReceiverDto()
|
||||
{
|
||||
public int EnvelopeId { get; set; }
|
||||
|
||||
public int ReceiverId { get; set; }
|
||||
|
||||
public int Sequence { get; set; }
|
||||
|
||||
[TemplatePlaceholder("[NAME_RECEIVER]")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
public string? JobTitle { get; set; }
|
||||
|
||||
public string? CompanyName { get; set; }
|
||||
|
||||
public string? PrivateMessage { get; set; }
|
||||
|
||||
public DateTime AddedWhen { get; set; }
|
||||
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
|
||||
public EnvelopeDto? Envelope { get; set; }
|
||||
|
||||
public ReceiverReadDto? Receiver { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record EnvelopeTypeDto(
|
||||
int Id,
|
||||
@@ -15,5 +17,5 @@
|
||||
bool? SendReminderEmails,
|
||||
int? FirstReminderDays,
|
||||
int? ReminderIntervalDays,
|
||||
int? ContractType);
|
||||
int? ContractType) : IUnique<int>;
|
||||
}
|
||||
19
EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs
Normal file
19
EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs.Messaging
|
||||
{
|
||||
public record SmsResponse
|
||||
{
|
||||
public required bool Ok { get; init; }
|
||||
|
||||
public DateTime? Expiration { get; set; }
|
||||
|
||||
public DateTime? AllowedAt { get; set; }
|
||||
|
||||
public TimeSpan AllowedAfter => Allowed ? TimeSpan.Zero : AllowedAt!.Value - DateTime.Now;
|
||||
|
||||
public bool Allowed => AllowedAt is null || DateTime.Now >= AllowedAt;
|
||||
|
||||
public bool Error => !Ok && Allowed;
|
||||
|
||||
public dynamic? Errors { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Text;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||
{
|
||||
public record ReceiverCreateDto([EmailAddress] string EmailAddress)
|
||||
public record ReceiverCreateDto([EmailAddress] string EmailAddress, string? TotpSecretkey = null, DateTime? TotpExpiration = null)
|
||||
{
|
||||
public string Signature => sha256HexOfMail.Value;
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||
{
|
||||
@@ -7,5 +11,16 @@ namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||
string EmailAddress,
|
||||
string Signature,
|
||||
DateTime AddedWhen
|
||||
) : BaseDTO<int>(Id);
|
||||
) : BaseDTO<int>(Id), IUnique<int>
|
||||
{
|
||||
[JsonIgnore]
|
||||
public IEnumerable<EnvelopeReceiverBasicDto>? EnvelopeReceivers { get; init; }
|
||||
|
||||
public string? LastUsedName => EnvelopeReceivers?.LastOrDefault()?.Name;
|
||||
|
||||
public string? TotpSecretkey { get; set; } = null;
|
||||
|
||||
[TemplatePlaceholder("[TFA_QR_EXPIRATION]")]
|
||||
public DateTime? TotpExpiration { get; set; } = null;
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||
{
|
||||
public record ReceiverUpdateDto();
|
||||
}
|
||||
public record ReceiverUpdateDto(int Id, string? TotpSecretkey = null, DateTime? TotpExpiration = null) : IUnique<int>;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
using DigitalData.Core.Abstractions;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
public record UserReceiverDto(
|
||||
int Id,
|
||||
@@ -7,5 +9,5 @@
|
||||
string Name,
|
||||
string CompanyName,
|
||||
string JobTitle,
|
||||
DateTime AddedWhen);
|
||||
DateTime AddedWhen) : IUnique<int>;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace EnvelopeGenerator.Application
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,20 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.1.1" />
|
||||
<PackageReference Include="DigitalData.Core.Application" Version="1.0.0" />
|
||||
<PackageReference Include="DigitalData.Core.DTO" Version="1.0.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="1.0.0" />
|
||||
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.Application" Version="2.0.0" />
|
||||
<PackageReference Include="DigitalData.Core.Client" Version="2.0.3" />
|
||||
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
|
||||
<PackageReference Include="UserManager.Application" Version="1.0.0" />
|
||||
<PackageReference Include="UserManager.Infrastructure" Version="1.0.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="QRCoder-ImageSharp" Version="0.10.0" />
|
||||
<PackageReference Include="UserManager.Application" Version="2.0.0" />
|
||||
<PackageReference Include="UserManager.Infrastructure" Version="2.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
82
EnvelopeGenerator.Application/Extensions/CacheExtensions.cs
Normal file
82
EnvelopeGenerator.Application/Extensions/CacheExtensions.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Extensions
|
||||
{
|
||||
public static class CacheExtensions
|
||||
{
|
||||
public static Task SetLongAsync(this IDistributedCache cache, string key, long value, DistributedCacheEntryOptions? options = null)
|
||||
=> options is null
|
||||
? cache.SetAsync(key, BitConverter.GetBytes(value))
|
||||
: cache.SetAsync(key, BitConverter.GetBytes(value), options: options);
|
||||
|
||||
public static async Task<long?> GetLongAsync(this IDistributedCache cache, string key)
|
||||
{
|
||||
var value = await cache.GetAsync(key);
|
||||
return value is null ? null : BitConverter.ToInt64(value, 0);
|
||||
}
|
||||
|
||||
public static Task SetDateTimeAsync(this IDistributedCache cache, string key, DateTime value, DistributedCacheEntryOptions? options = null)
|
||||
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options);
|
||||
|
||||
public static async Task<DateTime?> GetDateTimeAsync(this IDistributedCache cache, string key)
|
||||
{
|
||||
var value = await cache.GetAsync(key);
|
||||
return value is null ? null : new(BitConverter.ToInt64(value, 0));
|
||||
}
|
||||
|
||||
public static Task SetTimeSpanAsync(this IDistributedCache cache, string key, TimeSpan value, DistributedCacheEntryOptions? options = null)
|
||||
=> cache.SetLongAsync(key: key, value: value.Ticks, options: options);
|
||||
|
||||
public static async Task<TimeSpan?> GetTimeSpanAsync(this IDistributedCache cache, string key)
|
||||
{
|
||||
var value = await cache.GetAsync(key);
|
||||
return value is null ? null : new(BitConverter.ToInt64(value, 0));
|
||||
}
|
||||
|
||||
public static string GetOrSet(this IDistributedCache cache, string key, Func<string> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken token = default)
|
||||
{
|
||||
var value = cache.GetString(key);
|
||||
if (value is null)
|
||||
{
|
||||
// create new and save
|
||||
value = factory();
|
||||
|
||||
void Cache()
|
||||
{
|
||||
if (options is null)
|
||||
cache.SetString(key: key, value: value);
|
||||
else
|
||||
cache.SetString(key: key, value: value, options: options);
|
||||
}
|
||||
|
||||
if (cacheInBackground)
|
||||
_ = Task.Run(() => Cache(), token);
|
||||
else
|
||||
Cache();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static async Task<string> GetOrSetAsync(this IDistributedCache cache, string key, Func<Task<string>> factory, DistributedCacheEntryOptions? options = null, bool cacheInBackground = false, CancellationToken token = default)
|
||||
{
|
||||
var value = await cache.GetStringAsync(key, token: token);
|
||||
if(value is null)
|
||||
{
|
||||
// create new and save
|
||||
value = await factory();
|
||||
|
||||
Task CacheAsync() => options is null
|
||||
? cache.SetStringAsync(key: key, value: value, token: token)
|
||||
: cache.SetStringAsync(key: key, value: value, options: options, token: token);
|
||||
|
||||
if (cacheInBackground)
|
||||
_ = Task.Run(async () => await CacheAsync(), token);
|
||||
else
|
||||
await CacheAsync();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
EnvelopeGenerator.Application/Extensions/DIExtensions.cs
Normal file
78
EnvelopeGenerator.Application/Extensions/DIExtensions.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
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;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using DigitalData.Core.Client;
|
||||
using EnvelopeGenerator.Application.Configurations.GtxMessaging;
|
||||
using QRCoder;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Extensions
|
||||
{
|
||||
public static class DIExtensions
|
||||
{
|
||||
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfigurationSection dispatcherConfigSection, IConfigurationSection mailConfigSection, IConfigurationSection smsConfigSection, IConfigurationSection codeGeneratorConfigSection, IConfigurationSection envelopeReceiverCacheParamsSection)
|
||||
{
|
||||
//Inject CRUD Service and repositoriesad
|
||||
services.TryAddScoped<IConfigRepository, ConfigRepository>();
|
||||
services.TryAddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
||||
services.TryAddScoped<IEnvelopeDocumentRepository, EnvelopeDocumentRepository>();
|
||||
services.TryAddScoped<IConfigRepository, ConfigRepository>();
|
||||
services.TryAddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
||||
services.TryAddScoped<IDocumentStatusRepository, DocumentStatusRepository>();
|
||||
services.TryAddScoped<IEmailTemplateRepository, EmailTemplateRepository>();
|
||||
services.TryAddScoped<IEnvelopeRepository, EnvelopeRepository>();
|
||||
services.TryAddScoped<IEnvelopeCertificateRepository, EnvelopeCertificateRepository>();
|
||||
services.TryAddScoped<IEnvelopeDocumentRepository, EnvelopeDocumentRepository>();
|
||||
services.TryAddScoped<IEnvelopeHistoryRepository, EnvelopeHistoryRepository>();
|
||||
services.TryAddScoped<IEnvelopeReceiverRepository, EnvelopeReceiverRepository>();
|
||||
services.TryAddScoped<IEnvelopeTypeRepository, EnvelopeTypeRepository>();
|
||||
services.TryAddScoped<IReceiverRepository, ReceiverRepository>();
|
||||
services.TryAddScoped<IUserReceiverRepository, UserReceiverRepository>();
|
||||
services.TryAddScoped<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyRepository>();
|
||||
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<IEnvelopeCertificateService, EnvelopeCertificateService>();
|
||||
services.TryAddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
|
||||
services.TryAddScoped<IEnvelopeReceiverService, EnvelopeReceiverService>();
|
||||
services.TryAddScoped<IEnvelopeTypeService, EnvelopeTypeService>();
|
||||
services.TryAddScoped<IReceiverService, ReceiverService>();
|
||||
services.TryAddScoped<IUserReceiverService, UserReceiverService>();
|
||||
services.TryAddScoped<IEnvelopeReceiverReadOnlyService, EnvelopeReceiverReadOnlyService>();
|
||||
|
||||
//Auto mapping profiles
|
||||
services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly);
|
||||
services.AddAutoMapper(typeof(UserMappingProfile).Assembly);
|
||||
|
||||
services.Configure<DispatcherConfig>(dispatcherConfigSection);
|
||||
services.Configure<MailConfig>(mailConfigSection);
|
||||
services.Configure<CodeGeneratorParams>(codeGeneratorConfigSection);
|
||||
services.Configure<EnvelopeReceiverCacheParams>(envelopeReceiverCacheParamsSection);
|
||||
|
||||
services.AddHttpClientService<SmsParams>(smsConfigSection);
|
||||
services.TryAddSingleton<IMessagingService, GtxMessagingService>();
|
||||
services.TryAddSingleton<ICodeGenerator, CodeGenerator>();
|
||||
services.TryAddSingleton<IEnvelopeReceiverCache, EnvelopeReceiverCache>();
|
||||
services.TryAddSingleton<QRCodeGenerator>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration config) => services.AddEnvelopeGenerator(
|
||||
dispatcherConfigSection: config.GetSection("DispatcherConfig"),
|
||||
mailConfigSection: config.GetSection("MailConfig"),
|
||||
smsConfigSection: config.GetSection("SmsConfig"),
|
||||
codeGeneratorConfigSection: config.GetSection("CodeGeneratorParams"),
|
||||
envelopeReceiverCacheParamsSection: config.GetSection("EnvelopeReceiverCacheParams"));
|
||||
}
|
||||
}
|
||||
16
EnvelopeGenerator.Application/Extensions/DTOExtensions.cs
Normal file
16
EnvelopeGenerator.Application/Extensions/DTOExtensions.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Extensions
|
||||
{
|
||||
public static class DTOExtensions
|
||||
{
|
||||
public static bool IsTotpSecretExpired(this ReceiverReadDto dto, int minutesBeforeExpiration = 30)
|
||||
=> dto.TotpExpiration < DateTime.Now.AddMinutes(minutesBeforeExpiration * -1);
|
||||
|
||||
public static bool IsTotpSecretInvalid(this ReceiverReadDto dto, int minutesBeforeExpiration = 30)
|
||||
=> dto.IsTotpSecretExpired(minutesBeforeExpiration) || dto.TotpSecretkey is null;
|
||||
|
||||
public static bool IsTotpSecretValid(this ReceiverReadDto dto, int minutesBeforeExpiration = 30)
|
||||
=> !dto.IsTotpSecretInvalid(minutesBeforeExpiration);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using EnvelopeGenerator.Domain.HttpResponse;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Extensions
|
||||
{
|
||||
public static class MappingExtensions
|
||||
{
|
||||
public static bool Ok(this GtxMessagingResponse gtxMessagingResponse)
|
||||
=> gtxMessagingResponse.TryGetValue("message-status", out var status)
|
||||
&& status?.ToString()?.ToLower() == "ok";
|
||||
|
||||
public static string ToBase64String(this byte[] bytes)
|
||||
=> Convert.ToBase64String(bytes);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
public static readonly string PossibleSecurityBreach = nameof(PossibleSecurityBreach);
|
||||
public static readonly string WrongEnvelopeReceiverId = nameof(WrongEnvelopeReceiverId);
|
||||
public static readonly string EnvelopeOrReceiverNonexists = nameof(EnvelopeOrReceiverNonexists);
|
||||
public static readonly string PhoneNumberNonexists = nameof(PhoneNumberNonexists);
|
||||
public static readonly string Default = nameof(Default);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
|
||||
using EnvelopeGenerator.Application.DTOs.Messaging;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using EnvelopeGenerator.Application.Extensions;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Domain.HttpResponse;
|
||||
|
||||
namespace EnvelopeGenerator.Application.MappingProfiles
|
||||
{
|
||||
@@ -21,11 +26,13 @@ namespace EnvelopeGenerator.Application.MappingProfiles
|
||||
CreateMap<EnvelopeHistory, EnvelopeHistoryDto>();
|
||||
CreateMap<EnvelopeHistory, EnvelopeHistoryCreateDto>();
|
||||
CreateMap<EnvelopeReceiver, EnvelopeReceiverDto>();
|
||||
CreateMap<EnvelopeReceiver, EnvelopeReceiverSecretDto>();
|
||||
CreateMap<EnvelopeType, EnvelopeTypeDto>();
|
||||
CreateMap<Receiver, ReceiverReadDto>();
|
||||
CreateMap<Receiver, ReceiverCreateDto>();
|
||||
CreateMap<Receiver, ReceiverUpdateDto>();
|
||||
CreateMap<UserReceiver, UserReceiverDto>();
|
||||
CreateMap<EnvelopeReceiverReadOnly, EnvelopeReceiverReadOnlyDto>();
|
||||
|
||||
// DTO to Entity mappings
|
||||
CreateMap<ConfigDto, Config>();
|
||||
@@ -39,10 +46,20 @@ namespace EnvelopeGenerator.Application.MappingProfiles
|
||||
CreateMap<EnvelopeHistoryCreateDto, EnvelopeHistory>();
|
||||
CreateMap<EnvelopeReceiverDto, EnvelopeReceiver>();
|
||||
CreateMap<EnvelopeTypeDto, EnvelopeType>();
|
||||
CreateMap<ReceiverReadDto, Receiver>();
|
||||
CreateMap<ReceiverReadDto, Receiver>().ForMember(rcv => rcv.EnvelopeReceivers, rcvReadDto => rcvReadDto.Ignore());
|
||||
CreateMap<ReceiverCreateDto, Receiver>();
|
||||
CreateMap<ReceiverUpdateDto, Receiver>();
|
||||
CreateMap<UserReceiverDto, UserReceiver>();
|
||||
CreateMap<EnvelopeReceiverBase, EnvelopeReceiverBasicDto>();
|
||||
CreateMap<EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnly>();
|
||||
CreateMap<EnvelopeReceiverReadOnlyUpdateDto, EnvelopeReceiverReadOnly>();
|
||||
|
||||
// Messaging mappings
|
||||
// for GTX messaging
|
||||
CreateMap<GtxMessagingResponse, SmsResponse>()
|
||||
.ConstructUsing(gtxRes => gtxRes.Ok()
|
||||
? new SmsResponse() { Ok = true }
|
||||
: new SmsResponse() { Ok = false, Errors = gtxRes });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,27 +156,66 @@
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Hallo</value>
|
||||
</data>
|
||||
<data name="LocakedOpen" xml:space="preserve">
|
||||
<value>Öffnen</value>
|
||||
<data name="HomePageDescription" xml:space="preserve">
|
||||
<value>Das digitale Unterschriftenportal ist eine Plattform, die entwickelt wurde, um Ihre Dokumente sicher zu unterschreiben und zu verwalten. Mit seiner benutzerfreundlichen Oberfläche können Sie Ihre Dokumente schnell hochladen, die Unterschriftsprozesse verfolgen und Ihre digitalen Unterschriftenanwendungen einfach durchführen. Dieses Portal beschleunigt Ihren Arbeitsablauf mit rechtlich gültigen Unterschriften und erhöht gleichzeitig die Sicherheit Ihrer Dokumente.</value>
|
||||
</data>
|
||||
<data name="LocationWarning" xml:space="preserve">
|
||||
<value>Bitte überprüfen Sie die Standortinformationen. Wenn sie falsch sind, korrigieren Sie diese bitte.</value>
|
||||
</data>
|
||||
<data name="LockedAccessCode" xml:space="preserve">
|
||||
<value>Zugriffscode</value>
|
||||
</data>
|
||||
<data name="LockedBody" xml:space="preserve">
|
||||
<data name="LockedBodyAccess" xml:space="preserve">
|
||||
<value>Wir haben Ihnen gerade den Zugriffscode an die hinterlegte Email Adresse gesendet. Dies kann evtl. einige Minuten dauern.</value>
|
||||
</data>
|
||||
<data name="LockedFooterBody" xml:space="preserve">
|
||||
<data name="LockedBodyAuthenticator" xml:space="preserve">
|
||||
<value>Ihr QR-Code ist bis {0} gültig.</value>
|
||||
</data>
|
||||
<data name="LockedBodyAuthenticatorNew" xml:space="preserve">
|
||||
<value>Wir haben den QR-Code an Ihre E-Mail-Adresse gesendet. Ihr QR-Code ist bis {0} gültig. Sie können ihn für alle Umschläge verwenden, die Sie an diese E-Mail-Adresse erhalten.</value>
|
||||
</data>
|
||||
<data name="LockedBodySms" xml:space="preserve">
|
||||
<value>Wir haben soeben den Zugangscode als SMS an die von Ihnen angegebene Telefonnummer gesendet.</value>
|
||||
</data>
|
||||
<data name="LockedCodeLabelAccess" xml:space="preserve">
|
||||
<value>Zugriffscode</value>
|
||||
</data>
|
||||
<data name="LockedCodeLabelAuthenticator" xml:space="preserve">
|
||||
<value>TOTP</value>
|
||||
</data>
|
||||
<data name="LockedCodeLabelSms" xml:space="preserve">
|
||||
<value>SMS-Code</value>
|
||||
</data>
|
||||
<data name="LockedFooterBodyAccess" xml:space="preserve">
|
||||
<value>Bitte überprüfen Sie Ihr Email Postfach inklusive Spam-Ordner. Sie können auch den Absender bitten, Ihnen den Code auf anderem Wege zukommen zu lassen.</value>
|
||||
</data>
|
||||
<data name="LockedFooterTitle" xml:space="preserve">
|
||||
<data name="LockedFooterBodyAuthenticator" xml:space="preserve">
|
||||
<value>Der neue QR-Code wird nur einmal für einen bestimmten Zeitraum gesendet und nach dem Scannen in Ihrer Authenticator-App gespeichert. Er kann für alle Umschläge verwendet werden, die an dieselbe E-Mail-Adresse gesendet werden, bis er abläuft. Wenn Sie die QR-Code-Mail nicht erhalten oder sie sowohl aus der Mail als auch aus authenticator löschen, kontaktieren Sie bitte den Absender.</value>
|
||||
</data>
|
||||
<data name="LockedFooterBodySms" xml:space="preserve">
|
||||
<value>Sie können den Absender bitten, Ihre Rufnummer zu überprüfen. Die Telefonnummer muss mit der Ortsvorwahl eingegeben werden. Andernfalls können Sie beantragen, den Zwei-Faktor-Schutz zu entfernen.</value>
|
||||
</data>
|
||||
<data name="LockedFooterTitleAccess" xml:space="preserve">
|
||||
<value>Sie haben keinen Zugriffscode erhalten?</value>
|
||||
</data>
|
||||
<data name="LockedTitle" xml:space="preserve">
|
||||
<data name="LockedFooterTitleAuthenticator" xml:space="preserve">
|
||||
<value>Sie haben keinen QR-Code erhalten?</value>
|
||||
</data>
|
||||
<data name="LockedFooterTitleSms" xml:space="preserve">
|
||||
<value>Sie haben keine SMS erhalten?</value>
|
||||
</data>
|
||||
<data name="LockedTitleAccess" xml:space="preserve">
|
||||
<value>Dokument erfordert einen Zugriffscode</value>
|
||||
</data>
|
||||
<data name="LockedTitleAuthenticator" xml:space="preserve">
|
||||
<value>2-Faktor-Authentifizierung</value>
|
||||
</data>
|
||||
<data name="LockedTitleSms" xml:space="preserve">
|
||||
<value>2-Faktor-Authentifizierung</value>
|
||||
</data>
|
||||
<data name="Privacy" xml:space="preserve">
|
||||
<value>Datenschutz</value>
|
||||
</data>
|
||||
<data name="ReadOnlyMessage" xml:space="preserve">
|
||||
<value>Weitergeleitet von {0}. Gültig bis {1}.</value>
|
||||
</data>
|
||||
<data name="Reject" xml:space="preserve">
|
||||
<value>Ablehnen</value>
|
||||
</data>
|
||||
@@ -210,6 +249,9 @@
|
||||
<data name="UnexpectedError" xml:space="preserve">
|
||||
<value>Ein unerwarteter Fehler ist aufgetreten.</value>
|
||||
</data>
|
||||
<data name="ViewDoc" xml:space="preserve">
|
||||
<value>Dokument ansehen</value>
|
||||
</data>
|
||||
<data name="WelcomeToTheESignPortal" xml:space="preserve">
|
||||
<value>Herzlich willkommen im eSign-Portal</value>
|
||||
</data>
|
||||
|
||||
@@ -156,27 +156,66 @@
|
||||
<data name="Hello" xml:space="preserve">
|
||||
<value>Hello</value>
|
||||
</data>
|
||||
<data name="LocakedOpen" xml:space="preserve">
|
||||
<value>Open</value>
|
||||
<data name="HomePageDescription" xml:space="preserve">
|
||||
<value>The Digital Signature Portal is a platform developed for securely signing and managing your documents. With its user-friendly interface, you can quickly upload your documents, track the signing processes, and easily carry out your digital signature applications. This portal accelerates your workflow with legally valid signatures while enhancing the security of your documents.</value>
|
||||
</data>
|
||||
<data name="LocationWarning" xml:space="preserve">
|
||||
<value>Please review the location information. If it is incorrect, kindly make the necessary corrections.</value>
|
||||
</data>
|
||||
<data name="LockedAccessCode" xml:space="preserve">
|
||||
<value>Access Code</value>
|
||||
</data>
|
||||
<data name="LockedBody" xml:space="preserve">
|
||||
<data name="LockedBodyAccess" xml:space="preserve">
|
||||
<value>We have just sent you the access code to the email address you provided. This may take a few minutes.</value>
|
||||
</data>
|
||||
<data name="LockedFooterBody" xml:space="preserve">
|
||||
<data name="LockedBodyAuthenticator" xml:space="preserve">
|
||||
<value>Your QR code is valid until {0}.</value>
|
||||
</data>
|
||||
<data name="LockedBodyAuthenticatorNew" xml:space="preserve">
|
||||
<value>We have sent the QR code to your e-mail address. Your QR code is valid until {0}. You can use it for all envelopes received at this email address.</value>
|
||||
</data>
|
||||
<data name="LockedBodySms" xml:space="preserve">
|
||||
<value>We have just sent the access code as an SMS to the phone number you provided.</value>
|
||||
</data>
|
||||
<data name="LockedCodeLabelAccess" xml:space="preserve">
|
||||
<value>Access Code</value>
|
||||
</data>
|
||||
<data name="LockedCodeLabelAuthenticator" xml:space="preserve">
|
||||
<value>TOTP</value>
|
||||
</data>
|
||||
<data name="LockedCodeLabelSms" xml:space="preserve">
|
||||
<value>SMS Code</value>
|
||||
</data>
|
||||
<data name="LockedFooterBodyAccess" xml:space="preserve">
|
||||
<value>Please check your email inbox including your spam folder. Furthermore, you can also ask the sender to send the code by other means.</value>
|
||||
</data>
|
||||
<data name="LockedFooterTitle" xml:space="preserve">
|
||||
<data name="LockedFooterBodyAuthenticator" xml:space="preserve">
|
||||
<value>The new QR code is sent only once for a given period and is saved in your authenticator app once scanned. It can be used for all envelopes received at the same email address until it expires. If you do not receive the QR code mail or delete it both from the mail and from authenticator, please contact the sender.</value>
|
||||
</data>
|
||||
<data name="LockedFooterBodySms" xml:space="preserve">
|
||||
<value>You can ask the sender to check your phone number. The phone number must be entered with the area code. Otherwise you can request to remove the two-factor protection.</value>
|
||||
</data>
|
||||
<data name="LockedFooterTitleAccess" xml:space="preserve">
|
||||
<value>You have not received an access code?</value>
|
||||
</data>
|
||||
<data name="LockedTitle" xml:space="preserve">
|
||||
<data name="LockedFooterTitleAuthenticator" xml:space="preserve">
|
||||
<value>You have not received a QR code?</value>
|
||||
</data>
|
||||
<data name="LockedFooterTitleSms" xml:space="preserve">
|
||||
<value>You have not received an SMS?</value>
|
||||
</data>
|
||||
<data name="LockedTitleAccess" xml:space="preserve">
|
||||
<value>Document requires an access code</value>
|
||||
</data>
|
||||
<data name="LockedTitleAuthenticator" xml:space="preserve">
|
||||
<value>2-Factor Authentication</value>
|
||||
</data>
|
||||
<data name="LockedTitleSms" xml:space="preserve">
|
||||
<value>2-Factor Authentication</value>
|
||||
</data>
|
||||
<data name="Privacy" xml:space="preserve">
|
||||
<value>Privacy</value>
|
||||
</data>
|
||||
<data name="ReadOnlyMessage" xml:space="preserve">
|
||||
<value>Forwarded by {0}. Valid until {1}.</value>
|
||||
</data>
|
||||
<data name="Reject" xml:space="preserve">
|
||||
<value>Reject</value>
|
||||
</data>
|
||||
@@ -210,6 +249,9 @@
|
||||
<data name="UnexpectedError" xml:space="preserve">
|
||||
<value>An unexpected error has occurred.</value>
|
||||
</data>
|
||||
<data name="ViewDoc" xml:space="preserve">
|
||||
<value>View document</value>
|
||||
</data>
|
||||
<data name="WelcomeToTheESignPortal" xml:space="preserve">
|
||||
<value>Welcome to the eSign portal</value>
|
||||
</data>
|
||||
|
||||
66
EnvelopeGenerator.Application/Services/CodeGenerator.cs
Normal file
66
EnvelopeGenerator.Application/Services/CodeGenerator.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using EnvelopeGenerator.Application.Configurations;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OtpNet;
|
||||
using QRCoder;
|
||||
using System.Text;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class CodeGenerator : ICodeGenerator
|
||||
{
|
||||
public static Lazy<CodeGenerator> LazyStatic => new(() => new CodeGenerator(Options.Create<CodeGeneratorParams>(new()), new QRCodeGenerator()));
|
||||
|
||||
public static CodeGenerator Static => LazyStatic.Value;
|
||||
|
||||
private readonly CodeGeneratorParams _params;
|
||||
|
||||
private readonly QRCodeGenerator _qrCodeGenerator;
|
||||
|
||||
public CodeGenerator(IOptions<CodeGeneratorParams> options, QRCodeGenerator qrCodeGenerator)
|
||||
{
|
||||
_params = options.Value;
|
||||
_qrCodeGenerator = qrCodeGenerator;
|
||||
}
|
||||
|
||||
public string GenerateCode(int length)
|
||||
{
|
||||
//TODO: Inject Random as a singleton to support multithreading to improve performance.
|
||||
Random random = new();
|
||||
|
||||
if (length <= 0)
|
||||
throw new ArgumentException("Password length must be greater than 0.");
|
||||
|
||||
var passwordBuilder = new StringBuilder(length);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
passwordBuilder.Append(_params.CharPool[random.Next(_params.CharPool.Length)]);
|
||||
|
||||
return passwordBuilder.ToString();
|
||||
}
|
||||
|
||||
public string GenerateTotpSecretKey(int? length = null)
|
||||
=> Base32Encoding.ToString(KeyGeneration.GenerateRandomKey(length ?? _params.DefaultTotpSecretKeyLength));
|
||||
|
||||
public byte[] GenerateTotpQrCode(string userEmail, string secretKey, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null)
|
||||
{
|
||||
var url = string.Format(totpUrlFormat ?? _params.TotpUrlFormat,
|
||||
Uri.EscapeDataString(userEmail),
|
||||
Uri.EscapeDataString(secretKey),
|
||||
Uri.EscapeDataString(issuer ?? _params.TotpIssuer));
|
||||
using var qrCodeData = _qrCodeGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
|
||||
using var qrCode = new BitmapByteQRCode(qrCodeData);
|
||||
return qrCode.GetGraphic(pixelsPerModule ?? _params.TotpQRPixelsPerModule);
|
||||
}
|
||||
|
||||
public byte[] GenerateTotpQrCode(string userEmail, int? length = null, string? issuer = null, string? totpUrlFormat = null, int? pixelsPerModule = null)
|
||||
{
|
||||
return GenerateTotpQrCode(
|
||||
userEmail: userEmail,
|
||||
secretKey: GenerateTotpSecretKey(length: length),
|
||||
issuer: issuer,
|
||||
totpUrlFormat: totpUrlFormat,
|
||||
pixelsPerModule: pixelsPerModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,13 @@ using DigitalData.Core.Application;
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class ConfigService : BasicCRUDService<IConfigRepository, ConfigDto, Config, int>, IConfigService
|
||||
public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, int>, IConfigService
|
||||
{
|
||||
private static readonly Guid DefaultConfigCacheId = Guid.NewGuid();
|
||||
|
||||
@@ -28,7 +26,7 @@ namespace EnvelopeGenerator.Application.Services
|
||||
var config = await _repository.ReadFirstAsync();
|
||||
return config is null
|
||||
? Result.Fail<ConfigDto>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, "There is no configuration in DB.")
|
||||
: Result.Success(_mapper.MapOrThrow<ConfigDto>(config));
|
||||
: Result.Success(_mapper.Map<ConfigDto>(config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
using DigitalData.Core.Application;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
using DigitalData.Core.Application;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Application;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
using DigitalData.Core.DTO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -26,7 +24,7 @@ namespace EnvelopeGenerator.Application.Services
|
||||
? Result.Fail<EmailTemplateDto>()
|
||||
.Message(Key.InnerServiceError)
|
||||
.Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"EmailTemplateType '{type}' is not found in DB. Please, define required e-mail template.")
|
||||
: Result.Success(_mapper.MapOrThrow<EmailTemplateDto>(temp));
|
||||
: Result.Success(_mapper.Map<EmailTemplateDto>(temp));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Application;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
@@ -14,7 +12,7 @@ namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class EnvelopeHistoryService : CRUDService<IEnvelopeHistoryRepository, EnvelopeHistoryCreateDto, EnvelopeHistoryDto, EnvelopeHistoryDto, EnvelopeHistory, long>, IEnvelopeHistoryService
|
||||
{
|
||||
public EnvelopeHistoryService(IEnvelopeHistoryRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
|
||||
public EnvelopeHistoryService(IEnvelopeHistoryRepository repository, IMapper mapper)
|
||||
: base(repository, mapper)
|
||||
{
|
||||
}
|
||||
@@ -53,7 +51,7 @@ namespace EnvelopeGenerator.Application.Services
|
||||
|
||||
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false)
|
||||
{
|
||||
var histDTOs = _mapper.MapOrThrow<IEnumerable<EnvelopeHistoryDto>>(
|
||||
var histDTOs = _mapper.Map<IEnumerable<EnvelopeHistoryDto>>(
|
||||
await _repository.ReadAsync(
|
||||
envelopeId: envelopeId,
|
||||
userReference: userReference,
|
||||
|
||||
@@ -3,58 +3,72 @@ using DigitalData.Core.DTO;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.DTOs.EmailOut;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Services;
|
||||
using DigitalData.UserManager.Application;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||
using EnvelopeGenerator.Common;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
using EnvelopeGenerator.Extensions;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
|
||||
using EnvelopeGenerator.Application.Configurations;
|
||||
using EnvelopeGenerator.Application.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class EnvelopeMailService : EmailOutService, IEnvelopeMailService
|
||||
public class EnvelopeMailService : EmailOutService, IEnvelopeMailService
|
||||
{
|
||||
private readonly IEmailTemplateService _tempService;
|
||||
private readonly IEnvelopeReceiverService _envRcvService;
|
||||
private readonly DispatcherConfig _dConfig;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly Dictionary<string, string> _placeholders;
|
||||
private readonly ICodeGenerator _codeGenerator;
|
||||
|
||||
public EnvelopeMailService(IEmailOutRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions<DispatcherConfig> dispatcherConfigOptions, IConfigService configService) : base(repository, mapper)
|
||||
public EnvelopeMailService(IEmailOutRepository repository, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions<DispatcherConfig> dispatcherConfigOptions, IConfigService configService, IOptions<MailConfig> mailConfig, ICodeGenerator codeGenerator) : base(repository, mapper)
|
||||
{
|
||||
_tempService = tempService;
|
||||
_envRcvService = envelopeReceiverService;
|
||||
_dConfig = dispatcherConfigOptions.Value;
|
||||
_configService = configService;
|
||||
_placeholders = mailConfig.Value.Placeholders;
|
||||
_codeGenerator = codeGenerator;
|
||||
}
|
||||
|
||||
//TODO: create ioptions and implement TemplatePlaceHolderAttribute instead of this method
|
||||
private async Task<Dictionary<string, string>> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null)
|
||||
{
|
||||
Dictionary<string, string> placeholders = new() {
|
||||
{ "[NAME_PORTAL]", "signFlow" },
|
||||
{ "[SIGNATURE_TYPE]" , "signieren"},
|
||||
{ "[REASON]", string.Empty } };
|
||||
|
||||
if (accessCode is not null)
|
||||
placeholders["[DOCUMENT_ACCESS_CODE]"] = accessCode;
|
||||
_placeholders["[DOCUMENT_ACCESS_CODE]"] = accessCode;
|
||||
|
||||
if(envelopeReceiverDto is not null && envelopeReceiverDto.Envelope is not null && envelopeReceiverDto.Receiver is not null)
|
||||
if(envelopeReceiverDto?.Envelope is not null && envelopeReceiverDto.Receiver is not null)
|
||||
{
|
||||
var erId = (envelopeReceiverDto.Envelope.Uuid, envelopeReceiverDto.Receiver.Signature).EncodeEnvelopeReceiverId();
|
||||
var sigHost = await _configService.ReadDefaultSignatureHost();
|
||||
var linkToDoc = $"{sigHost}/envelope/{erId}";
|
||||
placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
|
||||
placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)];
|
||||
var linkToDoc = $"{sigHost}/EnvelopeKey/{erId}";
|
||||
_placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
|
||||
_placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
|
||||
}
|
||||
|
||||
return placeholders;
|
||||
return _placeholders;
|
||||
}
|
||||
|
||||
public async Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: Constants.EmailTemplateType.DocumentAccessCodeReceived);
|
||||
private async Task<Dictionary<string, string>> CreatePlaceholders(EnvelopeReceiverReadOnlyDto? readOnlyDto = null)
|
||||
{
|
||||
if (readOnlyDto?.Envelope is not null && readOnlyDto.Receiver is not null)
|
||||
{
|
||||
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMail(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
|
||||
var erReadOnlyId = (readOnlyDto.Id).EncodeEnvelopeReceiverId();
|
||||
var sigHost = await _configService.ReadDefaultSignatureHost();
|
||||
var linkToDoc = $"{sigHost}/EnvelopeKey/{erReadOnlyId}";
|
||||
_placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
|
||||
_placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
|
||||
}
|
||||
|
||||
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverDto dto, Constants.EmailTemplateType tempType)
|
||||
return _placeholders;
|
||||
}
|
||||
|
||||
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverDto dto, EmailTemplateType tempType, Dictionary<string, object>? optionalPlaceholders = null)
|
||||
{
|
||||
var tempSerResult = await _tempService.ReadByNameAsync(tempType);
|
||||
if (tempSerResult.IsFailed)
|
||||
@@ -92,8 +106,73 @@ namespace EnvelopeGenerator.Application.Services
|
||||
|
||||
var placeholders = await CreatePlaceholders(accessCode: accessCode, envelopeReceiverDto: dto);
|
||||
|
||||
// Add optional place holders.
|
||||
if (optionalPlaceholders is not null)
|
||||
foreach (var oph in optionalPlaceholders)
|
||||
placeholders[oph.Key] = oph.Value.ToString() ?? "NULL";
|
||||
|
||||
//TODO: remove the requirement to add the models using reflections
|
||||
return await CreateWithTemplateAsync(createDto: mail,placeholders: placeholders,
|
||||
dto, dto.Envelope.User!, dto.Envelope);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary<string, object>? optionalPlaceholders = null)
|
||||
{
|
||||
var tempSerResult = await _tempService.ReadByNameAsync(EmailTemplateType.DocumentShared);
|
||||
if (tempSerResult.IsFailed)
|
||||
return tempSerResult.ToFail<int>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"The email cannot send because '{Constants.EmailTemplateType.DocumentShared}' template cannot found.");
|
||||
var temp = tempSerResult.Data;
|
||||
|
||||
var mail = new EmailOutCreateDto()
|
||||
{
|
||||
EmailAddress = dto.ReceiverMail,
|
||||
EmailSubj = temp.Subject,
|
||||
EmailBody = temp.Body,
|
||||
//TODO: remove int casting when all
|
||||
ReferenceId = (int) dto.EnvelopeId, //REFERENCE_ID = ENVELOPE_ID
|
||||
ReferenceString = dto.Envelope!.Uuid, //REFERENCE_STRING = ENVELOPE_UUID
|
||||
//receiver_name = receiver.name,
|
||||
//receiver_access_code = receiver.access_code,
|
||||
//sender_adress = envelope.user.email,
|
||||
//sender_name = envelope.user.full_name,
|
||||
//envelope_title = envelope.title,
|
||||
ReminderTypeId = _dConfig.ReminderTypeId,
|
||||
SendingProfile = _dConfig.SendingProfile,
|
||||
EntityId = null,
|
||||
WfId = (int)EnvelopeStatus.EnvelopeShared,
|
||||
WfReference = null,
|
||||
AddedWho = _dConfig.AddedWho,
|
||||
EmailAttmt1 = _dConfig.EmailAttmt1
|
||||
};
|
||||
|
||||
var placeholders = await CreatePlaceholders(readOnlyDto: dto);
|
||||
|
||||
// Add optional place holders.
|
||||
if (optionalPlaceholders is not null)
|
||||
foreach (var oph in optionalPlaceholders)
|
||||
placeholders[oph.Key] = oph.Value.ToString() ?? "NULL";
|
||||
|
||||
return await CreateWithTemplateAsync(createDto: mail, placeholders: placeholders, dto.Envelope);
|
||||
}
|
||||
|
||||
public async Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: EmailTemplateType.DocumentAccessCodeReceived);
|
||||
|
||||
public Task<DataResult<int>> SendTFAQrCodeAsync(EnvelopeReceiverDto dto)
|
||||
{
|
||||
// Check if receiver or secret key is null
|
||||
if (dto.Receiver is null)
|
||||
throw new ArgumentNullException(nameof(dto), $"TFA Qr Code cannot sent. Receiver information is missing. Envelope receiver dto is {JsonConvert.SerializeObject(dto)}");
|
||||
if (dto.Receiver.TotpSecretkey is null)
|
||||
throw new ArgumentNullException(nameof(dto), $"TFA Qr Code cannot sent. Receiver.TotpSecretKey is null. Envelope receiver dto is {JsonConvert.SerializeObject(dto)}");
|
||||
if (dto.Receiver.TotpExpiration is null)
|
||||
throw new ArgumentNullException(nameof(dto), $"TFA Qr Code cannot sent. Receiver.TotpExpiration is null. Envelope receiver dto is {JsonConvert.SerializeObject(dto)}");
|
||||
|
||||
var totp_qr_64 = _codeGenerator.GenerateTotpQrCode(userEmail: dto.Receiver.EmailAddress, secretKey: dto.Receiver.TotpSecretkey).ToBase64String();
|
||||
return SendAsync(dto, EmailTemplateType.TotpSecret, new()
|
||||
{
|
||||
{"[TFA_QR_CODE]", totp_qr_64 },
|
||||
{"[TFA_EXPIRATION]", dto.Receiver.TotpExpiration }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using AngleSharp.Dom;
|
||||
using EnvelopeGenerator.Application.Configurations;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.Extensions;
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class EnvelopeReceiverCache : IEnvelopeReceiverCache
|
||||
{
|
||||
private readonly EnvelopeReceiverCacheParams _cacheParams;
|
||||
|
||||
private readonly DistributedCacheEntryOptions _codeCacheOptions;
|
||||
|
||||
private readonly IDistributedCache _cache;
|
||||
|
||||
public EnvelopeReceiverCache(IOptions<EnvelopeReceiverCacheParams> cacheParamOptions, IDistributedCache cache)
|
||||
{
|
||||
_cacheParams = cacheParamOptions.Value;
|
||||
_codeCacheOptions = new() { AbsoluteExpirationRelativeToNow = cacheParamOptions.Value.CodeCacheValidityPeriod };
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public async Task<string?> GetSmsCodeAsync(string envelopeReceiverId)
|
||||
{
|
||||
var code_key = string.Format(_cacheParams.CodeCacheKeyFormat, envelopeReceiverId);
|
||||
return await _cache.GetStringAsync(code_key);
|
||||
}
|
||||
|
||||
public async Task<DateTime> SetSmsCodeAsync(string envelopeReceiverId, string code)
|
||||
{
|
||||
// set key
|
||||
var code_key = string.Format(_cacheParams.CodeCacheKeyFormat, envelopeReceiverId);
|
||||
await _cache.SetStringAsync(code_key, code, _codeCacheOptions);
|
||||
|
||||
// set expiration
|
||||
var code_expiration_key = string.Format(_cacheParams.CodeExpirationCacheKeyFormat, envelopeReceiverId);
|
||||
var expiration = DateTime.Now + _cacheParams.CodeCacheValidityPeriod;
|
||||
await _cache.SetDateTimeAsync(code_expiration_key, expiration, _codeCacheOptions);
|
||||
return expiration;
|
||||
}
|
||||
|
||||
public async Task<DateTime?> GetSmsCodeExpirationAsync(string envelopeReceiverId)
|
||||
{
|
||||
var code_expiration_key = string.Format(_cacheParams.CodeExpirationCacheKeyFormat, envelopeReceiverId);
|
||||
return await _cache.GetDateTimeAsync(code_expiration_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Application;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class EnvelopeReceiverReadOnlyService : CRUDService<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnlyDto, EnvelopeReceiverReadOnlyUpdateDto, EnvelopeReceiverReadOnly, long>, IEnvelopeReceiverReadOnlyService
|
||||
{
|
||||
public EnvelopeReceiverReadOnlyService(IEnvelopeReceiverReadOnlyRepository repository, IMapper mapper) : base(repository, mapper)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,48 +2,69 @@
|
||||
using DigitalData.Core.Application;
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using EnvelopeGenerator.Extensions;
|
||||
using EnvelopeGenerator.Application.DTOs.Messaging;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverRepository, EnvelopeReceiverDto, EnvelopeReceiver, object>, IEnvelopeReceiverService
|
||||
public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverRepository, EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>, IEnvelopeReceiverService
|
||||
{
|
||||
private readonly IStringLocalizer<Resource> _localizer;
|
||||
|
||||
public EnvelopeReceiverService(IEnvelopeReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
|
||||
private readonly IMessagingService _messagingService;
|
||||
|
||||
public EnvelopeReceiverService(IEnvelopeReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper, IMessagingService messagingService)
|
||||
: base(repository, mapper)
|
||||
{
|
||||
_localizer = localizer;
|
||||
_messagingService = messagingService;
|
||||
}
|
||||
|
||||
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true)
|
||||
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true)
|
||||
{
|
||||
var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver);
|
||||
return Result.Success(_mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
|
||||
var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
|
||||
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
|
||||
}
|
||||
|
||||
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false)
|
||||
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true)
|
||||
{
|
||||
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
|
||||
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
|
||||
}
|
||||
|
||||
public async Task<DataResult<IEnumerable<string?>>> ReadAccessCodeByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true)
|
||||
{
|
||||
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver);
|
||||
return Result.Success(_mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
|
||||
return Result.Success(env_rcvs.Select(er => er.AccessCode));
|
||||
}
|
||||
|
||||
public async Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true)
|
||||
public async Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
|
||||
{
|
||||
var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver);
|
||||
var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
|
||||
if (env_rcv is null)
|
||||
return Result.Fail<EnvelopeReceiverDto>()
|
||||
.Message(Key.EnvelopeReceiverNotFound);
|
||||
|
||||
return Result.Success(_mapper.MapOrThrow<EnvelopeReceiverDto>(env_rcv));
|
||||
return Result.Success(_mapper.Map<EnvelopeReceiverDto>(env_rcv));
|
||||
}
|
||||
|
||||
public async Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true)
|
||||
public async Task<DataResult<EnvelopeReceiverSecretDto>> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
|
||||
{
|
||||
var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
|
||||
if (env_rcv is null)
|
||||
return Result.Fail<EnvelopeReceiverSecretDto>()
|
||||
.Message(Key.EnvelopeReceiverNotFound);
|
||||
|
||||
return Result.Success(_mapper.Map<EnvelopeReceiverSecretDto>(env_rcv));
|
||||
}
|
||||
|
||||
public async Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
|
||||
{
|
||||
(string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
|
||||
|
||||
@@ -54,7 +75,7 @@ namespace EnvelopeGenerator.Application.Services
|
||||
.Notice(LogLevel.Warning, EnvelopeFlag.WrongEnvelopeReceiverId)
|
||||
.Notice(LogLevel.Warning, Flag.PossibleSecurityBreach);
|
||||
|
||||
return await ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver);
|
||||
return await ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
|
||||
}
|
||||
|
||||
public async Task<DataResult<bool>> VerifyAccessCodeAsync(string uuid, string signature, string accessCode)
|
||||
@@ -119,8 +140,40 @@ namespace EnvelopeGenerator.Application.Services
|
||||
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses)
|
||||
{
|
||||
var er_list = await _repository.ReadByUsernameAsync(username: username, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);
|
||||
var dto_list = _mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(er_list);
|
||||
var dto_list = _mapper.Map<IEnumerable<EnvelopeReceiverDto>>(er_list);
|
||||
return Result.Success(dto_list);
|
||||
}
|
||||
|
||||
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail)
|
||||
{
|
||||
var er = await _repository.ReadLastByReceiver(mail);
|
||||
return er is null ? Result.Fail<string?>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
|
||||
}
|
||||
|
||||
public async Task<DataResult<SmsResponse>> SendSmsAsync(string envelopeReceiverId, string message)
|
||||
{
|
||||
(string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId();
|
||||
|
||||
if (uuid is null || signature is null)
|
||||
return Result.Fail<SmsResponse>()
|
||||
.Message(_localizer[Key.WrongEnvelopeReceiverId])
|
||||
.Notice(LogLevel.Warning, (uuid, signature).ToTitle())
|
||||
.Notice(LogLevel.Warning, EnvelopeFlag.WrongEnvelopeReceiverId)
|
||||
.Notice(LogLevel.Warning, Flag.PossibleSecurityBreach);
|
||||
|
||||
var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: false, withReceiver: false);
|
||||
if (env_rcv is null)
|
||||
return Result.Fail<SmsResponse>()
|
||||
.Message(Key.EnvelopeReceiverNotFound);
|
||||
|
||||
if (env_rcv.PhoneNumber is null)
|
||||
return Result.Fail<SmsResponse>()
|
||||
.Message(Key.PhoneNumberNonexists)
|
||||
.Notice(LogLevel.Error, Flag.NotFound, $"An attempt was made to send sms to the user whose phone number is null. Envelope recipient ID is {envelopeReceiverId}, UUID is {uuid} and signature is {signature}.");
|
||||
|
||||
var res = await _messagingService.SendSmsAsync(recipient: env_rcv.PhoneNumber, message: message);
|
||||
|
||||
return Result.Success(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,27 +3,22 @@ using DigitalData.Core.Application;
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class EnvelopeService : BasicCRUDService<IEnvelopeRepository, EnvelopeDto, Envelope, int>, IEnvelopeService
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
public EnvelopeService(IEnvelopeRepository repository, IMapper mapper, ILogger<EnvelopeService> logger)
|
||||
public EnvelopeService(IEnvelopeRepository repository, IMapper mapper)
|
||||
: base(repository, mapper)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false)
|
||||
{
|
||||
var envelopes = await _repository.ReadAllWithAsync(documents: documents, history: history, documentReceiverElement: documentReceiverElement);
|
||||
var readDto = _mapper.MapOrThrow<IEnumerable<EnvelopeDto>>(envelopes);
|
||||
var readDto = _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
||||
return Result.Success(readDto);
|
||||
}
|
||||
|
||||
@@ -34,7 +29,14 @@ namespace EnvelopeGenerator.Application.Services
|
||||
if (envelope is null)
|
||||
return Result.Fail<EnvelopeDto>();
|
||||
|
||||
var readDto = _mapper.MapOrThrow<EnvelopeDto>(envelope);
|
||||
var readDto = _mapper.Map<EnvelopeDto>(envelope);
|
||||
return Result.Success(readDto);
|
||||
}
|
||||
|
||||
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[] ignore_statuses)
|
||||
{
|
||||
var users = await _repository.ReadByUserAsync(userId: userId, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);
|
||||
var readDto = _mapper.Map<IEnumerable<EnvelopeDto>>(users);
|
||||
return Result.Success(readDto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Application;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using DigitalData.Core.DTO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class EnvelopeTypeService : BasicCRUDService<IEnvelopeTypeRepository, EnvelopeTypeDto, EnvelopeType, int>, IEnvelopeTypeService
|
||||
{
|
||||
public EnvelopeTypeService(IEnvelopeTypeRepository repository, IMapper mapper)
|
||||
private static readonly Guid CacheKey = Guid.NewGuid();
|
||||
|
||||
private readonly IMemoryCache _cache;
|
||||
|
||||
public EnvelopeTypeService(IEnvelopeTypeRepository repository, IMapper mapper, IMemoryCache cache)
|
||||
: base(repository, mapper)
|
||||
{
|
||||
_cache = cache;
|
||||
}
|
||||
|
||||
public override async Task<DataResult<IEnumerable<EnvelopeTypeDto>>> ReadAllAsync()
|
||||
=> await _cache.GetOrCreateAsync(CacheKey, async entry => await base.ReadAllAsync())
|
||||
?? Result.Fail<IEnumerable<EnvelopeTypeDto>>().Notice(LogLevel.Error, Flag.NotFound, "No cached envelope types are available in the database. If you have added any envelope types after the server started, please restart the server.");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Abstractions.Client;
|
||||
using DigitalData.Core.Client;
|
||||
using EnvelopeGenerator.Application.Configurations.GtxMessaging;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs.Messaging;
|
||||
using EnvelopeGenerator.Application.Extensions;
|
||||
using EnvelopeGenerator.Domain.HttpResponse;
|
||||
using Microsoft.Extensions.Caching.Distributed;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class GtxMessagingService : IMessagingService
|
||||
{
|
||||
private readonly IHttpClientService<SmsParams> _smsClient;
|
||||
|
||||
private readonly SmsParams _smsParams;
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
private readonly ICodeGenerator _codeGen;
|
||||
|
||||
private readonly IEnvelopeReceiverCache _erCache;
|
||||
|
||||
public string ServiceProvider { get; }
|
||||
|
||||
public GtxMessagingService(IHttpClientService<SmsParams> smsClient, IOptions<SmsParams> smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator, IEnvelopeReceiverCache envelopeReceiverCache)
|
||||
{
|
||||
_smsClient = smsClient;
|
||||
_smsParams = smsParamsOptions.Value;
|
||||
_mapper = mapper;
|
||||
ServiceProvider = GetType().Name.Replace("Service", string.Empty);
|
||||
_codeGen = codeGenerator;
|
||||
_erCache = envelopeReceiverCache;
|
||||
}
|
||||
|
||||
public async Task<SmsResponse> SendSmsAsync(string recipient, string message)
|
||||
{
|
||||
return await _smsClient.FetchAsync(queryParams: new Dictionary<string, object?>()
|
||||
{
|
||||
{ _smsParams.RecipientQueryParamName, recipient },
|
||||
{ _smsParams.MessageQueryParamName, message }
|
||||
})
|
||||
.ThenAsync(res => res.Json<GtxMessagingResponse>())
|
||||
.ThenAsync(_mapper.Map<SmsResponse>);
|
||||
}
|
||||
|
||||
public async Task<SmsResponse> SendSmsCodeAsync(string recipient, string envelopeReceiverId)
|
||||
{
|
||||
var code = await _erCache.GetSmsCodeAsync(envelopeReceiverId);
|
||||
|
||||
if (code is null)
|
||||
{
|
||||
code = _codeGen.GenerateCode(_smsParams.CodeLength);
|
||||
var expiration = await _erCache.SetSmsCodeAsync(envelopeReceiverId, code);
|
||||
var res = await SendSmsAsync(recipient: recipient, message: code);
|
||||
res.Expiration = expiration;
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
var code_expiration = await _erCache.GetSmsCodeExpirationAsync(envelopeReceiverId);
|
||||
return code_expiration is null
|
||||
? new() { Ok = false }
|
||||
: new() { Ok = false, AllowedAt = code_expiration };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Application;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>, IReceiverService
|
||||
{
|
||||
public ReceiverService(IReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
|
||||
public ReceiverService(IReceiverRepository repository, IMapper mapper)
|
||||
: base(repository, mapper)
|
||||
{
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace EnvelopeGenerator.Application.Services
|
||||
if (rcv is null)
|
||||
return Result.Fail<ReceiverReadDto>();
|
||||
|
||||
return Result.Success(_mapper.MapOrThrow<ReceiverReadDto>(rcv));
|
||||
return Result.Success(_mapper.Map<ReceiverReadDto>(rcv));
|
||||
}
|
||||
|
||||
public async Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null)
|
||||
@@ -36,5 +36,17 @@ namespace EnvelopeGenerator.Application.Services
|
||||
|
||||
return await _repository.DeleteAsync(rcv) ? Result.Success() : Result.Fail();
|
||||
}
|
||||
|
||||
public virtual async Task<Result> UpdateAsync<TUpdateDto>(TUpdateDto updateDto) where TUpdateDto : IUnique<int>
|
||||
{
|
||||
var val = await _repository.ReadByIdAsync(updateDto.Id);
|
||||
if (val == null)
|
||||
{
|
||||
return Result.Fail().Notice(LogLevel.Warning, Flag.NotFound, $"{updateDto.Id} is not found in update process of {GetType()} entity.");
|
||||
}
|
||||
|
||||
var entity = _mapper.Map(updateDto, val);
|
||||
return (await _repository.UpdateAsync(entity)) ? Result.Success() : Result.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
using AutoMapper;
|
||||
using DigitalData.Core.Application;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using EnvelopeGenerator.Application.Contracts;
|
||||
using EnvelopeGenerator.Application.DTOs;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using EnvelopeGenerator.Infrastructure.Contracts;
|
||||
using EnvelopeGenerator.Application.Resources;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Services
|
||||
{
|
||||
public class UserReceiverService : BasicCRUDService<IUserReceiverRepository, UserReceiverDto, UserReceiver, int>, IUserReceiverService
|
||||
{
|
||||
public UserReceiverService(IUserReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
|
||||
public UserReceiverService(IUserReceiverRepository repository, IMapper mapper)
|
||||
: base(repository, mapper)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Public Class Constants
|
||||
|
||||
#Region "Status Fields"
|
||||
'http://wiki.dd/xwiki13/bin/view/Anwendungen/Produkt-Handbuch/Sonstiges/SignFlow/Envelope%20Status/
|
||||
Public Enum EnvelopeStatus
|
||||
Invalid = 0
|
||||
EnvelopeCreated = 1001
|
||||
@@ -17,8 +18,11 @@
|
||||
AccessCodeIncorrect = 2003
|
||||
DocumentOpened = 2004
|
||||
DocumentSigned = 2005
|
||||
DocumentForwarded = 4001
|
||||
SignatureConfirmed = 2006
|
||||
DocumentRejected = 2007
|
||||
EnvelopeShared = 2008
|
||||
EnvelopeViewed = 2009
|
||||
MessageInvitationSent = 3001 ' Wird von Trigger verwendet
|
||||
MessageAccessCodeSent = 3002
|
||||
MessageConfirmationSent = 3003
|
||||
@@ -26,6 +30,7 @@
|
||||
MessageCompletionSent = 3005
|
||||
End Enum
|
||||
|
||||
'TODO: standardize in xwiki
|
||||
Public Enum ReferenceType
|
||||
Receiver
|
||||
Sender
|
||||
@@ -73,7 +78,7 @@
|
||||
|
||||
Public Enum CertificationType
|
||||
ElectronicSignature = 1
|
||||
QualifiedSignature = 2
|
||||
'QualifiedSignature = 2
|
||||
End Enum
|
||||
|
||||
Public Enum FinalEmailType
|
||||
@@ -93,6 +98,16 @@
|
||||
DocumentDeleted
|
||||
DocumentCompleted
|
||||
DocumentAccessCodeReceived
|
||||
DocumentShared
|
||||
TotpSecret
|
||||
End Enum
|
||||
|
||||
Public Enum EncodeType
|
||||
EnvelopeReceiver
|
||||
EnvelopeReceiverReadOnly
|
||||
Undefined
|
||||
DocumentForwarded
|
||||
DocumentShared
|
||||
End Enum
|
||||
|
||||
#End Region
|
||||
@@ -108,4 +123,4 @@
|
||||
Public Const RED_300 = "#fecaca"
|
||||
Public Const ORANGE_300 = "#fed7aa"
|
||||
#End Region
|
||||
End Class
|
||||
End Class
|
||||
@@ -1,15 +1,8 @@
|
||||
Public Class DbConfig
|
||||
Public Property ExternalProgramName As String = "Sign Flow"
|
||||
Public Property ExternalProgramName As String = "signFLOW"
|
||||
Public Property DocumentPathOrigin As String = ""
|
||||
Public Property DocumentPath As String = ""
|
||||
Public Property ExportPath As String = ""
|
||||
Public Property DocumentPath_DMZ As String = ""
|
||||
Public Property ExportPath_DMZ As String = ""
|
||||
Public Property DOCUMENT_PATH_MOVE_AFTSEND As String = ""
|
||||
Public Property FINISHED_PATH_EX_DMZ As String = ""
|
||||
Public Property EML_PATH_EX_DMZ As String = ""
|
||||
Public Property SendingProfile As Integer = 0
|
||||
Public Property SignatureHost As String = ""
|
||||
Public Property NetUse_necessary As Boolean = False
|
||||
Public Property NetUse_Finish As Boolean = False
|
||||
End Class
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<Deterministic>true</Deterministic>
|
||||
<TargetFrameworkProfile />
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -63,22 +65,20 @@
|
||||
<Reference Include="DevExpress.XtraEditors.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
|
||||
<Reference Include="DevExpress.XtraGauges.v21.2.Core, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DevExpress.XtraReports.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DigitalData.Modules.Base, Version=1.3.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\DDModules\Base\bin\Debug\DigitalData.Modules.Base.dll</HintPath>
|
||||
<Reference Include="DigitalData.Modules.Base">
|
||||
<HintPath>..\..\2_DLL Projekte\DDModules\Base\bin\Debug\DigitalData.Modules.Base.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Config">
|
||||
<HintPath>..\..\DDModules\Config\bin\Debug\DigitalData.Modules.Config.dll</HintPath>
|
||||
<HintPath>..\..\2_DLL Projekte\DDModules\Config\bin\Debug\DigitalData.Modules.Config.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Database">
|
||||
<HintPath>..\..\DDModules\Database\bin\Debug\DigitalData.Modules.Database.dll</HintPath>
|
||||
<HintPath>..\..\2_DLL Projekte\DDModules\Database\bin\Debug\DigitalData.Modules.Database.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Logging, Version=2.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath>
|
||||
<Reference Include="DigitalData.Modules.Logging">
|
||||
<HintPath>..\..\2_DLL Projekte\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="GdPicture.NET.14">
|
||||
<HintPath>D:\ProgramFiles\GdPicture.NET 14\Redist\GdPicture.NET (.NET Framework 4.5)\GdPicture.NET.14.dll</HintPath>
|
||||
<Reference Include="GdPicture.NET.14, Version=14.2.89.0, Culture=neutral, PublicKeyToken=f52a2e60ad468dbb, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\GdPicture.14.2.89\lib\net462\GdPicture.NET.14.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||
@@ -260,11 +260,13 @@
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Model.en.Designer.vb</LastGenOutput>
|
||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Strings\Model.resx">
|
||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Model.Designer.vb</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -289,4 +291,11 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||
<Import Project="..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets" Condition="Exists('..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -33,7 +33,7 @@ Namespace Jobs
|
||||
Private PDFMerger As PDFMerger
|
||||
Private ReportCreator As ReportCreator
|
||||
|
||||
Private ReadOnly CompleteWaitTime As Integer = 5
|
||||
Private ReadOnly CompleteWaitTime As Integer = 1
|
||||
Private ParentFolderUID As String = ""
|
||||
Private myTempFiles As TempFiles
|
||||
|
||||
@@ -82,49 +82,14 @@ Namespace Jobs
|
||||
|
||||
Logger.Debug("Loading ReportCreator..")
|
||||
ReportCreator = New ReportCreator(LogConfig, oState)
|
||||
Logger.Debug("My.Settings.RuninDMZ: [{0}]", My.Settings.RuninDMZ.ToString)
|
||||
Logger.Debug("My.Settings.NetUse_Usr: [{0}]", My.Settings.NetUse_Usr)
|
||||
|
||||
Config.DocumentPath = Config.DocumentPath
|
||||
|
||||
If My.Settings.RuninDMZ = True Then
|
||||
If Config.DocumentPath_DMZ <> String.Empty Then
|
||||
Logger.Debug("RuninDMZ - Using DocumentPath_DMZ: [{0}] - Overwrite Document-Path", Config.DocumentPath_DMZ)
|
||||
Config.DocumentPath = Config.DocumentPath_DMZ
|
||||
Config.NetUse_necessary = True
|
||||
Else
|
||||
Config.DocumentPath = Config.DocumentPath
|
||||
End If
|
||||
Else
|
||||
If Config.DOCUMENT_PATH_MOVE_AFTSEND <> String.Empty Then
|
||||
Logger.Debug("Using DMZRemotePath: [{0}] - Overwrite Document-Path ...", Config.DOCUMENT_PATH_MOVE_AFTSEND)
|
||||
Config.DocumentPath = Config.DOCUMENT_PATH_MOVE_AFTSEND
|
||||
Config.NetUse_Finish = True
|
||||
|
||||
Else
|
||||
Config.DocumentPath = Config.DocumentPath
|
||||
End If
|
||||
End If
|
||||
Logger.Debug("DocumentPath: [{0}]", Config.DocumentPath)
|
||||
|
||||
If My.Settings.RuninDMZ = True Then
|
||||
If Config.FINISHED_PATH_EX_DMZ <> String.Empty Then
|
||||
Logger.Debug("RuninDMZ - FINISHED_PATH_EX_DMZ configured: [{0}]", Config.FINISHED_PATH_EX_DMZ)
|
||||
Config.NetUse_Finish = True
|
||||
End If
|
||||
If Config.ExportPath_DMZ <> String.Empty Then
|
||||
Logger.Debug("RuninDMZ - Using ExportPath_DMZ: [{0}] - Overwrite ExportPath", Config.ExportPath_DMZ)
|
||||
Config.ExportPath = Config.ExportPath_DMZ
|
||||
End If
|
||||
End If
|
||||
|
||||
Logger.Debug("ExportPath: [{0}]", Config.ExportPath)
|
||||
|
||||
If Config.NetUse_Finish = True Then
|
||||
If NetUse_Command(Config.DocumentPath, My.Settings.NetUse_Usr, My.Settings.NetUse_PW) = True Then
|
||||
Logger.Debug("NetUse_Finish = successful!")
|
||||
End If
|
||||
End If
|
||||
|
||||
Dim oCompleteStatus As Integer = Constants.EnvelopeStatus.EnvelopeCompletelySigned
|
||||
Dim oSql = $"SELECT * FROM TBSIG_ENVELOPE WHERE STATUS = {oCompleteStatus} AND DATEDIFF(minute, CHANGED_WHEN, GETDATE()) >= {CompleteWaitTime} ORDER BY GUID"
|
||||
Dim oTable = Database.GetDatatable(oSql)
|
||||
@@ -157,10 +122,6 @@ Namespace Jobs
|
||||
Logger.Warn("EnvelopeData could not be loaded for Id [{0}]!", oId)
|
||||
Throw New ArgumentNullException("EnvelopeData")
|
||||
End If
|
||||
If Config.DOCUMENT_PATH_MOVE_AFTSEND <> String.Empty Then
|
||||
oEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DOCUMENT_PATH_MOVE_AFTSEND)
|
||||
Logger.Debug("Replaced Path in oEnvelopeData.DocumentPath!")
|
||||
End If
|
||||
Logger.Debug("Burning Annotations to pdf ...")
|
||||
Dim oBurnedDocument As Byte() = BurnAnnotationsToPdf(oEnvelopeData)
|
||||
If oBurnedDocument Is Nothing Then
|
||||
@@ -196,13 +157,6 @@ Namespace Jobs
|
||||
Throw New ExportDocumentException("Could not export final document to disk!", ex)
|
||||
End Try
|
||||
|
||||
If Config.NetUse_Finish = True Then
|
||||
If Config.FINISHED_PATH_EX_DMZ <> String.Empty Then
|
||||
If My.Settings.NetUse_PW <> String.Empty And My.Settings.NetUse_Usr <> String.Empty Then
|
||||
Clean_DNZ_PAth(Config.FINISHED_PATH_EX_DMZ)
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Logger.Info("Writing EB-bytes to database...")
|
||||
Update_File_DB(oOutputFilePath, oEnvelope.Id)
|
||||
|
||||
@@ -287,48 +241,48 @@ Namespace Jobs
|
||||
data = br.ReadBytes(CInt(numBytes))
|
||||
Return data
|
||||
End Function
|
||||
Private Function NetUse_Command(pDestinationPath As String, pUsername As String, pPassword As String)
|
||||
Dim oDectryptedPW = Helpers.Decrypt(My.Settings.NetUse_PW)
|
||||
Dim netUseCommand As String = $"net use {pDestinationPath} /user:{pUsername} {oDectryptedPW}"
|
||||
Logger.Debug("EXECUTING NetUse_Command for " & pDestinationPath)
|
||||
Dim processInfo As New ProcessStartInfo("cmd.exe", $"/C {netUseCommand}")
|
||||
processInfo.RedirectStandardOutput = True
|
||||
processInfo.UseShellExecute = False
|
||||
processInfo.CreateNoWindow = True
|
||||
'Private Function NetUse_Command(pDestinationPath As String, pUsername As String, pPassword As String)
|
||||
' Dim oDectryptedPW = Helpers.Decrypt(My.Settings.NetUse_PW)
|
||||
' Dim netUseCommand As String = $"net use {pDestinationPath} /user:{pUsername} {oDectryptedPW}"
|
||||
' Logger.Debug("EXECUTING NetUse_Command for " & pDestinationPath)
|
||||
' Dim processInfo As New ProcessStartInfo("cmd.exe", $"/C {netUseCommand}")
|
||||
' processInfo.RedirectStandardOutput = True
|
||||
' processInfo.UseShellExecute = False
|
||||
' processInfo.CreateNoWindow = True
|
||||
|
||||
Using process As Process = Process.Start(processInfo)
|
||||
process.WaitForExit()
|
||||
' Using process As Process = Process.Start(processInfo)
|
||||
' process.WaitForExit()
|
||||
|
||||
' Prüfe den Rückgabewert des net use Befehls
|
||||
If process.ExitCode = 0 Then
|
||||
Return True
|
||||
Else
|
||||
Return False
|
||||
End If
|
||||
End Using
|
||||
End Function
|
||||
' ' Prüfe den Rückgabewert des net use Befehls
|
||||
' If process.ExitCode = 0 Then
|
||||
' Return True
|
||||
' Else
|
||||
' Return False
|
||||
' End If
|
||||
' End Using
|
||||
'End Function
|
||||
|
||||
Private Function Clean_DNZ_PAth(pSourcePath As String) As Boolean
|
||||
Dim oFilename = System.IO.Path.GetFileName(pSourcePath)
|
||||
'Private Function Clean_DNZ_PAth(pSourcePath As String) As Boolean
|
||||
' Dim oFilename = System.IO.Path.GetFileName(pSourcePath)
|
||||
|
||||
Logger.Debug("## Starting Clean_DNZ_PAth ...")
|
||||
Logger.Debug("## pSourcePath {0}", pSourcePath)
|
||||
' Logger.Debug("## Starting Clean_DNZ_PAth ...")
|
||||
' Logger.Debug("## pSourcePath {0}", pSourcePath)
|
||||
|
||||
Dim oDirectorySource = Path.Combine(pSourcePath, ParentFolderUID)
|
||||
' Dim oDirectorySource = Path.Combine(pSourcePath, ParentFolderUID)
|
||||
|
||||
Try
|
||||
Logger.Debug($"Deleting oDirectorySource {oDirectorySource} ...")
|
||||
Directory.Delete(oDirectorySource, True)
|
||||
Console.WriteLine($"Folder successfully deleted!")
|
||||
Logger.Debug($"...Deleted!")
|
||||
Return True
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
Return False
|
||||
End Try
|
||||
' Try
|
||||
' Logger.Debug($"Deleting oDirectorySource {oDirectorySource} ...")
|
||||
' Directory.Delete(oDirectorySource, True)
|
||||
' Console.WriteLine($"Folder successfully deleted!")
|
||||
' Logger.Debug($"...Deleted!")
|
||||
' Return True
|
||||
' Catch ex As Exception
|
||||
' Logger.Error(ex)
|
||||
' Return False
|
||||
' End Try
|
||||
|
||||
|
||||
End Function
|
||||
'End Function
|
||||
Private Function SendFinalEmails(pEnvelope As Envelope) As Boolean ', pAttachment As String
|
||||
Dim oMailToCreator = pEnvelope.FinalEmailToCreator
|
||||
Dim oMailToReceivers = pEnvelope.FinalEmailToReceivers
|
||||
@@ -398,15 +352,7 @@ Namespace Jobs
|
||||
Dim oAnnotations = pEnvelopeData.AnnotationData
|
||||
Dim oInputPath = ""
|
||||
If IsNothing(pEnvelopeData.DocAsByte) Then
|
||||
If My.Settings.RuninDMZ Then
|
||||
Logger.Debug("Replacing Path in pData.DocumentPath ...")
|
||||
oInputPath = pEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DocumentPath)
|
||||
ElseIf Config.DOCUMENT_PATH_MOVE_AFTSEND <> String.Empty Then
|
||||
Logger.Debug("Replacing Path in pData.DocumentPath ...")
|
||||
oInputPath = pEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DOCUMENT_PATH_MOVE_AFTSEND)
|
||||
Else
|
||||
oInputPath = pEnvelopeData.DocumentPath
|
||||
End If
|
||||
oInputPath = pEnvelopeData.DocumentPath
|
||||
Logger.Info($"Input path: [{oInputPath}]")
|
||||
Else
|
||||
Logger.Info($"we got bytes..")
|
||||
|
||||
@@ -16,17 +16,12 @@ Public Class ConfigModel
|
||||
Dim oRow As DataRow = oTable.Rows.Item(0)
|
||||
|
||||
Return New DbConfig() With {
|
||||
.DocumentPath = oRow.ItemEx("DOCUMENT_PATH", ""),
|
||||
.DocumentPathOrigin = oRow.ItemEx("DOCUMENT_PATH", ""),
|
||||
.DocumentPath_DMZ = oRow.ItemEx("DOCUMENT_PATH_DMZ", ""),
|
||||
.ExportPath = oRow.ItemEx("EXPORT_PATH", ""),
|
||||
.ExportPath_DMZ = oRow.ItemEx("EXPORT_PATH_DMZ", ""),
|
||||
.SendingProfile = oRow.ItemEx("SENDING_PROFILE", 0),
|
||||
.SignatureHost = oRow.ItemEx("SIGNATURE_HOST", ""),
|
||||
.ExternalProgramName = oRow.ItemEx("EXTERNAL_PROGRAM_NAME", ""),
|
||||
.DOCUMENT_PATH_MOVE_AFTSEND = oRow.ItemEx("DOCUMENT_PATH_MOVE_AFTSEND", ""),
|
||||
.FINISHED_PATH_EX_DMZ = oRow.ItemEx("FINISHED_PATH_EX_DMZ", ""),
|
||||
.EML_PATH_EX_DMZ = oRow.ItemEx("EML_PATH_EX_DMZ", "")
|
||||
.DocumentPath = oRow.ItemEx("DOCUMENT_PATH", ""),
|
||||
.DocumentPathOrigin = oRow.ItemEx("DOCUMENT_PATH", ""),
|
||||
.ExportPath = oRow.ItemEx("EXPORT_PATH", ""),
|
||||
.SendingProfile = oRow.ItemEx("SENDING_PROFILE", 0),
|
||||
.SignatureHost = oRow.ItemEx("SIGNATURE_HOST", ""),
|
||||
.ExternalProgramName = oRow.ItemEx("EXTERNAL_PROGRAM_NAME", "")
|
||||
}
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' indem Sie "*" wie unten gezeigt eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.9.1.0")>
|
||||
<Assembly: AssemblyFileVersion("1.9.1.0")>
|
||||
<Assembly: AssemblyVersion("2.0.0.0")>
|
||||
<Assembly: AssemblyFileVersion("2.0.0.0")>
|
||||
|
||||
@@ -15,7 +15,7 @@ Option Explicit On
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
@@ -53,33 +53,6 @@ Namespace My
|
||||
Return defaultInstance
|
||||
End Get
|
||||
End Property
|
||||
|
||||
<Global.System.Configuration.ApplicationScopedSettingAttribute(), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Configuration.DefaultSettingValueAttribute("False")> _
|
||||
Public ReadOnly Property RuninDMZ() As Boolean
|
||||
Get
|
||||
Return CType(Me("RuninDMZ"),Boolean)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
<Global.System.Configuration.ApplicationScopedSettingAttribute(), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Configuration.DefaultSettingValueAttribute("dd-gan\Administrator")> _
|
||||
Public ReadOnly Property NetUse_Usr() As String
|
||||
Get
|
||||
Return CType(Me("NetUse_Usr"),String)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
<Global.System.Configuration.ApplicationScopedSettingAttribute(), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Configuration.DefaultSettingValueAttribute("sY4vnATDXwosbTJGip6SqA==")> _
|
||||
Public ReadOnly Property NetUse_PW() As String
|
||||
Get
|
||||
Return CType(Me("NetUse_PW"),String)
|
||||
End Get
|
||||
End Property
|
||||
End Class
|
||||
End Namespace
|
||||
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="My" GeneratedClassName="MySettings" UseMySettingsClassName="true">
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="RuninDMZ" Type="System.Boolean" Scope="Application">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="NetUse_Usr" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">dd-gan\Administrator</Value>
|
||||
</Setting>
|
||||
<Setting Name="NetUse_PW" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">sY4vnATDXwosbTJGip6SqA==</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -34,8 +34,18 @@ Public Class ActionService
|
||||
|
||||
Return True
|
||||
End Function
|
||||
Public Function Resend_Receiver(pEnvelope As Envelope, pmail As String) As Boolean
|
||||
If HistoryService.SetEnvelopeStatus(pEnvelope, Constants.EnvelopeStatus.EnvelopeQueued, pEnvelope.User.Email) = False Then
|
||||
Return False
|
||||
End If
|
||||
Dim oSendResult As Boolean = False
|
||||
For Each oReceiver In pEnvelope.Receivers
|
||||
EmailService.SendDocumentReceivedEmail(pEnvelope, oReceiver)
|
||||
Next
|
||||
Return oSendResult
|
||||
End Function
|
||||
Public Function ResendReceiver(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean
|
||||
EmailService.SendDocumentReceivedEmail(pEnvelope, pReceiver)
|
||||
Return EmailService.SendDocumentReceivedEmail(pEnvelope, pReceiver)
|
||||
End Function
|
||||
|
||||
|
||||
|
||||
@@ -138,6 +138,9 @@
|
||||
<data name="Document Could Not Be Saved" xml:space="preserve">
|
||||
<value>Document could not be saved!</value>
|
||||
</data>
|
||||
<data name="Document forwarded" xml:space="preserve">
|
||||
<value>Document forwarded to receiver: {0}</value>
|
||||
</data>
|
||||
<data name="Edit Envelope" xml:space="preserve">
|
||||
<value>Edit Envelope</value>
|
||||
</data>
|
||||
@@ -165,6 +168,9 @@
|
||||
<data name="Envelope-Editor" xml:space="preserve">
|
||||
<value>Envelope-Editor</value>
|
||||
</data>
|
||||
<data name="Error email Validation" xml:space="preserve">
|
||||
<value>The email [ @Mail ] could not be varified!</value>
|
||||
</data>
|
||||
<data name="Error sending the envelope" xml:space="preserve">
|
||||
<value>Error sending the envelope:</value>
|
||||
</data>
|
||||
@@ -186,6 +192,9 @@
|
||||
<data name="Invalid Email Address" xml:space="preserve">
|
||||
<value>Receiver {0} has an invalid Email Address.</value>
|
||||
</data>
|
||||
<data name="Invitation successfully resend" xml:space="preserve">
|
||||
<value>Invitation has been send once again!</value>
|
||||
</data>
|
||||
<data name="Missing Documents" xml:space="preserve">
|
||||
<value>Missing Documents</value>
|
||||
</data>
|
||||
|
||||
@@ -138,6 +138,9 @@
|
||||
<data name="Document Could Not Be Saved" xml:space="preserve">
|
||||
<value>Dokument konnte nicht gespeichert werden!</value>
|
||||
</data>
|
||||
<data name="Document forwarded" xml:space="preserve">
|
||||
<value>Umschlag an Empfänger {0} weitergeleitet.</value>
|
||||
</data>
|
||||
<data name="Edit Envelope" xml:space="preserve">
|
||||
<value>Bearbeite Umschlag</value>
|
||||
</data>
|
||||
@@ -165,6 +168,9 @@
|
||||
<data name="Envelope-Editor" xml:space="preserve">
|
||||
<value>Umschlag-Editor</value>
|
||||
</data>
|
||||
<data name="Error email Validation" xml:space="preserve">
|
||||
<value>Die Email-Adresse [ @Mail ] konnte nicht validiert werden!</value>
|
||||
</data>
|
||||
<data name="Error sending the envelope" xml:space="preserve">
|
||||
<value>Fehler beim Senden des Umschlags:</value>
|
||||
</data>
|
||||
@@ -186,6 +192,9 @@
|
||||
<data name="Invalid Email Address" xml:space="preserve">
|
||||
<value>Empfänger {0} hat keine gültige Email Addresse.</value>
|
||||
</data>
|
||||
<data name="Invitation successfully resend" xml:space="preserve">
|
||||
<value>Die Einladung wurde nochmal versendet!</value>
|
||||
</data>
|
||||
<data name="Missing Documents" xml:space="preserve">
|
||||
<value>Fehlendes Dokument</value>
|
||||
</data>
|
||||
|
||||
@@ -127,6 +127,15 @@ Namespace My.Resources
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Umschlag an Empfänger {0} weitergeleitet. ähnelt.
|
||||
'''</summary>
|
||||
Public Shared ReadOnly Property Document_forwarded() As String
|
||||
Get
|
||||
Return ResourceManager.GetString("Document forwarded", resourceCulture)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Bearbeite Umschlag ähnelt.
|
||||
'''</summary>
|
||||
@@ -208,6 +217,15 @@ Namespace My.Resources
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Die Email-Adresse [ @Mail ] konnte nicht validiert werden! ähnelt.
|
||||
'''</summary>
|
||||
Public Shared ReadOnly Property Error_email_Validation() As String
|
||||
Get
|
||||
Return ResourceManager.GetString("Error email Validation", resourceCulture)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Fehler beim Senden des Umschlags: ähnelt.
|
||||
'''</summary>
|
||||
@@ -271,6 +289,15 @@ Namespace My.Resources
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Die Einladung wurde nochmal versendet! ähnelt.
|
||||
'''</summary>
|
||||
Public Shared ReadOnly Property Invitation_successfully_resend() As String
|
||||
Get
|
||||
Return ResourceManager.GetString("Invitation successfully resend", resourceCulture)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Fehlendes Dokument ähnelt.
|
||||
'''</summary>
|
||||
|
||||
20
EnvelopeGenerator.Common/Strings/Model.Designer.vb
generated
20
EnvelopeGenerator.Common/Strings/Model.Designer.vb
generated
@@ -306,16 +306,16 @@ Namespace My.Resources
|
||||
Return ResourceManager.GetString("PartlySigned", resourceCulture)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Qualifizierte Signatur ähnelt.
|
||||
'''</summary>
|
||||
Public Shared ReadOnly Property QualifiedSignature() As String
|
||||
Get
|
||||
Return ResourceManager.GetString("QualifiedSignature", resourceCulture)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
|
||||
''''<summary>
|
||||
'''' Sucht eine lokalisierte Zeichenfolge, die Qualifizierte Signatur ähnelt.
|
||||
''''</summary>
|
||||
'Public Shared ReadOnly Property QualifiedSignature() As String
|
||||
' Get
|
||||
' Return ResourceManager.GetString("QualifiedSignature", resourceCulture)
|
||||
' End Get
|
||||
'End Property
|
||||
|
||||
'''<summary>
|
||||
''' Sucht eine lokalisierte Zeichenfolge, die Arbeitsanweisung ähnelt.
|
||||
'''</summary>
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
<configuration>
|
||||
|
||||
<configSections>
|
||||
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="EnvelopeGenerator.Common.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
@@ -29,17 +26,4 @@
|
||||
</sharedListeners>
|
||||
</system.diagnostics>
|
||||
|
||||
<applicationSettings>
|
||||
<EnvelopeGenerator.Common.My.MySettings>
|
||||
<setting name="RuninDMZ" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="NetUse_Usr" serializeAs="String">
|
||||
<value>dd-gan\Administrator</value>
|
||||
</setting>
|
||||
<setting name="NetUse_PW" serializeAs="String">
|
||||
<value>sY4vnATDXwosbTJGip6SqA==</value>
|
||||
</setting>
|
||||
</EnvelopeGenerator.Common.My.MySettings>
|
||||
</applicationSettings>
|
||||
</configuration>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="GdPicture" version="14.2.89" targetFramework="net462" />
|
||||
<package id="GdPicture.runtimes.windows" version="14.2.89" targetFramework="net462" />
|
||||
<package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" targetFramework="net462" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
|
||||
<package id="Quartz" version="3.8.0" targetFramework="net462" />
|
||||
|
||||
@@ -1,43 +1,32 @@
|
||||
using System.ComponentModel;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_CONFIG", Schema = "dbo")]
|
||||
public class Config
|
||||
public class Config : IUnique<int>
|
||||
{
|
||||
[Column("DOCUMENT_PATH", TypeName = "nvarchar(256)")]
|
||||
public string DocumentPath { get; set; }
|
||||
public string? DocumentPath { get; init; }
|
||||
|
||||
[Column("SENDING_PROFILE", TypeName = "int")]
|
||||
[Required]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.None)] // Assuming SENDING_PROFILE is manually entered or controlled by the application logic
|
||||
[DefaultValue(0)] // This sets the default value for SENDING_PROFILE
|
||||
public int SendingProfile { get; set; }
|
||||
public required int SendingProfile { get; init; }
|
||||
|
||||
[Column("SIGNATURE_HOST", TypeName = "nvarchar(128)")]
|
||||
public string SignatureHost { get; set; }
|
||||
public string? SignatureHost { get; init; }
|
||||
|
||||
[Column("EXTERNAL_PROGRAM_NAME", TypeName = "nvarchar(30)")]
|
||||
public string ExternalProgramName { get; set; }
|
||||
public string? ExternalProgramName { get; init; }
|
||||
|
||||
[Column("EXPORT_PATH", TypeName = "nvarchar(256)")]
|
||||
public string ExportPath { get; set; }
|
||||
public string? ExportPath { get; init; }
|
||||
|
||||
[Column("DOCUMENT_PATH_DMZ", TypeName = "nvarchar(512)")]
|
||||
[Required]
|
||||
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_DMZ
|
||||
public string DocumentPathDmz { get; set; }
|
||||
|
||||
[Column("EXPORT_PATH_DMZ", TypeName = "nvarchar(512)")]
|
||||
[Required]
|
||||
[DefaultValue("")] // This sets the default value for EXPORT_PATH_DMZ
|
||||
public string ExportPathDmz { get; set; }
|
||||
|
||||
[Column("DOCUMENT_PATH_MOVE_AFTSEND", TypeName = "nvarchar(512)")]
|
||||
[Required]
|
||||
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_MOVE_AFTSEND
|
||||
public string DocumentPathMoveAftsend { get; set; }
|
||||
[Obsolete("Configuration does not have an ID; it represents a single table in the database.")]
|
||||
[NotMapped]
|
||||
[JsonIgnore]
|
||||
public int Id => throw new InvalidOperationException("This configuration does not support an ID as it represents a single table in the database.");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_DOCUMENT_RECEIVER_ELEMENT", Schema = "dbo")]
|
||||
public class DocumentReceiverElement
|
||||
public class DocumentReceiverElement : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_DOCUMENT_STATUS", Schema = "dbo")]
|
||||
public class DocumentStatus
|
||||
public class DocumentStatus : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -27,7 +28,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
public DateTime? StatusChangedWhen { get; set; }
|
||||
|
||||
[Column("VALUE", TypeName = "nvarchar(max)")]
|
||||
public string Value { get; set; }
|
||||
public string? Value { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
@@ -42,4 +43,4 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
[ForeignKey("ReceiverId")]
|
||||
public virtual Receiver? Receiver { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_EMAIL_TEMPLATE", Schema = "dbo")]
|
||||
public class EmailTemplate
|
||||
public class EmailTemplate : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -12,12 +13,12 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("NAME", TypeName = "nvarchar(64)")]
|
||||
public string Name { get; set; }
|
||||
public string? Name { get; set; }
|
||||
|
||||
[Column("BODY", TypeName = "nvarchar(max)")]
|
||||
public string Body { get; set; }
|
||||
public string? Body { get; set; }
|
||||
|
||||
[Column("SUBJECT", TypeName = "nvarchar(512)")]
|
||||
public string Subject { get; set; }
|
||||
public string? Subject { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
using EnvelopeGenerator.Common;
|
||||
using EnvelopeGenerator.Common.My.Resources;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using EnvelopeGenerator.Common;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE", Schema = "dbo")]
|
||||
public class Envelope
|
||||
public class Envelope : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -26,11 +26,11 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")]
|
||||
public string Uuid { get; set; }
|
||||
public required string Uuid { get; init; }
|
||||
|
||||
[Required]
|
||||
[Column("MESSAGE", TypeName = "nvarchar(max)")]
|
||||
public string Message { get; set; }
|
||||
public string? Message { get; set; }
|
||||
|
||||
[Column("EXPIRES_WHEN", TypeName = "datetime")]
|
||||
public DateTime? ExpiresWhen { get; set; }
|
||||
@@ -46,13 +46,13 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
|
||||
[Column("TITLE", TypeName = "nvarchar(128)")]
|
||||
public string Title { get; set; }
|
||||
public string? Title { get; set; }
|
||||
|
||||
[Column("CONTRACT_TYPE")]
|
||||
public int? ContractType { get; set; }
|
||||
|
||||
[Column("LANGUAGE", TypeName = "nvarchar(5)")]
|
||||
public string Language { get; set; }
|
||||
public required string Language { get; set; }
|
||||
|
||||
[Column("SEND_REMINDER_EMAILS")]
|
||||
public bool? SendReminderEmails { get; set; }
|
||||
@@ -84,10 +84,6 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
[Column("EXPIRES_WARNING_WHEN_DAYS")]
|
||||
public int? ExpiresWarningWhenDays { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("DMZ_MOVED")]
|
||||
public bool DmzMoved { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The sender of envelope
|
||||
/// </summary>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE_CERTIFICATE", Schema = "dbo")]
|
||||
public class EnvelopeCertificate
|
||||
public class EnvelopeCertificate : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -17,11 +18,11 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")]
|
||||
public string EnvelopeUuid { get; set; }
|
||||
public required string EnvelopeUuid { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ENVELOPE_SUBJECT", TypeName = "nvarchar(512)")]
|
||||
public string EnvelopeSubject { get; set; }
|
||||
public required string EnvelopeSubject { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("CREATOR_ID")]
|
||||
@@ -29,11 +30,11 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[Column("CREATOR_NAME", TypeName = "nvarchar(128)")]
|
||||
public string CreatorName { get; set; }
|
||||
public required string CreatorName { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("CREATOR_EMAIL", TypeName = "nvarchar(128)")]
|
||||
public string CreatorEmail { get; set; }
|
||||
public required string CreatorEmail { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ENVELOPE_STATUS")]
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE_DOCUMENT", Schema = "dbo")]
|
||||
public class EnvelopeDocument
|
||||
public class EnvelopeDocument : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -15,20 +16,12 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
[Column("ENVELOPE_ID")]
|
||||
public int EnvelopeId { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("FILENAME", TypeName = "nvarchar(256)")]
|
||||
public string Filename { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("FILEPATH", TypeName = "nvarchar(256)")]
|
||||
public string Filepath { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
public DateTime AddedWhen { get; set; }
|
||||
public required DateTime AddedWhen { get; set; }
|
||||
|
||||
[Column("FILENAME_ORIGINAL", TypeName = "nvarchar(256)")]
|
||||
public string FilenameOriginal { get; set; }
|
||||
[Column("BYTE_DATA", TypeName = "varbinary(max)")]
|
||||
public byte[]? ByteData { get; init; }
|
||||
|
||||
public IEnumerable<DocumentReceiverElement>? Elements { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using DigitalData.UserManager.Domain.Entities;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using DigitalData.UserManager.Domain.Entities;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
@@ -6,7 +7,7 @@ using static EnvelopeGenerator.Common.Constants;
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE_HISTORY", Schema = "dbo")]
|
||||
public class EnvelopeHistory
|
||||
public class EnvelopeHistory : IUnique<long>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -19,7 +20,7 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[Column("USER_REFERENCE", TypeName = "nvarchar(128)")]
|
||||
public string UserReference { get; set; }
|
||||
public required string UserReference { get; init; }
|
||||
|
||||
[Required]
|
||||
[Column("STATUS")]
|
||||
@@ -43,11 +44,17 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
public virtual Receiver? Receiver { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public ReferenceType ReferenceType => (Status / 3) switch
|
||||
public ReferenceType ReferenceType => (Status / 1000) switch
|
||||
{
|
||||
1 => ReferenceType.Sender,
|
||||
2 or 3 => ReferenceType.Receiver,
|
||||
_ => ReferenceType.Unknown,
|
||||
};
|
||||
|
||||
[NotMapped]
|
||||
public string? StatusName
|
||||
=> (Enum.IsDefined(typeof(EnvelopeStatus), Status))
|
||||
? Enum.GetName(typeof(EnvelopeStatus), Status)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE_RECEIVER", Schema = "dbo")]
|
||||
public class EnvelopeReceiver
|
||||
public class EnvelopeReceiver : EnvelopeReceiverBase
|
||||
{
|
||||
[Key]
|
||||
[Column("ENVELOPE_ID")]
|
||||
public int EnvelopeId { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("RECEIVER_ID")]
|
||||
public int ReceiverId { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("SEQUENCE")]
|
||||
public int Sequence { get; set; }
|
||||
|
||||
[Column("NAME", TypeName = "nvarchar(128)")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
|
||||
public string? JobTitle { get; set; }
|
||||
|
||||
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
|
||||
public string? CompanyName { get; set; }
|
||||
|
||||
[Column("PRIVATE_MESSAGE", TypeName = "nvarchar(max)")]
|
||||
public string? PrivateMessage { get; set; }
|
||||
|
||||
[Column("ACCESS_CODE", TypeName = "nvarchar(64)")]
|
||||
public string? AccessCode { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
public DateTime AddedWhen { get; set; }
|
||||
|
||||
[Column("CHANGED_WHEN", TypeName = "datetime")]
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
|
||||
[ForeignKey("EnvelopeId")]
|
||||
public Envelope? Envelope { get; set; }
|
||||
|
||||
|
||||
58
EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs
Normal file
58
EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE_RECEIVER", Schema = "dbo")]
|
||||
public class EnvelopeReceiverBase : IUnique<(int Envelope, int Receiver)>
|
||||
{
|
||||
[Key]
|
||||
[Column("ENVELOPE_ID")]
|
||||
public int EnvelopeId { get; set; }
|
||||
|
||||
[Key]
|
||||
[Column("RECEIVER_ID")]
|
||||
public int ReceiverId { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("SEQUENCE")]
|
||||
public int Sequence { get; set; }
|
||||
|
||||
[Column("NAME", TypeName = "nvarchar(128)")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
|
||||
public string? JobTitle { get; set; }
|
||||
|
||||
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
|
||||
public string? CompanyName { get; set; }
|
||||
|
||||
[Column("PRIVATE_MESSAGE", TypeName = "nvarchar(max)")]
|
||||
public string? PrivateMessage { get; set; }
|
||||
|
||||
[Column("ACCESS_CODE", TypeName = "nvarchar(64)")]
|
||||
public string? AccessCode { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
public DateTime AddedWhen { get; set; }
|
||||
|
||||
[Column("CHANGED_WHEN", TypeName = "datetime")]
|
||||
public DateTime? ChangedWhen { get; set; }
|
||||
|
||||
[Column("PHONE_NUMBER")]
|
||||
[StringLength(20)]
|
||||
[RegularExpression(@"^\+[0-9]+$", ErrorMessage = "Phone number must start with '+' followed by digits.")]
|
||||
public string? PhoneNumber { get; set; }
|
||||
|
||||
[Column("TFA_ENABLED", TypeName = "bit")]
|
||||
public bool TFAEnabled { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
|
||||
|
||||
[NotMapped]
|
||||
public bool HasPhoneNumber => PhoneNumber is not null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE_RECEIVER_READ_ONLY")]
|
||||
public class EnvelopeReceiverReadOnly : IUnique<long>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
[Column("GUID")]
|
||||
public long Id { get; init; }
|
||||
|
||||
[Column("ENVELOPE_ID")]
|
||||
[Required]
|
||||
public long EnvelopeId { get; init; }
|
||||
|
||||
//TODO: remove NotMapped attribute when EnvelopeId data type is standardized
|
||||
[NotMapped]
|
||||
public Envelope? Envelope { get; set; }
|
||||
|
||||
[Column("RECEIVER_MAIL")]
|
||||
[Required]
|
||||
[StringLength(250)]
|
||||
[TemplatePlaceholder("NAME_RECEIVER")]
|
||||
public required string ReceiverMail { get; init; }
|
||||
|
||||
[Column("DATE_VALID")]
|
||||
[Required]
|
||||
public DateTime DateValid { get; init; }
|
||||
|
||||
[Column("ADDED_WHO")]
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public required string AddedWho { get; init; }
|
||||
|
||||
public Receiver? Receiver { get; init; }
|
||||
|
||||
[Column("ADDED_WHEN")]
|
||||
[Required]
|
||||
public DateTime AddedWhen { get; init; }
|
||||
|
||||
[Column("CHANGED_WHO")]
|
||||
[StringLength(100)]
|
||||
public string? ChangedWho { get; init; }
|
||||
|
||||
[Column("CHANGED_WHEN")]
|
||||
public DateTime? ChangedWhen { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
using System;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_ENVELOPE_TYPE", Schema = "dbo")]
|
||||
public class EnvelopeType
|
||||
public class EnvelopeType : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -15,10 +14,10 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[Column("TITLE", TypeName = "nvarchar(128)")]
|
||||
public string Title { get; set; }
|
||||
public required string Title { get; set; }
|
||||
|
||||
[Column("LANGUAGE", TypeName = "nvarchar(5)")]
|
||||
public string Language { get; set; }
|
||||
public string? Language { get; set; }
|
||||
|
||||
[Column("EXPIRES_DAYS")]
|
||||
public int? ExpiresDays { get; set; }
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_RECEIVER", Schema = "dbo")]
|
||||
public class Receiver
|
||||
public class Receiver : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -22,5 +23,13 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
[Required]
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
public DateTime AddedWhen { get; set; }
|
||||
|
||||
[Column("TOTP_SECRET_KEY", TypeName = "nvarchar(MAX)")]
|
||||
public string? TotpSecretkey { get; set; }
|
||||
|
||||
[Column("TOTP_EXPIRATION", TypeName = "datetime")]
|
||||
public DateTime? TotpExpiration { get; set; }
|
||||
|
||||
public IEnumerable<EnvelopeReceiver>? EnvelopeReceivers { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using DigitalData.Core.Abstractions;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Domain.Entities
|
||||
{
|
||||
[Table("TBSIG_USER_RECEIVER", Schema = "dbo")]
|
||||
public class UserReceiver
|
||||
public class UserReceiver : IUnique<int>
|
||||
{
|
||||
[Key]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@@ -21,16 +22,16 @@ namespace EnvelopeGenerator.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[Column("NAME", TypeName = "nvarchar(128)")]
|
||||
public string Name { get; set; }
|
||||
public required string Name { get; set; }
|
||||
|
||||
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
|
||||
public string CompanyName { get; set; }
|
||||
public string? CompanyName { get; set; }
|
||||
|
||||
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
|
||||
public string JobTitle { get; set; }
|
||||
public string? JobTitle { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("ADDED_WHEN", TypeName = "datetime")]
|
||||
public DateTime AddedWhen { get; set; }
|
||||
public required DateTime AddedWhen { get; init; }
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="1.0.0" />
|
||||
<PackageReference Include="UserManager.Domain" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace EnvelopeGenerator.Domain.HttpResponse
|
||||
{
|
||||
public class GtxMessagingResponse : Dictionary<string, object?> { }
|
||||
}
|
||||
@@ -1,12 +1,9 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text;
|
||||
using System.Text;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.Application
|
||||
namespace EnvelopeGenerator.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for decoding and extracting information from an envelope receiver ID.
|
||||
/// </summary>
|
||||
public static class EnvelopeGeneratorExtensions
|
||||
public static class DecodingExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates whether a given string is a correctly formatted Base-64 encoded string.
|
||||
@@ -67,6 +64,40 @@ namespace EnvelopeGenerator.Application
|
||||
return input.IndexOf('=') == -1; // No padding allowed except at the end
|
||||
}
|
||||
|
||||
public static bool TryDecode(this string encodedKey, out string[] decodedKeys)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] bytes = Convert.FromBase64String(encodedKey);
|
||||
string decodedString = Encoding.UTF8.GetString(bytes);
|
||||
decodedKeys = decodedString.Split(new string[] { "::" }, StringSplitOptions.None);
|
||||
return true;
|
||||
}
|
||||
catch(ArgumentNullException) { }
|
||||
catch (FormatException) { }
|
||||
catch(ArgumentException) { }
|
||||
|
||||
decodedKeys = Array.Empty<string>();
|
||||
return false;
|
||||
}
|
||||
|
||||
public static EncodeType GetEncodeType(this string[] decodedKeys) => decodedKeys.Length switch
|
||||
{
|
||||
2 => EncodeType.EnvelopeReceiver,
|
||||
3 => long.TryParse(decodedKeys[1], out var _) ? EncodeType.EnvelopeReceiverReadOnly : EncodeType.Undefined,
|
||||
_ => EncodeType.Undefined,
|
||||
};
|
||||
|
||||
public static (string? EnvelopeUuid, string? ReceiverSignature) ParseEnvelopeReceiverId(this string[] decodedKeys)
|
||||
=> decodedKeys.GetEncodeType() == EncodeType.EnvelopeReceiver
|
||||
? (EnvelopeUuid: decodedKeys[0], ReceiverSignature: decodedKeys[1])
|
||||
: throw new InvalidOperationException("Attempted to convert a decoded other than type EnvelopeReceiver to EnvelopeReceiver.");
|
||||
|
||||
public static long ParseReadOnlyId(this string[] decodedKeys)
|
||||
=> decodedKeys.GetEncodeType() == EncodeType.EnvelopeReceiverReadOnly
|
||||
? long.Parse(decodedKeys[1])
|
||||
: throw new InvalidOperationException("Attempted to convert a decoded other than type EnvelopeReceiver to EnvelopeReceiver. ");
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the envelope receiver ID and extracts the envelope UUID and receiver signature.
|
||||
/// </summary>
|
||||
@@ -79,7 +110,7 @@ namespace EnvelopeGenerator.Application
|
||||
return (null, null);
|
||||
}
|
||||
byte[] bytes = Convert.FromBase64String(envelopeReceiverId);
|
||||
string decodedString = System.Text.Encoding.UTF8.GetString(bytes);
|
||||
string decodedString = Encoding.UTF8.GetString(bytes);
|
||||
string[] parts = decodedString.Split(new string[] { "::" }, StringSplitOptions.None);
|
||||
|
||||
if (parts.Length > 1)
|
||||
@@ -88,6 +119,22 @@ namespace EnvelopeGenerator.Application
|
||||
return (string.Empty, string.Empty);
|
||||
}
|
||||
|
||||
public static long? DecodeEnvelopeReceiverReadOnlyId(this string envelopeReceiverReadOnlyId)
|
||||
{
|
||||
if (!envelopeReceiverReadOnlyId.IsBase64String())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
byte[] bytes = Convert.FromBase64String(envelopeReceiverReadOnlyId);
|
||||
string decodedString = System.Text.Encoding.UTF8.GetString(bytes);
|
||||
string[] parts = decodedString.Split(new string[] { "::" }, StringSplitOptions.None);
|
||||
|
||||
if (parts.Length > 2)
|
||||
return long.TryParse(parts[1], out long readOnlyId) ? readOnlyId : null;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the envelope UUID from the decoded envelope receiver ID.
|
||||
/// </summary>
|
||||
@@ -101,48 +148,5 @@ namespace EnvelopeGenerator.Application
|
||||
/// <param name="envelopeReceiverId">The base64 encoded string to decode.</param>
|
||||
/// <returns>The receiver signature.</returns>
|
||||
public static string? GetReceiverSignature(this string envelopeReceiverId) => envelopeReceiverId.DecodeEnvelopeReceiverId().ReceiverSignature;
|
||||
|
||||
public static string EncodeEnvelopeReceiverId(this (string envelopeUuid, string receiverSignature) input)
|
||||
{
|
||||
string combinedString = $"{input.envelopeUuid}::{input.receiverSignature}";
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(combinedString);
|
||||
string base64String = Convert.ToBase64String(bytes);
|
||||
|
||||
return base64String;
|
||||
}
|
||||
|
||||
public static void LogEnvelopeError(this ILogger logger, string envelopeReceiverId, Exception? exception = null, string? message = null, params object?[] args)
|
||||
{
|
||||
var sb = new StringBuilder().AppendLine(envelopeReceiverId.DecodeEnvelopeReceiverId().ToTitle());
|
||||
|
||||
if (message is not null)
|
||||
sb.AppendLine(message);
|
||||
|
||||
if(exception is null)
|
||||
logger.Log(LogLevel.Error, sb.ToString(), args);
|
||||
else
|
||||
logger.Log(LogLevel.Error, exception, sb.AppendLine(exception.Message).ToString(), args);
|
||||
}
|
||||
|
||||
public static void LogEnvelopeError(this ILogger logger, string? uuid, string? signature = null, Exception? exception = null, string? message = null, params object?[] args)
|
||||
{
|
||||
var sb = new StringBuilder($"Envelope Uuid: {uuid}");
|
||||
|
||||
if(signature is not null)
|
||||
sb.AppendLine().Append($"Receiver Signature: {signature}");
|
||||
|
||||
if (message is not null)
|
||||
sb.AppendLine().Append(message);
|
||||
|
||||
if (exception is null)
|
||||
logger.Log(LogLevel.Error, sb.ToString(), args);
|
||||
else
|
||||
logger.Log(LogLevel.Error, exception, sb.ToString(), args);
|
||||
}
|
||||
|
||||
public static string ToTitle(this (string? UUID, string? Signature) envelopeReceiverTuple)
|
||||
{
|
||||
return $"UUID is {envelopeReceiverTuple.UUID} and signature is {envelopeReceiverTuple.Signature}";
|
||||
}
|
||||
}
|
||||
}
|
||||
30
EnvelopeGenerator.Extensions/EncodingExtensions.cs
Normal file
30
EnvelopeGenerator.Extensions/EncodingExtensions.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text;
|
||||
|
||||
namespace EnvelopeGenerator.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for decoding and extracting information from an envelope receiver ID.
|
||||
/// </summary>
|
||||
public static class EncodingExtensions
|
||||
{
|
||||
public static string EncodeEnvelopeReceiverId(this long readOnlyId)
|
||||
{
|
||||
//The random number is used as a salt to increase security but it is not saved in the database.
|
||||
string combinedString = $"{Random.Shared.Next()}::{readOnlyId}::{Random.Shared.Next()}";
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(combinedString);
|
||||
string base64String = Convert.ToBase64String(bytes);
|
||||
|
||||
return base64String;
|
||||
}
|
||||
|
||||
public static string EncodeEnvelopeReceiverId(this (string envelopeUuid, string receiverSignature) input)
|
||||
{
|
||||
string combinedString = $"{input.envelopeUuid}::{input.receiverSignature}";
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(combinedString);
|
||||
string base64String = Convert.ToBase64String(bytes);
|
||||
|
||||
return base64String;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.19" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
|
||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
42
EnvelopeGenerator.Extensions/LoggerExtensions.cs
Normal file
42
EnvelopeGenerator.Extensions/LoggerExtensions.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text;
|
||||
|
||||
namespace EnvelopeGenerator.Extensions
|
||||
{
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
public static void LogEnvelopeError(this ILogger logger, string envelopeReceiverId, Exception? exception = null, string? message = null, params object?[] args)
|
||||
{
|
||||
var sb = new StringBuilder().AppendLine(envelopeReceiverId.DecodeEnvelopeReceiverId().ToTitle());
|
||||
|
||||
if (message is not null)
|
||||
sb.AppendLine(message);
|
||||
|
||||
if (exception is null)
|
||||
logger.Log(LogLevel.Error, sb.ToString(), args);
|
||||
else
|
||||
logger.Log(LogLevel.Error, exception, sb.AppendLine(exception.Message).ToString(), args);
|
||||
}
|
||||
|
||||
public static void LogEnvelopeError(this ILogger logger, string? uuid, string? signature = null, Exception? exception = null, string? message = null, params object?[] args)
|
||||
{
|
||||
var sb = new StringBuilder($"Envelope Uuid: {uuid}");
|
||||
|
||||
if (signature is not null)
|
||||
sb.AppendLine().Append($"Receiver Signature: {signature}");
|
||||
|
||||
if (message is not null)
|
||||
sb.AppendLine().Append(message);
|
||||
|
||||
if (exception is null)
|
||||
logger.Log(LogLevel.Error, sb.ToString(), args);
|
||||
else
|
||||
logger.Log(LogLevel.Error, exception, sb.ToString(), args);
|
||||
}
|
||||
|
||||
public static string ToTitle(this (string? UUID, string? Signature) envelopeReceiverTuple)
|
||||
{
|
||||
return $"UUID is {envelopeReceiverTuple.UUID} and signature is {envelopeReceiverTuple.Signature}";
|
||||
}
|
||||
}
|
||||
}
|
||||
14
EnvelopeGenerator.Extensions/StringExtension.cs
Normal file
14
EnvelopeGenerator.Extensions/StringExtension.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using OtpNet;
|
||||
|
||||
namespace EnvelopeGenerator.Extensions
|
||||
{
|
||||
public static class StringExtension
|
||||
{
|
||||
public static bool IsValidTotp(this string totp, string secret)
|
||||
{
|
||||
var secret_bytes = Base32Encoding.ToBytes(secret);
|
||||
var secret_totp = new Totp(secret_bytes);
|
||||
return secret_totp.VerifyTotp(totp, out _, VerificationWindow.RfcSpecifiedNetworkDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Text.Encodings.Web;
|
||||
|
||||
namespace EnvelopeGenerator.Web
|
||||
namespace EnvelopeGenerator.Extensions
|
||||
{
|
||||
public static class XSSExtensions
|
||||
{
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user