diff --git a/EnvelopeGenerator.Common/Constants.vb b/EnvelopeGenerator.Common/Constants.vb index 0e0d3933..a3c6fa73 100644 --- a/EnvelopeGenerator.Common/Constants.vb +++ b/EnvelopeGenerator.Common/Constants.vb @@ -12,12 +12,16 @@ EnvelopeArchived = 1007 EnvelopeTransmittedDMS = 1008 EnvelopeDeleted = 1009 - DocumentOpened = 2001 - DocumentSigned = 2002 - SignatureConfirmed = 2003 + AccessCodeRequested = 2001 + AccessCodeCorrect = 2002 + AccessCodeIncorrect = 2003 + DocumentOpened = 2004 + DocumentSigned = 2005 + SignatureConfirmed = 2006 MessageInvitationSent = 3001 ' Wird von Trigger verwendet - MessageConfirmationSent = 3002 - MessageDeletionSent = 3003 + MessageAccessCodeSent = 3002 + MessageConfirmationSent = 3003 + MessageDeletionSent = 3004 End Enum Public Enum ElementStatus diff --git a/EnvelopeGenerator.Common/Entities/EmailData.vb b/EnvelopeGenerator.Common/Entities/EmailData.vb index 2eae980b..673f3a1f 100644 --- a/EnvelopeGenerator.Common/Entities/EmailData.vb +++ b/EnvelopeGenerator.Common/Entities/EmailData.vb @@ -7,10 +7,11 @@ Public Class EmailData Public Property ReferenceID As Integer Public Property ReferenceString As String - + Public Property ReceiverAccessCode As String Public Property ReceiverName As String Public Property SenderName As String Public Property SenderAdress As String + Public Property SignatureLink As String Public Property Message As String Public Property EnvelopeTitle As String @@ -23,14 +24,10 @@ Public Class EmailData ReferenceID = pEnvelope.Id ReferenceString = pEnvelope.Uuid ReceiverName = pReceiver.Name + ReceiverAccessCode = pReceiver.AccessCode SenderAdress = pEnvelope.User.Email SenderName = pEnvelope.User.FullName EnvelopeTitle = pEnvelope.Title End Sub - Public Sub New() - End Sub - - - End Class diff --git a/EnvelopeGenerator.Common/Entities/EmailTemplate.vb b/EnvelopeGenerator.Common/Entities/EmailTemplate.vb index c870b966..b66801df 100644 --- a/EnvelopeGenerator.Common/Entities/EmailTemplate.vb +++ b/EnvelopeGenerator.Common/Entities/EmailTemplate.vb @@ -5,11 +5,13 @@ Public Class EmailTemplate Private _DocumentSignedBodyTemplate As List(Of String) Private _DocumentCompletedBodyTemplate As List(Of String) Private _DocumentDeletedBodyTemplate As List(Of String) + Private _DocumentAccessCodeReceivedBodyTemplate As List(Of String) Private _DocumentReceivedSubjectTemplate As String Private _DocumentSignedSubjectTemplate As String Private _DocumentDeletedSubjectTemplate As String Private _DocumentCompletedSubjectTemplate As String + Private _DocumentAccessCodeReceivedSubjectTemplate As String Private _replaceDictionary As Dictionary(Of String, String) @@ -27,6 +29,8 @@ Public Class EmailTemplate _DocumentSignedSubjectTemplate = "Dokument unterschrieben: '[DOCUMENT_TITLE]'" _DocumentDeletedSubjectTemplate = "Vorgang zurückgezogen: '[DOCUMENT_TITLE]'" _DocumentCompletedSubjectTemplate = "Vorgang abgeschlossen: '[DOCUMENT_TITLE]'" + _DocumentAccessCodeReceivedSubjectTemplate = "Dokument Passwort erhalten: '[DOCUMENT_TITLE]'" + End Sub Private Sub InitBodyTemplates() @@ -44,6 +48,7 @@ Public Class EmailTemplate } '_DocumentReceivedBodyTemplate = Common.My.Resources.email_de.Split(vbNewLine).ToList() + '_DocumentAccessCodeReceivedBodyTemplate = Common.My.Resources. _DocumentSignedBodyTemplate = New List(Of String) From { "Guten Tag [NAME_RECEIVER]", @@ -72,6 +77,18 @@ Public Class EmailTemplate "Vielen Dank für die Nutzung von", "[NAME_PORTAL]" } + + _DocumentAccessCodeReceivedBodyTemplate = New List(Of String) From { + "Guten Tag [NAME_RECEIVER]", + "", + "[NAME_SENDER] hat Ihnen ein Dokument zum [SIGNATURE_TYPE] gesendet. ", + "Verwenden Sie das folgende Passwort, um das Dokument einzusehen:", + "", + "[DOCUMENT_ACCESS_CODE]", + "", + "Vielen Dank für die Nutzung von", + "[NAME_PORTAL]" + } End Sub Private Sub InitDictionary(pEmailData As EmailData) @@ -83,7 +100,8 @@ Public Class EmailTemplate {"[LINK_TO_DOCUMENT]", pEmailData.SignatureLink}, {"[LINK_TO_DOCUMENT_TEXT]", $"{pEmailData.SignatureLink.Truncate(40)}.."}, {"[DOCUMENT_TITLE]", pEmailData.EnvelopeTitle}, - {"[MESSAGE]", pEmailData.Message} + {"[MESSAGE]", pEmailData.Message}, + {"[DOCUMENT_ACCESS_CODE]", pEmailData.ReceiverAccessCode} } End Sub @@ -107,7 +125,12 @@ Public Class EmailTemplate FillEmailSubject(pEmailData, _DocumentCompletedSubjectTemplate) End Sub - Public Sub FillEmailSubject(pEmailData As EmailData, pTemplate As String) + Public Sub FillDocumentAccessCodeReceivedEmailBody(pEmailData As EmailData) + FillEmailBody(pEmailData, _DocumentAccessCodeReceivedBodyTemplate) + FillEmailSubject(pEmailData, _DocumentAccessCodeReceivedSubjectTemplate) + End Sub + + Private Sub FillEmailSubject(pEmailData As EmailData, pTemplate As String) InitDictionary(pEmailData) Dim oSubject As String = pTemplate @@ -122,7 +145,7 @@ Public Class EmailTemplate pEmailData.EmailSubject = oSubject End Sub - Public Sub FillEmailBody(pEmailData As EmailData, pTemplate As List(Of String)) + Private Sub FillEmailBody(pEmailData As EmailData, pTemplate As List(Of String)) InitDictionary(pEmailData) Dim oBody As String = "" diff --git a/EnvelopeGenerator.Common/EnvelopeGenerator.Common.vbproj b/EnvelopeGenerator.Common/EnvelopeGenerator.Common.vbproj index 39da6d18..690e07db 100644 --- a/EnvelopeGenerator.Common/EnvelopeGenerator.Common.vbproj +++ b/EnvelopeGenerator.Common/EnvelopeGenerator.Common.vbproj @@ -277,6 +277,7 @@ PreserveNewest + diff --git a/EnvelopeGenerator.Common/Models/ReceiverModel.vb b/EnvelopeGenerator.Common/Models/ReceiverModel.vb index d02fd76b..9d91c796 100644 --- a/EnvelopeGenerator.Common/Models/ReceiverModel.vb +++ b/EnvelopeGenerator.Common/Models/ReceiverModel.vb @@ -32,6 +32,7 @@ Public Class ReceiverModel .Signature = pRow.ItemEx("SIGNATURE", ""), .Status = ReceiverSignedStatus, .ColorType = DirectCast(pColorIndex + 1, ColorType), + .AccessCode = pRow.ItemEx("ACCESS_CODE", ""), .SignedDate = SignedDate } End Function @@ -261,10 +262,11 @@ Public Class ReceiverModel End Try End Function - Private Function GetSignedDate(pEmailAdress As String, pEnvleopeId As Integer) As Date + Private Function GetSignedDate(pEmailAddress As String, pEnvelopeId As Integer) As Date Try - Return Database.GetScalarValue($"SELECT ACTION_DATE FROM [DD_ECM].[dbo].[TBSIG_ENVELOPE_HISTORY] WHERE ENVELOPE_ID = {pEnvleopeId} - AND USER_REFERENCE = '{pEmailAdress}' AND [STATUS] = 2002") + Dim oStatusInt As Integer = EnvelopeStatus.DocumentSigned + Return Database.GetScalarValue($"SELECT ACTION_DATE FROM [DD_ECM].[dbo].[TBSIG_ENVELOPE_HISTORY] WHERE ENVELOPE_ID = {pEnvelopeId} + And USER_REFERENCE = '{pEmailAddress}' AND [STATUS] = {oStatusInt}") Catch ex As Exception Logger.Error(ex) @@ -272,4 +274,17 @@ Public Class ReceiverModel End Try End Function + Public Function AccessCodeAlreadyRequested(pEmailAddress As String, pEnvelopeId As Integer) As Boolean + Try + Dim oStatusInt As Integer = EnvelopeStatus.AccessCodeRequested + Dim oResult As Integer = Database.GetScalarValue($"SELECT COUNT(*) FROM [DD_ECM].[dbo].[TBSIG_ENVELOPE_HISTORY] + WHERE ENVELOPE_ID = {pEnvelopeId} And USER_REFERENCE = '{pEmailAddress}' AND [STATUS] = {oStatusInt}") + + Return oResult > 0 + Catch ex As Exception + Logger.Error(ex) + Return False + End Try + End Function + End Class diff --git a/EnvelopeGenerator.Common/Services/ActionService.vb b/EnvelopeGenerator.Common/Services/ActionService.vb index 2d1fa7fa..e759a7f9 100644 --- a/EnvelopeGenerator.Common/Services/ActionService.vb +++ b/EnvelopeGenerator.Common/Services/ActionService.vb @@ -60,6 +60,36 @@ Public Class ActionService Return True End Function + Public Function RequestAccessCode(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean + Dim oUserReference = pReceiver.Email + + If HistoryService.SetEnvelopeStatus(pEnvelope, Constants.EnvelopeStatus.AccessCodeRequested, oUserReference) = False Then + Return False + End If + + Return True + End Function + + Public Function EnterCorrectAccessCode(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean + Dim oUserReference = pReceiver.Email + + If HistoryService.SetEnvelopeStatus(pEnvelope, Constants.EnvelopeStatus.AccessCodeCorrect, oUserReference) = False Then + Return False + End If + + Return True + End Function + + Public Function EnterIncorrectAccessCode(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean + Dim oUserReference = pReceiver.Email + + If HistoryService.SetEnvelopeStatus(pEnvelope, Constants.EnvelopeStatus.AccessCodeIncorrect, oUserReference) = False Then + Return False + End If + + Return True + End Function + Public Function SignEnvelope(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean Dim oUserReference = pReceiver.Email diff --git a/EnvelopeGenerator.Common/Services/EmailService.vb b/EnvelopeGenerator.Common/Services/EmailService.vb index da531942..c23ea3cc 100644 --- a/EnvelopeGenerator.Common/Services/EmailService.vb +++ b/EnvelopeGenerator.Common/Services/EmailService.vb @@ -5,8 +5,6 @@ Imports DigitalData.Modules.Logging Public Class EmailService Inherits BaseService - Private ReadOnly State As State - Private ReadOnly EnvelopeModel As EnvelopeModel Private ReadOnly ReceiverModel As ReceiverModel Private ReadOnly EmailModel As EmailModel @@ -54,6 +52,23 @@ Public Class EmailService Return True End Function + Public Function SendDocumentAccessCodeReceivedEmail(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean + + Dim oEmailData As New EmailData(pEnvelope, pReceiver, Constants.EnvelopeStatus.MessageAccessCodeSent) With + { + .SignatureLink = Helpers.GetEnvelopeURL(State.DbConfig.SignatureHost, pEnvelope.Uuid, pReceiver.Signature) + } + + EmailTemplate.FillDocumentAccessCodeReceivedEmailBody(oEmailData) + + If EmailModel.Insert(oEmailData) = False Then + Logger.Error("EMail data could not be inserted.") + Return False + End If + + Return True + End Function + Public Function SendSignedEmail(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean Dim oEmailData = New EmailData(pEnvelope, pReceiver, Constants.EnvelopeStatus.MessageConfirmationSent) With { diff --git a/EnvelopeGenerator.Common/Templates/document_access_code_de.html b/EnvelopeGenerator.Common/Templates/document_access_code_de.html new file mode 100644 index 00000000..e5e4abf4 --- /dev/null +++ b/EnvelopeGenerator.Common/Templates/document_access_code_de.html @@ -0,0 +1,450 @@ + + + + + + + + + Trigger newsletter 3 + + + + + + + +
+ + + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + + +
+ + + + + + +
+
+ + + + + + +
+ + + + + + +

Put your preheader text here

+
+
+
+ + + + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + +

[MAIL_SUBJECT]

Guten Tag [NAME_RECEIVER],

[NAME_SENDER] hat Ihnen ein Dokument zum [SIGNATURE_TYPE] gesendet. Verwenden Sie das folgende Passwort, um das Dokument einzusehen:

[DOCUMENT_ACCESS_CODE]

Mit freundlichen Grüßen,

+
+
+ + + + + + + +
+ + + + + + +
+
+ + + + + + +
+ + + + + + +

[NAME_PORTAL]

+
+
+
+ + + + + + + +
+
+ + + \ No newline at end of file diff --git a/EnvelopeGenerator.Form/frmMain.Designer.vb b/EnvelopeGenerator.Form/frmMain.Designer.vb index 9e8d361c..047f4e10 100644 --- a/EnvelopeGenerator.Form/frmMain.Designer.vb +++ b/EnvelopeGenerator.Form/frmMain.Designer.vb @@ -80,6 +80,7 @@ Partial Class frmMain Me.GridColumn5 = New DevExpress.XtraGrid.Columns.GridColumn() Me.GridColumn7 = New DevExpress.XtraGrid.Columns.GridColumn() Me.RefreshTimer = New System.Windows.Forms.Timer(Me.components) + Me.colAccessCode = New DevExpress.XtraGrid.Columns.GridColumn() CType(Me.SplitContainerControl1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.SplitContainerControl1.Panel1, System.ComponentModel.ISupportInitialize).BeginInit() Me.SplitContainerControl1.Panel1.SuspendLayout() @@ -157,7 +158,7 @@ Partial Class frmMain ' 'ViewReceivers ' - Me.ViewReceivers.Columns.AddRange(New DevExpress.XtraGrid.Columns.GridColumn() {Me.ColReceiverStatus, Me.ColName, Me.ColEmail, Me.ColSignedDate, Me.ColStatusReceiver}) + Me.ViewReceivers.Columns.AddRange(New DevExpress.XtraGrid.Columns.GridColumn() {Me.ColReceiverStatus, Me.ColName, Me.ColEmail, Me.ColSignedDate, Me.colAccessCode, Me.ColStatusReceiver}) Me.ViewReceivers.GridControl = Me.GridEnvelopes Me.ViewReceivers.Name = "ViewReceivers" Me.ViewReceivers.OptionsBehavior.Editable = False @@ -552,6 +553,12 @@ Partial Class frmMain ' Me.RefreshTimer.Interval = 120000 ' + 'colAccessCode + ' + resources.ApplyResources(Me.colAccessCode, "colAccessCode") + Me.colAccessCode.FieldName = "AccessCode" + Me.colAccessCode.Name = "colAccessCode" + ' 'frmMain ' resources.ApplyResources(Me, "$this") @@ -640,4 +647,5 @@ Partial Class frmMain Friend WithEvents btnOpenLogDirectory As DevExpress.XtraBars.BarButtonItem Friend WithEvents RibbonPage2 As DevExpress.XtraBars.Ribbon.RibbonPage Friend WithEvents RibbonPageGroup3 As DevExpress.XtraBars.Ribbon.RibbonPageGroup + Friend WithEvents colAccessCode As DevExpress.XtraGrid.Columns.GridColumn End Class diff --git a/EnvelopeGenerator.Form/frmMain.resx b/EnvelopeGenerator.Form/frmMain.resx index 78e7454e..ae785617 100644 --- a/EnvelopeGenerator.Form/frmMain.resx +++ b/EnvelopeGenerator.Form/frmMain.resx @@ -166,7 +166,7 @@ 0 - 138 + 129 Email Anrede @@ -178,7 +178,7 @@ 1 - 435 + 406 Email @@ -190,7 +190,7 @@ 2 - 377 + 332 Unterschrieben wann @@ -199,10 +199,22 @@ True - 3 + 4 - 134 + 110 + + + Zugangscode + + + True + + + 3 + + + 107 Status @@ -1265,6 +1277,12 @@ System.Windows.Forms.Timer, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + colAccessCode + + + DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a + frmMain diff --git a/EnvelopeGenerator.Web/Controllers/HomeController.cs b/EnvelopeGenerator.Web/Controllers/HomeController.cs index 737bb872..f51194f5 100644 --- a/EnvelopeGenerator.Web/Controllers/HomeController.cs +++ b/EnvelopeGenerator.Web/Controllers/HomeController.cs @@ -2,6 +2,7 @@ using EnvelopeGenerator.Web.Models; using EnvelopeGenerator.Web.Services; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Primitives; using System.Diagnostics; namespace EnvelopeGenerator.Web.Controllers @@ -10,7 +11,7 @@ namespace EnvelopeGenerator.Web.Controllers { private readonly EnvelopeService _envelopeService; - public HomeController(DatabaseService database, LoggingService logging, EnvelopeService envelopeService): base(database, logging) + public HomeController(DatabaseService databaseService, LoggingService loggingService, EnvelopeService envelopeService): base(databaseService, loggingService) { _envelopeService = envelopeService; } @@ -28,12 +29,83 @@ namespace EnvelopeGenerator.Web.Controllers [HttpGet] [Route("/EnvelopeKey/{EnvelopeReceiverId}")] public IActionResult ShowEnvelope() + { + string envelopeKey = (string)HttpContext.Request.RouteValues["EnvelopeReceiverId"]; + + EnvelopeResponse response = _envelopeService.LoadEnvelope(envelopeKey); + string accessCode = response.Receiver.AccessCode; + + if (!String.IsNullOrEmpty(accessCode)) + { + bool accessCodeAlreadyRequested = database.Models.receiverModel.AccessCodeAlreadyRequested(response.Receiver.Email, response.Envelope.Id); + + if (!accessCodeAlreadyRequested) + { + // Send email with password + bool actionResult = database.Services.actionService.RequestAccessCode(response.Envelope, response.Receiver); + bool result = database.Services.emailService.SendDocumentAccessCodeReceivedEmail(response.Envelope, response.Receiver); + } + + return Redirect($"/EnvelopeKey/{envelopeKey}/Locked"); + } + else + { + ViewData["EnvelopeKey"] = envelopeKey; + return View(); + } + } + + [HttpPost] + [Route("/EnvelopeKey/{EnvelopeReceiverId}/Locked")] + public IActionResult ShowEnvelopePost() + { + string envelopeKey = (string)HttpContext.Request.RouteValues["EnvelopeReceiverId"]; + + StringValues accessCodeFromForm = HttpContext.Request.Form["access_code"]; + + if (accessCodeFromForm.Count == 0) + { + return Redirect($"/EnvelopeKey/{envelopeKey}/Locked"); + } + + if (accessCodeFromForm.Count > 1) + { + return Redirect($"/EnvelopeKey/{envelopeKey}/Locked"); + } + + EnvelopeResponse response = _envelopeService.LoadEnvelope(envelopeKey); + string accessCode = response.Receiver.AccessCode; + + if (string.IsNullOrEmpty(accessCodeFromForm[0])) + { + return Redirect($"/EnvelopeKey/{envelopeKey}/Locked"); + } + + if (accessCode.Equals(accessCodeFromForm[0], StringComparison.Ordinal)) + { + bool actionResult = database.Services.actionService.EnterCorrectAccessCode(response.Envelope, response.Receiver); + ViewData["EnvelopeKey"] = envelopeKey; + return View("ShowEnvelope"); + } + else + { + bool actionResult = database.Services.actionService.EnterIncorrectAccessCode(response.Envelope, response.Receiver); + return Redirect($"/EnvelopeKey/{envelopeKey}/Locked"); + + } + } + + [HttpGet] + [Route("/EnvelopeKey/{EnvelopeReceiverId}/Locked")] + public IActionResult EnvelopeLocked() { ViewData["EnvelopeKey"] = HttpContext.Request.RouteValues["EnvelopeReceiverId"]; return View(); } + + [HttpGet] [Route("/EnvelopeKey/{EnvelopeReceiverId}/Success")] public IActionResult EnvelopeSigned() diff --git a/EnvelopeGenerator.Web/Services/DatabaseService.cs b/EnvelopeGenerator.Web/Services/DatabaseService.cs index 1d646d44..b8c9fe47 100644 --- a/EnvelopeGenerator.Web/Services/DatabaseService.cs +++ b/EnvelopeGenerator.Web/Services/DatabaseService.cs @@ -12,10 +12,12 @@ namespace EnvelopeGenerator.Web.Services public class ServiceContainer { public ActionService actionService; + public EmailService emailService; public ServiceContainer(State state) { actionService = new(state); + emailService = new(state); } } diff --git a/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml new file mode 100644 index 00000000..176f4ab8 --- /dev/null +++ b/EnvelopeGenerator.Web/Views/Home/EnvelopeLocked.cshtml @@ -0,0 +1,32 @@ +@{ + ViewData["Title"] = "Dokument geschützt"; +} + +
+
+
+ + + + +
+

Dokument erfordert ein Passwort

+
+ +
+

Wir haben Ihnen das Passwort an die hinterlegte Email Adresse gesendet.

+
+ +
+
+
+ + +
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/EnvelopeGenerator.Web/Views/Home/Index.cshtml b/EnvelopeGenerator.Web/Views/Home/Index.cshtml index da55e976..f02e067f 100644 --- a/EnvelopeGenerator.Web/Views/Home/Index.cshtml +++ b/EnvelopeGenerator.Web/Views/Home/Index.cshtml @@ -1,4 +1,5 @@ @using EnvelopeGenerator.Common; +@using static EnvelopeGenerator.Common.Constants; @{ ViewData["Title"] = "Home Page"; } @@ -13,12 +14,20 @@
- + @foreach (IGrouping group in ((List)@Model).GroupBy(item => item.Status).OrderBy(item => (int)item.Key)) + { +
+

@group.Key.ToString()

+ + +
+
+ }
diff --git a/EnvelopeGenerator.Web/wwwroot/css/site.css b/EnvelopeGenerator.Web/wwwroot/css/site.css index 638cbeb9..0077d5ac 100644 --- a/EnvelopeGenerator.Web/wwwroot/css/site.css +++ b/EnvelopeGenerator.Web/wwwroot/css/site.css @@ -50,3 +50,25 @@ padding: 15px; margin-bottom: 2rem; } + +/* Locked Page */ + +#page-locked header .icon { + display: inline-block; + border-radius: 10px; + padding: 15px; + margin-bottom: 2rem; +} + +#form-access-code { + max-width: 30rem; + margin: 2rem auto; + + display: flex; + gap: 1rem; +} + + #form-access-code > .input { + flex-grow: 1; + } +