diff --git a/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs index 1069795..e97bd90 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs @@ -8,10 +8,16 @@ var builder = WebApplication.CreateBuilder(args); // Add services to the container. +// CORS setup to allow requests from any origin. +builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { + build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); +})); + builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); +// Add Swagger/OpenAPI documentation support. builder.Services.AddSwaggerGen(c => { // Include XML comments from your assembly @@ -32,16 +38,23 @@ builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { var app = builder.Build(); - // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } +<<<<<<< HEAD app.UseCors("DamageAppCorsPolicy"); app.UseAuthorization(); +======= +>>>>>>> 9ec9b8b96fc7c5767fcddf1e4e52bde203fcf619 + +// Enable CORS, authentication, and authorization middleware. +app.UseCors("DamageAppCorsPolicy"); +app.UseAuthorization(); +// Map controllers to their respective routes. app.MapControllers(); app.Run(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs index 16c223c..e2fbe25 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs @@ -136,6 +136,80 @@ namespace DamageAssesment.Api.Attachments.Controllers } } /// + /// download an existing attachment. + /// + [HttpGet("attachments/download/{id}")] + public async Task downloadfile(int id) + { + try + { + var result = await this.AttachmentProvider.GetDownloadAttachmentAsync(id); + if (!result.IsSuccess) + return NotFound(); + string path = await UploadService.GetFile(result.Attachment.URI); + if (path == null) + return NotFound(); + var contentType = GetContentType(result.Attachment.FileName); + if (contentType == "application/octet-stream") + return PhysicalFile(path, contentType, result.Attachment.FileName); + return PhysicalFile(path, contentType, enableRangeProcessing: true);// result.Attachment.FileName); + } + catch (Exception ex) + { + // Handle the exception here or log it + return StatusCode(500, "An error occurred: " + ex.Message); + } + //try + //{ + // var result = await this.AttachmentProvider.GetDownloadAttachmentAsync(id); + // if(!result.IsSuccess) + // return NotFound(); + // byte[] fileContent = await UploadService.DownloadFile(result.Attachment.URI); + // if (fileContent == null || fileContent.Length == 0) + // return NotFound(); + // var contentType = "application/octet-stream"; + // return File(fileContent, contentType, result.Attachment.FileName); + //} + //catch (Exception ex) + //{ + // // Handle the exception here or log it + // return StatusCode(500, "An error occurred: " + ex.Message); + //} + } + private string GetContentType(string fileName) + { + // You can add more content types based on the file extensions + switch (Path.GetExtension(fileName).ToLower()) + { + //case ".txt": + // return "text/plain"; + case ".jpg": + case ".jpeg": + return "image/jpeg"; + case ".png": + return "image/png"; + case ".gif": + return "image/gif"; + case ".bmp": + return "image/bmp"; + case ".webp": + return "image/webp"; + case ".csv": + return "text/csv"; + case ".pdf": + return "application/pdf"; + case ".docx": + case ".doc": + return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + case ".xlsx": + case ".xls": + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + // Add more cases as needed + default: + return "application/octet-stream"; + } + } + /// /// Delete an existing attachment. /// [HttpDelete("attachments/{id}")] diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAttachmentsProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAttachmentsProvider.cs index 5e56dbb..06c4ead 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAttachmentsProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAttachmentsProvider.cs @@ -9,6 +9,7 @@ namespace DamageAssesment.Api.Attachments.Interfaces Task<(bool IsSuccess, IEnumerable Attachments, string ErrorMessage)> PostAttachmentAsync(List Attachments); Task<(bool IsSuccess, IEnumerable Attachments, string ErrorMessage)> PutAttachmentAsync(List Attachments); Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> DeleteAttachmentAsync(int Id); + Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> GetDownloadAttachmentAsync(int Id); Task<(bool IsSuccess, int counter, string Path)> DeleteAttachmentsAsync(int responseId, int answerId); Task<(bool IsSuccess, int counter, string Path)> DeleteBulkAttachmentsAsync(int responseId, List answerIds); Task<(bool IsSuccess, int counter, string message)> GetAttachmentCounter(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IUploadService.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IUploadService.cs index f645593..1d2d0e0 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IUploadService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IUploadService.cs @@ -7,6 +7,8 @@ namespace DamageAssesment.Api.Attachments.Interfaces List UploadAttachment(int responseId,int answerId, int counter, List postedFile); List UploadAttachment(int responseId, int counter, List answers); public List UpdateAttachments(int responseId, List answers, IEnumerable attachments); + Task DownloadFile(string path); + Task GetFile(string path); void Deletefile(string path); void Movefile(string path); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Program.cs index 3c5a440..ba0f71c 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Program.cs @@ -8,12 +8,18 @@ using System.Reflection; var builder = WebApplication.CreateBuilder(args); +// CORS setup to allow requests from any origin. +builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { + build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); +})); + // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); +// Add Swagger/OpenAPI documentation support. builder.Services.AddSwaggerGen(c => { // Include XML comments from your assembly @@ -21,6 +27,7 @@ builder.Services.AddSwaggerGen(c => var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); +builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -47,6 +54,11 @@ if (app.Environment.IsDevelopment()) app.UseSwagger(); app.UseSwaggerUI(); } +<<<<<<< HEAD +======= + +// Enable CORS, authentication, and authorization middleware. +>>>>>>> 9ec9b8b96fc7c5767fcddf1e4e52bde203fcf619 app.UseCors("DamageAppCorsPolicy"); app.UseAuthorization(); app.UseHttpsRedirection(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AttachmentsProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AttachmentsProvider.cs index 92c20e5..f409654 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AttachmentsProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AttachmentsProvider.cs @@ -13,25 +13,33 @@ namespace DamageAssesment.Api.Attachments.Providers private AttachmentsDbContext AttachmentDbContext; private ILogger logger; private IUploadService uploadservice; - private IMapper mapper; - - public AttachmentsProvider(AttachmentsDbContext AttachmentDbContext, ILogger logger, IMapper mapper,IUploadService uploadservice) + private IMapper mapper; + private readonly IHttpContextAccessor httpContextAccessor; + private string baseUrl; + public AttachmentsProvider(AttachmentsDbContext AttachmentDbContext, ILogger logger, IMapper mapper,IUploadService uploadservice, IHttpContextAccessor httpContextAccessor) { this.AttachmentDbContext = AttachmentDbContext; this.logger = logger; this.mapper = mapper; this.uploadservice = uploadservice; + this.httpContextAccessor = httpContextAccessor; + baseUrl = $"{httpContextAccessor.HttpContext.Request.Scheme}://{httpContextAccessor.HttpContext.Request.Host}"; + baseUrl = baseUrl + "/attachments/download"; //SeedData(); } public async Task<(bool IsSuccess, IEnumerable Attachments, string ErrorMessage)> GetAttachmentsAsync() { - + try { logger?.LogInformation("Query Question"); var Attachment = await AttachmentDbContext.Attachments.AsNoTracking().Where(a => !a.IsDeleted).ToListAsync(); if (Attachment != null) { + foreach (var attachment in Attachment) + { + attachment.URI = $"{baseUrl}/{attachment.Id}"; + } logger?.LogInformation($"{Attachment.Count} Attachments(s) found"); var result = mapper.Map, IEnumerable>(Attachment); return (true, result, null); @@ -54,6 +62,7 @@ namespace DamageAssesment.Api.Attachments.Providers if (Attachment != null) { logger?.LogInformation($"{Attachment} customer(s) found"); + Attachment.URI = $"{baseUrl}/{Attachment.Id}"; var result = mapper.Map(Attachment); return (true, result, null); } @@ -73,6 +82,10 @@ namespace DamageAssesment.Api.Attachments.Providers List attachments = mapper.Map, List>(Attachments); AttachmentDbContext.Attachments.AddRange(attachments); await AttachmentDbContext.SaveChangesAsync(); + foreach (var attachment in attachments) + { + attachment.URI = $"{baseUrl}/{attachment.Id}"; + } var result = mapper.Map, IEnumerable>(attachments); return (true, result, null); } @@ -91,6 +104,10 @@ namespace DamageAssesment.Api.Attachments.Providers List attachments = mapper.Map, List>(Attachments); AttachmentDbContext.Attachments.UpdateRange(attachments); await AttachmentDbContext.SaveChangesAsync(); + foreach (var attachment in attachments) + { + attachment.URI = $"{baseUrl}/{attachment.Id}"; + } var result = mapper.Map, IEnumerable>(attachments); return (true, result, null); } @@ -197,6 +214,24 @@ namespace DamageAssesment.Api.Attachments.Providers { return AttachmentDbContext.Attachments.AsNoTracking().Count(e => e.Id == id && !e.IsDeleted) > 0; } + public async Task<(bool IsSuccess, Models.Attachment Attachment, string Path)> GetDownloadAttachmentAsync(int Id) + { + try + { + Db.Attachment Attachment = AttachmentDbContext.Attachments.Where(a => a.Id == Id).AsNoTracking().FirstOrDefault(); + if (Attachment == null) + { + return (false, null, "Not Found"); + } + return (true, mapper.Map(Attachment), $"Attachment {Id}"); + } + catch (Exception ex) + { + + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } private void SeedData() { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/UploadService.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/UploadService.cs index 8c9045c..09711b5 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/UploadService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/UploadService.cs @@ -24,6 +24,41 @@ namespace DamageAssesment.Api.Attachments.Providers uploadpath = configuration.GetValue("Fileupload:folderpath"); Deletepath = configuration.GetValue("Fileupload:Deletepath"); } + public async Task GetFile(string path) + { + try + { + if (System.IO.File.Exists(path)) + { + return path; + } + + return null; // File not found + } + catch (Exception ex) + { + // Handle or log the exception as needed + throw; + } + + } + public async Task DownloadFile(string path) + { + try + { + if (System.IO.File.Exists(path)) + { + return await System.IO.File.ReadAllBytesAsync(path); + } + + return null; // File not found + } + catch (Exception ex) + { + // Handle or log the exception as needed + throw; + } + } public List UploadAttachment(int responseId,int answerId,int counter, List postedFile) { var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), uploadpath); @@ -89,7 +124,7 @@ namespace DamageAssesment.Api.Attachments.Providers { counter++; - var UserfileName = Path.GetFileName(file.FileName); + var UserfileName = Path.GetFileName(file.FileName+ file.FileExtension); var fileName = String.Format("Attachment_{0}{1}", counter, file.FileExtension); var dbPath = Path.Combine(fullDirectoryPath, fileName); File.WriteAllBytes(dbPath, Convert.FromBase64String(file.FileContent)); @@ -126,7 +161,7 @@ namespace DamageAssesment.Api.Attachments.Providers foreach (var file in item.postedFiles) { Models.Attachment attachment= attachments.Where(a=>a.Id == file.AttachmentId).FirstOrDefault(); - var UserfileName = Path.GetFileName(file.FileName); + var UserfileName = Path.GetFileName(file.FileName + file.FileExtension); var fileName = String.Format("Attachment_{0}{1}", attachment?.Id, file.FileExtension); var dbPath = Path.Combine(fullDirectoryPath, fileName); File.WriteAllBytes(dbPath, Convert.FromBase64String(file.FileContent)); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs index a8f45d1..e30925f 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs @@ -197,7 +197,29 @@ namespace DamageAssesment.Api.DocuLinks.Test var result = (NotFoundResult)await DocumentProvider.DeleteDocument(1); Assert.Equal(404, result.StatusCode); } + [Fact(DisplayName = "Update Document IsActive- Ok case")] + public async Task UpdateDocumentAsync_ShouldReturnStatusCode200() + { + var mockDocumentService = new Mock(); + var mockUploadService = new Mock(); + var mockResponse = await MockData.getOkResponse(1); + mockDocumentService.Setup(service => service.UpdateDocumentAsync(1,true)).ReturnsAsync(mockResponse); + var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); + var result = (OkObjectResult)await DocumentProvider.UpdateIsActiveDocument(1,true); + Assert.Equal(200, result.StatusCode); + } + [Fact(DisplayName = "Update Document IsActive - NotFound case")] + public async Task UpdateDocumentAsync_ShouldReturnStatusCode404() + { + var mockDocumentService = new Mock(); + var mockUploadService = new Mock(); + var mockResponse = await MockData.getNotFoundResponse(); + mockDocumentService.Setup(service => service.UpdateDocumentAsync(1,true)).ReturnsAsync(mockResponse); + var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); + var result = (NotFoundResult)await DocumentProvider.UpdateIsActiveDocument(1,true); + Assert.Equal(404, result.StatusCode); + } // Link Type Test cases diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs index 843b4d3..0466fa8 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs @@ -32,7 +32,8 @@ namespace DamageAssesment.Api.DocuLinks.Test doclinksAttachments.Add(new DoculinkAttachments() { docName = "",Path="www.google.com", - IsAttachments=false,CustomOrder=1 + Language = "en", + IsAttachments =false,CustomOrder=1 }); list.Add(new DocuLinks.Models.ResDoculink() { @@ -74,6 +75,7 @@ namespace DamageAssesment.Api.DocuLinks.Test docName = "", Path = "www.google.com", IsAttachments = false, + Language = "en", CustomOrder = 1 }); list.Add(new DocuLinks.Models.ResDoculink() @@ -138,6 +140,7 @@ namespace DamageAssesment.Api.DocuLinks.Test docName = "", Path = "www.google.com", IsAttachments = false, + Language = "en", CustomOrder = 1 }); return new Models.Doculink @@ -165,6 +168,7 @@ namespace DamageAssesment.Api.DocuLinks.Test docName = "", Path = "www.google.com", IsAttachments = false, + Language = "en", CustomOrder = 1 }); List DocuLinks = new List(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs index 99d00a8..4cee929 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs @@ -13,11 +13,11 @@ namespace DamageAssesment.Api.DocuLinks.Controllers private readonly IDoculinkProvider documentsProvider; private readonly IUploadService uploadService; - public DoculinkController(IDoculinkProvider documentsProvider,IUploadService uploadService) + public DoculinkController(IDoculinkProvider documentsProvider, IUploadService uploadService) { this.documentsProvider = documentsProvider; - this.uploadService = uploadService; + this.uploadService = uploadService; } /// @@ -41,7 +41,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers [HttpGet] [Route("doculinks/types/{id}")] [Route("doculinks/types/{id}/{language:alpha}")] - public async Task GetLinkTypeAsync(int id,string? language) + public async Task GetLinkTypeAsync(int id, string? language) { var result = await this.documentsProvider.GetLinkTypeAsync(id, language); if (result.IsSuccess) @@ -55,11 +55,11 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// [HttpPut] [Route("doculinks/types/{id}")] - public async Task UpdateLinkType(int id,Models.LinkType linkType) + public async Task UpdateLinkType(int id, Models.LinkType linkType) { if (linkType != null) { - var result = await this.documentsProvider.UpdateLinkTypeAsync(id,linkType); + var result = await this.documentsProvider.UpdateLinkTypeAsync(id, linkType); if (result.IsSuccess) { return Ok(result.LinkType); @@ -104,6 +104,80 @@ namespace DamageAssesment.Api.DocuLinks.Controllers return NotFound(); } /// + /// download an existing attachment. + /// + [HttpGet("doculinks/download/{id}")] + public async Task downloadfile(int id) + { + try + { + var result = await this.documentsProvider.GetDownloadAttachmentAsync(id); + if (!result.IsSuccess) + return NotFound(); + string path = await uploadService.GetFile(result.DoculinkAttachments.Path); + if (path == null) + return NotFound(); + var contentType = GetContentType(result.DoculinkAttachments.docName); + if (contentType == "application/octet-stream") + return PhysicalFile(path, contentType, result.DoculinkAttachments.docName); + return PhysicalFile(path, contentType, enableRangeProcessing: true); + } + catch (Exception ex) + { + // Handle the exception here or log it + return StatusCode(500, "An error occurred: " + ex.Message); + } + //try + //{ + // var result = await this.documentsProvider.GetDownloadAttachmentAsync(id); + // if (!result.IsSuccess) + // return NotFound(); + // byte[] fileContent = await uploadService.DownloadFile(result.DoculinkAttachments.Path); + // if (fileContent == null || fileContent.Length == 0) + // return NotFound(); + // var contentType = "application/octet-stream"; + // return File(fileContent, contentType, result.DoculinkAttachments.docName); + //} + //catch (Exception ex) + //{ + // // Handle the exception here or log it + // return StatusCode(500, "An error occurred: " + ex.Message); + //} + } + private string GetContentType(string fileName) + { + // You can add more content types based on the file extensions + switch (Path.GetExtension(fileName).ToLower()) + { + //case ".txt": + // return "text/plain"; + case ".jpg": + case ".jpeg": + return "image/jpeg"; + case ".png": + return "image/png"; + case ".gif": + return "image/gif"; + case ".bmp": + return "image/bmp"; + case ".webp": + return "image/webp"; + case ".csv": + return "text/csv"; + case ".pdf": + return "application/pdf"; + case ".docx": + case ".doc": + return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + case ".xlsx": + case ".xls": + return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + // Add more cases as needed + default: + return "application/octet-stream"; + } + } + /// /// Get all Doculink. /// /// @@ -111,7 +185,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers [Route("doculinks/{linktype:alpha}")] [Route("doculinks/{linktype:alpha}/{language:alpha}")] [HttpGet] - public async Task GetDocumentsAsync(string? linktype, string? language,bool? isactive) + public async Task GetDocumentsAsync(string? linktype, string? language, bool? isactive) { var result = await this.documentsProvider.GetdocumentsByLinkAsync(linktype, language, isactive); if (result.IsSuccess) @@ -129,7 +203,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers [HttpGet] public async Task GetDocumentsByActiveAsync(string? linktype, string? language) { - var result = await this.documentsProvider.GetdocumentsByLinkAsync(linktype, language,true); + var result = await this.documentsProvider.GetdocumentsByLinkAsync(linktype, language, true); if (result.IsSuccess) { return Ok(result.documents); @@ -158,7 +232,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers [Route("doculinks/{id}")] [Route("doculinks/{id}/{linktype:alpha}")] [Route("doculinks/{id}/{linktype:alpha}/{language:alpha}")] - public async Task GetDocumentAsync(int id,string? linktype, string? language) + public async Task GetDocumentAsync(int id, string? linktype, string? language) { var result = await this.documentsProvider.GetDocumentAsync(id, linktype, language); if (result.IsSuccess) @@ -172,7 +246,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// [HttpPut] [Route("doculinks/{id}")] - public async Task UpdateDocument(int id,ReqDoculink documentInfo) + public async Task UpdateDocument(int id, ReqDoculink documentInfo) { if (documentInfo != null) { @@ -180,7 +254,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers if (dbdoc.IsSuccess) { var documents = await this.documentsProvider.GetDocumentCounter(); - Models.Doculink DocuLink= uploadService.UpdateDocuments(documents.counter,dbdoc.Document, documentInfo); + Models.Doculink DocuLink = uploadService.UpdateDocuments(documents.counter, dbdoc.Document, documentInfo); var result = await this.documentsProvider.UpdateDocumentAsync(id, DocuLink); if (result.IsSuccess) { @@ -193,6 +267,20 @@ namespace DamageAssesment.Api.DocuLinks.Controllers return BadRequest(documentInfo); } /// + /// update existing doclink isactive field. + /// + [HttpPut] + [Route("doculinks/{id}/{isactive}")] + public async Task UpdateIsActiveDocument(int id, bool isactive) + { + var result = await this.documentsProvider.UpdateDocumentAsync(id, isactive); + if (result.IsSuccess) + { + return Ok(result.Document); + } + return NotFound(); + } + /// /// Create new doclink. /// [HttpPost] @@ -204,7 +292,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers if (documentInfo != null) { var documents = await this.documentsProvider.GetDocumentCounter(); - Models.Doculink DocuLink= uploadService.UploadDocument(documents.counter, documentInfo); + Models.Doculink DocuLink = uploadService.UploadDocument(documents.counter, documentInfo); var result = await this.documentsProvider.PostDocumentAsync(DocuLink); if (result.IsSuccess) { @@ -239,6 +327,6 @@ namespace DamageAssesment.Api.DocuLinks.Controllers } return NotFound(); } - + } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkAttachments.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkAttachments.cs index b6eac5c..f277570 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkAttachments.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkAttachments.cs @@ -15,5 +15,6 @@ namespace DamageAssesment.Api.DocuLinks.Db public string Path { get; set; } public bool IsAttachments { get; set; } public int CustomOrder { get; set; } + public string Language { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs index e9717ee..d873bbe 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs @@ -11,7 +11,9 @@ namespace DamageAssesment.Api.DocuLinks.Interfaces Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive); Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> PostDocumentAsync(Models.Doculink Document); Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> UpdateDocumentAsync(int id, Models.Doculink Document); + Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> UpdateDocumentAsync(int id, bool isactive); Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> DeleteDocumentAsync(int id); + Task<(bool IsSuccess, Models.DoculinkAttachments DoculinkAttachments, string Path)> GetDownloadAttachmentAsync(int id); Task<(bool IsSuccess, int counter, string message)> GetDocumentCounter(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IUploadService.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IUploadService.cs index 4219fd6..63c00aa 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IUploadService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IUploadService.cs @@ -7,6 +7,8 @@ namespace DamageAssesment.Api.DocuLinks.Interfaces Models.Doculink UploadDocument( int counter, ReqDoculink documentInfo); public Models.Doculink UpdateDocuments(int counter, Models.Doculink document, ReqDoculink documentInfo); void Deletefile(string path); + Task DownloadFile(string path); + Task GetFile(string path); void Movefile(string path); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/DoculinkAttachments.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/DoculinkAttachments.cs index ce87857..04a6970 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/DoculinkAttachments.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/DoculinkAttachments.cs @@ -8,6 +8,7 @@ namespace DamageAssesment.Api.DocuLinks.Models public string docName { get; set; } public string Path { get; set; } public bool IsAttachments { get; set; } + public string Language { get; set; } public int CustomOrder { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/ReqDoculink.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/ReqDoculink.cs index 0f2ea17..b2c129d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/ReqDoculink.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/ReqDoculink.cs @@ -7,6 +7,7 @@ namespace DamageAssesment.Api.DocuLinks.Models public int Id { get; set; } public int linkTypeId { get; set; } public List documentsTranslations { get; set; } + public bool IsActive { get; set; } public int CustomOrder { get; set; } public List? Files { get; set; } } @@ -18,5 +19,6 @@ namespace DamageAssesment.Api.DocuLinks.Models public int CustomOrder { get; set; } public string url { get;set; } public bool IsAttachments { get; set; } + public string Language { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs index 5dcf1ed..e7fe14c 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs @@ -6,6 +6,11 @@ using System.Reflection; var builder = WebApplication.CreateBuilder(args); +// CORS setup to allow requests from any origin. +builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { + build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); +})); + // Add services to the container. builder.Services.AddControllers(); @@ -19,6 +24,7 @@ builder.Services.AddSwaggerGen(c => // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -38,6 +44,12 @@ if (app.Environment.IsDevelopment()) app.UseSwagger(); app.UseSwaggerUI(); } +<<<<<<< HEAD +======= + + +// Enable CORS, authentication, and authorization middleware. +>>>>>>> 9ec9b8b96fc7c5767fcddf1e4e52bde203fcf619 app.UseCors("DamageAppCorsPolicy"); app.UseAuthorization(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs index 01ec9cf..b7c119d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs @@ -2,13 +2,16 @@ using DamageAssesment.Api.DocuLinks.Db; using DamageAssesment.Api.DocuLinks.Interfaces; using DamageAssesment.Api.DocuLinks.Models; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Internal; using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.Eventing.Reader; using System.Reflection.Metadata; +using System.Runtime.CompilerServices; using System.Xml; using System.Xml.Linq; @@ -22,13 +25,18 @@ namespace DamageAssesment.Api.DocuLinks.Providers private ILogger logger; private IUploadService uploadservice; private IMapper mapper; + private readonly IHttpContextAccessor httpContextAccessor; + private string baseUrl; - public DoculinkProvider(DoculinkDbContext DocumentDbContext, ILogger logger, IMapper mapper, IUploadService uploadservice) + public DoculinkProvider(DoculinkDbContext DocumentDbContext, ILogger logger, IMapper mapper, IUploadService uploadservice, IHttpContextAccessor httpContextAccessor) { this.DocumentDbContext = DocumentDbContext; this.logger = logger; this.mapper = mapper; this.uploadservice = uploadservice; + this.httpContextAccessor = httpContextAccessor; + baseUrl = $"{httpContextAccessor.HttpContext.Request.Scheme}://{httpContextAccessor.HttpContext.Request.Host}"; + baseUrl = baseUrl + "/doculinks/download"; SeedData(); } @@ -71,10 +79,10 @@ namespace DamageAssesment.Api.DocuLinks.Providers { linkTypeId = 1; - fileModel = new FileModel() { FileName = "Sample" + i, FileExtension = ".txt", FileContent = "c2FtcGxl", IsAttachments = true, CustomOrder = 1 }; + fileModel = new FileModel() { FileName = "Sample" + i, FileExtension = ".txt", FileContent = "c2FtcGxl", IsAttachments = true, CustomOrder = 1, Language = "en" }; } else - fileModel = new FileModel() { url = "www.google" + i + ".com", IsAttachments = false, CustomOrder = 1 }; + fileModel = new FileModel() { url = "www.google" + i + ".com", IsAttachments = false, CustomOrder = 1,Language="en" }; ReqDoculink documentInfo = new ReqDoculink() { linkTypeId = i, CustomOrder = i, Files = new List() { fileModel } }; Models.Doculink document = uploadservice.UploadDocument(counter, documentInfo); DocumentDbContext.Documents.Add(mapper.Map(document)); @@ -170,7 +178,42 @@ namespace DamageAssesment.Api.DocuLinks.Providers MultiLanguage = dicttitle; return MultiLanguage; } + private List GetDocumentAttachment(int id,string? language) + { + List doculinkAttachments = null; + if (string.IsNullOrEmpty(language)) + { + doculinkAttachments = DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList(); + } + else + { + doculinkAttachments = DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id && a.Language == language).ToList(); + } + foreach (var attachment in doculinkAttachments) + { + if (attachment.IsAttachments) + attachment.Path = $"{baseUrl}/{attachment.Id}"; + } + return mapper.Map, List>(doculinkAttachments); + } + public async Task<(bool IsSuccess, Models.DoculinkAttachments DoculinkAttachments, string Path)> GetDownloadAttachmentAsync(int id) + { + try + { + Db.DoculinkAttachments Attachment = DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.Id == id).AsNoTracking().FirstOrDefault(); + if (Attachment == null) + { + return (false, null, "Not Found"); + } + return (true, mapper.Map(Attachment), $"Attachment {id}"); + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive) { @@ -192,8 +235,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers item.titles = multilan.titles; item.description = multilan.description; item.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(item.linkTypeId, language)); - item.doclinksAttachments = mapper.Map, List>( - DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == item.Id).ToList()); + item.doclinksAttachments = GetDocumentAttachment(item.Id,language); } // List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); return (true, result, null); @@ -228,8 +270,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers item.titles = multilan.titles; item.description = multilan.description; item.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(item.linkTypeId, language)); - item.doclinksAttachments = mapper.Map, List>( - DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == item.Id).ToList()); + item.doclinksAttachments = GetDocumentAttachment(item.Id, language); } //List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); return (true, result, null); @@ -284,8 +325,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers result.documentsTranslations = mapper.Map, List>( DocumentDbContext.DocumentsTranslations.Where(a => a.DocumentId == result.Id).ToList()); - result.doclinksAttachments = mapper.Map, List>( - DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList()); + result.doclinksAttachments = GetDocumentAttachment(id, ""); return (true, result, null); } return (false, null, "Not found"); @@ -317,8 +357,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(result.linkTypeId, language)); result.titles = multilan.titles; result.description = multilan.description; - result.doclinksAttachments = mapper.Map, List>( - DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList()); + result.doclinksAttachments = GetDocumentAttachment(id, language); return (true, result, null); } return (false, null, "Not found"); @@ -349,7 +388,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(Document.linkTypeId, "")); result.titles = multilan.titles; result.description = multilan.description; - result.doclinksAttachments = Document.doclinksAttachments; + result.doclinksAttachments = GetDocumentAttachment(document.Id,""); return (true, result, null); } catch (Exception ex) @@ -391,7 +430,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(document.linkTypeId, "")); result.titles = multilan.titles; result.description = multilan.description; - result.doclinksAttachments = Document.doclinksAttachments; + result.doclinksAttachments = GetDocumentAttachment(document.Id, ""); return (true, result, "Successful"); } else @@ -414,6 +453,35 @@ namespace DamageAssesment.Api.DocuLinks.Providers return (false, null, ex.Message); } } + public async Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> UpdateDocumentAsync(int id,bool isactive) + { + + try + { + Db.Doculink Document = DocumentDbContext.Documents.AsNoTracking().Where(a => a.Id == id).FirstOrDefault(); + if (Document == null) + { + return (false, null, "Not Found"); + } + Document.IsActive = isactive; + DocumentDbContext.Documents.Update(Document); + DocumentDbContext.SaveChanges(); + var result = mapper.Map(Document); + var multilan = CreateMultiLanguageObject(GetDocumentTranslations(Document.Id, "")); + result.titles = multilan.titles; + result.description = multilan.description; + result.linktypes = CreateMultiLanguageLinkTypeObject(GetLinkTypeTranslations(result.linkTypeId, "")); + result.doclinksAttachments = mapper.Map, List>( + DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == id).ToList()); + return (true, result, $"DocumentId {id} deleted Successfuly"); + } + catch (Exception ex) + { + + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } public async Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> DeleteDocumentAsync(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs index 807a2e0..a916a1b 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs @@ -25,6 +25,41 @@ namespace DamageAssesment.Api.DocuLinks.Providers uploadpath = configuration.GetValue("Fileupload:folderpath"); Deletepath = configuration.GetValue("Fileupload:Deletepath"); } + public async Task GetFile(string path) + { + try + { + if (System.IO.File.Exists(path)) + { + return path; + } + + return null; // File not found + } + catch (Exception ex) + { + // Handle or log the exception as needed + throw; + } + + } + public async Task DownloadFile(string path) + { + try + { + if (System.IO.File.Exists(path)) + { + return await System.IO.File.ReadAllBytesAsync(path); + } + + return null; // File not found + } + catch (Exception ex) + { + // Handle or log the exception as needed + throw; + } + } public Models.Doculink UploadDocument(int counter, ReqDoculink documentInfo) { @@ -44,19 +79,20 @@ namespace DamageAssesment.Api.DocuLinks.Providers counter++; if (item.IsAttachments) { - UserfileName = Path.GetFileName(item.FileName); + UserfileName = Path.GetFileName(item.FileName + item.FileExtension); var fileName = String.Format("Document_{0}{1}", counter, item.FileExtension); path = Path.Combine(fullDirectoryPath, fileName); File.WriteAllBytes(path, Convert.FromBase64String(item.FileContent)); } else path = item.url; - attachments.Add(new Models.DoculinkAttachments { docName=UserfileName,Path=path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder }); + attachments.Add(new Models.DoculinkAttachments { docName=UserfileName,Path=path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder,Language=item.Language }); } } Documents=new Models.Doculink (){ linkTypeId = documentInfo.linkTypeId, documentsTranslations = documentInfo.documentsTranslations,doclinksAttachments=attachments, - IsDeleted=false,CustomOrder=documentInfo.CustomOrder, IsActive =true}; + IsDeleted=false,CustomOrder=documentInfo.CustomOrder, IsActive =documentInfo.IsActive + }; return Documents; } @@ -85,21 +121,21 @@ namespace DamageAssesment.Api.DocuLinks.Providers counter++; if (item.IsAttachments) { - UserfileName = Path.GetFileName(item.FileName); + UserfileName = Path.GetFileName(item.FileName+item.FileExtension); var fileName = String.Format("Document_{0}{1}", counter, item.FileExtension); path = Path.Combine(fullDirectoryPath, fileName); File.WriteAllBytes(path, Convert.FromBase64String(item.FileContent)); } else path = item.url; - attachments.Add(new Models.DoculinkAttachments { docName = UserfileName, Path = path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder }); + attachments.Add(new Models.DoculinkAttachments { docName = UserfileName, Path = path,IsAttachments=item.IsAttachments,CustomOrder=item.CustomOrder,Language=item.Language }); } Models.Doculink Documents = new Models.Doculink() { Id = documentInfo.Id, linkTypeId = documentInfo.linkTypeId, documentsTranslations=documentInfo.documentsTranslations, - IsActive = true, + IsActive = documentInfo.IsActive, IsDeleted=false, CustomOrder = documentInfo.CustomOrder, doclinksAttachments = attachments diff --git a/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs index c93eb2e..01d561b 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs @@ -6,12 +6,18 @@ using System.Reflection; var builder = WebApplication.CreateBuilder(args); -// Add services to the container. +// CORS setup to allow requests from any origin. +builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { + build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); +})); + + +// Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); -//builder.Services.AddSwaggerGen(); +// Add Swagger/OpenAPI documentation support. builder.Services.AddSwaggerGen(c => { // Include XML comments from your assembly @@ -44,7 +50,14 @@ if (app.Environment.IsDevelopment()) employeesProvider.SeedData(); } } +<<<<<<< HEAD app.UseCors("DamageAppCorsPolicy"); +======= + +// Enable CORS, authentication, and authorization middleware. +app.UseCors("DamageAppCorsPolicy"); + +>>>>>>> 9ec9b8b96fc7c5767fcddf1e4e52bde203fcf619 app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Employees/Providers/EmployeesProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Employees/Providers/EmployeesProvider.cs index b1741be..a071ab9 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Employees/Providers/EmployeesProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Employees/Providers/EmployeesProvider.cs @@ -77,7 +77,8 @@ namespace DamageAssesment.Api.Employees.Providers EmployeeDbContext.Employees.Add(_employee); Employee.Id = _employee.Id; EmployeeDbContext.SaveChanges(); - return (true, Employee, null); + //return (true, Employee, null); + return (true, mapper.Map(_employee), null); } return (false, null, "Employee code is already exits"); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs index 22457e4..d2ef35b 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs @@ -5,13 +5,18 @@ using Microsoft.EntityFrameworkCore; using System.Reflection; var builder = WebApplication.CreateBuilder(args); +// CORS setup to allow requests from any origin. +builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { + build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); +})); + // Add services to the container. - +// Add controller services and API Explorer for endpoint discovery. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); -//builder.Services.AddSwaggerGen(); +// Add Swagger/OpenAPI documentation support. builder.Services.AddSwaggerGen(c => { // Include XML comments from your assembly @@ -46,7 +51,14 @@ if (app.Environment.IsDevelopment()) regionProvider.SeedData(); } } +<<<<<<< HEAD app.UseCors("DamageAppCorsPolicy"); +======= + +// Enable CORS, authentication, and authorization middleware. +app.UseCors("DamageAppCorsPolicy"); + +>>>>>>> 9ec9b8b96fc7c5767fcddf1e4e52bde203fcf619 app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs index 7dec941..c73ff8a 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs @@ -89,6 +89,26 @@ namespace DamageAssesment.Api.Questions.Controllers return CreatedAtRoute("DefaultApi", new { id = question.Id }, question); } /// + /// POST request for creating a multiple question (multilingual). + /// + [HttpPost("questions/multiple")] + public async Task CreateQuestions(List questions) + { + if (questions != null) + { + var result = await this.questionsProvider.PostQuestionsAsync(questions); + if (result.IsSuccess) + { + return Ok(result.Question); + } + if (result.ErrorMessage == "Not Found") + return NotFound(result.ErrorMessage); + + return BadRequest(result.ErrorMessage); + } + return CreatedAtRoute("DefaultApi",questions); + } + /// /// POST request for creating a new question (multilingual). /// diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Interfaces/IQuestionsProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Interfaces/IQuestionsProvider.cs index f8e13c8..4fcea32 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Interfaces/IQuestionsProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Interfaces/IQuestionsProvider.cs @@ -8,6 +8,7 @@ namespace DamageAssesment.Api.Questions.Interfaces Task<(bool IsSuccess, IEnumerable Questions, string ErrorMessage)> GetQuestionsAsync(string language); Task<(bool IsSuccess, List SurveyQuestions, string ErrorMessage)> GetSurveyQuestionAsync(int surveyId,string language); Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> PostQuestionAsync(Models.Question Question); + Task<(bool IsSuccess, IEnumerable Question, string ErrorMessage)> PostQuestionsAsync(List Questions); Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> UpdateQuestionAsync(Models.Question Question); Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> DeleteQuestionAsync(int id); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs index 203f267..8908e35 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs @@ -15,8 +15,14 @@ builder.Services.AddControllers(); builder.Services.AddScoped(); builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); +// CORS setup to allow requests from any origin. +builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { + build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); +})); + +// Add controller services and API Explorer for endpoint discovery. builder.Services.AddEndpointsApiExplorer(); -//builder.Services.AddSwaggerGen(); +// Add Swagger/OpenAPI documentation support. builder.Services.AddSwaggerGen(c => { // Include XML comments from your assembly @@ -46,6 +52,11 @@ if (app.Environment.IsDevelopment()) questionProvider.SeedData(); } } +<<<<<<< HEAD +======= + +// Enable CORS, authentication, and authorization middleware. +>>>>>>> 9ec9b8b96fc7c5767fcddf1e4e52bde203fcf619 app.UseCors("DamageAppCorsPolicy"); app.UseAuthorization(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs index 0122af7..d6bfebc 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs @@ -334,16 +334,7 @@ namespace DamageAssesment.Api.Questions.Providers try { logger?.LogInformation("Query Question"); - var dbquestion = mapper.Map(Question); - var dbquestiontranslation = mapper.Map, List>(Question.Questions); - dbquestion.QuestionTypeId = questionDbContext.QuestionTypes.Where(a => a.TypeText == Question.TypeText).Select(a => a.Id).FirstOrDefault(); - questionDbContext.Questions.Add(dbquestion); - dbquestiontranslation.ForEach(i => i.QuestionId = dbquestion.Id); - questionDbContext.QuestionsTranslations.AddRange(dbquestiontranslation); - questionDbContext.SaveChanges(); - Question.Id = dbquestion.Id; - var result = mapper.Map(dbquestion); - result.Text = CreateMultiLanguageObject(GetQuestionsTranslations(result.Id,"")); + var result = InsertQuestion(Question); return (true, result, null); } catch (Exception ex) @@ -352,6 +343,39 @@ namespace DamageAssesment.Api.Questions.Providers return (false, null, ex.Message); } } + private Models.MultiLanguage InsertQuestion(Models.Question Question) + { + var dbquestion = mapper.Map(Question); + var dbquestiontranslation = mapper.Map, List>(Question.Questions); + dbquestion.QuestionTypeId = questionDbContext.QuestionTypes.Where(a => a.TypeText == Question.TypeText).Select(a => a.Id).FirstOrDefault(); + questionDbContext.Questions.Add(dbquestion); + questionDbContext.SaveChanges(); + dbquestiontranslation.ForEach(i => i.QuestionId = dbquestion.Id); + questionDbContext.QuestionsTranslations.AddRange(dbquestiontranslation); + questionDbContext.SaveChanges(); + Question.Id = dbquestion.Id; + var result = mapper.Map(dbquestion); + result.Text = CreateMultiLanguageObject(GetQuestionsTranslations(result.Id, "")); + return result; + } + public async Task<(bool IsSuccess, IEnumerable Question, string ErrorMessage)> PostQuestionsAsync(List Questions) + { + try + { + List results = new List(); + logger?.LogInformation("Query Question"); + foreach (Models.Question Question in Questions) + { + results.Add(InsertQuestion(Question)); + } + return (true, results, null); + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } public async Task<(bool IsSuccess, Models.MultiLanguage Question, string ErrorMessage)> UpdateQuestionAsync(Models.Question Question) { try diff --git a/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/MockData.cs b/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/MockData.cs index 8b13b70..df621f5 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/MockData.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/MockData.cs @@ -75,8 +75,19 @@ namespace DamageAssesment.Api.Questions.Test return new Questions.Models.Question { Id = 1, Questions=QuestionsTranslations, TypeText = "Text 1", SurveyId = 1, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId=1}; } - - - + public static async Task> getInputQuestionsData() + { + Models.QuestionsTranslation QuestionsTranslation = new Models.QuestionsTranslation() + { + Language = "en", + QuestionText = "Sample question" + }; + List QuestionsTranslations = new List(); + List Questions = new List(); + QuestionsTranslations.Add(QuestionsTranslation); + Questions.Models.Question question = new Questions.Models.Question() { Id = 1, Questions = QuestionsTranslations, TypeText = "Text 1", SurveyId = 1, QuestionNumber = 1, IsRequired = true, Comment = false, Key = true, CategoryId = 1 }; + Questions.Add(question); + return Questions; + } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/QuestionsServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/QuestionsServiceTest.cs index bda9db2..b44e479 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/QuestionsServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/QuestionsServiceTest.cs @@ -110,6 +110,33 @@ namespace DamageAssesment.Api.Questions.Test Assert.Equal(400, result.StatusCode); } + [Fact(DisplayName = "Post Questions - Ok case")] + public async Task PostQuestionsAsync_ShouldReturnStatusCode200() + { + var mockQuestionService = new Mock(); + var mockResponse = await MockData.getOkResponse(); + var mockInputQuestion = await MockData.getInputQuestionsData(); + mockQuestionService.Setup(service => service.PostQuestionsAsync(mockInputQuestion)).ReturnsAsync(mockResponse); + + var QuestionProvider = new QuestionsController(mockQuestionService.Object); + var result = (OkObjectResult)await QuestionProvider.CreateQuestions(mockInputQuestion); + + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Post Questions - BadRequest case")] + public async Task PostQuestionsAsync_ShouldReturnStatusCode400() + { + var mockQuestionService = new Mock(); + var mockInputQuestion = await MockData.getInputQuestionData(); + var mockResponse = await MockData.getBadRequestResponse(); + mockQuestionService.Setup(service => service.UpdateQuestionAsync(mockInputQuestion)).ReturnsAsync(mockResponse); + + var QuestionProvider = new QuestionsController(mockQuestionService.Object); + var result = (BadRequestObjectResult)await QuestionProvider.UpdateQuestion(mockInputQuestion); + + Assert.Equal(400, result.StatusCode); + } [Fact(DisplayName = "Put Question - Ok case")] public async Task PutQuestionAsync_ShouldReturnStatusCode200() diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs index d09a9d0..7304cfd 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs @@ -16,6 +16,10 @@ const int intervalForCircuitBraker = 5; //5 seconds // Add services to the container. builder.Services.AddControllers(); +// CORS setup to allow requests from any origin. +builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { + build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); +})); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddScoped(); @@ -36,6 +40,7 @@ builder.Services.AddHttpClient(). builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); +// Add Swagger/OpenAPI documentation support. builder.Services.AddSwaggerGen(c => { // Include XML comments from your assembly @@ -59,6 +64,10 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } +<<<<<<< HEAD +======= +// Enable CORS, authentication, and authorization middleware. +>>>>>>> 9ec9b8b96fc7c5767fcddf1e4e52bde203fcf619 app.UseCors("DamageAppCorsPolicy"); app.UseAuthorization(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs index f7f2306..8c774f6 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs @@ -10,7 +10,11 @@ using System.Reflection; var builder = WebApplication.CreateBuilder(args); // Add services to the container. + +// Retrieve the security key for JWT token validation. var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); + +// Configure JWT authentication and validation. builder.Services.AddAuthentication(item => { item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; @@ -29,16 +33,21 @@ builder.Services.AddAuthentication(item => }; }); +//CORS setup to allow requests from any origin. builder.Services.AddCors(p => p.AddPolicy("DamageAppCorsPolicy", build => { build.WithOrigins("*").AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin(); })); + + +// Add controller services and API Explorer for endpoint discovery. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddScoped(); builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddEndpointsApiExplorer(); -//builder.Services.AddSwaggerGen(); + +// Add Swagger/OpenAPI documentation support. builder.Services.AddSwaggerGen(c => { // Include XML comments from your assembly @@ -46,10 +55,13 @@ builder.Services.AddSwaggerGen(c => var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); + +// Configure the database context for SurveysDbContext using SQL Server. builder.Services.AddDbContext(option => { option.UseSqlServer("SurveyConnection"); }); + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -57,7 +69,7 @@ if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); - + // Seed initial data in the database when in development mode using (var serviceScope = app.Services.CreateScope()) { var services = serviceScope.ServiceProvider; @@ -65,11 +77,11 @@ if (app.Environment.IsDevelopment()) surveyProvider.seedData(); } } - +// Enable CORS, authentication, and authorization middleware. app.UseCors("DamageAppCorsPolicy"); app.UseAuthentication(); app.UseAuthorization(); - +// Map controllers to their respective routes. app.MapControllers(); app.Run();