Compare commits

...

19 Commits

Author SHA1 Message Date
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
34 changed files with 443 additions and 259 deletions

View File

@@ -3,23 +3,8 @@
/// <summary>
/// Represents the response for reading a document.
/// </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>
/// The binary data of the document, if available.
/// </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>
<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.Client" Version="2.0.3" />
<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 AddedWhen As Date
Public Property ChangedWhen As Date
Public Property User As New User()
Public Property Documents As New List(Of EnvelopeDocument)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -371,6 +371,15 @@ Namespace My.Resources
End Get
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>
''' Sucht eine lokalisierte Zeichenfolge, die Neuer Umschlag ähnelt.
'''</summary>

View File

@@ -325,6 +325,15 @@ Namespace My.Resources
End Get
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>
''' Sucht eine lokalisierte Zeichenfolge, die Nein ähnelt.
'''</summary>

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<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="UserManager.Domain" Version="3.0.2" />
</ItemGroup>

View File

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

View File

@@ -18,6 +18,9 @@ Public Class FlattenFormFields
Dim newFilesPath As String = Path.Combine(oFolder, "InputFieldsFlattend_" & Path.GetFileName(pFilePath))
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
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
' by using the '*' as shown below:
' [assembly: AssemblyVersion("1.0.*")]
<Assembly: AssemblyVersion("2.9.0.0")>
<Assembly: AssemblyVersion("2.9.1.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
Try
If SaveEnvelopeWithOutValidation() = True Then
bsitm_info.Caption = "Data saved succeddfully " + Now.ToString
bsitm_info.Caption = "Data saved successfully " + Now.ToString
Else
bsitm_info.Caption = "Exceprion - Error saving Data. Check LOG"
End If

View File

@@ -47,6 +47,7 @@ Partial Class frmMain
Me.colStatus = New DevExpress.XtraGrid.Columns.GridColumn()
Me.colTitle = 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.btnCreateEnvelope = 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.GridColumn5 = 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.SplitContainerControl2 = New DevExpress.XtraEditors.SplitContainerControl()
Me.GridControlData = New DevExpress.XtraGrid.GridControl()
Me.GridViewData = New DevExpress.XtraGrid.Views.Grid.GridView()
Me.PanelControl1 = New DevExpress.XtraEditors.PanelControl()
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.GroupControl1 = New DevExpress.XtraEditors.GroupControl()
Me.btnEnvelopes_All = New DevExpress.XtraEditors.SimpleButton()
Me.btnEnvelopes_thisYear = 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.SaveFileDialog1 = New System.Windows.Forms.SaveFileDialog()
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.Panel1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SplitContainerControl1.Panel1.SuspendLayout()
@@ -279,11 +281,12 @@ Partial Class frmMain
'
'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.Name = "ViewEnvelopes"
Me.ViewEnvelopes.OptionsBehavior.Editable = False
Me.ViewEnvelopes.OptionsBehavior.ReadOnly = True
Me.ViewEnvelopes.OptionsView.ShowAutoFilterRow = True
Me.ViewEnvelopes.OptionsView.ShowIndicator = False
'
'colEnvelopeId
@@ -318,6 +321,14 @@ Partial Class frmMain
Me.colAddedWhen.FieldName = "AddedWhen"
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
'
Me.RibbonControl.ExpandCollapseItem.Id = 0
@@ -637,11 +648,12 @@ Partial Class frmMain
'
'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.Name = "ViewCompleted"
Me.ViewCompleted.OptionsBehavior.Editable = False
Me.ViewCompleted.OptionsBehavior.ReadOnly = True
Me.ViewCompleted.OptionsView.ShowAutoFilterRow = True
Me.ViewCompleted.OptionsView.ShowIndicator = False
'
'GridColumn3
@@ -665,9 +677,19 @@ Partial Class frmMain
'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.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
'
Me.XtraTabPageAdmin.Controls.Add(Me.SplitContainerControl2)
@@ -688,7 +710,7 @@ Partial Class frmMain
'SplitContainerControl2.Panel2
'
resources.ApplyResources(Me.SplitContainerControl2.Panel2, "SplitContainerControl2.Panel2")
Me.SplitContainerControl2.SplitterPosition = 819
Me.SplitContainerControl2.SplitterPosition = 907
'
'GridControlData
'
@@ -702,6 +724,7 @@ Partial Class frmMain
'
Me.GridViewData.GridControl = Me.GridControlData
Me.GridViewData.Name = "GridViewData"
Me.GridViewData.OptionsView.ShowAutoFilterRow = True
'
'PanelControl1
'
@@ -717,6 +740,20 @@ Partial Class frmMain
resources.ApplyResources(Me.GroupControl2, "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
'
Me.GroupControl1.Controls.Add(Me.btnEnvelopes_All)
@@ -726,13 +763,6 @@ Partial Class frmMain
resources.ApplyResources(Me.GroupControl1, "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
'
Me.btnEnvelopes_All.Appearance.BackColor = System.Drawing.Color.MediumTurquoise
@@ -773,13 +803,6 @@ Partial Class frmMain
'
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
'
resources.ApplyResources(Me, "$this")
@@ -906,4 +929,6 @@ Partial Class frmMain
Friend WithEvents BarStaticItemGhost As DevExpress.XtraBars.BarStaticItem
Friend WithEvents btnEvvallUs_thismonth 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

View File

@@ -265,7 +265,7 @@
<value>2</value>
</data>
<data name="colContractType.Width" type="System.Int32, mscorlib">
<value>120</value>
<value>112</value>
</data>
<data name="colStatus.Caption" xml:space="preserve">
<value>Status</value>
@@ -277,7 +277,7 @@
<value>1</value>
</data>
<data name="colStatus.Width" type="System.Int32, mscorlib">
<value>193</value>
<value>180</value>
</data>
<data name="colTitle.Caption" xml:space="preserve">
<value>Titel</value>
@@ -289,7 +289,7 @@
<value>0</value>
</data>
<data name="colTitle.Width" type="System.Int32, mscorlib">
<value>575</value>
<value>538</value>
</data>
<data name="colAddedWhen.Caption" xml:space="preserve">
<value>Erstellt am</value>
@@ -301,7 +301,19 @@
<value>3</value>
</data>
<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 name="RibbonControl.ExpandCollapseItem.ImageOptions.ImageIndex" type="System.Int32, mscorlib">
<value>0</value>
@@ -1052,7 +1064,7 @@
<value>2</value>
</data>
<data name="GridColumn3.Width" type="System.Int32, mscorlib">
<value>120</value>
<value>100</value>
</data>
<data name="GridColumn4.Caption" xml:space="preserve">
<value>Status</value>
@@ -1064,7 +1076,7 @@
<value>1</value>
</data>
<data name="GridColumn4.Width" type="System.Int32, mscorlib">
<value>195</value>
<value>163</value>
</data>
<data name="GridColumn5.Caption" xml:space="preserve">
<value>Titel</value>
@@ -1076,7 +1088,7 @@
<value>0</value>
</data>
<data name="GridColumn5.Width" type="System.Int32, mscorlib">
<value>574</value>
<value>482</value>
</data>
<data name="GridColumn7.Caption" xml:space="preserve">
<value>Erstellt am</value>
@@ -1088,7 +1100,19 @@
<value>3</value>
</data>
<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 name="GridCompleted.Size" type="System.Drawing.Size, System.Drawing">
<value>1088, 469</value>
@@ -1139,7 +1163,7 @@
<value>0, 0</value>
</data>
<data name="GridControlData.Size" type="System.Drawing.Size, System.Drawing">
<value>819, 390</value>
<value>907, 390</value>
</data>
<data name="GridControlData.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
@@ -1262,7 +1286,7 @@
<value>2</value>
</data>
<data name="GroupControl2.Text" xml:space="preserve">
<value>Umschläge alle User</value>
<value>Umschläge alle User (abrechnungsrelevant)</value>
</data>
<data name="&gt;&gt;GroupControl2.Name" xml:space="preserve">
<value>GroupControl2</value>
@@ -1717,6 +1741,12 @@
<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>
</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">
<value>btnCreateEnvelope</value>
</data>
@@ -1939,6 +1969,12 @@
<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>
</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">
<value>GridViewData</value>
</data>

View File

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

View File

@@ -1,201 +1,150 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.UserManager.Application.Contracts;
using DigitalData.UserManager.Application.DTOs.User;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using DigitalData.UserManager.Application.DTOs.Auth;
using Microsoft.AspNetCore.Authorization;
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>
/// 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>
[Route("api/[controller]")]
[ApiController]
public partial class AuthController : ControllerBase
/// <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)
{
private readonly ILogger<AuthController> _logger;
private readonly IUserService _userService;
private readonly IDirectorySearchService _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();
_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 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>
<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="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="Scalar.AspNetCore" Version="2.1.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.4.3" />
<PackageReference Include="Scalar.AspNetCore" Version="2.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
<PackageReference Include="DigitalData.Core.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.1" />
<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.Application;
using DigitalData.UserManager.Application;
using EnvelopeGenerator.Infrastructure;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Localization;
@@ -10,11 +9,19 @@ using Scalar.AspNetCore;
using Microsoft.OpenApi.Models;
using DigitalData.UserManager.DependencyInjection;
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 config = builder.Configuration;
var deferredProvider = new DeferredServiceProvider();
builder.Services.AddControllers();
//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.");
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
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
@@ -114,6 +164,8 @@ builder.Services
var app = builder.Build();
deferredProvider.Factory = () => app.Services;
app.MapOpenApi();
// Configure the HTTP request pipeline.

View File

@@ -4,5 +4,15 @@
"Default": "Information",
"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=*))",
"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>
<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.AutoMapper" Version="1.0.2" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />

View File

@@ -32,11 +32,27 @@ public class CommandManager
[Subcommand]
public IEnvelopeReceiverService EnvelopeReceiver => _envelopeReceiverService;
[Command]
public async Task ReadDocument(IConsole console, int? id = null, int? envelopeId = null)
[Command(ArgumentSeparatorStrategy = ArgumentSeparatorStrategy.EndOfOptions)]
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);
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.IoC.MicrosoftDependencyInjection" Version="5.0.1" />
<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="Microsoft.EntityFrameworkCore.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;
@@ -8,6 +9,10 @@ public class Program
{
var builder = Host.CreateApplicationBuilder(args);
builder.Configuration
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
var config = builder.Configuration;
builder.Services.AddCommandManagerRunner(config);

View File

@@ -23,7 +23,7 @@
<ItemGroup>
<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.Application" Version="3.2.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.20" />

View File

@@ -2101,7 +2101,7 @@
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<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.Application" Version="3.2.1" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />