Compare commits
66 Commits
bugfix/sig
...
fe252b9979
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe252b9979 | ||
|
|
f17820e011 | ||
|
|
a21c993cb5 | ||
|
|
dd4afc5ddf | ||
|
|
c220b9e1c8 | ||
|
|
778a498e00 | ||
|
|
48240f2f30 | ||
|
|
e3dfa8dd39 | ||
|
|
6e641395d5 | ||
|
|
fbd09cb570 | ||
|
|
7389909d77 | ||
|
|
ded88383b3 | ||
|
|
1b9b51fbd2 | ||
|
|
afa6dda16f | ||
|
|
994c844f25 | ||
|
|
4551e5dc64 | ||
|
|
ff34e6afab | ||
|
|
a78912260a | ||
|
|
c1e81c546f | ||
|
|
9a950ae37d | ||
|
|
6cec82abd5 | ||
|
|
26616b4cab | ||
|
|
178ec9226d | ||
|
|
0147f525fa | ||
|
|
f0ed6137d1 | ||
|
|
b4ab2c4423 | ||
|
|
5715343651 | ||
|
|
6550be0235 | ||
|
|
99b0dba79f | ||
|
|
2f8d5f1fc8 | ||
|
|
6969f5f93e | ||
|
|
7bbed3890e | ||
|
|
98290c7b28 | ||
|
|
d55006fdda | ||
|
|
b2cc0cb65a | ||
|
|
049827a133 | ||
|
|
b02ab585cb | ||
|
|
c8a5a8627d | ||
|
|
ecf0771f9e | ||
|
|
02c7040b39 | ||
|
|
2cb5d0c0d5 | ||
|
|
9f186afdff | ||
|
|
ec76014ce7 | ||
|
|
e7bc43b339 | ||
|
|
26be8d4565 | ||
|
|
17902c4824 | ||
|
|
396c6014fb | ||
|
|
06175b0c95 | ||
|
|
5375d89d5b | ||
|
|
abd1807b18 | ||
|
|
3f33be452c | ||
|
|
9a4931781a | ||
|
|
b3a2e1559a | ||
|
|
261d1b3db9 | ||
|
|
401d03aac2 | ||
|
|
7871bf72f6 | ||
|
|
7e07afa384 | ||
|
|
251420134a | ||
|
|
701b26289b | ||
|
|
754e3ddc7a | ||
|
|
a0e8cc6989 | ||
|
|
b9f25a0ac4 | ||
|
|
f40ee49977 | ||
|
|
d08e93cbef | ||
|
|
4a48bbb3e2 | ||
|
|
9725e2a729 |
@@ -1,9 +1,11 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record ConfigDto(
|
||||
string DocumentPath,
|
||||
int SendingProfile,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record DocumentReceiverElementDto(
|
||||
int Id,
|
||||
int DocumentId,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record DocumentStatusDto(
|
||||
int Id,
|
||||
int EnvelopeId,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EmailTemplateDto(
|
||||
int Id,
|
||||
string Name,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeCertificateDto(
|
||||
int Id,
|
||||
int EnvelopeId,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeDocumentDto
|
||||
(
|
||||
int Id,
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
using DigitalData.UserManager.Application.DTOs.User;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeDto() : IUnique<int>
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeHistoryCreateDto(
|
||||
int EnvelopeId,
|
||||
string UserReference,
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.UserManager.Application.DTOs.User;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeHistoryDto(
|
||||
long Id,
|
||||
int EnvelopeId,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeReceiverBasicDto() : IUnique<(int Envelope, int Receiver)>
|
||||
{
|
||||
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeReceiverDto() : EnvelopeReceiverBasicDto()
|
||||
{
|
||||
public EnvelopeDto? Envelope { get; set; }
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeReceiverSecretDto() : EnvelopeReceiverDto()
|
||||
{
|
||||
public string? AccessCode { get; init; }
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeReceiverReadOnlyCreateDto(
|
||||
DateTime DateValid)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeReceiverReadOnlyDto(
|
||||
long Id,
|
||||
long EnvelopeId,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeReceiverReadOnlyUpdateDto(
|
||||
long Id,
|
||||
DateTime DateValid,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record EnvelopeTypeDto(
|
||||
int Id,
|
||||
string Title,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs.Messaging
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Messaging
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public class GtxMessagingResponse : Dictionary<string, object?> { }
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.DTOs.Messaging
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Messaging
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record SmsResponse
|
||||
{
|
||||
public required bool Ok { get; init; }
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Receiver
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record ReceiverCreateDto([EmailAddress] string EmailAddress, string? TotpSecretkey = null)
|
||||
{
|
||||
public string Signature => sha256HexOfMail.Value;
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record ReceiverReadDto(
|
||||
int Id,
|
||||
string EmailAddress,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record ReceiverUpdateDto(int Id, string? TotpSecretkey = null, DateTime? TfaRegDeadline = null) : IUnique<int>;
|
||||
@@ -1,7 +1,9 @@
|
||||
using DigitalData.Core.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.Application.DTOs
|
||||
{
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public record UserReceiverDto(
|
||||
int Id,
|
||||
int UserId,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using EnvelopeGenerator.Common;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
|
||||
|
||||
/// <summary>
|
||||
/// Ein Befehl zum Zurücksetzen einer E-Mail-Vorlage auf die Standardwerte.
|
||||
/// Erbt von <see cref="EmailTemplateQuery"/> und ermöglicht die Angabe einer optionalen ID und eines Typs der E-Mail-Vorlage.
|
||||
/// </summary>
|
||||
/// <param name="Id">Die optionale ID der E-Mail-Vorlage, die zurückgesetzt werden soll.</param>
|
||||
/// <param name="Type">Der Typ der E-Mail-Vorlage, z. B. <see cref="Constants.EmailTemplateType"/> (optional). Beispiele:
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.
|
||||
/// 7 - DocumentRejected_ADM (Für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.
|
||||
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.
|
||||
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </param>
|
||||
public record ResetEnvelopeTemplateCommand(int? Id, Constants.EmailTemplateType? Type) : EmailTemplateQuery(Id, Type);
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Commands.Update;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Befehl zum Aktualisieren einer E-Mail-Vorlage.
|
||||
/// </summary>
|
||||
/// <param name="Body">
|
||||
/// (Optional)Der neue Inhalt des E-Mail-Textkörpers. Wenn null, bleibt der vorhandene Inhalt unverändert.
|
||||
/// </param>
|
||||
/// <param name="Subject">
|
||||
/// (Optional) Der neue Betreff der E-Mail. Wenn null, bleibt der vorhandene Betreff unverändert.
|
||||
/// </param>
|
||||
public record UpdateEmailTemplateCommand(string? Body = null, string? Subject = null)
|
||||
{
|
||||
/// <param>
|
||||
/// Die Abfrage, die die E-Mail-Vorlage darstellt, die aktualisiert werden soll.
|
||||
/// </param>
|
||||
[JsonIgnore]
|
||||
public EmailTemplateQuery? EmailTemplateQuery { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using EnvelopeGenerator.Common;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für E-Mail-Vorlagen, die für Absender und Empfänger von Umschlägen verwendet werden.
|
||||
/// Die Standardkultur ist "de-DE".
|
||||
/// </summary>
|
||||
/// <param name="Id">Die eindeutige Kennung der E-Mail-Vorlage (optional).</param>
|
||||
/// <param name="Type">Der Typ der E-Mail-Vorlage, z. B. <see cref="Constants.EmailTemplateType"/> (optional). Beispiele:
|
||||
/// 0 - DocumentReceived: Benachrichtigung über den Empfang eines Dokuments.
|
||||
/// 1 - DocumentSigned: Benachrichtigung über die Unterzeichnung eines Dokuments.
|
||||
/// 2 - DocumentDeleted: Benachrichtigung über das Löschen eines Dokuments.
|
||||
/// 3 - DocumentCompleted: Benachrichtigung über den Abschluss eines Dokuments.
|
||||
/// 4 - DocumentAccessCodeReceived: Benachrichtigung über den Erhalt eines Zugangscodes.
|
||||
/// 5 - DocumentShared: Benachrichtigung über das Teilen eines Dokuments.
|
||||
/// 6 - TotpSecret: Benachrichtigung über ein TOTP-Geheimnis.
|
||||
/// 7 - DocumentRejected_ADM (Für den Absender): Mail an den Absender, wenn das Dokument abgelehnt wird.
|
||||
/// 8 - DocumentRejected_REC (Für den ablehnenden Empfänger): Mail an den ablehnenden Empfänger, wenn das Dokument abgelehnt wird.
|
||||
/// 9 - DocumentRejected_REC_2 (Für sonstige Empfänger): Mail an andere Empfänger (Brief), wenn das Dokument abgelehnt wird.
|
||||
/// </param>
|
||||
public record EmailTemplateQuery(int? Id = null, Constants.EmailTemplateType? Type = null)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage dar, um eine E-Mail-Vorlage zu lesen.
|
||||
/// Diese Klasse erbt von <see cref="EmailTemplateQuery"/>.
|
||||
/// </summary>
|
||||
public record ReadEmailTemplateQuery : EmailTemplateQuery
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt die Antwort für eine Abfrage von E-Mail-Vorlagen bereit.
|
||||
/// </summary>
|
||||
/// <param name="Id">Die eindeutige Kennung der E-Mail-Vorlage.</param>
|
||||
/// <param name="Type">Der Typ der E-Mail-Vorlage.</param>
|
||||
/// <param name="AddedWhen">Das Datum und die Uhrzeit, wann die Vorlage hinzugefügt wurde.</param>
|
||||
/// <param name="Body">Der Inhalt (Body) der E-Mail-Vorlage. Kann null sein.</param>
|
||||
/// <param name="Subject">Der Betreff der E-Mail-Vorlage. Kann null sein.</param>
|
||||
/// <param name="ChangedWhen">Das Datum und die Uhrzeit, wann die Vorlage zuletzt geändert wurde. Kann null sein.</param>
|
||||
public record ReadEmailTemplateResponse(
|
||||
int Id,
|
||||
int Type,
|
||||
DateTime AddedWhen,
|
||||
string? Body = null,
|
||||
string? Subject = null,
|
||||
DateTime? ChangedWhen = null)
|
||||
{
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -17,6 +19,7 @@
|
||||
<PackageReference Include="DigitalData.Core.Client" Version="2.0.3" />
|
||||
<PackageReference Include="DigitalData.Core.DTO" Version="2.0.0" />
|
||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="2.0.0" />
|
||||
<PackageReference Include="MediatR" Version="11.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
|
||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
using MediatR;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Commands.Create;
|
||||
|
||||
/// <summary>
|
||||
/// Befehl zur Erstellung eines Umschlags.
|
||||
/// </summary>
|
||||
/// <param name="Title">Der Titel des Umschlags. Dies ist ein Pflichtfeld.</param>
|
||||
/// <param name="Message">Die Nachricht, die im Umschlag enthalten sein soll. Dies ist ein Pflichtfeld.</param>
|
||||
/// <param name="Document">Das mit dem Umschlag verknüpfte Dokument. Dies ist ein Pflichtfeld.</param>
|
||||
/// <param name="Receivers">Eine Sammlung von Empfängern, die den Umschlag erhalten. Dies ist ein Pflichtfeld.</param>
|
||||
/// <param name="TFAEnabled">Gibt an, ob die Zwei-Faktor-Authentifizierung für den Umschlag aktiviert ist. Standardmäßig false.</param>
|
||||
public record CreateEnvelopeReceiverCommand(
|
||||
[Required] string Title,
|
||||
[Required] string Message,
|
||||
[Required] DocumentCreateCommand Document,
|
||||
[Required] IEnumerable<ReceiverGetOrCreateCommand> Receivers,
|
||||
bool TFAEnabled = false
|
||||
) : IRequest;
|
||||
|
||||
#region DTOs
|
||||
/// <summary>
|
||||
/// Signaturposition auf einem Dokument.
|
||||
/// </summary>
|
||||
/// <param name="X">X-Position</param>
|
||||
/// <param name="Y">Y-Position</param>
|
||||
/// <param name="Page">Seite, auf der sie sich befindet</param>
|
||||
public record Signature([Required] int X, [Required] int Y, [Required] int Page);
|
||||
|
||||
/// <summary>
|
||||
/// DTO für Empfänger, die erstellt oder abgerufen werden sollen.
|
||||
/// Wenn nicht, wird sie erstellt und mit einer Signatur versehen.
|
||||
/// </summary>
|
||||
/// <param name="Signatures">Unterschriften auf Dokumenten.</param>
|
||||
/// <param name="Salution">Der Name, mit dem der Empfänger angesprochen werden soll. Bei Null oder keinem Wert wird der zuletzt verwendete Name verwendet.</param>
|
||||
/// <param name="PhoneNumber">Sollte mit Vorwahl geschrieben werden</param>
|
||||
public record ReceiverGetOrCreateCommand([Required] IEnumerable<Signature> Signatures, string? Salution = null, string? PhoneNumber = null)
|
||||
{
|
||||
private string _emailAddress = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// E-Mail-Adresse des Empfängers.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required string EmailAddress { get => _emailAddress.ToLower(); init => _emailAddress = _emailAddress.ToLower(); }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// DTO zum Erstellen eines Dokuments.
|
||||
/// </summary>
|
||||
/// <param name="DataAsByte">
|
||||
/// Die Dokumentdaten im Byte-Array-Format. Wird verwendet, wenn das Dokument als Roh-Binärdaten bereitgestellt wird.
|
||||
/// </param>
|
||||
/// <param name="DataAsBase64">
|
||||
/// Die Dokumentdaten im Base64-String-Format. Wird verwendet, wenn das Dokument als Base64-codierter String bereitgestellt wird.
|
||||
/// </param>
|
||||
public record DocumentCreateCommand(byte[]? DataAsByte = null, string? DataAsBase64 = null);
|
||||
#endregion
|
||||
@@ -0,0 +1,47 @@
|
||||
using EnvelopeGenerator.Application.Histories;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage für einen Envelope-Empfänger dar.
|
||||
/// </summary>
|
||||
/// <param name="Status">Der Status der Abfrage, optional.</param>
|
||||
public record EnvelopeReceiverQuery(EnvelopeStatusQuery? Status = null);
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert den Status eines Umschlags und dessen Beziehung zum Empfänger. (vgl. auch <see cref="Common.Constants.EnvelopeStatus"/>
|
||||
/// Invalid (0): Ungültiger Status.
|
||||
/// EnvelopeCreated (1001): Der Umschlag wurde erstellt.
|
||||
/// EnvelopeSaved (1002): Der Umschlag wurde gespeichert.
|
||||
/// EnvelopeQueued (1003): Der Umschlag wurde zur Verarbeitung eingeplant.
|
||||
/// EnvelopeSent (1004): Der Umschlag wurde versendet. (Nicht verwendet)
|
||||
/// EnvelopePartlySigned (1005): Der Umschlag wurde teilweise unterschrieben.
|
||||
/// EnvelopeCompletelySigned (1006): Der Umschlag wurde vollständig unterschrieben.
|
||||
/// EnvelopeReportCreated (1007): Ein Abschlussbericht wurde für den Umschlag erstellt.
|
||||
/// EnvelopeArchived (1008): Der Umschlag wurde archiviert.
|
||||
/// EnvelopeDeleted (1009): Der Umschlag wurde gelöscht.
|
||||
/// AccessCodeRequested (2001): Der Zugriffscode wurde angefordert.
|
||||
/// AccessCodeCorrect (2002): Der Zugriffscode war korrekt.
|
||||
/// AccessCodeIncorrect (2003): Der Zugriffscode war falsch.
|
||||
/// DocumentOpened (2004): Das Dokument wurde geöffnet.
|
||||
/// DocumentSigned (2005): Ein Dokument wurde unterschrieben.
|
||||
/// SignatureConfirmed (2006): Die Signatur wurde bestätigt.
|
||||
/// DocumentRejected (2007): Ein Dokument wurde abgelehnt.
|
||||
/// EnvelopeShared (2008): Der Umschlag wurde geteilt.
|
||||
/// EnvelopeViewed (2009): Der Umschlag wurde angesehen.
|
||||
/// DocumentForwarded (4001): Das Dokument wurde weitergeleitet.
|
||||
/// MessageInvitationSent (3001): Einladung wurde gesendet (vom Trigger verwendet).
|
||||
/// MessageAccessCodeSent (3002): Zugriffscode wurde gesendet.
|
||||
/// MessageConfirmationSent (3003): Bestätigungsnachricht wurde gesendet.
|
||||
/// MessageDeletionSent (3004): Löschbenachrichtigung wurde gesendet.
|
||||
/// MessageCompletionSent (3005): Abschlussbenachrichtigung wurde gesendet.
|
||||
/// <param name="Min">Der minimale Statuswert, der berücksichtigt werden soll.</param>
|
||||
/// <param name="Max">Der maximale Statuswert, der berücksichtigt werden soll.</param>
|
||||
/// <param name="Ignore">Eine Liste von Statuswerten, die ignoriert werden sollen.</param>
|
||||
/// </summary>
|
||||
public record EnvelopeStatusQuery(
|
||||
int? Min = null,
|
||||
int? Max = null,
|
||||
int[]? Ignore = null)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using EnvelopeGenerator.Application.Histories;
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries.Read;
|
||||
using EnvelopeGenerator.Application.Receivers.Queries.Read;
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage zum Lesen eines Envelope-Empfängers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Diese Abfrage kombiniert Informationen über einen Umschlag (<see cref="ReadEnvelopeQuery"/>)
|
||||
/// und einen Empfänger (<see cref="ReadReceiverQuery"/>), um eine vollständige Antwort
|
||||
/// (<see cref="ReadEnvelopeReceiverResponse"/>) zu generieren.
|
||||
/// Die Antwort enthält Details wie den Status, die Zuordnung zwischen Umschlag und Empfänger
|
||||
/// sowie zusätzliche Metadaten.
|
||||
/// </remarks>
|
||||
/// <param name="Status">Umschlag oder Empfängerstatus.</param>
|
||||
public record ReadEnvelopeReceiverQuery(EnvelopeStatusQuery? Status = null) : EnvelopeReceiverQuery(Status), IRequest<ReadEnvelopeReceiverResponse>
|
||||
{
|
||||
/// <summary>
|
||||
/// Der Umschlag, der mit dem Empfänger verknüpft ist.
|
||||
/// </summary>
|
||||
public ReadEnvelopeQuery? Envelope { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Empfänger, der mit dem Umschlag verknüpft ist.
|
||||
/// </summary>
|
||||
public ReadReceiverQuery? Receiver { get; init; }
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries.Read;
|
||||
using EnvelopeGenerator.Application.Receivers.Queries.Read;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace EnvelopeGenerator.Application.EnvelopeReceivers.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert die Antwort für das Lesen eines Envelope-Empfängers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Diese Klasse enthält Informationen über einen spezifischen Empfänger eines Umschlags (Envelope).
|
||||
/// Sie verknüpft die Empfängerinformationen mit den zugehörigen Umschlagsdaten und bietet zusätzliche Metadaten.
|
||||
/// </remarks>
|
||||
/// <param name="UserId">Die eindeutige Kennung des Benutzers, der den Empfänger erstellt hat.</param>
|
||||
/// <param name="Status">Der Status des Empfängers als numerischer Wert.</param>
|
||||
public record ReadEnvelopeReceiverResponse(int UserId, int Status)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gibt die zusammengesetzte Kennung des Empfängers zurück, bestehend aus der Umschlags-ID und der Empfänger-ID.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Diese Eigenschaft kombiniert die eindeutige Kennung des Umschlags (EnvelopeId) und die des Empfängers (ReceiverId)
|
||||
/// zu einer einzigen, leicht zugänglichen Struktur.
|
||||
/// </remarks>
|
||||
[NotMapped]
|
||||
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
|
||||
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des zugehörigen Umschlags.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int EnvelopeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Die eindeutige Kennung des Empfängers.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public int ReceiverId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Die Reihenfolge des Empfängers innerhalb des Umschlags.
|
||||
/// </summary>
|
||||
public int Sequence { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Name des Empfängers. Kann als Platzhalter verwendet werden.
|
||||
/// </summary>
|
||||
[TemplatePlaceholder("[NAME_RECEIVER]")]
|
||||
public string? Name { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Die Berufsbezeichnung des Empfängers.
|
||||
/// </summary>
|
||||
public string? JobTitle { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Der Firmenname des Empfängers.
|
||||
/// </summary>
|
||||
public string? CompanyName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Eine private Nachricht, die mit dem Empfänger verknüpft ist.
|
||||
/// </summary>
|
||||
public string? PrivateMessage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann der Empfänger hinzugefügt wurde.
|
||||
/// </summary>
|
||||
public DateTime AddedWhen { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Das Datum und die Uhrzeit, wann der Empfänger zuletzt geändert wurde (falls vorhanden).
|
||||
/// </summary>
|
||||
public DateTime? ChangedWhen { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gibt an, ob der Empfänger eine Telefonnummer hat.
|
||||
/// </summary>
|
||||
public bool HasPhoneNumber { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Die zugehörigen Umschlagsdaten.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public required ReadEnvelopeResponse Envelope { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Die Liste der Empfängerinformationen.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public IEnumerable<ReadReceiverResponse> Receiver { get; init; } = new List<ReadReceiverResponse>();
|
||||
}
|
||||
16
EnvelopeGenerator.Application/Envelopes/EnvelopeQuery.cs
Normal file
16
EnvelopeGenerator.Application/Envelopes/EnvelopeQuery.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using MediatR;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Envelopes;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für Umschläge.
|
||||
/// </summary>
|
||||
/// <param name="Id">Die eindeutige Kennung des Umschlags.</param>
|
||||
/// <param name="Status">Der Status des Umschlags.</param>
|
||||
/// <param name="Uuid">Die universell eindeutige Kennung des Umschlags.</param>
|
||||
public record EnvelopeQuery(
|
||||
int? Id = null,
|
||||
int? Status = null,
|
||||
string? Uuid = null) : IRequest
|
||||
{
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EnvelopeGenerator.Application.Envelopes.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage zum Lesen von Briefumschlägen dar.
|
||||
/// </summary>
|
||||
public record ReadEnvelopeQuery : EnvelopeQuery
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using EnvelopeGenerator.Common;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Envelopes.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert die Antwort für das Lesen eines Umschlags.
|
||||
/// </summary>
|
||||
/// <param name="Id">Die eindeutige Kennung des Umschlags.</param>
|
||||
/// <param name="UserId">Die Kennung des Benutzers, der den Umschlag erstellt hat.</param>
|
||||
/// <param name="Status">Der Status des Umschlags als numerischer Wert.</param>
|
||||
/// <param name="Uuid">Die universelle eindeutige Kennung (UUID) des Umschlags.</param>
|
||||
/// <param name="Message">Eine optionale Nachricht, die mit dem Umschlag verknüpft ist.</param>
|
||||
/// <param name="AddedWhen">Das Datum und die Uhrzeit, wann der Umschlag hinzugefügt wurde.</param>
|
||||
/// <param name="ChangedWhen">Das Datum und die Uhrzeit, wann der Umschlag zuletzt geändert wurde (falls vorhanden).</param>
|
||||
/// <param name="Title">Ein optionaler Titel des Umschlags.</param>
|
||||
/// <param name="Language">Die Sprache, die mit dem Umschlag verknüpft ist.</param>
|
||||
/// <param name="TFAEnabled">Gibt an, ob die Zwei-Faktor-Authentifizierung (TFA) aktiviert ist.</param>
|
||||
/// <param name="User">Das Benutzerobjekt, das mit dem Umschlag verknüpft ist.</param>
|
||||
public record ReadEnvelopeResponse(
|
||||
int Id,
|
||||
int UserId,
|
||||
int Status,
|
||||
string Uuid,
|
||||
string? Message,
|
||||
DateTime AddedWhen,
|
||||
DateTime? ChangedWhen,
|
||||
string? Title,
|
||||
string Language,
|
||||
bool TFAEnabled,
|
||||
DigitalData.UserManager.Domain.Entities.User User)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gibt den Namen des Status zurück, der dem numerischen Statuswert entspricht.
|
||||
/// </summary>
|
||||
public string StatusName => ((Constants.EnvelopeStatus)Status).ToString();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using EnvelopeGenerator.Application.Receivers.Queries.Read;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Envelopes.Queries.ReceiverName;
|
||||
|
||||
/// <summary>
|
||||
/// Eine Abfrage, um die zuletzt verwendete Anrede eines Empfängers zu ermitteln,
|
||||
/// damit diese für zukünftige Umschläge wiederverwendet werden kann.
|
||||
/// </summary>
|
||||
/// <param name="Envelope">Der Umschlag, für den die Anrede des Empfängers ermittelt werden soll.</param>
|
||||
/// <param name="OnlyLast">Gibt an, ob nur die zuletzt verwendete Anrede zurückgegeben werden soll.</param>
|
||||
public record ReadReceiverNameQuery(EnvelopeQuery? Envelope = null, bool OnlyLast = true) : ReadReceiverQuery
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries.Read;
|
||||
using EnvelopeGenerator.Application.Receivers.Queries.Read;
|
||||
using EnvelopeGenerator.Common;
|
||||
|
||||
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||
/// </summary>
|
||||
/// <param name="EnvelopeId">Die eindeutige Kennung des Umschlags.</param>
|
||||
/// <param name="Envelope">Die Abfrage, die den Umschlag beschreibt.</param>
|
||||
/// <param name="Receiver">Die Abfrage, die den Empfänger beschreibt.</param>
|
||||
/// <param name="Related">Abfrage, die angibt, worauf sich der Datensatz bezieht. Ob er sich auf den Empfänger, den Sender oder das System bezieht, wird durch 0, 1 bzw. 2 dargestellt.</param>
|
||||
/// <param name="OnlyLast">Abfrage zur Steuerung, ob nur der aktuelle Status oder der gesamte Datensatz zurückgegeben wird.</param>
|
||||
public record ReadHistoryQuery(
|
||||
int EnvelopeId,
|
||||
ReadEnvelopeQuery? Envelope = null,
|
||||
ReadReceiverQuery? Receiver = null,
|
||||
Constants.ReferenceType? Related = null,
|
||||
bool? OnlyLast = true);
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace EnvelopeGenerator.Application.Receivers.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Stellt eine Abfrage dar, um die Details eines Empfängers zu lesen.
|
||||
/// Diese Abfrage erbt von <see cref="ReceiverQuery"/> und wird verwendet,
|
||||
/// um spezifische Informationen über einen Empfänger abzurufen.
|
||||
/// </summary>
|
||||
public record ReadReceiverQuery : ReceiverQuery
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace EnvelopeGenerator.Application.Receivers.Queries.Read;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert die Antwort auf eine Abfrage, um einen Empfänger zu lesen.
|
||||
/// </summary>
|
||||
/// <param name="Id">Die eindeutige Identifikationsnummer des Empfängers.</param>
|
||||
/// <param name="EmailAddress">Die E-Mail-Adresse des Empfängers.</param>
|
||||
/// <param name="AddedWhen">Das Datum und die Uhrzeit, wann der Empfänger hinzugefügt wurde.</param>
|
||||
/// <param name="Signature">Die Signatur des Empfängers.</param>
|
||||
public record ReadReceiverResponse(int Id, string EmailAddress, DateTime AddedWhen, string Signature)
|
||||
{
|
||||
}
|
||||
9
EnvelopeGenerator.Application/Receivers/ReceiverQuery.cs
Normal file
9
EnvelopeGenerator.Application/Receivers/ReceiverQuery.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace EnvelopeGenerator.Application.Receivers;
|
||||
|
||||
/// <summary>
|
||||
/// Empfänger des Umschlags
|
||||
/// </summary>
|
||||
/// <param name="Id">ID des Empfängers</param>
|
||||
/// <param name="EmailAddress">E-Mail Adresse des Empfängers</param>
|
||||
/// <param name="Signature">Eindeutige Signatur des Empfängers</param>
|
||||
public record ReceiverQuery(int? Id = null, string? EmailAddress = null, string? Signature = null);
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
'TODO: standardize in xwiki
|
||||
Public Enum ReferenceType
|
||||
Receiver
|
||||
Receiver = 0
|
||||
Sender
|
||||
System
|
||||
Unknown
|
||||
@@ -94,13 +94,16 @@
|
||||
End Enum
|
||||
|
||||
Public Enum EmailTemplateType
|
||||
DocumentReceived
|
||||
DocumentReceived = 0
|
||||
DocumentSigned
|
||||
DocumentDeleted
|
||||
DocumentCompleted
|
||||
DocumentAccessCodeReceived
|
||||
DocumentShared
|
||||
TotpSecret
|
||||
DocumentRejected_ADM
|
||||
DocumentRejected_REC
|
||||
DocumentRejected_REC_2
|
||||
End Enum
|
||||
|
||||
Public Enum EncodeType
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
13
EnvelopeGenerator.GeneratorAPI/.config/dotnet-tools.json
Normal file
13
EnvelopeGenerator.GeneratorAPI/.config/dotnet-tools.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-ef": {
|
||||
"version": "9.0.3",
|
||||
"commands": [
|
||||
"dotnet-ef"
|
||||
],
|
||||
"rollForward": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,17 +7,27 @@ 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Controller verantwortlich für die Benutzer-Authentifizierung, einschließlich Anmelden, Abmelden und Überprüfung des Authentifizierungsstatus.
|
||||
/// </summary>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class AuthController : ControllerBase
|
||||
public partial class AuthController : ControllerBase
|
||||
{
|
||||
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;
|
||||
@@ -25,10 +35,37 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
_dirSearchService = dirSearchService;
|
||||
}
|
||||
|
||||
//TODO: When a user group is created for signFlow, add a process to check if the user is in this group (like "PM_USER")
|
||||
/// <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("login")]
|
||||
public async Task<IActionResult> Login([FromBody] LogInDto login)
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Login([FromBody] Login login, [FromQuery] bool cookie = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -48,13 +85,13 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
|
||||
// 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!),
|
||||
};
|
||||
{
|
||||
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);
|
||||
@@ -75,13 +112,58 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
|
||||
return Ok();
|
||||
}
|
||||
catch(Exception ex)
|
||||
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()
|
||||
@@ -98,8 +180,22 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet("check")]
|
||||
public IActionResult IsAuthenticated() => Ok(User.Identity?.IsAuthenticated ?? false);
|
||||
/// <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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using AutoMapper;
|
||||
using EnvelopeGenerator.Application.EmailTemplates;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Commands.Update;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Commands.Reset;
|
||||
using EnvelopeGenerator.Application.EmailTemplates.Queries.Read;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller for managing email templates.
|
||||
/// Steuerung zur Verwaltung von E-Mail-Vorlagen.
|
||||
/// </summary>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class EmailTemplateController : ControllerBase
|
||||
{
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz der <see cref="EmailTemplateController"/>-Klasse.
|
||||
/// </summary>
|
||||
/// <param name="mapper">
|
||||
/// Die AutoMapper-Instanz, die zum Zuordnen von Objekten verwendet wird.
|
||||
/// </param>
|
||||
public EmailTemplateController(IMapper mapper)
|
||||
{
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft E-Mail-Vorlagen basierend auf der angegebenen Abfrage ab.
|
||||
/// Gibt alles zurück, wenn keine Id- oder Typ-Informationen eingegeben wurden.
|
||||
/// </summary>
|
||||
/// <param name="emailTemplate">Die Abfrageparameter zum Abrufen von E-Mail-Vorlagen.</param>
|
||||
/// <returns>Gibt HTTP-Antwort zurück</returns>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
/// GET /api/EmailTemplate?emailTemplateId=123
|
||||
/// </remarks>
|
||||
/// <response code="200">Wenn die E-Mail-Vorlagen erfolgreich abgerufen werden.</response>
|
||||
/// <response code="400">Wenn die Abfrageparameter ungültig sind.</response>
|
||||
/// <response code="401">Wenn der Benutzer nicht authentifiziert ist.</response>
|
||||
/// <response code="404">Wenn die gesuchte Abfrage nicht gefunden wird.</response>
|
||||
[HttpGet]
|
||||
public IActionResult Get([FromQuery] ReadEmailTemplateQuery? emailTemplate = null)
|
||||
{
|
||||
// Implementation logic here
|
||||
return Ok(); // Placeholder for actual implementation
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an email template or resets it if no update command is provided.
|
||||
/// Aktualisiert eine E-Mail-Vorlage oder setzt sie zurück, wenn kein Aktualisierungsbefehl angegeben ist.
|
||||
/// </summary>
|
||||
/// <param name="email">Die E-Mail-Vorlagenabfrage.</param>
|
||||
/// <param name="update">Der Aktualisierungsbefehl für die E-Mail-Vorlage.
|
||||
/// Wird auf Standardwert aktualisiert, wenn die Anfrage ohne http-Body gesendet wird.
|
||||
/// </param>
|
||||
/// <returns>Gibt HTTP-Antwort zurück</returns>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
/// PUT /api/EmailTemplate
|
||||
/// {
|
||||
/// "emailTemplateId": 123,
|
||||
/// "newContent": "Updated content"
|
||||
/// }
|
||||
/// </remarks>
|
||||
/// <response code="200">Wenn die E-Mail-Vorlage erfolgreich aktualisiert oder zurückgesetzt wird.</response>
|
||||
/// <response code="400">Wenn die Abfrage ohne einen String gesendet wird.</response>
|
||||
/// <response code="401">Wenn der Benutzer nicht authentifiziert ist.</response>
|
||||
/// <response code="404">Wenn die gesuchte Abfrage nicht gefunden wird.</response>
|
||||
[HttpPut]
|
||||
public IActionResult Update([FromQuery] EmailTemplateQuery email, [FromBody] UpdateEmailTemplateCommand? update = null)
|
||||
{
|
||||
if (update is null)
|
||||
{
|
||||
var reset = _mapper.Map<ResetEnvelopeTemplateCommand>(email);
|
||||
// Logic for resetting the email template
|
||||
}
|
||||
else
|
||||
{
|
||||
update.EmailTemplateQuery = email;
|
||||
// Logic for updating the email template
|
||||
}
|
||||
|
||||
return Ok(); // Placeholder for actual implementation
|
||||
}
|
||||
}
|
||||
@@ -1,52 +1,78 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.Contracts.Services;
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries.Read;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Dieser Controller stellt Endpunkte für die Verwaltung von Umschlägen bereit.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Die API ermöglicht das Abrufen und Verwalten von Umschlägen basierend auf Benutzerinformationen und Statusfiltern.
|
||||
///
|
||||
/// Mögliche Antworten:
|
||||
/// - 200 OK: Die Anfrage war erfolgreich, und die angeforderten Daten werden zurückgegeben.
|
||||
/// - 400 Bad Request: Die Anfrage war fehlerhaft oder unvollständig.
|
||||
/// - 401 Unauthorized: Der Benutzer ist nicht authentifiziert.
|
||||
/// - 403 Forbidden: Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen.
|
||||
/// - 404 Not Found: Die angeforderte Ressource wurde nicht gefunden.
|
||||
/// - 500 Internal Server Error: Ein unerwarteter Fehler ist aufgetreten.
|
||||
/// </remarks>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class EnvelopeController : ControllerBase
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class EnvelopeController : ControllerBase
|
||||
private readonly ILogger<EnvelopeController> _logger;
|
||||
private readonly IEnvelopeService _envelopeService;
|
||||
|
||||
/// <summary>
|
||||
/// Erstellt eine neue Instanz des EnvelopeControllers.
|
||||
/// </summary>
|
||||
/// <param name="logger">Der Logger, der für das Protokollieren von Informationen verwendet wird.</param>
|
||||
/// <param name="envelopeService">Der Dienst, der für die Verarbeitung von Umschlägen zuständig ist.</param>
|
||||
public EnvelopeController(ILogger<EnvelopeController> logger, IEnvelopeService envelopeService)
|
||||
{
|
||||
private readonly ILogger<EnvelopeController> _logger;
|
||||
private readonly IEnvelopeService _envelopeService;
|
||||
_logger = logger;
|
||||
_envelopeService = envelopeService;
|
||||
}
|
||||
|
||||
public EnvelopeController(ILogger<EnvelopeController> logger, IEnvelopeService envelopeService)
|
||||
/// <summary>
|
||||
/// Ruft eine Liste von Umschlägen basierend auf dem Benutzer und den angegebenen Statusfiltern ab.
|
||||
/// </summary>
|
||||
/// <param name="envelope"></param>
|
||||
/// <returns>Eine IActionResult-Instanz, die die abgerufenen Umschläge oder einen Fehlerstatus enthält.</returns>
|
||||
/// <response code="200">Die Anfrage war erfolgreich, und die Umschläge werden zurückgegeben.</response>
|
||||
/// <response code="400">Die Anfrage war fehlerhaft oder unvollständig.</response>
|
||||
/// <response code="401">Der Benutzer ist nicht authentifiziert.</response>
|
||||
/// <response code="403">Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen.</response>
|
||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||
[Authorize]
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAsync([FromQuery] ReadEnvelopeQuery envelope)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_envelopeService = envelopeService;
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetCurrentAsync(
|
||||
[FromQuery] int? min_status = null,
|
||||
[FromQuery] int? max_status = null,
|
||||
[FromQuery] params int[] ignore_statuses)
|
||||
{
|
||||
try
|
||||
if (User.GetId() is int intId)
|
||||
return await _envelopeService.ReadByUserAsync(intId, min_status: envelope.Status, max_status: envelope.Status).ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
else
|
||||
{
|
||||
if (User.GetId() is int intId)
|
||||
return await _envelopeService.ReadByUserAsync(intId, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses).ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
else
|
||||
{
|
||||
_logger.LogError("Despite successful authorization, the 'api/envelope' route encountered an issue: the user ID is not recognized as an integer. This may be due to the removal of the ID during the creation of the claims list.");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{Message}", ex.Message);
|
||||
_logger.LogError("Trotz erfolgreicher Autorisierung wurde die Benutzer-ID nicht als Ganzzahl erkannt. Dies könnte auf eine fehlerhafte Erstellung der Anspruchsliste zurückzuführen sein.");
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{Message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,98 +1,165 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.Contracts.Services;
|
||||
using EnvelopeGenerator.Common.My.Resources;
|
||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Commands.Create;
|
||||
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries.Read;
|
||||
using EnvelopeGenerator.Application.Envelopes.Queries.ReceiverName;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller für die Verwaltung von Umschlagempfängern.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dieser Controller bietet Endpunkte für das Abrufen und Verwalten von Umschlagempfängerdaten.
|
||||
/// </remarks>
|
||||
[Route("api/[controller]")]
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class EnvelopeReceiverController : ControllerBase
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class EnvelopeReceiverController : ControllerBase
|
||||
private readonly ILogger<EnvelopeReceiverController> _logger;
|
||||
|
||||
private readonly IEnvelopeReceiverService _erService;
|
||||
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
/// <summary>
|
||||
/// Konstruktor für den EnvelopeReceiverController.
|
||||
/// </summary>
|
||||
/// <param name="logger">Logger-Instanz zur Protokollierung von Informationen und Fehlern.</param>
|
||||
/// <param name="envelopeReceiverService">Service zur Verwaltung von Umschlagempfängern.</param>
|
||||
/// <param name="mediator">Mediator-Instanz zur Verarbeitung von Befehlen und Abfragen.</param>
|
||||
public EnvelopeReceiverController(ILogger<EnvelopeReceiverController> logger, IEnvelopeReceiverService envelopeReceiverService, IMediator mediator)
|
||||
{
|
||||
private readonly ILogger<EnvelopeReceiverController> _logger;
|
||||
private readonly IEnvelopeReceiverService _erService;
|
||||
_logger = logger;
|
||||
_erService = envelopeReceiverService;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
public EnvelopeReceiverController(ILogger<EnvelopeReceiverController> logger, IEnvelopeReceiverService envelopeReceiverService)
|
||||
/// <summary>
|
||||
/// Ruft eine Liste von Umschlagempfängern basierend auf den angegebenen Abfrageparametern ab.
|
||||
/// </summary>
|
||||
/// <param name="envelopeReceiver">Die Abfrageparameter für die Filterung von Umschlagempfängern.</param>
|
||||
/// <returns>Eine HTTP-Antwort mit der Liste der gefundenen Umschlagempfänger oder einem Fehlerstatus.</returns>
|
||||
/// <remarks>
|
||||
/// Dieser Endpunkt ermöglicht es, Umschlagempfänger basierend auf dem Benutzernamen und optionalen Statusfiltern abzurufen.
|
||||
/// Wenn der Benutzername nicht ermittelt werden kann, wird ein Serverfehler zurückgegeben.
|
||||
/// </remarks>
|
||||
/// <response code="200">Die Liste der Umschlagempfänger wurde erfolgreich abgerufen.</response>
|
||||
/// <response code="401">Wenn kein autorisierter Token vorhanden ist</response>
|
||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||
[Authorize]
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetEnvelopeReceiver([FromQuery] ReadEnvelopeReceiverQuery envelopeReceiver)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_erService = envelopeReceiverService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetEnvelopeReceiver([FromQuery] int? min_status = null, [FromQuery] int? max_status = null, [FromQuery] int[]? ignore_status = null)
|
||||
{
|
||||
try
|
||||
var username = User.GetUsername();
|
||||
|
||||
if (username is null)
|
||||
{
|
||||
var username = User.GetUsername();
|
||||
|
||||
if (username is null)
|
||||
{
|
||||
_logger.LogError(@"Envelope Receiver dto cannot be sent because username claim is null. Potential authentication and authorization error. The value of other claims are [id: {id}], [username: {username}], [name: {name}], [prename: {prename}], [email: {email}].",
|
||||
User.GetId(), User.GetUsername(), User.GetName(), User.GetPrename(), User.GetEmail());
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
|
||||
ignore_status ??= Array.Empty<int>();
|
||||
|
||||
return await _erService.ReadByUsernameAsync(username: username, min_status: min_status, max_status: max_status, ignore_statuses: ignore_status).ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, msg);
|
||||
});
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An unexpected error occurred. {message}", ex.Message);
|
||||
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("receiver-name/{mail}")]
|
||||
public async Task<IActionResult> GetReceiverName([FromRoute] string mail)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _erService.ReadLastUsedReceiverNameByMail(mail).ThenAsync(
|
||||
Success: res => res is null ? Ok(string.Empty) : Ok(res),
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
if (ntc.HasFlag(Flag.NotFound))
|
||||
return NotFound();
|
||||
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{message}", ex.Message);
|
||||
_logger.LogError(@"Envelope Receiver dto cannot be sent because username claim is null. Potential authentication and authorization error. The value of other claims are [id: {id}], [username: {username}], [name: {name}], [prename: {prename}], [email: {email}].",
|
||||
User.GetId(), User.GetUsername(), User.GetName(), User.GetPrename(), User.GetEmail());
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("secret")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetSecretAsync([FromQuery] string uuid)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _erService.ReadWithSecretByUuidAsync(uuid: uuid).ThenAsync(
|
||||
return await _erService.ReadByUsernameAsync(username: username).ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError, msg);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An unexpected error occurred. {message}", ex.Message);
|
||||
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft den Namen des zuletzt verwendeten Empfängers basierend auf der angegebenen E-Mail-Adresse ab.
|
||||
/// </summary>
|
||||
/// <param name="receiverName">Die Abfrage, die die E-Mail-Adresse des Empfängers enthält.</param>
|
||||
/// <returns>Eine HTTP-Antwort mit dem Namen des Empfängers oder einem Fehlerstatus.</returns>
|
||||
/// <remarks>
|
||||
/// Dieser Endpunkt ermöglicht es, den Namen des zuletzt verwendeten Empfängers basierend auf der E-Mail-Adresse abzurufen.
|
||||
/// </remarks>
|
||||
/// <response code="200">Der Name des Empfängers wurde erfolgreich abgerufen.</response>
|
||||
/// <response code="401">Wenn kein autorisierter Token vorhanden ist</response>
|
||||
/// <response code="404">Kein Empfänger gefunden.</response>
|
||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||
[Authorize]
|
||||
[HttpGet("salute")]
|
||||
public async Task<IActionResult> GetReceiverName([FromQuery] ReadReceiverNameQuery receiverName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _erService.ReadLastUsedReceiverNameByMail(receiverName.EmailAddress).ThenAsync(
|
||||
Success: res => res is null ? Ok(string.Empty) : Ok(res),
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
if (ntc.HasFlag(Flag.NotFound))
|
||||
return NotFound();
|
||||
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Datenübertragungsobjekt mit Informationen zu Umschlägen, Empfängern und Unterschriften.
|
||||
/// </summary>
|
||||
/// <param name="createEnvelopeQuery"></param>
|
||||
/// <param name="cancellationToken">Token to cancel the operation</param>
|
||||
/// <returns>HTTP-Antwort</returns>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
///
|
||||
/// POST /api/envelope
|
||||
/// {
|
||||
/// "title": "Vertragsdokument",
|
||||
/// "message": "Bitte unterschreiben Sie dieses Dokument.",
|
||||
/// "document": {
|
||||
/// "dataAsBase64": "dGVzdC1iYXNlNjQtZGF0YQ=="
|
||||
/// },
|
||||
/// "receivers": [
|
||||
/// {
|
||||
/// "emailAddress": "example@example.com",
|
||||
/// "signatures": [
|
||||
/// {
|
||||
/// "x": 100,
|
||||
/// "y": 200,
|
||||
/// "page": 1
|
||||
/// }
|
||||
/// ],
|
||||
/// "name": "Max Mustermann",
|
||||
/// "phoneNumber": "+49123456789"
|
||||
/// }
|
||||
/// ],
|
||||
/// "tfaEnabled": false
|
||||
/// }
|
||||
///
|
||||
/// </remarks>
|
||||
/// <response code="202">Envelope-Erstellung und Sendeprozessbefehl erfolgreich</response>
|
||||
/// <response code="400">Wenn ein Fehler im HTTP-Body auftritt</response>
|
||||
/// <response code="401">Wenn kein autorisierter Token vorhanden ist</response>
|
||||
/// <response code="500">Es handelt sich um einen unerwarteten Fehler. Die Protokolle sollten überprüft werden.</response>
|
||||
[Authorize]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateAsync([FromBody] CreateEnvelopeReceiverCommand createEnvelopeQuery, CancellationToken cancellationToken)
|
||||
{
|
||||
await _mediator.Send(createEnvelopeQuery, cancellationToken);
|
||||
return Accepted();
|
||||
}
|
||||
}
|
||||
@@ -1,43 +1,40 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.Contracts.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Net.Mail;
|
||||
using System.Security.Cryptography.Xml;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EnvelopeTypeController : ControllerBase
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class EnvelopeTypeController : ControllerBase
|
||||
private readonly ILogger<EnvelopeTypeController> _logger;
|
||||
private readonly IEnvelopeTypeService _service;
|
||||
|
||||
public EnvelopeTypeController(ILogger<EnvelopeTypeController> logger, IEnvelopeTypeService service)
|
||||
{
|
||||
private readonly ILogger<EnvelopeTypeController> _logger;
|
||||
private readonly IEnvelopeTypeService _service;
|
||||
_logger = logger;
|
||||
_service = service;
|
||||
}
|
||||
|
||||
public EnvelopeTypeController(ILogger<EnvelopeTypeController> logger, IEnvelopeTypeService service)
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAllAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_service = service;
|
||||
return await _service.ReadAllAsync().ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return ntc.HasFlag(Flag.NotFound) ? NotFound() : StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAllAsync()
|
||||
catch (Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _service.ReadAllAsync().ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return ntc.HasFlag(Flag.NotFound) ? NotFound() : StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{Message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
_logger.LogError(ex, "{Message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,155 @@
|
||||
using EnvelopeGenerator.Application.Contracts.Services;
|
||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
|
||||
using EnvelopeGenerator.Application.Contracts.Services;
|
||||
using EnvelopeGenerator.Application.Histories.Queries.Read;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using static EnvelopeGenerator.Common.Constants;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Dieser Controller stellt Endpunkte für den Zugriff auf die Umschlaghistorie bereit.
|
||||
/// </summary>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class HistoryController : ControllerBase
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class HistoryController : ControllerBase
|
||||
private readonly ILogger<HistoryController> _logger;
|
||||
|
||||
private readonly IEnvelopeHistoryService _service;
|
||||
|
||||
/// <summary>
|
||||
/// Konstruktor für den HistoryController.
|
||||
/// </summary>
|
||||
/// <param name="logger">Der Logger, der für das Protokollieren von Informationen verwendet wird.</param>
|
||||
/// <param name="service">Der Dienst, der für die Verarbeitung der Umschlaghistorie verantwortlich ist.</param>
|
||||
public HistoryController(ILogger<HistoryController> logger, IEnvelopeHistoryService service)
|
||||
{
|
||||
private readonly ILogger<HistoryController> _logger;
|
||||
|
||||
private readonly IEnvelopeHistoryService _service;
|
||||
|
||||
public HistoryController(ILogger<HistoryController> logger, IEnvelopeHistoryService service)
|
||||
{
|
||||
_logger = logger;
|
||||
_service = service;
|
||||
}
|
||||
|
||||
[HttpGet("reference-type")]
|
||||
[Authorize]
|
||||
public IActionResult GetReferenceTypes()
|
||||
{
|
||||
// Enum to Key-Value pair
|
||||
var referenceTypes = Enum.GetValues(typeof(ReferenceType))
|
||||
.Cast<ReferenceType>()
|
||||
.ToDictionary(rt =>
|
||||
{
|
||||
var key = rt.ToString();
|
||||
var keyAsCamelCase = char.ToLower(key[0]) + key[1..];
|
||||
return keyAsCamelCase;
|
||||
}, rt => (int)rt);
|
||||
|
||||
return Ok(referenceTypes);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetAllAsync([FromQuery] int? envelopeId = null, [FromQuery] string? userReference = null, [FromQuery] int? referenceType = null, [FromQuery] bool withSender = false, [FromQuery] bool withReceiver = false)
|
||||
{
|
||||
ReferenceType? refTypEnum = null;
|
||||
|
||||
if (referenceType is int refTypInt)
|
||||
if (Enum.IsDefined(typeof(ReferenceType), refTypInt))
|
||||
refTypEnum = (ReferenceType)refTypInt;
|
||||
else
|
||||
throw new ArgumentException($"The provided referenceType '{referenceType}' is not valid. It must correspond to a valid value in the {nameof(ReferenceType)} enum.");
|
||||
|
||||
switch(referenceType)
|
||||
{
|
||||
case (int)ReferenceType.Receiver:
|
||||
withReceiver = true;
|
||||
break;
|
||||
case (int)ReferenceType.Sender:
|
||||
withSender = true;
|
||||
break;
|
||||
}
|
||||
|
||||
var histories = await _service.ReadAsync(
|
||||
envelopeId: envelopeId,
|
||||
userReference: userReference,
|
||||
referenceType: refTypEnum,
|
||||
withSender: withSender,
|
||||
withReceiver: withReceiver);
|
||||
|
||||
return Ok(histories);
|
||||
}
|
||||
_logger = logger;
|
||||
_service = service;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt alle möglichen Verweise auf alle möglichen Status in einem Verlaufsdatensatz zurück. (z. B. DocumentSigned bezieht sich auf Receiver.)
|
||||
/// Dies wird hinzugefügt, damit Client-Anwendungen sich selbst auf dem neuesten Stand halten können.
|
||||
/// 0 - Receiver:
|
||||
/// Historische Datensätze, die sich auf den Status des Absenders beziehen. Sie haben Statuscodes, die mit 1* beginnen.
|
||||
/// 1 - Sender:
|
||||
/// Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 2* beginnen.
|
||||
/// 2 - System:
|
||||
/// Historische Datensätze, die sich auf den allgemeinen Zustand des Umschlags beziehen. Diese haben Statuscodes, die mit 3* beginnen.
|
||||
/// 3 - Unknown:
|
||||
/// Ein unbekannter Datensatz weist auf einen möglichen Mangel oder eine Unstimmigkeit im Aktualisierungsprozess der Anwendung hin.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <response code="200"></response>
|
||||
[HttpGet("related")]
|
||||
[Authorize]
|
||||
public IActionResult GetReferenceTypes()
|
||||
{
|
||||
// Enum zu Schlüssel-Wert-Paar
|
||||
var referenceTypes = Enum.GetValues(typeof(ReferenceType))
|
||||
.Cast<ReferenceType>()
|
||||
.ToDictionary(rt =>
|
||||
{
|
||||
var key = rt.ToString();
|
||||
var keyAsCamelCase = char.ToLower(key[0]) + key[1..];
|
||||
return keyAsCamelCase;
|
||||
}, rt => (int)rt);
|
||||
|
||||
return Ok(referenceTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gibt alle möglichen Status in einem Verlaufsdatensatz zurück.
|
||||
/// Dies wird hinzugefügt, damit Client-Anwendungen sich selbst auf dem neuesten Stand halten können.
|
||||
/// 0: Invalid
|
||||
/// 1001: EnvelopeCreated
|
||||
/// 1002: EnvelopeSaved
|
||||
/// 1003: EnvelopeQueued
|
||||
/// 1004: EnvelopeSent (Nicht verwendet)
|
||||
/// 1005: EnvelopePartlySigned
|
||||
/// 1006: EnvelopeCompletelySigned
|
||||
/// 1007: EnvelopeReportCreated
|
||||
/// 1008: EnvelopeArchived
|
||||
/// 1009: EnvelopeDeleted
|
||||
/// 2001: AccessCodeRequested
|
||||
/// 2002: AccessCodeCorrect
|
||||
/// 2003: AccessCodeIncorrect
|
||||
/// 2004: DocumentOpened
|
||||
/// 2005: DocumentSigned
|
||||
/// 4001: DocumentForwarded
|
||||
/// 2006: SignatureConfirmed
|
||||
/// 2007: DocumentRejected
|
||||
/// 2008: EnvelopeShared
|
||||
/// 2009: EnvelopeViewed
|
||||
/// 3001: MessageInvitationSent (Wird von Trigger verwendet)
|
||||
/// 3002: MessageAccessCodeSent
|
||||
/// 3003: MessageConfirmationSent
|
||||
/// 3004: MessageDeletionSent
|
||||
/// 3005: MessageCompletionSent
|
||||
/// </summary>
|
||||
/// <param name="related">
|
||||
/// Abfrageparameter, der angibt, auf welche Referenz sich der Status bezieht.
|
||||
/// 0 - Sender: Historische Datensätze, die sich auf den Status des Absenders beziehen. Sie haben Statuscodes, die mit 1* beginnen.
|
||||
/// 1 - Receiver: Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 2* beginnen.
|
||||
/// 2 - System: Diese werden durch Datenbank-Trigger aktualisiert und sind in den Tabellen EnvelopeHistory und EmailOut zu finden.Sie arbeiten
|
||||
/// integriert mit der Anwendung EmailProfiler, um E-Mails zu versenden und haben die Codes, die mit 3* beginnen.
|
||||
/// </param>
|
||||
/// <returns>Gibt die HTTP-Antwort zurück.</returns>
|
||||
/// <response code="200"></response>
|
||||
[HttpGet("status")]
|
||||
[Authorize]
|
||||
public IActionResult GetEnvelopeStatus([FromQuery] ReferenceType? related = null)
|
||||
{
|
||||
// Enum zu Schlüssel-Wert-Paar
|
||||
var referenceTypes = Enum.GetValues(typeof(EnvelopeStatus))
|
||||
.Cast<EnvelopeStatus>()
|
||||
.ToDictionary(rt =>
|
||||
{
|
||||
var key = rt.ToString();
|
||||
var keyAsCamelCase = char.ToLower(key[0]) + key[1..];
|
||||
return keyAsCamelCase;
|
||||
}, rt => (int)rt);
|
||||
|
||||
return Ok(referenceTypes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft die gesamte Umschlaghistorie basierend auf den angegebenen Abfrageparametern ab.
|
||||
/// </summary>
|
||||
/// <param name="history">Die Abfrageparameter, die die Filterkriterien für die Umschlaghistorie definieren.</param>
|
||||
/// <returns>Eine Liste von Historieneinträgen, die den angegebenen Kriterien entsprechen, oder nur der letzte Eintrag.</returns>
|
||||
/// <response code="200">Die Anfrage war erfolgreich, und die Umschlaghistorie wird zurückgegeben.</response>
|
||||
/// <response code="400">Die Anfrage war ungültig oder unvollständig.</response>
|
||||
/// <response code="401">Der Benutzer ist nicht authentifiziert.</response>
|
||||
/// <response code="403">Der Benutzer hat keine Berechtigung, auf die Ressource zuzugreifen.</response>
|
||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> GetAllAsync([FromQuery] ReadHistoryQuery history)
|
||||
{
|
||||
bool withReceiver = false;
|
||||
bool withSender = false;
|
||||
|
||||
switch (history.Related)
|
||||
{
|
||||
case ReferenceType.Receiver:
|
||||
withReceiver = true;
|
||||
break;
|
||||
case ReferenceType.Sender:
|
||||
withSender = true;
|
||||
break;
|
||||
}
|
||||
|
||||
var histories = await _service.ReadAsync(
|
||||
envelopeId: history.EnvelopeId,
|
||||
referenceType: history.Related,
|
||||
withSender: withSender,
|
||||
withReceiver: withReceiver);
|
||||
|
||||
return Ok(histories);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,85 +6,115 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller für die Verwaltung der Lokalisierung und Spracheinstellungen.
|
||||
/// </summary>
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class LocalizationController : ControllerBase
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class LocalizationController : ControllerBase
|
||||
private static readonly Guid L_KEY = Guid.NewGuid();
|
||||
|
||||
private readonly ILogger<LocalizationController> _logger;
|
||||
private readonly IStringLocalizer<Model> _mLocalizer;
|
||||
private readonly IStringLocalizer<Resource> _localizer;
|
||||
private readonly IMemoryCache _cache;
|
||||
|
||||
/// <summary>
|
||||
/// Konstruktor für den <see cref="LocalizationController"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">Logger für die Protokollierung.</param>
|
||||
/// <param name="localizer">Lokalisierungsdienst für Ressourcen.</param>
|
||||
/// <param name="memoryCache">Speicher-Cache für die Zwischenspeicherung von Daten.</param>
|
||||
/// <param name="_modelLocalizer">Lokalisierungsdienst für Modelle.</param>
|
||||
public LocalizationController(
|
||||
ILogger<LocalizationController> logger,
|
||||
IStringLocalizer<Resource> localizer,
|
||||
IMemoryCache memoryCache,
|
||||
IStringLocalizer<Model> _modelLocalizer)
|
||||
{
|
||||
private static readonly Guid L_KEY = Guid.NewGuid();
|
||||
_logger = logger;
|
||||
_localizer = localizer;
|
||||
_cache = memoryCache;
|
||||
_mLocalizer = _modelLocalizer;
|
||||
}
|
||||
|
||||
private readonly ILogger<LocalizationController> _logger;
|
||||
private readonly IStringLocalizer<Model> _mLocalizer;
|
||||
private readonly IStringLocalizer<Resource> _localizer;
|
||||
private readonly IMemoryCache _cache;
|
||||
/// <summary>
|
||||
/// Ruft alle lokalisierten Daten ab.
|
||||
/// </summary>
|
||||
/// <returns>Eine Liste aller lokalisierten Daten.</returns>
|
||||
[HttpGet]
|
||||
public IActionResult GetAll() => Ok(_cache.GetOrCreate(Language ?? string.Empty + L_KEY, _ => _mLocalizer.ToDictionary()));
|
||||
|
||||
public LocalizationController(
|
||||
ILogger<LocalizationController> logger,
|
||||
IStringLocalizer<Resource> localizer,
|
||||
IMemoryCache memoryCache,
|
||||
IStringLocalizer<Model> _modelLocalizer)
|
||||
/// <summary>
|
||||
/// Ruft die aktuelle Sprache ab.
|
||||
/// </summary>
|
||||
/// <returns>Die aktuelle Sprache oder ein NotFound-Ergebnis, wenn keine Sprache gesetzt ist.</returns>
|
||||
[HttpGet("lang")]
|
||||
public IActionResult GetLanguage() => Language is null ? NotFound() : Ok(Language);
|
||||
|
||||
/// <summary>
|
||||
/// Setzt die Sprache.
|
||||
/// </summary>
|
||||
/// <param name="language">Die zu setzende Sprache.</param>
|
||||
/// <returns>Ein Ok-Ergebnis, wenn die Sprache erfolgreich gesetzt wurde, oder ein BadRequest-Ergebnis, wenn die Eingabe ungültig ist.</returns>
|
||||
[HttpPost("lang")]
|
||||
public IActionResult SetLanguage([FromQuery] string language)
|
||||
{
|
||||
if (string.IsNullOrEmpty(language))
|
||||
return BadRequest();
|
||||
|
||||
Language = language;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Löscht die aktuelle Sprache.
|
||||
/// </summary>
|
||||
/// <returns>Ein Ok-Ergebnis, wenn die Sprache erfolgreich gelöscht wurde.</returns>
|
||||
[HttpDelete("lang")]
|
||||
public IActionResult DeleteLanguage()
|
||||
{
|
||||
Language = null;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Eigenschaft für die Verwaltung der aktuellen Sprache über Cookies.
|
||||
/// </summary>
|
||||
private string? Language
|
||||
{
|
||||
get
|
||||
{
|
||||
_logger = logger;
|
||||
_localizer = localizer;
|
||||
_cache = memoryCache;
|
||||
_mLocalizer = _modelLocalizer;
|
||||
var cookieValue = Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
|
||||
|
||||
if (string.IsNullOrEmpty(cookieValue))
|
||||
return null;
|
||||
|
||||
var culture = CookieRequestCultureProvider.ParseCookieValue(cookieValue)?.Cultures[0];
|
||||
return culture?.Value ?? null;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult GetAll() => Ok(_cache.GetOrCreate(Language ?? string.Empty + L_KEY, _ => _mLocalizer.ToDictionary()));
|
||||
|
||||
[HttpGet("lang")]
|
||||
public IActionResult GetLanguage() => Language is null ? NotFound() : Ok(Language);
|
||||
|
||||
[HttpPost("lang")]
|
||||
public IActionResult SetLanguage([FromQuery] string language)
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(language))
|
||||
return BadRequest();
|
||||
|
||||
Language = language;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpDelete("lang")]
|
||||
public IActionResult DeleteLanguage()
|
||||
{
|
||||
Language = null;
|
||||
return Ok();
|
||||
}
|
||||
|
||||
private string? Language
|
||||
{
|
||||
get
|
||||
if (value is null)
|
||||
Response.Cookies.Delete(CookieRequestCultureProvider.DefaultCookieName);
|
||||
else
|
||||
{
|
||||
var cookieValue = Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
|
||||
|
||||
if (string.IsNullOrEmpty(cookieValue))
|
||||
return null;
|
||||
|
||||
var culture = CookieRequestCultureProvider.ParseCookieValue(cookieValue)?.Cultures[0];
|
||||
return culture?.Value ?? null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value is null)
|
||||
Response.Cookies.Delete(CookieRequestCultureProvider.DefaultCookieName);
|
||||
else
|
||||
var cookieOptions = new CookieOptions()
|
||||
{
|
||||
var cookieOptions = new CookieOptions()
|
||||
{
|
||||
Expires = DateTimeOffset.UtcNow.AddYears(1),
|
||||
Secure = false,
|
||||
SameSite = SameSiteMode.Strict,
|
||||
HttpOnly = true
|
||||
};
|
||||
Expires = DateTimeOffset.UtcNow.AddYears(1),
|
||||
Secure = false,
|
||||
SameSite = SameSiteMode.Strict,
|
||||
HttpOnly = true
|
||||
};
|
||||
|
||||
Response.Cookies.Append(
|
||||
CookieRequestCultureProvider.DefaultCookieName,
|
||||
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(value)),
|
||||
cookieOptions);
|
||||
}
|
||||
Response.Cookies.Append(
|
||||
CookieRequestCultureProvider.DefaultCookieName,
|
||||
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(value)),
|
||||
cookieOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,88 +2,97 @@
|
||||
using DigitalData.Core.DTO;
|
||||
using EnvelopeGenerator.Application.Contracts.Services;
|
||||
using EnvelopeGenerator.Application.DTOs.Receiver;
|
||||
using EnvelopeGenerator.Application.Receivers.Queries.Read;
|
||||
using EnvelopeGenerator.Domain.Entities;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller für die Verwaltung von Empfängern.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Dieser Controller bietet Endpunkte für CRUD-Operationen (Erstellen, Lesen, Aktualisieren, Löschen)
|
||||
/// sowie zusätzliche Funktionen wie das Abrufen von Empfängern basierend auf E-Mail-Adresse oder Signatur.
|
||||
/// </remarks>
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ReceiverController : CRUDControllerBaseWithErrorHandling<IReceiverService, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ReceiverController : CRUDControllerBaseWithErrorHandling<IReceiverService, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
|
||||
/// <summary>
|
||||
/// Initialisiert eine neue Instanz des <see cref="ReceiverController"/>-Controllers.
|
||||
/// </summary>
|
||||
/// <param name="logger">Der Logger für die Protokollierung.</param>
|
||||
/// <param name="service">Der Dienst für Empfängeroperationen.</param>
|
||||
public ReceiverController(ILogger<ReceiverController> logger, IReceiverService service) : base(logger, service)
|
||||
{
|
||||
public ReceiverController(ILogger<ReceiverController> logger, IReceiverService service) : base(logger, service)
|
||||
{
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Get([FromQuery] string? emailAddress = null, [FromQuery] string? signature = null)
|
||||
{
|
||||
if (emailAddress is null && signature is null)
|
||||
return await base.GetAll();
|
||||
|
||||
try
|
||||
{
|
||||
return await _service.ReadByAsync(emailAddress: emailAddress, signature: signature).ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{Message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async override Task<IActionResult> Create(ReceiverCreateDto createDto)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(ModelState);
|
||||
|
||||
return await base.Create(createDto);
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
public async Task<IActionResult> Delete([FromQuery] int? id = null, [FromQuery]string? emailAddress = null, [FromQuery] string? signature = null)
|
||||
{
|
||||
if(id is int id_int)
|
||||
return await base.Delete(id_int);
|
||||
|
||||
try
|
||||
{
|
||||
if (emailAddress is not null || signature is not null)
|
||||
return await _service.DeleteByAsync(emailAddress: emailAddress, signature: signature).ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{Message}", ex.Message);
|
||||
return StatusCode(500);
|
||||
}
|
||||
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
#region REMOVED ENDPOINTS
|
||||
[NonAction]
|
||||
public override Task<IActionResult> GetAll() => base.GetAll();
|
||||
|
||||
[NonAction]
|
||||
public override Task<IActionResult> Delete([FromRoute] int id) => base.Delete(id);
|
||||
|
||||
[NonAction]
|
||||
public override Task<IActionResult> Update(ReceiverUpdateDto updateDto) => base.Update(updateDto);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ruft eine Liste von Empfängern ab, basierend auf den angegebenen Abfrageparametern.
|
||||
/// </summary>
|
||||
/// <param name="receiver">Die Abfrageparameter, einschließlich E-Mail-Adresse und Signatur.</param>
|
||||
/// <returns>Eine Liste von Empfängern oder ein Fehlerstatus.</returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Get([FromQuery] ReadReceiverQuery receiver)
|
||||
{
|
||||
if (receiver.EmailAddress is null && receiver.Signature is null)
|
||||
return await base.GetAll();
|
||||
|
||||
try
|
||||
{
|
||||
return await _service.ReadByAsync(emailAddress: receiver.EmailAddress, signature: receiver.Signature).ThenAsync(
|
||||
Success: Ok,
|
||||
Fail: IActionResult (msg, ntc) =>
|
||||
{
|
||||
_logger.LogNotice(ntc);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "{Message}", ex.Message);
|
||||
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||
}
|
||||
}
|
||||
|
||||
#region REMOVED ENDPOINTS
|
||||
/// <summary>
|
||||
/// Diese Methode ist deaktiviert und wird nicht verwendet.
|
||||
/// </summary>
|
||||
[NonAction]
|
||||
public override Task<IActionResult> GetAll() => base.GetAll();
|
||||
|
||||
/// <summary>
|
||||
/// Diese Methode ist deaktiviert und wird nicht verwendet.
|
||||
/// </summary>
|
||||
[NonAction]
|
||||
public override Task<IActionResult> Delete([FromRoute] int id) => base.Delete(id);
|
||||
|
||||
/// <summary>
|
||||
/// Diese Methode ist deaktiviert und wird nicht verwendet.
|
||||
/// </summary>
|
||||
[NonAction]
|
||||
public override Task<IActionResult> Update(ReceiverUpdateDto updateDto) => base.Update(updateDto);
|
||||
|
||||
/// <summary>
|
||||
/// Diese Methode ist deaktiviert und wird nicht verwendet.
|
||||
/// </summary>
|
||||
[NonAction]
|
||||
public override Task<IActionResult> Create(ReceiverCreateDto createDto)
|
||||
{
|
||||
return base.Create(createDto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Diese Methode ist deaktiviert und wird nicht verwendet.
|
||||
/// </summary>
|
||||
[NonAction]
|
||||
public override Task<IActionResult> GetById([FromRoute] int id)
|
||||
{
|
||||
return base.GetById(id);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,16 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFrameworks>net9.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageId>EnvelopeGenerator.GeneratorAPI</PackageId>
|
||||
<Title></Title>
|
||||
<Authors>Digital Data GmbH</Authors>
|
||||
<Company>Digital Data GmbH</Company>
|
||||
<Product>EnvelopeGenerator.GeneratorAPI</Product>
|
||||
<Version>1.1.0</Version>
|
||||
<FileVersion>1.1.0</FileVersion>
|
||||
<AssemblyVersion>1.1.0</AssemblyVersion>
|
||||
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
|
||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AspNetCore.Scalar" Version="1.1.8" />
|
||||
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.2.1" />
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.15" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.3" />
|
||||
<PackageReference Include="Scalar.AspNetCore" Version="2.1.4" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
|
||||
<PackageReference Include="System.DirectoryServices" Version="7.0.1" />
|
||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="7.0.1" />
|
||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="7.0.1" />
|
||||
|
||||
13
EnvelopeGenerator.GeneratorAPI/Models/Login.cs
Normal file
13
EnvelopeGenerator.GeneratorAPI/Models/Login.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace EnvelopeGenerator.GeneratorAPI.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Repräsentiert ein Login-Modell mit erforderlichem Passwort und optionaler ID und Benutzername.
|
||||
/// </summary>
|
||||
/// <param name="Password">Das erforderliche Passwort für das Login.</param>
|
||||
/// <param name="Id">Die optionale ID des Benutzers.</param>
|
||||
/// <param name="Username">Der optionale Benutzername.</param>
|
||||
public record Login([Required] string Password, int? Id = null, string? Username = null)
|
||||
{
|
||||
}
|
||||
@@ -7,6 +7,9 @@ using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Globalization;
|
||||
using Scalar.AspNetCore;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using System.Reflection;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -31,8 +34,53 @@ builder.Services.AddCors(options =>
|
||||
|
||||
// Swagger
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
options.SwaggerDoc("v1", new OpenApiInfo
|
||||
{
|
||||
Version = "v1",
|
||||
Title = "signFLOW Absender-API",
|
||||
Description = "Eine API zur Verwaltung der Erstellung, des Versands und der Nachverfolgung von Umschlägen in der signFLOW-Anwendung.",
|
||||
Contact = new OpenApiContact
|
||||
{
|
||||
Name = "Digital Data GmbH",
|
||||
Url = new Uri("https://digitaldata.works/digitale-signatur#kontakt"),
|
||||
Email = "info-flow@digitaldata.works"
|
||||
},
|
||||
});
|
||||
|
||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||
{
|
||||
Name = "Authorization",
|
||||
Type = SecuritySchemeType.Http,
|
||||
Scheme = "Bearer",
|
||||
BearerFormat = "JWT",
|
||||
In = ParameterLocation.Header,
|
||||
Description = "JWT-Autorisierungs-Header unter Verwendung des Bearer-Schemas.",
|
||||
});
|
||||
|
||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
new string[] {}
|
||||
}
|
||||
});
|
||||
|
||||
var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
|
||||
foreach (var xmlFile in xmlFiles)
|
||||
{
|
||||
options.IncludeXmlComments(xmlFile);
|
||||
}
|
||||
});
|
||||
builder.Services.AddOpenApi();
|
||||
// DbContext
|
||||
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));
|
||||
@@ -60,15 +108,20 @@ builder.Services.AddDirectorySearchService();
|
||||
builder.Services.AddCookieBasedLocalizer() ;
|
||||
|
||||
// Envelope generator serives
|
||||
builder.Services.AddEnvelopeGenerator(config);
|
||||
builder.Services
|
||||
.AddEnvelopeGeneratorRepositories()
|
||||
.AddEnvelopeGeneratorServices(config);
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapOpenApi();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
if (app.Environment.IsDevelopment() || (app.IsDevOrDiP() && config.GetValue<bool>("UseSwagger")))
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
app.MapScalarApiReference();
|
||||
}
|
||||
|
||||
// Set CORS policy
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
{
|
||||
"UseSwagger": true,
|
||||
"DiPMode": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFrameworks>net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
Reference in New Issue
Block a user