Compare commits
20 Commits
ea6d80918c
...
feat/signF
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
456c591fae | ||
|
|
41b2841c25 | ||
|
|
6a6da4a876 | ||
|
|
af280ee64e | ||
|
|
9b945ce232 | ||
|
|
8b1199bc71 | ||
|
|
1d74b7ca06 | ||
|
|
c1bce7c639 | ||
|
|
4401a70217 | ||
|
|
fd53f5bfd6 | ||
|
|
6126fce24d | ||
|
|
ce41090979 | ||
|
|
3fa113003c | ||
|
|
5504093591 | ||
|
|
040cf8641d | ||
|
|
09df86000b | ||
|
|
406ddfb226 | ||
|
|
b01f13fb5f | ||
|
|
00fedc7c4c | ||
|
|
171de98552 |
@@ -21,5 +21,5 @@ public interface IEnvelopeReceiverRepository : ICRUDRepository<EnvelopeReceiver,
|
|||||||
|
|
||||||
Task<IEnumerable<EnvelopeReceiver>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
|
Task<IEnumerable<EnvelopeReceiver>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
|
||||||
|
|
||||||
Task<EnvelopeReceiver?> ReadLastByReceiver(string email);
|
Task<EnvelopeReceiver?> ReadLastByReceiverAsync(string? email = null, int? id = null, string? signature = null);
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDt
|
|||||||
|
|
||||||
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, EnvelopeQuery? envelopeQuery = null, ReadReceiverQuery? receiverQuery = null, params int[] ignore_statuses);
|
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, EnvelopeQuery? envelopeQuery = null, ReadReceiverQuery? receiverQuery = null, params int[] ignore_statuses);
|
||||||
|
|
||||||
Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail);
|
Task<DataResult<string?>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null);
|
||||||
|
|
||||||
Task<DataResult<SmsResponse>> SendSmsAsync(string envelopeReceiverId, string message);
|
Task<DataResult<SmsResponse>> SendSmsAsync(string envelopeReceiverId, string message);
|
||||||
Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadWithSecretByUuidAsync(string uuid);
|
Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadWithSecretByUuidAsync(string uuid);
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ namespace EnvelopeGenerator.Application.DTOs
|
|||||||
|
|
||||||
[TemplatePlaceholder("[MESSAGE]")]
|
[TemplatePlaceholder("[MESSAGE]")]
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public DateTime? ExpiresWhen { get; set; }
|
|
||||||
public DateTime? ExpiresWarningWhen { get; set; }
|
|
||||||
public DateTime AddedWhen { get; set; }
|
public DateTime AddedWhen { get; set; }
|
||||||
|
|
||||||
public DateTime? ChangedWhen { get; set; }
|
public DateTime? ChangedWhen { get; set; }
|
||||||
|
|
||||||
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
|
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
|
||||||
@@ -33,40 +33,22 @@ namespace EnvelopeGenerator.Application.DTOs
|
|||||||
|
|
||||||
public string Language { get; set; }
|
public string Language { get; set; }
|
||||||
|
|
||||||
public bool? SendReminderEmails { get; set; }
|
|
||||||
|
|
||||||
public int? FirstReminderDays { get; set; }
|
|
||||||
|
|
||||||
public int? ReminderIntervalDays { get; set; }
|
|
||||||
|
|
||||||
public int? EnvelopeTypeId { get; set; }
|
public int? EnvelopeTypeId { get; set; }
|
||||||
|
|
||||||
public int? CertificationType { get; set; }
|
public int? CertificationType { get; set; }
|
||||||
|
|
||||||
public bool? UseAccessCode { get; set; }
|
public bool? UseAccessCode { get; set; }
|
||||||
|
|
||||||
public int? FinalEmailToCreator { get; set; }
|
|
||||||
|
|
||||||
public int? FinalEmailToReceivers { get; set; }
|
|
||||||
|
|
||||||
public int? ExpiresWhenDays { get; set; }
|
|
||||||
|
|
||||||
public int? ExpiresWarningWhenDays { get; set; }
|
|
||||||
|
|
||||||
public bool TFAEnabled { get; init; }
|
public bool TFAEnabled { get; init; }
|
||||||
|
|
||||||
public bool DmzMoved { get; set; }
|
|
||||||
public UserReadDto? User { get; set; }
|
public UserReadDto? User { get; set; }
|
||||||
|
|
||||||
public EnvelopeType? EnvelopeType { get; set; }
|
public EnvelopeType? EnvelopeType { get; set; }
|
||||||
|
|
||||||
public string? EnvelopeTypeTitle { get; set; }
|
public string? EnvelopeTypeTitle { get; set; }
|
||||||
|
|
||||||
public bool IsAlreadySent { get; set; }
|
public bool IsAlreadySent { get; set; }
|
||||||
|
|
||||||
public string? StatusTranslated { get; set; }
|
|
||||||
|
|
||||||
public string? ContractTypeTranslated { get; set; }
|
|
||||||
|
|
||||||
public byte[]? DocResult { get; init; }
|
public byte[]? DocResult { get; init; }
|
||||||
|
|
||||||
public IEnumerable<EnvelopeDocumentDto>? Documents { get; set; }
|
public IEnumerable<EnvelopeDocumentDto>? Documents { get; set; }
|
||||||
|
|||||||
@@ -5,19 +5,32 @@ using EnvelopeGenerator.Application.DTOs.Receiver;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using static EnvelopeGenerator.Common.Constants;
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
|
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
|
||||||
{
|
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
/// <summary>
|
||||||
public record EnvelopeHistoryDto(
|
///
|
||||||
long Id,
|
/// </summary>
|
||||||
int EnvelopeId,
|
/// <param name="Id"></param>
|
||||||
string UserReference,
|
/// <param name="EnvelopeId"></param>
|
||||||
int Status,
|
/// <param name="UserReference"></param>
|
||||||
string? StatusName,
|
/// <param name="Status"></param>
|
||||||
DateTime AddedWhen,
|
/// <param name="StatusName"></param>
|
||||||
DateTime? ActionDate,
|
/// <param name="AddedWhen"></param>
|
||||||
UserCreateDto? Sender,
|
/// <param name="ActionDate"></param>
|
||||||
ReceiverReadDto? Receiver,
|
/// <param name="Sender"></param>
|
||||||
ReferenceType ReferenceType,
|
/// <param name="Receiver"></param>
|
||||||
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
|
/// <param name="ReferenceType"></param>
|
||||||
}
|
/// <param name="Comment"></param>
|
||||||
|
[ApiExplorerSettings(IgnoreApi = true)]
|
||||||
|
public record EnvelopeHistoryDto(
|
||||||
|
long Id,
|
||||||
|
int EnvelopeId,
|
||||||
|
string UserReference,
|
||||||
|
int Status,
|
||||||
|
string? StatusName,
|
||||||
|
DateTime AddedWhen,
|
||||||
|
DateTime? ActionDate,
|
||||||
|
UserCreateDto? Sender,
|
||||||
|
ReceiverReadDto? Receiver,
|
||||||
|
ReferenceType ReferenceType,
|
||||||
|
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />
|
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="3.0.0" />
|
||||||
<PackageReference Include="MediatR" Version="12.5.0" />
|
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
|
||||||
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.1" />
|
||||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.4" />
|
||||||
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
<PackageReference Include="Otp.NET" Version="1.4.0" />
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
|
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
|
||||||
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
|
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class ReadHistoryMappingProfile: Profile
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public ReadHistoryMappingProfile()
|
||||||
|
{
|
||||||
|
CreateMap<EnvelopeHistory, ReadHistoryResponse>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using EnvelopeGenerator.Application.Envelopes.Queries.Read;
|
using EnvelopeGenerator.Common;
|
||||||
using EnvelopeGenerator.Application.Receivers.Queries.Read;
|
using MediatR;
|
||||||
using EnvelopeGenerator.Common;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
|
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
|
||||||
|
|
||||||
@@ -9,9 +9,12 @@ namespace EnvelopeGenerator.Application.Histories.Queries.Read;
|
|||||||
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="EnvelopeId">Die eindeutige Kennung des Umschlags.</param>
|
/// <param name="EnvelopeId">Die eindeutige Kennung des Umschlags.</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="Status">Der Status des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.</param>
|
||||||
/// <param name="OnlyLast">Abfrage zur Steuerung, ob nur der aktuelle Status oder der gesamte Datensatz zurückgegeben wird.</param>
|
/// <param name="OnlyLast">Abfrage zur Steuerung, ob nur der aktuelle Status oder der gesamte Datensatz zurückgegeben wird.</param>
|
||||||
public record ReadHistoryQuery(
|
public record ReadHistoryQuery(
|
||||||
int? EnvelopeId = null,
|
[Required]
|
||||||
Constants.ReferenceType? Related = null,
|
int EnvelopeId,
|
||||||
bool? OnlyLast = true);
|
Constants.EnvelopeStatus? Status = null,
|
||||||
|
bool? OnlyLast = true) : IRequest<IEnumerable<ReadHistoryResponse>>
|
||||||
|
{
|
||||||
|
};
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using AutoMapper;
|
||||||
|
using EnvelopeGenerator.Application.Contracts.Repositories;
|
||||||
|
using EnvelopeGenerator.Application.Exceptions;
|
||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<ReadHistoryResponse>>
|
||||||
|
{
|
||||||
|
private readonly IEnvelopeHistoryRepository _repository;
|
||||||
|
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="repository"></param>
|
||||||
|
/// <param name="mapper"></param>
|
||||||
|
public ReadHistoryQueryHandler(IEnvelopeHistoryRepository repository, IMapper mapper)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
_mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="NotFoundException"></exception>
|
||||||
|
public async Task<IEnumerable<ReadHistoryResponse>> Handle(ReadHistoryQuery request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var hists = await _repository.ReadAsync(request.EnvelopeId, status: request.Status is null ? null : (int) request.Status);
|
||||||
|
|
||||||
|
if (!hists.Any())
|
||||||
|
throw new NotFoundException();
|
||||||
|
|
||||||
|
return _mapper.Map<IEnumerable<ReadHistoryResponse>>(hists);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using EnvelopeGenerator.Common;
|
||||||
|
|
||||||
|
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the history of an envelope, including its status, user actions, and references.
|
||||||
|
/// </summary>
|
||||||
|
public class ReadHistoryResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the unique identifier of the envelope history record.
|
||||||
|
/// </summary>
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the identifier of the associated envelope.
|
||||||
|
/// </summary>
|
||||||
|
public int EnvelopeId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the reference identifier of the user who performed the action.
|
||||||
|
/// </summary>
|
||||||
|
public string UserReference { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the status code of the envelope.
|
||||||
|
/// </summary>
|
||||||
|
public int Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public Common.Constants.ReferenceType ReferenceType => Status.ToString().FirstOrDefault() switch
|
||||||
|
{
|
||||||
|
'1' => Constants.ReferenceType.Sender,
|
||||||
|
'2' => Constants.ReferenceType.Receiver,
|
||||||
|
_ => Constants.ReferenceType.System,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the date and time when the record was added.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime AddedWhen { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the date and time when the action occurred.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? ActionDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the optional comment about the envelope history record.
|
||||||
|
/// </summary>
|
||||||
|
public string? Comment { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Id.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using Dapper;
|
using Dapper;
|
||||||
using EnvelopeGenerator.Application.Contracts.SQLExecutor;
|
using EnvelopeGenerator.Application.Contracts.SQLExecutor;
|
||||||
|
using EnvelopeGenerator.Application.Exceptions;
|
||||||
using EnvelopeGenerator.Domain.Entities;
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Application.SQL;
|
namespace EnvelopeGenerator.Application.SQL;
|
||||||
@@ -34,9 +35,16 @@ public class DocumentCreateReadSQL : ISQL<EnvelopeDocument>
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static DynamicParameters CreateParmas(string base64)
|
public static DynamicParameters CreateParmas(string base64)
|
||||||
{
|
{
|
||||||
var parameters = new DynamicParameters();
|
try
|
||||||
byte[] byteData = Convert.FromBase64String(base64);
|
{
|
||||||
parameters.Add("ByteData", byteData, System.Data.DbType.Binary);
|
var parameters = new DynamicParameters();
|
||||||
return parameters;
|
byte[] byteData = Convert.FromBase64String(base64);
|
||||||
|
parameters.Add("ByteData", byteData, System.Data.DbType.Binary);
|
||||||
|
return parameters;
|
||||||
|
}
|
||||||
|
catch(FormatException ex)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(ex.Message.Replace("input", "dataAsBase64"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace EnvelopeGenerator.Application.Services
|
|||||||
{
|
{
|
||||||
if (readOnlyDto?.Envelope is not null && readOnlyDto.Receiver is not null)
|
if (readOnlyDto?.Envelope is not null && readOnlyDto.Receiver is not null)
|
||||||
{
|
{
|
||||||
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMail(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
|
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMailAsync(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
|
||||||
var erReadOnlyId = (readOnlyDto.Id).EncodeEnvelopeReceiverId();
|
var erReadOnlyId = (readOnlyDto.Id).EncodeEnvelopeReceiverId();
|
||||||
var sigHost = await _configService.ReadDefaultSignatureHost();
|
var sigHost = await _configService.ReadDefaultSignatureHost();
|
||||||
var linkToDoc = $"{sigHost}/EnvelopeKey/{erReadOnlyId}";
|
var linkToDoc = $"{sigHost}/EnvelopeKey/{erReadOnlyId}";
|
||||||
|
|||||||
@@ -162,9 +162,9 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
|
|||||||
return Result.Success(dto_list);
|
return Result.Success(dto_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail)
|
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null)
|
||||||
{
|
{
|
||||||
var er = await _repository.ReadLastByReceiver(mail);
|
var er = await _repository.ReadLastByReceiverAsync(mail, id, signature);
|
||||||
return er is null ? Result.Fail<string?>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
|
return er is null ? Result.Fail<string?>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
AccessCodeIncorrect = 2003
|
AccessCodeIncorrect = 2003
|
||||||
DocumentOpened = 2004
|
DocumentOpened = 2004
|
||||||
DocumentSigned = 2005
|
DocumentSigned = 2005
|
||||||
DocumentForwarded = 4001
|
DocumentForwarded = 2006
|
||||||
DocumentRejected = 2007
|
DocumentRejected = 2007
|
||||||
EnvelopeShared = 2008
|
EnvelopeShared = 2008
|
||||||
EnvelopeViewed = 2009
|
EnvelopeViewed = 2009
|
||||||
@@ -48,8 +48,8 @@
|
|||||||
|
|
||||||
'TODO: standardize in xwiki
|
'TODO: standardize in xwiki
|
||||||
Public Enum ReferenceType
|
Public Enum ReferenceType
|
||||||
Receiver = 0
|
Sender = 1
|
||||||
Sender
|
Receiver
|
||||||
System
|
System
|
||||||
Unknown
|
Unknown
|
||||||
End Enum
|
End Enum
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
using DigitalData.UserManager.Domain.Entities;
|
using DigitalData.UserManager.Domain.Entities;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using static EnvelopeGenerator.Common.Constants;
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Domain.Entities
|
namespace EnvelopeGenerator.Domain.Entities
|
||||||
{
|
{
|
||||||
@@ -42,19 +41,5 @@ namespace EnvelopeGenerator.Domain.Entities
|
|||||||
|
|
||||||
[ForeignKey("UserReference")]
|
[ForeignKey("UserReference")]
|
||||||
public virtual Receiver? Receiver { get; set; }
|
public virtual Receiver? Receiver { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public ReferenceType ReferenceType => (Status / 1000) switch
|
|
||||||
{
|
|
||||||
1 => ReferenceType.Sender,
|
|
||||||
2 or 3 => ReferenceType.Receiver,
|
|
||||||
_ => ReferenceType.Unknown,
|
|
||||||
};
|
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public string? StatusName
|
|
||||||
=> (Enum.IsDefined(typeof(EnvelopeStatus), Status))
|
|
||||||
? Enum.GetName(typeof(EnvelopeStatus), Status)
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,24 @@ public static class MemoryCacheExtensions
|
|||||||
{
|
{
|
||||||
private static readonly Guid BaseId = Guid.NewGuid();
|
private static readonly Guid BaseId = Guid.NewGuid();
|
||||||
|
|
||||||
public static IDictionary<string, int> GetEnumAsDictionary<TEnum>(this IMemoryCache memoryCache)
|
public static IDictionary<string, int> GetEnumAsDictionary<TEnum>(this IMemoryCache memoryCache, string key = "", params object[] ignores)
|
||||||
where TEnum : Enum
|
where TEnum : Enum
|
||||||
=> memoryCache.GetOrCreate(BaseId + typeof(TEnum).FullName, _ =>
|
=> memoryCache.GetOrCreate(BaseId + typeof(TEnum).FullName + key, _ =>
|
||||||
Enum.GetValues(typeof(TEnum))
|
{
|
||||||
|
var mergedIgnores = new List<TEnum>();
|
||||||
|
|
||||||
|
foreach (var ignore in ignores)
|
||||||
|
{
|
||||||
|
if (ignore is IEnumerable<TEnum> ignoreList)
|
||||||
|
mergedIgnores.AddRange(ignoreList);
|
||||||
|
else if (ignore is TEnum ignoreVal)
|
||||||
|
mergedIgnores.Add(ignoreVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Enum.GetValues(typeof(TEnum))
|
||||||
.Cast<TEnum>()
|
.Cast<TEnum>()
|
||||||
.ToDictionary(e => e.ToString(), e => Convert.ToInt32(e)))
|
.Where(e => !mergedIgnores.Contains(e))
|
||||||
|
.ToDictionary(e => e.ToString(), e => Convert.ToInt32(e));
|
||||||
|
})
|
||||||
?? throw new InvalidOperationException($"Failed to cache or retrieve enum dictionary for type '{typeof(TEnum).FullName}'.");
|
?? throw new InvalidOperationException($"Failed to cache or retrieve enum dictionary for type '{typeof(TEnum).FullName}'.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class EnvelopeController : ControllerBase
|
|||||||
if (envelope.Uuid is string uuid)
|
if (envelope.Uuid is string uuid)
|
||||||
envelopes = envelopes.Where(e => e.Uuid == uuid);
|
envelopes = envelopes.Where(e => e.Uuid == uuid);
|
||||||
|
|
||||||
return Ok(envelopes);
|
return envelopes.Any() ? Ok(envelopes) : NotFound();
|
||||||
},
|
},
|
||||||
Fail: IActionResult (msg, ntc) =>
|
Fail: IActionResult (msg, ntc) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public class EnvelopeReceiverController : ControllerBase
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ruft den Namen des zuletzt verwendeten Empfängers basierend auf der angegebenen E-Mail-Adresse ab.
|
/// Ruft den Namen des zuletzt verwendeten Empfängers basierend auf der angegebenen E-Mail-Adresse ab.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="receiverName">Die Abfrage, die die E-Mail-Adresse des Empfängers enthält.</param>
|
/// <param name="receiver">Abfrage, bei der nur eine der Angaben ID, Signatur oder E-Mail-Adresse des Empfängers eingegeben werden muss.</param>
|
||||||
/// <returns>Eine HTTP-Antwort mit dem Namen des Empfängers oder einem Fehlerstatus.</returns>
|
/// <returns>Eine HTTP-Antwort mit dem Namen des Empfängers oder einem Fehlerstatus.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Dieser Endpunkt ermöglicht es, den Namen des zuletzt verwendeten Empfängers basierend auf der E-Mail-Adresse abzurufen.
|
/// Dieser Endpunkt ermöglicht es, den Namen des zuletzt verwendeten Empfängers basierend auf der E-Mail-Adresse abzurufen.
|
||||||
@@ -123,13 +123,10 @@ public class EnvelopeReceiverController : ControllerBase
|
|||||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpGet("salute")]
|
[HttpGet("salute")]
|
||||||
public async Task<IActionResult> GetReceiverName([FromQuery] ReadReceiverNameQuery receiverName)
|
public async Task<IActionResult> GetReceiverName([FromQuery] ReadReceiverNameQuery receiver)
|
||||||
{
|
{
|
||||||
if (receiverName.EmailAddress is null)
|
return await _erService.ReadLastUsedReceiverNameByMailAsync(receiver.EmailAddress, receiver.Id, receiver.Signature).ThenAsync(
|
||||||
return BadRequest();
|
Success: res => res is null ? NotFound() : Ok(res),
|
||||||
|
|
||||||
return await _erService.ReadLastUsedReceiverNameByMail(receiverName.EmailAddress).ThenAsync(
|
|
||||||
Success: res => res is null ? Ok(string.Empty) : Ok(res),
|
|
||||||
Fail: IActionResult (msg, ntc) =>
|
Fail: IActionResult (msg, ntc) =>
|
||||||
{
|
{
|
||||||
if (ntc.HasFlag(Flag.NotFound))
|
if (ntc.HasFlag(Flag.NotFound))
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
|
using EnvelopeGenerator.Application.Contracts.Services;
|
||||||
using EnvelopeGenerator.Application.Contracts.Services;
|
|
||||||
using EnvelopeGenerator.Application.Histories.Queries.Read;
|
using EnvelopeGenerator.Application.Histories.Queries.Read;
|
||||||
using EnvelopeGenerator.Extensions;
|
using EnvelopeGenerator.Extensions;
|
||||||
|
using MediatR;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using static EnvelopeGenerator.Common.Constants;
|
using static EnvelopeGenerator.Common.Constants;
|
||||||
|
|
||||||
|
|
||||||
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -18,34 +17,35 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers;
|
|||||||
[Authorize]
|
[Authorize]
|
||||||
public class HistoryController : ControllerBase
|
public class HistoryController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger<HistoryController> _logger;
|
|
||||||
|
|
||||||
private readonly IEnvelopeHistoryService _service;
|
private readonly IEnvelopeHistoryService _service;
|
||||||
|
|
||||||
private readonly IMemoryCache _memoryCache;
|
private readonly IMemoryCache _memoryCache;
|
||||||
|
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Konstruktor für den HistoryController.
|
/// Konstruktor für den HistoryController.
|
||||||
/// </summary>
|
/// </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>
|
/// <param name="service">Der Dienst, der für die Verarbeitung der Umschlaghistorie verantwortlich ist.</param>
|
||||||
public HistoryController(ILogger<HistoryController> logger, IEnvelopeHistoryService service, IMemoryCache memoryCache)
|
/// <param name="memoryCache"></param>
|
||||||
|
/// param name="mediator"
|
||||||
|
public HistoryController(IEnvelopeHistoryService service, IMemoryCache memoryCache, IMediator mediator)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
|
||||||
_service = service;
|
_service = service;
|
||||||
_memoryCache = memoryCache;
|
_memoryCache = memoryCache;
|
||||||
|
_mediator = mediator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gibt alle möglichen Verweise auf alle möglichen Status in einem Verlaufsdatensatz zurück. (z. B. DocumentSigned bezieht sich auf Receiver.)
|
/// 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.
|
/// 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:
|
/// 1 - Sender:
|
||||||
/// Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 2* beginnen.
|
/// Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 1* beginnen.
|
||||||
/// 2 - System:
|
/// 2 - Receiver:
|
||||||
|
/// Historische Datensätze, die sich auf den Status des Absenders beziehen. Sie haben Statuscodes, die mit 2* beginnen.
|
||||||
|
/// 3 - System:
|
||||||
/// Historische Datensätze, die sich auf den allgemeinen Zustand des Umschlags beziehen. Diese haben Statuscodes, die mit 3* beginnen.
|
/// Historische Datensätze, die sich auf den allgemeinen Zustand des Umschlags beziehen. Diese haben Statuscodes, die mit 3* beginnen.
|
||||||
/// 3 - Unknown:
|
/// 4 - Unknown:
|
||||||
/// Ein unbekannter Datensatz weist auf einen möglichen Mangel oder eine Unstimmigkeit im Aktualisierungsprozess der Anwendung hin.
|
/// Ein unbekannter Datensatz weist auf einen möglichen Mangel oder eine Unstimmigkeit im Aktualisierungsprozess der Anwendung hin.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -54,29 +54,25 @@ public class HistoryController : ControllerBase
|
|||||||
[Authorize]
|
[Authorize]
|
||||||
public IActionResult GetReferenceTypes(ReferenceType? referenceType = null)
|
public IActionResult GetReferenceTypes(ReferenceType? referenceType = null)
|
||||||
{
|
{
|
||||||
return referenceType is null ? Ok(_memoryCache.GetEnumAsDictionary<ReferenceType>()) : Ok(referenceType.ToString());
|
return referenceType is null ? Ok(_memoryCache.GetEnumAsDictionary<ReferenceType>("gen.api", ReferenceType.Unknown)) : Ok(referenceType.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gibt alle möglichen Status in einem Verlaufsdatensatz zurück.
|
/// 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.
|
/// Dies wird hinzugefügt, damit Client-Anwendungen sich selbst auf dem neuesten Stand halten können.
|
||||||
/// 0: Invalid
|
|
||||||
/// 1001: EnvelopeCreated
|
|
||||||
/// 1002: EnvelopeSaved
|
|
||||||
/// 1003: EnvelopeQueued
|
/// 1003: EnvelopeQueued
|
||||||
/// 1004: EnvelopeSent (Nicht verwendet)
|
|
||||||
/// 1005: EnvelopePartlySigned
|
|
||||||
/// 1006: EnvelopeCompletelySigned
|
/// 1006: EnvelopeCompletelySigned
|
||||||
/// 1007: EnvelopeReportCreated
|
/// 1007: EnvelopeReportCreated
|
||||||
/// 1008: EnvelopeArchived
|
/// 1008: EnvelopeArchived
|
||||||
/// 1009: EnvelopeDeleted
|
/// 1009: EnvelopeDeleted
|
||||||
|
/// 10007: EnvelopeRejected
|
||||||
|
/// 10009: EnvelopeWithdrawn
|
||||||
/// 2001: AccessCodeRequested
|
/// 2001: AccessCodeRequested
|
||||||
/// 2002: AccessCodeCorrect
|
/// 2002: AccessCodeCorrect
|
||||||
/// 2003: AccessCodeIncorrect
|
/// 2003: AccessCodeIncorrect
|
||||||
/// 2004: DocumentOpened
|
/// 2004: DocumentOpened
|
||||||
/// 2005: DocumentSigned
|
/// 2005: DocumentSigned
|
||||||
/// 4001: DocumentForwarded
|
/// 2006: DocumentForwarded
|
||||||
/// 2006: SignatureConfirmed
|
|
||||||
/// 2007: DocumentRejected
|
/// 2007: DocumentRejected
|
||||||
/// 2008: EnvelopeShared
|
/// 2008: EnvelopeShared
|
||||||
/// 2009: EnvelopeViewed
|
/// 2009: EnvelopeViewed
|
||||||
@@ -88,9 +84,9 @@ public class HistoryController : ControllerBase
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="status">
|
/// <param name="status">
|
||||||
/// Abfrageparameter, der angibt, auf welche Referenz sich der Status bezieht.
|
/// 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 - 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 - 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
|
/// 3 - 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.
|
/// integriert mit der Anwendung EmailProfiler, um E-Mails zu versenden und haben die Codes, die mit 3* beginnen.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>Gibt die HTTP-Antwort zurück.</returns>
|
/// <returns>Gibt die HTTP-Antwort zurück.</returns>
|
||||||
@@ -99,13 +95,13 @@ public class HistoryController : ControllerBase
|
|||||||
[Authorize]
|
[Authorize]
|
||||||
public IActionResult GetEnvelopeStatus([FromQuery] EnvelopeStatus? status = null)
|
public IActionResult GetEnvelopeStatus([FromQuery] EnvelopeStatus? status = null)
|
||||||
{
|
{
|
||||||
return status is null ? Ok(_memoryCache.GetEnumAsDictionary<EnvelopeStatus>()) : Ok(status.ToString());
|
return status is null ? Ok(_memoryCache.GetEnumAsDictionary<EnvelopeStatus>("gen.api", Status.NonHist, Status.RelatedToFormApp)) : Ok(status.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ruft die gesamte Umschlaghistorie basierend auf den angegebenen Abfrageparametern ab.
|
/// Ruft die gesamte Umschlaghistorie basierend auf den angegebenen Abfrageparametern ab.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="history">Die Abfrageparameter, die die Filterkriterien für die Umschlaghistorie definieren.</param>
|
/// <param name="historyQuery">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>
|
/// <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="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="400">Die Anfrage war ungültig oder unvollständig.</response>
|
||||||
@@ -114,29 +110,10 @@ public class HistoryController : ControllerBase
|
|||||||
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public async Task<IActionResult> GetAllAsync([FromQuery] ReadHistoryQuery history)
|
public async Task<IActionResult> GetAllAsync([FromQuery] ReadHistoryQuery historyQuery)
|
||||||
{
|
{
|
||||||
|
var history = await _mediator.Send(historyQuery);
|
||||||
|
|
||||||
|
return Ok((historyQuery.OnlyLast ?? false) ? history.MaxBy(h => h.AddedWhen) : 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
<Authors>Digital Data GmbH</Authors>
|
<Authors>Digital Data GmbH</Authors>
|
||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>EnvelopeGenerator.GeneratorAPI</Product>
|
<Product>EnvelopeGenerator.GeneratorAPI</Product>
|
||||||
<Version>1.2.2</Version>
|
<Version>1.2.3</Version>
|
||||||
<FileVersion>1.2.2</FileVersion>
|
<FileVersion>1.2.3</FileVersion>
|
||||||
<AssemblyVersion>1.2.2</AssemblyVersion>
|
<AssemblyVersion>1.2.3</AssemblyVersion>
|
||||||
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
|
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
|
||||||
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
|
<PackageReference Include="DigitalData.Core.API" Version="2.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.4" />
|
||||||
|
<PackageReference Include="NLog" Version="5.2.5" />
|
||||||
|
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.0" />
|
||||||
<PackageReference Include="Scalar.AspNetCore" Version="2.2.1" />
|
<PackageReference Include="Scalar.AspNetCore" Version="2.2.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.1" />
|
||||||
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
|
<PackageReference Include="DigitalData.Core.Abstractions" Version="3.6.0" />
|
||||||
|
|||||||
@@ -16,19 +16,34 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using DigitalData.Core.Abstractions.Security.Extensions;
|
using DigitalData.Core.Abstractions.Security.Extensions;
|
||||||
using EnvelopeGenerator.GeneratorAPI.Middleware;
|
using EnvelopeGenerator.GeneratorAPI.Middleware;
|
||||||
|
using NLog.Web;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
||||||
|
logger.Info("Logging initialized!");
|
||||||
|
|
||||||
var config = builder.Configuration;
|
try
|
||||||
|
{
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
var deferredProvider = new DeferredServiceProvider();
|
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
if (!builder.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
builder.Logging.ClearProviders();
|
||||||
|
builder.Host.UseNLog();
|
||||||
|
}
|
||||||
|
|
||||||
//CORS Policy
|
var config = builder.Configuration;
|
||||||
var allowedOrigins = config.GetSection("AllowedOrigins").Get<string[]>() ??
|
|
||||||
throw new InvalidOperationException("AllowedOrigins section is missing in the configuration.");
|
var deferredProvider = new DeferredServiceProvider();
|
||||||
builder.Services.AddCors(options =>
|
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
|
//CORS Policy
|
||||||
|
var allowedOrigins = config.GetSection("AllowedOrigins").Get<string[]>() ??
|
||||||
|
throw new InvalidOperationException("AllowedOrigins section is missing in the configuration.");
|
||||||
|
builder.Services.AddCors(options =>
|
||||||
{
|
{
|
||||||
options.AddPolicy("AllowSpecificOriginsPolicy", builder =>
|
options.AddPolicy("AllowSpecificOriginsPolicy", builder =>
|
||||||
{
|
{
|
||||||
@@ -40,34 +55,34 @@ builder.Services.AddCors(options =>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Swagger
|
// Swagger
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen(options =>
|
builder.Services.AddSwaggerGen(options =>
|
||||||
{
|
|
||||||
options.SwaggerDoc("v1", new OpenApiInfo
|
|
||||||
{
|
{
|
||||||
Version = "v1",
|
options.SwaggerDoc("v1", new OpenApiInfo
|
||||||
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",
|
Version = "v1",
|
||||||
Url = new Uri("https://digitaldata.works/digitale-signatur#kontakt"),
|
Title = "signFLOW Absender-API",
|
||||||
Email = "info-flow@digitaldata.works"
|
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
|
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||||
{
|
{
|
||||||
Name = "Authorization",
|
Name = "Authorization",
|
||||||
Type = SecuritySchemeType.Http,
|
Type = SecuritySchemeType.Http,
|
||||||
Scheme = "bearer",
|
Scheme = "bearer",
|
||||||
BearerFormat = "JWT",
|
BearerFormat = "JWT",
|
||||||
In = ParameterLocation.Header,
|
In = ParameterLocation.Header,
|
||||||
Description = "JWT-Autorisierungs-Header unter Verwendung des Bearer-Schemas.",
|
Description = "JWT-Autorisierungs-Header unter Verwendung des Bearer-Schemas.",
|
||||||
});
|
});
|
||||||
|
|
||||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
new OpenApiSecurityScheme
|
new OpenApiSecurityScheme
|
||||||
@@ -82,130 +97,136 @@ builder.Services.AddSwaggerGen(options =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
|
var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
|
||||||
foreach (var xmlFile in xmlFiles)
|
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.Configure<ConnectionString>(cs => cs.Value = connStr);
|
|
||||||
|
|
||||||
builder.Services.AddDbContext<EGDbContext>(options => options.UseSqlServer(connStr));
|
|
||||||
|
|
||||||
builder.Services.AddAuthHubClient(config.GetSection("AuthClientParams"));
|
|
||||||
|
|
||||||
var authTokenKeys = config.GetOrDefault<AuthTokenKeys>();
|
|
||||||
|
|
||||||
builder.Services.AddAuthentication(options =>
|
|
||||||
{
|
|
||||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
|
||||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
|
||||||
})
|
|
||||||
.AddJwtBearer(opt =>
|
|
||||||
{
|
|
||||||
opt.TokenValidationParameters = new TokenValidationParameters
|
|
||||||
{
|
{
|
||||||
ValidateIssuerSigningKey = true,
|
options.IncludeXmlComments(xmlFile);
|
||||||
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) =>
|
}
|
||||||
{
|
});
|
||||||
var clientParams = deferredProvider.GetOptions<ClientParams>();
|
builder.Services.AddOpenApi();
|
||||||
var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience);
|
// DbContext
|
||||||
return new List<SecurityKey>() { publicKey.SecurityKey };
|
var connStr = config.GetConnectionString("Default") ?? throw new InvalidOperationException("There is no default connection string in appsettings.json.");
|
||||||
},
|
|
||||||
ValidateIssuer = true,
|
|
||||||
ValidIssuer = authTokenKeys.Issuer,
|
|
||||||
ValidateAudience = true,
|
|
||||||
ValidAudience = authTokenKeys.Audience,
|
|
||||||
};
|
|
||||||
|
|
||||||
opt.Events = new JwtBearerEvents
|
builder.Services.Configure<ConnectionString>(cs => cs.Value = connStr);
|
||||||
|
|
||||||
|
builder.Services.AddDbContext<EGDbContext>(options => options.UseSqlServer(connStr));
|
||||||
|
|
||||||
|
builder.Services.AddAuthHubClient(config.GetSection("AuthClientParams"));
|
||||||
|
|
||||||
|
var authTokenKeys = config.GetOrDefault<AuthTokenKeys>();
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
})
|
||||||
|
.AddJwtBearer(opt =>
|
||||||
{
|
{
|
||||||
OnMessageReceived = context =>
|
opt.TokenValidationParameters = new TokenValidationParameters
|
||||||
{
|
{
|
||||||
// if there is no token read related cookie or query string
|
ValidateIssuerSigningKey = true,
|
||||||
if (context.Token is null) // if there is no token
|
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) =>
|
||||||
{
|
{
|
||||||
if (context.Request.Cookies.TryGetValue(authTokenKeys.Cookie, out var cookieToken) && cookieToken is not null)
|
var clientParams = deferredProvider.GetOptions<ClientParams>();
|
||||||
context.Token = cookieToken;
|
var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience);
|
||||||
else if (context.Request.Query.TryGetValue(authTokenKeys.QueryString, out var queryStrToken))
|
return new List<SecurityKey>() { publicKey.SecurityKey };
|
||||||
context.Token = queryStrToken;
|
},
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidIssuer = authTokenKeys.Issuer,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidAudience = authTokenKeys.Audience,
|
||||||
|
};
|
||||||
|
|
||||||
|
opt.Events = new JwtBearerEvents
|
||||||
|
{
|
||||||
|
OnMessageReceived = context =>
|
||||||
|
{
|
||||||
|
// if there is no token read related cookie or query string
|
||||||
|
if (context.Token is null) // if there is no token
|
||||||
|
{
|
||||||
|
if (context.Request.Cookies.TryGetValue(authTokenKeys.Cookie, out var cookieToken) && cookieToken is not null)
|
||||||
|
context.Token = cookieToken;
|
||||||
|
else if (context.Request.Query.TryGetValue(authTokenKeys.QueryString, out var queryStrToken))
|
||||||
|
context.Token = queryStrToken;
|
||||||
|
}
|
||||||
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
};
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
// Authentication
|
||||||
|
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||||||
|
.AddCookie(options =>
|
||||||
|
{
|
||||||
|
options.Cookie.HttpOnly = true; // Makes the cookie inaccessible to client-side scripts for security
|
||||||
|
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; // Ensures cookies are sent over HTTPS only
|
||||||
|
options.Cookie.SameSite = SameSiteMode.Strict; // Protects against CSRF attacks by restricting how cookies are sent with requests from external sites
|
||||||
|
options.LoginPath = "/api/auth/login";
|
||||||
|
options.LogoutPath = "/api/auth/logout";
|
||||||
|
options.SlidingExpiration = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Authentication
|
// User manager
|
||||||
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
builder.Services.AddUserManager<EGDbContext>();
|
||||||
.AddCookie(options =>
|
|
||||||
{
|
|
||||||
options.Cookie.HttpOnly = true; // Makes the cookie inaccessible to client-side scripts for security
|
|
||||||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; // Ensures cookies are sent over HTTPS only
|
|
||||||
options.Cookie.SameSite = SameSiteMode.Strict; // Protects against CSRF attacks by restricting how cookies are sent with requests from external sites
|
|
||||||
options.LoginPath = "/api/auth/login";
|
|
||||||
options.LogoutPath = "/api/auth/logout";
|
|
||||||
options.SlidingExpiration = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// User manager
|
// LDAP
|
||||||
builder.Services.AddUserManager<EGDbContext>();
|
builder.ConfigureBySection<DirectorySearchOptions>();
|
||||||
|
builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions"));
|
||||||
|
|
||||||
// LDAP
|
// Localizer
|
||||||
builder.ConfigureBySection<DirectorySearchOptions>();
|
builder.Services.AddCookieBasedLocalizer();
|
||||||
builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions"));
|
|
||||||
|
|
||||||
// Localizer
|
// Envelope generator serives
|
||||||
builder.Services.AddCookieBasedLocalizer() ;
|
builder.Services
|
||||||
|
.AddEnvelopeGeneratorInfrastructureServices(sqlExecutorConfigureOptions: executor => executor.ConnectionString = connStr)
|
||||||
|
.AddEnvelopeGeneratorServices(config);
|
||||||
|
|
||||||
// Envelope generator serives
|
var app = builder.Build();
|
||||||
builder.Services
|
|
||||||
.AddEnvelopeGeneratorInfrastructureServices(sqlExecutorConfigureOptions: executor => executor.ConnectionString = connStr)
|
|
||||||
.AddEnvelopeGeneratorServices(config);
|
|
||||||
|
|
||||||
var app = builder.Build();
|
deferredProvider.Factory = () => app.Services;
|
||||||
|
|
||||||
deferredProvider.Factory = () => app.Services;
|
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
||||||
|
|
||||||
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
app.MapOpenApi();
|
||||||
|
|
||||||
app.MapOpenApi();
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment() || (app.IsDevOrDiP() && config.GetValue<bool>("UseSwagger")))
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
app.MapScalarApiReference();
|
||||||
|
}
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Set CORS policy
|
||||||
if (app.Environment.IsDevelopment() || (app.IsDevOrDiP() && config.GetValue<bool>("UseSwagger")))
|
app.UseCors("AllowSpecificOriginsPolicy");
|
||||||
{
|
|
||||||
app.UseSwagger();
|
// Localizer
|
||||||
app.UseSwaggerUI();
|
string[] supportedCultureNames = { "de-DE", "en-US" };
|
||||||
app.MapScalarApiReference();
|
IList<CultureInfo> list = supportedCultureNames.Select((string cn) => new CultureInfo(cn)).ToList();
|
||||||
|
CultureInfo cultureInfo = list.FirstOrDefault() ?? throw new ArgumentNullException("supportedCultureNames", "Supported cultures cannot be empty.");
|
||||||
|
RequestLocalizationOptions requestLocalizationOptions = new RequestLocalizationOptions
|
||||||
|
{
|
||||||
|
SupportedCultures = list,
|
||||||
|
SupportedUICultures = list
|
||||||
|
};
|
||||||
|
requestLocalizationOptions.RequestCultureProviders.Add(new QueryStringRequestCultureProvider());
|
||||||
|
app.UseRequestLocalization(requestLocalizationOptions);
|
||||||
|
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseDefaultFiles();
|
||||||
|
app.UseStaticFiles();
|
||||||
|
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
// Set CORS policy
|
|
||||||
app.UseCors("AllowSpecificOriginsPolicy");
|
|
||||||
|
|
||||||
// Localizer
|
|
||||||
string[] supportedCultureNames = { "de-DE", "en-US" };
|
|
||||||
IList<CultureInfo> list = supportedCultureNames.Select((string cn) => new CultureInfo(cn)).ToList();
|
|
||||||
CultureInfo cultureInfo = list.FirstOrDefault() ?? throw new ArgumentNullException("supportedCultureNames", "Supported cultures cannot be empty.");
|
|
||||||
RequestLocalizationOptions requestLocalizationOptions = new RequestLocalizationOptions
|
|
||||||
{
|
{
|
||||||
SupportedCultures = list,
|
logger.Error(ex, "Stopped program because of exception");
|
||||||
SupportedUICultures = list
|
throw;
|
||||||
};
|
}
|
||||||
requestLocalizationOptions.RequestCultureProviders.Add(new QueryStringRequestCultureProvider());
|
|
||||||
app.UseRequestLocalization(requestLocalizationOptions);
|
|
||||||
|
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
|
||||||
|
|
||||||
app.UseDefaultFiles();
|
|
||||||
app.UseStaticFiles();
|
|
||||||
|
|
||||||
app.UseAuthentication();
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
app.MapControllers();
|
|
||||||
|
|
||||||
app.Run();
|
|
||||||
@@ -2,6 +2,9 @@
|
|||||||
using EnvelopeGenerator.Domain.Entities;
|
using EnvelopeGenerator.Domain.Entities;
|
||||||
using EnvelopeGenerator.Application.Contracts.Repositories;
|
using EnvelopeGenerator.Application.Contracts.Repositories;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.AspNetCore.Http.HttpResults;
|
||||||
|
using EnvelopeGenerator.Application.Exceptions;
|
||||||
|
using EnvelopeGenerator.Common.My.Resources;
|
||||||
|
|
||||||
namespace EnvelopeGenerator.Infrastructure.Repositories;
|
namespace EnvelopeGenerator.Infrastructure.Repositories;
|
||||||
|
|
||||||
@@ -39,7 +42,11 @@ public class EnvelopeReceiverRepository : CRUDRepository<EnvelopeReceiver, (int
|
|||||||
=> await ReadWhere(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).ToListAsync();
|
=> await ReadWhere(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).ToListAsync();
|
||||||
|
|
||||||
public async Task<EnvelopeReceiver?> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
|
public async Task<EnvelopeReceiver?> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true, bool readOnly = true)
|
||||||
=> await ReadWhere(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly).FirstOrDefaultAsync();
|
{
|
||||||
|
var query = ReadWhere(uuid: uuid, signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver, readOnly: readOnly);
|
||||||
|
|
||||||
|
return await query.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<string?> ReadAccessCodeAsync(string uuid, string signature, bool readOnly = true)
|
public async Task<string?> ReadAccessCodeAsync(string uuid, string signature, bool readOnly = true)
|
||||||
=> await ReadWhere(uuid: uuid, signature: signature, readOnly: readOnly)
|
=> await ReadWhere(uuid: uuid, signature: signature, readOnly: readOnly)
|
||||||
@@ -89,8 +96,26 @@ public class EnvelopeReceiverRepository : CRUDRepository<EnvelopeReceiver, (int
|
|||||||
return await query.Include(er => er.Envelope).Include(er => er.Receiver).ToListAsync();
|
return await query.Include(er => er.Envelope).Include(er => er.Receiver).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EnvelopeReceiver?> ReadLastByReceiver(string email)
|
public async Task<EnvelopeReceiver?> ReadLastByReceiverAsync(string? email = null, int? id = null, string? signature = null)
|
||||||
{
|
{
|
||||||
return await _dbSet.Where(er => er.Receiver!.EmailAddress == email).OrderBy(er => er.EnvelopeId).LastOrDefaultAsync();
|
var parameters = new[] { email, id?.ToString(), signature }.Count(p => p != null);
|
||||||
|
|
||||||
|
if (parameters == 0)
|
||||||
|
throw new BadRequestException("You must provide either 'email', 'id', or 'signature' for the query.");
|
||||||
|
if (parameters > 1)
|
||||||
|
throw new BadRequestException("Please provide only one parameter: either 'email', 'id', or 'signature'.");
|
||||||
|
|
||||||
|
var query = _dbSet.AsNoTracking();
|
||||||
|
|
||||||
|
if(email is not null)
|
||||||
|
query = query.Where(er => er.Receiver!.EmailAddress == email);
|
||||||
|
|
||||||
|
if (id is not null)
|
||||||
|
query = query.Where(er => er.Receiver!.Id == id);
|
||||||
|
|
||||||
|
if (signature is not null)
|
||||||
|
query = query.Where(er => er.Receiver!.Signature == signature);
|
||||||
|
|
||||||
|
return await query.OrderBy(er => er.EnvelopeId).LastOrDefaultAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,31 +96,32 @@ public class HomeController : ViewControllerBase
|
|||||||
|
|
||||||
ViewData["EnvelopeKey"] = envelopeReceiverId;
|
ViewData["EnvelopeKey"] = envelopeReceiverId;
|
||||||
|
|
||||||
return await _envRcvService.ReadByEnvelopeReceiverIdAsync(envelopeReceiverId: envelopeReceiverId).ThenAsync<EnvelopeReceiverDto, IActionResult>(
|
var er_res = await _envRcvService.ReadByEnvelopeReceiverIdAsync(envelopeReceiverId: envelopeReceiverId);
|
||||||
SuccessAsync: async er =>
|
|
||||||
|
if (er_res.IsFailed)
|
||||||
|
{
|
||||||
|
_logger.LogNotice(er_res.Notices);
|
||||||
|
return this.ViewEnvelopeNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var er = er_res.Data;
|
||||||
|
|
||||||
|
EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId);
|
||||||
|
|
||||||
|
bool accessCodeAlreadyRequested = await _historyService.AccessCodeAlreadyRequested(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress);
|
||||||
|
if (!accessCodeAlreadyRequested)
|
||||||
|
{
|
||||||
|
await _historyService.RecordAsync(er.EnvelopeId, er.Receiver.EmailAddress, EnvelopeStatus.AccessCodeRequested);
|
||||||
|
|
||||||
|
var mailRes = await _mailService.SendAccessCodeAsync(envelopeReceiverDto: er);
|
||||||
|
if (mailRes.IsFailed)
|
||||||
{
|
{
|
||||||
EnvelopeResponse response = await envelopeOldService.LoadEnvelope(envelopeReceiverId);
|
_logger.LogNotice(mailRes);
|
||||||
|
return this.ViewAccessCodeNotSent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool accessCodeAlreadyRequested = await _historyService.AccessCodeAlreadyRequested(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress);
|
return Redirect($"{envelopeReceiverId}/Locked");
|
||||||
if (!accessCodeAlreadyRequested)
|
|
||||||
{
|
|
||||||
await _historyService.RecordAsync(er.EnvelopeId, er.Receiver.EmailAddress, EnvelopeStatus.AccessCodeRequested);
|
|
||||||
|
|
||||||
var mailRes = await _mailService.SendAccessCodeAsync(envelopeReceiverDto: er);
|
|
||||||
if (mailRes.IsFailed)
|
|
||||||
{
|
|
||||||
_logger.LogNotice(mailRes);
|
|
||||||
return this.ViewAccessCodeNotSent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Redirect($"{envelopeReceiverId}/Locked");
|
|
||||||
},
|
|
||||||
Fail: (messages, notices) =>
|
|
||||||
{
|
|
||||||
_logger.LogNotice(notices);
|
|
||||||
return this.ViewEnvelopeNotFound();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<PackageId>EnvelopeGenerator.Web</PackageId>
|
<PackageId>EnvelopeGenerator.Web</PackageId>
|
||||||
<Version>3.1.2</Version>
|
<Version>3.1.4</Version>
|
||||||
<Authors>Digital Data GmbH</Authors>
|
<Authors>Digital Data GmbH</Authors>
|
||||||
<Company>Digital Data GmbH</Company>
|
<Company>Digital Data GmbH</Company>
|
||||||
<Product>EnvelopeGenerator.Web</Product>
|
<Product>EnvelopeGenerator.Web</Product>
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
<PackageTags>digital data envelope generator web</PackageTags>
|
<PackageTags>digital data envelope generator web</PackageTags>
|
||||||
<Description>EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description>
|
<Description>EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description>
|
||||||
<ApplicationIcon>Assets\icon.ico</ApplicationIcon>
|
<ApplicationIcon>Assets\icon.ico</ApplicationIcon>
|
||||||
<AssemblyVersion>3.1.2</AssemblyVersion>
|
<AssemblyVersion>3.1.4</AssemblyVersion>
|
||||||
<FileVersion>3.1.2</FileVersion>
|
<FileVersion>3.1.4</FileVersion>
|
||||||
<Copyright>Copyright © 2025 Digital Data GmbH. All rights reserved.</Copyright>
|
<Copyright>Copyright © 2025 Digital Data GmbH. All rights reserved.</Copyright>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
@@ -2126,7 +2126,7 @@
|
|||||||
<PackageReference Include="Quartz.Serialization.Json" Version="3.8.0" />
|
<PackageReference Include="Quartz.Serialization.Json" Version="3.8.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
|
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="7.0.0" />
|
||||||
<PackageReference Include="System.DirectoryServices" Version="7.0.1" />
|
<PackageReference Include="System.DirectoryServices" Version="7.0.1" />
|
||||||
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="7.0.1" />
|
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="7.0.1" />
|
||||||
<PackageReference Include="System.DirectoryServices.Protocols" Version="7.0.1" />
|
<PackageReference Include="System.DirectoryServices.Protocols" Version="7.0.1" />
|
||||||
|
|||||||
@@ -24,6 +24,14 @@ try
|
|||||||
{
|
{
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
|
||||||
|
|
||||||
|
if (!builder.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
builder.Logging.ClearProviders();
|
||||||
|
builder.Host.UseNLog();
|
||||||
|
}
|
||||||
|
|
||||||
var config = builder.Configuration;
|
var config = builder.Configuration;
|
||||||
|
|
||||||
var allowedOrigins = config.GetSection("AllowedOrigins").Get<string[]>() ??
|
var allowedOrigins = config.GetSection("AllowedOrigins").Get<string[]>() ??
|
||||||
@@ -41,15 +49,14 @@ try
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Logging.ClearProviders();
|
|
||||||
builder.Host.UseNLog();
|
|
||||||
|
|
||||||
// Add base services
|
// Add base services
|
||||||
builder.Services.AddScoped<DatabaseService>();
|
builder.Services.AddScoped<DatabaseService>();
|
||||||
|
|
||||||
// Add higher order services
|
// Add higher order services
|
||||||
builder.Services.AddScoped<EnvelopeOldService>();
|
builder.Services.AddScoped<EnvelopeOldService>();
|
||||||
|
|
||||||
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
|
||||||
builder.ConfigureBySection<TFARegParams>();
|
builder.ConfigureBySection<TFARegParams>();
|
||||||
|
|
||||||
// Add controllers and razor views
|
// Add controllers and razor views
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ namespace EnvelopeGenerator.Web.Services
|
|||||||
public ActionService actionService;
|
public ActionService actionService;
|
||||||
public EmailService emailService;
|
public EmailService emailService;
|
||||||
|
|
||||||
public ServiceContainer(State state)
|
public ServiceContainer(State state, MSSQLServer MSSQL)
|
||||||
{
|
{
|
||||||
actionService = new(state);
|
actionService = new(state, MSSQL);
|
||||||
emailService = new(state);
|
emailService = new(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ namespace EnvelopeGenerator.Web.Services
|
|||||||
State.DbConfig = configModel.LoadConfiguration();
|
State.DbConfig = configModel.LoadConfiguration();
|
||||||
|
|
||||||
Models = new(State);
|
Models = new(State);
|
||||||
Services = new(State);
|
Services = new(State, MSSQL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,5 +7,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AdminPassword": "dd",
|
"AdminPassword": "dd",
|
||||||
"UseCSPInDev": false
|
"UseCSPInDev": false,
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"Default": "Server=sDD-VMP04-SQL19\\CURSORAG;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,11 @@
|
|||||||
"fileName": "${logDirectory}\\${logFileNamePrefix}-Info.log",
|
"fileName": "${logDirectory}\\${logFileNamePrefix}-Info.log",
|
||||||
"maxArchiveDays": 30
|
"maxArchiveDays": 30
|
||||||
},
|
},
|
||||||
|
"warningLogs": {
|
||||||
|
"type": "File",
|
||||||
|
"fileName": "${logDirectory}\\${logFileNamePrefix}-Warning.log",
|
||||||
|
"maxArchiveDays": 30
|
||||||
|
},
|
||||||
"errorLogs": {
|
"errorLogs": {
|
||||||
"type": "File",
|
"type": "File",
|
||||||
"fileName": "${logDirectory}\\${logFileNamePrefix}-Error.log",
|
"fileName": "${logDirectory}\\${logFileNamePrefix}-Error.log",
|
||||||
@@ -50,14 +55,17 @@
|
|||||||
"maxArchiveDays": 30
|
"maxArchiveDays": 30
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Trace, Debug, Info, Warn, Error and *Fatal*
|
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"logger": "*",
|
"logger": "*",
|
||||||
"minLevel": "Info",
|
"level": "Info",
|
||||||
"maxLevel": "Warn",
|
|
||||||
"writeTo": "infoLogs"
|
"writeTo": "infoLogs"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"logger": "*",
|
||||||
|
"level": "Warn",
|
||||||
|
"writeTo": "warningLogs"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"logger": "*",
|
"logger": "*",
|
||||||
"level": "Error",
|
"level": "Error",
|
||||||
|
|||||||
Reference in New Issue
Block a user