Compare commits

...

21 Commits

Author SHA1 Message Date
Developer01
dc4b5bade0 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2025-05-07 16:51:02 +02:00
Developer01
6fc0c32c46 Common und Service API Send API Mails 2025-05-07 16:50:46 +02:00
Developer 02
14e6a661d3 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2025-04-29 09:37:12 +02:00
Developer 02
3d1966a715 feat(Jenkinsfile): Als Beispiel erstellt 2025-04-29 09:34:57 +02:00
Developer 02
c173814b8d refactor(AuthController): Login-Methoden aktualisieren, um NotImplementedException zu werfen, nur um Swagger-Dokumentation bereitzustellen 2025-04-29 09:21:05 +02:00
Developer 02
a85397a363 refactor(auth): Refactoring der Login-Methoden für OpenAPI-Kompatibilität
– Die Login-Methoden wurden überarbeitet, um NotImplementedException auszulösen und OpenAPI (Swagger) und Skalar zu konfigurieren.
– Unnötige using-Anweisungen wurden entfernt, um den Code zu optimieren.
2025-04-28 16:49:46 +02:00
Developer 02
2d3987b81e Add JWT Bearer authentication support
- Integrated JWT Bearer authentication for API security.
- Replaced previous CookieAuthenticationDefaults with JwtBearerDefaults as the default authentication scheme.
- Configured JWT token validation with issuer, audience, and signing key parameters.
- Added handling for token retrieval from cookies or query strings when missing in the header.
- Updated the authentication configuration to support both Cookie and JWT authentication schemes.
- Enhanced security by validating JWT tokens against provided public keys.
2025-04-28 16:18:31 +02:00
Developer 02
875ff95278 feat(AuthTokenKeys): Erstellt, um Parameter für Authentifizierungs-Tokens zu konfigurieren.
- AuthTokenKeys aus der Konfiguration in Program.cs lesen.
 - Upgrade von Core.Abstractions auf 3.5
2025-04-28 15:49:40 +02:00
Developer 02
dcdf0844cb feat(Program): DeferredServiceProvider-Instanz erstellen und Fabrik einstellen 2025-04-28 15:08:07 +02:00
Developer 02
27e9de4709 chore(Core.Abstraction): Aktualisiert auf 3.4.4 2025-04-28 15:02:49 +02:00
Developer 02
e2bdc73b76 chore: auth-hub-client hinzufügen und konfigurieren 2025-04-28 14:15:45 +02:00
Developer01
4f95a1eed4 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2025-04-28 13:27:38 +02:00
Developer01
6874e7e92c MS Initial 2.9.1 2025-04-28 13:27:27 +02:00
Developer 02
7abb3a6c8a chore(deps): NuGet-Paketversionen aktualisieren und DigitalData.Auth.Client hinzufügen 2025-04-28 10:47:55 +02:00
Developer 02
9183ba4da5 Merge branch 'feat/terminal' 2025-04-28 09:19:52 +02:00
Developer 02
08e2e91e9a feat(program): Konfiguration aus appsettings.json laden
Die Anwendung lädt nun Konfigurationseinstellungen aus einer "appsettings.json"-Datei im Basisverzeichnis.
Dies ermöglicht eine externe Konfiguration ohne Codeänderungen und unterstützt das Neuladen der Einstellungen zur Laufzeit bei Änderungen der Datei.
2025-04-28 09:16:24 +02:00
Developer 02
2966d64455 feat(terminal): ReadDocument-Befehl um PDF-Speicheroptionen erweitert
Optionen `save`, `dir` und `fileName` zum `ReadDocument`-Befehl hinzugefügt.
Wenn `save` aktiviert ist, wird das PDF an dem angegebenen oder dem Standardpfad gespeichert.
Ermöglicht dem Benutzer mehr Kontrolle über Speicherort und Dateinamen.
2025-04-25 19:33:29 +02:00
Developer 02
41cb2c2d93 fix(PDFBurnerParams): Verschieben in das Verzeichnis /FinalizeDocument 2025-04-25 11:39:59 +02:00
Developer 02
edd54ab302 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2025-04-24 16:08:48 +02:00
Developer01
5714c54385 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2025-04-24 16:00:29 +02:00
Developer01
09d2640345 V 2.9.0.0 WISAG 2025-04-24 16:00:16 +02:00
39 changed files with 701 additions and 268 deletions

View File

@@ -3,23 +3,8 @@
/// <summary> /// <summary>
/// Represents the response for reading a document. /// Represents the response for reading a document.
/// </summary> /// </summary>
public class ReadDocumentResponse public class ReadDocumentResponse : ReadDocumentResponseBase
{ {
/// <summary>
/// The unique identifier of the document.
/// </summary>
public int Guid { get; init; }
/// <summary>
/// The identifier of the associated envelope.
/// </summary>
public int EnvelopeId { get; init; }
/// <summary>
/// The date and time when the document was added.
/// </summary>
public DateTime AddedWhen { get; init; }
/// <summary> /// <summary>
/// The binary data of the document, if available. /// The binary data of the document, if available.
/// </summary> /// </summary>

View File

@@ -0,0 +1,22 @@
namespace EnvelopeGenerator.Application.Documents.Queries.Read;
/// <summary>
/// Represents the response for reading a document.
/// </summary>
public class ReadDocumentResponseBase
{
/// <summary>
/// The unique identifier of the document.
/// </summary>
public int Guid { get; init; }
/// <summary>
/// The identifier of the associated envelope.
/// </summary>
public int EnvelopeId { get; init; }
/// <summary>
/// The date and time when the document was added.
/// </summary>
public DateTime AddedWhen { get; init; }
}

View File

@@ -13,7 +13,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" /> <PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.Core.Client" Version="2.0.3" /> <PackageReference Include="DigitalData.Core.Client" Version="2.0.3" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" /> <PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" />

View File

@@ -25,6 +25,7 @@
Public Property Message As String = My.Resources.Envelope.Please_read_and_sign_this_document Public Property Message As String = My.Resources.Envelope.Please_read_and_sign_this_document
Public Property AddedWhen As Date Public Property AddedWhen As Date
Public Property ChangedWhen As Date
Public Property User As New User() Public Property User As New User()
Public Property Documents As New List(Of EnvelopeDocument) Public Property Documents As New List(Of EnvelopeDocument)

View File

@@ -8,6 +8,7 @@
Public Property HasAccess As Boolean Public Property HasAccess As Boolean
Public Property IsAdmin As Boolean Public Property IsAdmin As Boolean
Public Property GhostModeActive As Boolean
Public ReadOnly Property FullName() As String Public ReadOnly Property FullName() As String
Get Get

View File

@@ -281,7 +281,8 @@
<Compile Include="Entities\ElementStatus.vb" /> <Compile Include="Entities\ElementStatus.vb" />
<Compile Include="Entities\EmailData.vb" /> <Compile Include="Entities\EmailData.vb" />
<Compile Include="Entities\EmailTemplate.vb" /> <Compile Include="Entities\EmailTemplate.vb" />
<Compile Include="Jobs\PDFBurnerParams.vb" /> <Compile Include="Jobs\APIBackendJobs\SendInvitationMailJob.vb" />
<Compile Include="Jobs\FinalizeDocument\PDFBurnerParams.vb" />
<Compile Include="Services\TemplateService.vb" /> <Compile Include="Services\TemplateService.vb" />
<Compile Include="Entities\Envelope.vb" /> <Compile Include="Entities\Envelope.vb" />
<Compile Include="Entities\EnvelopeDocument.vb" /> <Compile Include="Entities\EnvelopeDocument.vb" />

View File

@@ -0,0 +1,170 @@
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Base
Imports GdPicture14
Imports Quartz
Imports System.Security.Cryptography
Imports System.IO
Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument.FinalizeDocumentExceptions
Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument
Imports EnvelopeGenerator.Common.Constants
Imports DevExpress.DataProcessing
Imports System.Data.SqlClient
Imports DevExpress.XtraRichEdit.Layout.Engine
Namespace Jobs
Public Class SendInvitationMailJob
Implements IJob
Private LogConfig As LogConfig
Private Logger As Logger
Private Database As MSSQLServer
Private Config As DbConfig
Private ConfigModel As ConfigModel
Private EnvelopeModel As EnvelopeModel
Private ReceiverModel As ReceiverModel
Private ActionService As ActionService
Private ReadOnly CompleteWaitTime As Integer = 1
Private myTempFiles As TempFiles
Private Class EnvelopeData
Public EnvelopeId As Integer
Public EnvelopeUUID As String
Public DocumentPath As String
End Class
Public Function Execute(pContext As IJobExecutionContext) As Task Implements IJob.Execute
LogConfig = pContext.MergedJobDataMap.Item(Constants.LOGCONFIG)
Logger = LogConfig.GetLogger()
myTempFiles = New TempFiles(LogConfig)
myTempFiles.Create()
Dim JobId = pContext.JobDetail.Key
Logger.Info("SendInvMail - Starting job {0}", JobId)
Try
Logger.Debug("SendInvMail - Loading Database..")
Database = GetDatabase(pContext, LogConfig)
Logger.Debug("SendInvMail - Loading Models & Services")
Dim oState = GetState()
InitializeModels(oState)
Logger.Debug("SendInvMail - Loading Configuration..")
Config = ConfigModel.LoadConfiguration()
oState.DbConfig = Config
InitializeServices(oState)
Config.DocumentPath = Config.DocumentPath
Logger.Debug("SendInvMail - ExportPath: [{0}]", Config.ExportPath)
Dim oCompleteStatus As Integer = Constants.EnvelopeStatus.EnvelopeCompletelySigned
Dim oSql = $"SELECT * FROM TBSIG_ENVELOPE where SOURCE = 'API' AND STATUS = 1003 order by guid"
Dim oTable = Database.GetDatatable(oSql)
Dim oEnvelopeIds As List(Of Integer) = oTable.Rows.Cast(Of DataRow).
Select(Function(r) r.Item("GUID")).
Cast(Of Integer).
ToList()
If oEnvelopeIds.Count > 0 Then
Logger.Info("SendInvMail - Found [{0}] envelopes.", oEnvelopeIds.Count)
End If
Dim oTotal As Integer = oEnvelopeIds.Count
Dim oCurrent As Integer = 1
For Each oId In oEnvelopeIds
Logger.Info("SendInvMail - Gathering Info for Envelope [{0}] ({1}/{2})", oId, oCurrent, oTotal)
Logger.Debug("SendInvMail - Loading Envelope..")
Try
Dim oEnvelope = EnvelopeModel.GetById(oId)
If oEnvelope Is Nothing Then
Logger.Warn("SendInvMail - Envelope could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
Logger.Debug("SendInvMail - Loading Envelope Data..")
Dim oEnvelopeData = GetEnvelopeData(oId)
oEnvelope.Receivers = ReceiverModel.ListEnvelopeReceivers(oEnvelope.Id).ToList()
Logger.Debug("SendInvMail - Created Reveivers!")
If oEnvelopeData Is Nothing Then
Logger.Warn("SendInvMail - EnvelopeData could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
Logger.Info("SendInvMail - Sending InvitationMails for Envelope [{0}]", oId)
If ActionService.SendEnvelope(oEnvelope) = False Then
Throw New ArgumentNullException("EnvelopeData")
End If
Catch ex As Exception
Logger.Warn(ex, $"Unhandled exception while working envelope [{oId}]")
End Try
oCurrent += 1
Logger.Info("SendInvMail - Envelope finalized!")
Next
Logger.Debug("SendInvMail - Completed job {0} successfully!", JobId)
Catch ex As Exception
Logger.Warn("SendInvMail job failed!")
Logger.Error(ex)
Finally
Logger.Info("SendInvMail execution for [{0}] ended", JobId)
End Try
Return Task.FromResult(True)
End Function
Private Sub InitializeModels(pState As State)
ConfigModel = New ConfigModel(pState)
EnvelopeModel = New EnvelopeModel(pState)
ReceiverModel = New ReceiverModel(pState)
End Sub
Private Sub InitializeServices(pState As State)
ActionService = New ActionService(pState)
End Sub
Private Function GetDatabase(pContext As IJobExecutionContext, pLogConfig As LogConfig) As MSSQLServer
Dim oConnectionString As String = pContext.MergedJobDataMap.Item(Constants.DATABASE)
Dim Database = New MSSQLServer(pLogConfig, MSSQLServer.DecryptConnectionString(oConnectionString))
Return Database
End Function
Private Function GetEnvelopeData(pEnvelopeId As Integer) As EnvelopeData
Dim oSql = $"SELECT T.GUID, T.ENVELOPE_UUID,T2.FILEPATH, T2.BYTE_DATA FROM [dbo].[TBSIG_ENVELOPE] T
JOIN TBSIG_ENVELOPE_DOCUMENT T2 ON T.GUID = T2.ENVELOPE_ID
WHERE T.GUID = {pEnvelopeId}"
Dim oTable As DataTable = Database.GetDatatable(oSql)
Dim oRow As DataRow = oTable.Rows.Cast(Of DataRow).SingleOrDefault()
If oRow Is Nothing Then
Return Nothing
End If
Dim oData As New EnvelopeData With {
.EnvelopeId = pEnvelopeId,
.DocumentPath = oRow.ItemEx("FILEPATH", ""),
.EnvelopeUUID = oRow.ItemEx("ENVELOPE_UUID", "")
}
Logger.Debug("Document path: [{0}]", oData.DocumentPath)
Return oData
End Function
Private Function GetState() As State
Return New State With {
.LogConfig = LogConfig,
.Database = Database,
.UserId = 0,
.Config = Nothing,
.DbConfig = Nothing
}
End Function
End Class
End Namespace

View File

@@ -35,6 +35,7 @@ Public Class EnvelopeModel
.Language = pRow.ItemEx("LANGUAGE", "de-DE"), .Language = pRow.ItemEx("LANGUAGE", "de-DE"),
.Status = ObjectEx.ToEnum(Of Constants.EnvelopeStatus)(pRow.ItemEx("STATUS", Constants.EnvelopeStatus.EnvelopeCreated.ToString())), .Status = ObjectEx.ToEnum(Of Constants.EnvelopeStatus)(pRow.ItemEx("STATUS", Constants.EnvelopeStatus.EnvelopeCreated.ToString())),
.AddedWhen = pRow.Item("ADDED_WHEN"), .AddedWhen = pRow.Item("ADDED_WHEN"),
.ChangedWhen = pRow.Item("CHANGED_WHEN"),
.CertificationType = ObjectEx.ToEnum(Of Constants.CertificationType)(pRow.ItemEx("CERTIFICATION_TYPE", Constants.CertificationType.AdvancedElectronicSignature.ToString())), .CertificationType = ObjectEx.ToEnum(Of Constants.CertificationType)(pRow.ItemEx("CERTIFICATION_TYPE", Constants.CertificationType.AdvancedElectronicSignature.ToString())),
.User = New User(), .User = New User(),
.ExpiresWhen = pRow.ItemEx(Of Date)("EXPIRES_WHEN", Nothing), .ExpiresWhen = pRow.ItemEx(Of Date)("EXPIRES_WHEN", Nothing),

View File

@@ -33,10 +33,10 @@ Public Class UserModel
Dim oRow = oTable.Rows.Item(0) Dim oRow = oTable.Rows.Item(0)
Dim oHasAccess = oRow.ItemEx("MODULE_ACCESS", False) Dim oHasAccess = oRow.ItemEx("MODULE_ACCESS", False)
Dim oIsAdmin = oRow.ItemEx("IS_ADMIN", False) Dim oIsAdmin = oRow.ItemEx("IS_ADMIN", False)
Dim oGhostmode = oRow.ItemEx("GHOST_MODE_OVERRIDE", False)
pUser.HasAccess = oHasAccess pUser.HasAccess = oHasAccess
pUser.IsAdmin = oIsAdmin pUser.IsAdmin = oIsAdmin
pUser.GhostModeActive = oGhostmode
Return pUser Return pUser
Catch ex As Exception Catch ex As Exception
Logger.Error(ex) Logger.Error(ex)

View File

@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
' indem Sie "*" wie unten gezeigt eingeben: ' indem Sie "*" wie unten gezeigt eingeben:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("2.4.3.0")> <Assembly: AssemblyVersion("2.6.0.0")>
<Assembly: AssemblyFileVersion("2.4.3.0")> <Assembly: AssemblyFileVersion("2.6.0.0")>

View File

@@ -220,6 +220,9 @@ Pattern: +491234567890</value>
<data name="Missing Receivers" xml:space="preserve"> <data name="Missing Receivers" xml:space="preserve">
<value>Fehlende Empfänger</value> <value>Fehlende Empfänger</value>
</data> </data>
<data name="ModificationOriginFile_FormFields" xml:space="preserve">
<value />
</data>
<data name="New Envelope" xml:space="preserve"> <data name="New Envelope" xml:space="preserve">
<value>Neuer Umschlag</value> <value>Neuer Umschlag</value>
</data> </data>

View File

@@ -371,6 +371,15 @@ Namespace My.Resources
End Get End Get
End Property End Property
'''<summary>
''' Sucht eine lokalisierte Zeichenfolge, die ähnelt.
'''</summary>
Public Shared ReadOnly Property ModificationOriginFile_FormFields() As String
Get
Return ResourceManager.GetString("ModificationOriginFile_FormFields", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Sucht eine lokalisierte Zeichenfolge, die Neuer Umschlag ähnelt. ''' Sucht eine lokalisierte Zeichenfolge, die Neuer Umschlag ähnelt.
'''</summary> '''</summary>

View File

@@ -325,6 +325,15 @@ Namespace My.Resources
End Get End Get
End Property End Property
'''<summary>
''' Sucht eine lokalisierte Zeichenfolge, die ähnelt.
'''</summary>
Public Shared ReadOnly Property ModificationOriginFile_FormFields() As String
Get
Return ResourceManager.GetString("ModificationOriginFile_FormFields", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Sucht eine lokalisierte Zeichenfolge, die Nein ähnelt. ''' Sucht eine lokalisierte Zeichenfolge, die Nein ähnelt.
'''</summary> '''</summary>

View File

@@ -7,7 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="3.0.0" /> <PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="3.0.0" />
<PackageReference Include="UserManager.Domain" Version="3.0.2" /> <PackageReference Include="UserManager.Domain" Version="3.0.2" />
</ItemGroup> </ItemGroup>

View File

@@ -416,6 +416,7 @@
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="frmGhostMode.resx"> <EmbeddedResource Include="frmGhostMode.resx">
<DependentUpon>frmGhostMode.vb</DependentUpon> <DependentUpon>frmGhostMode.vb</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="frmMain.en.resx"> <EmbeddedResource Include="frmMain.en.resx">
<DependentUpon>frmMain.vb</DependentUpon> <DependentUpon>frmMain.vb</DependentUpon>

View File

@@ -18,6 +18,9 @@ Public Class FlattenFormFields
Dim newFilesPath As String = Path.Combine(oFolder, "InputFieldsFlattend_" & Path.GetFileName(pFilePath)) Dim newFilesPath As String = Path.Combine(oFolder, "InputFieldsFlattend_" & Path.GetFileName(pFilePath))
If gdpicturePdf.SaveToFile(newFilesPath) = GdPictureStatus.OK Then If gdpicturePdf.SaveToFile(newFilesPath) = GdPictureStatus.OK Then
Dim oNameofFile = Path.GetFileName(newFilesPath)
MsgBox("Your PDF-file contained form-fields!" & vbNewLine & "We needed to adapt the file and created an new version!" & vbNewLine &
$"New filename: {oNameofFile}", MsgBoxStyle.Exclamation, "Information")
Return newFilesPath Return newFilesPath
End If End If

View File

@@ -32,5 +32,5 @@ Imports System.Runtime.InteropServices
' You can specify all the values or you can default the Build and Revision Numbers ' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below: ' by using the '*' as shown below:
' [assembly: AssemblyVersion("1.0.*")] ' [assembly: AssemblyVersion("1.0.*")]
<Assembly: AssemblyVersion("2.9.0.0")> <Assembly: AssemblyVersion("2.9.1.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")> <Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@@ -200,7 +200,7 @@ Partial Public Class frmEnvelopeEditor
Private Sub btnSave_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles btnSave.ItemClick Private Sub btnSave_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles btnSave.ItemClick
Try Try
If SaveEnvelopeWithOutValidation() = True Then If SaveEnvelopeWithOutValidation() = True Then
bsitm_info.Caption = "Data saved succeddfully " + Now.ToString bsitm_info.Caption = "Data saved successfully " + Now.ToString
Else Else
bsitm_info.Caption = "Exceprion - Error saving Data. Check LOG" bsitm_info.Caption = "Exceprion - Error saving Data. Check LOG"
End If End If

View File

@@ -47,6 +47,7 @@ Partial Class frmMain
Me.colStatus = New DevExpress.XtraGrid.Columns.GridColumn() Me.colStatus = New DevExpress.XtraGrid.Columns.GridColumn()
Me.colTitle = New DevExpress.XtraGrid.Columns.GridColumn() Me.colTitle = New DevExpress.XtraGrid.Columns.GridColumn()
Me.colAddedWhen = New DevExpress.XtraGrid.Columns.GridColumn() Me.colAddedWhen = New DevExpress.XtraGrid.Columns.GridColumn()
Me.GridColumn2 = New DevExpress.XtraGrid.Columns.GridColumn()
Me.RibbonControl = New DevExpress.XtraBars.Ribbon.RibbonControl() Me.RibbonControl = New DevExpress.XtraBars.Ribbon.RibbonControl()
Me.btnCreateEnvelope = New DevExpress.XtraBars.BarButtonItem() Me.btnCreateEnvelope = New DevExpress.XtraBars.BarButtonItem()
Me.btnEditEnvelope = New DevExpress.XtraBars.BarButtonItem() Me.btnEditEnvelope = New DevExpress.XtraBars.BarButtonItem()
@@ -88,14 +89,16 @@ Partial Class frmMain
Me.GridColumn4 = New DevExpress.XtraGrid.Columns.GridColumn() Me.GridColumn4 = New DevExpress.XtraGrid.Columns.GridColumn()
Me.GridColumn5 = New DevExpress.XtraGrid.Columns.GridColumn() Me.GridColumn5 = New DevExpress.XtraGrid.Columns.GridColumn()
Me.GridColumn7 = New DevExpress.XtraGrid.Columns.GridColumn() Me.GridColumn7 = New DevExpress.XtraGrid.Columns.GridColumn()
Me.GridColumn1 = New DevExpress.XtraGrid.Columns.GridColumn()
Me.XtraTabPageAdmin = New DevExpress.XtraTab.XtraTabPage() Me.XtraTabPageAdmin = New DevExpress.XtraTab.XtraTabPage()
Me.SplitContainerControl2 = New DevExpress.XtraEditors.SplitContainerControl() Me.SplitContainerControl2 = New DevExpress.XtraEditors.SplitContainerControl()
Me.GridControlData = New DevExpress.XtraGrid.GridControl() Me.GridControlData = New DevExpress.XtraGrid.GridControl()
Me.GridViewData = New DevExpress.XtraGrid.Views.Grid.GridView() Me.GridViewData = New DevExpress.XtraGrid.Views.Grid.GridView()
Me.PanelControl1 = New DevExpress.XtraEditors.PanelControl() Me.PanelControl1 = New DevExpress.XtraEditors.PanelControl()
Me.GroupControl2 = New DevExpress.XtraEditors.GroupControl() Me.GroupControl2 = New DevExpress.XtraEditors.GroupControl()
Me.GroupControl1 = New DevExpress.XtraEditors.GroupControl() Me.btnEvvallUs_lastmonth = New DevExpress.XtraEditors.SimpleButton()
Me.btnEvvallUs_thismonth = New DevExpress.XtraEditors.SimpleButton() Me.btnEvvallUs_thismonth = New DevExpress.XtraEditors.SimpleButton()
Me.GroupControl1 = New DevExpress.XtraEditors.GroupControl()
Me.btnEnvelopes_All = New DevExpress.XtraEditors.SimpleButton() Me.btnEnvelopes_All = New DevExpress.XtraEditors.SimpleButton()
Me.btnEnvelopes_thisYear = New DevExpress.XtraEditors.SimpleButton() Me.btnEnvelopes_thisYear = New DevExpress.XtraEditors.SimpleButton()
Me.btnEnvelopes_lastmonth = New DevExpress.XtraEditors.SimpleButton() Me.btnEnvelopes_lastmonth = New DevExpress.XtraEditors.SimpleButton()
@@ -103,7 +106,6 @@ Partial Class frmMain
Me.RefreshTimer = New System.Windows.Forms.Timer(Me.components) Me.RefreshTimer = New System.Windows.Forms.Timer(Me.components)
Me.SaveFileDialog1 = New System.Windows.Forms.SaveFileDialog() Me.SaveFileDialog1 = New System.Windows.Forms.SaveFileDialog()
Me.XtraSaveFileDialog1 = New DevExpress.XtraEditors.XtraSaveFileDialog(Me.components) Me.XtraSaveFileDialog1 = New DevExpress.XtraEditors.XtraSaveFileDialog(Me.components)
Me.btnEvvallUs_lastmonth = New DevExpress.XtraEditors.SimpleButton()
CType(Me.SplitContainerControl1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.SplitContainerControl1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.SplitContainerControl1.Panel1, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.SplitContainerControl1.Panel1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SplitContainerControl1.Panel1.SuspendLayout() Me.SplitContainerControl1.Panel1.SuspendLayout()
@@ -279,11 +281,12 @@ Partial Class frmMain
' '
'ViewEnvelopes 'ViewEnvelopes
' '
Me.ViewEnvelopes.Columns.AddRange(New DevExpress.XtraGrid.Columns.GridColumn() {Me.colEnvelopeId, Me.colContractType, Me.colStatus, Me.colTitle, Me.colAddedWhen}) Me.ViewEnvelopes.Columns.AddRange(New DevExpress.XtraGrid.Columns.GridColumn() {Me.colEnvelopeId, Me.colContractType, Me.colStatus, Me.colTitle, Me.colAddedWhen, Me.GridColumn2})
Me.ViewEnvelopes.GridControl = Me.GridEnvelopes Me.ViewEnvelopes.GridControl = Me.GridEnvelopes
Me.ViewEnvelopes.Name = "ViewEnvelopes" Me.ViewEnvelopes.Name = "ViewEnvelopes"
Me.ViewEnvelopes.OptionsBehavior.Editable = False Me.ViewEnvelopes.OptionsBehavior.Editable = False
Me.ViewEnvelopes.OptionsBehavior.ReadOnly = True Me.ViewEnvelopes.OptionsBehavior.ReadOnly = True
Me.ViewEnvelopes.OptionsView.ShowAutoFilterRow = True
Me.ViewEnvelopes.OptionsView.ShowIndicator = False Me.ViewEnvelopes.OptionsView.ShowIndicator = False
' '
'colEnvelopeId 'colEnvelopeId
@@ -318,6 +321,14 @@ Partial Class frmMain
Me.colAddedWhen.FieldName = "AddedWhen" Me.colAddedWhen.FieldName = "AddedWhen"
Me.colAddedWhen.Name = "colAddedWhen" Me.colAddedWhen.Name = "colAddedWhen"
' '
'GridColumn2
'
resources.ApplyResources(Me.GridColumn2, "GridColumn2")
Me.GridColumn2.DisplayFormat.FormatString = "G"
Me.GridColumn2.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime
Me.GridColumn2.FieldName = "ChangedWhen"
Me.GridColumn2.Name = "GridColumn2"
'
'RibbonControl 'RibbonControl
' '
Me.RibbonControl.ExpandCollapseItem.Id = 0 Me.RibbonControl.ExpandCollapseItem.Id = 0
@@ -637,11 +648,12 @@ Partial Class frmMain
' '
'ViewCompleted 'ViewCompleted
' '
Me.ViewCompleted.Columns.AddRange(New DevExpress.XtraGrid.Columns.GridColumn() {Me.GridColumn3, Me.GridColumn4, Me.GridColumn5, Me.GridColumn7}) Me.ViewCompleted.Columns.AddRange(New DevExpress.XtraGrid.Columns.GridColumn() {Me.GridColumn3, Me.GridColumn4, Me.GridColumn5, Me.GridColumn7, Me.GridColumn1})
Me.ViewCompleted.GridControl = Me.GridCompleted Me.ViewCompleted.GridControl = Me.GridCompleted
Me.ViewCompleted.Name = "ViewCompleted" Me.ViewCompleted.Name = "ViewCompleted"
Me.ViewCompleted.OptionsBehavior.Editable = False Me.ViewCompleted.OptionsBehavior.Editable = False
Me.ViewCompleted.OptionsBehavior.ReadOnly = True Me.ViewCompleted.OptionsBehavior.ReadOnly = True
Me.ViewCompleted.OptionsView.ShowAutoFilterRow = True
Me.ViewCompleted.OptionsView.ShowIndicator = False Me.ViewCompleted.OptionsView.ShowIndicator = False
' '
'GridColumn3 'GridColumn3
@@ -665,9 +677,19 @@ Partial Class frmMain
'GridColumn7 'GridColumn7
' '
resources.ApplyResources(Me.GridColumn7, "GridColumn7") resources.ApplyResources(Me.GridColumn7, "GridColumn7")
Me.GridColumn7.DisplayFormat.FormatString = "G"
Me.GridColumn7.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime
Me.GridColumn7.FieldName = "AddedWhen" Me.GridColumn7.FieldName = "AddedWhen"
Me.GridColumn7.Name = "GridColumn7" Me.GridColumn7.Name = "GridColumn7"
' '
'GridColumn1
'
resources.ApplyResources(Me.GridColumn1, "GridColumn1")
Me.GridColumn1.DisplayFormat.FormatString = "G"
Me.GridColumn1.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime
Me.GridColumn1.FieldName = "ChangedWhen"
Me.GridColumn1.Name = "GridColumn1"
'
'XtraTabPageAdmin 'XtraTabPageAdmin
' '
Me.XtraTabPageAdmin.Controls.Add(Me.SplitContainerControl2) Me.XtraTabPageAdmin.Controls.Add(Me.SplitContainerControl2)
@@ -688,7 +710,7 @@ Partial Class frmMain
'SplitContainerControl2.Panel2 'SplitContainerControl2.Panel2
' '
resources.ApplyResources(Me.SplitContainerControl2.Panel2, "SplitContainerControl2.Panel2") resources.ApplyResources(Me.SplitContainerControl2.Panel2, "SplitContainerControl2.Panel2")
Me.SplitContainerControl2.SplitterPosition = 819 Me.SplitContainerControl2.SplitterPosition = 907
' '
'GridControlData 'GridControlData
' '
@@ -702,6 +724,7 @@ Partial Class frmMain
' '
Me.GridViewData.GridControl = Me.GridControlData Me.GridViewData.GridControl = Me.GridControlData
Me.GridViewData.Name = "GridViewData" Me.GridViewData.Name = "GridViewData"
Me.GridViewData.OptionsView.ShowAutoFilterRow = True
' '
'PanelControl1 'PanelControl1
' '
@@ -717,6 +740,20 @@ Partial Class frmMain
resources.ApplyResources(Me.GroupControl2, "GroupControl2") resources.ApplyResources(Me.GroupControl2, "GroupControl2")
Me.GroupControl2.Name = "GroupControl2" Me.GroupControl2.Name = "GroupControl2"
' '
'btnEvvallUs_lastmonth
'
Me.btnEvvallUs_lastmonth.Appearance.BackColor = System.Drawing.Color.MediumPurple
Me.btnEvvallUs_lastmonth.Appearance.Options.UseBackColor = True
resources.ApplyResources(Me.btnEvvallUs_lastmonth, "btnEvvallUs_lastmonth")
Me.btnEvvallUs_lastmonth.Name = "btnEvvallUs_lastmonth"
'
'btnEvvallUs_thismonth
'
Me.btnEvvallUs_thismonth.Appearance.BackColor = System.Drawing.Color.MediumSlateBlue
Me.btnEvvallUs_thismonth.Appearance.Options.UseBackColor = True
resources.ApplyResources(Me.btnEvvallUs_thismonth, "btnEvvallUs_thismonth")
Me.btnEvvallUs_thismonth.Name = "btnEvvallUs_thismonth"
'
'GroupControl1 'GroupControl1
' '
Me.GroupControl1.Controls.Add(Me.btnEnvelopes_All) Me.GroupControl1.Controls.Add(Me.btnEnvelopes_All)
@@ -726,13 +763,6 @@ Partial Class frmMain
resources.ApplyResources(Me.GroupControl1, "GroupControl1") resources.ApplyResources(Me.GroupControl1, "GroupControl1")
Me.GroupControl1.Name = "GroupControl1" Me.GroupControl1.Name = "GroupControl1"
' '
'btnEvvallUs_thismonth
'
Me.btnEvvallUs_thismonth.Appearance.BackColor = System.Drawing.Color.MediumSlateBlue
Me.btnEvvallUs_thismonth.Appearance.Options.UseBackColor = True
resources.ApplyResources(Me.btnEvvallUs_thismonth, "btnEvvallUs_thismonth")
Me.btnEvvallUs_thismonth.Name = "btnEvvallUs_thismonth"
'
'btnEnvelopes_All 'btnEnvelopes_All
' '
Me.btnEnvelopes_All.Appearance.BackColor = System.Drawing.Color.MediumTurquoise Me.btnEnvelopes_All.Appearance.BackColor = System.Drawing.Color.MediumTurquoise
@@ -773,13 +803,6 @@ Partial Class frmMain
' '
Me.XtraSaveFileDialog1.FileName = "XtraSaveFileDialog1" Me.XtraSaveFileDialog1.FileName = "XtraSaveFileDialog1"
' '
'btnEvvallUs_lastmonth
'
Me.btnEvvallUs_lastmonth.Appearance.BackColor = System.Drawing.Color.MediumPurple
Me.btnEvvallUs_lastmonth.Appearance.Options.UseBackColor = True
resources.ApplyResources(Me.btnEvvallUs_lastmonth, "btnEvvallUs_lastmonth")
Me.btnEvvallUs_lastmonth.Name = "btnEvvallUs_lastmonth"
'
'frmMain 'frmMain
' '
resources.ApplyResources(Me, "$this") resources.ApplyResources(Me, "$this")
@@ -906,4 +929,6 @@ Partial Class frmMain
Friend WithEvents BarStaticItemGhost As DevExpress.XtraBars.BarStaticItem Friend WithEvents BarStaticItemGhost As DevExpress.XtraBars.BarStaticItem
Friend WithEvents btnEvvallUs_thismonth As DevExpress.XtraEditors.SimpleButton Friend WithEvents btnEvvallUs_thismonth As DevExpress.XtraEditors.SimpleButton
Friend WithEvents btnEvvallUs_lastmonth As DevExpress.XtraEditors.SimpleButton Friend WithEvents btnEvvallUs_lastmonth As DevExpress.XtraEditors.SimpleButton
Friend WithEvents GridColumn1 As DevExpress.XtraGrid.Columns.GridColumn
Friend WithEvents GridColumn2 As DevExpress.XtraGrid.Columns.GridColumn
End Class End Class

View File

@@ -265,7 +265,7 @@
<value>2</value> <value>2</value>
</data> </data>
<data name="colContractType.Width" type="System.Int32, mscorlib"> <data name="colContractType.Width" type="System.Int32, mscorlib">
<value>120</value> <value>112</value>
</data> </data>
<data name="colStatus.Caption" xml:space="preserve"> <data name="colStatus.Caption" xml:space="preserve">
<value>Status</value> <value>Status</value>
@@ -277,7 +277,7 @@
<value>1</value> <value>1</value>
</data> </data>
<data name="colStatus.Width" type="System.Int32, mscorlib"> <data name="colStatus.Width" type="System.Int32, mscorlib">
<value>193</value> <value>180</value>
</data> </data>
<data name="colTitle.Caption" xml:space="preserve"> <data name="colTitle.Caption" xml:space="preserve">
<value>Titel</value> <value>Titel</value>
@@ -289,7 +289,7 @@
<value>0</value> <value>0</value>
</data> </data>
<data name="colTitle.Width" type="System.Int32, mscorlib"> <data name="colTitle.Width" type="System.Int32, mscorlib">
<value>575</value> <value>538</value>
</data> </data>
<data name="colAddedWhen.Caption" xml:space="preserve"> <data name="colAddedWhen.Caption" xml:space="preserve">
<value>Erstellt am</value> <value>Erstellt am</value>
@@ -301,7 +301,19 @@
<value>3</value> <value>3</value>
</data> </data>
<data name="colAddedWhen.Width" type="System.Int32, mscorlib"> <data name="colAddedWhen.Width" type="System.Int32, mscorlib">
<value>196</value> <value>130</value>
</data>
<data name="GridColumn2.Caption" xml:space="preserve">
<value>Zuletzt geändert am</value>
</data>
<data name="GridColumn2.Visible" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="GridColumn2.VisibleIndex" type="System.Int32, mscorlib">
<value>4</value>
</data>
<data name="GridColumn2.Width" type="System.Int32, mscorlib">
<value>130</value>
</data> </data>
<data name="RibbonControl.ExpandCollapseItem.ImageOptions.ImageIndex" type="System.Int32, mscorlib"> <data name="RibbonControl.ExpandCollapseItem.ImageOptions.ImageIndex" type="System.Int32, mscorlib">
<value>0</value> <value>0</value>
@@ -1052,7 +1064,7 @@
<value>2</value> <value>2</value>
</data> </data>
<data name="GridColumn3.Width" type="System.Int32, mscorlib"> <data name="GridColumn3.Width" type="System.Int32, mscorlib">
<value>120</value> <value>100</value>
</data> </data>
<data name="GridColumn4.Caption" xml:space="preserve"> <data name="GridColumn4.Caption" xml:space="preserve">
<value>Status</value> <value>Status</value>
@@ -1064,7 +1076,7 @@
<value>1</value> <value>1</value>
</data> </data>
<data name="GridColumn4.Width" type="System.Int32, mscorlib"> <data name="GridColumn4.Width" type="System.Int32, mscorlib">
<value>195</value> <value>163</value>
</data> </data>
<data name="GridColumn5.Caption" xml:space="preserve"> <data name="GridColumn5.Caption" xml:space="preserve">
<value>Titel</value> <value>Titel</value>
@@ -1076,7 +1088,7 @@
<value>0</value> <value>0</value>
</data> </data>
<data name="GridColumn5.Width" type="System.Int32, mscorlib"> <data name="GridColumn5.Width" type="System.Int32, mscorlib">
<value>574</value> <value>482</value>
</data> </data>
<data name="GridColumn7.Caption" xml:space="preserve"> <data name="GridColumn7.Caption" xml:space="preserve">
<value>Erstellt am</value> <value>Erstellt am</value>
@@ -1088,7 +1100,19 @@
<value>3</value> <value>3</value>
</data> </data>
<data name="GridColumn7.Width" type="System.Int32, mscorlib"> <data name="GridColumn7.Width" type="System.Int32, mscorlib">
<value>195</value> <value>120</value>
</data>
<data name="GridColumn1.Caption" xml:space="preserve">
<value>Zuletzt geändert am</value>
</data>
<data name="GridColumn1.Visible" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<data name="GridColumn1.VisibleIndex" type="System.Int32, mscorlib">
<value>4</value>
</data>
<data name="GridColumn1.Width" type="System.Int32, mscorlib">
<value>120</value>
</data> </data>
<data name="GridCompleted.Size" type="System.Drawing.Size, System.Drawing"> <data name="GridCompleted.Size" type="System.Drawing.Size, System.Drawing">
<value>1088, 469</value> <value>1088, 469</value>
@@ -1139,7 +1163,7 @@
<value>0, 0</value> <value>0, 0</value>
</data> </data>
<data name="GridControlData.Size" type="System.Drawing.Size, System.Drawing"> <data name="GridControlData.Size" type="System.Drawing.Size, System.Drawing">
<value>819, 390</value> <value>907, 390</value>
</data> </data>
<data name="GridControlData.TabIndex" type="System.Int32, mscorlib"> <data name="GridControlData.TabIndex" type="System.Int32, mscorlib">
<value>1</value> <value>1</value>
@@ -1262,7 +1286,7 @@
<value>2</value> <value>2</value>
</data> </data>
<data name="GroupControl2.Text" xml:space="preserve"> <data name="GroupControl2.Text" xml:space="preserve">
<value>Umschläge alle User</value> <value>Umschläge alle User (abrechnungsrelevant)</value>
</data> </data>
<data name="&gt;&gt;GroupControl2.Name" xml:space="preserve"> <data name="&gt;&gt;GroupControl2.Name" xml:space="preserve">
<value>GroupControl2</value> <value>GroupControl2</value>
@@ -1717,6 +1741,12 @@
<data name="&gt;&gt;colAddedWhen.Type" xml:space="preserve"> <data name="&gt;&gt;colAddedWhen.Type" xml:space="preserve">
<value>DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value> <value>DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data> </data>
<data name="&gt;&gt;GridColumn2.Name" xml:space="preserve">
<value>GridColumn2</value>
</data>
<data name="&gt;&gt;GridColumn2.Type" xml:space="preserve">
<value>DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;btnCreateEnvelope.Name" xml:space="preserve"> <data name="&gt;&gt;btnCreateEnvelope.Name" xml:space="preserve">
<value>btnCreateEnvelope</value> <value>btnCreateEnvelope</value>
</data> </data>
@@ -1939,6 +1969,12 @@
<data name="&gt;&gt;GridColumn7.Type" xml:space="preserve"> <data name="&gt;&gt;GridColumn7.Type" xml:space="preserve">
<value>DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value> <value>DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data> </data>
<data name="&gt;&gt;GridColumn1.Name" xml:space="preserve">
<value>GridColumn1</value>
</data>
<data name="&gt;&gt;GridColumn1.Type" xml:space="preserve">
<value>DevExpress.XtraGrid.Columns.GridColumn, DevExpress.XtraGrid.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;GridViewData.Name" xml:space="preserve"> <data name="&gt;&gt;GridViewData.Name" xml:space="preserve">
<value>GridViewData</value> <value>GridViewData</value>
</data> </data>

View File

@@ -90,9 +90,11 @@ Public Class frmMain
If ViewEnvelopes.RowCount = 0 Then If ViewEnvelopes.RowCount = 0 Then
RibbonPageGroupFunctions.Enabled = False RibbonPageGroupFunctions.Enabled = False
btnDeleteEnvelope.Visibility = DevExpress.XtraBars.BarItemVisibility.Never btnDeleteEnvelope.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
btnEditEnvelope.Enabled = False
Else Else
RibbonPageGroupFunctions.Enabled = True RibbonPageGroupFunctions.Enabled = True
btnDeleteEnvelope.Visibility = DevExpress.XtraBars.BarItemVisibility.Always btnDeleteEnvelope.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
btnEditEnvelope.Enabled = True
End If End If
Catch ex As Exception Catch ex As Exception
Logger.Error(ex) Logger.Error(ex)
@@ -222,9 +224,6 @@ Public Class frmMain
bbtnitmEB.Enabled = True bbtnitmEB.Enabled = True
LoadEnvelopeData() LoadEnvelopeData()
Case 0 Case 0
If ViewEnvelopes.RowCount = 0 Then
RibbonPageGroupFunctions.Enabled = False
End If
btnEditEnvelope.Enabled = True btnEditEnvelope.Enabled = True
btnDeleteEnvelope.Enabled = True btnDeleteEnvelope.Enabled = True
btnContactReceiver.Enabled = True btnContactReceiver.Enabled = True
@@ -233,6 +232,7 @@ Public Class frmMain
bbtnitmInfoMail.Enabled = True bbtnitmInfoMail.Enabled = True
bbtnitmEB.Enabled = False bbtnitmEB.Enabled = False
LoadEnvelopeData() LoadEnvelopeData()
txtEnvelopeIdLabel.Caption = "No Envelope selected" txtEnvelopeIdLabel.Caption = "No Envelope selected"
Case 2 Case 2
@@ -538,7 +538,7 @@ Public Class frmMain
End If End If
bbtnitmEB.Enabled = False bbtnitmEB.Enabled = False
RefreshTimer.Start() RefreshTimer.Start()
If USER_GHOST_MODE_ACTIVE Then If USER_GHOST_MODE_ACTIVE Or MYUSER.GhostModeActive Then
frmGhostMode.ShowDialog() frmGhostMode.ShowDialog()
If USER_GHOST_MODE_USRNAME <> "" Then If USER_GHOST_MODE_USRNAME <> "" Then
MyUserModel = New UserModel(MyState) MyUserModel = New UserModel(MyState)
@@ -546,7 +546,8 @@ Public Class frmMain
Dim oUser = MyUserModel.SelectUser() Dim oUser = MyUserModel.SelectUser()
If oUser IsNot Nothing Then If oUser IsNot Nothing Then
MyUserModel.CheckUserLogin(oUser) MyUserModel.CheckUserLogin(oUser)
BarStaticItemGhost.Caption = $"GhostMode active: {USER_GHOST_MODE_USRNAME} - End signFLOW to quit mode" BarStaticItemGhost.Caption = $"GhostMode active: {USER_GHOST_MODE_USRNAME} - End signFLOW to quit ghost-mode"
Me.Text = $"GhostMode active: {USER_GHOST_MODE_USRNAME} - End signFLOW to quit ghost - mode"
BarStaticItemGhost.Visibility = DevExpress.XtraBars.BarItemVisibility.Always BarStaticItemGhost.Visibility = DevExpress.XtraBars.BarItemVisibility.Always
LoadEnvelopeData() LoadEnvelopeData()
End If End If

View File

@@ -1,201 +1,150 @@
using DigitalData.Core.Abstractions.Application; using DigitalData.Core.Abstractions.Application;
using DigitalData.UserManager.Application.Contracts; using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using DigitalData.UserManager.Application.DTOs.Auth;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using EnvelopeGenerator.GeneratorAPI.Models; using EnvelopeGenerator.GeneratorAPI.Models;
namespace EnvelopeGenerator.GeneratorAPI.Controllers namespace EnvelopeGenerator.GeneratorAPI.Controllers;
/// <summary>
/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public partial class AuthController : ControllerBase
{ {
private readonly ILogger<AuthController> _logger;
private readonly IUserService _userService;
private readonly IDirectorySearchService _dirSearchService;
/// <summary> /// <summary>
/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus. /// Initializes a new instance of the <see cref="AuthController"/> class.
/// </summary> /// </summary>
[Route("api/[controller]")] /// <param name="logger">The logger instance.</param>
[ApiController] /// <param name="userService">The user service instance.</param>
public partial class AuthController : ControllerBase /// <param name="dirSearchService">The directory search service instance.</param>
public AuthController(ILogger<AuthController> logger, IUserService userService, IDirectorySearchService dirSearchService)
{ {
private readonly ILogger<AuthController> _logger; _logger = logger;
private readonly IUserService _userService; _userService = userService;
private readonly IDirectorySearchService _dirSearchService; _dirSearchService = dirSearchService;
/// <summary>
/// Initializes a new instance of the <see cref="AuthController"/> class.
/// </summary>
/// <param name="logger">The logger instance.</param>
/// <param name="userService">The user service instance.</param>
/// <param name="dirSearchService">The directory search service instance.</param>
public AuthController(ILogger<AuthController> logger, IUserService userService, IDirectorySearchService dirSearchService)
{
_logger = logger;
_userService = userService;
_dirSearchService = dirSearchService;
}
/// <summary>
/// Authentifiziert einen Benutzer und generiert ein JWT-Token. Wenn 'cookie' wahr ist, wird das Token als HTTP-Only-Cookie zurückgegeben.
/// </summary>
/// <param name="login">Benutzeranmeldedaten (Benutzername und Passwort).</param>
/// <param name="cookie">Wenn wahr, wird das JWT-Token auch als HTTP-Only-Cookie gesendet.</param>
/// <returns>
/// Gibt eine HTTP 200 oder 401.
/// </returns>
/// <remarks>
/// Sample request:
///
/// POST /api/auth?cookie=true
/// {
/// "username": "MaxMustermann",
/// "password": "Geheim123!"
/// }
///
/// POST /api/auth?cookie=true
/// {
/// "id": "1",
/// "password": "Geheim123!"
/// }
///
/// </remarks>
/// <response code="200">Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist.</response>
/// <response code="401">Unbefugt. Ungültiger Benutzername oder Passwort.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Login([FromBody] Login login, [FromQuery] bool cookie = false)
{
try
{
bool isValid = _dirSearchService.ValidateCredentials(login.Username, login.Password);
if (!isValid)
return Unauthorized();
//find the user
var uRes = await _userService.ReadByUsernameAsync(login.Username);
if (!uRes.IsSuccess || uRes.Data is null)
{
return Forbid();
}
UserReadDto user = uRes.Data;
// Create claims
var claims = new List<Claim>
{
new (ClaimTypes.NameIdentifier, user.Id.ToString()),
new (ClaimTypes.Name, user.Username),
new (ClaimTypes.Surname, user.Name!),
new (ClaimTypes.GivenName, user.Prename!),
new (ClaimTypes.Email, user.Email!),
};
// Create claimsIdentity
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
// Create authProperties
var authProperties = new AuthenticationProperties
{
IsPersistent = true,
AllowRefresh = true,
ExpiresUtc = DateTime.Now.AddMinutes(180)
};
// Sign in
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
return Ok();
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error occurred.\n{ErrorMessage}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
/// <summary>
/// Authentifiziert einen Benutzer und generiert ein JWT-Token. Das Token wird als HTTP-only-Cookie zurückgegeben.
/// </summary>
/// <param name="login">Benutzeranmeldedaten (Benutzername und Passwort).</param>
/// <returns>
/// Gibt eine HTTP 200 oder 401.
/// </returns>
/// <remarks>
/// Sample request:
///
/// POST /api/auth/form
/// {
/// "username": "MaxMustermann",
/// "password": "Geheim123!"
/// }
///
/// </remarks>
/// <response code="200">Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist.</response>
/// <response code="401">Unbefugt. Ungültiger Benutzername oder Passwort.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[AllowAnonymous]
[HttpPost]
[Route("form")]
public async Task<IActionResult> Login([FromForm] Login login)
{
return await Login(login, true);
}
/// <summary>
/// Entfernt das Authentifizierungs-Cookie des Benutzers (AuthCookie)
/// </summary>
/// <returns>
/// Gibt eine HTTP 200 oder 401.
/// </returns>
/// <remarks>
/// Sample request:
///
/// POST /api/auth/logout
///
/// </remarks>
/// <response code="200">Erfolgreich gelöscht, wenn der Benutzer ein berechtigtes Cookie hat.</response>
/// <response code="401">Wenn es kein zugelassenes Cookie gibt, wird „nicht zugelassen“ zurückgegeben.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[Authorize]
[HttpPost("logout")]
public async Task<IActionResult> Logout()
{
try
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error occurred.\n{ErrorMessage}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
/// <summary>
/// Prüft, ob der Benutzer ein autorisiertes Token hat.
/// </summary>
/// <returns>Wenn ein autorisiertes Token vorhanden ist HTTP 200 asynchron 401</returns>
/// <remarks>
/// Sample request:
///
/// GET /api/auth
///
/// </remarks>
/// <response code="200">Wenn es einen autorisierten Cookie gibt.</response>
/// <response code="401">Wenn kein Cookie vorhanden ist oder nicht autorisierte.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[Authorize]
[HttpGet]
public IActionResult IsAuthenticated() => Ok();
} }
/// <summary>
/// Authentifiziert einen Benutzer und generiert ein JWT-Token. Wenn 'cookie' wahr ist, wird das Token als HTTP-Only-Cookie zurückgegeben.
/// </summary>
/// <param name="login">Benutzeranmeldedaten (Benutzername und Passwort).</param>
/// <param name="cookie">Wenn wahr, wird das JWT-Token auch als HTTP-Only-Cookie gesendet.</param>
/// <returns>
/// Gibt eine HTTP 200 oder 401.
/// </returns>
/// <remarks>
/// Sample request:
///
/// POST /api/auth?cookie=true
/// {
/// "username": "MaxMustermann",
/// "password": "Geheim123!"
/// }
///
/// POST /api/auth?cookie=true
/// {
/// "id": "1",
/// "password": "Geheim123!"
/// }
///
/// </remarks>
/// <response code="200">Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist.</response>
/// <response code="401">Unbefugt. Ungültiger Benutzername oder Passwort.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[AllowAnonymous]
[HttpPost]
public Task<IActionResult> Login([FromBody] Login login, [FromQuery] bool cookie = false)
{
// added to configure open API (swagger and scalar)
throw new NotImplementedException();
}
/// <summary>
/// Authentifiziert einen Benutzer und generiert ein JWT-Token. Das Token wird als HTTP-only-Cookie zurückgegeben.
/// </summary>
/// <param name="login">Benutzeranmeldedaten (Benutzername und Passwort).</param>
/// <returns>
/// Gibt eine HTTP 200 oder 401.
/// </returns>
/// <remarks>
/// Sample request:
///
/// POST /api/auth/form
/// {
/// "username": "MaxMustermann",
/// "password": "Geheim123!"
/// }
///
/// </remarks>
/// <response code="200">Erfolgreiche Anmeldung. Gibt das JWT-Token im Antwortkörper oder als Cookie zurück, wenn 'cookie' wahr ist.</response>
/// <response code="401">Unbefugt. Ungültiger Benutzername oder Passwort.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[AllowAnonymous]
[HttpPost]
[Route("form")]
public Task<IActionResult> Login([FromForm] Login login)
{
// added to configure open API (swagger and scalar)
throw new NotImplementedException();
}
/// <summary>
/// Entfernt das Authentifizierungs-Cookie des Benutzers (AuthCookie)
/// </summary>
/// <returns>
/// Gibt eine HTTP 200 oder 401.
/// </returns>
/// <remarks>
/// Sample request:
///
/// POST /api/auth/logout
///
/// </remarks>
/// <response code="200">Erfolgreich gelöscht, wenn der Benutzer ein berechtigtes Cookie hat.</response>
/// <response code="401">Wenn es kein zugelassenes Cookie gibt, wird „nicht zugelassen“ zurückgegeben.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[Authorize]
[HttpPost("logout")]
public async Task<IActionResult> Logout()
{
try
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
catch (Exception ex)
{
_logger.LogError(ex, "Unexpected error occurred.\n{ErrorMessage}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
/// <summary>
/// Prüft, ob der Benutzer ein autorisiertes Token hat.
/// </summary>
/// <returns>Wenn ein autorisiertes Token vorhanden ist HTTP 200 asynchron 401</returns>
/// <remarks>
/// Sample request:
///
/// GET /api/auth
///
/// </remarks>
/// <response code="200">Wenn es einen autorisierten Cookie gibt.</response>
/// <response code="401">Wenn kein Cookie vorhanden ist oder nicht autorisierte.</response>
[ProducesResponseType(typeof(string), StatusCodes.Status200OK, "text/javascript")]
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[Authorize]
[HttpGet]
public IActionResult IsAuthenticated() => Ok();
} }

View File

@@ -19,12 +19,13 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AspNetCore.Scalar" Version="1.1.8" /> <PackageReference Include="AspNetCore.Scalar" Version="1.1.8" />
<PackageReference Include="DigitalData.Auth.Client" Version="1.3.7" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" /> <PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.3" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
<PackageReference Include="Scalar.AspNetCore" Version="2.1.4" /> <PackageReference Include="Scalar.AspNetCore" Version="2.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" /> <PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" /> <PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="3.0.0" /> <PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="3.0.0" />

View File

@@ -0,0 +1,10 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'dotnet build'
}
}
}
}

View File

@@ -0,0 +1,28 @@
namespace EnvelopeGenerator.GeneratorAPI.Models;
/// <summary>
/// Represents the keys and default values used for authentication token handling
/// within the Envelope Generator API.
/// </summary>
public class AuthTokenKeys
{
/// <summary>
/// Gets the name of the cookie used to store the authentication token.
/// </summary>
public string Cookie { get; init; } = "AuthToken";
/// <summary>
/// Gets the name of the query string parameter used to pass the authentication token.
/// </summary>
public string QueryString { get; init; } = "AuthToken";
/// <summary>
/// Gets the expected issuer value for the authentication token.
/// </summary>
public string Issuer { get; init; } = "auth.digitaldata.works";
/// <summary>
/// Gets the expected audience value for the authentication token.
/// </summary>
public string Audience { get; init; } = "sign-flow-gen.digitaldata.works";
}

View File

@@ -1,6 +1,5 @@
using DigitalData.Core.API; using DigitalData.Core.API;
using DigitalData.Core.Application; using DigitalData.Core.Application;
using DigitalData.UserManager.Application;
using EnvelopeGenerator.Infrastructure; using EnvelopeGenerator.Infrastructure;
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Localization;
@@ -10,11 +9,19 @@ using Scalar.AspNetCore;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using DigitalData.UserManager.DependencyInjection; using DigitalData.UserManager.DependencyInjection;
using EnvelopeGenerator.Application; using EnvelopeGenerator.Application;
using DigitalData.Auth.Client;
using DigitalData.Core.Abstractions;
using EnvelopeGenerator.GeneratorAPI.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using DigitalData.Core.Abstractions.Security.Extensions;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration; var config = builder.Configuration;
var deferredProvider = new DeferredServiceProvider();
builder.Services.AddControllers(); builder.Services.AddControllers();
//CORS Policy //CORS Policy
@@ -85,6 +92,49 @@ builder.Services.AddOpenApi();
var connStr = config.GetConnectionString("Default") ?? throw new InvalidOperationException("There is no default connection string in appsettings.json."); var connStr = config.GetConnectionString("Default") ?? throw new InvalidOperationException("There is no default connection string in appsettings.json.");
builder.Services.AddDbContext<EGDbContext>(options => options.UseSqlServer(connStr)); builder.Services.AddDbContext<EGDbContext>(options => options.UseSqlServer(connStr));
builder.Services.AddAuthHubClient(config.GetSection("AuthClientParams"));
var authTokenKeys = config.GetOrDefault<AuthTokenKeys>();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) =>
{
var clientParams = deferredProvider.GetOptions<ClientParams>();
var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience);
return new List<SecurityKey>() { publicKey.SecurityKey };
},
ValidateIssuer = true,
ValidIssuer = authTokenKeys.Issuer,
ValidateAudience = true,
ValidAudience = authTokenKeys.Audience,
};
opt.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
// if there is no token read related cookie or query string
if (context.Token is null) // if there is no token
{
if (context.Request.Cookies.TryGetValue(authTokenKeys.Cookie, out var cookieToken) && cookieToken is not null)
context.Token = cookieToken;
else if (context.Request.Query.TryGetValue(authTokenKeys.QueryString, out var queryStrToken))
context.Token = queryStrToken;
}
return Task.CompletedTask;
}
};
});
// Authentication // Authentication
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => .AddCookie(options =>
@@ -114,6 +164,8 @@ builder.Services
var app = builder.Build(); var app = builder.Build();
deferredProvider.Factory = () => app.Services;
app.MapOpenApi(); app.MapOpenApi();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.

View File

@@ -4,5 +4,15 @@
"Default": "Information", "Default": "Information",
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
},
"AuthClientParams": {
"Url": "https://localhost:7192/auth-hub",
"PublicKeys": [
{
"Issuer": "auth.digitaldata.works",
"Audience": "sign-flow-gen.digitaldata.works"
}
],
"RetryDelay": "00:00:05"
} }
} }

View File

@@ -20,5 +20,21 @@
"User": "(&(objectClass=user)(sAMAccountName=*))", "User": "(&(objectClass=user)(sAMAccountName=*))",
"Group": "(&(objectClass=group)(samAccountName=*))" "Group": "(&(objectClass=group)(samAccountName=*))"
} }
},
"AuthClientParams": {
"Url": "https://localhost:7192/auth-hub",
"PublicKeys": [
{
"Issuer": "auth.digitaldata.works",
"Audience": "sign-flow-gen.digitaldata.works"
}
],
"RetryDelay": "00:00:05"
},
"AuthTokenKeys": {
"Cookie": "AuthToken",
"QueryString": "AuthToken",
"Issuer": "auth.digitaldata.works",
"Audience": "work-flow.digitaldata.works"
} }
} }

View File

@@ -7,7 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Infrastructure" Version="2.0.4" /> <PackageReference Include="DigitalData.Core.Infrastructure" Version="2.0.4" />
<PackageReference Include="DigitalData.Core.Infrastructure.AutoMapper" Version="1.0.2" /> <PackageReference Include="DigitalData.Core.Infrastructure.AutoMapper" Version="1.0.2" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" /> <PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />

View File

@@ -260,6 +260,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="Config.vb" /> <Compile Include="Config.vb" />
<Compile Include="LogProvider.vb" /> <Compile Include="LogProvider.vb" />
<Compile Include="Scheduler_API_SendEnvelopeMails.vb" />
<Compile Include="Service.Designer.vb"> <Compile Include="Service.Designer.vb">
<DependentUpon>Service.vb</DependentUpon> <DependentUpon>Service.vb</DependentUpon>
</Compile> </Compile>
@@ -288,7 +289,7 @@
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile> </Compile>
<Compile Include="Scheduler.vb" /> <Compile Include="Scheduler_FinishEnvelope.vb" />
<Compile Include="TempFiles.vb" /> <Compile Include="TempFiles.vb" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -0,0 +1,72 @@
Imports System.Collections.Specialized
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports EnvelopeGenerator.Common.Jobs
Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument
Imports Quartz
Public Class Scheduler_API_SendEnvelopeMails
Inherits BaseClass
Private Scheduler As IScheduler
Private ReadOnly ConnectionString As String
Private Const JobName = "SendInvitationMailsAPI"
Public Sub New(pLogConfig As LogConfig, pConnectionString As String)
MyBase.New(pLogConfig)
ConnectionString = pConnectionString
Dim oLogProvider = New LogProvider(Logger)
Logging.LogProvider.SetCurrentLogProvider(oLogProvider)
End Sub
Public Async Function Start(pInterval As Integer) As Task
Try
Logger.Debug("Starting Scheduler SendMailsfromAPI..")
Dim oProperties As New NameValueCollection()
Scheduler = Await SchedulerBuilder.Create(oProperties).
UseDefaultThreadPool(Sub(x) x.MaxConcurrency = 5).
BuildScheduler()
Dim oJobKey = New JobKey(JobName)
Dim oJobData = New JobDataMap() From {
{Common.Constants.LOGCONFIG, LogConfig},
{Common.Constants.DATABASE, ConnectionString}
}
Logger.Debug("Initialized Job [{0}]", JobName)
Dim oJob As IJobDetail = JobBuilder.Create(Of SendInvitationMailJob).
UsingJobData(oJobData).
WithIdentity(oJobKey).
Build()
Dim oTrigger As ITrigger = TriggerBuilder.Create().
ForJob(oJobKey).
WithIdentity($"{JobName}-trigger").
WithSimpleSchedule(Sub(s) s.
RepeatForever().
WithIntervalInMinutes(pInterval)).
StartNow().
Build()
Logger.Debug($"{JobName}-trigger initialized")
Await Scheduler.ScheduleJob(oJob, oTrigger)
Logger.Debug($"{JobName}-scheduled")
Await Scheduler.Start()
Logger.Info($"{JobName}-started")
Catch ex As Exception
Logger.Error(ex)
End Try
End Function
Public Async Function [Stop]() As Task
Logger.Info("Stopping scheduler SendMailsfromAPI..")
Await Scheduler.Shutdown()
Logger.Info("Scheduler SendMailsfromAPI stopped!")
End Function
End Class

View File

@@ -6,7 +6,7 @@ Imports EnvelopeGenerator.Common.Jobs
Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument
Imports Quartz Imports Quartz
Public Class Scheduler Public Class Scheduler_FinishEnvelope
Inherits BaseClass Inherits BaseClass
Private Scheduler As IScheduler Private Scheduler As IScheduler
@@ -28,7 +28,7 @@ Public Class Scheduler
Public Async Function Start(pInterval As Integer) As Task Public Async Function Start(pInterval As Integer) As Task
Try Try
Logger.Debug("Starting Scheduler..") Logger.Debug("Starting Scheduler Finish Envelope..")
Dim oProperties As New NameValueCollection() Dim oProperties As New NameValueCollection()

View File

@@ -10,7 +10,8 @@ Public Class Service
Private Config As Config Private Config As Config
Private Database As MSSQLServer Private Database As MSSQLServer
Private TempFiles As TempFiles Private TempFiles As TempFiles
Private Scheduler As Scheduler Private Scheduler1 As Scheduler_FinishEnvelope
Private Scheduler2 As Scheduler_API_SendEnvelopeMails
Protected Overrides Async Sub OnStart(ByVal args() As String) Protected Overrides Async Sub OnStart(ByVal args() As String)
Try Try
@@ -53,10 +54,13 @@ Public Class Service
' === Initialize Queue === ' === Initialize Queue ===
Logger.Debug("Inititalize Quartz") Logger.Debug("Inititalizing scheduler(s) ...")
Scheduler = New Scheduler(LogConfig, Config.ConnectionString, oKey, Config.PDFBurnerParams) Scheduler1 = New Scheduler_FinishEnvelope(LogConfig, Config.ConnectionString, oKey, Config.PDFBurnerParams)
Await Scheduler.Start(Config.IntervalInMin) Await Scheduler1.Start(Config.IntervalInMin)
Scheduler2 = New Scheduler_API_SendEnvelopeMails(LogConfig, Config.ConnectionString)
Await Scheduler2.Start(Config.IntervalInMin)
Logger.Info("Started [{0}] !", ServiceName) Logger.Info("Started [{0}] !", ServiceName)
@@ -67,8 +71,9 @@ Public Class Service
Protected Overrides Async Sub OnStop() Protected Overrides Async Sub OnStop()
Try Try
Logger.Info("Stopping [{0}] !", ServiceName) Logger.Info("Stopping [{0}] ...", ServiceName)
Await Scheduler.Stop() Await Scheduler1.Stop()
Await Scheduler2.Stop()
TempFiles.CleanUp() TempFiles.CleanUp()
Logger.Info("Stopped [{0}] !", ServiceName) Logger.Info("Stopped [{0}] !", ServiceName)
Catch ex As Exception Catch ex As Exception

View File

@@ -32,11 +32,27 @@ public class CommandManager
[Subcommand] [Subcommand]
public IEnvelopeReceiverService EnvelopeReceiver => _envelopeReceiverService; public IEnvelopeReceiverService EnvelopeReceiver => _envelopeReceiverService;
[Command] [Command(ArgumentSeparatorStrategy = ArgumentSeparatorStrategy.EndOfOptions)]
public async Task ReadDocument(IConsole console, int? id = null, int? envelopeId = null) public async Task ReadDocument(IConsole console,
[Option(Description = "ID of the document.")] int? id = null,
[Option(Description = "ID of the envelope containing the document.")] int? envelopeId = null,
[Option(Description = "Path to save the PDF")] bool save = false,
[Option(Description = "Directory to save the PDF")] string? dir = null,
[Option(Description = "Name of file to save the PDF")] string? fileName = null)
{ {
ReadDocumentQuery query = new(id, envelopeId); ReadDocumentQuery query = new(id, envelopeId);
var document = await _mediator.Send(query); var document = await _mediator.Send(query);
console.WriteLine(JsonSerializer.Serialize(document, Options)); console.WriteLine(JsonSerializer.Serialize(save ? document as ReadDocumentResponseBase : document, Options));
if (save)
{
dir ??= AppContext.BaseDirectory;
fileName ??= $"D{document?.Guid}E{document?.EnvelopeId}.pdf";
var path = Path.Combine(dir, fileName);
console.WriteLine("Save to " + path);
File.WriteAllBytes(path, document?.ByteData ?? Array.Empty<byte>());
}
} }
} }

View File

@@ -19,7 +19,7 @@
<PackageReference Include="CommandDotNet" Version="7.0.5" /> <PackageReference Include="CommandDotNet" Version="7.0.5" />
<PackageReference Include="CommandDotNet.IoC.MicrosoftDependencyInjection" Version="5.0.1" /> <PackageReference Include="CommandDotNet.IoC.MicrosoftDependencyInjection" Version="5.0.1" />
<PackageReference Include="CommandDotNet.NameCasing" Version="4.0.2" /> <PackageReference Include="CommandDotNet.NameCasing" Version="4.0.2" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" /> <PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.20" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.20" />
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" /> <PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.20" />

View File

@@ -1,4 +1,5 @@
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace EnvelopeGenerator.Terminal; namespace EnvelopeGenerator.Terminal;
@@ -8,6 +9,10 @@ public class Program
{ {
var builder = Host.CreateApplicationBuilder(args); var builder = Host.CreateApplicationBuilder(args);
builder.Configuration
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
var config = builder.Configuration; var config = builder.Configuration;
builder.Services.AddCommandManagerRunner(config); builder.Services.AddCommandManagerRunner(config);

View File

@@ -23,7 +23,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" /> <PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" /> <PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" /> <PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" />

View File

@@ -2101,7 +2101,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" /> <PackageReference Include="BuildBundlerMinifier2022" Version="2.9.9" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" /> <PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" /> <PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" /> <PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />