This commit is contained in:
SchreiberM 2024-03-15 11:47:30 +01:00
commit a3c66ecd19
36 changed files with 537 additions and 329 deletions

View File

@ -0,0 +1,14 @@
using DigitalData.Core.Contracts.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Contracts
{
public interface IConfigService : IBasicCRUDService<IConfigRepository, ConfigDto, Config, int>
{
Task<IServiceResult<ConfigDto>> ReadFirstAsync();
async Task<IServiceResult<ConfigDto>> ReadDefaultAsync() => await ReadFirstAsync();
}
}

View File

@ -0,0 +1,11 @@
using DigitalData.Core.Contracts.Application;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Contracts
{
public interface IEnvelopeDocumentService : IBasicCRUDService<IEnvelopeDocumentRepository, EnvelopeDocumentDto, EnvelopeDocument, int>
{
}
}

View File

@ -0,0 +1,15 @@
namespace EnvelopeGenerator.Application.DTOs
{
public record ConfigDto
{
public string DocumentPath { get; init; }
public int SendingProfile { get; init; }
public string SignatureHost { get; init; }
public string ExternalProgramName { get; init; }
public string ExportPath { get; init; }
public string DocumentPathDmz { get; init; }
public string ExportPathDmz { get; init; }
public string SignedMailPath { get; init; }
public string DocumentPathMoveAftsend { get; init; }
}
}

View File

@ -0,0 +1,12 @@
namespace EnvelopeGenerator.Application.DTOs
{
public record EnvelopeDocumentDto
{
public int Guid { get; init; }
public int EnvelopeId { get; init; }
public string Filename { get; init; }
public string Filepath { get; init; }
public DateTime AddedWhen { get; init; }
public string FilenameOriginal { get; init; }
}
}

View File

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="DigitalData.Core.Application">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Application\bin\Debug\net7.0\DigitalData.Core.Application.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Core.Contracts">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Application\bin\Debug\net7.0\DigitalData.Core.Contracts.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,18 @@
using AutoMapper;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.MappingProfiles
{
public class BasicDtoMappingProfile : Profile
{
public BasicDtoMappingProfile()
{
CreateMap<Config, ConfigDto>();
CreateMap<EnvelopeDocument, EnvelopeDocumentDto>();
CreateMap<ConfigDto, Config>();
CreateMap<EnvelopeDocumentDto, EnvelopeDocument>();
}
}
}

View File

@ -0,0 +1,30 @@
using AutoMapper;
using DigitalData.Core.Application;
using DigitalData.Core.Contracts.Application;
using DigitalData.Core.Contracts.CultureServices;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Services
{
public class ConfigService : BasicCRUDService<IConfigRepository, ConfigDto, Config, int>, IConfigService
{
public ConfigService(IConfigRepository repository, IKeyTranslationService translationService, IMapper mapper) : base(repository, translationService, mapper)
{
}
public async Task<IServiceResult<ConfigDto>> ReadFirstAsync()
{
var config = await _repository.ReadFirstAsync();
if (config is null)
return Failed<ConfigDto>("There is no configuration in DB.");
return Successful(_mapper.MapOrThrow<ConfigDto>(config));
}
public async Task<IServiceResult<ConfigDto>> ReadDefaultAsync() => await ReadFirstAsync();
}
}

View File

@ -0,0 +1,18 @@
using AutoMapper;
using DigitalData.Core.Application;
using DigitalData.Core.Contracts.Application;
using DigitalData.Core.Contracts.CultureServices;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Services
{
public class EnvelopeDocumentService : BasicCRUDService<IEnvelopeDocumentRepository, EnvelopeDocumentDto, EnvelopeDocument, int>, IEnvelopeDocumentService
{
public EnvelopeDocumentService(IEnvelopeDocumentRepository repository, IKeyTranslationService translationService, IMapper mapper) : base(repository, translationService, mapper)
{
}
}
}

View File

@ -19,10 +19,4 @@ Public Class EnvelopeDocument
Public Property Filepath As String
Public Property PageCount As Integer
Public ReadOnly Property PageCountTranslated As String
Get
Return $"{PageCount} Seiten"
End Get
End Property
End Class

View File

@ -45,7 +45,7 @@ Public Class DocumentModel
Public Function List(pEnvelopeId As Integer) As IEnumerable(Of EnvelopeDocument)
Try
Dim oSql = $"SELECT FROM [dbo].[TBSIG_ENVELOPE_DOCUMENT] WHERE ENVELOPE_ID = {pEnvelopeId}"
Dim oSql = $"SELECT * FROM [dbo].[TBSIG_ENVELOPE_DOCUMENT] WHERE ENVELOPE_ID = {pEnvelopeId}"
Dim oTable = Database.GetDatatable(oSql)
Return oTable?.Rows.Cast(Of DataRow).

View File

@ -0,0 +1,48 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_CONFIG", Schema = "dbo")]
public class Config
{
[Column("DOCUMENT_PATH", TypeName = "nvarchar(256)")]
public string DocumentPath { get; set; }
[Column("SENDING_PROFILE", TypeName = "int")]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)] // Assuming SENDING_PROFILE is manually entered or controlled by the application logic
[DefaultValue(0)] // This sets the default value for SENDING_PROFILE
public int SendingProfile { get; set; }
[Column("SIGNATURE_HOST", TypeName = "nvarchar(128)")]
public string SignatureHost { get; set; }
[Column("EXTERNAL_PROGRAM_NAME", TypeName = "nvarchar(30)")]
public string ExternalProgramName { get; set; }
[Column("EXPORT_PATH", TypeName = "nvarchar(256)")]
public string ExportPath { get; set; }
[Column("DOCUMENT_PATH_DMZ", TypeName = "nvarchar(512)")]
[Required]
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_DMZ
public string DocumentPathDmz { get; set; }
[Column("EXPORT_PATH_DMZ", TypeName = "nvarchar(512)")]
[Required]
[DefaultValue("")] // This sets the default value for EXPORT_PATH_DMZ
public string ExportPathDmz { get; set; }
[Column("SIGNED_MAIL_PATH", TypeName = "nvarchar(512)")]
[Required]
[DefaultValue("")] // This sets the default value for SIGNED_MAIL_PATH
public string SignedMailPath { get; set; }
[Column("DOCUMENT_PATH_MOVE_AFTSEND", TypeName = "nvarchar(512)")]
[Required]
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_MOVE_AFTSEND
public string DocumentPathMoveAftsend { get; set; }
}
}

View File

@ -0,0 +1,33 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_DOCUMENT", Schema = "dbo")]
public class EnvelopeDocument
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("GUID", TypeName = "int")]
public int Guid { get; set; }
[Column("ENVELOPE_ID", TypeName = "int")]
[Required]
public int EnvelopeId { get; set; }
[Column("FILENAME", TypeName = "nvarchar(256)")]
[Required]
public string Filename { get; set; }
[Column("FILEPATH", TypeName = "nvarchar(256)")]
[Required]
public string Filepath { get; set; }
[Column("ADDED_WHEN", TypeName = "datetime")]
[Required]
public DateTime AddedWhen { get; set; }
[Column("FILENAME_ORIGINAL", TypeName = "nvarchar(256)")]
public string FilenameOriginal { get; set; }
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,11 @@
using DigitalData.Core.Contracts.Application;
using DigitalData.Core.Contracts.Infrastructure;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Infrastructure.Contracts
{
public interface IConfigRepository : ICRUDRepository<Config, int>
{
Task<Config?> ReadFirstAsync();
}
}

View File

@ -0,0 +1,9 @@
using DigitalData.Core.Contracts.Infrastructure;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Infrastructure.Contracts
{
public interface IEnvelopeDocumentRepository : ICRUDRepository<EnvelopeDocument, int>
{
}
}

View File

@ -0,0 +1,20 @@
using EnvelopeGenerator.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace DigitalData.UserManager.Infrastructure.Repositories
{
public class EGDbContext : DbContext
{
public EGDbContext(DbContextOptions<EGDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Config>().HasNoKey();
modelBuilder.Entity<EnvelopeDocument>();
base.OnModelCreating(modelBuilder);
}
}
}

View File

@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.15" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="DigitalData.Core.Contracts">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Infrastructure\bin\Debug\net7.0\DigitalData.Core.Contracts.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Core.Infrastructure">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Infrastructure\bin\Debug\net7.0\DigitalData.Core.Infrastructure.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,21 @@
using DigitalData.Core.Infrastructure;
using DigitalData.UserManager.Infrastructure.Repositories;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.EntityFrameworkCore;
namespace EnvelopeGenerator.Infrastructure.Repositories
{
public class ConfigRepository : CRUDRepository<Config, int, EGDbContext>, IConfigRepository
{
public ConfigRepository(EGDbContext dbContext) : base(dbContext)
{
}
public async Task<Config?> ReadFirstAsync()
{
var configs = await _dbSet.ToListAsync();
return configs.Count > 0 ? configs[0] : default;
}
}
}

View File

@ -0,0 +1,14 @@
using DigitalData.Core.Infrastructure;
using DigitalData.UserManager.Infrastructure.Repositories;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Infrastructure.Repositories
{
public class EnvelopeDocumentRepository : CRUDRepository<EnvelopeDocument, int, EGDbContext>, IEnvelopeDocumentRepository
{
public EnvelopeDocumentRepository(EGDbContext dbContext) : base(dbContext)
{
}
}
}

View File

@ -1,192 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using DigitalData.Modules.Base;
using DigitalData.Modules.Logging;
using GdPicture14;
using Newtonsoft.Json;
namespace EnvelopeGenerator.Web.Classes
{
public partial class PDFBurner : BaseClass
{
private readonly string LicenseKey;
private readonly AnnotationManager Manager;
private readonly LicenseManager LicenseManager;
private const string ANNOTATION_TYPE_IMAGE = "pspdfkit/image";
private const string ANNOTATION_TYPE_INK = "pspdfkit/ink";
public PDFBurner(LogConfig pLogConfig, string pGDPictureLicenseKey) : base(pLogConfig)
{
LicenseKey = pGDPictureLicenseKey;
LicenseManager = new LicenseManager();
LicenseManager.RegisterKEY(pGDPictureLicenseKey);
Manager = new AnnotationManager();
}
public bool BurnInstantJSONAnnotationsToPDF(string pSourcePath, List<string> pInstantJSONList, string pDestinationPath)
{
if (Manager.InitFromFile(pSourcePath) != GdPictureStatus.OK)
{
Logger.Warn("Could not open file [{0}] for burning.", pSourcePath);
return false;
}
foreach (var oJSON in pInstantJSONList)
{
if (AddInstantJSONAnnotationToPDF(oJSON) == false)
{
Logger.Warn("Adding Annotation failed. Exiting");
return false;
}
}
try
{
Manager.BurnAnnotationsToPage(RemoveInitialAnnots: true, VectorMode: true);
Manager.SaveDocumentToPDF(pDestinationPath);
Manager.Close();
return true;
}
catch (Exception ex)
{
Logger.Warn("Could not burn and save annotations to file [{0}]!", pDestinationPath);
Logger.Error(ex);
return false;
}
}
private bool AddInstantJSONAnnotationToPDF(string pInstantJSON)
{
try
{
var oAnnotationData = JsonConvert.DeserializeObject<AnnotationData>(pInstantJSON);
foreach (Annotation oAnnotation in oAnnotationData.annotations)
{
switch (oAnnotation.type)
{
case ANNOTATION_TYPE_IMAGE:
{
AddImageAnnotation(oAnnotation, oAnnotationData.attachments);
break;
}
case ANNOTATION_TYPE_INK:
{
AddInkAnnotation(oAnnotation);
break;
}
}
}
return true;
}
catch (Exception ex)
{
Logger.Warn("Could not create annotation from InstantJSON");
Logger.Error(ex);
return false;
}
}
private bool AddImageAnnotation(Annotation pAnnotation, Dictionary<string, Attachment> pAttachments)
{
try
{
var oAttachment = pAttachments.Where(a => (a.Key ?? "") == (pAnnotation.imageAttachmentId ?? "")).SingleOrDefault();
// Convert pixels to Inches
var oBounds = pAnnotation.bbox.Select(ToInches).ToList();
float oX = oBounds[0];
float oY = oBounds[1];
float oWidth = oBounds[2];
float oHeight = oBounds[3];
Manager.AddEmbeddedImageAnnotFromBase64(oAttachment.Value.binary, oX, oY, oWidth, oHeight);
return true;
}
catch (Exception ex)
{
Logger.Warn("Could not add image annotation!");
Logger.Error(ex);
return false;
}
}
private bool AddInkAnnotation(Annotation pAnnotation)
{
try
{
var oSegments = pAnnotation.lines.points;
var oColor = ColorTranslator.FromHtml(pAnnotation.strokeColor);
Manager.SelectPage(pAnnotation.pageIndex);
foreach (List<List<float>> oSegment in oSegments)
{
var oPoints = oSegment.Select(ToPointF).ToArray();
Manager.AddFreeHandAnnot(oColor, oPoints);
}
return true;
}
catch (Exception ex)
{
Logger.Warn("Could not add image annotation!");
Logger.Error(ex);
return false;
}
}
private PointF ToPointF(List<float> pPoints)
{
var oPoints = pPoints.Select(ToInches).ToList();
return new PointF(oPoints[0], oPoints[1]);
}
private float ToInches(float pValue)
{
return pValue / 72f;
}
internal partial class AnnotationData
{
public List<Annotation> annotations { get; set; }
public Dictionary<string, Attachment> attachments { get; set; }
}
internal partial class Annotation
{
public string id { get; set; }
public List<float> bbox { get; set; }
public string type { get; set; }
public bool isSignature { get; set; }
public string imageAttachmentId { get; set; }
public Lines lines { get; set; }
public int pageIndex { get; set; }
public string strokeColor { get; set; }
}
internal partial class Lines
{
public List<List<List<float>>> points { get; set; }
}
internal partial class Attachment
{
public string binary { get; set; }
public string contentType { get; set; }
}
}
}

View File

@ -1,12 +0,0 @@
namespace EnvelopeGenerator.Web
{
public class Constants
{
public enum ErrorType
{
None,
ServerError,
FilesystemError
}
}
}

View File

@ -2,7 +2,6 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Web.Services;
using Microsoft.AspNetCore.Mvc;
using static EnvelopeGenerator.Web.Constants;
namespace EnvelopeGenerator.Web.Controllers
{
@ -27,7 +26,7 @@ namespace EnvelopeGenerator.Web.Controllers
return Problem(
statusCode: 500,
detail: e.Message,
type: ErrorType.ServerError.ToString());
type: "ServerError");
}
}
}

View File

@ -0,0 +1,15 @@
using DigitalData.Core.API;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Web.Controllers
{
public class ConfigTestController : CRUDControllerBase<ConfigTestController, IConfigService, IConfigRepository, ConfigDto, ConfigDto, ConfigDto, Config, int>
{
public ConfigTestController(ILogger<ConfigTestController> logger, IConfigService service) : base(logger, service)
{
}
}
}

View File

@ -2,6 +2,7 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Web.Services;
using static EnvelopeGenerator.Common.Constants;
using EnvelopeGenerator.Application.Contracts;
namespace EnvelopeGenerator.Web.Controllers
{
@ -9,16 +10,18 @@ namespace EnvelopeGenerator.Web.Controllers
{
private readonly EnvelopeService envelopeService;
private readonly ActionService? actionService;
private readonly IEnvelopeDocumentService _envDocService;
public DocumentController(DatabaseService database, LoggingService logging, EnvelopeService envelope) : base(database, logging)
public DocumentController(DatabaseService database, LoggingService logging, EnvelopeService envelope, IEnvelopeDocumentService envDocService) : base(database, logging)
{
envelopeService = envelope;
actionService = database.Services?.actionService;
_envDocService = envDocService;
}
[HttpGet]
[Route("api/document/{envelopeKey}")]
public async Task<IActionResult> Get(string envelopeKey)
public async Task<IActionResult> Get([FromRoute] string envelopeKey, [FromQuery] int index)
{
try
{
@ -26,11 +29,11 @@ namespace EnvelopeGenerator.Web.Controllers
// Validate Envelope Key and load envelope
envelopeService.EnsureValidEnvelopeKey(envelopeKey);
EnvelopeResponse response = envelopeService.LoadEnvelope(envelopeKey);
EnvelopeResponse response = await envelopeService.LoadEnvelope(envelopeKey);
// Load document info
var Request = ControllerContext.HttpContext.Request;
var document = envelopeService.GetDocument(Request, envelopeKey);
var document = await envelopeService.GetDocument(Request, envelopeKey);
// Load the document from disk
var bytes = await envelopeService.GetDocumentContents(document);
@ -46,7 +49,7 @@ namespace EnvelopeGenerator.Web.Controllers
[HttpPost]
[Route("api/document/{envelopeKey}")]
public IActionResult Open(string envelopeKey)
public async Task<IActionResult> Open(string envelopeKey)
{
try
{
@ -54,7 +57,7 @@ namespace EnvelopeGenerator.Web.Controllers
// Validate Envelope Key and load envelope
envelopeService.EnsureValidEnvelopeKey(envelopeKey);
EnvelopeResponse response = envelopeService.LoadEnvelope(envelopeKey);
EnvelopeResponse response = await envelopeService.LoadEnvelope(envelopeKey);
actionService.OpenEnvelope(response.Envelope, response.Receiver);

View File

@ -17,7 +17,7 @@ namespace EnvelopeGenerator.Web.Controllers
[HttpGet]
[Route("api/envelope/{envelopeKey}")]
public IActionResult Get(string envelopeKey)
public async Task<IActionResult> Get(string envelopeKey)
{
try
{
@ -25,7 +25,7 @@ namespace EnvelopeGenerator.Web.Controllers
// Validate Envelope Key and load envelope
envelopeService.EnsureValidEnvelopeKey(envelopeKey);
EnvelopeResponse response = envelopeService.LoadEnvelope(envelopeKey);
EnvelopeResponse response = await envelopeService.LoadEnvelope(envelopeKey);
if (envelopeService.ReceiverAlreadySigned(response.Envelope, response.Receiver.Id) == true)
{
@ -51,7 +51,7 @@ namespace EnvelopeGenerator.Web.Controllers
// Validate Envelope Key and load envelope
envelopeService.EnsureValidEnvelopeKey(envelopeKey);
EnvelopeResponse response = envelopeService.LoadEnvelope(envelopeKey);
EnvelopeResponse response = await envelopeService.LoadEnvelope(envelopeKey);
// Again check if receiver has already signed
if (envelopeService.ReceiverAlreadySigned(response.Envelope, response.Receiver.Id) == true)

View File

@ -0,0 +1,15 @@
using DigitalData.Core.API;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Web.Controllers
{
public class EnvelopeDocumentTestController : CRUDControllerBase<EnvelopeDocumentTestController, IEnvelopeDocumentService, IEnvelopeDocumentRepository, EnvelopeDocumentDto, EnvelopeDocumentDto, EnvelopeDocumentDto, EnvelopeDocument, int>
{
public EnvelopeDocumentTestController(ILogger<EnvelopeDocumentTestController> logger, IEnvelopeDocumentService service) : base(logger, service)
{
}
}
}

View File

@ -70,11 +70,10 @@ namespace EnvelopeGenerator.Web.Controllers
}
[HttpGet]
[Route("/EnvelopeKey/{EnvelopeReceiverId}")]
public IActionResult ShowEnvelope()
[Route("/EnvelopeKey/{envelopeReceiverId}")]
public async Task<IActionResult> ShowEnvelope([FromRoute] string envelopeReceiverId)
{
string envelopeKey = (string)HttpContext.Request.RouteValues["EnvelopeReceiverId"];
EnvelopeResponse response = _envelopeService.LoadEnvelope(envelopeKey);
EnvelopeResponse response = await _envelopeService.LoadEnvelope(envelopeReceiverId);
if (response.Envelope.UseAccessCode)
{
@ -87,61 +86,46 @@ namespace EnvelopeGenerator.Web.Controllers
bool result = database.Services.emailService.SendDocumentAccessCodeReceivedEmail(response.Envelope, response.Receiver);
}
return Redirect($"/EnvelopeKey/{envelopeKey}/Locked");
return Redirect($"/EnvelopeKey/{envelopeReceiverId}/Locked");
}
else
{
ViewData["EnvelopeKey"] = envelopeKey;
ViewData["EnvelopeKey"] = envelopeReceiverId;
return View();
}
}
[HttpPost]
[Route("/EnvelopeKey/{EnvelopeReceiverId}/Locked")]
public IActionResult ShowEnvelopePost()
[Route("/EnvelopeKey/{envelopeReceiverId}/Locked")]
public async Task<IActionResult> ShowEnvelopePost([FromRoute] string envelopeReceiverId, [FromForm] string access_code)
{
string envelopeKey = (string)HttpContext.Request.RouteValues["EnvelopeReceiverId"];
StringValues accessCodeFromForm = HttpContext.Request.Form["access_code"];
if (accessCodeFromForm.Count == 0)
{
return Redirect($"/EnvelopeKey/{envelopeKey}/Locked");
}
if (accessCodeFromForm.Count > 1)
{
return Redirect($"/EnvelopeKey/{envelopeKey}/Locked");
}
EnvelopeResponse response = _envelopeService.LoadEnvelope(envelopeKey);
EnvelopeResponse response = await _envelopeService.LoadEnvelope(envelopeReceiverId);
string accessCode = response.Receiver.AccessCode;
if (string.IsNullOrEmpty(accessCodeFromForm[0]))
if (string.IsNullOrEmpty(access_code))
{
return Redirect($"/EnvelopeKey/{envelopeKey}/Locked");
return Redirect($"/EnvelopeKey/{envelopeReceiverId}/Locked");
}
if (accessCode.Equals(accessCodeFromForm[0], StringComparison.Ordinal))
if (accessCode.Equals(access_code, StringComparison.Ordinal))
{
bool actionResult = database.Services.actionService.EnterCorrectAccessCode(response.Envelope, response.Receiver);
ViewData["EnvelopeKey"] = envelopeKey;
ViewData["EnvelopeKey"] = envelopeReceiverId;
return View("ShowEnvelope");
}
else
{
bool actionResult = database.Services.actionService.EnterIncorrectAccessCode(response.Envelope, response.Receiver);
return Redirect($"/EnvelopeKey/{envelopeKey}/Locked");
return Redirect($"/EnvelopeKey/{envelopeReceiverId}/Locked");
}
}
[HttpGet]
[Route("/EnvelopeKey/{EnvelopeReceiverId}/Locked")]
public IActionResult EnvelopeLocked()
[Route("/EnvelopeKey/{envelopeReceiverId}/Locked")]
public IActionResult EnvelopeLocked([FromRoute] string envelopeReceiverId)
{
ViewData["EnvelopeKey"] = HttpContext.Request.RouteValues["EnvelopeReceiverId"];
ViewData["EnvelopeKey"] = envelopeReceiverId;
return View();
}

View File

@ -7,24 +7,50 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.15" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.2.5" />
<PackageReference Include="Quartz" Version="3.8.0" />
<PackageReference Include="Quartz.AspNetCore" Version="3.8.0" />
<PackageReference Include="Quartz.Plugins" Version="3.8.0" />
<PackageReference Include="Quartz.Serialization.Json" Version="3.8.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="DevExpress.Data.v21.2">
<HintPath>D:\ProgramFiles\DevExpress 21.2\Components\Bin\Framework\DevExpress.Data.v21.2.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Core.API">
<HintPath>..\..\WebCoreModules\DigitalData.Core.API\bin\Debug\net7.0\DigitalData.Core.API.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Core.Application">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Application\bin\Debug\net7.0\DigitalData.Core.Application.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Core.Contracts">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Contracts\bin\Debug\net7.0\DigitalData.Core.Contracts.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Core.CultureServices">
<HintPath>..\..\WebCoreModules\DigitalData.Core.CultureServices\bin\Debug\net7.0\DigitalData.Core.CultureServices.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Core.Infrastructure">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Infrastructure\bin\Debug\net7.0\DigitalData.Core.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="DigitalData.Modules.Base">
<HintPath>..\..\DDModules\Base\bin\Debug\DigitalData.Modules.Base.dll</HintPath>
</Reference>

View File

@ -1,6 +1,12 @@
using DigitalData.Modules.Logging;
using EnvelopeGenerator.Common;
using DigitalData.Core.CultureServices;
using DigitalData.UserManager.Infrastructure.Repositories;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.MappingProfiles;
using EnvelopeGenerator.Application.Services;
using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Infrastructure.Repositories;
using EnvelopeGenerator.Web.Services;
using Microsoft.EntityFrameworkCore;
using Quartz;
namespace EnvelopeGenerator.Web
@ -13,10 +19,10 @@ namespace EnvelopeGenerator.Web
// Add base services
builder.Services.AddSingleton<LoggingService>();
builder.Services.AddTransient<DatabaseService>();
builder.Services.AddScoped<DatabaseService>();
// Add higher order services
builder.Services.AddSingleton<EnvelopeService>();
builder.Services.AddScoped<EnvelopeService>();
// Add services to the container.
builder.Services.AddControllersWithViews().AddJsonOptions(q =>
@ -25,6 +31,26 @@ namespace EnvelopeGenerator.Web
q.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
});
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddKeyTranslationService();
//AddEF Core dbcontext
var connStr = builder.Configuration["Config:ConnectionString"];
builder.Services.AddDbContext<EGDbContext>(options =>
options.UseSqlServer(connStr));
//Inject CRUD Service and repositories
builder.Services.AddScoped<IConfigRepository, ConfigRepository>();
builder.Services.AddScoped<IEnvelopeDocumentRepository, EnvelopeDocumentRepository>();
builder.Services.AddScoped<IConfigService, ConfigService>();
builder.Services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
//Auto mapping profiles
builder.Services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly);
var app = builder.Build();
// Configure the HTTP request pipeline.
@ -35,6 +61,9 @@ namespace EnvelopeGenerator.Web
app.UseHsts();
}
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseStaticFiles();

View File

@ -23,6 +23,16 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"swagger": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7202;http://localhost:5009",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -1,44 +0,0 @@
using DigitalData.Modules.Base;
using DigitalData.Modules.Logging;
using EnvelopeGenerator.Common;
using Quartz;
using System;
using System.Collections.Specialized;
using System.ComponentModel.DataAnnotations;
namespace EnvelopeGenerator.Web
{
public class Scheduler : BaseClass
{
private const string DATABASE = "DATABASE";
private const string LOGCONFIG = "LOGCONFIG";
private string ConnectionString;
public Scheduler(LogConfig logConfig, string connectionString) : base(logConfig)
{
this.ConnectionString = connectionString;
}
public void ScheduleJob<TJob>(IServiceCollectionQuartzConfigurator q, string name, int interval) where TJob : IJob
{
var jobKey = new JobKey(name);
var jobData = new JobDataMap
{
{ DATABASE, ConnectionString },
{ LOGCONFIG, LogConfig }
};
q.AddJob<TJob>(opts => opts
.WithIdentity(jobKey)
.UsingJobData(jobData));
q.AddTrigger(opts => opts
.ForJob(jobKey)
.WithIdentity($"{name}-trigger")
.WithSimpleSchedule(s => s
.RepeatForever()
.WithIntervalInMinutes(interval)));
}
}
}

View File

@ -1,8 +1,7 @@
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Common;
using Microsoft.Extensions.Primitives;
using System.Reflection.Metadata;
using System.Text;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Web.Services
{
@ -14,7 +13,9 @@ namespace EnvelopeGenerator.Web.Services
private readonly DocumentStatusModel documentStatusModel;
public EnvelopeService(IConfiguration Config, LoggingService Logging, DatabaseService database) : base(Config, Logging)
private IConfigService _configService;
public EnvelopeService(IConfiguration Config, LoggingService Logging, DatabaseService database, IConfigService configService) : base(Config, Logging)
{
logger = Logging.LogConfig.GetLogger();
@ -27,6 +28,8 @@ namespace EnvelopeGenerator.Web.Services
envelopeModel = database.Models.envelopeModel;
historyModel = database.Models.historyModel;
documentStatusModel = database.Models.documentStatusModel;
_configService = configService;
}
public void EnsureValidEnvelopeKey(string envelopeKey)
@ -47,7 +50,7 @@ namespace EnvelopeGenerator.Web.Services
throw new ArgumentNullException("ReceiverSignature");
}
public EnvelopeResponse LoadEnvelope(string pEnvelopeKey)
public async Task<EnvelopeResponse> LoadEnvelope(string pEnvelopeKey)
{
logger.Debug("Loading Envelope by Key [{0}]", pEnvelopeKey);
@ -87,7 +90,30 @@ namespace EnvelopeGenerator.Web.Services
logger.Debug("Loading documents for receiver [{0}]", receiver.Email);
envelope.Documents = FilterElementsByReceiver(envelope, receiverId);
// filter elements by receiver
envelope.Documents = envelope.Documents.Select((document) =>
{
document.Elements = document.Elements.Where((e) => e.ReceiverId == receiverId).ToList();
return document;
}).ToList();
//if documenet_path_dmz is existing in config, replace the path with it
var configResult = await _configService.ReadDefaultAsync();
if (configResult.IsSuccess && configResult.Data is not null)
{
var config = configResult.Data;
if(config.DocumentPathDmz is not null && config.DocumentPathDmz != string.Empty)
foreach(var doc in envelope.Documents)
{
doc.Filepath = doc.Filepath.Replace(config.DocumentPath , config.DocumentPathDmz);
}
}
else
{
logger.Error(configResult.Messages);
throw new InvalidOperationException(String.Join(". ", configResult.Messages));
}
return new()
{
@ -96,18 +122,6 @@ namespace EnvelopeGenerator.Web.Services
};
}
private static List<EnvelopeDocument> FilterElementsByReceiver(Envelope envelope, int receiverId)
{
return envelope.Documents.
Select((document) =>
{
var elements = document.Elements.Where((e) => e.ReceiverId == receiverId);
document.Elements = elements.ToList();
return document;
}).
ToList();
}
public List<Envelope> LoadEnvelopes()
{
var receivers = receiverModel.ListReceivers();
@ -176,9 +190,9 @@ namespace EnvelopeGenerator.Web.Services
return documentIndex;
}
public EnvelopeDocument GetDocument(HttpRequest request, string envelopeKey)
public async Task<EnvelopeDocument> GetDocument(HttpRequest request, string envelopeKey)
{
EnvelopeResponse response = LoadEnvelope(envelopeKey);
EnvelopeResponse response = await LoadEnvelope(envelopeKey);
int documentId = EnsureValidDocumentIndex(request);
logger.Debug("Loading document for Id [{0}]", documentId);

View File

@ -7,7 +7,8 @@
}
},
"Config": {
"ConnectionString": "Server=sDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;",
"ConnectionString": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;",
//preivous connection string without Encrypt=false and TrustServerCertificate=True -> "Server=sDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;"
"LogPath": "E:\\EnvelopeGenerator\\Logs",
"LogDebug": true,
"LogJson": true,

View File

@ -1,9 +1,17 @@
{
"DetailedErrors": true,
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"Config": {
"ConnectionString": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;",
//preivous connection string without Encrypt=false and TrustServerCertificate=True -> "Server=sDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;"
"LogPath": "E:\\EnvelopeGenerator\\Logs",
"LogDebug": true,
"LogJson": true,
"AdminPassword": "dd"
}
}

View File

@ -28,7 +28,7 @@
* @param {any} documentId
*/
async getDocument(envelopeKey, documentId) {
console.log("getDocument")
console.log("getDocument", `/api/document/${envelopeKey}?index=${documentId}`)
return this.getRequest(`/api/document/${envelopeKey}?index=${documentId}`)
.then(this.wrapBinaryResponse.bind(this))
}

View File

@ -13,6 +13,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnvelopeGenerator.Web", "En
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "EnvelopeGenerator.Service", "EnvelopeGenerator.Service\EnvelopeGenerator.Service.vbproj", "{83ED2617-B398-4859-8F59-B38F8807E83E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Domain", "EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj", "{4F32A98D-E6F0-4A09-BD97-1CF26107E837}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Infrastructure", "EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj", "{63E32615-0ECA-42DC-96E3-91037324B7C7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvelopeGenerator.Application", "EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj", "{5A9984F8-51A2-4558-A415-EC5FEED7CF7D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -39,6 +45,18 @@ Global
{83ED2617-B398-4859-8F59-B38F8807E83E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83ED2617-B398-4859-8F59-B38F8807E83E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83ED2617-B398-4859-8F59-B38F8807E83E}.Release|Any CPU.Build.0 = Release|Any CPU
{4F32A98D-E6F0-4A09-BD97-1CF26107E837}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F32A98D-E6F0-4A09-BD97-1CF26107E837}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F32A98D-E6F0-4A09-BD97-1CF26107E837}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F32A98D-E6F0-4A09-BD97-1CF26107E837}.Release|Any CPU.Build.0 = Release|Any CPU
{63E32615-0ECA-42DC-96E3-91037324B7C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63E32615-0ECA-42DC-96E3-91037324B7C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63E32615-0ECA-42DC-96E3-91037324B7C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63E32615-0ECA-42DC-96E3-91037324B7C7}.Release|Any CPU.Build.0 = Release|Any CPU
{5A9984F8-51A2-4558-A415-EC5FEED7CF7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A9984F8-51A2-4558-A415-EC5FEED7CF7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A9984F8-51A2-4558-A415-EC5FEED7CF7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A9984F8-51A2-4558-A415-EC5FEED7CF7D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE