using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Common; using Microsoft.Extensions.Primitives; using System.Text; namespace EnvelopeGenerator.Web.Services { public class EnvelopeService : BaseService { private readonly ReceiverModel receiverModel; private readonly EnvelopeModel envelopeModel; private readonly HistoryModel historyModel; private readonly DocumentStatusModel documentStatusModel; private IConfigService _configService; public EnvelopeService(IConfiguration Config, LoggingService Logging, DatabaseService database, IConfigService configService) : base(Config, Logging) { logger = Logging.LogConfig.GetLogger(); if (database.Models == null) { throw new ArgumentNullException("Models not loaded."); } receiverModel = database.Models.receiverModel; envelopeModel = database.Models.envelopeModel; historyModel = database.Models.historyModel; documentStatusModel = database.Models.documentStatusModel; _configService = configService; } public void EnsureValidEnvelopeKey(string envelopeKey) { logger.Debug("Parsing EnvelopeKey.."); if (string.IsNullOrEmpty(envelopeKey)) throw new ArgumentNullException("EnvelopeKey"); Tuple result = Helpers.DecodeEnvelopeReceiverId(envelopeKey); logger.Debug("EnvelopeUUID: [{0}]", result.Item1); logger.Debug("ReceiverSignature: [{0}]", result.Item2); if (string.IsNullOrEmpty(result.Item1)) throw new ArgumentNullException("EnvelopeUUID"); if (string.IsNullOrEmpty(result.Item2)) throw new ArgumentNullException("ReceiverSignature"); } public async Task LoadEnvelope(string pEnvelopeKey) { logger.Debug("Loading Envelope by Key [{0}]", pEnvelopeKey); Tuple result = Helpers.DecodeEnvelopeReceiverId(pEnvelopeKey); var envelopeUuid = result.Item1; var receiverSignature = result.Item2; var receiverId = receiverModel.GetReceiverIdBySignature(receiverSignature); logger.Debug("Resolved receiver signature to receiverId [{0}]", receiverId); logger.Debug("Loading envelope.."); Envelope? envelope = envelopeModel.GetByUuid(envelopeUuid); if (envelope == null) { logger.Warn("Envelope not found"); throw new NullReferenceException("Envelope not found"); } logger.Debug("Envelope loaded"); if (envelope.Receivers == null) { logger.Warn("Receivers for envelope not loaded"); throw new NullReferenceException("Receivers for envelope not loaded"); } logger.Debug("Envelope receivers found: [{0}]", envelope.Receivers.Count); EnvelopeReceiver? receiver = envelope.Receivers.Where(r => r.Id == receiverId).SingleOrDefault(); if (receiver == null) { logger.Warn("Receiver [{0}] not found", receiverId); throw new NullReferenceException("Receiver not found"); } logger.Debug("Loading documents for receiver [{0}]", receiver.Email); // 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() { Receiver = receiver, Envelope = envelope }; } public List LoadEnvelopes() { var receivers = receiverModel.ListReceivers(); List envelopes = new(); foreach (var receiver in receivers) { var envs = (List)envelopeModel.List(receiver.Id); envelopes.AddRange(envs); } return envelopes; } public List LoadEnvelopes(int pReceiverId) { return (List)envelopeModel.List(pReceiverId); } public bool ReceiverAlreadySigned(Envelope envelope, int receiverId) { return historyModel.HasReceiverSigned(envelope.Id, receiverId); } public async Task EnsureValidAnnotationData(HttpRequest request) { try { logger.Debug("Parsing annotation data from request.."); using MemoryStream ms = new(); await request.BodyReader.CopyToAsync(ms); var bytes = ms.ToArray(); logger.Debug("Annotation data parsed, size: [{0}]", bytes.Length); return Encoding.UTF8.GetString(bytes); } catch (Exception e) { logger.Error(e); throw new ArgumentNullException("AnnotationData"); } } public int EnsureValidDocumentIndex(HttpRequest request) { if (!request.Query.TryGetValue("index", out StringValues documentIndexStringList)) { logger.Warn("There is no query parameter called index"); throw new ArgumentNullException("DocumentIndex"); } if (documentIndexStringList.FirstOrDefault() == null) { logger.Warn("There is no query parameter called index"); throw new ArgumentNullException("DocumentIndex"); } if (!int.TryParse(documentIndexStringList.First(), out int documentIndex)) { logger.Warn("Invalid document index [{0}]", documentIndexStringList.First()); throw new ArgumentNullException("DocumentIndex"); } return documentIndex; } public async Task GetDocument(HttpRequest request, string envelopeKey) { EnvelopeResponse response = await LoadEnvelope(envelopeKey); int documentId = EnsureValidDocumentIndex(request); logger.Debug("Loading document for Id [{0}]", documentId); var document = response.Envelope.Documents. Where(d => d.Id == documentId). FirstOrDefault(); if (document == null) throw new ArgumentException("DocumentId"); logger.Debug("Document [{0}] loaded!", documentId); return document; } public bool InsertDocumentStatus(Common.DocumentStatus documentStatus) { logger.Debug("Saving annotation data.."); return documentStatusModel.InsertOrUpdate(documentStatus); } public async Task GetDocumentContents(EnvelopeDocument document) { logger.Debug("Loading file [{0}]", document.Filepath); var bytes = await File.ReadAllBytesAsync(document.Filepath); logger.Info("File loaded, size: [{0}]", bytes.Length); return bytes; } } }