From 30f93f2439e29de82c3e376f4f73468c004f69ee Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 21 Nov 2024 11:46:15 +0100 Subject: [PATCH 001/104] feat(GTXMessagingService): initialisiert mit Konfigurationsoption --- .../Configurations/GTXMessagingConfig.cs | 7 +++++++ .../Services/GTXMessagingService.cs | 15 +++++++++++++++ EnvelopeGenerator.Web/appsettings.json | 3 +++ 3 files changed, 25 insertions(+) create mode 100644 EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs create mode 100644 EnvelopeGenerator.Application/Services/GTXMessagingService.cs diff --git a/EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs b/EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs new file mode 100644 index 00000000..45f9934b --- /dev/null +++ b/EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs @@ -0,0 +1,7 @@ +namespace EnvelopeGenerator.Application.Configurations +{ + public class GTXMessagingConfig + { + public required string AuthKey { get; init; } + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs new file mode 100644 index 00000000..ee2b1db5 --- /dev/null +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -0,0 +1,15 @@ +using EnvelopeGenerator.Application.Configurations; +using Microsoft.Extensions.Options; + +namespace EnvelopeGenerator.Application.Services +{ + public class GTXMessagingService + { + private readonly string _authKey; + + public GTXMessagingService(IOptions options) + { + _authKey = options.Value.AuthKey; + } + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 7f37fbf3..6b2aaaf8 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -125,5 +125,8 @@ "[SIGNATURE_TYPE]": "signieren", "[REASON]": "" } + }, + "GTXMessagingConfig": { + "AuthKey": "ep$?A!Gs" } } \ No newline at end of file From 949001791c70aa454829d449dffe29a51f8de20b Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 21 Nov 2024 17:22:21 +0100 Subject: [PATCH 002/104] refactor: Umbenennung von GTX in Gtx und GTXMessagingConfig in SmsParams --- .../Configurations/GTXMessagingConfig.cs | 7 ------- .../Configurations/GtxMessaging/SmsParams.cs | 7 +++++++ .../Services/GTXMessagingService.cs | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs create mode 100644 EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs diff --git a/EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs b/EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs deleted file mode 100644 index 45f9934b..00000000 --- a/EnvelopeGenerator.Application/Configurations/GTXMessagingConfig.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace EnvelopeGenerator.Application.Configurations -{ - public class GTXMessagingConfig - { - public required string AuthKey { get; init; } - } -} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs new file mode 100644 index 00000000..04500ea7 --- /dev/null +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -0,0 +1,7 @@ +namespace EnvelopeGenerator.Application.Configurations.GtxMessaging +{ + public class SmsParams + { + public required string AuthKey { get; init; } + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index ee2b1db5..acfa76d6 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,15 +1,15 @@ -using EnvelopeGenerator.Application.Configurations; +using EnvelopeGenerator.Application.Configurations.GtxMessaging; using Microsoft.Extensions.Options; namespace EnvelopeGenerator.Application.Services { - public class GTXMessagingService + public class GtxMessagingService { - private readonly string _authKey; + private readonly SmsParams _smsParams; - public GTXMessagingService(IOptions options) + public GtxMessagingService(IOptions smsParamsOptions) { - _authKey = options.Value.AuthKey; + _smsParams = smsParamsOptions.Value; } } } \ No newline at end of file From d55233061dd34472164cc9ca3d35ae2a67d6e78c Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 21 Nov 2024 18:25:14 +0100 Subject: [PATCH 003/104] =?UTF-8?q?feat:=20erweitere=20`SmsParams`=20um=20?= =?UTF-8?q?zus=C3=A4tzliche=20Eigenschaften=20f=C3=BCr=20die=20SMS-API-Int?= =?UTF-8?q?egration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Neue erforderliche Eigenschaft `Endpoint` hinzugefügt, mit einem Standardwert für den GTX Messaging REST-API-Endpunkt. - Optionale Eigenschaften wie `Format`, `Accept`, `ContentType` und SMS-spezifische Parameter (`From`, `Texts`, `DlrMask` usw.) hinzugefügt, um API-Anforderungen zu erfüllen. - XML-Dokumentation mit API-Referenzlink aktualisiert, um besseren Kontext zu bieten. - TODO hinzugefügt, um Regex-Validierung in `init`-Methoden zu implementieren und Eingabefehler zu reduzieren. --- .../Configurations/GtxMessaging/SmsParams.cs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index 04500ea7..1de22bb0 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -1,7 +1,50 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging { + /// + /// https://www.gtx-messaging.com/en/api-docs/sms-rest-api/ + /// public class SmsParams { + //TODO: Add a regex check to init methods to reduce the chance of errors. + public required string Endpoint { get; init; } = "https://rest.gtx-messaging.net/smsc/sendsms"; + + // path params public required string AuthKey { get; init; } + + public string? Format { get; init; } + + // header params + public string? Accept { get; init; } + + public string? ContentType { get; init; } + + // query params + public required string From { get; init; } + + public required Dictionary Texts { get; init; } + + public int? DlrMask { get; init; } + + public string? DlrUrl { get; init; } + + public string? Udh { get; init; } + + public int? Dcs { get; init; } + + public int? MClass { get; init; } + + public int? MWI { get; init; } + + public int? Coding { get; init; } + + public string? Charset { get; init; } + + public int? Validity { get; init; } + + public DateTime? ValidityTime { get; init; } + + public int? Deferred { get; init; } + + public DateTime? DeferredTime { get; init; } } } \ No newline at end of file From b76ebd2abc6e2576f506207716733a190476167b Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 22 Nov 2024 14:57:20 +0100 Subject: [PATCH 004/104] =?UTF-8?q?chore:=20Aktualisierung=20von=20Core.Ab?= =?UTF-8?q?straction=20auf=202.1.0=20=20-=20Core.Client=20zur=20Anwendungs?= =?UTF-8?q?schicht=20hinzuf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EnvelopeGenerator.Application.csproj | 3 ++- EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj | 2 +- .../EnvelopeGenerator.GeneratorAPI.csproj | 2 +- .../EnvelopeGenerator.Infrastructure.csproj | 2 +- EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj index f1267868..6bec01fe 100644 --- a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj +++ b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj @@ -12,8 +12,9 @@ - + + diff --git a/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj b/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj index 3480802f..cd66fb31 100644 --- a/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj +++ b/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj b/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj index 2684ed2c..940fcb65 100644 --- a/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj +++ b/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj b/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj index f295ff69..7cbf572f 100644 --- a/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj +++ b/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index 0d04bfa5..aff9f6b6 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -46,7 +46,7 @@ - + From 18ef1d19b5ca20b2e54be8573c43fe0150fb281a Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 22 Nov 2024 15:20:19 +0100 Subject: [PATCH 005/104] feat(GtxMessagingService): Eingespritzter Client.IHttpClientService --- .../Configurations/GtxMessaging/SmsParams.cs | 10 +++++++--- .../Services/GTXMessagingService.cs | 9 +++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index 1de22bb0..f9efd3ad 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -1,12 +1,16 @@ -namespace EnvelopeGenerator.Application.Configurations.GtxMessaging +using DigitalData.Core.Abstractions.Client; + +namespace EnvelopeGenerator.Application.Configurations.GtxMessaging { /// /// https://www.gtx-messaging.com/en/api-docs/sms-rest-api/ /// - public class SmsParams + public class SmsParams : IHttpClientOptions { //TODO: Add a regex check to init methods to reduce the chance of errors. - public required string Endpoint { get; init; } = "https://rest.gtx-messaging.net/smsc/sendsms"; + public string Uri { get; set; } = "https://rest.gtx-messaging.net"; + + public string Path { get; set; } = "smsc/sendsms"; // path params public required string AuthKey { get; init; } diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index acfa76d6..46148ad1 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,4 +1,6 @@ -using EnvelopeGenerator.Application.Configurations.GtxMessaging; +using DigitalData.Core.Abstractions.Client; +using DigitalData.Core.Client; +using EnvelopeGenerator.Application.Configurations.GtxMessaging; using Microsoft.Extensions.Options; namespace EnvelopeGenerator.Application.Services @@ -7,9 +9,12 @@ namespace EnvelopeGenerator.Application.Services { private readonly SmsParams _smsParams; - public GtxMessagingService(IOptions smsParamsOptions) + private readonly IHttpClientService _smsClient; + + public GtxMessagingService(IOptions smsParamsOptions, HttpClientService smsClient) { _smsParams = smsParamsOptions.Value; + _smsClient = smsClient; } } } \ No newline at end of file From 5da306acd35f741969917b003bbe32230b709728 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 22 Nov 2024 15:37:59 +0100 Subject: [PATCH 006/104] =?UTF-8?q?feat(GtxMessagingService):=20SendSms-Me?= =?UTF-8?q?thode=20initialisiert=20und=20Authentifizierungspfad=20hinzugef?= =?UTF-8?q?=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configurations/GtxMessaging/SmsParams.cs | 2 ++ .../Services/GTXMessagingService.cs | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index f9efd3ad..c57d65f5 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -50,5 +50,7 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging public int? Deferred { get; init; } public DateTime? DeferredTime { get; init; } + + internal string AuthPath => Format is null ? AuthKey : string.Join('/', AuthKey, Format); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 46148ad1..43ad6934 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,5 +1,5 @@ using DigitalData.Core.Abstractions.Client; -using DigitalData.Core.Client; +using DigitalData.Core.DTO; using EnvelopeGenerator.Application.Configurations.GtxMessaging; using Microsoft.Extensions.Options; @@ -11,10 +11,19 @@ namespace EnvelopeGenerator.Application.Services private readonly IHttpClientService _smsClient; - public GtxMessagingService(IOptions smsParamsOptions, HttpClientService smsClient) + private readonly string _authPath; + + public GtxMessagingService(IOptions smsParamsOptions, IHttpClientService smsClient) { _smsParams = smsParamsOptions.Value; _smsClient = smsClient; + + _authPath = _smsParams.AuthPath; + } + + public async Task SendSms() + { + await _smsClient.FetchAsync(path: _authPath); } } } \ No newline at end of file From 6e6f3fd2ede237c6a8cfc67e9c16a5a67c05db00 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 11:55:09 +0100 Subject: [PATCH 007/104] chore: Aktualisierung von Core.Abstraction auf 2.2.0 --- .../EnvelopeGenerator.GeneratorAPI.csproj | 2 +- .../EnvelopeGenerator.Infrastructure.csproj | 2 +- EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj b/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj index 940fcb65..c534c3d3 100644 --- a/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj +++ b/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj b/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj index 7cbf572f..709a805d 100644 --- a/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj +++ b/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index aff9f6b6..7bb840c0 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -46,7 +46,7 @@ - + From ed808397777ebf4f09559820113293b9d28439ec Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 12:47:30 +0100 Subject: [PATCH 008/104] feat(SmsParams): Aktualisiert, um IHttpClientOptions zu implementieren --- .../Configurations/GtxMessaging/SmsParams.cs | 45 ++----------------- .../EnvelopeGenerator.Application.csproj | 2 +- .../Services/GTXMessagingService.cs | 13 +----- 3 files changed, 7 insertions(+), 53 deletions(-) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index c57d65f5..ca7a34d5 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -8,49 +8,12 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging public class SmsParams : IHttpClientOptions { //TODO: Add a regex check to init methods to reduce the chance of errors. - public string Uri { get; set; } = "https://rest.gtx-messaging.net"; + public required string Uri { get; init; } - public string Path { get; set; } = "smsc/sendsms"; + public string? Path { get; init; } - // path params - public required string AuthKey { get; init; } + public IEnumerable>? Headers { get; init; } - public string? Format { get; init; } - - // header params - public string? Accept { get; init; } - - public string? ContentType { get; init; } - - // query params - public required string From { get; init; } - - public required Dictionary Texts { get; init; } - - public int? DlrMask { get; init; } - - public string? DlrUrl { get; init; } - - public string? Udh { get; init; } - - public int? Dcs { get; init; } - - public int? MClass { get; init; } - - public int? MWI { get; init; } - - public int? Coding { get; init; } - - public string? Charset { get; init; } - - public int? Validity { get; init; } - - public DateTime? ValidityTime { get; init; } - - public int? Deferred { get; init; } - - public DateTime? DeferredTime { get; init; } - - internal string AuthPath => Format is null ? AuthKey : string.Join('/', AuthKey, Format); + public IEnumerable>? QueryParams { get; init; } } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj index 6bec01fe..17aa1124 100644 --- a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj +++ b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj @@ -12,7 +12,7 @@ - + diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 43ad6934..7044140f 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,29 +1,20 @@ using DigitalData.Core.Abstractions.Client; -using DigitalData.Core.DTO; using EnvelopeGenerator.Application.Configurations.GtxMessaging; -using Microsoft.Extensions.Options; namespace EnvelopeGenerator.Application.Services { public class GtxMessagingService { - private readonly SmsParams _smsParams; - private readonly IHttpClientService _smsClient; - private readonly string _authPath; - - public GtxMessagingService(IOptions smsParamsOptions, IHttpClientService smsClient) + public GtxMessagingService(IHttpClientService smsClient) { - _smsParams = smsParamsOptions.Value; _smsClient = smsClient; - - _authPath = _smsParams.AuthPath; } public async Task SendSms() { - await _smsClient.FetchAsync(path: _authPath); + await _smsClient.FetchAsync(); } } } \ No newline at end of file From 132acd35cc3d476ed8a1e18e9dc528dac5998ae7 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 13:01:12 +0100 Subject: [PATCH 009/104] =?UTF-8?q?feat(GtxMessagingService):=20Empf=C3=A4?= =?UTF-8?q?nger-=20und=20Nachrichteneingaben=20zur=20SendSms-Methode=20?= =?UTF-8?q?=C3=BCber=20SMS-Parameter=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configurations/GtxMessaging/SmsParams.cs | 5 ++++- .../Services/GTXMessagingService.cs | 13 ++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index ca7a34d5..a2faf739 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -7,7 +7,6 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging /// public class SmsParams : IHttpClientOptions { - //TODO: Add a regex check to init methods to reduce the chance of errors. public required string Uri { get; init; } public string? Path { get; init; } @@ -15,5 +14,9 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging public IEnumerable>? Headers { get; init; } public IEnumerable>? QueryParams { get; init; } + + public string RecipientQueryParamName { get; init; } = "from"; + + public string MessageQueryParamName { get; init; } = "text"; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 7044140f..81a03545 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,5 +1,6 @@ using DigitalData.Core.Abstractions.Client; using EnvelopeGenerator.Application.Configurations.GtxMessaging; +using Microsoft.Extensions.Options; namespace EnvelopeGenerator.Application.Services { @@ -7,14 +8,20 @@ namespace EnvelopeGenerator.Application.Services { private readonly IHttpClientService _smsClient; - public GtxMessagingService(IHttpClientService smsClient) + private readonly SmsParams _smsParams; + + public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions) { _smsClient = smsClient; + _smsParams = smsParamsOptions.Value; } - public async Task SendSms() + public async Task SendSms(string recipient, string message) { - await _smsClient.FetchAsync(); + await _smsClient.FetchAsync(queryParams: new Dictionary() { + { _smsParams.RecipientQueryParamName, recipient }, + { _smsParams.MessageQueryParamName, message } + }); } } } \ No newline at end of file From 4a62ab0c5675a122b002a934d4a33911fa9037da Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 13:01:43 +0100 Subject: [PATCH 010/104] feat(GtxMessagingService): Umbenennung von SendSms in SendSmsAsync --- EnvelopeGenerator.Application/Services/GTXMessagingService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 81a03545..c8e5090f 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -16,7 +16,7 @@ namespace EnvelopeGenerator.Application.Services _smsParams = smsParamsOptions.Value; } - public async Task SendSms(string recipient, string message) + public async Task SendSmsAsync(string recipient, string message) { await _smsClient.FetchAsync(queryParams: new Dictionary() { { _smsParams.RecipientQueryParamName, recipient }, From 33e99f584adbd3c32f456d428b20fbcd66d38761 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 13:07:39 +0100 Subject: [PATCH 011/104] feat(IMessagingService): Initialisiert und implementiert in GtxMessagingService --- .../Contracts/IMessagingService.cs | 7 +++++++ .../Services/GTXMessagingService.cs | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 EnvelopeGenerator.Application/Contracts/IMessagingService.cs diff --git a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs new file mode 100644 index 00000000..ff84a5f5 --- /dev/null +++ b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs @@ -0,0 +1,7 @@ +namespace EnvelopeGenerator.Application.Contracts +{ + public interface IMessagingService + { + public Task SendSmsAsync(string recipient, string message); + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index c8e5090f..12208a6d 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,10 +1,11 @@ using DigitalData.Core.Abstractions.Client; using EnvelopeGenerator.Application.Configurations.GtxMessaging; +using EnvelopeGenerator.Application.Contracts; using Microsoft.Extensions.Options; namespace EnvelopeGenerator.Application.Services { - public class GtxMessagingService + public class GtxMessagingService : IMessagingService { private readonly IHttpClientService _smsClient; From 2943fe0e2d06b07f1b43db1681b2e4e0fe05b203 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 13:10:43 +0100 Subject: [PATCH 012/104] =?UTF-8?q?refactor(DIExtensions):=20Aktualisiert,?= =?UTF-8?q?=20um=20TryAddScoped=20anstelle=20von=20AddScoped=20f=C3=BCr=20?= =?UTF-8?q?sicherere=20DI-Injektion=20zu=20verwenden.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/DIExtensions.cs | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/EnvelopeGenerator.Application/DIExtensions.cs b/EnvelopeGenerator.Application/DIExtensions.cs index c8179fa6..ea51c7db 100644 --- a/EnvelopeGenerator.Application/DIExtensions.cs +++ b/EnvelopeGenerator.Application/DIExtensions.cs @@ -7,6 +7,7 @@ using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Repositories; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace EnvelopeGenerator.Application { @@ -15,36 +16,36 @@ namespace EnvelopeGenerator.Application public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration dispatcherConfigSection, IConfiguration mailConfigSection) { //Inject CRUD Service and repositoriesad - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); //Auto mapping profiles services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly); From de6d4b9dd83f755f2814b069e9f74fff9f368682 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 13:25:22 +0100 Subject: [PATCH 013/104] =?UTF-8?q?feat(DIExtensions):=20HTTP-Client-Diens?= =?UTF-8?q?t=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/DIExtensions.cs | 9 +++++++-- .../EnvelopeGenerator.Application.csproj | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.Application/DIExtensions.cs b/EnvelopeGenerator.Application/DIExtensions.cs index ea51c7db..8b8bcec3 100644 --- a/EnvelopeGenerator.Application/DIExtensions.cs +++ b/EnvelopeGenerator.Application/DIExtensions.cs @@ -8,12 +8,14 @@ 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; namespace EnvelopeGenerator.Application { public static class DIExtensions { - public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration dispatcherConfigSection, IConfiguration mailConfigSection) + public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfigurationSection dispatcherConfigSection, IConfigurationSection mailConfigSection, IConfigurationSection smsConfigSection) { //Inject CRUD Service and repositoriesad services.TryAddScoped(); @@ -54,11 +56,14 @@ namespace EnvelopeGenerator.Application services.Configure(dispatcherConfigSection); services.Configure(mailConfigSection); + services.AddHttpClientService(smsConfigSection); + return services; } public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration config) => services.AddEnvelopeGenerator( dispatcherConfigSection: config.GetSection("DispatcherConfig"), - mailConfigSection: config.GetSection("MailConfig")); + mailConfigSection: config.GetSection("MailConfig"), + smsConfigSection: config.GetSection("SmsConfig")); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj index 17aa1124..f283256f 100644 --- a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj +++ b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj @@ -14,7 +14,7 @@ - + From ec206ab33a42f207618848f0c27d7df11cbf1652 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 13:27:09 +0100 Subject: [PATCH 014/104] =?UTF-8?q?feat(DIExtensions):=20Gtx-Nachrichtendi?= =?UTF-8?q?enst=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/DIExtensions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/EnvelopeGenerator.Application/DIExtensions.cs b/EnvelopeGenerator.Application/DIExtensions.cs index 8b8bcec3..ecbef1aa 100644 --- a/EnvelopeGenerator.Application/DIExtensions.cs +++ b/EnvelopeGenerator.Application/DIExtensions.cs @@ -57,6 +57,7 @@ namespace EnvelopeGenerator.Application services.Configure(mailConfigSection); services.AddHttpClientService(smsConfigSection); + services.TryAddSingleton(); return services; } From d23b8b91874a178456379122b01ef9905eba9694 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 13:32:50 +0100 Subject: [PATCH 015/104] feat(TestMessagingController): initialized --- .../Test/TestMessagingController.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs diff --git a/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs new file mode 100644 index 00000000..b61e3569 --- /dev/null +++ b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs @@ -0,0 +1,23 @@ +using EnvelopeGenerator.Application.Contracts; +using Microsoft.AspNetCore.Mvc; + +namespace EnvelopeGenerator.Web.Controllers.Test +{ + [Route("api/[controller]")] + [ApiController] + public class TestMessagingController : ControllerBase + { + private readonly IMessagingService _service; + + public TestMessagingController(IMessagingService service) + { + _service = service; + } + + public async Task SendAsync(string recipient, string message) + { + await _service.SendSmsAsync(recipient: recipient, message: message); + return Ok(); + } + } +} \ No newline at end of file From d3104500d4adc27278e374013084005b21ac02f1 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 14:08:47 +0100 Subject: [PATCH 016/104] =?UTF-8?q?refactor(Application):=20Aufr=C3=BCstun?= =?UTF-8?q?g=20von=20Core.Client=20auf=202.0.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EnvelopeGenerator.Application.csproj | 2 +- .../Controllers/Test/TestMessagingController.cs | 1 + EnvelopeGenerator.Web/appsettings.json | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj index f283256f..a3a50b9d 100644 --- a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj +++ b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj @@ -14,7 +14,7 @@ - + diff --git a/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs index b61e3569..de1abd80 100644 --- a/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs +++ b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs @@ -14,6 +14,7 @@ namespace EnvelopeGenerator.Web.Controllers.Test _service = service; } + [HttpPost] public async Task SendAsync(string recipient, string message) { await _service.SendSmsAsync(recipient: recipient, message: message); diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 6b2aaaf8..c17bd5a2 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -128,5 +128,13 @@ }, "GTXMessagingConfig": { "AuthKey": "ep$?A!Gs" + }, + "SmsConfig": { + "Uri": "https://rest.gtx-messaging.net", + "Path": "smsc/sendsms/f566f7e5-bdf2-4a9a-bf52-ed88215a432e/json", + "Headers": {}, + "QueryParams": { + "from": "signFLOW Portal" + } } } \ No newline at end of file From da06daf7763fa1ecc89f97d3e350bf0299d6fa34 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 14:13:34 +0100 Subject: [PATCH 017/104] =?UTF-8?q?refactor(GtxMessagingService):=20Option?= =?UTF-8?q?en=20f=C3=BCr=20generische=20und=20dynamische=20Antworttypen=20?= =?UTF-8?q?zur=20SendSmsAsync-Methode=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IMessagingService.cs | 4 +++- .../Services/GTXMessagingService.cs | 9 ++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs index ff84a5f5..09048206 100644 --- a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs +++ b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs @@ -2,6 +2,8 @@ { public interface IMessagingService { - public Task SendSmsAsync(string recipient, string message); + public Task SendSmsAsync(string recipient, string message); + + public Task SendSmsAsync(string recipient, string message); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 12208a6d..407d5908 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,4 +1,5 @@ using DigitalData.Core.Abstractions.Client; +using DigitalData.Core.Client; using EnvelopeGenerator.Application.Configurations.GtxMessaging; using EnvelopeGenerator.Application.Contracts; using Microsoft.Extensions.Options; @@ -17,12 +18,14 @@ namespace EnvelopeGenerator.Application.Services _smsParams = smsParamsOptions.Value; } - public async Task SendSmsAsync(string recipient, string message) + public Task SendSmsAsync(string recipient, string message) => SendSmsAsync(recipient: recipient, message: message); + + public async Task SendSmsAsync(string recipient, string message) { - await _smsClient.FetchAsync(queryParams: new Dictionary() { + return await _smsClient.FetchAsync(queryParams: new Dictionary() { { _smsParams.RecipientQueryParamName, recipient }, { _smsParams.MessageQueryParamName, message } - }); + }).ThenAsync(res => res.Json()); } } } \ No newline at end of file From f2ee509727f55b5d563fb444c8001354a57c3b90 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 14:40:52 +0100 Subject: [PATCH 018/104] chore: Upgrade von Core.Abstractions 2.2.1 und Core.Client auf 2.0.2 --- .../Configurations/GtxMessaging/SmsParams.cs | 6 +++--- .../EnvelopeGenerator.Application.csproj | 4 ++-- EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj | 2 +- .../EnvelopeGenerator.GeneratorAPI.csproj | 2 +- .../EnvelopeGenerator.Infrastructure.csproj | 2 +- .../Controllers/Test/TestMessagingController.cs | 4 ++-- EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index a2faf739..1f452cf2 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -11,11 +11,11 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging public string? Path { get; init; } - public IEnumerable>? Headers { get; init; } + public Dictionary? Headers { get; init; } - public IEnumerable>? QueryParams { get; init; } + public Dictionary? QueryParams { get; init; } - public string RecipientQueryParamName { get; init; } = "from"; + public string RecipientQueryParamName { get; init; } = "to"; public string MessageQueryParamName { get; init; } = "text"; } diff --git a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj index a3a50b9d..08fbb9fd 100644 --- a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj +++ b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj @@ -12,9 +12,9 @@ - + - + diff --git a/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj b/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj index cd66fb31..50561806 100644 --- a/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj +++ b/EnvelopeGenerator.Domain/EnvelopeGenerator.Domain.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj b/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj index c534c3d3..51efca53 100644 --- a/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj +++ b/EnvelopeGenerator.GeneratorAPI/EnvelopeGenerator.GeneratorAPI.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj b/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj index 709a805d..146af618 100644 --- a/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj +++ b/EnvelopeGenerator.Infrastructure/EnvelopeGenerator.Infrastructure.csproj @@ -7,7 +7,7 @@ - + diff --git a/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs index de1abd80..d7a6ecdd 100644 --- a/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs +++ b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs @@ -17,8 +17,8 @@ namespace EnvelopeGenerator.Web.Controllers.Test [HttpPost] public async Task SendAsync(string recipient, string message) { - await _service.SendSmsAsync(recipient: recipient, message: message); - return Ok(); + var res = await _service.SendSmsAsync(recipient: recipient, message: message); + return res is null? StatusCode(StatusCodes.Status500InternalServerError) : Ok(res); } } } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index 7bb840c0..34d344a4 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -46,7 +46,7 @@ - + From 9c431ddf56bfd15c3d850daaea8c3f933f9f6b67 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 14:58:32 +0100 Subject: [PATCH 019/104] =?UTF-8?q?refactor(Config):=20DocumentPathDmz,=20?= =?UTF-8?q?ExportPathDmz=20und=20DocumentPathMoveAftsend=20sowohl=20in=20d?= =?UTF-8?q?er=20Entit=C3=A4t=20als=20auch=20im=20DTO=20entfernt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/DTOs/ConfigDto.cs | 7 +++---- EnvelopeGenerator.Domain/Entities/Config.cs | 15 +++------------ .../Services/EnvelopeOldService.cs | 7 ------- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/EnvelopeGenerator.Application/DTOs/ConfigDto.cs b/EnvelopeGenerator.Application/DTOs/ConfigDto.cs index f96f131d..2dc76824 100644 --- a/EnvelopeGenerator.Application/DTOs/ConfigDto.cs +++ b/EnvelopeGenerator.Application/DTOs/ConfigDto.cs @@ -1,4 +1,5 @@ using DigitalData.Core.Abstractions; +using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json.Serialization; namespace EnvelopeGenerator.Application.DTOs @@ -8,11 +9,9 @@ namespace EnvelopeGenerator.Application.DTOs int SendingProfile, string SignatureHost, string ExternalProgramName, - string ExportPath, - string DocumentPathDmz, - string ExportPathDmz, - string DocumentPathMoveAftsend) : IUnique + string ExportPath) : IUnique { + [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."); diff --git a/EnvelopeGenerator.Domain/Entities/Config.cs b/EnvelopeGenerator.Domain/Entities/Config.cs index 6621beb5..0f5d48e5 100644 --- a/EnvelopeGenerator.Domain/Entities/Config.cs +++ b/EnvelopeGenerator.Domain/Entities/Config.cs @@ -1,6 +1,7 @@ using DigitalData.Core.Abstractions; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; namespace EnvelopeGenerator.Domain.Entities { @@ -23,19 +24,9 @@ namespace EnvelopeGenerator.Domain.Entities [Column("EXPORT_PATH", TypeName = "nvarchar(256)")] public string? ExportPath { get; init; } - [Column("DOCUMENT_PATH_DMZ", TypeName = "nvarchar(512)")] - [Required] - public string? DocumentPathDmz { get; init; } - - [Column("EXPORT_PATH_DMZ", TypeName = "nvarchar(512)")] - [Required] - public required string ExportPathDmz { get; init; } - - [Column("DOCUMENT_PATH_MOVE_AFTSEND", TypeName = "nvarchar(512)")] - [Required] - public required string DocumentPathMoveAftsend { get; init; } - [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."); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Services/EnvelopeOldService.cs b/EnvelopeGenerator.Web/Services/EnvelopeOldService.cs index f8786918..8dcd4d61 100644 --- a/EnvelopeGenerator.Web/Services/EnvelopeOldService.cs +++ b/EnvelopeGenerator.Web/Services/EnvelopeOldService.cs @@ -98,13 +98,6 @@ namespace EnvelopeGenerator.Web.Services //if documenet_path_dmz is existing in config, replace the path with it var config = await _configService.ReadDefaultAsync(); - if (config.DocumentPathDmz is not null && config.DocumentPathDmz != string.Empty) - foreach (var doc in envelope.Documents) - { - doc.Filepath = doc.Filepath.Replace(config.DocumentPath, config.DocumentPathDmz); - } - - return new() { Receiver = receiver, From 1f57914f9ec66e41476a6614b73a0cc83ee42f05 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 15:12:48 +0100 Subject: [PATCH 020/104] =?UTF-8?q?refactor(=5FLayout.cshtml):=20aktualisi?= =?UTF-8?q?ert,=20um=20Datenschutz=20und=20die=20Website=20der=20Digital?= =?UTF-8?q?=20Data=20GmbH=20bei=20Klick=20in=20einem=20neuen=20Tab=20zu=20?= =?UTF-8?q?=C3=B6ffnen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml b/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml index ecef6a3b..34b53040 100644 --- a/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml +++ b/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml @@ -79,7 +79,7 @@ @Html.AntiForgeryToken() \ No newline at end of file From 360bb9b3d882038e37f44a33dc68959b7eebfb80 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 15:24:18 +0100 Subject: [PATCH 021/104] =?UTF-8?q?refactor(=5Flayout.cshtml):=20Datenschu?= =?UTF-8?q?tz-Link=20in=20der=20Fu=C3=9Fzeile=20aktualisiert,=20unterst?= =?UTF-8?q?=C3=BCtzt=20mehrere=20Sprachen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/Resources/Resource.de-DE.resx | 3 +++ EnvelopeGenerator.Application/Resources/Resource.en-US.resx | 3 +++ EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml | 2 +- EnvelopeGenerator.Web/WebKey.cs | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx index 244fbc28..b86a15c3 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx @@ -180,6 +180,9 @@ Dokument erfordert einen Zugriffscode + + Datenschutz + Weitergeleitet von {0}. Gültig bis {1}. diff --git a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx index b99951ec..5509c519 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx @@ -180,6 +180,9 @@ Document requires an access code + + Privacy + Forwarded by {0}. Valid until {1}. diff --git a/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml b/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml index 34b53040..62be76b2 100644 --- a/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml +++ b/EnvelopeGenerator.Web/Views/Shared/_Layout.cshtml @@ -97,7 +97,7 @@ } - Datenschutz + @_localizer[WebKey.Privacy] \ No newline at end of file diff --git a/EnvelopeGenerator.Web/WebKey.cs b/EnvelopeGenerator.Web/WebKey.cs index d87c179e..d7507b68 100644 --- a/EnvelopeGenerator.Web/WebKey.cs +++ b/EnvelopeGenerator.Web/WebKey.cs @@ -36,5 +36,6 @@ public static readonly string WelcomeToTheESignPortal = nameof(WelcomeToTheESignPortal); public static readonly string ViewDoc = nameof(ViewDoc); public static readonly string HomePageDescription = nameof(HomePageDescription); + public static readonly string Privacy = nameof(Privacy); } } \ No newline at end of file From 62dcb4152606c0a52ece27cf8725dbbc5a8441eb Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 15:37:28 +0100 Subject: [PATCH 022/104] =?UTF-8?q?Refactor:=20Unn=C3=B6tige=20alte=20Fu?= =?UTF-8?q?=C3=9Fzeilen=20aus=20den=20Ansichten=20=E2=80=9EUmschlag=20abge?= =?UTF-8?q?laufen=E2=80=9C,=20=E2=80=9EAbgelehnt=E2=80=9C=20und=20?= =?UTF-8?q?=E2=80=9ESigniert=E2=80=9C=20entfernt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Views/Home/EnvelopeExpired.cshtml | 3 +-- EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml | 3 +-- EnvelopeGenerator.Web/Views/Home/EnvelopeSigned.cshtml | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeExpired.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeExpired.cshtml index 7ba52d25..843acfa4 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeExpired.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeExpired.cshtml @@ -20,5 +20,4 @@

Der Zeitraum für die gemeinsame Nutzung von Dokumenten ist abgelaufen.

- - \ No newline at end of file + \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml index 8ba4a6b4..f7663271 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeRejected.cshtml @@ -68,5 +68,4 @@

- - \ No newline at end of file + \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeSigned.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeSigned.cshtml index 5d0d7379..67cd10ff 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeSigned.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeSigned.cshtml @@ -14,5 +14,4 @@

Sie haben das Dokument signiert. Im Anschluss erhalten Sie eine schriftliche Bestätigung.

- - \ No newline at end of file + \ No newline at end of file From 62d396932dfb596a2cd2ff7b36f4dcb98019e52d Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 15:42:51 +0100 Subject: [PATCH 023/104] refactor(EnvelopeDocument): removed Filename, Filepath and FilenameOriginal properties. --- EnvelopeGenerator.Domain/Entities/EnvelopeDocument.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/EnvelopeGenerator.Domain/Entities/EnvelopeDocument.cs b/EnvelopeGenerator.Domain/Entities/EnvelopeDocument.cs index 85d9ce77..97723f0a 100644 --- a/EnvelopeGenerator.Domain/Entities/EnvelopeDocument.cs +++ b/EnvelopeGenerator.Domain/Entities/EnvelopeDocument.cs @@ -16,21 +16,10 @@ namespace EnvelopeGenerator.Domain.Entities [Column("ENVELOPE_ID")] public int EnvelopeId { get; set; } - [Required] - [Column("FILENAME", TypeName = "nvarchar(256)")] - public required string Filename { get; set; } - - [Required] - [Column("FILEPATH", TypeName = "nvarchar(256)")] - public required string Filepath { get; set; } - [Required] [Column("ADDED_WHEN", TypeName = "datetime")] public required DateTime AddedWhen { get; set; } - [Column("FILENAME_ORIGINAL", TypeName = "nvarchar(256)")] - public required string FilenameOriginal { get; set; } - [Column("BYTE_DATA", TypeName = "varbinary(max)")] public byte[]? ByteData { get; init; } From 608d79d35bbe2882f95410152e02f988bdeef7b9 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 25 Nov 2024 15:54:15 +0100 Subject: [PATCH 024/104] chore(Web): upgraded to 2.6.0 --- EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index 34d344a4..cdf7bca1 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -5,7 +5,7 @@ enable enable EnvelopeGenerator.Web - 2.5.0.0 + 2.6.0 Digital Data GmbH Digital Data GmbH EnvelopeGenerator.Web @@ -13,8 +13,8 @@ digital data envelope generator web EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly. Assets\icon.ico - 2.5.0.0 - 2.5.0.0 + 2.6.0 + 2.6.0 Copyright © 2024 Digital Data GmbH. All rights reserved. From 40c25ee111fef12407927e070fc6396b4b041276 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 26 Nov 2024 23:47:42 +0100 Subject: [PATCH 025/104] fix(appsettings): Leerzeichen aus SmsConfig.QueryParams.from entfernt, da vom SMS-Dienst nicht erlaubt --- EnvelopeGenerator.Web/appsettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index c17bd5a2..28b5a7d9 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -134,7 +134,7 @@ "Path": "smsc/sendsms/f566f7e5-bdf2-4a9a-bf52-ed88215a432e/json", "Headers": {}, "QueryParams": { - "from": "signFLOW Portal" + "from": "signFlow" } } } \ No newline at end of file From 168c33bfea74473b28fd59b7161bb003975bd6b8 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 26 Nov 2024 23:58:07 +0100 Subject: [PATCH 026/104] =?UTF-8?q?chore(Application):=20Core.Client=20auf?= =?UTF-8?q?=202.0.3=20hochger=C3=BCstet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EnvelopeGenerator.Application.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj index 08fbb9fd..5cc3a33f 100644 --- a/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj +++ b/EnvelopeGenerator.Application/EnvelopeGenerator.Application.csproj @@ -14,7 +14,7 @@ - + From 941b98b1a4e400e581f725c7be97aa7f6a5116eb Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 27 Nov 2024 15:13:41 +0100 Subject: [PATCH 027/104] =?UTF-8?q?feat(SmsResponse):=20Erstellung=20eines?= =?UTF-8?q?=20Standardantwort-DTOs=20f=C3=BCr=20SMS-Anfragen.=20=20-=20Gtx?= =?UTF-8?q?MessagingResponse=20f=C3=BCr=20rohe=20dynamische=20Antwort=20er?= =?UTF-8?q?stellt.=20=20-=20Mapping-Profil=20hinzuf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IMessagingService.cs | 8 +++---- .../DTOs/Messaging/SmsResponse.cs | 17 ++++++++++++++ .../MappingExtensions,.cs | 11 +++++++++ .../MappingProfiles/BasicDtoMappingProfile.cs | 9 ++++++++ .../Services/GTXMessagingService.cs | 23 ++++++++++++------- .../HttpResponse/GtxMessagingResponse.cs | 4 ++++ .../Test/TestMessagingController.cs | 2 +- 7 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs create mode 100644 EnvelopeGenerator.Application/MappingExtensions,.cs create mode 100644 EnvelopeGenerator.Domain/HttpResponse/GtxMessagingResponse.cs diff --git a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs index 09048206..42ef85fd 100644 --- a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs +++ b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs @@ -1,9 +1,9 @@ -namespace EnvelopeGenerator.Application.Contracts +using EnvelopeGenerator.Application.DTOs.Messaging; + +namespace EnvelopeGenerator.Application.Contracts { public interface IMessagingService { - public Task SendSmsAsync(string recipient, string message); - - public Task SendSmsAsync(string recipient, string message); + public Task SendSmsAsync(string recipient, string message); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs b/EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs new file mode 100644 index 00000000..57528863 --- /dev/null +++ b/EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs @@ -0,0 +1,17 @@ +namespace EnvelopeGenerator.Application.DTOs.Messaging +{ + public record SmsResponse + { + public required bool Ok { get; init; } + + 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; } + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/MappingExtensions,.cs b/EnvelopeGenerator.Application/MappingExtensions,.cs new file mode 100644 index 00000000..e9d6c06f --- /dev/null +++ b/EnvelopeGenerator.Application/MappingExtensions,.cs @@ -0,0 +1,11 @@ +using EnvelopeGenerator.Domain.HttpResponse; + +namespace EnvelopeGenerator.Application +{ + public static class MappingExtensions + { + public static bool Ok(this GtxMessagingResponse gtxMessagingResponse) + => gtxMessagingResponse.TryGetValue("message-status", out var status) + && status?.ToString()?.ToLower() == "ok"; + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs index 18462893..aad668cb 100644 --- a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs +++ b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs @@ -3,8 +3,10 @@ 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.Domain.Entities; +using EnvelopeGenerator.Domain.HttpResponse; namespace EnvelopeGenerator.Application.MappingProfiles { @@ -50,6 +52,13 @@ namespace EnvelopeGenerator.Application.MappingProfiles CreateMap(); CreateMap(); CreateMap(); + + // Messaging mappings + // for GTX messaging + CreateMap() + .ConstructUsing(gtxRes => gtxRes.Ok() + ? new SmsResponse() { Ok = true } + : new SmsResponse() { Ok = false, Errors = gtxRes }); } } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 407d5908..21cbb003 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -1,7 +1,10 @@ -using DigitalData.Core.Abstractions.Client; +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.Domain.HttpResponse; using Microsoft.Extensions.Options; namespace EnvelopeGenerator.Application.Services @@ -11,21 +14,25 @@ namespace EnvelopeGenerator.Application.Services private readonly IHttpClientService _smsClient; private readonly SmsParams _smsParams; - - public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions) + + private readonly IMapper _mapper; + + public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions, IMapper mapper) { _smsClient = smsClient; _smsParams = smsParamsOptions.Value; + _mapper = mapper; } - public Task SendSmsAsync(string recipient, string message) => SendSmsAsync(recipient: recipient, message: message); - - public async Task SendSmsAsync(string recipient, string message) + public async Task SendSmsAsync(string recipient, string message) { - return await _smsClient.FetchAsync(queryParams: new Dictionary() { + return await _smsClient.FetchAsync(queryParams: new Dictionary() + { { _smsParams.RecipientQueryParamName, recipient }, { _smsParams.MessageQueryParamName, message } - }).ThenAsync(res => res.Json()); + }) + .ThenAsync(res => res.Json()) + .ThenAsync(_mapper.Map); } } } \ No newline at end of file diff --git a/EnvelopeGenerator.Domain/HttpResponse/GtxMessagingResponse.cs b/EnvelopeGenerator.Domain/HttpResponse/GtxMessagingResponse.cs new file mode 100644 index 00000000..cc948e52 --- /dev/null +++ b/EnvelopeGenerator.Domain/HttpResponse/GtxMessagingResponse.cs @@ -0,0 +1,4 @@ +namespace EnvelopeGenerator.Domain.HttpResponse +{ + public class GtxMessagingResponse : Dictionary { } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs index d7a6ecdd..b0d6ee7a 100644 --- a/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs +++ b/EnvelopeGenerator.Web/Controllers/Test/TestMessagingController.cs @@ -15,7 +15,7 @@ namespace EnvelopeGenerator.Web.Controllers.Test } [HttpPost] - public async Task SendAsync(string recipient, string message) + public async Task SendAsync(string recipient, string message, bool staticResponse = true) { var res = await _service.SendSmsAsync(recipient: recipient, message: message); return res is null? StatusCode(StatusCodes.Status500InternalServerError) : Ok(res); From fe106c5a8c178dc931d0a213ed0e206afd93c18b Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 27 Nov 2024 17:09:17 +0100 Subject: [PATCH 028/104] =?UTF-8?q?feat(EnvelopeReceiverBase):=20Eigenscha?= =?UTF-8?q?ft=20=E2=80=9ETelefonnummer=E2=80=9C=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs b/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs index ef934a19..8b2e537e 100644 --- a/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs +++ b/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs @@ -41,6 +41,11 @@ namespace EnvelopeGenerator.Domain.Entities [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; } + public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId); } } \ No newline at end of file From 27618a343ef5016996969d7b63279dc6a7e8d637 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 27 Nov 2024 17:35:38 +0100 Subject: [PATCH 029/104] =?UTF-8?q?feat(EnvelopeReceiverService):=20SendSm?= =?UTF-8?q?sAsync=20hinzugef=C3=BCgt,=20um=20SMS=20an=20den=20Benutzer=20?= =?UTF-8?q?=C3=BCber=20die=20Umschlag-Empf=C3=A4nger-ID=20mithilfe=20des?= =?UTF-8?q?=20Messaging-Services=20zu=20senden.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IEnvelopeReceiverService.cs | 4 ++- EnvelopeGenerator.Application/Key.cs | 1 + .../Services/EnvelopeReceiverService.cs | 32 ++++++++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs index 75a897a2..0004238e 100644 --- a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs @@ -1,7 +1,7 @@ using DigitalData.Core.Abstractions.Application; using DigitalData.Core.DTO; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; -using EnvelopeGenerator.Application.DTOs.Receiver; +using EnvelopeGenerator.Application.DTOs.Messaging; using EnvelopeGenerator.Domain.Entities; namespace EnvelopeGenerator.Application.Contracts @@ -30,5 +30,7 @@ namespace EnvelopeGenerator.Application.Contracts Task>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses); Task> ReadLastUsedReceiverNameByMail(string mail); + + Task> SendSmsAsync(string envelopeReceiverId, string message); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Key.cs b/EnvelopeGenerator.Application/Key.cs index 4509d0ea..52f35d19 100644 --- a/EnvelopeGenerator.Application/Key.cs +++ b/EnvelopeGenerator.Application/Key.cs @@ -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); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs index 12b5ea11..0ab6eb7c 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs @@ -9,6 +9,7 @@ using EnvelopeGenerator.Infrastructure.Contracts; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Logging; using EnvelopeGenerator.Extensions; +using EnvelopeGenerator.Application.DTOs.Messaging; namespace EnvelopeGenerator.Application.Services { @@ -16,10 +17,13 @@ namespace EnvelopeGenerator.Application.Services { private readonly IStringLocalizer _localizer; - public EnvelopeReceiverService(IEnvelopeReceiverRepository repository, IStringLocalizer localizer, IMapper mapper) + private readonly IMessagingService _messagingService; + + public EnvelopeReceiverService(IEnvelopeReceiverRepository repository, IStringLocalizer localizer, IMapper mapper, IMessagingService messagingService) : base(repository, mapper) { _localizer = localizer; + _messagingService = messagingService; } public async Task>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true) @@ -135,5 +139,31 @@ namespace EnvelopeGenerator.Application.Services var er = await _repository.ReadLastByReceiver(mail); return er is null ? Result.Fail().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name); } + + public async Task> SendSmsAsync(string envelopeReceiverId, string message) + { + (string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId(); + + if (uuid is null || signature is null) + return Result.Fail() + .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() + .Message(Key.EnvelopeReceiverNotFound); + + if (env_rcv.PhoneNumber is null) + return Result.Fail() + .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); + } } } \ No newline at end of file From 423b2931974ad5837ea6269ee1233d9592fdc655 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 27 Nov 2024 17:46:32 +0100 Subject: [PATCH 030/104] =?UTF-8?q?feat(MessagingService):=20M=C3=B6glichk?= =?UTF-8?q?eit=20hinzugef=C3=BCgt,=20den=20Anbieter=20des=20Messaging-Serv?= =?UTF-8?q?ers=20zu=20benachrichtigen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/Contracts/IMessagingService.cs | 2 ++ EnvelopeGenerator.Application/Services/GTXMessagingService.cs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs index 42ef85fd..84c26e3d 100644 --- a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs +++ b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs @@ -5,5 +5,7 @@ namespace EnvelopeGenerator.Application.Contracts public interface IMessagingService { public Task SendSmsAsync(string recipient, string message); + + string ServiceProvider { get; } } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 21cbb003..68fc78bf 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -22,6 +22,7 @@ namespace EnvelopeGenerator.Application.Services _smsClient = smsClient; _smsParams = smsParamsOptions.Value; _mapper = mapper; + ServiceProvider = GetType().Name.Replace("Service", string.Empty); } public async Task SendSmsAsync(string recipient, string message) @@ -34,5 +35,7 @@ namespace EnvelopeGenerator.Application.Services .ThenAsync(res => res.Json()) .ThenAsync(_mapper.Map); } + + public string ServiceProvider { get; } } } \ No newline at end of file From b4a97abe6bb5b46c530d4d1c9bcd4f2f73d14dba Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 28 Nov 2024 20:46:51 +0100 Subject: [PATCH 031/104] =?UTF-8?q?feat(EnvelopeReceiverBase):=20HasPhoneN?= =?UTF-8?q?umber-Eigenschaft=20sowohl=20zur=20Entit=C3=A4t=20als=20auch=20?= =?UTF-8?q?zum=20DTO=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DTOs/EnvelopeReceiver/EnvelopeReceiverBasicDto.cs | 2 ++ .../{MappingExtensions,.cs => MappingExtensions.cs} | 0 EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs | 4 ++++ 3 files changed, 6 insertions(+) rename EnvelopeGenerator.Application/{MappingExtensions,.cs => MappingExtensions.cs} (100%) diff --git a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverBasicDto.cs b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverBasicDto.cs index 4dfdf6a8..64c5b869 100644 --- a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverBasicDto.cs +++ b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverBasicDto.cs @@ -25,5 +25,7 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver public DateTime AddedWhen { get; init; } public DateTime? ChangedWhen { get; init; } + + public bool HasPhoneNumber { get; init; } } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/MappingExtensions,.cs b/EnvelopeGenerator.Application/MappingExtensions.cs similarity index 100% rename from EnvelopeGenerator.Application/MappingExtensions,.cs rename to EnvelopeGenerator.Application/MappingExtensions.cs diff --git a/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs b/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs index 8b2e537e..7a344170 100644 --- a/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs +++ b/EnvelopeGenerator.Domain/Entities/EnvelopeReceiverBase.cs @@ -46,6 +46,10 @@ namespace EnvelopeGenerator.Domain.Entities [RegularExpression(@"^\+[0-9]+$", ErrorMessage = "Phone number must start with '+' followed by digits.")] public string? PhoneNumber { get; set; } + [NotMapped] public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId); + + [NotMapped] + public bool HasPhoneNumber => PhoneNumber is not null; } } \ No newline at end of file From 0469f057c9f7b920c7599281f0ab74fae468b582 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 28 Nov 2024 21:50:05 +0100 Subject: [PATCH 032/104] =?UTF-8?q?refactor(HomeController):=20Aktualisier?= =?UTF-8?q?t,=20um=20den=20Envelope-Empf=C3=A4nger=20als=20Modell=20zur=20?= =?UTF-8?q?EnvelopeLocked-Ansicht=20hinzuzuf=C3=BCgen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Controllers/HomeController.cs | 7 +++---- .../Views/Home/EnvelopeLocked.cshtml | 12 ++++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index ad5687d7..aebc3eaa 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -18,7 +18,6 @@ using static EnvelopeGenerator.Common.Constants; using Ganss.Xss; using Newtonsoft.Json; using EnvelopeGenerator.Application.DTOs; -using EnvelopeGenerator.Domain.Entities; namespace EnvelopeGenerator.Web.Controllers { @@ -134,9 +133,9 @@ namespace EnvelopeGenerator.Web.Controllers { ViewData["UserCulture"] = _cultures[UserLanguage]; - return await _envRcvService.IsExisting(envelopeReceiverId: envelopeReceiverId).ThenAsync( - Success: isExisting => isExisting ? View().WithData("EnvelopeKey", envelopeReceiverId) : this.ViewEnvelopeNotFound(), - Fail: IActionResult (messages,notices) => + return await _envRcvService.ReadByEnvelopeReceiverIdAsync(envelopeReceiverId: envelopeReceiverId).ThenAsync( + Success: er => View(er).WithData("EnvelopeKey", envelopeReceiverId), + Fail: IActionResult (messages, notices) => { _logger.LogNotice(notices); Response.StatusCode = StatusCodes.Status401Unauthorized; diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index 6738e567..cdc94ccf 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -1,4 +1,6 @@ -@{ +@using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; +@model EnvelopeReceiverDto; +@{ var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string; var logo = _logoOpt.Value; ViewData["Title"] = _localizer[WebKey.DocProtected]; @@ -49,4 +51,10 @@

@_localizer[WebKey.LockedFooterBody]

- \ No newline at end of file + +@if (Model.HasPhoneNumber) +{ + +} \ No newline at end of file From f1ca1e9067ed700bd85b3a7cb32a3a982586a182 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 28 Nov 2024 23:38:51 +0100 Subject: [PATCH 033/104] feat(Auth): Erstellung eines Authentifizierungsmodells anstelle der direkten Verwendung des Zugriffscodes. --- EnvelopeGenerator.Web/Controllers/HomeController.cs | 4 ++-- EnvelopeGenerator.Web/Models/Auth.cs | 4 ++++ EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 EnvelopeGenerator.Web/Models/Auth.cs diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index aebc3eaa..c4662af5 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -150,7 +150,7 @@ namespace EnvelopeGenerator.Web.Controllers } [HttpPost("EnvelopeKey/{envelopeReceiverId}/Locked")] - public async Task LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] string access_code) + public async Task LogInEnvelope([FromRoute] string envelopeReceiverId, [FromForm] Auth auth) { try { @@ -169,7 +169,7 @@ namespace EnvelopeGenerator.Web.Controllers //check access code EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId); - var verification = await _envRcvService.VerifyAccessCodeAsync(uuid: uuid, signature: signature, accessCode: access_code); + var verification = await _envRcvService.VerifyAccessCodeAsync(uuid: uuid, signature: signature, accessCode: auth.AccessCode!); if (verification.IsFailed) { _logger.LogNotice(verification.Notices); diff --git a/EnvelopeGenerator.Web/Models/Auth.cs b/EnvelopeGenerator.Web/Models/Auth.cs new file mode 100644 index 00000000..e557aada --- /dev/null +++ b/EnvelopeGenerator.Web/Models/Auth.cs @@ -0,0 +1,4 @@ +namespace EnvelopeGenerator.Web.Models +{ + public record Auth(string? AccessCode = null); +} diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index cdc94ccf..b79eb7fa 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -27,7 +27,7 @@
- +
-@if (Model.HasPhoneNumber) -{ - -} \ No newline at end of file +
\ No newline at end of file From 44dc7185c6c699900cd5418c05f1b6dd1656b28c Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Thu, 28 Nov 2024 23:57:18 +0100 Subject: [PATCH 035/104] =?UTF-8?q?feat(Auth):=20Getter-Methoden=20zur=20W?= =?UTF-8?q?ertepr=C3=BCfung=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Auth.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Auth.cs b/EnvelopeGenerator.Web/Models/Auth.cs index e557aada..4159fd90 100644 --- a/EnvelopeGenerator.Web/Models/Auth.cs +++ b/EnvelopeGenerator.Web/Models/Auth.cs @@ -1,4 +1,13 @@ namespace EnvelopeGenerator.Web.Models { - public record Auth(string? AccessCode = null); -} + public record Auth(string? AccessCode = null, string? SmsCode = null) + { + public bool HasAccessCode => AccessCode is not null; + + public bool HasSmsCode => SmsCode is not null; + + public bool HasMulti => HasAccessCode && HasSmsCode; + + public bool HasNone => !(HasAccessCode || HasSmsCode); + } +} \ No newline at end of file From d8f74971f31ed15c0a012241141082c71992964e Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 00:26:29 +0100 Subject: [PATCH 036/104] =?UTF-8?q?feat(EnvelopeLocked):=20Der=20Parameter?= =?UTF-8?q?=20viaSms=20wurde=20hinzugef=C3=BCgt,=20um=20die=20Seite=20sowo?= =?UTF-8?q?hl=20f=C3=BCr=20die=20=C3=9Cberpr=C3=BCfung=20des=20Zugangscode?= =?UTF-8?q?s=20als=20auch=20des=20SMS-Codes=20zu=20verwenden.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - accessCodeName und accessCodeLabel wurden aktualisiert, um bedingt zugewiesen zu werden. --- .../Resources/Resource.de-DE.resx | 3 +++ .../Resources/Resource.en-US.resx | 3 +++ EnvelopeGenerator.Web/Controllers/HomeController.cs | 6 ++++++ EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml | 7 +++++-- EnvelopeGenerator.Web/WebKey.cs | 1 + 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx index b86a15c3..fba4b798 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx @@ -177,6 +177,9 @@ Sie haben keinen Zugriffscode erhalten? + + SMS-Code + Dokument erfordert einen Zugriffscode diff --git a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx index 5509c519..357e4a8a 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx @@ -177,6 +177,9 @@ You have not received an access code? + + SMS Code + Document requires an access code diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 2145bc7a..9ab90aa2 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -193,6 +193,12 @@ namespace EnvelopeGenerator.Web.Controllers await _historyService.RecordAsync(er.EnvelopeId, er.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeCorrect); + //check if the user has phone is added + if (er.HasPhoneNumber) + { + return View("EnvelopeLocked").WithData("ViaSms", true); + } + ViewData["EnvelopeKey"] = envelopeReceiverId; //check rejection var rejRcvrs = await _historyService.ReadRejectingReceivers(er.Envelope!.Id); diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index 41e42a27..a3ea477d 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -4,6 +4,9 @@ var logo = _logoOpt.Value; ViewData["Title"] = _localizer[WebKey.DocProtected]; var userCulture = ViewData["UserCulture"] as Culture; + bool viaSms = ViewData["ViaSms"] is bool _viaSms && _viaSms; + var accessCodeName = viaSms ? "smsAccessCode" : "accessCode"; + var accessCodeLabel = viaSms ? _localizer[WebKey.LockedSmsAccessCode] : _localizer[WebKey.LockedAccessCode]; }
@@ -26,8 +29,8 @@
- - + +
-
+
diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.css b/EnvelopeGenerator.Web/wwwroot/css/site.css index 90f162d4..0e01b728 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.css @@ -221,10 +221,15 @@ footer { } .page header .icon.locked { - background-color: #ffc107; + background-color: #ffa407; color: #000; } + .page header .icon.locked.sms-tfa { + background-color: #ff7207; + color: #000; + } + .page header .icon.signed { background-color: #146c43; color: #fff; diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.min.css b/EnvelopeGenerator.Web/wwwroot/css/site.min.css index d10c4ed6..c235c4d3 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.min.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.min.css @@ -1 +1 @@ -.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffc107;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:start;flex-direction:row}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file +.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffa407;color:#000}.page header .icon.locked.sms-tfa{background-color:#ff7207;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:start;flex-direction:row}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file From 28a8e20b639d4f09a21ee4e55f285899f17f31f5 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 00:45:21 +0100 Subject: [PATCH 038/104] =?UTF-8?q?feat(WebKey):=20Lokalisierungstasten=20?= =?UTF-8?q?sms=20tfa=20in=20EnvelopeLocked=20Ansicht=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/WebKey.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/EnvelopeGenerator.Web/WebKey.cs b/EnvelopeGenerator.Web/WebKey.cs index f09a6501..3555be45 100644 --- a/EnvelopeGenerator.Web/WebKey.cs +++ b/EnvelopeGenerator.Web/WebKey.cs @@ -11,12 +11,16 @@ public static readonly string de_DE = nameof(de_DE).Replace("_", "-"); public static readonly string en_US = nameof(en_US).Replace("_", "-"); public static readonly string LockedTitle = nameof(LockedTitle); + public static readonly string LockedSmsTfaTitle = nameof(LockedSmsTfaTitle); public static readonly string LockedBody = nameof(LockedBody); + public static readonly string LockedSmsTfaBody = nameof(LockedSmsTfaBody); public static readonly string LocakedOpen = nameof(LocakedOpen); public static readonly string LockedAccessCode = nameof(LockedAccessCode); public static readonly string LockedSmsAccessCode = nameof(LockedSmsAccessCode); public static readonly string LockedFooterTitle = nameof(LockedFooterTitle); + public static readonly string LockedSmsTfaFooterTitle = nameof(LockedSmsTfaFooterTitle); public static readonly string LockedFooterBody = nameof(LockedFooterBody); + public static readonly string LockedSmsTfaFooterBody = nameof(LockedSmsTfaFooterBody); public static readonly string WrongAccessCode = nameof(WrongAccessCode); public static readonly string SignDoc = nameof(SignDoc); public static readonly string DocRejected = nameof(DocRejected); From a763fd6a244cede08f3ee9f54c9560439e1b8b94 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 01:10:08 +0100 Subject: [PATCH 039/104] =?UTF-8?q?feat(EnvelopeLocked):=20Textk=C3=B6rper?= =?UTF-8?q?=20und=20Fu=C3=9Fzeile=20f=C3=BCr=20SMS-Ansicht=20hinzugef?= =?UTF-8?q?=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/Resource.de-DE.resx | 12 ++++++++++++ .../Resources/Resource.en-US.resx | 12 ++++++++++++ .../Views/Home/EnvelopeLocked.cshtml | 15 +++++++-------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx index fba4b798..4950cd18 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx @@ -180,6 +180,18 @@ SMS-Code + + Wir haben soeben den Zugangscode als SMS an die von Ihnen angegebene Telefonnummer gesendet. + + + 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. + + + Sie haben keine SMS erhalten? + + + 2-Faktor-Authentifizierung + Dokument erfordert einen Zugriffscode diff --git a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx index 357e4a8a..00598290 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx @@ -180,6 +180,18 @@ SMS Code + + We have just sent the access code as an SMS to the phone number you provided. + + + 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. + + + You have not received an SMS? + + + 2-Factor Authentication + Document requires an access code diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index cd41c523..2444bc7b 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -5,8 +5,7 @@ ViewData["Title"] = _localizer[WebKey.DocProtected]; var userCulture = ViewData["UserCulture"] as Culture; bool viaSms = ViewData["ViaSms"] is bool _viaSms && _viaSms; - var accessCodeName = viaSms ? "smsAccessCode" : "accessCode"; - var accessCodeLabel = viaSms ? _localizer[WebKey.LockedSmsAccessCode] : _localizer[WebKey.LockedAccessCode]; + var accessCodeName = viaSms ? "smsCode" : "accessCode"; }
@@ -20,17 +19,17 @@
-

@_localizer[WebKey.LockedTitle]

+

@_localizer[viaSms ? WebKey.LockedSmsTfaTitle : WebKey.LockedTitle]

-

@_localizer[WebKey.LockedBody]

+

@_localizer[viaSms ? WebKey.LockedSmsTfaBody : WebKey.LockedBody]

- - + +
\ No newline at end of file From 6b65fc28fd02a1908e259027d267b0e00cca6a9f Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 09:29:27 +0100 Subject: [PATCH 040/104] refactor(HomeController): log message format more appropriately written --- EnvelopeGenerator.Web/Controllers/HomeController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 9ab90aa2..0321a7d5 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -165,7 +165,7 @@ namespace EnvelopeGenerator.Web.Controllers return Unauthorized(); } - _logger.LogInformation($"Envelope UUID: [{uuid}]\nReceiver Signature: [{signature}]"); + _logger.LogInformation("Envelope UUID: [{uuid}]\nReceiver Signature: [{signature}]", uuid, signature); //check access code EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId); From a1618fc8d0a35f9ec7d7ecde27a8b008d90e8130 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 10:01:28 +0100 Subject: [PATCH 041/104] refactor(HomeController): EnvelopeReceiverSecretDto zur Vereinfachung entfernt und direkt String verwendet --- .../Contracts/IEnvelopeReceiverService.cs | 2 +- .../DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs | 4 ---- .../MappingProfiles/BasicDtoMappingProfile.cs | 1 - .../Services/EnvelopeReceiverService.cs | 4 ++-- 4 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs index 0004238e..88fd8549 100644 --- a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs @@ -11,7 +11,7 @@ namespace EnvelopeGenerator.Application.Contracts Task>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false); - Task>> ReadSecretByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true); + Task>> ReadAccessCodeByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true); Task>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true); diff --git a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs deleted file mode 100644 index 511c6d42..00000000 --- a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver -{ - public record EnvelopeReceiverSecretDto(string? AccessCode) : EnvelopeReceiverDto; -} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs index aad668cb..021eebea 100644 --- a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs +++ b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs @@ -25,7 +25,6 @@ namespace EnvelopeGenerator.Application.MappingProfiles CreateMap(); CreateMap(); CreateMap(); - CreateMap(); CreateMap(); CreateMap(); CreateMap(); diff --git a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs index 0ab6eb7c..7d4c3b9f 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs @@ -38,10 +38,10 @@ namespace EnvelopeGenerator.Application.Services return Result.Success(_mapper.Map>(env_rcvs)); } - public async Task>> ReadSecretByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true) + public async Task>> 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.Map>(env_rcvs)); + return Result.Success(env_rcvs.Select(er => er.AccessCode)); } public async Task> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true) From ec37518245b8516964b424c20997f5bf7302fbbf Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 10:07:09 +0100 Subject: [PATCH 042/104] =?UTF-8?q?feat(EnvelopeReceiverSecretDto):=20Erst?= =?UTF-8?q?ellt=20als=20Erbe=20von=20EnvelopeReceiverDto,=20hinzugef=C3=BC?= =?UTF-8?q?gt=20AccessCode=20und=20PhoneNumber.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs diff --git a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs new file mode 100644 index 00000000..9470766e --- /dev/null +++ b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs @@ -0,0 +1,9 @@ +namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver +{ + public record EnvelopeReceiverSecretDto() : EnvelopeReceiverDto() + { + public string? AccessCode { get; init; } + + public string? PhoneNumber { get; init; } + } +} \ No newline at end of file From e77532ebfd02265b9f6bcedd654b2eed345865f7 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 10:11:33 +0100 Subject: [PATCH 043/104] =?UTF-8?q?feat(EnvelopeReceiverService):=20ReadWi?= =?UTF-8?q?thSecretByUuidSignatureAsync=20zum=20Lesen=20mit=20Zugangscode?= =?UTF-8?q?=20und=20Telefonnummer=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IEnvelopeReceiverService.cs | 2 ++ .../Services/EnvelopeReceiverService.cs | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs index 88fd8549..65834a4d 100644 --- a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs @@ -17,6 +17,8 @@ namespace EnvelopeGenerator.Application.Contracts Task> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true); + Task> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true); + Task> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true); Task> ReadAccessCodeByIdAsync(int envelopeId, int receiverId); diff --git a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs index 7d4c3b9f..cdb35a98 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs @@ -54,6 +54,16 @@ namespace EnvelopeGenerator.Application.Services return Result.Success(_mapper.Map(env_rcv)); } + public async Task> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true) + { + var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver); + if (env_rcv is null) + return Result.Fail() + .Message(Key.EnvelopeReceiverNotFound); + + return Result.Success(_mapper.Map(env_rcv)); + } + public async Task> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true) { (string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId(); From b8d9963fac635408b507ecd2653d0e03629cfd33 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 10:22:11 +0100 Subject: [PATCH 044/104] refactor(HomeController): ReadWithSecretByUuidSignatureAsync implementiert, um alle Informationen in einer einzigen Sql-Transaktion zu erhalten. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Methode hinzugefügt, um geheimes dto in dto zu konvertieren --- .../EnvelopeReceiverSecretDto.cs | 2 ++ .../Controllers/HomeController.cs | 23 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs index 9470766e..ebc529e7 100644 --- a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs +++ b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs @@ -5,5 +5,7 @@ public string? AccessCode { get; init; } public string? PhoneNumber { get; init; } + + public EnvelopeReceiverDto WithoutSecrets => this; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 0321a7d5..b245a210 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -18,6 +18,7 @@ using static EnvelopeGenerator.Common.Constants; using Ganss.Xss; using Newtonsoft.Json; using EnvelopeGenerator.Application.DTOs; +using DigitalData.Core.Client; namespace EnvelopeGenerator.Web.Controllers { @@ -169,36 +170,30 @@ namespace EnvelopeGenerator.Web.Controllers //check access code EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId); - var verification = await _envRcvService.VerifyAccessCodeAsync(uuid: uuid, signature: signature, accessCode: auth.AccessCode!); - if (verification.IsFailed) - { - _logger.LogNotice(verification.Notices); - Response.StatusCode = StatusCodes.Status401Unauthorized; - return View("EnvelopeLocked") - .WithData("ErrorMessage", _localizer[WebKey.WrongAccessCode].Value); - } - return await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync( - SuccessAsync: async er => + return await _envRcvService.ReadWithSecretByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync( + SuccessAsync: async er_secret => { //check the access code verification - if (verification.IsWrong()) + if (er_secret.AccessCode != auth.AccessCode) { //Constants.EnvelopeStatus.AccessCodeIncorrect - await _historyService.RecordAsync(er.EnvelopeId, er.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeIncorrect); + await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeIncorrect); Response.StatusCode = StatusCodes.Status401Unauthorized; return View("EnvelopeLocked") .WithData("ErrorMessage", _localizer[WebKey.WrongAccessCode].Value); } - await _historyService.RecordAsync(er.EnvelopeId, er.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeCorrect); + await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeCorrect); //check if the user has phone is added - if (er.HasPhoneNumber) + if (er_secret.HasPhoneNumber) { return View("EnvelopeLocked").WithData("ViaSms", true); } + var er = er_secret.WithoutSecrets; + ViewData["EnvelopeKey"] = envelopeReceiverId; //check rejection var rejRcvrs = await _historyService.ReadRejectingReceivers(er.Envelope!.Id); From b11f32bd3ce60367a13a299815b71ac42fa014a8 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 11:08:01 +0100 Subject: [PATCH 045/104] =?UTF-8?q?feat:=20CodeGenerator-Service=20mit=20K?= =?UTF-8?q?onfigurationsunterst=C3=BCtzung=20implementiert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CodeGenerator-Service erstellt, der zufällige Codes basierend auf einem konfigurierbaren Zeichensatz generiert. - IOptions für DI-Injektion der Konfigurationseinstellungen integriert. - Lazy-Initialisierung für statische Instanz des CodeGenerators hinzugefügt. - Validierung hinzugefügt, um sicherzustellen, dass die Code-Länge größer als null ist. - Geplante zukünftige Verbesserung: Random als Singleton injizieren, um die Multithreading-Performance zu verbessern. --- .../Configurations/CodeGeneratorConfig.cs | 7 ++++ .../Contracts/ICodeGenerator.cs | 7 ++++ EnvelopeGenerator.Application/DIExtensions.cs | 7 +++- .../Services/CodeGenerator.cs | 37 +++++++++++++++++++ .../Controllers/HomeController.cs | 1 + 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs create mode 100644 EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs create mode 100644 EnvelopeGenerator.Application/Services/CodeGenerator.cs diff --git a/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs b/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs new file mode 100644 index 00000000..d321401e --- /dev/null +++ b/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs @@ -0,0 +1,7 @@ +namespace EnvelopeGenerator.Application.Configurations +{ + public class CodeGeneratorConfig + { + public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs b/EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs new file mode 100644 index 00000000..4a282c66 --- /dev/null +++ b/EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs @@ -0,0 +1,7 @@ +namespace EnvelopeGenerator.Application.Contracts +{ + public interface ICodeGenerator + { + string GenerateCode(int length); + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/DIExtensions.cs b/EnvelopeGenerator.Application/DIExtensions.cs index ecbef1aa..c8dd5eb2 100644 --- a/EnvelopeGenerator.Application/DIExtensions.cs +++ b/EnvelopeGenerator.Application/DIExtensions.cs @@ -15,7 +15,7 @@ namespace EnvelopeGenerator.Application { public static class DIExtensions { - public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfigurationSection dispatcherConfigSection, IConfigurationSection mailConfigSection, IConfigurationSection smsConfigSection) + public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfigurationSection dispatcherConfigSection, IConfigurationSection mailConfigSection, IConfigurationSection smsConfigSection, IConfigurationSection codeGeneratorConfigSection) { //Inject CRUD Service and repositoriesad services.TryAddScoped(); @@ -48,6 +48,7 @@ namespace EnvelopeGenerator.Application services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); + services.TryAddScoped(); //Auto mapping profiles services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly); @@ -55,6 +56,7 @@ namespace EnvelopeGenerator.Application services.Configure(dispatcherConfigSection); services.Configure(mailConfigSection); + services.Configure(codeGeneratorConfigSection); services.AddHttpClientService(smsConfigSection); services.TryAddSingleton(); @@ -65,6 +67,7 @@ namespace EnvelopeGenerator.Application public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration config) => services.AddEnvelopeGenerator( dispatcherConfigSection: config.GetSection("DispatcherConfig"), mailConfigSection: config.GetSection("MailConfig"), - smsConfigSection: config.GetSection("SmsConfig")); + smsConfigSection: config.GetSection("SmsConfig"), + codeGeneratorConfigSection: config.GetSection("CodeGeneratorConfig")); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/CodeGenerator.cs b/EnvelopeGenerator.Application/Services/CodeGenerator.cs new file mode 100644 index 00000000..c09eaf34 --- /dev/null +++ b/EnvelopeGenerator.Application/Services/CodeGenerator.cs @@ -0,0 +1,37 @@ +using EnvelopeGenerator.Application.Configurations; +using EnvelopeGenerator.Application.Contracts; +using Microsoft.Extensions.Options; +using System.Text; + +namespace EnvelopeGenerator.Application.Services +{ + public class CodeGenerator : ICodeGenerator + { + public static Lazy LazyStatic => new(() => new CodeGenerator(Options.Create(new()))); + + public static CodeGenerator Static => LazyStatic.Value; + + private readonly string _charPool = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + public CodeGenerator(IOptions options) + { + _charPool = options.Value.CharPool; + } + + 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(_charPool[random.Next(_charPool.Length)]); + + return passwordBuilder.ToString(); + } + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index b245a210..06db6647 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -192,6 +192,7 @@ namespace EnvelopeGenerator.Web.Controllers return View("EnvelopeLocked").WithData("ViaSms", true); } + //continue the process without important data to minimize security errors. var er = er_secret.WithoutSecrets; ViewData["EnvelopeKey"] = envelopeReceiverId; From 0c81a8661058443606d335f913d7b34fa9f701ea Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 11:13:59 +0100 Subject: [PATCH 046/104] =?UTF-8?q?feat(GtxMessagingService):=20SendSmsCod?= =?UTF-8?q?eAsync=20mit=20Basisfunktionalit=C3=A4t=20als=20Schnittstelleni?= =?UTF-8?q?mplementierung=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IMessagingService.cs | 6 ++++-- .../Services/GTXMessagingService.cs | 13 +++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs index 84c26e3d..0fda64cb 100644 --- a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs +++ b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs @@ -4,8 +4,10 @@ namespace EnvelopeGenerator.Application.Contracts { public interface IMessagingService { - public Task SendSmsAsync(string recipient, string message); - string ServiceProvider { get; } + + Task SendSmsAsync(string recipient, string message); + + Task SendSmsCodeAsync(string recipient); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 68fc78bf..3ced55eb 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -17,12 +17,17 @@ namespace EnvelopeGenerator.Application.Services private readonly IMapper _mapper; - public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions, IMapper mapper) + private readonly ICodeGenerator _codeGen; + + public string ServiceProvider { get; } + + public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator) { _smsClient = smsClient; _smsParams = smsParamsOptions.Value; _mapper = mapper; ServiceProvider = GetType().Name.Replace("Service", string.Empty); + _codeGen = codeGenerator; } public async Task SendSmsAsync(string recipient, string message) @@ -36,6 +41,10 @@ namespace EnvelopeGenerator.Application.Services .ThenAsync(_mapper.Map); } - public string ServiceProvider { get; } + public async Task SendSmsCodeAsync(string recipient) + { + var code = _codeGen.GenerateCode(5); + return await SendSmsAsync(recipient: recipient, message: code); + } } } \ No newline at end of file From b779ef6f0ba940a2c6b4dd42c93c2b1a83daecd8 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 11:16:08 +0100 Subject: [PATCH 047/104] =?UTF-8?q?feat(GtxMessagingService):=20Konfigurie?= =?UTF-8?q?rte=20Codel=C3=A4nge=20=C3=BCber=20ioptions.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Standardmäßig ist sie 5 --- .../Configurations/GtxMessaging/SmsParams.cs | 2 ++ EnvelopeGenerator.Application/Services/GTXMessagingService.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index 1f452cf2..e52e0892 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -18,5 +18,7 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging public string RecipientQueryParamName { get; init; } = "to"; public string MessageQueryParamName { get; init; } = "text"; + + public int CodeLength { get; init; } = 5; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 3ced55eb..2c1edcb7 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -43,7 +43,7 @@ namespace EnvelopeGenerator.Application.Services public async Task SendSmsCodeAsync(string recipient) { - var code = _codeGen.GenerateCode(5); + var code = _codeGen.GenerateCode(_smsParams.CodeLength); return await SendSmsAsync(recipient: recipient, message: code); } } From 9d1a2e7254b9c30a432061f9c8f7065ae2b0ae99 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 12:05:07 +0100 Subject: [PATCH 048/104] =?UTF-8?q?refactor(HomeController):=20SMS-Code=20?= =?UTF-8?q?zum=20Senden=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/DIExtensions.cs | 2 +- .../MappingProfiles/BasicDtoMappingProfile.cs | 1 + .../Controllers/HomeController.cs | 15 ++++++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Application/DIExtensions.cs b/EnvelopeGenerator.Application/DIExtensions.cs index c8dd5eb2..694adb0d 100644 --- a/EnvelopeGenerator.Application/DIExtensions.cs +++ b/EnvelopeGenerator.Application/DIExtensions.cs @@ -48,7 +48,6 @@ namespace EnvelopeGenerator.Application services.TryAddScoped(); services.TryAddScoped(); services.TryAddScoped(); - services.TryAddScoped(); //Auto mapping profiles services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly); @@ -60,6 +59,7 @@ namespace EnvelopeGenerator.Application services.AddHttpClientService(smsConfigSection); services.TryAddSingleton(); + services.TryAddSingleton(); return services; } diff --git a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs index 021eebea..aad668cb 100644 --- a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs +++ b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs @@ -25,6 +25,7 @@ namespace EnvelopeGenerator.Application.MappingProfiles CreateMap(); CreateMap(); CreateMap(); + CreateMap(); CreateMap(); CreateMap(); CreateMap(); diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 06db6647..0f008dd0 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -34,8 +34,8 @@ namespace EnvelopeGenerator.Web.Controllers private readonly Cultures _cultures; private readonly IEnvelopeMailService _mailService; private readonly IEnvelopeReceiverReadOnlyService _readOnlyService; - - public HomeController(EnvelopeOldService envelopeOldService, ILogger logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeHistoryService historyService, IStringLocalizer localizer, IConfiguration configuration, HtmlSanitizer sanitizer, Cultures cultures, IEnvelopeMailService envelopeMailService, IEnvelopeReceiverReadOnlyService readOnlyService) + private readonly IMessagingService _msgService; + public HomeController(EnvelopeOldService envelopeOldService, ILogger logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeHistoryService historyService, IStringLocalizer localizer, IConfiguration configuration, HtmlSanitizer sanitizer, Cultures cultures, IEnvelopeMailService envelopeMailService, IEnvelopeReceiverReadOnlyService readOnlyService, IMessagingService messagingService) { this.envelopeOldService = envelopeOldService; _envRcvService = envelopeReceiverService; @@ -47,6 +47,7 @@ namespace EnvelopeGenerator.Web.Controllers _mailService = envelopeMailService; _logger = logger; _readOnlyService = readOnlyService; + _msgService = messagingService; } [HttpGet("/")] @@ -189,7 +190,15 @@ namespace EnvelopeGenerator.Web.Controllers //check if the user has phone is added if (er_secret.HasPhoneNumber) { - return View("EnvelopeLocked").WithData("ViaSms", true); + var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!); + if(res.Ok) + return View("EnvelopeLocked").WithData("ViaSms", true); + else + { + var res_json = JsonConvert.SerializeObject(res); + _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, message: $"An unexpected error occurred while sending an SMS code. Response: ${res_json}"); + return this.ViewInnerServiceError(); + } } //continue the process without important data to minimize security errors. From 2a963a1861c522b6a2376da95069e7c778064196 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 14:08:07 +0100 Subject: [PATCH 049/104] =?UTF-8?q?feat(Web):=20Verteilter=20Sql=20Server-?= =?UTF-8?q?Cache=20hinzugef=C3=BCgt.=20=20-=20Bat-Datei=20erstellt,=20um?= =?UTF-8?q?=20Tabelle=20f=C3=BCr=20Cache=20zu=20erstellen.=20=20-=20Sql-Da?= =?UTF-8?q?tei=20zum=20Erstellen=20einer=20Tabelle=20f=C3=BCr=20den=20Cach?= =?UTF-8?q?e=20erstellt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Test/TestCacheController.cs | 35 +++++++++++++++++++ .../EnvelopeGenerator.Web.csproj | 7 ++++ EnvelopeGenerator.Web/Program.cs | 8 +++-- .../Scripts/create-sql-cache.bat | 2 ++ .../Scripts/create-sql-cache.sql | 23 ++++++++++++ 5 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 EnvelopeGenerator.Web/Controllers/Test/TestCacheController.cs create mode 100644 EnvelopeGenerator.Web/Scripts/create-sql-cache.bat create mode 100644 EnvelopeGenerator.Web/Scripts/create-sql-cache.sql diff --git a/EnvelopeGenerator.Web/Controllers/Test/TestCacheController.cs b/EnvelopeGenerator.Web/Controllers/Test/TestCacheController.cs new file mode 100644 index 00000000..114aab85 --- /dev/null +++ b/EnvelopeGenerator.Web/Controllers/Test/TestCacheController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Distributed; + +namespace EnvelopeGenerator.Web.Controllers.Test +{ + [Route("api/[controller]")] + [ApiController] + public class TestCacheController : ControllerBase + { + private readonly IDistributedCache _cache; + + public TestCacheController(IDistributedCache cache) + { + _cache = cache; + } + + [HttpPost] + public async Task SetCacheAsync(string key, string value) + { + var options = new DistributedCacheEntryOptions() + .SetAbsoluteExpiration(TimeSpan.FromMinutes(5)); + + await _cache.SetStringAsync(key, value, options); + + return Ok(); + } + + [HttpGet] + public async Task GetCacheAsync(string key) + { + var value = await _cache.GetStringAsync(key); + return value is null ? BadRequest() : Ok(value); + } + } +} diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index cdf7bca1..2d02d4fe 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -57,6 +57,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -120,6 +121,12 @@ True \ + + PreserveNewest + + + PreserveNewest + diff --git a/EnvelopeGenerator.Web/Program.cs b/EnvelopeGenerator.Web/Program.cs index c2c2a23d..167ddaac 100644 --- a/EnvelopeGenerator.Web/Program.cs +++ b/EnvelopeGenerator.Web/Program.cs @@ -1,4 +1,3 @@ -using DigitalData.UserManager.Infrastructure.Repositories; using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Services; using EnvelopeGenerator.Web.Services; @@ -9,7 +8,6 @@ using NLog.Web; using DigitalData.Core.API; using Microsoft.AspNetCore.Authentication.Cookies; using EnvelopeGenerator.Web.Models; -using DigitalData.Core.DTO; using System.Text.Encodings.Web; using Ganss.Xss; using Microsoft.Extensions.Options; @@ -81,6 +79,12 @@ try //AddEF Core dbcontext var connStr = config.GetConnectionString(Key.Default) ?? throw new InvalidOperationException("There is no default connection string in appsettings.json."); builder.Services.AddDbContext(options => options.UseSqlServer(connStr)); + builder.Services.AddDistributedSqlServerCache(options => + { + options.ConnectionString = connStr; + options.SchemaName = "dbo"; + options.TableName = "TBDD_CACHE"; + }); // Add envelope generator services builder.Services.AddEnvelopeGenerator(config); diff --git a/EnvelopeGenerator.Web/Scripts/create-sql-cache.bat b/EnvelopeGenerator.Web/Scripts/create-sql-cache.bat new file mode 100644 index 00000000..138f70e3 --- /dev/null +++ b/EnvelopeGenerator.Web/Scripts/create-sql-cache.bat @@ -0,0 +1,2 @@ +dotnet sql-cache create "CONNECTION_STRING" dbo TBDD_CACHE +pause \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Scripts/create-sql-cache.sql b/EnvelopeGenerator.Web/Scripts/create-sql-cache.sql new file mode 100644 index 00000000..77aa2261 --- /dev/null +++ b/EnvelopeGenerator.Web/Scripts/create-sql-cache.sql @@ -0,0 +1,23 @@ +USE [DD_ECM] +GO + +SET ANSI_NULLS ON +GO + +SET QUOTED_IDENTIFIER ON +GO + +CREATE TABLE [dbo].[TBDD_CACHE]( + [Id] [nvarchar](449) NOT NULL, + [Value] [varbinary](max) NOT NULL, + [ExpiresAtTime] [datetimeoffset](7) NOT NULL, + [SlidingExpirationInSeconds] [bigint] NULL, + [AbsoluteExpiration] [datetimeoffset](7) NULL, +PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +GO + + From cdec5485c621f5f790695112a33c449f752711a7 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Fri, 29 Nov 2024 16:25:20 +0100 Subject: [PATCH 050/104] =?UTF-8?q?feat(GtxMessagingService):=20Zwischensp?= =?UTF-8?q?eicherung=20f=C3=BCr=20SMS-Code=20und=20Ablauf=20des=20SMS-Code?= =?UTF-8?q?s=20mittels=20Envelope-Receiver-ID=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Erweiterungsmethode für Zeitcaching hinzugefügt. --- .../Configurations/GtxMessaging/SmsParams.cs | 15 +++++++ .../Contracts/IMessagingService.cs | 2 +- .../Extensions/CacheExtensions.cs | 43 +++++++++++++++++++ .../{ => Extensions}/DIExtensions.cs | 2 +- .../{ => Extensions}/MappingExtensions.cs | 2 +- .../MappingProfiles/BasicDtoMappingProfile.cs | 1 + .../Services/GTXMessagingService.cs | 36 ++++++++++++++-- EnvelopeGenerator.GeneratorAPI/Program.cs | 2 +- .../Controllers/HomeController.cs | 2 +- EnvelopeGenerator.Web/Program.cs | 1 + 10 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 EnvelopeGenerator.Application/Extensions/CacheExtensions.cs rename EnvelopeGenerator.Application/{ => Extensions}/DIExtensions.cs (98%) rename EnvelopeGenerator.Application/{ => Extensions}/MappingExtensions.cs (85%) diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index e52e0892..e65be8ac 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -1,4 +1,5 @@ using DigitalData.Core.Abstractions.Client; +using Microsoft.Extensions.Caching.Distributed; namespace EnvelopeGenerator.Application.Configurations.GtxMessaging { @@ -20,5 +21,19 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging public string MessageQueryParamName { get; init; } = "text"; public int CodeLength { get; init; } = 5; + + /// + /// Gets the cache key format for SMS codes. + /// The placeholder {0} represents the envelopeReceiverId. + /// + public string CodeCacheKeyFormat { get; init; } = "sms-code-{0}"; + + /// + /// Gets the cache expiration key format for SMS codes. + /// The placeholder {0} represents the envelopeReceiverId. + /// + public string CodeExpirationCacheKeyFormat { get; init; } = "sms-code-expiration-{0}"; + + public TimeSpan CodeCacheValidityPeriod { get; init; } = new(0, 5, 0); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs index 0fda64cb..5940e50d 100644 --- a/EnvelopeGenerator.Application/Contracts/IMessagingService.cs +++ b/EnvelopeGenerator.Application/Contracts/IMessagingService.cs @@ -8,6 +8,6 @@ namespace EnvelopeGenerator.Application.Contracts Task SendSmsAsync(string recipient, string message); - Task SendSmsCodeAsync(string recipient); + Task SendSmsCodeAsync(string recipient, string envelopeReceiverId); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Extensions/CacheExtensions.cs b/EnvelopeGenerator.Application/Extensions/CacheExtensions.cs new file mode 100644 index 00000000..88f8cdce --- /dev/null +++ b/EnvelopeGenerator.Application/Extensions/CacheExtensions.cs @@ -0,0 +1,43 @@ +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Options; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +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 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 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 GetTimeSpanAsync(this IDistributedCache cache, string key) + { + var value = await cache.GetAsync(key); + return value is null ? null : new(BitConverter.ToInt64(value, 0)); + } + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/DIExtensions.cs b/EnvelopeGenerator.Application/Extensions/DIExtensions.cs similarity index 98% rename from EnvelopeGenerator.Application/DIExtensions.cs rename to EnvelopeGenerator.Application/Extensions/DIExtensions.cs index 694adb0d..83a92bd0 100644 --- a/EnvelopeGenerator.Application/DIExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/DIExtensions.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using DigitalData.Core.Client; using EnvelopeGenerator.Application.Configurations.GtxMessaging; -namespace EnvelopeGenerator.Application +namespace EnvelopeGenerator.Application.Extensions { public static class DIExtensions { diff --git a/EnvelopeGenerator.Application/MappingExtensions.cs b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs similarity index 85% rename from EnvelopeGenerator.Application/MappingExtensions.cs rename to EnvelopeGenerator.Application/Extensions/MappingExtensions.cs index e9d6c06f..0d7f19c8 100644 --- a/EnvelopeGenerator.Application/MappingExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs @@ -1,6 +1,6 @@ using EnvelopeGenerator.Domain.HttpResponse; -namespace EnvelopeGenerator.Application +namespace EnvelopeGenerator.Application.Extensions { public static class MappingExtensions { diff --git a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs index aad668cb..403c8bb0 100644 --- a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs +++ b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs @@ -5,6 +5,7 @@ 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; diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 2c1edcb7..3670795b 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -4,7 +4,9 @@ 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 @@ -19,15 +21,21 @@ namespace EnvelopeGenerator.Application.Services private readonly ICodeGenerator _codeGen; + private readonly IDistributedCache _cache; + public string ServiceProvider { get; } - public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator) + private readonly DistributedCacheEntryOptions _codeCacheOptions; + + public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator, IDistributedCache distributedCache) { _smsClient = smsClient; _smsParams = smsParamsOptions.Value; _mapper = mapper; ServiceProvider = GetType().Name.Replace("Service", string.Empty); _codeGen = codeGenerator; + _cache = distributedCache; + _codeCacheOptions = new() { AbsoluteExpirationRelativeToNow = smsParamsOptions.Value.CodeCacheValidityPeriod }; } public async Task SendSmsAsync(string recipient, string message) @@ -41,10 +49,30 @@ namespace EnvelopeGenerator.Application.Services .ThenAsync(_mapper.Map); } - public async Task SendSmsCodeAsync(string recipient) + public async Task SendSmsCodeAsync(string recipient, string envelopeReceiverId) { - var code = _codeGen.GenerateCode(_smsParams.CodeLength); - return await SendSmsAsync(recipient: recipient, message: code); + var code_expiration_key = string.Format(_smsParams.CodeExpirationCacheKeyFormat, envelopeReceiverId); + + var code_key = string.Format(_smsParams.CodeCacheKeyFormat, envelopeReceiverId); + var code = await _cache.GetStringAsync(code_key); + + if (code is null) + { + code = _codeGen.GenerateCode(_smsParams.CodeLength); + + await _cache.SetStringAsync(code_key, code, _codeCacheOptions); + + await _cache.SetDateTimeAsync(code_expiration_key, DateTime.Now + _smsParams.CodeCacheValidityPeriod, _codeCacheOptions); + + return await SendSmsAsync(recipient: recipient, message: code); + } + else + { + var code_expiration = await _cache.GetDateTimeAsync(code_expiration_key); + return code_expiration is null + ? new() { Ok = false } + : new() { Ok = false, AllowedAt = code_expiration }; + } } } } \ No newline at end of file diff --git a/EnvelopeGenerator.GeneratorAPI/Program.cs b/EnvelopeGenerator.GeneratorAPI/Program.cs index d95f039b..5d734ea5 100644 --- a/EnvelopeGenerator.GeneratorAPI/Program.cs +++ b/EnvelopeGenerator.GeneratorAPI/Program.cs @@ -1,7 +1,7 @@ using DigitalData.Core.API; using DigitalData.Core.Application; using DigitalData.UserManager.Application; -using EnvelopeGenerator.Application; +using EnvelopeGenerator.Application.Extensions; using EnvelopeGenerator.Infrastructure; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Localization; diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 0f008dd0..07320bfc 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -190,7 +190,7 @@ namespace EnvelopeGenerator.Web.Controllers //check if the user has phone is added if (er_secret.HasPhoneNumber) { - var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!); + var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId); if(res.Ok) return View("EnvelopeLocked").WithData("ViaSms", true); else diff --git a/EnvelopeGenerator.Web/Program.cs b/EnvelopeGenerator.Web/Program.cs index 167ddaac..fbf24996 100644 --- a/EnvelopeGenerator.Web/Program.cs +++ b/EnvelopeGenerator.Web/Program.cs @@ -15,6 +15,7 @@ using EnvelopeGenerator.Application; using DigitalData.EmailProfilerDispatcher; using EnvelopeGenerator.Infrastructure; using EnvelopeGenerator.Web.Sanitizers; +using EnvelopeGenerator.Application.Extensions; var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); logger.Info("Logging initialized!"); From fa44b82493a3f17e546da1c19dbaf83ec3d2d7f4 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Sat, 30 Nov 2024 01:56:02 +0100 Subject: [PATCH 051/104] =?UTF-8?q?feat(EnvelopeLocked):=20Timer=20mit=20C?= =?UTF-8?q?SS-Konfiguration=20und=20Javascript-Ereignis=20hinzugef=C3=BCgt?= =?UTF-8?q?.=20=20-=20Ablauf=20=C3=BCber=20Home-Controller-Ansichtsdaten?= =?UTF-8?q?=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configurations/CodeGeneratorConfig.cs | 2 +- .../DTOs/Messaging/SmsResponse.cs | 2 ++ .../Services/CodeGenerator.cs | 2 +- .../Services/GTXMessagingService.cs | 9 +++-- .../Controllers/HomeController.cs | 6 ++-- .../EnvelopeGenerator.Web.csproj | 2 +- .../Views/Home/EnvelopeLocked.cshtml | 34 ++++++++++++++++++- EnvelopeGenerator.Web/appsettings.json | 3 +- EnvelopeGenerator.Web/wwwroot/css/site.css | 23 ++++++++++++- .../wwwroot/css/site.min.css | 2 +- .../wwwroot/js/event-binder.js | 26 +++++++++++++- .../wwwroot/js/event-binder.min.js | 2 +- 12 files changed, 99 insertions(+), 14 deletions(-) diff --git a/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs b/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs index d321401e..b44c989a 100644 --- a/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs +++ b/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs @@ -2,6 +2,6 @@ { public class CodeGeneratorConfig { - public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789"; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs b/EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs index 57528863..96b67515 100644 --- a/EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs +++ b/EnvelopeGenerator.Application/DTOs/Messaging/SmsResponse.cs @@ -4,6 +4,8 @@ { 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; diff --git a/EnvelopeGenerator.Application/Services/CodeGenerator.cs b/EnvelopeGenerator.Application/Services/CodeGenerator.cs index c09eaf34..7b3f4b3c 100644 --- a/EnvelopeGenerator.Application/Services/CodeGenerator.cs +++ b/EnvelopeGenerator.Application/Services/CodeGenerator.cs @@ -11,7 +11,7 @@ namespace EnvelopeGenerator.Application.Services public static CodeGenerator Static => LazyStatic.Value; - private readonly string _charPool = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private readonly string _charPool; public CodeGenerator(IOptions options) { diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index 3670795b..be2c1cc9 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -61,10 +61,13 @@ namespace EnvelopeGenerator.Application.Services code = _codeGen.GenerateCode(_smsParams.CodeLength); await _cache.SetStringAsync(code_key, code, _codeCacheOptions); + + var expiration = DateTime.Now + _smsParams.CodeCacheValidityPeriod; + await _cache.SetDateTimeAsync(code_expiration_key, expiration, _codeCacheOptions); - await _cache.SetDateTimeAsync(code_expiration_key, DateTime.Now + _smsParams.CodeCacheValidityPeriod, _codeCacheOptions); - - return await SendSmsAsync(recipient: recipient, message: code); + var res = await SendSmsAsync(recipient: recipient, message: code); + res.Expiration = expiration; + return res; } else { diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 07320bfc..d221bad0 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -191,8 +191,10 @@ namespace EnvelopeGenerator.Web.Controllers if (er_secret.HasPhoneNumber) { var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId); - if(res.Ok) - return View("EnvelopeLocked").WithData("ViaSms", true); + if (res.Ok) + return View("EnvelopeLocked").WithData("ViaSms", true).WithData("Expiration", res.Expiration); + else if (!res.Allowed) + return View("EnvelopeLocked").WithData("ViaSms", true).WithData("Expiration", res.AllowedAt); else { var res_json = JsonConvert.SerializeObject(res); diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index 2d02d4fe..a1f2b5f2 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -47,7 +47,7 @@ - + diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index 2444bc7b..335b2441 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -1,4 +1,5 @@ @using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; +@using Newtonsoft.Json @{ var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string; var logo = _logoOpt.Value; @@ -6,6 +7,7 @@ var userCulture = ViewData["UserCulture"] as Culture; bool viaSms = ViewData["ViaSms"] is bool _viaSms && _viaSms; var accessCodeName = viaSms ? "smsCode" : "accessCode"; + DateTime? expiration = ViewData["Expiration"] is DateTime _expiration ? _expiration : null; }
@@ -35,6 +37,10 @@ login + @if (expiration is not null) + { + + }
@@ -52,4 +58,30 @@

@_localizer[viaSms ? WebKey.LockedSmsTfaFooterBody : WebKey.LockedFooterBody]

-
\ No newline at end of file +
+ \ No newline at end of file diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 28b5a7d9..19d64dd2 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -135,6 +135,7 @@ "Headers": {}, "QueryParams": { "from": "signFlow" - } + }, + "CodeCacheValidityPeriod": "00:10:00" } } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.css b/EnvelopeGenerator.Web/wwwroot/css/site.css index 0e01b728..07ebcce9 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.css @@ -402,14 +402,17 @@ footer#page-footer { .access-code-form-floating { display: flex; - justify-content: start; + justify-content: space-between; flex-direction: row; + align-items: center; } .access-code-form-floating button { align-content: center; border-bottom-left-radius: 0; border-top-left-radius: 0; + margin:0; + height: 100%; } .access-code-form-floating input { @@ -427,6 +430,24 @@ footer#page-footer { height: 2.5rem; } +#sms-timer { + height: 3rem; + display: flex; + align-items: center; + font-family: 'Arial', sans-serif; + font-weight: bold; + color: #ffffff; + background-color: #007bff; + margin: 0 0 0 2rem; + border-radius: 8px; + text-align: center; +} + + #sms-timer:hover { + background-color: #0056b3; + cursor: pointer; + } + /*.flag-dropdown button { height: 100%; }*/ diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.min.css b/EnvelopeGenerator.Web/wwwroot/css/site.min.css index c235c4d3..4adc28ba 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.min.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.min.css @@ -1 +1 @@ -.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffa407;color:#000}.page header .icon.locked.sms-tfa{background-color:#ff7207;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:start;flex-direction:row}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file +.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffa407;color:#000}.page header .icon.locked.sms-tfa{background-color:#ff7207;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:space-between;flex-direction:row;align-items:center}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0;margin:0;height:100%}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}#sms-timer{height:3rem;display:flex;align-items:center;font-family:'Arial',sans-serif;font-weight:bold;color:#fff;background-color:#007bff;margin:0 0 0 2rem;border-radius:8px;text-align:center}#sms-timer:hover{background-color:#0056b3;cursor:pointer}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file diff --git a/EnvelopeGenerator.Web/wwwroot/js/event-binder.js b/EnvelopeGenerator.Web/wwwroot/js/event-binder.js index d36137ed..04c1a5c9 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/event-binder.js +++ b/EnvelopeGenerator.Web/wwwroot/js/event-binder.js @@ -11,7 +11,7 @@ document.querySelectorAll('.email-input').forEach(input => { document.addEventListener('DOMContentLoaded', function () { var dropdownItems = document.querySelectorAll('.culture-dropdown-item'); dropdownItems.forEach(function (item) { - item.addEventListener('click', async function(event) { + item.addEventListener('click', async function (event) { event.preventDefault(); var language = this.getAttribute('data-language'); var flagCode = this.getAttribute('data-flag'); @@ -21,6 +21,30 @@ document.addEventListener('DOMContentLoaded', function () { }); }); +const setTimer = (elementId, expirationTime) => { + const element = document.getElementById(elementId); + + const interval = setInterval(function () { + var now = new Date(); + + var diffInMillis = expirationTime - now; + + if (diffInMillis <= 0) { + element.textContent = "00:00"; + clearInterval(interval); + } + + var minutes = Math.floor(diffInMillis / 1000 / 60); + var seconds = Math.floor((diffInMillis / 1000) % 60); + + var formattedMinutes = minutes.toString().padStart(2, '0'); + var formattedSeconds = seconds.toString().padStart(2, '0'); + + var remainingTime = `${formattedMinutes}:${formattedSeconds}`; + element.textContent = remainingTime; + }, 1000); +} + const bsNotify = (message, options) => alertify.notify( ``, 'custom', diff --git a/EnvelopeGenerator.Web/wwwroot/js/event-binder.min.js b/EnvelopeGenerator.Web/wwwroot/js/event-binder.min.js index 30f6d827..d56f9789 100644 --- a/EnvelopeGenerator.Web/wwwroot/js/event-binder.min.js +++ b/EnvelopeGenerator.Web/wwwroot/js/event-binder.min.js @@ -1 +1 @@ -document.querySelectorAll(".email-input").forEach(n=>{n.addEventListener("input",function(){/^\S+@\S+\.\S+$/.test(this.value)?this.classList.remove("is-invalid"):this.classList.add("is-invalid")})});document.addEventListener("DOMContentLoaded",function(){var n=document.querySelectorAll(".culture-dropdown-item");n.forEach(function(n){n.addEventListener("click",async function(n){n.preventDefault();var t=this.getAttribute("data-language"),i=this.getAttribute("data-flag");document.getElementById("selectedFlag").className="fi "+i+" me-2";await setLanguage(t)})})});const bsNotify=(n,t)=>alertify.notify(``,"custom",t?.delay??5);class Comp{static ActPanel=class{static __Root;static get Root(){Comp.ActPanel.__Root??=document.getElementById("flex-action-panel");return Comp.ActPanel.__Root}static get Elements(){return[...Comp.ActPanel.Root.children]}static get IsHided(){return Comp.ActPanel.Root.style.display=="none"}static set Display(n){Comp.ActPanel.Root.style.display=n;Comp.ActPanel.Elements.forEach(t=>t.style.display=n)}static Toggle(){Comp.ActPanel.Display=Comp.ActPanel.IsHided?"":"none"}};static SignatureProgress=class{static __SignatureCount;static get SignatureCount(){this.__SignatureCount=parseInt(document.getElementById("signature-count").innerText);return this.__SignatureCount}static __SignedCountSpan;static get SignedCountSpan(){this.__SignedCountSpan??=document.getElementById("signed-count");return Comp.SignatureProgress.__SignedCountSpan}static __signedCount=0;static get SignedCount(){return this.__signedCount}static set SignedCount(n){this.__signedCount=n;const t=(n/this.SignatureCount)*100;this.SignedCountBar.style.setProperty("--progress-width",t+"%");this.SignedCountSpan.innerText=n.toString()}static __SignedCountBar;static get SignedCountBar(){this.__SignedCountBar??=document.getElementById("signed-count-bar");return this.__SignedCountBar}};static __ShareBackdrop;static get ShareBackdrop(){return Comp.__ShareBackdrop??=new bootstrap.Modal(document.getElementById("shareBackdrop")),this.__ShareBackdrop}} \ No newline at end of file +document.querySelectorAll(".email-input").forEach(n=>{n.addEventListener("input",function(){/^\S+@\S+\.\S+$/.test(this.value)?this.classList.remove("is-invalid"):this.classList.add("is-invalid")})});document.addEventListener("DOMContentLoaded",function(){var n=document.querySelectorAll(".culture-dropdown-item");n.forEach(function(n){n.addEventListener("click",async function(n){n.preventDefault();var t=this.getAttribute("data-language"),i=this.getAttribute("data-flag");document.getElementById("selectedFlag").className="fi "+i+" me-2";await setLanguage(t)})})});const setTimer=(n,t)=>{const i=document.getElementById(n),r=setInterval(function(){var u=new Date,n=t-u;n<=0&&(i.textContent="00:00",clearInterval(r));var f=Math.floor(n/6e4),e=Math.floor(n/1e3%60),o=f.toString().padStart(2,"0"),s=e.toString().padStart(2,"0"),h=`${o}:${s}`;i.textContent=h},1e3)},bsNotify=(n,t)=>alertify.notify(``,"custom",t?.delay??5);class Comp{static ActPanel=class{static __Root;static get Root(){Comp.ActPanel.__Root??=document.getElementById("flex-action-panel");return Comp.ActPanel.__Root}static get Elements(){return[...Comp.ActPanel.Root.children]}static get IsHided(){return Comp.ActPanel.Root.style.display=="none"}static set Display(n){Comp.ActPanel.Root.style.display=n;Comp.ActPanel.Elements.forEach(t=>t.style.display=n)}static Toggle(){Comp.ActPanel.Display=Comp.ActPanel.IsHided?"":"none"}};static SignatureProgress=class{static __SignatureCount;static get SignatureCount(){this.__SignatureCount=parseInt(document.getElementById("signature-count").innerText);return this.__SignatureCount}static __SignedCountSpan;static get SignedCountSpan(){this.__SignedCountSpan??=document.getElementById("signed-count");return Comp.SignatureProgress.__SignedCountSpan}static __signedCount=0;static get SignedCount(){return this.__signedCount}static set SignedCount(n){this.__signedCount=n;const t=(n/this.SignatureCount)*100;this.SignedCountBar.style.setProperty("--progress-width",t+"%");this.SignedCountSpan.innerText=n.toString()}static __SignedCountBar;static get SignedCountBar(){this.__SignedCountBar??=document.getElementById("signed-count-bar");return this.__SignedCountBar}};static __ShareBackdrop;static get ShareBackdrop(){return Comp.__ShareBackdrop??=new bootstrap.Modal(document.getElementById("shareBackdrop")),this.__ShareBackdrop}} \ No newline at end of file From 40a21a0b897269a24614513b96056ed9e06135d9 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Sat, 30 Nov 2024 03:46:40 +0100 Subject: [PATCH 052/104] =?UTF-8?q?feat(EnvelopeReceiverCache):=20zum=20Ab?= =?UTF-8?q?rufen=20und=20Setzen=20von=20Caches=20=C3=BCber=20Envelope=20Re?= =?UTF-8?q?ceiver=20unter=20Verwendung=20von=20Standard-Schl=C3=BCsselw?= =?UTF-8?q?=C3=B6rtern=20als=20Schnittstellenimplementierung=20erstellt.?= =?UTF-8?q?=20=20-=20Erstellte=20Optionen.=20=20-=20Zu=20DI=20hinzugef?= =?UTF-8?q?=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EnvelopeReceiverCacheParams.cs | 19 +++++++ .../Configurations/GtxMessaging/SmsParams.cs | 14 ------ .../Contracts/IEnvelopeReceiverCache.cs | 17 +++++++ .../Extensions/DIExtensions.cs | 7 ++- .../Services/EnvelopeReceiverCache.cs | 50 +++++++++++++++++++ .../Services/GTXMessagingService.cs | 25 +++------- EnvelopeGenerator.Web/appsettings.json | 5 +- 7 files changed, 101 insertions(+), 36 deletions(-) create mode 100644 EnvelopeGenerator.Application/Configurations/EnvelopeReceiverCacheParams.cs create mode 100644 EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverCache.cs create mode 100644 EnvelopeGenerator.Application/Services/EnvelopeReceiverCache.cs diff --git a/EnvelopeGenerator.Application/Configurations/EnvelopeReceiverCacheParams.cs b/EnvelopeGenerator.Application/Configurations/EnvelopeReceiverCacheParams.cs new file mode 100644 index 00000000..b8ab323e --- /dev/null +++ b/EnvelopeGenerator.Application/Configurations/EnvelopeReceiverCacheParams.cs @@ -0,0 +1,19 @@ +namespace EnvelopeGenerator.Application.Configurations +{ + public class EnvelopeReceiverCacheParams + { + /// + /// Gets the cache key format for SMS codes. + /// The placeholder {0} represents the envelopeReceiverId. + /// + public string CodeCacheKeyFormat { get; init; } = "sms-code-{0}"; + + /// + /// Gets the cache expiration key format for SMS codes. + /// The placeholder {0} represents the envelopeReceiverId. + /// + public string CodeExpirationCacheKeyFormat { get; init; } = "sms-code-expiration-{0}"; + + public TimeSpan CodeCacheValidityPeriod { get; init; } = new(0, 5, 0); + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs index e65be8ac..7cea8047 100644 --- a/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs +++ b/EnvelopeGenerator.Application/Configurations/GtxMessaging/SmsParams.cs @@ -21,19 +21,5 @@ namespace EnvelopeGenerator.Application.Configurations.GtxMessaging public string MessageQueryParamName { get; init; } = "text"; public int CodeLength { get; init; } = 5; - - /// - /// Gets the cache key format for SMS codes. - /// The placeholder {0} represents the envelopeReceiverId. - /// - public string CodeCacheKeyFormat { get; init; } = "sms-code-{0}"; - - /// - /// Gets the cache expiration key format for SMS codes. - /// The placeholder {0} represents the envelopeReceiverId. - /// - public string CodeExpirationCacheKeyFormat { get; init; } = "sms-code-expiration-{0}"; - - public TimeSpan CodeCacheValidityPeriod { get; init; } = new(0, 5, 0); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverCache.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverCache.cs new file mode 100644 index 00000000..e2ac2a7c --- /dev/null +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverCache.cs @@ -0,0 +1,17 @@ +namespace EnvelopeGenerator.Application.Contracts +{ + public interface IEnvelopeReceiverCache + { + Task GetSmsCodeAsync(string envelopeReceiverId); + + /// + /// Asynchronously stores an SMS verification code in the cache and returns the expiration date of the code. + /// + /// The unique identifier for the recipient of the envelope to associate with the SMS code. + /// The SMS verification code to be stored. + /// A task that represents the asynchronous operation. The task result contains the expiration date and time of the stored SMS code. + Task SetSmsCodeAsync(string envelopeReceiverId, string code); + + Task GetSmsCodeExpirationAsync(string envelopeReceiverId); + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Extensions/DIExtensions.cs b/EnvelopeGenerator.Application/Extensions/DIExtensions.cs index 83a92bd0..3c1c62d5 100644 --- a/EnvelopeGenerator.Application/Extensions/DIExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/DIExtensions.cs @@ -15,7 +15,7 @@ namespace EnvelopeGenerator.Application.Extensions { public static class DIExtensions { - public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfigurationSection dispatcherConfigSection, IConfigurationSection mailConfigSection, IConfigurationSection smsConfigSection, IConfigurationSection codeGeneratorConfigSection) + public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfigurationSection dispatcherConfigSection, IConfigurationSection mailConfigSection, IConfigurationSection smsConfigSection, IConfigurationSection codeGeneratorConfigSection, IConfigurationSection envelopeReceiverCacheParamsSection) { //Inject CRUD Service and repositoriesad services.TryAddScoped(); @@ -56,10 +56,12 @@ namespace EnvelopeGenerator.Application.Extensions services.Configure(dispatcherConfigSection); services.Configure(mailConfigSection); services.Configure(codeGeneratorConfigSection); + services.Configure(envelopeReceiverCacheParamsSection); services.AddHttpClientService(smsConfigSection); services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddSingleton(); return services; } @@ -68,6 +70,7 @@ namespace EnvelopeGenerator.Application.Extensions dispatcherConfigSection: config.GetSection("DispatcherConfig"), mailConfigSection: config.GetSection("MailConfig"), smsConfigSection: config.GetSection("SmsConfig"), - codeGeneratorConfigSection: config.GetSection("CodeGeneratorConfig")); + codeGeneratorConfigSection: config.GetSection("CodeGeneratorConfig"), + envelopeReceiverCacheParamsSection: config.GetSection("EnvelopeReceiverCacheParams")); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/EnvelopeReceiverCache.cs b/EnvelopeGenerator.Application/Services/EnvelopeReceiverCache.cs new file mode 100644 index 00000000..525b5468 --- /dev/null +++ b/EnvelopeGenerator.Application/Services/EnvelopeReceiverCache.cs @@ -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 cacheParamOptions, IDistributedCache cache) + { + _cacheParams = cacheParamOptions.Value; + _codeCacheOptions = new() { AbsoluteExpirationRelativeToNow = cacheParamOptions.Value.CodeCacheValidityPeriod }; + _cache = cache; + } + + public async Task GetSmsCodeAsync(string envelopeReceiverId) + { + var code_key = string.Format(_cacheParams.CodeCacheKeyFormat, envelopeReceiverId); + return await _cache.GetStringAsync(code_key); + } + + public async Task 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 GetSmsCodeExpirationAsync(string envelopeReceiverId) + { + var code_expiration_key = string.Format(_cacheParams.CodeExpirationCacheKeyFormat, envelopeReceiverId); + return await _cache.GetDateTimeAsync(code_expiration_key); + } + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs index be2c1cc9..17d179eb 100644 --- a/EnvelopeGenerator.Application/Services/GTXMessagingService.cs +++ b/EnvelopeGenerator.Application/Services/GTXMessagingService.cs @@ -21,21 +21,18 @@ namespace EnvelopeGenerator.Application.Services private readonly ICodeGenerator _codeGen; - private readonly IDistributedCache _cache; + private readonly IEnvelopeReceiverCache _erCache; public string ServiceProvider { get; } - private readonly DistributedCacheEntryOptions _codeCacheOptions; - - public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator, IDistributedCache distributedCache) + public GtxMessagingService(IHttpClientService smsClient, IOptions smsParamsOptions, IMapper mapper, ICodeGenerator codeGenerator, IEnvelopeReceiverCache envelopeReceiverCache) { _smsClient = smsClient; _smsParams = smsParamsOptions.Value; _mapper = mapper; ServiceProvider = GetType().Name.Replace("Service", string.Empty); _codeGen = codeGenerator; - _cache = distributedCache; - _codeCacheOptions = new() { AbsoluteExpirationRelativeToNow = smsParamsOptions.Value.CodeCacheValidityPeriod }; + _erCache = envelopeReceiverCache; } public async Task SendSmsAsync(string recipient, string message) @@ -51,27 +48,19 @@ namespace EnvelopeGenerator.Application.Services public async Task SendSmsCodeAsync(string recipient, string envelopeReceiverId) { - var code_expiration_key = string.Format(_smsParams.CodeExpirationCacheKeyFormat, envelopeReceiverId); - - var code_key = string.Format(_smsParams.CodeCacheKeyFormat, envelopeReceiverId); - var code = await _cache.GetStringAsync(code_key); + var code = await _erCache.GetSmsCodeAsync(envelopeReceiverId); if (code is null) { - code = _codeGen.GenerateCode(_smsParams.CodeLength); - - await _cache.SetStringAsync(code_key, code, _codeCacheOptions); - - var expiration = DateTime.Now + _smsParams.CodeCacheValidityPeriod; - await _cache.SetDateTimeAsync(code_expiration_key, expiration, _codeCacheOptions); - + 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 _cache.GetDateTimeAsync(code_expiration_key); + var code_expiration = await _erCache.GetSmsCodeExpirationAsync(envelopeReceiverId); return code_expiration is null ? new() { Ok = false } : new() { Ok = false, AllowedAt = code_expiration }; diff --git a/EnvelopeGenerator.Web/appsettings.json b/EnvelopeGenerator.Web/appsettings.json index 19d64dd2..6c4b4e50 100644 --- a/EnvelopeGenerator.Web/appsettings.json +++ b/EnvelopeGenerator.Web/appsettings.json @@ -136,6 +136,7 @@ "QueryParams": { "from": "signFlow" }, - "CodeCacheValidityPeriod": "00:10:00" - } + "CodeCacheValidityPeriod": "00:10:00" + }, + "EnvelopeReceiverCacheParams": {} } \ No newline at end of file From a6468c2ff1038b5502905a2f3c00a75ed5c3e0ae Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Sat, 30 Nov 2024 04:23:24 +0100 Subject: [PATCH 053/104] =?UTF-8?q?feat(HomeController):=20Funktionalit?= =?UTF-8?q?=C3=A4t=20zur=20=C3=9Cberpr=C3=BCfung=20des=20SMS-Codes=20hinzu?= =?UTF-8?q?gef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EnvelopeReceiverSecretDto.cs | 2 - .../Extensions/MappingExtensions.cs | 3 +- .../Controllers/HomeController.cs | 69 ++++++++++++++----- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs index ebc529e7..9470766e 100644 --- a/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs +++ b/EnvelopeGenerator.Application/DTOs/EnvelopeReceiver/EnvelopeReceiverSecretDto.cs @@ -5,7 +5,5 @@ public string? AccessCode { get; init; } public string? PhoneNumber { get; init; } - - public EnvelopeReceiverDto WithoutSecrets => this; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs index 0d7f19c8..d2ebb946 100644 --- a/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs @@ -1,4 +1,5 @@ -using EnvelopeGenerator.Domain.HttpResponse; +using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; +using EnvelopeGenerator.Domain.HttpResponse; namespace EnvelopeGenerator.Application.Extensions { diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index d221bad0..202229c3 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -19,6 +19,7 @@ using Ganss.Xss; using Newtonsoft.Json; using EnvelopeGenerator.Application.DTOs; using DigitalData.Core.Client; +using DevExpress.Utils.About; namespace EnvelopeGenerator.Web.Controllers { @@ -35,7 +36,9 @@ namespace EnvelopeGenerator.Web.Controllers private readonly IEnvelopeMailService _mailService; private readonly IEnvelopeReceiverReadOnlyService _readOnlyService; private readonly IMessagingService _msgService; - public HomeController(EnvelopeOldService envelopeOldService, ILogger logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeHistoryService historyService, IStringLocalizer localizer, IConfiguration configuration, HtmlSanitizer sanitizer, Cultures cultures, IEnvelopeMailService envelopeMailService, IEnvelopeReceiverReadOnlyService readOnlyService, IMessagingService messagingService) + private readonly IEnvelopeReceiverCache _erCache; + + public HomeController(EnvelopeOldService envelopeOldService, ILogger logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeHistoryService historyService, IStringLocalizer localizer, IConfiguration configuration, HtmlSanitizer sanitizer, Cultures cultures, IEnvelopeMailService envelopeMailService, IEnvelopeReceiverReadOnlyService readOnlyService, IMessagingService messagingService, IEnvelopeReceiverCache envelopeReceiverCache) { this.envelopeOldService = envelopeOldService; _envRcvService = envelopeReceiverService; @@ -48,6 +51,7 @@ namespace EnvelopeGenerator.Web.Controllers _logger = logger; _readOnlyService = readOnlyService; _msgService = messagingService; + _erCache = envelopeReceiverCache; } [HttpGet("/")] @@ -175,20 +179,7 @@ namespace EnvelopeGenerator.Web.Controllers return await _envRcvService.ReadWithSecretByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync( SuccessAsync: async er_secret => { - //check the access code verification - if (er_secret.AccessCode != auth.AccessCode) - { - //Constants.EnvelopeStatus.AccessCodeIncorrect - await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeIncorrect); - Response.StatusCode = StatusCodes.Status401Unauthorized; - return View("EnvelopeLocked") - .WithData("ErrorMessage", _localizer[WebKey.WrongAccessCode].Value); - } - - await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeCorrect); - - //check if the user has phone is added - if (er_secret.HasPhoneNumber) + async Task SendSmsView() { var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId); if (res.Ok) @@ -203,8 +194,54 @@ namespace EnvelopeGenerator.Web.Controllers } } + if (auth.HasMulti) + { + Response.StatusCode = StatusCodes.Status401Unauthorized; + return View("EnvelopeLocked") + .WithData("ErrorMessage", _localizer[WebKey.WrongAccessCode].Value); + } + else if (auth.HasAccessCode) + { + //check the access code verification + if (er_secret.AccessCode != auth.AccessCode) + { + //Constants.EnvelopeStatus.AccessCodeIncorrect + await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeIncorrect); + Response.StatusCode = StatusCodes.Status401Unauthorized; + return View("EnvelopeLocked") + .WithData("ErrorMessage", _localizer[WebKey.WrongAccessCode].Value); + } + + await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeCorrect); + + //check if the user has phone is added + if (er_secret.HasPhoneNumber) + { + return await SendSmsView(); + } + } + else if (auth.HasSmsCode) + { + var smsCode = await _erCache.GetSmsCodeAsync(envelopeReceiverId); + if (smsCode is null) + return RedirectToAction("EnvelopeLocked", new { envelopeReceiverId }); + + if(auth.SmsCode != smsCode) + { + Response.StatusCode = StatusCodes.Status401Unauthorized; + ViewData["ErrorMessage"] = _localizer[WebKey.WrongAccessCode].Value; + return await SendSmsView(); + } + } + else + { + Response.StatusCode = StatusCodes.Status401Unauthorized; + return View("EnvelopeLocked") + .WithData("ErrorMessage", _localizer[WebKey.WrongAccessCode].Value); + } + //continue the process without important data to minimize security errors. - var er = er_secret.WithoutSecrets; + EnvelopeReceiverDto er = er_secret; ViewData["EnvelopeKey"] = envelopeReceiverId; //check rejection From 46b8bde1626ecda7b53e3182a84958ab7c9dc047 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 2 Dec 2024 10:12:10 +0100 Subject: [PATCH 054/104] chore(Web): Aktualisiert auf 2.7.0. --- EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj index a1f2b5f2..42f94324 100644 --- a/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj +++ b/EnvelopeGenerator.Web/EnvelopeGenerator.Web.csproj @@ -5,7 +5,7 @@ enable enable EnvelopeGenerator.Web - 2.6.0 + 2.7.0 Digital Data GmbH Digital Data GmbH EnvelopeGenerator.Web @@ -13,8 +13,8 @@ digital data envelope generator web EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly. Assets\icon.ico - 2.6.0 - 2.6.0 + 2.7.0 + 2.7.0 Copyright © 2024 Digital Data GmbH. All rights reserved. From e33d85960346ffe4fcfea046db34554853b2aa01 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 2 Dec 2024 14:57:10 +0100 Subject: [PATCH 055/104] =?UTF-8?q?refactor(ShowEnvelope):=20=C3=A4nderte?= =?UTF-8?q?=20die=20Farbe=20der=20Schaltfl=C3=A4che=20via=20Bootstrap=20in?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Views/Home/ShowEnvelope.cshtml | 2 +- EnvelopeGenerator.sln | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Web/Views/Home/ShowEnvelope.cshtml b/EnvelopeGenerator.Web/Views/Home/ShowEnvelope.cshtml index f92297f5..62cd7266 100644 --- a/EnvelopeGenerator.Web/Views/Home/ShowEnvelope.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/ShowEnvelope.cshtml @@ -29,7 +29,7 @@ @if (!isReadOnly) {
- + @if (tfaEnabled) + { +
+ + +
+ } @if (expiration is not null) { diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.css b/EnvelopeGenerator.Web/wwwroot/css/site.css index 07ebcce9..82c1601e 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.css @@ -448,6 +448,16 @@ footer#page-footer { cursor: pointer; } +.form-check.tfa-sms { + margin-left: 2rem; +} + + .form-check.tfa-sms .form-check-label { + font-size: 0.875rem; + font-weight: 500; + margin-left: -.1rem; + } + /*.flag-dropdown button { height: 100%; }*/ diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.min.css b/EnvelopeGenerator.Web/wwwroot/css/site.min.css index 4adc28ba..fed1d51e 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.min.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.min.css @@ -1 +1 @@ -.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffa407;color:#000}.page header .icon.locked.sms-tfa{background-color:#ff7207;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:space-between;flex-direction:row;align-items:center}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0;margin:0;height:100%}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}#sms-timer{height:3rem;display:flex;align-items:center;font-family:'Arial',sans-serif;font-weight:bold;color:#fff;background-color:#007bff;margin:0 0 0 2rem;border-radius:8px;text-align:center}#sms-timer:hover{background-color:#0056b3;cursor:pointer}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file +.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffa407;color:#000}.page header .icon.locked.sms-tfa{background-color:#ff7207;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:space-between;flex-direction:row;align-items:center}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0;margin:0;height:100%}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}#sms-timer{height:3rem;display:flex;align-items:center;font-family:'Arial',sans-serif;font-weight:bold;color:#fff;background-color:#007bff;margin:0 0 0 2rem;border-radius:8px;text-align:center}#sms-timer:hover{background-color:#0056b3;cursor:pointer}.form-check.tfa-sms{margin-left:2rem}.form-check.tfa-sms .form-check-label{font-size:.875rem;font-weight:500;margin-left:-.1rem}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file From a371abaabe9a6e901c65bf50ed136007c26d2ca2 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 17:47:45 +0100 Subject: [PATCH 064/104] =?UTF-8?q?feat(Auth):=20Nullbare=20Eigenschaft=20?= =?UTF-8?q?namens=20'UserSelectSMS'=20hinzugef=C3=BCgt.=20=20-=20Sie=20wir?= =?UTF-8?q?d=20standardm=C3=A4=C3=9Fig=20als=20null=20zugewiesen.=20=20-?= =?UTF-8?q?=20Die=20Checkbox=20des=20Formulars=20in=20Envelope.cshtml=20wu?= =?UTF-8?q?rde=20userSelectSMS=20genannt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Auth.cs | 2 +- EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Auth.cs b/EnvelopeGenerator.Web/Models/Auth.cs index 4159fd90..b13dfa1a 100644 --- a/EnvelopeGenerator.Web/Models/Auth.cs +++ b/EnvelopeGenerator.Web/Models/Auth.cs @@ -1,6 +1,6 @@ namespace EnvelopeGenerator.Web.Models { - public record Auth(string? AccessCode = null, string? SmsCode = null) + public record Auth(string? AccessCode = null, string? SmsCode = null, bool? UserSelectSMS = null) { public bool HasAccessCode => AccessCode is not null; diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index 006d9c21..cb780996 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -42,7 +42,7 @@ @if (tfaEnabled) {
- +
} From bed51992d23ada00f06ddfe0542bb7a2d07ed08b Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 18:08:01 +0100 Subject: [PATCH 065/104] =?UTF-8?q?feat(Auth):=20Proproty=20mit=20dem=20Na?= =?UTF-8?q?men=20AuthenticatorCode=20f=C3=BCr=20die=20Verwendung=20von=20A?= =?UTF-8?q?uthenticators=20hinzugef=C3=BCgt.=20=20-=20Getter=20mit=20dem?= =?UTF-8?q?=20Namen=20HasAuthenticatorCode=20hinzugef=C3=BCgt.=20=20-=20Ak?= =?UTF-8?q?tualisierte=20HasMulti=20und=20HasNone=20Getter=20Methoden,=20d?= =?UTF-8?q?ie=20dies=20ber=C3=BCcksichtigen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Models/Auth.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.Web/Models/Auth.cs b/EnvelopeGenerator.Web/Models/Auth.cs index b13dfa1a..9cf54cb1 100644 --- a/EnvelopeGenerator.Web/Models/Auth.cs +++ b/EnvelopeGenerator.Web/Models/Auth.cs @@ -1,13 +1,15 @@ namespace EnvelopeGenerator.Web.Models { - public record Auth(string? AccessCode = null, string? SmsCode = null, bool? UserSelectSMS = null) + public record Auth(string? AccessCode = null, string? SmsCode = null, string? AuthenticatorCode = null, bool? UserSelectSMS = null) { public bool HasAccessCode => AccessCode is not null; public bool HasSmsCode => SmsCode is not null; - public bool HasMulti => HasAccessCode && HasSmsCode; + public bool HasAuthenticatorCode => AuthenticatorCode is not null; - public bool HasNone => !(HasAccessCode || HasSmsCode); + public bool HasMulti => new[] { HasAccessCode, HasSmsCode, HasAuthenticatorCode }.Count(state => state) > 1; + + public bool HasNone => !(HasAccessCode || HasSmsCode || HasAuthenticatorCode); } } \ No newline at end of file From 137d8e09d4c29237ceed7dbd51a65653d87255b6 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 18:24:29 +0100 Subject: [PATCH 066/104] =?UTF-8?q?refactor(HomeController):=20Aktualisier?= =?UTF-8?q?t,=20um=20zu=20pr=C3=BCfen,=20ob=20der=20UserSelectSMS-Status?= =?UTF-8?q?=20null=20ist.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/HomeController.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index db75f349..8204b9cd 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -19,6 +19,7 @@ using Ganss.Xss; using Newtonsoft.Json; using EnvelopeGenerator.Application.DTOs; using DigitalData.Core.Client; +using System.Text.Json; namespace EnvelopeGenerator.Web.Controllers { @@ -217,9 +218,20 @@ namespace EnvelopeGenerator.Web.Controllers await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeCorrect); //check if the user has phone is added - if (er_secret.HasPhoneNumber) + if (er_secret.TFAEnabled) { - return await SendSmsView(); + if (auth.UserSelectSMS is bool userSelectSMS) + { + if(userSelectSMS) + return await SendSmsView(); + } + else + { + // if If TFA is enabled but UserSelectSMS is null, there is an unauthorized request(e.g. via an application like postman) + Response.StatusCode = StatusCodes.Status401Unauthorized; + _logger.LogError("TFA is enabled but UserSelectSMS is null. In this case there is an unauthorized request (for example via an application like postman). Form data: {form}", JsonConvert.SerializeObject(auth)); + return this.ViewInnerServiceError(); + } } } else if (auth.HasSmsCode) From 6a6da39bc4f731b01294c4aba87ecf4c9f001da3 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 18:48:05 +0100 Subject: [PATCH 067/104] =?UTF-8?q?refactor(HomeController):=20Aktualisier?= =?UTF-8?q?t,=20um=20zu=20pr=C3=BCfen,=20ob=20der=20UserSelectSMS-Wert=20f?= =?UTF-8?q?alsch=20ist.=20=20-=20Relevante=20Variablen=20zu=20EnvelopeLock?= =?UTF-8?q?ed.cshtml=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/HomeController.cs | 32 +++++++++++-------- .../Views/Home/EnvelopeLocked.cshtml | 6 ++-- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 8204b9cd..f6407d04 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -182,18 +182,25 @@ namespace EnvelopeGenerator.Web.Controllers return await _envRcvService.ReadWithSecretByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync( SuccessAsync: async er_secret => { - async Task SendSmsView() + async Task TFAView(bool viaSms) { - var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId); - if (res.Ok) - return View("EnvelopeLocked").WithData("ViaSms", true).WithData("Expiration", res.Expiration); - else if (!res.Allowed) - return View("EnvelopeLocked").WithData("ViaSms", true).WithData("Expiration", res.AllowedAt); + if (viaSms) + { + var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId); + if (res.Ok) + return View("EnvelopeLocked").WithData("AccessCodeName", "smsCode").WithData("Expiration", res.Expiration); + else if (!res.Allowed) + return View("EnvelopeLocked").WithData("AccessCodeName", "smsCode").WithData("Expiration", res.AllowedAt); + else + { + var res_json = JsonConvert.SerializeObject(res); + _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, message: $"An unexpected error occurred while sending an SMS code. Response: ${res_json}"); + return this.ViewInnerServiceError(); + } + } else { - var res_json = JsonConvert.SerializeObject(res); - _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, message: $"An unexpected error occurred while sending an SMS code. Response: ${res_json}"); - return this.ViewInnerServiceError(); + return View("EnvelopeLocked").WithData("AccessCodeName", "authenticatorCode"); } } @@ -221,10 +228,7 @@ namespace EnvelopeGenerator.Web.Controllers if (er_secret.TFAEnabled) { if (auth.UserSelectSMS is bool userSelectSMS) - { - if(userSelectSMS) - return await SendSmsView(); - } + return await TFAView(userSelectSMS); else { // if If TFA is enabled but UserSelectSMS is null, there is an unauthorized request(e.g. via an application like postman) @@ -244,7 +248,7 @@ namespace EnvelopeGenerator.Web.Controllers { Response.StatusCode = StatusCodes.Status401Unauthorized; ViewData["ErrorMessage"] = _localizer[WebKey.WrongAccessCode].Value; - return await SendSmsView(); + return await TFAView(viaSms: true); } } else diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index cb780996..379d9724 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -5,8 +5,10 @@ var logo = _logoOpt.Value; ViewData["Title"] = _localizer[WebKey.DocProtected]; var userCulture = ViewData["UserCulture"] as Culture; - bool viaSms = ViewData["ViaSms"] is bool _viaSms && _viaSms; - var accessCodeName = viaSms ? "smsCode" : "accessCode"; + string accessCodeName = ViewData["AccessCodeName"] is string _accessCodeName ? _accessCodeName : "accessCode"; + bool viaSms = accessCodeName == "smsCode"; + bool viaAuthenticator = accessCodeName == "authenticatorCode"; + bool viaTFA = viaSms || viaAuthenticator; DateTime? expiration = ViewData["Expiration"] is DateTime _expiration ? _expiration : null; bool tfaEnabled = ViewData["TFAEnabled"] is bool _tfaEnabled && _tfaEnabled; bool hasPhoneNumber = ViewData["HasPhoneNumber"] is bool _hasPhoneNumber && _hasPhoneNumber; From 76bd1a102fb5abd8254d5a4ab84740cd967503ec Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 20:13:26 +0100 Subject: [PATCH 068/104] =?UTF-8?q?fix(EnvelopedLocked):=20asp-for=20tag?= =?UTF-8?q?=20helper=20verwendet,=20um=20die=20Daten=20der=20UserSelectSMS?= =?UTF-8?q?=20Eigenschaft=20zu=20erhalten.=20=20-=20nullibility=20und=20nu?= =?UTF-8?q?ll=20check=20von=20UserSelectSMS=20entfernt,=20weil=20es=20f?= =?UTF-8?q?=C3=BCr=20tag=20helper=20nicht=20akzeptabel=20ist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/Controllers/HomeController.cs | 12 +----------- EnvelopeGenerator.Web/Models/Auth.cs | 2 +- .../Views/Home/EnvelopeLocked.cshtml | 11 ++++++++++- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index f6407d04..537908f2 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -226,17 +226,7 @@ namespace EnvelopeGenerator.Web.Controllers //check if the user has phone is added if (er_secret.TFAEnabled) - { - if (auth.UserSelectSMS is bool userSelectSMS) - return await TFAView(userSelectSMS); - else - { - // if If TFA is enabled but UserSelectSMS is null, there is an unauthorized request(e.g. via an application like postman) - Response.StatusCode = StatusCodes.Status401Unauthorized; - _logger.LogError("TFA is enabled but UserSelectSMS is null. In this case there is an unauthorized request (for example via an application like postman). Form data: {form}", JsonConvert.SerializeObject(auth)); - return this.ViewInnerServiceError(); - } - } + return await TFAView(auth.UserSelectSMS); } else if (auth.HasSmsCode) { diff --git a/EnvelopeGenerator.Web/Models/Auth.cs b/EnvelopeGenerator.Web/Models/Auth.cs index 9cf54cb1..c85733f8 100644 --- a/EnvelopeGenerator.Web/Models/Auth.cs +++ b/EnvelopeGenerator.Web/Models/Auth.cs @@ -1,6 +1,6 @@ namespace EnvelopeGenerator.Web.Models { - public record Auth(string? AccessCode = null, string? SmsCode = null, string? AuthenticatorCode = null, bool? UserSelectSMS = null) + public record Auth(string? AccessCode = null, string? SmsCode = null, string? AuthenticatorCode = null, bool UserSelectSMS = default) { public bool HasAccessCode => AccessCode is not null; diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index 379d9724..cc285a6c 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -1,11 +1,13 @@ @using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; @using Newtonsoft.Json +@model Auth; @{ var nonce = _accessor.HttpContext?.Items["csp-nonce"] as string; var logo = _logoOpt.Value; ViewData["Title"] = _localizer[WebKey.DocProtected]; var userCulture = ViewData["UserCulture"] as Culture; string accessCodeName = ViewData["AccessCodeName"] is string _accessCodeName ? _accessCodeName : "accessCode"; + string codePropName = char.ToUpper(accessCodeName[0]) + accessCodeName.Substring(1); bool viaSms = accessCodeName == "smsCode"; bool viaAuthenticator = accessCodeName == "authenticatorCode"; bool viaTFA = viaSms || viaAuthenticator; @@ -44,7 +46,14 @@ @if (tfaEnabled) {
- + @if(hasPhoneNumber) + { + + } + else + { + + }
} From ff6d27df8edf9f7134cbdfce785fb719b699635a Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 20:32:09 +0100 Subject: [PATCH 069/104] =?UTF-8?q?feat(DTOExtensions):=20Erstellt,=20um?= =?UTF-8?q?=20Erweiterungsmethoden=20f=C3=BCr=20DTOs=20hinzuzuf=C3=BCgen.?= =?UTF-8?q?=20=20-=20IsTotpSecretExpired,=20IsTotpSecretInvalid=20und=20Is?= =?UTF-8?q?TotpSecretValid=20Erweiterungsmethoden=20f=C3=BCr=20ReceiverRea?= =?UTF-8?q?dDto=20hinzugef=C3=BCgt,=20um=20den=20Zustand=20des=20geheimen?= =?UTF-8?q?=20Schl=C3=BCssels=20zu=20behandeln.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/DTOExtensions.cs | 14 ++++++++++++++ .../Extensions/MappingExtensions.cs | 3 +-- 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 EnvelopeGenerator.Application/Extensions/DTOExtensions.cs diff --git a/EnvelopeGenerator.Application/Extensions/DTOExtensions.cs b/EnvelopeGenerator.Application/Extensions/DTOExtensions.cs new file mode 100644 index 00000000..753a08cc --- /dev/null +++ b/EnvelopeGenerator.Application/Extensions/DTOExtensions.cs @@ -0,0 +1,14 @@ +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) => dto.IsTotpSecretExpired() || dto.TotpSecretkey is null; + + public static bool IsTotpSecretValid(this ReceiverReadDto dto) => !dto.IsTotpSecretInvalid(); + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs index d2ebb946..0d7f19c8 100644 --- a/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs @@ -1,5 +1,4 @@ -using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; -using EnvelopeGenerator.Domain.HttpResponse; +using EnvelopeGenerator.Domain.HttpResponse; namespace EnvelopeGenerator.Application.Extensions { From 1657a99aa67dd891b5f85d692080b09fec697e42 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 20:34:22 +0100 Subject: [PATCH 070/104] =?UTF-8?q?feat(DTOExtensions):=20Optionale=20minu?= =?UTF-8?q?tesBeforeExpiration=20Eingaben=20zu=20IsTotpSecretInvalid=20und?= =?UTF-8?q?=20IsTotpSecretValid=20Methoden=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Application/Extensions/DTOExtensions.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Application/Extensions/DTOExtensions.cs b/EnvelopeGenerator.Application/Extensions/DTOExtensions.cs index 753a08cc..8c88b34f 100644 --- a/EnvelopeGenerator.Application/Extensions/DTOExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/DTOExtensions.cs @@ -7,8 +7,10 @@ namespace EnvelopeGenerator.Application.Extensions public static bool IsTotpSecretExpired(this ReceiverReadDto dto, int minutesBeforeExpiration = 30) => dto.TotpExpiration < DateTime.Now.AddMinutes(minutesBeforeExpiration * -1); - public static bool IsTotpSecretInvalid(this ReceiverReadDto dto) => dto.IsTotpSecretExpired() || dto.TotpSecretkey is null; + public static bool IsTotpSecretInvalid(this ReceiverReadDto dto, int minutesBeforeExpiration = 30) + => dto.IsTotpSecretExpired(minutesBeforeExpiration) || dto.TotpSecretkey is null; - public static bool IsTotpSecretValid(this ReceiverReadDto dto) => !dto.IsTotpSecretInvalid(); + public static bool IsTotpSecretValid(this ReceiverReadDto dto, int minutesBeforeExpiration = 30) + => !dto.IsTotpSecretInvalid(minutesBeforeExpiration); } } \ No newline at end of file From 085f37de160c0efc2b0d0449db194a0b4b77a94a Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 22:05:52 +0100 Subject: [PATCH 071/104] =?UTF-8?q?feat(CodeGenerator):=20Die=20Methoden?= =?UTF-8?q?=20GenerateTotpSecretKey,=20GenerateTotpQrCode=20und=20Generate?= =?UTF-8?q?TotpQrCode=20wurden=20als=20Schnittstellenimplementierung=20hin?= =?UTF-8?q?zugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Configurations/CodeGeneratorConfig.cs | 7 ---- .../Configurations/CodeGeneratorParams.cs | 18 +++++++++ .../Contracts/ICodeGenerator.cs | 6 +++ .../Extensions/DIExtensions.cs | 6 ++- .../Extensions/MappingExtensions.cs | 3 ++ .../Services/CodeGenerator.cs | 39 ++++++++++++++++--- 6 files changed, 65 insertions(+), 14 deletions(-) delete mode 100644 EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs create mode 100644 EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs diff --git a/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs b/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs deleted file mode 100644 index b44c989a..00000000 --- a/EnvelopeGenerator.Application/Configurations/CodeGeneratorConfig.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace EnvelopeGenerator.Application.Configurations -{ - public class CodeGeneratorConfig - { - public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789"; - } -} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs b/EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs new file mode 100644 index 00000000..f4c8e1b1 --- /dev/null +++ b/EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs @@ -0,0 +1,18 @@ +namespace EnvelopeGenerator.Application.Configurations +{ + public class CodeGeneratorParams + { + public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789"; + + public int DefaultTotpSecretKeyLength { get; init; } = 32; + + public string TotpIssuer { get; init; } = "signFlow"; + + /// + /// 0 is user email, 1 is secret key and 2 is issuer. + /// + public string TotpUrlFormat { get; init; } = "otpauth://totp/{0}?secret={1}&issuer={2}"; + + public int TotpQRPixelsPerModule { get; init; } = 20; + } +} \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs b/EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs index 4a282c66..38a27b85 100644 --- a/EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs +++ b/EnvelopeGenerator.Application/Contracts/ICodeGenerator.cs @@ -3,5 +3,11 @@ 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); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Extensions/DIExtensions.cs b/EnvelopeGenerator.Application/Extensions/DIExtensions.cs index 3c1c62d5..ae8fedf9 100644 --- a/EnvelopeGenerator.Application/Extensions/DIExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/DIExtensions.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using DigitalData.Core.Client; using EnvelopeGenerator.Application.Configurations.GtxMessaging; +using QRCoder; namespace EnvelopeGenerator.Application.Extensions { @@ -55,13 +56,14 @@ namespace EnvelopeGenerator.Application.Extensions services.Configure(dispatcherConfigSection); services.Configure(mailConfigSection); - services.Configure(codeGeneratorConfigSection); + services.Configure(codeGeneratorConfigSection); services.Configure(envelopeReceiverCacheParamsSection); services.AddHttpClientService(smsConfigSection); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); + services.TryAddSingleton(); return services; } @@ -70,7 +72,7 @@ namespace EnvelopeGenerator.Application.Extensions dispatcherConfigSection: config.GetSection("DispatcherConfig"), mailConfigSection: config.GetSection("MailConfig"), smsConfigSection: config.GetSection("SmsConfig"), - codeGeneratorConfigSection: config.GetSection("CodeGeneratorConfig"), + codeGeneratorConfigSection: config.GetSection("CodeGeneratorParams"), envelopeReceiverCacheParamsSection: config.GetSection("EnvelopeReceiverCacheParams")); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs index 0d7f19c8..bd996b58 100644 --- a/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs +++ b/EnvelopeGenerator.Application/Extensions/MappingExtensions.cs @@ -7,5 +7,8 @@ namespace EnvelopeGenerator.Application.Extensions 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); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/CodeGenerator.cs b/EnvelopeGenerator.Application/Services/CodeGenerator.cs index 7b3f4b3c..89d22522 100644 --- a/EnvelopeGenerator.Application/Services/CodeGenerator.cs +++ b/EnvelopeGenerator.Application/Services/CodeGenerator.cs @@ -1,21 +1,26 @@ 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 LazyStatic => new(() => new CodeGenerator(Options.Create(new()))); + public static Lazy LazyStatic => new(() => new CodeGenerator(Options.Create(new()), new QRCodeGenerator())); public static CodeGenerator Static => LazyStatic.Value; - private readonly string _charPool; + private readonly CodeGeneratorParams _params; - public CodeGenerator(IOptions options) + private readonly QRCodeGenerator _qrCodeGenerator; + + public CodeGenerator(IOptions options, QRCodeGenerator qrCodeGenerator) { - _charPool = options.Value.CharPool; + _params = options.Value; + _qrCodeGenerator = qrCodeGenerator; } public string GenerateCode(int length) @@ -29,9 +34,33 @@ namespace EnvelopeGenerator.Application.Services var passwordBuilder = new StringBuilder(length); for (int i = 0; i < length; i++) - passwordBuilder.Append(_charPool[random.Next(_charPool.Length)]); + 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); + } } } \ No newline at end of file From f0f1275e7503d278c194014b19fd5f7d91dabcef Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 22:33:32 +0100 Subject: [PATCH 072/104] =?UTF-8?q?feat(EnvelopeReceiverRepository):=20Opt?= =?UTF-8?q?ionale=20schreibgesch=C3=BCtzte=20Eingabe=20als=20Schnittstelle?= =?UTF-8?q?nimplementierung=20hinzugef=C3=BCgt.=20=20-=20Standardm=C3=A4?= =?UTF-8?q?=C3=9Fig=20ist=20schreibgesch=C3=BCtzt=20falsch.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IEnvelopeReceiverRepository.cs | 12 +++---- .../Repositories/EnvlopeReceiverRepository.cs | 35 ++++++++++--------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs b/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs index e471ddf7..4aa2946c 100644 --- a/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs +++ b/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs @@ -5,19 +5,19 @@ namespace EnvelopeGenerator.Infrastructure.Contracts { public interface IEnvelopeReceiverRepository : ICRUDRepository { - Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false); + Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = false); - Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true); + Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = false); - Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true); + Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = false); - Task ReadAccessCodeAsync(string uuid, string signature); + Task ReadAccessCodeAsync(string uuid, string signature, bool readOnly = false); Task CountAsync(string uuid, string signature); - Task ReadByIdAsync(int envelopeId, int receiverId); + Task ReadByIdAsync(int envelopeId, int receiverId, bool readOnly = false); - Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId); + Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId, bool readOnly = false); Task> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses); diff --git a/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs b/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs index 7b72f29e..80c0970c 100644 --- a/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs +++ b/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs @@ -11,9 +11,9 @@ namespace EnvelopeGenerator.Infrastructure.Repositories { } - private IQueryable ReadWhere(string? uuid = null, string? signature = null, bool withEnvelope = false, bool withReceiver = false) + private IQueryable ReadWhere(string? uuid = null, string? signature = null, bool withEnvelope = false, bool withReceiver = false, bool readOnly = false) { - var query = _dbSet.AsNoTracking(); + var query = readOnly ? _dbSet.AsNoTracking() : _dbSet; if (uuid is not null) query = query.Where(er => er.Envelope != null && er.Envelope.Uuid == uuid); @@ -32,31 +32,34 @@ namespace EnvelopeGenerator.Infrastructure.Repositories return query; } - public async Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false) - => await ReadWhere(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver).ToListAsync(); + public async Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = false) + => await ReadWhere(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).ToListAsync(); - public async Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true) - => await ReadWhere(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver).ToListAsync(); + public async Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = false) + => await ReadWhere(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).ToListAsync(); - public async Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true) - => await ReadWhere(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver).FirstOrDefaultAsync(); + public async Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = false) + => await ReadWhere(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).FirstOrDefaultAsync(); - public async Task ReadAccessCodeAsync(string uuid, string signature) - => await ReadWhere(uuid: uuid, signature: signature) + public async Task ReadAccessCodeAsync(string uuid, string signature, bool readOnly = false) + => await ReadWhere(uuid: uuid, signature: signature, readOnly: readOnly) .Select(er => er.AccessCode) .FirstOrDefaultAsync(); public async Task CountAsync(string uuid, string signature) => await ReadWhere(uuid: uuid, signature: signature).CountAsync(); - public IQueryable ReadById(int envelopeId, int receiverId) => _dbSet.AsNoTracking() - .Where(er => er.EnvelopeId == envelopeId && er.ReceiverId == receiverId); + private IQueryable ReadById(int envelopeId, int receiverId, bool readOnly = false) + { + var query = readOnly ? _dbSet.AsNoTracking() : _dbSet; + return query.Where(er => er.EnvelopeId == envelopeId && er.ReceiverId == receiverId); + } - public async Task ReadByIdAsync(int envelopeId, int receiverId) - => await ReadById(envelopeId: envelopeId, receiverId: receiverId) + public async Task ReadByIdAsync(int envelopeId, int receiverId, bool readOnly = false) + => await ReadById(envelopeId: envelopeId, receiverId: receiverId, readOnly: readOnly) .FirstOrDefaultAsync(); - public async Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId) - => await ReadById(envelopeId: envelopeId, receiverId: receiverId) + public async Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId, bool readOnly = false) + => await ReadById(envelopeId: envelopeId, receiverId: receiverId, readOnly: readOnly) .Select(er => er.AccessCode) .FirstOrDefaultAsync(); From f06b41492edf4402576beab55b1acdea5770a830 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 22:43:53 +0100 Subject: [PATCH 073/104] feat(EnvelopeReceiverRepository): Standardwert readOnly als true aktualisiert. --- .../Contracts/IEnvelopeReceiverRepository.cs | 12 ++++++------ .../Repositories/EnvlopeReceiverRepository.cs | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs b/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs index 4aa2946c..ffd56528 100644 --- a/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs +++ b/EnvelopeGenerator.Infrastructure/Contracts/IEnvelopeReceiverRepository.cs @@ -5,19 +5,19 @@ namespace EnvelopeGenerator.Infrastructure.Contracts { public interface IEnvelopeReceiverRepository : ICRUDRepository { - Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = false); + Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true); - Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = false); + Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true); - Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = false); + Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true); - Task ReadAccessCodeAsync(string uuid, string signature, bool readOnly = false); + Task ReadAccessCodeAsync(string uuid, string signature, bool readOnly = true); Task CountAsync(string uuid, string signature); - Task ReadByIdAsync(int envelopeId, int receiverId, bool readOnly = false); + Task ReadByIdAsync(int envelopeId, int receiverId, bool readOnly = true); - Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId, bool readOnly = false); + Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId, bool readOnly = true); Task> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses); diff --git a/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs b/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs index 80c0970c..9bfb26e4 100644 --- a/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs +++ b/EnvelopeGenerator.Infrastructure/Repositories/EnvlopeReceiverRepository.cs @@ -11,7 +11,7 @@ namespace EnvelopeGenerator.Infrastructure.Repositories { } - private IQueryable ReadWhere(string? uuid = null, string? signature = null, bool withEnvelope = false, bool withReceiver = false, bool readOnly = false) + private IQueryable ReadWhere(string? uuid = null, string? signature = null, bool withEnvelope = false, bool withReceiver = false, bool readOnly = true) { var query = readOnly ? _dbSet.AsNoTracking() : _dbSet; @@ -32,33 +32,33 @@ namespace EnvelopeGenerator.Infrastructure.Repositories return query; } - public async Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = false) + public async Task> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true) => await ReadWhere(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).ToListAsync(); - public async Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = false) + public async Task> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true) => await ReadWhere(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).ToListAsync(); - public async Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = false) + public async Task ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true) => await ReadWhere(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).FirstOrDefaultAsync(); - public async Task ReadAccessCodeAsync(string uuid, string signature, bool readOnly = false) + public async Task ReadAccessCodeAsync(string uuid, string signature, bool readOnly = true) => await ReadWhere(uuid: uuid, signature: signature, readOnly: readOnly) .Select(er => er.AccessCode) .FirstOrDefaultAsync(); public async Task CountAsync(string uuid, string signature) => await ReadWhere(uuid: uuid, signature: signature).CountAsync(); - private IQueryable ReadById(int envelopeId, int receiverId, bool readOnly = false) + private IQueryable ReadById(int envelopeId, int receiverId, bool readOnly = true) { var query = readOnly ? _dbSet.AsNoTracking() : _dbSet; return query.Where(er => er.EnvelopeId == envelopeId && er.ReceiverId == receiverId); } - public async Task ReadByIdAsync(int envelopeId, int receiverId, bool readOnly = false) + public async Task ReadByIdAsync(int envelopeId, int receiverId, bool readOnly = true) => await ReadById(envelopeId: envelopeId, receiverId: receiverId, readOnly: readOnly) .FirstOrDefaultAsync(); - public async Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId, bool readOnly = false) + public async Task ReadAccessCodeByIdAsync(int envelopeId, int receiverId, bool readOnly = true) => await ReadById(envelopeId: envelopeId, receiverId: receiverId, readOnly: readOnly) .Select(er => er.AccessCode) .FirstOrDefaultAsync(); From 4f5b8f9d766ad959dacb8e4e0503012255e8db44 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 22:48:43 +0100 Subject: [PATCH 074/104] =?UTF-8?q?feat(EnvelopeReceiverService):=20Option?= =?UTF-8?q?ale=20schreibgesch=C3=BCtzte=20Eingabe=20als=20Schnittstellenim?= =?UTF-8?q?plementierung=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - als Standard ist Nur-Lesen wahr. --- .../Contracts/IEnvelopeReceiverService.cs | 10 +++++----- .../Services/EnvelopeReceiverService.cs | 20 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs index 65834a4d..f22fde28 100644 --- a/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeReceiverService.cs @@ -9,17 +9,17 @@ namespace EnvelopeGenerator.Application.Contracts public interface IEnvelopeReceiverService : IBasicCRUDService { - Task>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false); + Task>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true); Task>> ReadAccessCodeByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true); - Task>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true); + Task>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true); - Task> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true); + Task> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true); - Task> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true); + Task> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true); - Task> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true); + Task> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true); Task> ReadAccessCodeByIdAsync(int envelopeId, int receiverId); diff --git a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs index cdb35a98..ee3e07fe 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeReceiverService.cs @@ -26,15 +26,15 @@ namespace EnvelopeGenerator.Application.Services _messagingService = messagingService; } - public async Task>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true) + public async Task>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true, bool readOnly = true) { - var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver); + var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly); return Result.Success(_mapper.Map>(env_rcvs)); } - public async Task>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false) + public async Task>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false, bool readOnly = true) { - var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver); + var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly); return Result.Success(_mapper.Map>(env_rcvs)); } @@ -44,9 +44,9 @@ namespace EnvelopeGenerator.Application.Services return Result.Success(env_rcvs.Select(er => er.AccessCode)); } - public async Task> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true) + public async Task> 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() .Message(Key.EnvelopeReceiverNotFound); @@ -54,9 +54,9 @@ namespace EnvelopeGenerator.Application.Services return Result.Success(_mapper.Map(env_rcv)); } - public async Task> ReadWithSecretByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true) + public async Task> 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); + var env_rcv = await _repository.ReadByUuidSignatureAsync(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly); if (env_rcv is null) return Result.Fail() .Message(Key.EnvelopeReceiverNotFound); @@ -64,7 +64,7 @@ namespace EnvelopeGenerator.Application.Services return Result.Success(_mapper.Map(env_rcv)); } - public async Task> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true) + public async Task> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true) { (string? uuid, string? signature) = envelopeReceiverId.DecodeEnvelopeReceiverId(); @@ -75,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> VerifyAccessCodeAsync(string uuid, string signature, string accessCode) From 8e1b4e0832128488ab67f848eee2d2bf9bc71e70 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Tue, 10 Dec 2024 23:48:01 +0100 Subject: [PATCH 075/104] =?UTF-8?q?feat(ReceiverService):=20Generische=20U?= =?UTF-8?q?pdate-Methode=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IReceiverService.cs | 9 ++++++--- .../Services/ReceiverService.cs | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IReceiverService.cs b/EnvelopeGenerator.Application/Contracts/IReceiverService.cs index 3c08f17b..c474363b 100644 --- a/EnvelopeGenerator.Application/Contracts/IReceiverService.cs +++ b/EnvelopeGenerator.Application/Contracts/IReceiverService.cs @@ -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 { - public Task> ReadByAsync(string? emailAddress = null, string? signature = null); + Task> ReadByAsync(string? emailAddress = null, string? signature = null); - public Task DeleteByAsync(string? emailAddress = null, string? signature = null); + Task DeleteByAsync(string? emailAddress = null, string? signature = null); + + Task UpdateAsync(TUpdateDto updateDto) where TUpdateDto : IUnique; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/ReceiverService.cs b/EnvelopeGenerator.Application/Services/ReceiverService.cs index 422f5c0f..97015953 100644 --- a/EnvelopeGenerator.Application/Services/ReceiverService.cs +++ b/EnvelopeGenerator.Application/Services/ReceiverService.cs @@ -5,6 +5,8 @@ using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Application.DTOs.Receiver; using DigitalData.Core.DTO; +using DigitalData.Core.Abstractions; +using Microsoft.Extensions.Logging; namespace EnvelopeGenerator.Application.Services { @@ -34,5 +36,17 @@ namespace EnvelopeGenerator.Application.Services return await _repository.DeleteAsync(rcv) ? Result.Success() : Result.Fail(); } + + public virtual async Task UpdateAsync(TUpdateDto updateDto) where TUpdateDto : IUnique + { + 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(); + } } } \ No newline at end of file From ea4b35f4b40bca011d48fed729d39389aa9f0dc1 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 00:04:29 +0100 Subject: [PATCH 076/104] =?UTF-8?q?feat(HomeController):=20Anweisung=20hin?= =?UTF-8?q?zugef=C3=BCgt,=20um=20den=20geheimen=20Totp-Schl=C3=BCssel=20zu?= =?UTF-8?q?=20aktualisieren,=20wenn=20er=20in=20Kraft=20ist.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DTOs/Receiver/ReceiverReadDto.cs | 13 ++++++++----- .../Controllers/HomeController.cs | 19 ++++++++++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs b/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs index 7871e7bd..49654fea 100644 --- a/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs +++ b/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs @@ -1,4 +1,5 @@ -using DigitalData.Core.DTO; +using DigitalData.Core.Abstractions; +using DigitalData.Core.DTO; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; using System.Text.Json.Serialization; @@ -8,14 +9,16 @@ namespace EnvelopeGenerator.Application.DTOs.Receiver int Id, string EmailAddress, string Signature, - DateTime AddedWhen, - string? TotpSecretkey = null, - DateTime? TotpExpiration = null - ) : BaseDTO(Id) + DateTime AddedWhen + ) : BaseDTO(Id), IUnique { [JsonIgnore] public IEnumerable? EnvelopeReceivers { get; init; } public string? LastUsedName => EnvelopeReceivers?.LastOrDefault()?.Name; + + public string? TotpSecretkey { get; set; } = null; + + public DateTime? TotpExpiration { get; set; } = null; }; } \ No newline at end of file diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 537908f2..89341ae3 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -20,6 +20,7 @@ using Newtonsoft.Json; using EnvelopeGenerator.Application.DTOs; using DigitalData.Core.Client; using System.Text.Json; +using EnvelopeGenerator.Application.Extensions; namespace EnvelopeGenerator.Web.Controllers { @@ -37,8 +38,10 @@ namespace EnvelopeGenerator.Web.Controllers private readonly IEnvelopeReceiverReadOnlyService _readOnlyService; private readonly IMessagingService _msgService; private readonly IEnvelopeReceiverCache _erCache; + private readonly ICodeGenerator _codeGenerator; + private readonly IReceiverService _rcvService; - public HomeController(EnvelopeOldService envelopeOldService, ILogger logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeHistoryService historyService, IStringLocalizer localizer, IConfiguration configuration, HtmlSanitizer sanitizer, Cultures cultures, IEnvelopeMailService envelopeMailService, IEnvelopeReceiverReadOnlyService readOnlyService, IMessagingService messagingService, IEnvelopeReceiverCache envelopeReceiverCache) + public HomeController(EnvelopeOldService envelopeOldService, ILogger logger, IEnvelopeReceiverService envelopeReceiverService, IEnvelopeHistoryService historyService, IStringLocalizer localizer, IConfiguration configuration, HtmlSanitizer sanitizer, Cultures cultures, IEnvelopeMailService envelopeMailService, IEnvelopeReceiverReadOnlyService readOnlyService, IMessagingService messagingService, IEnvelopeReceiverCache envelopeReceiverCache, ICodeGenerator codeGenerator, IReceiverService receiverService) { this.envelopeOldService = envelopeOldService; _envRcvService = envelopeReceiverService; @@ -52,6 +55,8 @@ namespace EnvelopeGenerator.Web.Controllers _readOnlyService = readOnlyService; _msgService = messagingService; _erCache = envelopeReceiverCache; + _codeGenerator = codeGenerator; + _rcvService = receiverService; } [HttpGet("/")] @@ -226,7 +231,19 @@ namespace EnvelopeGenerator.Web.Controllers //check if the user has phone is added if (er_secret.TFAEnabled) + { + var rcv = er_secret.Receiver; + if (rcv.IsTotpSecretInvalid()) + { + rcv.TotpSecretkey = _codeGenerator.GenerateTotpSecretKey(); + rcv.TotpExpiration = DateTime.Now.AddMonths(1); + await _rcvService.UpdateAsync(rcv); + var totp_qr_64 = _codeGenerator.GenerateTotpQrCode(userEmail: rcv.EmailAddress, secretKey: rcv.TotpSecretkey).ToBase64String(); + // send by email + } return await TFAView(auth.UserSelectSMS); + } + } else if (auth.HasSmsCode) { From 7f1009e4021c6365df5b494b0d20ace78e142583 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 10:02:53 +0100 Subject: [PATCH 077/104] =?UTF-8?q?feat(mapping):=20Ignorierregel=20f?= =?UTF-8?q?=C3=BCr=20EnvelopeReceivers=20in=20ReceiverReadDto-Mapping=20hi?= =?UTF-8?q?nzugef=C3=BCgt.=20=20-=20ReceiverReadDto-Mapping=20aktualisiert?= =?UTF-8?q?,=20um=20die=20Eigenschaft=20EnvelopeReceivers=20in=20der=20Ent?= =?UTF-8?q?it=C3=A4t=20Receiver=20zu=20ignorieren.=20=20-=20Stellt=20siche?= =?UTF-8?q?r,=20dass=20die=20Datenzuordnung=20sauber=20bleibt=20und=20kein?= =?UTF-8?q?e=20unbeabsichtigten=20Eigenschaften=20einbezogen=20werden.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MappingProfiles/BasicDtoMappingProfile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs index 403c8bb0..cf3c006b 100644 --- a/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs +++ b/EnvelopeGenerator.Application/MappingProfiles/BasicDtoMappingProfile.cs @@ -46,7 +46,7 @@ namespace EnvelopeGenerator.Application.MappingProfiles CreateMap(); CreateMap(); CreateMap(); - CreateMap(); + CreateMap().ForMember(rcv => rcv.EnvelopeReceivers, rcvReadDto => rcvReadDto.Ignore()); CreateMap(); CreateMap(); CreateMap(); From 535ca23c86e7e030c19213408b2943dada152c5f Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 11:44:39 +0100 Subject: [PATCH 078/104] =?UTF-8?q?feat(HomeController):=20Befehl=20zum=20?= =?UTF-8?q?Senden=20von=20E-Mails=20hinzugef=C3=BCgt,=20um=20QR-Code=20zu?= =?UTF-8?q?=20senden.=20=20-=20TotpSecret=20zu=20EmailTemplateType=20hinzu?= =?UTF-8?q?gef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DTOs/Receiver/ReceiverReadDto.cs | 2 ++ .../Services/EnvelopeMailService.cs | 8 ++++---- EnvelopeGenerator.Common/Constants.vb | 1 + EnvelopeGenerator.Web/Controllers/HomeController.cs | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs b/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs index 49654fea..6d1b5a19 100644 --- a/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs +++ b/EnvelopeGenerator.Application/DTOs/Receiver/ReceiverReadDto.cs @@ -1,5 +1,6 @@ using DigitalData.Core.Abstractions; using DigitalData.Core.DTO; +using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver; using System.Text.Json.Serialization; @@ -19,6 +20,7 @@ namespace EnvelopeGenerator.Application.DTOs.Receiver public string? TotpSecretkey { get; set; } = null; + [TemplatePlaceholder("[TFA_QR_EXPIRATION]")] public DateTime? TotpExpiration { get; set; } = null; }; } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs index 5e6ca13e..58a3c6b8 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs @@ -32,7 +32,7 @@ namespace EnvelopeGenerator.Application.Services _placeholders = mailConfig.Value.Placeholders; } - private async Task> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null, EnvelopeReceiverReadOnlyDto? readOnlyDto = null) + private async Task> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null) { if (accessCode is not null) _placeholders["[DOCUMENT_ACCESS_CODE]"] = accessCode; @@ -64,9 +64,9 @@ namespace EnvelopeGenerator.Application.Services return _placeholders; } - public async Task> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: Constants.EmailTemplateType.DocumentAccessCodeReceived); + public async Task> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: EmailTemplateType.DocumentAccessCodeReceived); - public async Task> SendAsync(EnvelopeReceiverDto dto, Constants.EmailTemplateType tempType) + public async Task> SendAsync(EnvelopeReceiverDto dto, EmailTemplateType tempType) { var tempSerResult = await _tempService.ReadByNameAsync(tempType); if (tempSerResult.IsFailed) @@ -111,7 +111,7 @@ namespace EnvelopeGenerator.Application.Services public async Task> SendAsync(EnvelopeReceiverReadOnlyDto dto) { - var tempSerResult = await _tempService.ReadByNameAsync(Constants.EmailTemplateType.DocumentShared); + var tempSerResult = await _tempService.ReadByNameAsync(EmailTemplateType.DocumentShared); if (tempSerResult.IsFailed) return tempSerResult.ToFail().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"The email cannot send because '{Constants.EmailTemplateType.DocumentShared}' template cannot found."); var temp = tempSerResult.Data; diff --git a/EnvelopeGenerator.Common/Constants.vb b/EnvelopeGenerator.Common/Constants.vb index d04f3bfd..d6c09439 100644 --- a/EnvelopeGenerator.Common/Constants.vb +++ b/EnvelopeGenerator.Common/Constants.vb @@ -99,6 +99,7 @@ DocumentCompleted DocumentAccessCodeReceived DocumentShared + TotpSecret End Enum Public Enum EncodeType diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 89341ae3..d5ce93ac 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -239,7 +239,7 @@ namespace EnvelopeGenerator.Web.Controllers rcv.TotpExpiration = DateTime.Now.AddMonths(1); await _rcvService.UpdateAsync(rcv); var totp_qr_64 = _codeGenerator.GenerateTotpQrCode(userEmail: rcv.EmailAddress, secretKey: rcv.TotpSecretkey).ToBase64String(); - // send by email + await _mailService.SendAsync(er_secret, EmailTemplateType.TotpSecret); } return await TFAView(auth.UserSelectSMS); } From 85cacc822d687f1e29465035d7f10171809d33c0 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 12:14:10 +0100 Subject: [PATCH 079/104] =?UTF-8?q?feat(EnvelopeMailService):=20Optionale?= =?UTF-8?q?=20Platzhalter=20als=20W=C3=B6rterbuch=20hinzugef=C3=BCgt.=20?= =?UTF-8?q?=20-=20Als=20Standard=20ist=20es=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IEnvelopeMailService.cs | 4 ++-- .../Services/EnvelopeMailService.cs | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs index 06a4ab18..23c86e32 100644 --- a/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs @@ -10,8 +10,8 @@ namespace EnvelopeGenerator.Application.Contracts { Task> SendAsync(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType); - Task> SendAsync(EnvelopeReceiverReadOnlyDto dto); + Task> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary? optionalPlaceholders = null); - Task> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto); + Task> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto, Dictionary? optionalPlaceholders = null); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs index 58a3c6b8..da2d0aa8 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs @@ -12,6 +12,7 @@ using static EnvelopeGenerator.Common.Constants; using EnvelopeGenerator.Extensions; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly; using EnvelopeGenerator.Application.Configurations; +using Newtonsoft.Json.Linq; namespace EnvelopeGenerator.Application.Services { @@ -66,7 +67,7 @@ namespace EnvelopeGenerator.Application.Services public async Task> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: EmailTemplateType.DocumentAccessCodeReceived); - public async Task> SendAsync(EnvelopeReceiverDto dto, EmailTemplateType tempType) + public async Task> SendAsync(EnvelopeReceiverDto dto, EmailTemplateType tempType, Dictionary? optionalPlaceholders = null) { var tempSerResult = await _tempService.ReadByNameAsync(tempType); if (tempSerResult.IsFailed) @@ -104,12 +105,17 @@ 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> SendAsync(EnvelopeReceiverReadOnlyDto dto) + public async Task> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary? optionalPlaceholders = null) { var tempSerResult = await _tempService.ReadByNameAsync(EmailTemplateType.DocumentShared); if (tempSerResult.IsFailed) @@ -140,6 +146,11 @@ namespace EnvelopeGenerator.Application.Services 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); } } From 6dfdd48ec059036c9aa66cb8c8de50dc13ef822d Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 12:16:53 +0100 Subject: [PATCH 080/104] fix(IEnvelopeMailService): Optionale Platzhalter in die richtige Methode verschoben. --- .../Contracts/IEnvelopeMailService.cs | 4 ++-- EnvelopeGenerator.Application/Services/EnvelopeMailService.cs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs index 23c86e32..008bcdf8 100644 --- a/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs @@ -8,10 +8,10 @@ namespace EnvelopeGenerator.Application.Contracts { public interface IEnvelopeMailService : IEmailOutService { - Task> SendAsync(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType); + Task> SendAsync(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType, Dictionary? optionalPlaceholders = null); Task> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary? optionalPlaceholders = null); - Task> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto, Dictionary? optionalPlaceholders = null); + Task> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs index da2d0aa8..e41fb12f 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs @@ -12,7 +12,6 @@ using static EnvelopeGenerator.Common.Constants; using EnvelopeGenerator.Extensions; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly; using EnvelopeGenerator.Application.Configurations; -using Newtonsoft.Json.Linq; namespace EnvelopeGenerator.Application.Services { From 31e647d3e5fe78c17db6c2dd0306e197fbd0847c Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 12:53:45 +0100 Subject: [PATCH 081/104] =?UTF-8?q?feat(EnvelopeMailService):=20SendTFAQrC?= =?UTF-8?q?odeAsync=20als=20Schnittstellenimplementierung=20zum=20Senden?= =?UTF-8?q?=20von=20QR-Code-E-Mails=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/IEnvelopeMailService.cs | 2 ++ .../Services/EnvelopeMailService.cs | 27 ++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs b/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs index 008bcdf8..14d94057 100644 --- a/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Contracts/IEnvelopeMailService.cs @@ -13,5 +13,7 @@ namespace EnvelopeGenerator.Application.Contracts Task> SendAsync(EnvelopeReceiverReadOnlyDto dto, Dictionary? optionalPlaceholders = null); Task> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto); + + Task> SendTFAQrCodeAsync(EnvelopeReceiverDto envelopeReceiverDto); } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs index e41fb12f..0763fb59 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs @@ -12,6 +12,8 @@ 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 { @@ -22,14 +24,16 @@ namespace EnvelopeGenerator.Application.Services private readonly DispatcherConfig _dConfig; private readonly IConfigService _configService; private readonly Dictionary _placeholders; + private readonly ICodeGenerator _codeGenerator; - public EnvelopeMailService(IEmailOutRepository repository, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions dispatcherConfigOptions, IConfigService configService, IOptions mailConfig) : base(repository, mapper) + public EnvelopeMailService(IEmailOutRepository repository, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions dispatcherConfigOptions, IConfigService configService, IOptions mailConfig, ICodeGenerator codeGenerator) : base(repository, mapper) { _tempService = tempService; _envRcvService = envelopeReceiverService; _dConfig = dispatcherConfigOptions.Value; _configService = configService; _placeholders = mailConfig.Value.Placeholders; + _codeGenerator = codeGenerator; } private async Task> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null) @@ -63,9 +67,7 @@ namespace EnvelopeGenerator.Application.Services return _placeholders; } - - public async Task> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: EmailTemplateType.DocumentAccessCodeReceived); - + public async Task> SendAsync(EnvelopeReceiverDto dto, EmailTemplateType tempType, Dictionary? optionalPlaceholders = null) { var tempSerResult = await _tempService.ReadByNameAsync(tempType); @@ -152,5 +154,22 @@ namespace EnvelopeGenerator.Application.Services return await CreateWithTemplateAsync(createDto: mail, placeholders: placeholders, dto.Envelope); } + + public async Task> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: EmailTemplateType.DocumentAccessCodeReceived); + + public Task> 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)}"); + + 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 } + }); + } } } \ No newline at end of file From 030fd0e45b5cdcdb0c4bf8fc264bd3f85ab9064f Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 12:55:53 +0100 Subject: [PATCH 082/104] refactor(HomeController): Aktualisierung zur Verwendung der SendTFAQrCodeAsync-Methode anstelle von SendAsync durch den Maildienst. --- EnvelopeGenerator.Web/Controllers/HomeController.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index d5ce93ac..f353bd21 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -238,8 +238,7 @@ namespace EnvelopeGenerator.Web.Controllers rcv.TotpSecretkey = _codeGenerator.GenerateTotpSecretKey(); rcv.TotpExpiration = DateTime.Now.AddMonths(1); await _rcvService.UpdateAsync(rcv); - var totp_qr_64 = _codeGenerator.GenerateTotpQrCode(userEmail: rcv.EmailAddress, secretKey: rcv.TotpSecretkey).ToBase64String(); - await _mailService.SendAsync(er_secret, EmailTemplateType.TotpSecret); + await _mailService.SendTFAQrCodeAsync(er_secret); } return await TFAView(auth.UserSelectSMS); } From c6fc665002755a1d8edd715c1c965b548fdf256c Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 14:45:36 +0100 Subject: [PATCH 083/104] =?UTF-8?q?refactor(EnvelopeMailService):=20Hinzuf?= =?UTF-8?q?=C3=BCgen=20von=20[TFA=5FEXPIRATION]=20=C3=BCber=20optionale=20?= =?UTF-8?q?Platzhalter=20in=20der=20Methode=20SendTFAQrCodeAsync.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/EnvelopeMailService.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs index 0763fb59..99a77ca0 100644 --- a/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs +++ b/EnvelopeGenerator.Application/Services/EnvelopeMailService.cs @@ -164,11 +164,14 @@ namespace EnvelopeGenerator.Application.Services 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_QR_CODE]", totp_qr_64 }, + {"[TFA_EXPIRATION]", dto.Receiver.TotpExpiration } }); } } From 556d02870e5730eb4ca818cc2aa901bc46d70b80 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 14:56:30 +0100 Subject: [PATCH 084/104] refactor(CodeGeneratorParams): DefaultTotpSecretKeyLength auf 20 setzen. --- .../Configurations/CodeGeneratorParams.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs b/EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs index f4c8e1b1..2ba65399 100644 --- a/EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs +++ b/EnvelopeGenerator.Application/Configurations/CodeGeneratorParams.cs @@ -4,7 +4,8 @@ { public string CharPool { get; init; } = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789012345678901234567890123456789"; - public int DefaultTotpSecretKeyLength { get; init; } = 32; + //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"; From 6b6c8e407c25d83b6854dee18bddc60a9354a0b3 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 15:22:33 +0100 Subject: [PATCH 085/104] refactor(EnvelopeLocked): Umbenennung von AccessCodeName in CodeType. - HomeController aktualisiert. --- EnvelopeGenerator.Web/Controllers/HomeController.cs | 10 +++++----- EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index f353bd21..0d1c0ade 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -193,9 +193,9 @@ namespace EnvelopeGenerator.Web.Controllers { var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId); if (res.Ok) - return View("EnvelopeLocked").WithData("AccessCodeName", "smsCode").WithData("Expiration", res.Expiration); + return View("EnvelopeLocked").WithData("CodeType", "smsCode").WithData("Expiration", res.Expiration); else if (!res.Allowed) - return View("EnvelopeLocked").WithData("AccessCodeName", "smsCode").WithData("Expiration", res.AllowedAt); + return View("EnvelopeLocked").WithData("CodeType", "smsCode").WithData("Expiration", res.AllowedAt); else { var res_json = JsonConvert.SerializeObject(res); @@ -205,7 +205,7 @@ namespace EnvelopeGenerator.Web.Controllers } else { - return View("EnvelopeLocked").WithData("AccessCodeName", "authenticatorCode"); + return View("EnvelopeLocked").WithData("CodeType", "authenticatorCode"); } } @@ -221,13 +221,13 @@ namespace EnvelopeGenerator.Web.Controllers if (er_secret.AccessCode != auth.AccessCode) { //Constants.EnvelopeStatus.AccessCodeIncorrect - await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeIncorrect); + await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, EnvelopeStatus.AccessCodeIncorrect); Response.StatusCode = StatusCodes.Status401Unauthorized; return View("EnvelopeLocked") .WithData("ErrorMessage", _localizer[WebKey.WrongAccessCode].Value); } - await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, Constants.EnvelopeStatus.AccessCodeCorrect); + await _historyService.RecordAsync(er_secret.EnvelopeId, er_secret.Receiver!.EmailAddress, EnvelopeStatus.AccessCodeCorrect); //check if the user has phone is added if (er_secret.TFAEnabled) diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index cc285a6c..6c870f80 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -6,10 +6,10 @@ var logo = _logoOpt.Value; ViewData["Title"] = _localizer[WebKey.DocProtected]; var userCulture = ViewData["UserCulture"] as Culture; - string accessCodeName = ViewData["AccessCodeName"] is string _accessCodeName ? _accessCodeName : "accessCode"; - string codePropName = char.ToUpper(accessCodeName[0]) + accessCodeName.Substring(1); - bool viaSms = accessCodeName == "smsCode"; - bool viaAuthenticator = accessCodeName == "authenticatorCode"; + string codeType = ViewData["CodeType"] is string _accessCodeName ? _accessCodeName : "accessCode"; + string codePropName = char.ToUpper(codeType[0]) + codeType.Substring(1); + bool viaSms = codeType == "smsCode"; + bool viaAuthenticator = codeType == "authenticatorCode"; bool viaTFA = viaSms || viaAuthenticator; DateTime? expiration = ViewData["Expiration"] is DateTime _expiration ? _expiration : null; bool tfaEnabled = ViewData["TFAEnabled"] is bool _tfaEnabled && _tfaEnabled; @@ -36,7 +36,7 @@
- +
-
+
diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.css b/EnvelopeGenerator.Web/wwwroot/css/site.css index 82c1601e..00fa9a6d 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.css @@ -225,7 +225,7 @@ footer { color: #000; } - .page header .icon.locked.sms-tfa { + .page header .icon.locked.tfa { background-color: #ff7207; color: #000; } diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.min.css b/EnvelopeGenerator.Web/wwwroot/css/site.min.css index fed1d51e..4a2cdb24 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.min.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.min.css @@ -1 +1 @@ -.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffa407;color:#000}.page header .icon.locked.sms-tfa{background-color:#ff7207;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:space-between;flex-direction:row;align-items:center}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0;margin:0;height:100%}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}#sms-timer{height:3rem;display:flex;align-items:center;font-family:'Arial',sans-serif;font-weight:bold;color:#fff;background-color:#007bff;margin:0 0 0 2rem;border-radius:8px;text-align:center}#sms-timer:hover{background-color:#0056b3;cursor:pointer}.form-check.tfa-sms{margin-left:2rem}.form-check.tfa-sms .form-check-label{font-size:.875rem;font-weight:500;margin-left:-.1rem}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file +.navbar-toggler{border:0}.material-symbols-outlined{align-content:center}.btn-group{margin-right:10vw;margin-bottom:10vh}.btn_refresh,.btn_reject,.btn_complete{height:2.5rem}.btn_complete .icon,.btn_reject .icon,.btn_refresh .icon{width:1.1rem}.btn_complete span,.btn_reject span,.btn_refresh span{vertical-align:middle}.button-finish{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-finish:hover{color:#fff;background-color:#0b5ed7;border-color:#0a58ca}.button-finish:focus{box-shadow:0 0 0 .25rem rgba(49,132,253,.5)}.button-finish:active{color:#fff;background-color:#0a58ca;border-color:#0a53be;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-finish:disabled{color:#fff;background-color:#0d6efd;border-color:#0d6efd}.button-reject{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reject:hover{color:#fff;background-color:#bb2d3b;border-color:#b02a37}.button-reject:focus{box-shadow:0 0 0 .25rem rgba(225,83,97,.5)}.button-reject:active{color:#fff;background-color:#b02a37;border-color:#a52834;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reject:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.button-reset{color:#fff;background-color:#6c757d;border-color:#6c757d}.button-reset:hover{color:#fff;background-color:#5c636a;border-color:#565e64}.button-reset:focus{box-shadow:0 0 0 .25rem rgba(130,138,145,.5)}.button-reset:active{color:#fff;background-color:#565e64;border-color:#51585e;box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.button-reset:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}body{background:#f8fcfc;display:flex;flex-direction:column;height:100vh;margin:0}main{display:flex;margin:0 0 .5vh 0}.home-description{text-align:justify;font-family:Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New;font-weight:500;font-size:.95em;letter-spacing:-1px;word-spacing:-2px}.envelope-view{display:flex;flex-direction:column;width:100vw;height:95.9vh}#app{background:#808080;width:100vw;height:100%;flex-grow:1;border-width:0}footer{height:4vh;min-height:1.5rem;background-color:#001f61;border-radius:10px 10px 0 0;color:#fff;font-family:'Muli';padding:.5vh 0;position:fixed;bottom:0;width:100%;z-index:998;border-width:0;font-size:clamp(.58rem,1.5vw,1rem);display:flex;flex-direction:row;justify-content:space-around;align-items:center}footer *{margin-left:clamp(.5rem,2vw,1rem)}footer a{color:#ff7500;text-decoration:none}footer .dropdown-toggle,footer .flag-dropdown,footer li{margin:0;padding:0;border-width:0}footer .dropdown-menu a{padding:.25rem 1rem .25rem 1rem;margin-left:0;user-select:none}.page{margin-top:3rem;background:#fff;border-radius:.313rem;box-shadow:rgba(9,30,66,.25) 0 .25rem .5rem -.125rem,rgba(9,30,66,.08) 0 0 0 .063rem;max-width:40rem}.page section{max-width:30rem;margin:0 auto}.page header .icon{display:inline-block;border-radius:6.25rem;padding:.938rem;margin-bottom:2rem}.page header .icon.admin{background-color:#331904;color:#fecba1}.page header .icon.locked{background-color:#ffa407;color:#000}.page header .icon.locked.tfa{background-color:#ff7207;color:#000}.page header .icon.signed{background-color:#146c43;color:#fff}.page header .icon.rejected{background-color:#e4d8d5;color:#fff}.page header .icon.expired{background-color:rgba(228,216,213,.5);color:#fff}.page .form{max-width:30rem;margin:2rem auto;display:flex;gap:1rem}#form-access-code>.input,#form-admin-password>.input{flex-grow:1}#page-admin header .icon{background-color:#331904;color:#fecba1}.envelope{display:block;border:.063rem solid #eee;margin-bottom:1rem;padding:.5rem}footer#page-footer{color:#333;max-width:40rem;margin-top:1rem;font-size:.85rem}footer#page-footer a,footer#page-footer a:link,footer#page-footer a:hover,footer#page-footer a:visited,footer#page-footer a:focus{color:#444}.sender-card{background-color:transparent;border:0}.sender-card .row{height:7vh}.sender-card img{height:7vh;background-color:#d1cfcf;border-radius:3.125rem}.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{position:absolute;display:flex;width:calc(100% - 8rem);align-items:center;justify-content:start;margin-left:4rem}.envelope-message .icon{margin-right:.5rem}.envelope-message .message{font-family:'Roboto',sans-serif;font-size:16px;font-weight:550}.logo{width:9rem;position:absolute;right:0;margin-right:2rem}.none-display{display:none}.dropdown-flag img,.img-flag{width:30%;height:70%}.dropdown-flag{height:75%;width:75%}.increase-dropdown-height{min-height:25rem}.dropdown-flag .select2-container{width:100%!important;max-width:11.25rem}.lang-item{font-size:.85rem}#langDropdownMenuButton{min-width:4vw}.highlight{font-weight:700;font-size:.85rem}.signature-process-title,.signature-process-name{font-size:1.125rem}.mail-link{color:#000;text-decoration:none}.mail-link:hover{text-decoration:underline}#flex-action-panel{z-index:1050}#form-access-code{justify-content:space-evenly}.access-code-form-floating{display:flex;justify-content:space-between;flex-direction:row;align-items:center}.access-code-form-floating button{align-content:center;border-bottom-left-radius:0;border-top-left-radius:0;margin:0;height:100%}.access-code-form-floating input{align-content:center;border-bottom-right-radius:0;border-top-right-radius:0;border-right-width:0;width:7rem}#access-code-error-message{justify-content:center;align-content:center;margin:1.5rem 7rem 0 7rem;height:2.5rem}#sms-timer{height:3rem;display:flex;align-items:center;font-family:'Arial',sans-serif;font-weight:bold;color:#fff;background-color:#007bff;margin:0 0 0 2rem;border-radius:8px;text-align:center}#sms-timer:hover{background-color:#0056b3;cursor:pointer}.form-check.tfa-sms{margin-left:2rem}.form-check.tfa-sms .form-check-label{font-size:.875rem;font-weight:500;margin-left:-.1rem}.header-1{align-items:center;justify-content:space-between;margin-top:0;padding-top:0}.header-1 .text{text-align:center;margin-left:1.5vw;margin-top:0;padding-top:0}.no-receiver-explanation{padding:2.5rem}.ajs-message.ajs-custom{margin:0 0 0 0;padding:0 0 0 0;width:50rem}.ajs-message.ajs-custom .alert{display:flex;flex-direction:row}.ajs-message.ajs-custom span{margin:0 1rem 0 0}.ajs-message.ajs-custom p{margin:0;padding:0}@media(max-height:850px){.navbar .container{display:flex;padding:0;margin:0}.navbar-toggler{padding:0;margin:0;width:4rem;left:0}.envelope-message{width:calc(100% - 4rem - 9rem)}.envelope-message .message{font-size:14px;font-weight:550}.logo{width:9rem;position:absolute;right:0}.card-text,.card-text{font-size:.6rem;margin:0;padding:0}.highlight{font-weight:700;font-size:.5rem}.signature-process-title,.signature-process-name{font-size:.7rem}}@media(max-width:767px){.navbar{flex-direction:column;align-items:flex-start}.navbar-brand{font-size:.5rem;text-align:center;overflow:hidden;text-overflow:ellipsis}.envelope-message{width:calc(100% - 4rem - 4.5rem);margin-left:3rem}.envelope-message .message{font-size:12px;font-weight:550}.envelope-message .icon{margin-right:.1rem;font-size:1rem}.logo{width:5rem;right:0;margin-right:1rem}.btn_group{position:fixed;flex-direction:row;bottom:.5rem;right:.5rem}.img-fluid{width:1.2rem;height:100%;display:none}.page{margin-top:1rem;max-width:90%;padding:.5rem}.page section{max-width:90%}#form-access-code{margin-left:0}}@media(max-width:1024px){#flex-action-panel,.btn-desktop{display:none}}@media(max-height:600px){.collapse{height:4rem}} \ No newline at end of file From abda0d14e8c1ade3cb605fb91f3f3d064832ea07 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 15:41:31 +0100 Subject: [PATCH 087/104] fix: Behebung der falschen Variablenbenennung bei der Zuweisung von `codeType` --- EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index 8d8c5081..abe014c4 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -6,7 +6,7 @@ var logo = _logoOpt.Value; ViewData["Title"] = _localizer[WebKey.DocProtected]; var userCulture = ViewData["UserCulture"] as Culture; - string codeType = ViewData["CodeType"] is string _accessCodeName ? _accessCodeName : "accessCode"; + string codeType = ViewData["CodeType"] is string _codeType ? _codeType : "accessCode"; string codePropName = char.ToUpper(codeType[0]) + codeType.Substring(1); bool viaSms = codeType == "smsCode"; bool viaAuthenticator = codeType == "authenticatorCode"; From 3b5c6086a9aee947e781dc380442244e9283261c Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 16:21:31 +0100 Subject: [PATCH 088/104] =?UTF-8?q?feat(WebKey):=20Statische=20Klasse=20Fo?= =?UTF-8?q?rmats=20zur=20Aufnahme=20von=20Schl=C3=BCsselformaten=20hinzuge?= =?UTF-8?q?f=C3=BCgt.=20=20-=20Erweiterungsmethoden=20f=C3=BCr=20die=20For?= =?UTF-8?q?matierung=20von=20Tastenformaten=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/WebKey.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/EnvelopeGenerator.Web/WebKey.cs b/EnvelopeGenerator.Web/WebKey.cs index 3555be45..1b8ec48f 100644 --- a/EnvelopeGenerator.Web/WebKey.cs +++ b/EnvelopeGenerator.Web/WebKey.cs @@ -42,5 +42,22 @@ public static readonly string ViewDoc = nameof(ViewDoc); public static readonly string HomePageDescription = nameof(HomePageDescription); public static readonly string Privacy = nameof(Privacy); + + public static class Formats + { + public static readonly string LockedTitle = "Locked{0}Title"; + + public static readonly string LockedBody = "Locked{0}Body"; + + public static readonly string LockedCodeLabel = "Locked{0}CodeLabel"; + + public static readonly string LockedFooterTitle = "Locked{0}FooterTitle"; + + public static readonly string LockedFooterBody = "Locked{0}FooterBody"; + } + + public static string Format(this string st, object? arg0) => string.Format(st, arg0: arg0); + + public static string Format(this string st, params object?[] args) => string.Format(st, args: args); } } \ No newline at end of file From 10a5adeeeef9bcb9ece49ac4b38e7f024fc3fcc1 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 16:29:20 +0100 Subject: [PATCH 089/104] fix: LocakedOpen entfernt. --- EnvelopeGenerator.Application/Resources/Resource.de-DE.resx | 3 --- EnvelopeGenerator.Application/Resources/Resource.en-US.resx | 3 --- EnvelopeGenerator.Web/WebKey.cs | 1 - 3 files changed, 7 deletions(-) diff --git a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx index 4950cd18..95cfca23 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx @@ -159,9 +159,6 @@ 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. - - Öffnen - Bitte überprüfen Sie die Standortinformationen. Wenn sie falsch sind, korrigieren Sie diese bitte. diff --git a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx index 00598290..af769710 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx @@ -159,9 +159,6 @@ 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. - - Open - Please review the location information. If it is incorrect, kindly make the necessary corrections. diff --git a/EnvelopeGenerator.Web/WebKey.cs b/EnvelopeGenerator.Web/WebKey.cs index 1b8ec48f..8fc05137 100644 --- a/EnvelopeGenerator.Web/WebKey.cs +++ b/EnvelopeGenerator.Web/WebKey.cs @@ -14,7 +14,6 @@ public static readonly string LockedSmsTfaTitle = nameof(LockedSmsTfaTitle); public static readonly string LockedBody = nameof(LockedBody); public static readonly string LockedSmsTfaBody = nameof(LockedSmsTfaBody); - public static readonly string LocakedOpen = nameof(LocakedOpen); public static readonly string LockedAccessCode = nameof(LockedAccessCode); public static readonly string LockedSmsAccessCode = nameof(LockedSmsAccessCode); public static readonly string LockedFooterTitle = nameof(LockedFooterTitle); From 15f3bd1bbd1a12ac9a5f5431622a72ad69b81214 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 16:39:01 +0100 Subject: [PATCH 090/104] =?UTF-8?q?refactor(WebKey.Formate):=20Aktualisier?= =?UTF-8?q?t,=20um=20in=20der=20resx-Datei=20in=20alphabetischer=20Reihenf?= =?UTF-8?q?olge=20gruppieren=20zu=20k=C3=B6nnen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EnvelopeGenerator.Web/WebKey.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Web/WebKey.cs b/EnvelopeGenerator.Web/WebKey.cs index 8fc05137..11c938c0 100644 --- a/EnvelopeGenerator.Web/WebKey.cs +++ b/EnvelopeGenerator.Web/WebKey.cs @@ -44,15 +44,15 @@ public static class Formats { - public static readonly string LockedTitle = "Locked{0}Title"; + public static readonly string LockedTitle = nameof(LockedTitle) + "{0}"; - public static readonly string LockedBody = "Locked{0}Body"; + public static readonly string LockedBody = nameof(LockedBody) + "{0}"; - public static readonly string LockedCodeLabel = "Locked{0}CodeLabel"; + public static readonly string LockedCodeLabel = nameof(LockedCodeLabel) + "{0}"; - public static readonly string LockedFooterTitle = "Locked{0}FooterTitle"; + public static readonly string LockedFooterTitle = nameof(LockedFooterTitle) + "{0}"; - public static readonly string LockedFooterBody = "Locked{0}FooterBody"; + public static readonly string LockedFooterBody = nameof(LockedFooterBody) + "{0}"; } public static string Format(this string st, object? arg0) => string.Format(st, arg0: arg0); From 103d8da6b2b63ba791896553fe3447efc99623bd Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 16:54:02 +0100 Subject: [PATCH 091/104] =?UTF-8?q?refactor(Resource.resx):=20Aktualisiert?= =?UTF-8?q?e=20Schl=C3=BCsselnamen=20f=C3=BCr=20Schl=C3=BCsselformate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/Resource.de-DE.resx | 34 +++++++++---------- .../Resources/Resource.en-US.resx | 34 +++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx index 95cfca23..d8247391 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx @@ -162,36 +162,36 @@ Bitte überprüfen Sie die Standortinformationen. Wenn sie falsch sind, korrigieren Sie diese bitte. - - Zugriffscode - - + Wir haben Ihnen gerade den Zugriffscode an die hinterlegte Email Adresse gesendet. Dies kann evtl. einige Minuten dauern. - - 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. + + Wir haben soeben den Zugangscode als SMS an die von Ihnen angegebene Telefonnummer gesendet. - - Sie haben keinen Zugriffscode erhalten? + + Zugriffscode - + SMS-Code - - Wir haben soeben den Zugangscode als SMS an die von Ihnen angegebene Telefonnummer gesendet. + + 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. - + 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. - - Sie haben keine SMS erhalten? + + Sie haben keinen Zugriffscode erhalten? - - 2-Faktor-Authentifizierung + + Sie haben keine SMS erhalten? - + Dokument erfordert einen Zugriffscode + + 2-Faktor-Authentifizierung + Datenschutz diff --git a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx index af769710..5d120122 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx @@ -162,36 +162,36 @@ Please review the location information. If it is incorrect, kindly make the necessary corrections. - - Access Code - - + We have just sent you the access code to the email address you provided. This may take a few minutes. - - Please check your email inbox including your spam folder. Furthermore, you can also ask the sender to send the code by other means. + + We have just sent the access code as an SMS to the phone number you provided. - - You have not received an access code? + + Access Code - + SMS Code - - We have just sent the access code as an SMS to the phone number you provided. + + Please check your email inbox including your spam folder. Furthermore, you can also ask the sender to send the code by other means. - + 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. - - You have not received an SMS? + + You have not received an access code? - - 2-Factor Authentication + + You have not received an SMS? - + Document requires an access code + + 2-Factor Authentication + Privacy From 4b50b6c35d3a508b26ac94d02d26fdee5086b340 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 17:32:17 +0100 Subject: [PATCH 092/104] =?UTF-8?q?refactor(Resource.resx):=20Schl=C3=BCss?= =?UTF-8?q?el-Werte=20f=C3=BCr=20Authenticators=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/Resource.de-DE.resx | 18 ++++++++++++++++++ .../Resources/Resource.en-US.resx | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx index d8247391..6a951a19 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.de-DE.resx @@ -165,30 +165,48 @@ Wir haben Ihnen gerade den Zugriffscode an die hinterlegte Email Adresse gesendet. Dies kann evtl. einige Minuten dauern. + + Ihr QR-Code ist bis {0} gültig. + + + 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. + Wir haben soeben den Zugangscode als SMS an die von Ihnen angegebene Telefonnummer gesendet. Zugriffscode + + TOTP + SMS-Code 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. + + 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. + 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. Sie haben keinen Zugriffscode erhalten? + + Sie haben keinen QR-Code erhalten? + Sie haben keine SMS erhalten? Dokument erfordert einen Zugriffscode + + 2-Faktor-Authentifizierung + 2-Faktor-Authentifizierung diff --git a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx index 5d120122..4ae7197e 100644 --- a/EnvelopeGenerator.Application/Resources/Resource.en-US.resx +++ b/EnvelopeGenerator.Application/Resources/Resource.en-US.resx @@ -165,30 +165,48 @@ We have just sent you the access code to the email address you provided. This may take a few minutes. + + Your QR code is valid until {0}. + + + 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. + We have just sent the access code as an SMS to the phone number you provided. Access Code + + TOTP + SMS Code Please check your email inbox including your spam folder. Furthermore, you can also ask the sender to send the code by other means. + + 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. + 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. You have not received an access code? + + You have not received a QR code? + You have not received an SMS? Document requires an access code + + 2-Factor Authentication + 2-Factor Authentication From e82d7552c2679cb62be3ccc1e35dfbcc2f71dfdf Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 17:58:46 +0100 Subject: [PATCH 093/104] =?UTF-8?q?refactor(EnvelopeLocked):=20Formatierba?= =?UTF-8?q?re=20Schl=C3=BCsselnamen=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/Home/EnvelopeLocked.cshtml | 13 +++++++------ EnvelopeGenerator.Web/WebKey.cs | 10 ---------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index abe014c4..a64fe20c 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -8,6 +8,7 @@ var userCulture = ViewData["UserCulture"] as Culture; string codeType = ViewData["CodeType"] is string _codeType ? _codeType : "accessCode"; string codePropName = char.ToUpper(codeType[0]) + codeType.Substring(1); + string codeKeyName = codePropName.Replace("Code", ""); bool viaSms = codeType == "smsCode"; bool viaAuthenticator = codeType == "authenticatorCode"; bool viaTFA = viaSms || viaAuthenticator; @@ -27,17 +28,17 @@
-

@_localizer[viaSms ? WebKey.LockedSmsTfaTitle : WebKey.LockedTitle]

+

@_localizer[WebKey.Formats.LockedTitle.Format(codeKeyName)]

-

@_localizer[viaSms ? WebKey.LockedSmsTfaBody : WebKey.LockedBody]

+

@_localizer[WebKey.Formats.LockedBody.Format(codeKeyName)].Value.Format("")

- - + +
diff --git a/EnvelopeGenerator.Web/WebKey.cs b/EnvelopeGenerator.Web/WebKey.cs index 11c938c0..e039ba05 100644 --- a/EnvelopeGenerator.Web/WebKey.cs +++ b/EnvelopeGenerator.Web/WebKey.cs @@ -10,16 +10,6 @@ public static readonly string NonDecodableEnvelopeReceiverId = nameof(NonDecodableEnvelopeReceiverId); public static readonly string de_DE = nameof(de_DE).Replace("_", "-"); public static readonly string en_US = nameof(en_US).Replace("_", "-"); - public static readonly string LockedTitle = nameof(LockedTitle); - public static readonly string LockedSmsTfaTitle = nameof(LockedSmsTfaTitle); - public static readonly string LockedBody = nameof(LockedBody); - public static readonly string LockedSmsTfaBody = nameof(LockedSmsTfaBody); - public static readonly string LockedAccessCode = nameof(LockedAccessCode); - public static readonly string LockedSmsAccessCode = nameof(LockedSmsAccessCode); - public static readonly string LockedFooterTitle = nameof(LockedFooterTitle); - public static readonly string LockedSmsTfaFooterTitle = nameof(LockedSmsTfaFooterTitle); - public static readonly string LockedFooterBody = nameof(LockedFooterBody); - public static readonly string LockedSmsTfaFooterBody = nameof(LockedSmsTfaFooterBody); public static readonly string WrongAccessCode = nameof(WrongAccessCode); public static readonly string SignDoc = nameof(SignDoc); public static readonly string DocRejected = nameof(DocRejected); From 72a0cb78c750b1b0bda2861221678f3b97314c63 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Wed, 11 Dec 2024 18:00:48 +0100 Subject: [PATCH 094/104] refactor(EnvelopeLocked): Umbenennung von Expiration in SmsExpiration. - HomeController aktualisiert. --- EnvelopeGenerator.Web/Controllers/HomeController.cs | 4 ++-- EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 0d1c0ade..18b7de70 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -193,9 +193,9 @@ namespace EnvelopeGenerator.Web.Controllers { var res = await _msgService.SendSmsCodeAsync(er_secret.PhoneNumber!, envelopeReceiverId: envelopeReceiverId); if (res.Ok) - return View("EnvelopeLocked").WithData("CodeType", "smsCode").WithData("Expiration", res.Expiration); + return View("EnvelopeLocked").WithData("CodeType", "smsCode").WithData("SmsExpiration", res.Expiration); else if (!res.Allowed) - return View("EnvelopeLocked").WithData("CodeType", "smsCode").WithData("Expiration", res.AllowedAt); + return View("EnvelopeLocked").WithData("CodeType", "smsCode").WithData("SmsExpiration", res.AllowedAt); else { var res_json = JsonConvert.SerializeObject(res); diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml index a64fe20c..b4ee9905 100644 --- a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -12,7 +12,7 @@ bool viaSms = codeType == "smsCode"; bool viaAuthenticator = codeType == "authenticatorCode"; bool viaTFA = viaSms || viaAuthenticator; - DateTime? expiration = ViewData["Expiration"] is DateTime _expiration ? _expiration : null; + DateTime? smsExpiration = ViewData["SmsExpiration"] is DateTime _smsExpiration ? _smsExpiration : null; bool tfaEnabled = ViewData["TFAEnabled"] is bool _tfaEnabled && _tfaEnabled; bool hasPhoneNumber = ViewData["HasPhoneNumber"] is bool _hasPhoneNumber && _hasPhoneNumber; } @@ -58,7 +58,7 @@
} - @if (expiration is not null) + @if (smsExpiration is not null) { } @@ -81,7 +81,7 @@