using DigitalData.Modules.Database; using DigitalData.Modules.Logging; using EnvelopeGenerator.Common; using EnvelopeGenerator.Common.My.Resources; using EnvelopeGenerator.Web.Services; using Microsoft.Extensions.Primitives; using System.IO.Pipelines; using System.Reflection.Metadata.Ecma335; using System.Text; namespace EnvelopeGenerator.Web.Handler { public class FileHandler { /// /// URL: GET /api/envelope/{envelopeKey} /// /// Returns a /// /// public IResult HandleGetEnvelope(HttpContext ctx, DatabaseService database, LoggingService logging) { var logger = logging.LogConfig.GetLogger("FileHandler"); try { logger.Info("Handling envelope loading."); // Load Envelope from EnvelopeKey string envelopeKey = EnsureValidEnvelopeKey(logger, ctx.Request); EnvelopeResponse r = database.LoadEnvelope(envelopeKey); // Return the envelope and additional data as json return Results.Json(r); } catch (Exception e) { // Better error handling & reporting logger.Error(e); return Results.Problem(e.Message); } } /// /// URL: GET /api/document/{envelopeKey}?index={documentIndex} /// /// Returns a document for the supplied EnvelopeKey and Document Id / Index /// /// file buffer of the requested document public async Task HandleGetDocument(HttpContext ctx, DatabaseService database, LoggingService logging) { var logger = logging.LogConfig.GetLogger("FileHandler"); try { logger.Info("Handling file download."); // Load Envelope from EnvelopeKey string envelopeKey = EnsureValidEnvelopeKey(logger, ctx.Request); EnvelopeResponse r = database.LoadEnvelope(envelopeKey); // Get the document Index int documentId = EnsureValidDocumentIndex(logger, ctx.Request); var document = GetDocument(r.Envelope, documentId); // Load the document from disk var bytes = await File.ReadAllBytesAsync(document.Filepath); logger.Info("Serving file, size: [{0}]", bytes.Length); // Return the document as bytes return Results.File(bytes); } catch (Exception e) { // Better error handling & reporting logger.Error(e); return Results.Problem(); } } public async Task HandlePostDocument(HttpContext ctx, DatabaseService database, LoggingService logging) { var logger = logging.LogConfig.GetLogger("FileHandler"); try { logger.Info("Handling file upload."); // Load Envelope from EnvelopeKey string envelopeKey = EnsureValidEnvelopeKey(logger, ctx.Request); EnvelopeResponse r = database.LoadEnvelope(envelopeKey); // Get the document Index int documentId = EnsureValidDocumentIndex(logger, ctx.Request); var document = GetDocument(r.Envelope, documentId); using FileStream fs = new(document.Filepath, FileMode.Open); await ctx.Request.Body.CopyToAsync(fs); fs.Flush(); return Results.Ok(); } catch (Exception e) { // Better error handling & reporting logger.Error(e); return Results.Problem(); } } public async Task HandlePostEnvelope(HttpContext ctx, DatabaseService database, LoggingService logging) { var logger = logging.LogConfig.GetLogger("FileHandler"); try { logger.Info("Handling envelope saving."); // Load Envelope from EnvelopeKey string envelopeKey = EnsureValidEnvelopeKey(logger, ctx.Request); EnvelopeResponse r = database.LoadEnvelope(envelopeKey); // Get the document Index int documentId = EnsureValidDocumentIndex(logger, ctx.Request); var document = GetDocument(r.Envelope, documentId); string? annotationData = await EnsureValidAnnotationData(logger, ctx.Request); if (annotationData == null) { throw new ArgumentNullException("AnnotationData"); } State state = GetState(logging.LogConfig, database.MSSQL); DocumentStatusModel model = new(state); model.InsertOrUpdate(new DocumentStatus() { EnvelopeId = r.Envelope.Id, ReceiverId = r.ReceiverId, Value = annotationData, Status = Common.Constants.DocumentStatus.Signed }); return Results.Ok(); } catch (Exception e) { // Better error handling & reporting logger.Error(e); return Results.Problem(); } } private State GetState(LogConfig LogConfig, MSSQLServer Database) { return new State { LogConfig = LogConfig, Database = Database, }; } private int EnsureValidDocumentIndex(Logger logger, HttpRequest request) { if (request.Query.TryGetValue("index", out StringValues documentIndexString)) { try { return int.Parse(documentIndexString.First()); } catch (Exception e) { throw new ArgumentNullException("DocumentIndex", e); } } else { throw new ArgumentNullException("DocumentIndex"); } } private string EnsureValidEnvelopeKey(Logger logger, HttpRequest request) { logger.Debug("Parsing EnvelopeKey.."); var envelopeKey = request.RouteValues["envelopeKey"] as string; 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"); return envelopeKey; } private async Task EnsureValidAnnotationData(Logger logger, HttpRequest request) { logger.Debug("Parsing AnnotationData.."); try { using MemoryStream ms = new(); await request.BodyReader.CopyToAsync(ms); var bytes = ms.ToArray(); return Encoding.UTF8.GetString(bytes); } catch (Exception e) { logger.Error(e); return null; } } private EnvelopeDocument GetDocument(Common.Envelope envelope, int documentId) { var document = envelope.Documents. Where(d => d.Id == documentId). FirstOrDefault(); if (document == null) throw new ArgumentException("DocumentId"); return document; } } }