From c7a2dc5910803030eb4baf4d8efdcae604ff46f2 Mon Sep 17 00:00:00 2001 From: uppuv Date: Fri, 6 Oct 2023 15:53:09 -0400 Subject: [PATCH 01/40] seed changes for doculinks --- .../Providers/DoculinkProvider.cs | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs index cf8bcfe..64fd608 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs @@ -63,13 +63,15 @@ namespace DamageAssesment.Api.DocuLinks.Providers int counter = 0; for (int i = 1; i <= 4; i++) { - FileModel fileModel = new FileModel() { url = "www.google"+i+".com", IsAttachments = false, CustomOrder = 1 }; - ReqDoculink documentInfo = new ReqDoculink() { linkTypeId = i,CustomOrder=i, Files = new List() { fileModel } }; - Db.DoculinkTranslation documents = new Db.DoculinkTranslation { DocumentId = i, title = "Test"+i, description = "ss"+i, Language = "en" }; + FileModel fileModel = new FileModel(); + if (i<3) + fileModel = new FileModel() { FileName="Sample"+i,FileExtension=".txt",FileContent= "c2FtcGxl", IsAttachments = true, CustomOrder = 1 }; + else + fileModel = new FileModel() { url = "www.google" + i + ".com", IsAttachments = false, CustomOrder = 1 }; + 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)); DocumentDbContext.SaveChanges(); - DocumentDbContext.DocumentsTranslations.AddRange(documents); var dbattachments = mapper.Map, List>(document.doclinksAttachments); dbattachments.ForEach(a => a.DocumentId = i); DocumentDbContext.DoclinksAttachments.AddRange(dbattachments); @@ -77,6 +79,34 @@ namespace DamageAssesment.Api.DocuLinks.Providers counter++; } } + if (!DocumentDbContext.DocumentsTranslations.Any()) + { + string[] titles = { + "Mobile App Damage Assessment Instructions", + "PC Damage Assessment Instructions", + "Emergency Evacuation centers", + "Mobile App Damage Assessment Instructions" }; + string[] esTranslations = { + "Instrucciones de Evaluación de Daños de la Aplicación Móvil", + "Instrucciones de Evaluación de Daños del PC", + "Centros de Evacuación de Emergencia", + "Instrucciones de Evaluación de Daños de la Aplicación Móvil" }; + string[] frTranslations = { + "Instructions d'Évaluation des Dommages de l'Application Mobile", + "Instructions d'Évaluation des Dommages du PC", + "Centres d'Évacuation d'Urgence", + "Instructions d'Évaluation des Dommages de l'Application Mobile" }; + List documents = new List(); + for(int i = 0; i < 4; i++) + { + documents.Add(new Db.DoculinkTranslation { DocumentId = i+1, title = titles[i], description = titles[i], Language = "en" }); + documents.Add(new Db.DoculinkTranslation { DocumentId = i + 1, title = esTranslations[i], description = esTranslations[i], Language = "es" }); + documents.Add(new Db.DoculinkTranslation { DocumentId = i + 1, title = frTranslations[i], description = frTranslations[i], Language = "fr" }); + } + DocumentDbContext.DocumentsTranslations.AddRange(documents); + DocumentDbContext.SaveChanges(); + } + } public List GetDocumentTranslations(int id, string? language) { From 71d4b524e7d5779c7d164ab4728de683b29b61ab Mon Sep 17 00:00:00 2001 From: uppuv Date: Mon, 9 Oct 2023 13:29:01 -0400 Subject: [PATCH 02/40] doculinks changes for grouping --- .../DoculinkServiceTest.cs | 34 ++++++++++-- .../MockData.cs | 49 ++++++++++++++++- .../Controllers/DoculinkController.cs | 16 +++++- .../Interfaces/IDoculinkProvider.cs | 3 +- .../Models/Doculink.cs | 5 ++ .../Providers/DoculinkProvider.cs | 55 +++++++++++++++++-- 6 files changed, 150 insertions(+), 12 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs index b953eeb..14ddaaa 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs @@ -16,7 +16,7 @@ namespace DamageAssesment.Api.DocuLinks.Test { var mockDocumentService = new Mock(); var mockUploadService = new Mock(); - var mockResponse = await MockData.getNoContentResponse(); + var mockResponse = await MockData.getNoContentResponses(); mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms","en",null)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); @@ -30,7 +30,7 @@ namespace DamageAssesment.Api.DocuLinks.Test { var mockDocumentService = new Mock(); var mockUploadService = new Mock(); - var mockResponse = await MockData.getNoContentResponse(); + var mockResponse = await MockData.getNoContentResponses(); mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms", "en", true)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); @@ -43,7 +43,7 @@ namespace DamageAssesment.Api.DocuLinks.Test { var mockDocumentService = new Mock(); var mockUploadService = new Mock(); - var mockResponse = await MockData.getOkResponse(); + var mockResponse = await MockData.getOkResponses(); mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms","en", null)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); @@ -56,7 +56,7 @@ namespace DamageAssesment.Api.DocuLinks.Test { var mockDocumentService = new Mock(); var mockUploadService = new Mock(); - var mockResponse = await MockData.getOkResponse(); + var mockResponse = await MockData.getOkResponses(); mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms", "en", true)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); @@ -65,6 +65,32 @@ namespace DamageAssesment.Api.DocuLinks.Test Assert.Equal(200, result.StatusCode); } + [Fact(DisplayName = "Get active Documents by linktypeid - Ok case")] + public async Task GetActiveDocumentsLinkTypeIdAsync_ShouldReturnStatusCode200() + { + var mockDocumentService = new Mock(); + var mockUploadService = new Mock(); + var mockResponse = await MockData.getOkResponses(); + mockDocumentService.Setup(service => service.GetdocumentsByLinkTypeIdAsync(null, "en", true)).ReturnsAsync(mockResponse); + + var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); + var result = (OkObjectResult)await DocumentProvider.GetDocumentsByActiveLinkTypeIdAsync(null, "en"); + + Assert.Equal(200, result.StatusCode); + } + [Fact(DisplayName = "Get active Documents by linktypeid - NoContent Case")] + public async Task GetDocumentsLinkTypeIdAsync_ShouldReturnStatusCode204() + { + var mockDocumentService = new Mock(); + var mockUploadService = new Mock(); + var mockResponse = await MockData.getNoContentResponses(); + mockDocumentService.Setup(service => service.GetdocumentsByLinkTypeIdAsync(null, "en", true)).ReturnsAsync(mockResponse); + + var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); + var result = (NoContentResult)await DocumentProvider.GetDocumentsByActiveLinkTypeIdAsync(null, ""); + + Assert.Equal(204, result.StatusCode); + } [Fact(DisplayName = "Get Document by Id - Ok case")] public async Task GetDocumentAsync_ShouldReturnStatusCode200() { diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs index bd10e4b..23ffae4 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs @@ -11,7 +11,7 @@ namespace DamageAssesment.Api.DocuLinks.Test public class MockData { - public static async Task<(bool, List, string)> getOkResponse() + public static async Task<(bool, List, string)> getOkResponses() { List list = new List(); @@ -46,6 +46,48 @@ namespace DamageAssesment.Api.DocuLinks.Test doclinksAttachments= doclinksAttachments }); } + List doculinks = list.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); + return (true, doculinks, null); + } + + + public static async Task<(bool, List, string)> getOkResponse() + { + List list = new List(); + + for (int i = 1; i < 4; i++) + { + Dictionary dicttitle = new Dictionary(); + Dictionary dictdesc = new Dictionary(); + dicttitle.Add("en", "test"); dicttitle.Add("fr", "tester"); + dictdesc.Add("en", "test"); dictdesc.Add("fr", "tester"); + List DocuLinksTranslations = new List(); + DocuLinksTranslations.Add(new DoculinkTranslation() + { + Language = "en", + title = "tel" + i, + description = "Sample" + i + }); + List doclinksAttachments = new List(); + doclinksAttachments.Add(new DoculinkAttachments() + { + docName = "", + Path = "www.google.com", + IsAttachments = false, + CustomOrder = 1 + }); + list.Add(new DocuLinks.Models.ResDoculink() + { + + Id = i, + linkTypeId = i, + IsActive = true, + titles = dicttitle, + description = dictdesc, + CustomOrder = i, + doclinksAttachments = doclinksAttachments + }); + } return (true, list, null); } public static async Task<(bool, DocuLinks.Models.ResDoculink, string)> getOkResponse(int Id) @@ -64,6 +106,11 @@ namespace DamageAssesment.Api.DocuLinks.Test { return (false, null, "Not Found"); } + public static async Task<(bool, IEnumerable, string)> getNoContentResponses() + { + IEnumerable list = new List(); + return (false, list, null); + } public static async Task<(bool, IEnumerable, string)> getNoContentResponse() { IEnumerable list = new List(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs index cfbd508..99d00a8 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs @@ -136,7 +136,21 @@ namespace DamageAssesment.Api.DocuLinks.Controllers } return NoContent(); } - + /// + /// Get all active Doculink. + /// + [Route("doculinks/active/{linktypeid:int}")] + [Route("doculinks/active/{linktypeid:int}/{language:alpha}")] + [HttpGet] + public async Task GetDocumentsByActiveLinkTypeIdAsync(int? linktypeid, string? language) + { + var result = await this.documentsProvider.GetdocumentsByLinkTypeIdAsync(linktypeid, language, true); + if (result.IsSuccess) + { + return Ok(result.documents); + } + return NoContent(); + } /// /// Get a Doculink by id. /// diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs index f4f9c84..6d271fd 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs @@ -7,7 +7,8 @@ namespace DamageAssesment.Api.DocuLinks.Interfaces Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> GetDocumentAsync(int id, string? linktype, string? language); Task<(bool IsSuccess, Models.Doculink Document, string ErrorMessage)> GetDocumentByidAsync(int id); // Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetDocumnetsAsync(string? language); - Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive); + Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive); + 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)> DeleteDocumentAsync(int id); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/Doculink.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/Doculink.cs index 6fb538b..33259e1 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/Doculink.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Models/Doculink.cs @@ -7,6 +7,11 @@ namespace DamageAssesment.Api.DocuLinks.Models { public List documentsTranslations { get; set; } } + public class ResDoculinks + { + public int linkTypeId { get; set; } + public List doculinks { get; set; } + } public class ResDoculink:BaseDoculink { public object titles { get; set; } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs index 64fd608..28e8664 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs @@ -6,8 +6,10 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Internal; using System; +using System.Collections.Immutable; using System.Diagnostics.Eventing.Reader; using System.Reflection.Metadata; +using System.Xml; using System.Xml.Linq; namespace DamageAssesment.Api.DocuLinks.Providers @@ -63,12 +65,17 @@ namespace DamageAssesment.Api.DocuLinks.Providers int counter = 0; for (int i = 1; i <= 4; i++) { + int linkTypeId = 2; FileModel fileModel = new FileModel(); - if (i<3) - fileModel = new FileModel() { FileName="Sample"+i,FileExtension=".txt",FileContent= "c2FtcGxl", IsAttachments = true, CustomOrder = 1 }; + if (i < 3) + { + linkTypeId = 1; + + fileModel = new FileModel() { FileName = "Sample" + i, FileExtension = ".txt", FileContent = "c2FtcGxl", IsAttachments = true, CustomOrder = 1 }; + } else fileModel = new FileModel() { url = "www.google" + i + ".com", IsAttachments = false, CustomOrder = 1 }; - ReqDoculink documentInfo = new ReqDoculink() { linkTypeId = i, CustomOrder = i, Files = new List() { fileModel } }; + ReqDoculink documentInfo = new ReqDoculink() { linkTypeId = linkTypeId, CustomOrder = i, Files = new List() { fileModel } }; Models.Doculink document = uploadservice.UploadDocument(counter, documentInfo); DocumentDbContext.Documents.Add(mapper.Map(document)); DocumentDbContext.SaveChanges(); @@ -163,7 +170,44 @@ namespace DamageAssesment.Api.DocuLinks.Providers MultiLanguage = dicttitle; return MultiLanguage; } - public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive) + + public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive) + { + + try + { + logger?.LogInformation("Query Question"); + var documents = new List(); + if (linkTypeId==null) + documents = await DocumentDbContext.Documents.AsNoTracking().Where(q => (isactive == null || q.IsActive == isactive.Value)).ToListAsync(); + else + documents = await DocumentDbContext.Documents.AsNoTracking().Where(q => (isactive == null || q.IsActive == isactive.Value) && + q.linkTypeId == linkTypeId.Value).ToListAsync(); + if (documents != null) + { + var result = mapper.Map, List>(documents); + foreach (var item in result) + { + var multilan = CreateMultiLanguageObject(GetDocumentTranslations(item.Id, language)); + 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()); + } + List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); + return (true, doculinks, null); + } + return (false, null, "Not found"); + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + + } + public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive) { try @@ -187,7 +231,8 @@ namespace DamageAssesment.Api.DocuLinks.Providers item.doclinksAttachments = mapper.Map, List>( DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == item.Id).ToList()); } - return (true, result, null); + List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); + return (true, doculinks, null); } return (false, null, "Not found"); } From cb3c7f8f6af3e7992af41d6c22566c5c875c242e Mon Sep 17 00:00:00 2001 From: uppuv Date: Fri, 13 Oct 2023 13:21:33 -0400 Subject: [PATCH 03/40] added muilti language return format for question categories for question by survey --- .../appsettings.Development.json | 8 -------- .../appsettings.Development.json | 8 -------- .../appsettings.Development.json | 8 -------- .../appsettings.Development.json | 8 -------- .../appsettings.Development.json | 8 -------- .../Models/SurveyQuestion.cs | 1 + .../Providers/QuestionsProvider.cs | 1 + .../appsettings.Development.json | 8 -------- .../appsettings.Development.json | 8 -------- 9 files changed, 2 insertions(+), 56 deletions(-) delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.Development.json delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.Development.json delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.Development.json delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.Development.json delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.Development.json delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.Development.json delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.Development.json diff --git a/DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/SurveyQuestion.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/SurveyQuestion.cs index 8f4fd7b..b7ce8d1 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/SurveyQuestion.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/SurveyQuestion.cs @@ -5,6 +5,7 @@ public int CategoryId { get; set; } public string IconName { get; set; } public string IconLibrary { get; set; } + public object CategoryNames { get; set; } public List QuestionsText { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs index 5a010fa..45f6ecf 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs @@ -314,6 +314,7 @@ namespace DamageAssesment.Api.Questions.Providers CategoryId = item.Id, IconLibrary = item.IconLibrary, IconName = item.IconName, + CategoryNames= CreateCategoryMultiLanguageObject(GetCategoryTranslations(item.Id, language)), QuestionsText = GetSurveyQuestion(mapper.Map, List>(questions.Where(a => a.CategoryId == item.Id).ToList()), language) }); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.Development.json deleted file mode 100644 index 0c208ae..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} From f91b935374aebabd1307e05380a9499e3c2c38ca Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Fri, 13 Oct 2023 18:28:15 -0400 Subject: [PATCH 04/40] Added Azure Pipeline to ACR --- ...28165655_InitialDocumentCreate.Designer.cs | 95 -------------- .../20230828165655_InitialDocumentCreate.cs | 60 --------- ...0830200432_DocumentTranslation.Designer.cs | 118 ------------------ .../20230830200432_DocumentTranslation.cs | 70 ----------- .../DocumentDbContextModelSnapshot.cs | 115 ----------------- DamageAssesmentApi/azure-pipelines.yml | 21 ++++ 6 files changed, 21 insertions(+), 458 deletions(-) delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.Designer.cs delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.cs delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.Designer.cs delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.cs delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/DocumentDbContextModelSnapshot.cs create mode 100644 DamageAssesmentApi/azure-pipelines.yml diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.Designer.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.Designer.cs deleted file mode 100644 index 8072057..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.Designer.cs +++ /dev/null @@ -1,95 +0,0 @@ -// -using System; -using DamageAssesment.Api.DocuLinks.Db; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace DamageAssesment.Api.DocuLinks.Migrations -{ - [DbContext(typeof(DoculinkDbContext))] - [Migration("20230828165655_InitialDocumentCreate")] - partial class InitialDocumentCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.9") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IsActive") - .HasColumnType("bit"); - - b.Property("Path") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("dateCreated") - .HasColumnType("datetime2"); - - b.Property("dateUpdated") - .HasColumnType("datetime2"); - - b.Property("description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("docName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("linkTypeId") - .HasColumnType("int"); - - b.Property("title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("url") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Documents"); - }); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.LinkType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IsActive") - .HasColumnType("bit"); - - b.Property("TypeText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("LinkTypes"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.cs deleted file mode 100644 index 741574e..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230828165655_InitialDocumentCreate.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace DamageAssesment.Api.DocuLinks.Migrations -{ - /// - public partial class InitialDocumentCreate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Documents", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - title = table.Column(type: "nvarchar(max)", nullable: false), - linkTypeId = table.Column(type: "int", nullable: false), - description = table.Column(type: "nvarchar(max)", nullable: false), - docName = table.Column(type: "nvarchar(max)", nullable: false), - url = table.Column(type: "nvarchar(max)", nullable: false), - Path = table.Column(type: "nvarchar(max)", nullable: false), - IsActive = table.Column(type: "bit", nullable: false), - dateCreated = table.Column(type: "datetime2", nullable: false), - dateUpdated = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Documents", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "LinkTypes", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - TypeText = table.Column(type: "nvarchar(max)", nullable: false), - IsActive = table.Column(type: "bit", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_LinkTypes", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Documents"); - - migrationBuilder.DropTable( - name: "LinkTypes"); - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.Designer.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.Designer.cs deleted file mode 100644 index b9006ba..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.Designer.cs +++ /dev/null @@ -1,118 +0,0 @@ -// -using System; -using DamageAssesment.Api.DocuLinks.Db; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace DamageAssesment.Api.DocuLinks.Migrations -{ - [DbContext(typeof(DoculinkDbContext))] - [Migration("20230830200432_DocumentTranslation")] - partial class DocumentTranslation - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.9") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IsActive") - .HasColumnType("bit"); - - b.Property("Path") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("dateCreated") - .HasColumnType("datetime2"); - - b.Property("dateUpdated") - .HasColumnType("datetime2"); - - b.Property("docName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("linkTypeId") - .HasColumnType("int"); - - b.Property("url") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Documents"); - }); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.DocumentsTranslation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("DocumentId") - .HasColumnType("int"); - - b.Property("Language") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("DocumentsTranslations"); - }); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.LinkType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IsActive") - .HasColumnType("bit"); - - b.Property("IsAttachment") - .HasColumnType("bit"); - - b.Property("TypeText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("LinkTypes"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.cs deleted file mode 100644 index d639539..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/20230830200432_DocumentTranslation.cs +++ /dev/null @@ -1,70 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace DamageAssesment.Api.DocuLinks.Migrations -{ - /// - public partial class DocumentTranslation : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "description", - table: "Documents"); - - migrationBuilder.DropColumn( - name: "title", - table: "Documents"); - - migrationBuilder.AddColumn( - name: "IsAttachment", - table: "LinkTypes", - type: "bit", - nullable: false, - defaultValue: false); - - migrationBuilder.CreateTable( - name: "DocumentsTranslations", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - DocumentId = table.Column(type: "int", nullable: false), - title = table.Column(type: "nvarchar(max)", nullable: false), - description = table.Column(type: "nvarchar(max)", nullable: false), - Language = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_DocumentsTranslations", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "DocumentsTranslations"); - - migrationBuilder.DropColumn( - name: "IsAttachment", - table: "LinkTypes"); - - migrationBuilder.AddColumn( - name: "description", - table: "Documents", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "title", - table: "Documents", - type: "nvarchar(max)", - nullable: false, - defaultValue: ""); - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/DocumentDbContextModelSnapshot.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/DocumentDbContextModelSnapshot.cs deleted file mode 100644 index a692f80..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Migrations/DocumentDbContextModelSnapshot.cs +++ /dev/null @@ -1,115 +0,0 @@ -// -using System; -using DamageAssesment.Api.DocuLinks.Db; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace DamageAssesment.Api.DocuLinks.Migrations -{ - [DbContext(typeof(DoculinkDbContext))] - partial class DocumentDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.9") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.Document", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IsActive") - .HasColumnType("bit"); - - b.Property("Path") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("dateCreated") - .HasColumnType("datetime2"); - - b.Property("dateUpdated") - .HasColumnType("datetime2"); - - b.Property("docName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("linkTypeId") - .HasColumnType("int"); - - b.Property("url") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Documents"); - }); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.DocumentsTranslation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("DocumentId") - .HasColumnType("int"); - - b.Property("Language") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("description") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("title") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("DocumentsTranslations"); - }); - - modelBuilder.Entity("DamageAssesment.Api.DocuLinks.Db.LinkType", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("IsActive") - .HasColumnType("bit"); - - b.Property("IsAttachment") - .HasColumnType("bit"); - - b.Property("TypeText") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("LinkTypes"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml new file mode 100644 index 0000000..147dd91 --- /dev/null +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -0,0 +1,21 @@ +trigger: + - docker-branch # Change this to your preferred branch or trigger + +pr: + - '*' + +pool: + vmImage: 'ubuntu-latest' + +jobs: +- job: 'BuildAndPush' + steps: + - script: | + docker-compose -f docker-compose.yml build + docker login -u $(acrServiceConnectionUsername) -p $(acrServiceConnectionPassword) $(acrServiceConnectionServer) + docker-compose -f docker-compose.yml push + displayName: 'Build and Push Docker Compose Project' + env: + acrServiceConnectionUsername: $(ACRServiceConnectionName.username) + acrServiceConnectionPassword: $(ACRServiceConnectionName.password) + acrServiceConnectionServer: $(ACRServiceConnectionName.server) \ No newline at end of file From 45109881ad3a7909550a08f15a459c9c545baf2e Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Sat, 14 Oct 2023 04:12:30 +0000 Subject: [PATCH 05/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 147dd91..747ee0f 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -16,6 +16,6 @@ jobs: docker-compose -f docker-compose.yml push displayName: 'Build and Push Docker Compose Project' env: - acrServiceConnectionUsername: $(ACRServiceConnectionName.username) - acrServiceConnectionPassword: $(ACRServiceConnectionName.password) - acrServiceConnectionServer: $(ACRServiceConnectionName.server) \ No newline at end of file + acrServiceConnectionUsername: "dadeSchoolsContainerRegistry" + acrServiceConnectionPassword: "k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn" + acrServiceConnectionServer: "dadeschoolscontainerregistry.azurecr.io" From d3cf6a63e51d2c215065967afd75531a1e0c166d Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Sat, 14 Oct 2023 04:13:24 +0000 Subject: [PATCH 06/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 747ee0f..32a0e68 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -9,13 +9,13 @@ pool: jobs: - job: 'BuildAndPush' + env: + acrServiceConnectionUsername: "dadeSchoolsContainerRegistry" + acrServiceConnectionPassword: "k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn" + acrServiceConnectionServer: "dadeschoolscontainerregistry.azurecr.io" steps: - script: | docker-compose -f docker-compose.yml build docker login -u $(acrServiceConnectionUsername) -p $(acrServiceConnectionPassword) $(acrServiceConnectionServer) docker-compose -f docker-compose.yml push displayName: 'Build and Push Docker Compose Project' - env: - acrServiceConnectionUsername: "dadeSchoolsContainerRegistry" - acrServiceConnectionPassword: "k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn" - acrServiceConnectionServer: "dadeschoolscontainerregistry.azurecr.io" From 0dd6d3b1e36afcfc6e8452f9f14e39326ee0896b Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Sat, 14 Oct 2023 04:14:40 +0000 Subject: [PATCH 07/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 32a0e68..3f78ac3 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -9,13 +9,15 @@ pool: jobs: - job: 'BuildAndPush' - env: - acrServiceConnectionUsername: "dadeSchoolsContainerRegistry" - acrServiceConnectionPassword: "k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn" - acrServiceConnectionServer: "dadeschoolscontainerregistry.azurecr.io" + pool: + vmImage: 'ubuntu-latest' steps: - script: | docker-compose -f docker-compose.yml build docker login -u $(acrServiceConnectionUsername) -p $(acrServiceConnectionPassword) $(acrServiceConnectionServer) docker-compose -f docker-compose.yml push displayName: 'Build and Push Docker Compose Project' + env: + acrServiceConnectionUsername: "dadeSchoolsContainerRegistry" + acrServiceConnectionPassword: "k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn" + acrServiceConnectionServer: "dadeschoolscontainerregistry.azurecr.io" From 7985428f8b70037edecd4c85818936086b00d83d Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Sat, 14 Oct 2023 04:16:24 +0000 Subject: [PATCH 08/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 3f78ac3..33fad0a 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -1,5 +1,7 @@ trigger: - - docker-branch # Change this to your preferred branch or trigger + branches: + include: + - docker-branch # Change this to your preferred branch or trigger pr: - '*' From 3ac36bf86fc09475c4b74ee40a43bb0b77ab0931 Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Sun, 15 Oct 2023 16:48:47 +0000 Subject: [PATCH 09/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 33fad0a..aba5677 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -16,10 +16,7 @@ jobs: steps: - script: | docker-compose -f docker-compose.yml build - docker login -u $(acrServiceConnectionUsername) -p $(acrServiceConnectionPassword) $(acrServiceConnectionServer) + docker login -u $("dadeSchoolsContainerRegistry") -p $("k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn") $("dadeschoolscontainerregistry.azurecr.io") docker-compose -f docker-compose.yml push displayName: 'Build and Push Docker Compose Project' - env: - acrServiceConnectionUsername: "dadeSchoolsContainerRegistry" - acrServiceConnectionPassword: "k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn" - acrServiceConnectionServer: "dadeschoolscontainerregistry.azurecr.io" + \ No newline at end of file From 55e27059e5d018760c90293465fb404211fbf99b Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Mon, 16 Oct 2023 03:31:15 +0000 Subject: [PATCH 10/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index aba5677..996f9db 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -1,8 +1,3 @@ -trigger: - branches: - include: - - docker-branch # Change this to your preferred branch or trigger - pr: - '*' @@ -14,9 +9,14 @@ jobs: pool: vmImage: 'ubuntu-latest' steps: + - checkout: self - script: | docker-compose -f docker-compose.yml build - docker login -u $("dadeSchoolsContainerRegistry") -p $("k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn") $("dadeschoolscontainerregistry.azurecr.io") + docker login -u "$(dadeSchoolsContainerRegistry)" -p "$(k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn)" "dadeschoolscontainerregistry.azurecr.io" docker-compose -f docker-compose.yml push displayName: 'Build and Push Docker Compose Project' - \ No newline at end of file + +trigger: + branches: + include: + - docker-branch From 7935302b2d31c112af057590519e23086803e403 Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Mon, 16 Oct 2023 03:40:48 +0000 Subject: [PATCH 11/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 996f9db..4ee7e7b 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -1,3 +1,5 @@ +name: Build & Push to ACR Pipeline # Replace "Build and Push to ACR" with the desired name + pr: - '*' @@ -11,9 +13,9 @@ jobs: steps: - checkout: self - script: | - docker-compose -f docker-compose.yml build + docker-compose -f compose-files/docker-compose.sql.yml build docker login -u "$(dadeSchoolsContainerRegistry)" -p "$(k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn)" "dadeschoolscontainerregistry.azurecr.io" - docker-compose -f docker-compose.yml push + docker-compose -f compose-files/docker-compose.sql.yml push displayName: 'Build and Push Docker Compose Project' trigger: From dadbcf98b9473eaf63fce9075ff9372c78ca38e2 Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Mon, 16 Oct 2023 03:44:19 +0000 Subject: [PATCH 12/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 4ee7e7b..f6df08d 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -1,4 +1,4 @@ -name: Build & Push to ACR Pipeline # Replace "Build and Push to ACR" with the desired name +name: Build & Push to ACR Pipeline pr: - '*' @@ -13,9 +13,9 @@ jobs: steps: - checkout: self - script: | - docker-compose -f compose-files/docker-compose.sql.yml build + docker-compose build docker login -u "$(dadeSchoolsContainerRegistry)" -p "$(k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn)" "dadeschoolscontainerregistry.azurecr.io" - docker-compose -f compose-files/docker-compose.sql.yml push + docker-compose push displayName: 'Build and Push Docker Compose Project' trigger: From 08f873e8e35ec75836074309de23f7748cab8f70 Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Mon, 16 Oct 2023 03:47:09 +0000 Subject: [PATCH 13/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index f6df08d..e473b30 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -13,9 +13,9 @@ jobs: steps: - checkout: self - script: | - docker-compose build + docker-compose -f **/docker-compose.yml build docker login -u "$(dadeSchoolsContainerRegistry)" -p "$(k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn)" "dadeschoolscontainerregistry.azurecr.io" - docker-compose push + docker-compose -f **/docker-compose.yml push displayName: 'Build and Push Docker Compose Project' trigger: From c89c6f60c36d72f1853c0d418195ae78ef2f312a Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Mon, 16 Oct 2023 11:21:54 +0000 Subject: [PATCH 14/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index e473b30..7cc8ea8 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -13,8 +13,9 @@ jobs: steps: - checkout: self - script: | + export DOCKER_CLI_CONTEXT=default docker-compose -f **/docker-compose.yml build - docker login -u "$(dadeSchoolsContainerRegistry)" -p "$(k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn)" "dadeschoolscontainerregistry.azurecr.io" + docker login -u dadeSchoolsContainerRegistry -p k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn dadeschoolscontainerregistry.azurecr.io docker-compose -f **/docker-compose.yml push displayName: 'Build and Push Docker Compose Project' From 8a803ad1577b74bd4683aae3f3051a49cc40ef6c Mon Sep 17 00:00:00 2001 From: uppuv Date: Mon, 16 Oct 2023 14:02:28 -0400 Subject: [PATCH 15/40] added logic to get active surveys from survey responses --- .../Controllers/SurveyResponsesController.cs | 22 ++++++++++++--- .../Interfaces/ISurveysResponse.cs | 4 +-- .../Providers/SurveyResponsesProvider.cs | 28 +++++++++---------- .../Providers/SurveysProvider.cs | 5 ++-- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs index d5f6192..36f40a5 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs @@ -198,11 +198,12 @@ namespace DamageAssesment.Api.Responses.Controllers else return BadRequest(result.ErrorMessage); } - + [Route("responses/surveys/active")] + [Route("responses/surveys/active/{language:alpha}")] [Route("responses/surveys/active/{employeeid:int}")] [Route("responses/surveys/active/{employeeid:int}/{language:alpha}")] [HttpGet] - public async Task GetActiveSurveysAsync(int employeeid, string? language) + public async Task GetActiveSurveysAsync(int? employeeid, string? language) { var result = await this.surveyResponseProvider.GetActiveSurveysAsync(employeeid, language); if (result.IsSuccess) @@ -211,11 +212,24 @@ namespace DamageAssesment.Api.Responses.Controllers } return NoContent(); } - + //[Route("responses/surveys/active")] + //[Route("responses/surveys/active/{language:alpha}")] + //[HttpGet] + //public async Task GetActiveSurveysAsync( string? language) + //{ + // var result = await this.surveyResponseProvider.GetActiveSurveysAsync(null, language); + // if (result.IsSuccess) + // { + // return Ok(result.Surveys); + // } + // return NoContent(); + //} + [Route("responses/surveys/historic")] + [Route("responses/surveys/historic/{language:alpha}")] [Route("responses/surveys/historic/{employeeid:int}")] [Route("responses/surveys/historic/{employeeid:int}/{language:alpha}")] [HttpGet] - public async Task GetHistoricSurveysAsync(int employeeid, string? language) + public async Task GetHistoricSurveysAsync(int? employeeid, string? language) { var result = await this.surveyResponseProvider.GetHistoricSurveysAsync(employeeid, language); if (result.IsSuccess) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs index dea50eb..19893c8 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs @@ -9,8 +9,8 @@ namespace DamageAssesment.Api.Responses.Interfaces Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyResponseAsync(Models.SurveyResponse surveyResponse); // Task<(bool IsSuccess,dynamic surveyResponses, string ErrorMessage)> GetSurveyResponseAsync(int responseId); Task<(bool IsSuccess, dynamic surveyResponses, string ErrorMessage)> GetSurveyResponsesAsync(int employeeid); - Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int employeeid, string language); - Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int employeeid, string language); + Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int? employeeid, string language); + Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int? employeeid, string language); Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PutSurveyResponseAsync(int Id, Models.SurveyResponse surveyResponse); Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> DeleteSurveyResponseAsync(int Id); Task<(bool IsSuccess, dynamic SurveyResponse, string ErrorMessage)> GetSurveyResponseByIdAsync(int responseId); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs index 5278c5c..af11925 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs @@ -112,24 +112,18 @@ namespace DamageAssesment.Api.Responses.Providers } } - public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int employeeid, string language) + public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int? employeeid, string language) { try { logger?.LogInformation("Querying to get SurveyResponse object from DB"); //get all the survey that already taken by the employee - var listOfsurveysId = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).Select(y => y.SurveyId).ToListAsync(); var surveys = await surveyServiceProvider.getSurveysAsync(language); - - if (surveys != null) - { - surveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now).ToList(); - } - - if (listOfsurveysId==null || listOfsurveysId.Count == 0) + surveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now).ToList(); + if (employeeid==null || employeeid==0) return (true, surveys, null); - - var activeSurveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now && !listOfsurveysId.Contains(s.Id)); + List listOfsurveysId = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid.Value).Select(y => y.SurveyId).ToListAsync(); + var activeSurveys = surveys.Where(s => !listOfsurveysId.Contains(s.Id)); return (true, activeSurveys, null); } catch (Exception ex) @@ -139,21 +133,25 @@ namespace DamageAssesment.Api.Responses.Providers } } - public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int employeeid, string language) + public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int? employeeid, string language) { try { logger?.LogInformation("Querying to get SurveyResponse object from DB"); - //get all the survey that already taken by the employee - var surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).ToListAsync(); + var surveys = await surveyServiceProvider.getSurveysAsync(language); + // returning only historic data: end date is less than current date. + surveys = surveys.Where(s => s.EndDate < DateTime.Now).ToList(); + if(employeeid==null|| employeeid==0) + return (true, surveys, null); + var surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).ToListAsync(); var historicSurveys = from s in surveys from r in surveyResponses where s.Id == r.SurveyId select s; - return (true, historicSurveys, null); + } catch (Exception ex) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs index 2d6cbc9..de945c6 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs @@ -18,7 +18,7 @@ namespace DamageAssesment.Api.Surveys.Providers this.surveyDbContext = surveysDbContext; this.logger = logger; this.mapper = mapper; - //seedData(); + // seedData(); } // Method to seed initial data into the database @@ -93,7 +93,8 @@ namespace DamageAssesment.Api.Surveys.Providers try { logger?.LogInformation("Get all Surveys from DB"); - var surveys = await surveyDbContext.Surveys.Where(s => s.IsEnabled == true).ToListAsync(); + //checking is enabled in survey response + var surveys = await surveyDbContext.Surveys.ToListAsync();//Where(s => s.IsEnabled == true) if (surveys != null) { From c77e0452c49763f0e4907060e10ebf961f6e6ddd Mon Sep 17 00:00:00 2001 From: uppuv Date: Mon, 16 Oct 2023 14:13:20 -0400 Subject: [PATCH 16/40] added logic to get active surveys from survey responses --- .../Controllers/SurveyResponsesController.cs | 8 +++-- .../Interfaces/ISurveysResponse.cs | 4 +-- .../Providers/SurveyResponsesProvider.cs | 31 +++++++++---------- .../Providers/SurveysProvider.cs | 3 +- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs index d5f6192..55b7f5d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs @@ -199,10 +199,12 @@ namespace DamageAssesment.Api.Responses.Controllers return BadRequest(result.ErrorMessage); } + [Route("responses/surveys/active")] + [Route("responses/surveys/active/{language:alpha}")] [Route("responses/surveys/active/{employeeid:int}")] [Route("responses/surveys/active/{employeeid:int}/{language:alpha}")] [HttpGet] - public async Task GetActiveSurveysAsync(int employeeid, string? language) + public async Task GetActiveSurveysAsync(int? employeeid, string? language) { var result = await this.surveyResponseProvider.GetActiveSurveysAsync(employeeid, language); if (result.IsSuccess) @@ -212,10 +214,12 @@ namespace DamageAssesment.Api.Responses.Controllers return NoContent(); } + [Route("responses/surveys/historic")] + [Route("responses/surveys/historic/{language:alpha}")] [Route("responses/surveys/historic/{employeeid:int}")] [Route("responses/surveys/historic/{employeeid:int}/{language:alpha}")] [HttpGet] - public async Task GetHistoricSurveysAsync(int employeeid, string? language) + public async Task GetHistoricSurveysAsync(int? employeeid, string? language) { var result = await this.surveyResponseProvider.GetHistoricSurveysAsync(employeeid, language); if (result.IsSuccess) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs index dea50eb..19893c8 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs @@ -9,8 +9,8 @@ namespace DamageAssesment.Api.Responses.Interfaces Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyResponseAsync(Models.SurveyResponse surveyResponse); // Task<(bool IsSuccess,dynamic surveyResponses, string ErrorMessage)> GetSurveyResponseAsync(int responseId); Task<(bool IsSuccess, dynamic surveyResponses, string ErrorMessage)> GetSurveyResponsesAsync(int employeeid); - Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int employeeid, string language); - Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int employeeid, string language); + Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int? employeeid, string language); + Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int? employeeid, string language); Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PutSurveyResponseAsync(int Id, Models.SurveyResponse surveyResponse); Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> DeleteSurveyResponseAsync(int Id); Task<(bool IsSuccess, dynamic SurveyResponse, string ErrorMessage)> GetSurveyResponseByIdAsync(int responseId); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs index 5278c5c..0c6c817 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs @@ -111,25 +111,19 @@ namespace DamageAssesment.Api.Responses.Providers return (false, null, ex.Message); } } - - public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int employeeid, string language) + + public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int? employeeid, string language) { try { logger?.LogInformation("Querying to get SurveyResponse object from DB"); //get all the survey that already taken by the employee - var listOfsurveysId = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).Select(y => y.SurveyId).ToListAsync(); var surveys = await surveyServiceProvider.getSurveysAsync(language); - - if (surveys != null) - { - surveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now).ToList(); - } - - if (listOfsurveysId==null || listOfsurveysId.Count == 0) + surveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now).ToList(); + if (employeeid == null || employeeid == 0) return (true, surveys, null); - - var activeSurveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now && !listOfsurveysId.Contains(s.Id)); + List listOfsurveysId = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid.Value).Select(y => y.SurveyId).ToListAsync(); + var activeSurveys = surveys.Where(s => !listOfsurveysId.Contains(s.Id)); return (true, activeSurveys, null); } catch (Exception ex) @@ -139,21 +133,24 @@ namespace DamageAssesment.Api.Responses.Providers } } - public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int employeeid, string language) + public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int? employeeid, string language) { try { logger?.LogInformation("Querying to get SurveyResponse object from DB"); - //get all the survey that already taken by the employee - var surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).ToListAsync(); - var surveys = await surveyServiceProvider.getSurveysAsync(language); + var surveys = await surveyServiceProvider.getSurveysAsync(language); + // returning only historic data: end date is less than current date. + surveys = surveys.Where(s => s.EndDate < DateTime.Now).ToList(); + if (employeeid == null || employeeid == 0) + return (true, surveys, null); + var surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).ToListAsync(); var historicSurveys = from s in surveys from r in surveyResponses where s.Id == r.SurveyId select s; - return (true, historicSurveys, null); + } catch (Exception ex) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs index 3332f6d..fe09798 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs @@ -93,7 +93,8 @@ namespace DamageAssesment.Api.Surveys.Providers try { logger?.LogInformation("Get all Surveys from DB"); - var surveys = await surveyDbContext.Surveys.Where(s => s.IsEnabled == true).ToListAsync(); + //checking is enabled in survey response + var surveys = await surveyDbContext.Surveys.ToListAsync();//Where(s => s.IsEnabled == true) if (surveys != null) { From 8349e78f6ecbb15f7eaccfd83da708e8d4b92e40 Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Mon, 16 Oct 2023 23:30:50 +0000 Subject: [PATCH 17/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 64 ++++++++++++++++++++------ 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 7cc8ea8..2e367d4 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -1,25 +1,61 @@ name: Build & Push to ACR Pipeline +trigger: +- '*' + pr: - - '*' +- '*' pool: vmImage: 'ubuntu-latest' jobs: -- job: 'BuildAndPush' - pool: - vmImage: 'ubuntu-latest' +- job: BuildAndPushImages steps: - checkout: self - - script: | - export DOCKER_CLI_CONTEXT=default - docker-compose -f **/docker-compose.yml build - docker login -u dadeSchoolsContainerRegistry -p k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn dadeschoolscontainerregistry.azurecr.io - docker-compose -f **/docker-compose.yml push - displayName: 'Build and Push Docker Compose Project' -trigger: - branches: - include: - - docker-branch + - bash: | + #!/bin/bash + + # Specify the path to your docker-compose.yml + composeFile="$(find $(Build.SourcesDirectory) -name docker-compose.yml | head -1)" + + # Check if a docker-compose.yml file was found + if [ -z "$composeFile" ]; then + echo "No docker-compose.yml file found in the workspace." + exit 1 + fi + + # Log the path to the docker-compose.yml file + echo "Using docker-compose file at: $composeFile" + + # Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD) + docker login dadeschoolscontainerregistry.azurecr.io -u ACR_USERNAME -p ACR_PASSWORD + + # List of services to build, tag, and push + services=( + "damageassesmentapianswers" + "damageassesmentapiattachments" + "damageassesmentapiemployees" + "damageassesmentapilocations" + "damageassesmentapiquestions" + "damageassesmentapisurveys" + "damageassesmentapidoculinks" + "damageassesmentapiresponses" + ) + + # Loop through the services and build, tag, and push + for service in "${services[@]}"; do + # Build the service + docker-compose -f "$composeFile" build "$service" + + # Tag the image for ACR + docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" + + # Push the image to ACR + docker push "dadeschoolscontainerregistry.azurecr.io/$service" + done + displayName: 'Build and Push Docker Images' + env: + ACR_USERNAME: $(acrUsername) # Set your ACR username secret here + ACR_PASSWORD: $(acrPassword) # Set your ACR password secret here From 16d45d6632eb2b29d35af0618f821874e0aa5305 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Mon, 16 Oct 2023 22:44:08 -0400 Subject: [PATCH 18/40] docker-compose.acr added --- DamageAssesmentApi/docker-compose.acr.yml | 75 +++++++++++++++++++++++ DamageAssesmentApi/docker-compose.dcproj | 1 + 2 files changed, 76 insertions(+) create mode 100644 DamageAssesmentApi/docker-compose.acr.yml diff --git a/DamageAssesmentApi/docker-compose.acr.yml b/DamageAssesmentApi/docker-compose.acr.yml new file mode 100644 index 0000000..b275839 --- /dev/null +++ b/DamageAssesmentApi/docker-compose.acr.yml @@ -0,0 +1,75 @@ +version: '3.4' + +services: + damageassesment.api.answers: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapianswers + build: + context: . + dockerfile: DamageAssesment.Api.Answers/Dockerfile + ports: + - "6001:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapianswers" + + damageassesment.api.attachments: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiattachments + build: + context: . + dockerfile: DamageAssesment.Api.Attachments/Dockerfile + ports: + - "6001:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiattachments" + + damageassesment.api.employees: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiemployees + build: + context: . + dockerfile: DamageAssesment.Api.Employees/Dockerfile + ports: + - "6003:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiemployees" + + damageassesment.api.locations: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapilocations + build: + context: . + dockerfile: DamageAssesment.Api.Locations/Dockerfile + ports: + - "6004:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapilocations" + + damageassesment.api.questions: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiquestions + build: + context: . + dockerfile: DamageAssesment.Api.Questions/Dockerfile + ports: + - "6005:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiquestions" + + damageassesment.api.surveys: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapisurveys + build: + context: . + dockerfile: DamageAssesment.Api.Surveys/Dockerfile + ports: + - "6006:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapisurveys" + + damageassesment.api.doculinks: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapidoculinks + build: + context: . + dockerfile: DamageAssesment.Api.DocuLinks/Dockerfile + ports: + - "6008:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapidoculinks" + + damageassesment.api.responses: + image: dadeschoolscontainerregistry.azurecr.io/damageassesmentapiresponses + build: + context: . + dockerfile: DamageAssesment.Api.Responses/Dockerfile + ports: + - "6007:80" + command: bash -c "docker push dadeschoolscontainerregistry.azurecr.io/damageassesmentapiresponses" + diff --git a/DamageAssesmentApi/docker-compose.dcproj b/DamageAssesmentApi/docker-compose.dcproj index 178f3d6..185e0e4 100644 --- a/DamageAssesmentApi/docker-compose.dcproj +++ b/DamageAssesmentApi/docker-compose.dcproj @@ -9,6 +9,7 @@ damageassesment.api.answers + From f3216418701b080965e42c87a3b3deef7eeb76b4 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 11:36:35 -0400 Subject: [PATCH 19/40] folder for Common build support scripts --- Scripts/build_and_push_services2acr.ps1 | 30 ++++++++++++++++++++++++ Scripts/build_and_push_services2acr.sh | 31 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 Scripts/build_and_push_services2acr.ps1 create mode 100644 Scripts/build_and_push_services2acr.sh diff --git a/Scripts/build_and_push_services2acr.ps1 b/Scripts/build_and_push_services2acr.ps1 new file mode 100644 index 0000000..d61eb0e --- /dev/null +++ b/Scripts/build_and_push_services2acr.ps1 @@ -0,0 +1,30 @@ +# powershell -ExecutionPolicy Bypass -File .\build_and_push_services2acr.ps1 +# Specify the path to your docker-compose.yml +$composeFile = "C:\Users\santh\OneDrive\Desktop\DOCKERS\ubuntu\Sprint6\C1011\Backend-API-Services\DamageAssesmentApi\docker-compose.yml" + +# List of services to build, tag, and push +$services = @( + "damageassesmentapianswers", + "damageassesmentapiattachments", + "damageassesmentapiemployees", + "damageassesmentapilocations", + "damageassesmentapiquestions", + "damageassesmentapisurveys", + "damageassesmentapidoculinks", + "damageassesmentapiresponses" +) + +# Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD) +docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegistry -p k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn + +# Loop through the services and build, tag, and push +foreach ($service in $services) { + # Build the service + docker-compose -f $composeFile build $service + + # Tag the image for ACR + docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" + + # Push the image to ACR + docker push "dadeschoolscontainerregistry.azurecr.io/$service" +} diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh new file mode 100644 index 0000000..990902b --- /dev/null +++ b/Scripts/build_and_push_services2acr.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Specify the path to your docker-compose.yml +composeFile="C:/Users/santh/OneDrive/Desktop/DOCKERS/ubuntu/Sprint6/C1011/Backend-API-Services/DamageAssesmentApi/docker-compose.yml" + +# List of services to build, tag, and push +services=( + "damageassesmentapianswers" + "damageassesmentapiattachments" + "damageassesmentapiemployees" + "damageassesmentapilocations" + "damageassesmentapiquestions" + "damageassesmentapisurveys" + "damageassesmentapidoculinks" + "damageassesmentapiresponses" +) + +# Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD) +docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegistry -p k1f8hE0O5hj3tYCCR/5stNrkw5BZoTmAqid/hvaVo8+ACRDc2Arn + +# Loop through the services and build, tag, and push +for service in "${services[@]}"; do + # Build the service + docker-compose -f "$composeFile" build "$service" + + # Tag the image for ACR + docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" + + # Push the image to ACR + docker push "dadeschoolscontainerregistry.azurecr.io/$service" +done From 7b821decbd8f0d08fca100ab414f501a3544edb7 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 12:09:42 -0400 Subject: [PATCH 20/40] Updated with folder path --- Scripts/build_and_push_services2acr.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index 990902b..478a313 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -1,7 +1,13 @@ #!/bin/bash -# Specify the path to your docker-compose.yml -composeFile="C:/Users/santh/OneDrive/Desktop/DOCKERS/ubuntu/Sprint6/C1011/Backend-API-Services/DamageAssesmentApi/docker-compose.yml" +# Get the current working directory +current_directory="$(pwd)" + +# Specify the relative path to the docker-compose.yml +relative_path="Backend-API-Services/DamageAssesmentApi/docker-compose.yml" + +# Combine the current directory with the relative path to get the full path to docker-compose.yml +composeFile="$current_directory/$relative_path" # List of services to build, tag, and push services=( From 1f046e0c70ff8c5adf2ee2c580da166aaf237ba7 Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Tue, 17 Oct 2023 16:37:23 +0000 Subject: [PATCH 21/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 57 ++++---------------------- 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 2e367d4..9bd1ee7 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -1,61 +1,18 @@ -name: Build & Push to ACR Pipeline - trigger: -- '*' + - '*' pr: -- '*' + - '*' pool: vmImage: 'ubuntu-latest' -jobs: -- job: BuildAndPushImages - steps: +steps: - checkout: self - - bash: | + - script: | #!/bin/bash - # Specify the path to your docker-compose.yml - composeFile="$(find $(Build.SourcesDirectory) -name docker-compose.yml | head -1)" - - # Check if a docker-compose.yml file was found - if [ -z "$composeFile" ]; then - echo "No docker-compose.yml file found in the workspace." - exit 1 - fi - - # Log the path to the docker-compose.yml file - echo "Using docker-compose file at: $composeFile" - - # Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD) - docker login dadeschoolscontainerregistry.azurecr.io -u ACR_USERNAME -p ACR_PASSWORD - - # List of services to build, tag, and push - services=( - "damageassesmentapianswers" - "damageassesmentapiattachments" - "damageassesmentapiemployees" - "damageassesmentapilocations" - "damageassesmentapiquestions" - "damageassesmentapisurveys" - "damageassesmentapidoculinks" - "damageassesmentapiresponses" - ) - - # Loop through the services and build, tag, and push - for service in "${services[@]}"; do - # Build the service - docker-compose -f "$composeFile" build "$service" - - # Tag the image for ACR - docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" - - # Push the image to ACR - docker push "dadeschoolscontainerregistry.azurecr.io/$service" - done - displayName: 'Build and Push Docker Images' - env: - ACR_USERNAME: $(acrUsername) # Set your ACR username secret here - ACR_PASSWORD: $(acrPassword) # Set your ACR password secret here + chmod +x ./Backend-API-Services/Script/build_and_push_services2acr.sh + ./Backend-API-Services/Script/build_and_push_services2acr.sh + displayName: 'Run build_and_push_services2acr.sh' From afb520463a0276715313d75ca80e76206681fb6a Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Tue, 17 Oct 2023 16:41:54 +0000 Subject: [PATCH 22/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 9bd1ee7..6778953 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -13,6 +13,6 @@ steps: - script: | #!/bin/bash - chmod +x ./Backend-API-Services/Script/build_and_push_services2acr.sh - ./Backend-API-Services/Script/build_and_push_services2acr.sh + chmod +x ./Script/build_and_push_services2acr.sh + ./Script/build_and_push_services2acr.sh displayName: 'Run build_and_push_services2acr.sh' From e8cbe7616643d2e41580a5e17c3e5c11d79a56a9 Mon Sep 17 00:00:00 2001 From: Santhosh Nair <913441@dadeschools.net> Date: Tue, 17 Oct 2023 16:44:04 +0000 Subject: [PATCH 23/40] Update azure-pipelines.yml for Azure Pipelines --- DamageAssesmentApi/azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DamageAssesmentApi/azure-pipelines.yml b/DamageAssesmentApi/azure-pipelines.yml index 6778953..bbaebd3 100644 --- a/DamageAssesmentApi/azure-pipelines.yml +++ b/DamageAssesmentApi/azure-pipelines.yml @@ -13,6 +13,6 @@ steps: - script: | #!/bin/bash - chmod +x ./Script/build_and_push_services2acr.sh - ./Script/build_and_push_services2acr.sh + chmod +x ./Scripts/build_and_push_services2acr.sh + ./Scripts/build_and_push_services2acr.sh displayName: 'Run build_and_push_services2acr.sh' From f7141493cad663d0b8a8b76502ac6b480160ea84 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 12:51:51 -0400 Subject: [PATCH 24/40] Updated relative path --- Scripts/build_and_push_services2acr.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index 478a313..10ee2c5 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -4,21 +4,21 @@ current_directory="$(pwd)" # Specify the relative path to the docker-compose.yml -relative_path="Backend-API-Services/DamageAssesmentApi/docker-compose.yml" +relative_path="Backend-API-Services/DamageAssesmentApi" # Combine the current directory with the relative path to get the full path to docker-compose.yml -composeFile="$current_directory/$relative_path" +composeFile="$current_directory/$relative_path/docker-compose.yml" # List of services to build, tag, and push services=( - "damageassesmentapianswers" - "damageassesmentapiattachments" - "damageassesmentapiemployees" - "damageassesmentapilocations" - "damageassesmentapiquestions" - "damageassesmentapisurveys" - "damageassesmentapidoculinks" - "damageassesmentapiresponses" + "damageassesment.api.answers" + "damageassesment.api.attachments" + "damageassesment.api.employees" + "damageassesment.api.locations" + "damageassesment.api.questions" + "damageassesment.api.responses" + "damageassesment.api.surveys" + "damageassesment.api.doculinks" ) # Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD) From fa68071d64123f33feb305321852baa453f3787c Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 15:14:41 -0400 Subject: [PATCH 25/40] modified push acr script --- Scripts/build_and_push_services2acr.sh | 36 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index 10ee2c5..0f128ac 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -2,23 +2,31 @@ # Get the current working directory current_directory="$(pwd)" +echo "Current directory: $current_directory" + +# Navigate one folder up +cd .. + +# Get and display the new working directory +current_directory="$(pwd)" +echo "New directory: $current_directory" # Specify the relative path to the docker-compose.yml -relative_path="Backend-API-Services/DamageAssesmentApi" +relative_path="DamageAssesmentApi" # Combine the current directory with the relative path to get the full path to docker-compose.yml composeFile="$current_directory/$relative_path/docker-compose.yml" # List of services to build, tag, and push services=( - "damageassesment.api.answers" - "damageassesment.api.attachments" - "damageassesment.api.employees" - "damageassesment.api.locations" - "damageassesment.api.questions" - "damageassesment.api.responses" - "damageassesment.api.surveys" - "damageassesment.api.doculinks" + "damageassesmentapianswers" + "damageassesmentapiattachments" + "damageassesmentapiemployees" + "damageassesmentapilocations" + "damageassesmentapiquestions" + "damageassesmentapisurveys" + "damageassesmentapidoculinks" + "damageassesmentapiresponses" ) # Log in to ACR (replace ACR_USERNAME and ACR_PASSWORD) @@ -27,7 +35,7 @@ docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegi # Loop through the services and build, tag, and push for service in "${services[@]}"; do # Build the service - docker-compose -f "$composeFile" build "$service" + docker-compose -f "$composeFile" build # "$service" # Tag the image for ACR docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" @@ -35,3 +43,11 @@ for service in "${services[@]}"; do # Push the image to ACR docker push "dadeschoolscontainerregistry.azurecr.io/$service" done + +# Get and display the current working directory +current_directory="$(pwd)" +echo "Current directory: $current_directory" + +# Wait for a keypress +echo "Press any key to continue..." +read -n 1 -s -r -p "" From 0cc5be64ee2b63065dc44c7e52f788367bc96792 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 15:27:44 -0400 Subject: [PATCH 26/40] modified push acr script --- Scripts/build_and_push_services2acr.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index 0f128ac..c650dc9 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -35,10 +35,10 @@ docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegi # Loop through the services and build, tag, and push for service in "${services[@]}"; do # Build the service - docker-compose -f "$composeFile" build # "$service" + docker-compose -f "$composeFile" build "$service" # Tag the image for ACR - docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" + docker tag $service "dadeschoolscontainerregistry.azurecr.io/$service" # Push the image to ACR docker push "dadeschoolscontainerregistry.azurecr.io/$service" @@ -49,5 +49,5 @@ current_directory="$(pwd)" echo "Current directory: $current_directory" # Wait for a keypress -echo "Press any key to continue..." -read -n 1 -s -r -p "" +#echo "Press any key to continue..." +#read -n 1 -s -r -p "" From 39df8c017b58a9fd42592eb9392f4fa7bfc45c14 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 22:07:15 -0400 Subject: [PATCH 27/40] modified push acr script --- Scripts/build_and_push_services2acr.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index c650dc9..0483d57 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -15,7 +15,7 @@ echo "New directory: $current_directory" relative_path="DamageAssesmentApi" # Combine the current directory with the relative path to get the full path to docker-compose.yml -composeFile="$current_directory/$relative_path/docker-compose.yml" +composeFile="$current_directory/DamageAssesmentApi/docker-compose.yml" # List of services to build, tag, and push services=( @@ -35,7 +35,7 @@ docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegi # Loop through the services and build, tag, and push for service in "${services[@]}"; do # Build the service - docker-compose -f "$composeFile" build "$service" + docker-compose -f "$composeFile" build #"$service" # Tag the image for ACR docker tag $service "dadeschoolscontainerregistry.azurecr.io/$service" From aae073d4566483c7ed860ef196d312934d609211 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 22:10:31 -0400 Subject: [PATCH 28/40] modified push acr script --- Scripts/build_and_push_services2acr.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index 0483d57..48412a4 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -15,7 +15,8 @@ echo "New directory: $current_directory" relative_path="DamageAssesmentApi" # Combine the current directory with the relative path to get the full path to docker-compose.yml -composeFile="$current_directory/DamageAssesmentApi/docker-compose.yml" +#composeFile="$current_directory/DamageAssesmentApi/docker-compose.yml" +composeFile="./DamageAssesmentApi/docker-compose.yml" # List of services to build, tag, and push services=( From 40ab868e82f3b5d19208d6ce9bba41fce4ee5b00 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 22:18:56 -0400 Subject: [PATCH 29/40] Updated relative path --- Scripts/build_and_push_services2acr.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index 48412a4..a4fd039 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -5,7 +5,7 @@ current_directory="$(pwd)" echo "Current directory: $current_directory" # Navigate one folder up -cd .. +#cd .. # Get and display the new working directory current_directory="$(pwd)" @@ -16,7 +16,7 @@ relative_path="DamageAssesmentApi" # Combine the current directory with the relative path to get the full path to docker-compose.yml #composeFile="$current_directory/DamageAssesmentApi/docker-compose.yml" -composeFile="./DamageAssesmentApi/docker-compose.yml" +composeFile="../DamageAssesmentApi/docker-compose.yml" # List of services to build, tag, and push services=( @@ -51,4 +51,4 @@ echo "Current directory: $current_directory" # Wait for a keypress #echo "Press any key to continue..." -#read -n 1 -s -r -p "" +read -n 1 -s -r -p "" From d219faa14709cca9c36d6d254cc89fd682f70b8d Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 22:40:34 -0400 Subject: [PATCH 30/40] Updated with folder path --- Scripts/build_and_push_services2acr.sh | 32 ++++++++------------------ 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index a4fd039..dd0250b 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -1,22 +1,16 @@ #!/bin/bash -# Get the current working directory -current_directory="$(pwd)" -echo "Current directory: $current_directory" +# Determine the current directory (where the script is located) +script_directory="$( cd "$(dirname "$0")" ; pwd -P )" -# Navigate one folder up -#cd .. - -# Get and display the new working directory -current_directory="$(pwd)" -echo "New directory: $current_directory" +# Navigate to the root of the repository +repository_root="$script_directory/.." # Specify the relative path to the docker-compose.yml -relative_path="DamageAssesmentApi" +relative_path="DamageAssesmentApi/docker-compose.yml" -# Combine the current directory with the relative path to get the full path to docker-compose.yml -#composeFile="$current_directory/DamageAssesmentApi/docker-compose.yml" -composeFile="../DamageAssesmentApi/docker-compose.yml" +# Combine the repository root directory with the relative path to get the full path to docker-compose.yml +composeFile="$repository_root/$relative_path" # List of services to build, tag, and push services=( @@ -36,19 +30,11 @@ docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegi # Loop through the services and build, tag, and push for service in "${services[@]}"; do # Build the service - docker-compose -f "$composeFile" build #"$service" + docker-compose -f "$composeFile" build #"$service" # Tag the image for ACR - docker tag $service "dadeschoolscontainerregistry.azurecr.io/$service" + docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" # Push the image to ACR docker push "dadeschoolscontainerregistry.azurecr.io/$service" done - -# Get and display the current working directory -current_directory="$(pwd)" -echo "Current directory: $current_directory" - -# Wait for a keypress -#echo "Press any key to continue..." -read -n 1 -s -r -p "" From f9b7fad33b96dd78a4a357d1193e40c255e909d0 Mon Sep 17 00:00:00 2001 From: Santhosh S <913341@dadeschools.net> Date: Tue, 17 Oct 2023 23:04:28 -0400 Subject: [PATCH 31/40] Updated with folder path --- Scripts/build_and_push_services2acr.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Scripts/build_and_push_services2acr.sh b/Scripts/build_and_push_services2acr.sh index dd0250b..d562f19 100644 --- a/Scripts/build_and_push_services2acr.sh +++ b/Scripts/build_and_push_services2acr.sh @@ -3,14 +3,13 @@ # Determine the current directory (where the script is located) script_directory="$( cd "$(dirname "$0")" ; pwd -P )" -# Navigate to the root of the repository -repository_root="$script_directory/.." +# Use the 'find' command to locate the 'docker-compose.yml' file within the repository directory +composeFile=$(find "$script_directory/.." -name "docker-compose.yml" -type f | head -n 1) -# Specify the relative path to the docker-compose.yml -relative_path="DamageAssesmentApi/docker-compose.yml" - -# Combine the repository root directory with the relative path to get the full path to docker-compose.yml -composeFile="$repository_root/$relative_path" +if [ -z "$composeFile" ]; then + echo "docker-compose.yml not found." + exit 1 +fi # List of services to build, tag, and push services=( @@ -30,7 +29,7 @@ docker login dadeschoolscontainerregistry.azurecr.io -u dadeSchoolsContainerRegi # Loop through the services and build, tag, and push for service in "${services[@]}"; do # Build the service - docker-compose -f "$composeFile" build #"$service" + docker-compose -f "$composeFile" build "$service" # Tag the image for ACR docker tag "$service" "dadeschoolscontainerregistry.azurecr.io/$service" From e2bed664280da52239578b645533989ff3d32146 Mon Sep 17 00:00:00 2001 From: uppuv Date: Thu, 19 Oct 2023 15:59:02 -0400 Subject: [PATCH 32/40] merged user access module with latest changes for sql database --- .../Controllers/AnswersController.cs | 16 +- .../DamageAssesment.Api.Answers/Program.cs | 58 +++- .../appsettings.json | 5 +- .../AttachmentsServiceTest.cs | 18 +- .../Controllers/AttachmentsController.cs | 18 +- .../Interfaces/IAzureBlobService.cs | 7 +- .../Program.cs | 57 +++- .../Providers/AzureBlobService.cs | 143 +++++++- .../appsettings.json | 10 +- .../DoculinkServiceTest.cs | 28 +- .../MockData.cs | 34 +- .../Controllers/DoculinkController.cs | 26 +- .../DamageAssesment.Api.DocuLinks.csproj | 3 +- .../Db/DoculinkDbContext.cs | 2 +- .../Interfaces/IAzureBlobService.cs | 4 + .../DamageAssesment.Api.DocuLinks/Program.cs | 59 +++- .../Providers/AzureBlobService.cs | 163 +++++++++- .../Providers/DoculinkProvider.cs | 8 +- .../Providers/UploadService.cs | 5 +- .../appsettings.json | 12 +- .../Controllers/EmployeesController.cs | 10 +- .../DamageAssesment.Api.Employees/Program.cs | 56 +++- .../appsettings.json | 10 +- .../Controllers/LocationsController.cs | 11 +- .../Controllers/RegionsController.cs | 11 +- .../DamageAssesment.Api.Locations/Program.cs | 60 +++- .../appsettings.json | 8 +- .../Controllers/QuestionsController.cs | 20 +- .../Models/Question.cs | 2 +- .../DamageAssesment.Api.Questions/Program.cs | 58 +++- .../appsettings.json | 5 +- .../SurveyResponsesServiceTest.cs | 61 ++-- ...esController.cs => ResponsesController.cs} | 22 +- .../Interfaces/IAnswerServiceProvider.cs | 6 +- .../Interfaces/IAttachmentServiceProvider.cs | 4 +- .../Interfaces/IEmployeeServiceProvider.cs | 8 +- .../Interfaces/IHttpUtil.cs | 4 +- .../Interfaces/ILocationServiceProvider.cs | 2 +- .../Interfaces/IQuestionServiceProvider.cs | 6 +- .../Interfaces/IRegionServiceProvider.cs | 2 +- .../Interfaces/ISurveyServiceProvider.cs | 4 +- .../Models/Employee.cs | 2 +- .../DamageAssesment.Api.Responses/Program.cs | 56 +++- .../Properties/launchSettings.json | 2 +- .../Providers/SurveyResponsesProvider.cs | 231 ++++++------- .../Services/AnswerServiceProvider.cs | 13 +- .../Services/AttachmentServiceProvider.cs | 8 +- .../Services/EmployeeServiceProvider.cs | 10 +- .../Services/HttpUtil.cs | 9 +- .../Services/LocationServiceProvider.cs | 4 +- .../Services/QuestionServiceProvider.cs | 12 +- .../Services/RegionServiceProvider.cs | 4 +- .../Services/SurveyServiceProvider.cs | 12 +- .../appsettings.json | 13 +- ...17221348_InitialSurveyResponse.Designer.cs | 55 ---- .../20230817221348_InitialSurveyResponse.cs | 36 --- .../SurveyResponseDbContextModelSnapshot.cs | 52 --- .../Controllers/SurveysController.cs | 7 + .../DamageAssesment.Api.Surveys/Program.cs | 37 ++- .../Providers/SurveysProvider.cs | 1 - .../appsettings.json | 6 +- ...amageAssesment.Api.UsersAccess.Test.csproj | 30 ++ .../MockData.cs | 44 +++ .../UsersAccessTest.cs | 194 +++++++++++ .../Controllers/UsersAccessController.cs | 117 +++++++ .../DamageAssesment.Api.UsersAccess.csproj | 29 ++ .../Db/Role.cs | 21 ++ .../Db/Token.cs | 17 + .../Db/User.cs | 31 ++ .../Db/UsersAccessDbContext.cs | 39 +++ .../Interfaces/IEmployeeServiceProvider.cs | 10 + .../Interfaces/IRoleProvider.cs | 12 + .../Interfaces/ITokenServiceProvider.cs | 11 + .../Interfaces/IUsersAccessProvider.cs | 17 + .../Interfaces/Interface.cs | 7 + .../Models/Employee.cs | 14 + .../Models/JwtSettings.cs | 9 + .../Models/Role.cs | 8 + .../Models/Token.cs | 10 + .../Models/TokenResponse.cs | 8 + .../Models/User.cs | 13 + .../Models/UserCredentials.cs | 5 + .../Profiles/UsersAccessProfile.cs | 14 + .../Program.cs | 146 +++++++++ .../Properties/launchSettings.json | 31 ++ .../Providers/UserAccessProvider.cs | 305 ++++++++++++++++++ .../Services/EmployeeServiceProvider.cs | 50 +++ .../Services/HttpUtil.cs | 42 +++ .../Services/ServiceProviderBase.cs | 25 ++ .../Services/TokenServiceProvider.cs | 59 ++++ .../appsettings.Development.json | 8 + .../appsettings.json | 41 +++ .../DamageAssesment.Api.Responses.Test.csproj | 30 ++ .../MockData.cs | 30 ++ .../ResponsesServiceTest.cs | 251 ++++++++++++++ DamageAssesmentApi/DamageAssesment.sln | 12 + 96 files changed, 2773 insertions(+), 533 deletions(-) rename DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/{SurveyResponsesController.cs => ResponsesController.cs} (90%) delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.Designer.cs delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.cs delete mode 100644 DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/SurveyResponseDbContextModelSnapshot.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/DamageAssesment.Api.UsersAccess.Test.csproj create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/MockData.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/UsersAccessTest.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/DamageAssesment.Api.UsersAccess.csproj create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Role.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Token.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/User.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/UsersAccessDbContext.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IEmployeeServiceProvider.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IRoleProvider.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/ITokenServiceProvider.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/Interface.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Employee.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/JwtSettings.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Role.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Token.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/TokenResponse.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/User.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/UserCredentials.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Profiles/UsersAccessProfile.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Program.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Properties/launchSettings.json create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/EmployeeServiceProvider.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/HttpUtil.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/ServiceProviderBase.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/TokenServiceProvider.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.Development.json create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json create mode 100644 DamageAssesmentApi/DamageAssesment.Responses.Test/DamageAssesment.Api.Responses.Test.csproj create mode 100644 DamageAssesmentApi/DamageAssesment.Responses.Test/MockData.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Responses.Test/ResponsesServiceTest.cs diff --git a/DamageAssesmentApi/DamageAssesment.Api.Answers/Controllers/AnswersController.cs b/DamageAssesmentApi/DamageAssesment.Api.Answers/Controllers/AnswersController.cs index fe225b6..8130de4 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Answers/Controllers/AnswersController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Answers/Controllers/AnswersController.cs @@ -1,7 +1,6 @@ using DamageAssesment.Api.Answers.Interfaces; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.OpenApi.Any; namespace DamageAssesment.Api.Answers.Controllers { @@ -16,7 +15,7 @@ namespace DamageAssesment.Api.Answers.Controllers /// /// Get all answers /// - + [Authorize(Roles = "admin")] [HttpGet("answers")] public async Task GetAnswersAsync() { @@ -32,7 +31,7 @@ namespace DamageAssesment.Api.Answers.Controllers /// Get an answer based on answerId. /// - + [Authorize(Roles = "admin")] [HttpGet("answers/{id}")] public async Task GetAnswerByIdAsync(int id) { @@ -48,6 +47,7 @@ namespace DamageAssesment.Api.Answers.Controllers /// /// Get all answers based on responseId. /// + [Authorize(Roles = "admin")] [HttpGet("answers/byresponse/{responseid}")] public async Task GetAnswersByResponseId(int responseid) { @@ -61,7 +61,7 @@ namespace DamageAssesment.Api.Answers.Controllers /// /// Get all answers based on questionId. /// - + [Authorize(Roles = "admin")] [HttpGet("answers/byquestion/{questionid}")] public async Task AnswersByQuestionId(int questionid) { @@ -75,7 +75,7 @@ namespace DamageAssesment.Api.Answers.Controllers /// /// Update an existing answer. /// - + [Authorize(Roles = "admin")] [HttpPut("answers")] public async Task UpdateAnswer(Models.Answer answer) { @@ -96,7 +96,7 @@ namespace DamageAssesment.Api.Answers.Controllers /// /// Save a new answer. /// - + [Authorize(Roles = "admin")] [HttpPost("answers")] public async Task CreateAnswer(Models.Answer answer) { @@ -114,7 +114,7 @@ namespace DamageAssesment.Api.Answers.Controllers /// /// Delete an existing answer. /// - + [Authorize(Roles = "admin")] [HttpDelete("answers/{id}")] public async Task DeleteAnswer(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs index 0a38399..77e7544 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Answers/Program.cs @@ -1,23 +1,73 @@ using DamageAssesment.Api.Answers.Db; using DamageAssesment.Api.Answers.Interfaces; using DamageAssesment.Api.Answers.Providers; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; using System.Reflection; +using System.Text; var builder = WebApplication.CreateBuilder(args); - +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); +builder.Services.AddAuthentication(item => +{ + item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(item => +{ + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}); // 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(); -builder.Services.AddSwaggerGen(c => +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + + options.AddSecurityRequirement(securityRequirements); }); builder.Services.AddScoped(); builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //4/30 @@ -35,7 +85,7 @@ if (app.Environment.IsDevelopment()) app.UseSwagger(); app.UseSwaggerUI(); } - +app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.json index fbe7ccb..b759c3e 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Answers/appsettings.json @@ -10,9 +10,8 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - //"AnswerConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" - // "AnswerConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;", - "AnswerConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" + "AnswerConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"AnswerConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments.Test/AttachmentsServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments.Test/AttachmentsServiceTest.cs index 1b3ff31..8dd9ba8 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments.Test/AttachmentsServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments.Test/AttachmentsServiceTest.cs @@ -33,7 +33,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task GetAttachmentsAsync_ShouldReturnStatusCode204() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockResponse = await MockData.getNoContentResponse(); mockAttachmentService.Setup(service => service.GetAttachmentsAsync()).ReturnsAsync(mockResponse); @@ -47,7 +47,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task GetAttachmentAsync_ShouldReturnStatusCode200() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockResponse = await MockData.getOkResponse(1); mockAttachmentService.Setup(service => service.GetAttachmentByIdAsync(1)).ReturnsAsync(mockResponse); @@ -61,7 +61,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task GetAttachmentAsync_ShouldReturnStatusCode404() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockResponse = await MockData.getNotFoundResponse(); mockAttachmentService.Setup(service => service.GetAttachmentByIdAsync(99)).ReturnsAsync(mockResponse); var AttachmentProvider = new AttachmentsController(mockAttachmentService.Object, mockUploadService.Object); @@ -73,7 +73,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task PostAttachmentAsync_ShouldReturnStatusCode200() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockResponse = await MockData.getOkResponse(); var AttachmentResponse = await MockData.GetAttachmentInfo(0); var mockInputAttachment = await MockData.getInputAttachmentData(); @@ -89,7 +89,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task PostAttachmentAsync_ShouldReturnStatusCode400() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockInputAttachment = await MockData.getInputAttachmentData(); var mockResponse = await MockData.getBadRequestResponse(); mockAttachmentService.Setup(service => service.PostAttachmentAsync(mockInputAttachment)).ReturnsAsync(mockResponse); @@ -105,7 +105,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task PutAttachmentAsync_ShouldReturnStatusCode200() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockResponse = await MockData.getOkResponse(); var AttachmentResponse = await MockData.GetAttachmentInfo(1); var mockInputAttachment = await MockData.getInputAttachmentData(); @@ -121,7 +121,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task PutAttachmentAsync_ShouldReturnStatusCode400() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockInputAttachment = await MockData.getInputAttachmentData(); var mockResponse = await MockData.getBadRequestResponse(); mockAttachmentService.Setup(service => service.PostAttachmentAsync(mockInputAttachment)).ReturnsAsync(mockResponse); @@ -136,7 +136,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task DeleteAttachmentAsync_ShouldReturnStatusCode200() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockResponse = await MockData.getOkResponse(1); mockAttachmentService.Setup(service => service.DeleteAttachmentAsync(1)).ReturnsAsync(mockResponse); mockUploadService.Setup(service => service.Deletefile("")); @@ -150,7 +150,7 @@ namespace DamageAssesment.Api.Attachments.Test public async Task DeleteAttachmentAsync_ShouldReturnStatusCode404() { var mockAttachmentService = new Mock(); - var mockUploadService = new Mock(); + var mockUploadService = new Mock(); var mockResponse = await MockData.getNotFoundResponse(); mockAttachmentService.Setup(service => service.DeleteAttachmentAsync(1)).ReturnsAsync(mockResponse); var AttachmentProvider = new AttachmentsController(mockAttachmentService.Object, mockUploadService.Object); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs index 16c223c..f20f380 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Controllers/AttachmentsController.cs @@ -1,6 +1,7 @@ using Azure; using DamageAssesment.Api.Attachments.Interfaces; using DamageAssesment.Api.Attachments.Models; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Net.Http.Headers; @@ -12,16 +13,17 @@ namespace DamageAssesment.Api.Attachments.Controllers { private IAttachmentsProvider AttachmentProvider; private IUploadService UploadService; + private IAzureBlobService azureBlobService; - public AttachmentsController(IAttachmentsProvider AttachmentsProvider, IUploadService uploadService) + public AttachmentsController(IAttachmentsProvider AttachmentsProvider, IUploadService UploadService) { this.AttachmentProvider = AttachmentsProvider; - this.UploadService = uploadService; + this.UploadService = UploadService; } /// /// Get all attachments. /// - + [Authorize(Roles = "admin")] [HttpGet("attachments")] public async Task GetAttachmentsAsync() { @@ -37,6 +39,7 @@ namespace DamageAssesment.Api.Attachments.Controllers /// /// Get all attachments by attachmentId. /// + [Authorize(Roles = "admin")] [HttpGet("attachments/{id}")] public async Task GetAttachmentbyIdAsync(int id) { @@ -80,7 +83,7 @@ namespace DamageAssesment.Api.Attachments.Controllers /// /// Save new Attachment(s) /// - + [Authorize(Roles = "admin")] [HttpPost("attachments"), DisableRequestSizeLimit] public async Task UploadAttachmentAsync(AttachmentInfo attachmentInfo) { @@ -89,7 +92,7 @@ namespace DamageAssesment.Api.Attachments.Controllers if (attachmentInfo.Answers.Count > 0) { var Attachments = await this.AttachmentProvider.GetAttachmentCounter(); - List attachments = UploadService.UploadAttachment(attachmentInfo.ResponseId, Attachments.counter, attachmentInfo.Answers); + List attachments = UploadService.UploadAttachment(attachmentInfo.ResponseId, Attachments.counter, attachmentInfo.Answers); var result = await this.AttachmentProvider.PostAttachmentAsync(attachments); if (result.IsSuccess) { @@ -107,7 +110,7 @@ namespace DamageAssesment.Api.Attachments.Controllers /// /// Modify an new attachment. /// - + [Authorize(Roles = "admin")] [HttpPut("attachments"), DisableRequestSizeLimit] public async Task UpdateAttachmentAsync(AttachmentInfo attachmentInfo) { @@ -118,7 +121,7 @@ namespace DamageAssesment.Api.Attachments.Controllers var res = await this.AttachmentProvider.GetAttachmentInfo(attachmentInfo.Answers); if (res.IsSuccess) { - List attachments = UploadService.UpdateAttachments(attachmentInfo.ResponseId, attachmentInfo.Answers, res.Attachments); + List attachments = UploadService.UpdateAttachments(attachmentInfo.ResponseId, attachmentInfo.Answers, res.Attachments); var result = await this.AttachmentProvider.PutAttachmentAsync(attachments); if (result.IsSuccess) { @@ -138,6 +141,7 @@ namespace DamageAssesment.Api.Attachments.Controllers /// /// Delete an existing attachment. /// + [Authorize(Roles = "admin")] [HttpDelete("attachments/{id}")] public async Task DeleteAttachment(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAzureBlobService.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAzureBlobService.cs index f15ed9e..39e892d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAzureBlobService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Interfaces/IAzureBlobService.cs @@ -1,10 +1,15 @@ using Azure.Storage.Blobs.Models; +using DamageAssesment.Api.Attachments.Models; namespace DamageAssesment.Api.Attachments.Interfaces { public interface IAzureBlobService { Task>> UploadFiles(List files); - void DeleteFile(string path); + Task> UploadAttachment(int responseId, int answerId, int counter, List postedFile); + Task> UploadAttachment(int responseId, int counter, List answers); + Task> UpdateAttachments(int responseId, List answers, IEnumerable attachments); + 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 4fd2e59..62cf0cb 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Program.cs @@ -1,25 +1,75 @@ using DamageAssesment.Api.Attachments.Db; using DamageAssesment.Api.Attachments.Interfaces; using DamageAssesment.Api.Attachments.Providers; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Http.Features; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.FileProviders; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; using System.Reflection; +using System.Text; var builder = WebApplication.CreateBuilder(args); - +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); +builder.Services.AddAuthentication(item => +{ + item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(item => +{ + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}); // 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(); -builder.Services.AddSwaggerGen(c => +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + + options.AddSecurityRequirement(securityRequirements); }); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -45,6 +95,7 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } +app.UseAuthentication(); app.UseAuthorization(); app.UseHttpsRedirection(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AzureBlobService.cs b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AzureBlobService.cs index 4e30b42..2cb4558 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AzureBlobService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/Providers/AzureBlobService.cs @@ -3,6 +3,9 @@ using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Azure.Storage.Blobs.Specialized; using DamageAssesment.Api.Attachments.Interfaces; +using DamageAssesment.Api.Attachments.Models; +using System.Diagnostics.Metrics; +using System.Text; namespace DamageAssesment.Api.Attachments.Providers { @@ -10,11 +13,95 @@ namespace DamageAssesment.Api.Attachments.Providers { BlobServiceClient _blobClient; BlobContainerClient _containerClient; - string azureConnectionString = ""; - public AzureBlobService() + string azureConnectionString; + private string uploadpath = ""; + private string Deletepath = ""; + public AzureBlobService(IConfiguration configuration) { - _blobClient = new BlobServiceClient(azureConnectionString); - _containerClient = _blobClient.GetBlobContainerClient("apiimages"); + uploadpath = configuration.GetValue("Fileupload:folderpath"); + Deletepath = configuration.GetValue("Fileupload:Deletepath"); + _blobClient = new BlobServiceClient(configuration.GetValue("Fileupload:BlobConnectionString")); + _containerClient = _blobClient.GetBlobContainerClient(configuration.GetValue("Fileupload:BlobContainerName")); + } + public async Task> UploadAttachment(int responseId, int answerId, int counter, List postedFile) + { + var pathToSave = Path.Combine(uploadpath, "Response-" + responseId); + String fullDirectoryPath = Path.Combine(pathToSave, "Answer-" + answerId); + List attachments = new List(); + foreach (IFormFile item in postedFile) + { + + counter++; + var UserfileName = Path.GetFileName(item.FileName); + var extension = System.IO.Path.GetExtension(UserfileName); + var fileName = String.Format("Attachment_{0}{1}", counter, extension); + var stream = item.OpenReadStream(); + BlobClient client = _containerClient.GetBlobClient(fullDirectoryPath + "/" + fileName); + string dbPath = fullDirectoryPath + "/" + fileName; + var result = await client.UploadAsync(stream, true); + attachments.Add(new Models.Attachment { AnswerId = answerId, ResponseId = responseId, IsDeleted = false, FileName = UserfileName, URI = dbPath }); + } + return attachments; + } + public async Task> UploadAttachment(int responseId, int counter, List answers) + { + List attachments = new List(); + try + { + foreach (var item in answers) + { + int answerId = item.AnswerId; + var pathToSave = Path.Combine(uploadpath, "Response-" + responseId); + String fullDirectoryPath = Path.Combine(pathToSave, "Answer-" + answerId); + foreach (var file in item.postedFiles) + { + counter++; + + var UserfileName = Path.GetFileName(file.FileName); + var fileName = String.Format("Attachment_{0}{1}", counter, file.FileExtension); + byte[] byteArray = Convert.FromBase64String(file.FileContent); + MemoryStream stream = new MemoryStream(byteArray); + BlobClient client = _containerClient.GetBlobClient(fullDirectoryPath + "/" + fileName); + string dbPath = fullDirectoryPath + "/" + fileName; + var result = await client.UploadAsync(stream, true); + attachments.Add(new Models.Attachment { AnswerId = answerId, ResponseId = responseId, IsDeleted = false, FileName = UserfileName, URI = dbPath }); + } + } + return attachments; + } + catch (Exception ex) + { + return new List(); + } + + + } + public async Task> UpdateAttachments(int responseId, List answers, IEnumerable attachments) + { + List Dbattachments = new List(); + foreach (Models.Attachment searchFile in attachments) + { + Movefile(searchFile.URI); + } + foreach (var item in answers) + { + int answerId = item.AnswerId; + var pathToSave = Path.Combine(uploadpath, "Response-" + responseId); + String fullDirectoryPath = Path.Combine(pathToSave, "Answer-" + answerId); + foreach (var file in item.postedFiles) + { + Models.Attachment attachment = attachments.Where(a => a.Id == file.AttachmentId).FirstOrDefault(); + var UserfileName = Path.GetFileName(file.FileName); + var fileName = String.Format("Attachment_{0}{1}", attachment?.Id, file.FileExtension); + byte[] byteArray = Convert.FromBase64String(file.FileContent); + MemoryStream stream = new MemoryStream(byteArray); + BlobClient client = _containerClient.GetBlobClient(fullDirectoryPath + "/" + fileName); + string dbPath = fullDirectoryPath + "/" + fileName; + var result = await client.UploadAsync(stream, true); + Dbattachments.Add(new Models.Attachment { Id = attachment.Id, AnswerId = answerId, ResponseId = responseId, IsDeleted = false, FileName = UserfileName, URI = dbPath }); + } + } + return Dbattachments; } public async Task>> UploadFiles(List files) @@ -35,10 +122,52 @@ namespace DamageAssesment.Api.Attachments.Providers return azureResponse; } - public void DeleteFile(string url) + public string getMovefilename(string movefilename) { - var blob = _containerClient.GetBlockBlobClient(url); - blob.DeleteIfExists(); + var list = movefilename.Split('.'); + if (list.Length > 0) + list[list.Length - 1] = DateTime.Now.ToShortDateString().Replace("/", "_") + "_" + DateTime.Now.ToShortTimeString().Replace("/", "_") + "." + list[list.Length - 1]; + return string.Join("_", list); + } + public void Movefile(string path) + { + try + { + if (path != "") + { + string MovePath = getMovefilename(path.Replace(uploadpath, Deletepath)); + // Get references to the source and destination blobs + BlobClient sourceBlobClient = _containerClient.GetBlobClient(path); + BlobClient destinationBlobClient = _containerClient.GetBlobClient(MovePath); + // Start the copy operation from the source to the destination + destinationBlobClient.StartCopyFromUri(sourceBlobClient.Uri); + + // Check if the copy operation completed successfully + WaitForCopyToComplete(destinationBlobClient); + + // Delete the source blob after a successful copy + sourceBlobClient.DeleteIfExists(); + } + } + catch (Exception ex) + { + + } + } + static void WaitForCopyToComplete(BlobClient blobClient) + { + BlobProperties properties = blobClient.GetProperties(); + + while (properties.CopyStatus == CopyStatus.Pending) + { + Task.Delay(TimeSpan.FromSeconds(1)); + properties = blobClient.GetProperties(); + } + } + public void Deletefile(string url) + { + BlobClient sourceBlobClient = _containerClient.GetBlobClient(url); + sourceBlobClient.DeleteIfExists(); } } } \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.json index c894752..a664e43 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Attachments/appsettings.json @@ -11,12 +11,14 @@ "AllowedHosts": "*", "Fileupload": { "folderpath": "DMS_Attachments/Active", - "Deletepath": "DMS_Attachments/Deleted" + "Deletepath": "DMS_Attachments/Deleted", + "BlobConnectionString": "DefaultEndpointsProtocol=https;AccountName=damagedoculink;AccountKey=blynpwrAQtthEneXC5f4vFewJ3tPV+QZUt1AX3nefZScPPjkr5hMoC18B9ni6/ZYdhRiERPQw+hB+AStonf+iw==;EndpointSuffix=core.windows.net", + "BlobContainerName": "doculinks" }, "ConnectionStrings": { - //"AttachmentConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" - // "AttachmentConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;" - "AttachmentConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" + "AttachmentConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"AttachmentConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" + } } \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs index 14ddaaa..d7253e0 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs @@ -17,7 +17,7 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockDocumentService = new Mock(); var mockUploadService = new Mock(); var mockResponse = await MockData.getNoContentResponses(); - mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms","en",null)).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms", "en", null)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); var result = (NoContentResult)await DocumentProvider.GetDocumentsAsync("", "", null); @@ -44,10 +44,10 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockDocumentService = new Mock(); var mockUploadService = new Mock(); var mockResponse = await MockData.getOkResponses(); - mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms","en", null)).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms", "en", null)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); - var result = (OkObjectResult)await DocumentProvider.GetDocumentsAsync("forms","en", null); + var result = (OkObjectResult)await DocumentProvider.GetDocumentsAsync("forms", "en", null); Assert.Equal(200, result.StatusCode); } @@ -97,7 +97,7 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockDocumentService = new Mock(); var mockUploadService = new Mock(); var mockResponse = await MockData.getOkResponse(1); - mockDocumentService.Setup(service => service.GetDocumentAsync(1,"forms","en")).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.GetDocumentAsync(1, "forms", "en")).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); var result = (OkObjectResult)await DocumentProvider.GetDocumentAsync(1, "forms", "en"); @@ -154,9 +154,9 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockResponse = await MockData.getOkResponse(1); var mockInputDocument = await MockData.getInputDocumentData(); var DocumentResponse = await MockData.GetDocuLinksInfo(1); - mockDocumentService.Setup(service => service.UpdateDocumentAsync(1,mockInputDocument)).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.UpdateDocumentAsync(1, mockInputDocument)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); - var result = (NotFoundResult)await DocumentProvider.UpdateDocument(1,DocumentResponse); + var result = (NotFoundResult)await DocumentProvider.UpdateDocument(1, DocumentResponse); Assert.Equal(404, result.StatusCode); } @@ -168,9 +168,9 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockUploadService = new Mock(); var mockResponse = await MockData.getBadRequestResponse(); var mockInputDocument = await MockData.getInputDocumentData(); - mockDocumentService.Setup(service => service.UpdateDocumentAsync(99,mockInputDocument)).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.UpdateDocumentAsync(99, mockInputDocument)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); - var result = (BadRequestObjectResult)await DocumentProvider.UpdateDocument(99,null); + var result = (BadRequestObjectResult)await DocumentProvider.UpdateDocument(99, null); Assert.Equal(400, result.StatusCode); } @@ -235,7 +235,7 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockDocumentService = new Mock(); var mockUploadService = new Mock(); var mockResponse = await LinkTypeMockData.getOkResponse(1); - mockDocumentService.Setup(service => service.GetLinkTypeAsync(1,"en")).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.GetLinkTypeAsync(1, "en")).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); var result = (OkObjectResult)await DocumentProvider.GetLinkTypeAsync(1, "en"); @@ -290,9 +290,9 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockUploadService = new Mock(); var mockResponse = await LinkTypeMockData.getOkResponse(1); var mockInputDocument = await LinkTypeMockData.getInputLinkData(1); - mockDocumentService.Setup(service => service.UpdateLinkTypeAsync(1,mockInputDocument)).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.UpdateLinkTypeAsync(1, mockInputDocument)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); - var result = (OkObjectResult)await DocumentProvider.UpdateLinkType(1,mockInputDocument); + var result = (OkObjectResult)await DocumentProvider.UpdateLinkType(1, mockInputDocument); Assert.Equal(200, result.StatusCode); } @@ -304,9 +304,9 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockUploadService = new Mock(); var mockResponse = await LinkTypeMockData.getNotFoundResponse(); var mockInputDocument = await LinkTypeMockData.getInputLinkData(99); - mockDocumentService.Setup(service => service.UpdateLinkTypeAsync(99,mockInputDocument)).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.UpdateLinkTypeAsync(99, mockInputDocument)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); - var result = (NotFoundObjectResult)await DocumentProvider.UpdateLinkType(99,mockInputDocument); + var result = (NotFoundObjectResult)await DocumentProvider.UpdateLinkType(99, mockInputDocument); Assert.Equal(404, result.StatusCode); } @@ -318,7 +318,7 @@ namespace DamageAssesment.Api.DocuLinks.Test var mockUploadService = new Mock(); var mockResponse = await LinkTypeMockData.getBadRequestResponse(); var mockInputDocument = await LinkTypeMockData.getInputLinkData(1); - mockDocumentService.Setup(service => service.UpdateLinkTypeAsync(1,mockInputDocument)).ReturnsAsync(mockResponse); + mockDocumentService.Setup(service => service.UpdateLinkTypeAsync(1, mockInputDocument)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); var result = (BadRequestObjectResult)await DocumentProvider.UpdateLinkType(1, mockInputDocument); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs index 23ffae4..e5e2d67 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs @@ -14,25 +14,27 @@ namespace DamageAssesment.Api.DocuLinks.Test public static async Task<(bool, List, string)> getOkResponses() { List list = new List(); - + for (int i = 1; i < 4; i++) { Dictionary dicttitle = new Dictionary(); - Dictionary dictdesc = new Dictionary(); + Dictionary dictdesc = new Dictionary(); dicttitle.Add("en", "test"); dicttitle.Add("fr", "tester"); - dictdesc.Add("en", "test"); dictdesc.Add("fr", "tester"); + dictdesc.Add("en", "test"); dictdesc.Add("fr", "tester"); List DocuLinksTranslations = new List(); DocuLinksTranslations.Add(new DoculinkTranslation() { Language = "en", - title = "tel"+i, - description = "Sample"+i + title = "tel" + i, + description = "Sample" + i }); List doclinksAttachments = new List(); doclinksAttachments.Add(new DoculinkAttachments() { - docName = "",Path="www.google.com", - IsAttachments=false,CustomOrder=1 + docName = "", + Path = "www.google.com", + IsAttachments = false, + CustomOrder = 1 }); list.Add(new DocuLinks.Models.ResDoculink() { @@ -40,10 +42,10 @@ namespace DamageAssesment.Api.DocuLinks.Test Id = i, linkTypeId = i, IsActive = true, - titles= dicttitle, - description=dictdesc, - CustomOrder=i, - doclinksAttachments= doclinksAttachments + titles = dicttitle, + description = dictdesc, + CustomOrder = i, + doclinksAttachments = doclinksAttachments }); } List doculinks = list.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); @@ -120,8 +122,8 @@ namespace DamageAssesment.Api.DocuLinks.Test { List fileModels = new List(); - fileModels.Add( new FileModel() { FileName = "Sample", FileContent = "c2FtcGxl", FileExtension = ".txt",IsAttachments=true,CustomOrder=1 }); - return new ReqDoculink() { Id=id, linkTypeId = 1, CustomOrder = 1, Files = fileModels }; + fileModels.Add(new FileModel() { FileName = "Sample", FileContent = "c2FtcGxl", FileExtension = ".txt", IsAttachments = true, CustomOrder = 1 }); + return new ReqDoculink() { Id = id, linkTypeId = 1, CustomOrder = 1, Files = fileModels }; } public static async Task getInputDocumentData() { @@ -131,7 +133,7 @@ namespace DamageAssesment.Api.DocuLinks.Test Language = "en", title = "tel", description = "Sample" - }); + }); List doclinksAttachments = new List(); doclinksAttachments.Add(new DoculinkAttachments() { @@ -145,9 +147,9 @@ namespace DamageAssesment.Api.DocuLinks.Test Id = 1, linkTypeId = 1, IsActive = true, - CustomOrder=1, + CustomOrder = 1, documentsTranslations = DocuLinksTranslations, - doclinksAttachments= doclinksAttachments + doclinksAttachments = doclinksAttachments }; } public static async Task> getInputDocuLinksData() diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs index 99d00a8..f151186 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Controllers/DoculinkController.cs @@ -2,6 +2,7 @@ using DamageAssesment.Api.DocuLinks.Interfaces; using DamageAssesment.Api.DocuLinks.Models; using DamageAssesment.Api.DocuLinks.Providers; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -12,18 +13,20 @@ namespace DamageAssesment.Api.DocuLinks.Controllers { private readonly IDoculinkProvider documentsProvider; private readonly IUploadService uploadService; + private readonly IAzureBlobService azureBlobService; - public DoculinkController(IDoculinkProvider documentsProvider,IUploadService uploadService) + public DoculinkController(IDoculinkProvider documentsProvider, IUploadService uploadService) { this.documentsProvider = documentsProvider; - this.uploadService = uploadService; + this.uploadService = uploadService; } /// /// Get all Doculink type. /// [HttpGet] + [Authorize(Roles = "admin")] [Route("doculinks/types")] [Route("doculinks/types/{language:alpha}")] public async Task GetLinkTypesAsync(string? language) @@ -38,6 +41,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// Get a Doculink type by id. /// + [Authorize(Roles = "admin")] [HttpGet] [Route("doculinks/types/{id}")] [Route("doculinks/types/{id}/{language:alpha}")] @@ -53,6 +57,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// Update a existing Doculink type. /// + [Authorize(Roles = "admin")] [HttpPut] [Route("doculinks/types/{id}")] public async Task UpdateLinkType(int id,Models.LinkType linkType) @@ -74,6 +79,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// Create a new Doculink type. /// + [Authorize(Roles = "admin")] [HttpPost] [Route("doculinks/types")] public async Task CreateLinkType(Models.LinkType linkType) @@ -92,6 +98,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// Delete a existing Doculink type by id. /// + [Authorize(Roles = "admin")] [HttpDelete] [Route("doculinks/types/{id}")] public async Task DeleteLinkType(int id) @@ -104,9 +111,10 @@ namespace DamageAssesment.Api.DocuLinks.Controllers return NotFound(); } /// - /// Get all Doculink. + /// Get all documents. /// - /// + + [Authorize(Roles = "admin")] [Route("doculinks")] [Route("doculinks/{linktype:alpha}")] [Route("doculinks/{linktype:alpha}/{language:alpha}")] @@ -154,6 +162,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// Get a Doculink by id. /// + [Authorize(Roles = "admin")] [HttpGet] [Route("doculinks/{id}")] [Route("doculinks/{id}/{linktype:alpha}")] @@ -170,6 +179,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// update existing doclink. /// + [Authorize(Roles = "admin")] [HttpPut] [Route("doculinks/{id}")] public async Task UpdateDocument(int id,ReqDoculink documentInfo) @@ -180,7 +190,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) { @@ -195,6 +205,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// Create new doclink. /// + // [Authorize(Roles = "admin")] [HttpPost] [Route("doculinks")] public async Task CreateDocument(ReqDoculink documentInfo) @@ -203,8 +214,8 @@ namespace DamageAssesment.Api.DocuLinks.Controllers { if (documentInfo != null) { - var documents = await this.documentsProvider.GetDocumentCounter(); - Models.Doculink DocuLink= uploadService.UploadDocument(documents.counter, documentInfo); + //var documents = await this.documentsProvider.GetDocumentCounter(); + Models.Doculink DocuLink= uploadService.UploadDocument(1, documentInfo); var result = await this.documentsProvider.PostDocumentAsync(DocuLink); if (result.IsSuccess) { @@ -222,6 +233,7 @@ namespace DamageAssesment.Api.DocuLinks.Controllers /// /// Delete Doculink by id. /// + [Authorize(Roles = "admin")] [HttpDelete] [Route("doculinks/{id}")] public async Task DeleteDocument(int id) diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/DamageAssesment.Api.DocuLinks.csproj b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/DamageAssesment.Api.DocuLinks.csproj index 45347ee..7058f27 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/DamageAssesment.Api.DocuLinks.csproj +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/DamageAssesment.Api.DocuLinks.csproj @@ -11,7 +11,8 @@ - + + diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkDbContext.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkDbContext.cs index f24303e..7eeec65 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkDbContext.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Db/DoculinkDbContext.cs @@ -15,7 +15,7 @@ namespace DamageAssesment.Api.DocuLinks.Db protected override void OnConfiguring(DbContextOptionsBuilder options) { // connect to sql server with connection string from app settings - options.UseSqlServer(_Configuration.GetConnectionString("DoculinConnection")); + options.UseSqlServer(_Configuration.GetConnectionString("DoculinkConnection")); } public DbSet Documents { get; set; } public DbSet LinkTypes { get; set; } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IAzureBlobService.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IAzureBlobService.cs index 844945e..043d8a1 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IAzureBlobService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IAzureBlobService.cs @@ -1,10 +1,14 @@ using Azure.Storage.Blobs.Models; +using DamageAssesment.Api.DocuLinks.Models; namespace DamageAssesment.Api.DocuLinks.Interfaces { public interface IAzureBlobService { Task>> UploadFiles(List files); + Task UploadDocument(int counter, ReqDoculink documentInfo); + Task UpdateDocuments(int counter, Models.Doculink document, ReqDoculink documentInfo); void DeleteFile(string path); + void Movefile(string path); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs index f28dd76..cdd5a72 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Program.cs @@ -2,19 +2,69 @@ using DamageAssesment.Api.DocuLinks.Db; using DamageAssesment.Api.DocuLinks.Interfaces; using DamageAssesment.Api.DocuLinks.Providers; using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.IdentityModel.Tokens; using System.Reflection; +using System.Text; +using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. - +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); +builder.Services.AddAuthentication(item => +{ + item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(item => +{ + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}); builder.Services.AddControllers(); -builder.Services.AddSwaggerGen(c => +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + + options.AddSecurityRequirement(securityRequirements); }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); @@ -25,7 +75,7 @@ builder.Services.AddScoped(); builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); //4/30 builder.Services.AddDbContext(option => { - option.UseSqlServer("DoculinConnection"); + option.UseSqlServer("DoculinkConnection"); }); var app = builder.Build(); @@ -36,6 +86,7 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } +app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/AzureBlobService.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/AzureBlobService.cs index bfa2ca4..9931de2 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/AzureBlobService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/AzureBlobService.cs @@ -1,8 +1,17 @@  +using Azure; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Azure.Storage.Blobs.Specialized; using DamageAssesment.Api.DocuLinks.Interfaces; +using DamageAssesment.Api.DocuLinks.Models; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Configuration; +using Microsoft.VisualBasic; +using System.ComponentModel; +using System.IO; +using System.Text; +using System.Threading.Tasks; namespace DamageAssesment.Api.DocuLinks.Providers { @@ -10,11 +19,111 @@ namespace DamageAssesment.Api.DocuLinks.Providers { BlobServiceClient _blobClient; BlobContainerClient _containerClient; - string azureConnectionString = ""; - public AzureBlobService() + string azureConnectionString; + private string uploadpath = ""; + private string Deletepath = ""; + public AzureBlobService(IConfiguration configuration) { - _blobClient = new BlobServiceClient(azureConnectionString); - _containerClient = _blobClient.GetBlobContainerClient("apiimages"); + uploadpath = configuration.GetValue("Fileupload:folderpath"); + Deletepath = configuration.GetValue("Fileupload:Deletepath"); + _blobClient = new BlobServiceClient(configuration.GetValue("Fileupload:BlobConnectionString")); + _containerClient = _blobClient.GetBlobContainerClient(configuration.GetValue("Fileupload:BlobContainerName")); + } + public async Task UploadDocument(int counter, ReqDoculink documentInfo) + { + Models.Doculink Documents = new Models.Doculink(); + List attachments = new List(); + try + { + string path = "", UserfileName = ""; + if (documentInfo.Files != null) + { + + int counter1 = 1; + foreach (var item in documentInfo.Files) + { + if (item.IsAttachments) + { + UserfileName = Path.GetFileName(item.FileName); + var fileName = String.Format("Document_{0}_{1}{2}", counter, counter1, item.FileExtension); + byte[] byteArray = Convert.FromBase64String(item.FileContent); + MemoryStream stream = new MemoryStream(byteArray); + BlobClient client = _containerClient.GetBlobClient(uploadpath + "/" + fileName); + var result = await client.UploadAsync(stream, true); + path = uploadpath + "/" + fileName; + counter1++; + } + else + path = item.url; + attachments.Add(new Models.DoculinkAttachments { docName = UserfileName, Path = path, IsAttachments = item.IsAttachments, CustomOrder = item.CustomOrder }); + } + } + Documents = new Models.Doculink() + { + linkTypeId = documentInfo.linkTypeId, + documentsTranslations = documentInfo.documentsTranslations, + doclinksAttachments = attachments, + IsDeleted = false, + CustomOrder = documentInfo.CustomOrder, + IsActive = true + }; + + return Documents; + } + catch (Exception ex) + { + return new Models.Doculink(); + } + + + } + + public async Task UpdateDocuments(int counter, Models.Doculink document, ReqDoculink documentInfo) + { + try + { + foreach (var item in document.doclinksAttachments) + { + Movefile(item.Path); + } + string path = "", UserfileName = ""; + List attachments = new List(); + int counter1 = 1; + foreach (var item in documentInfo.Files) + { + if (item.IsAttachments) + { + UserfileName = Path.GetFileName(item.FileName); + var fileName = String.Format("Document_{0}_{1}{2)", document.Id, counter1, item.FileExtension); + byte[] byteArray = Encoding.UTF8.GetBytes(item.FileContent); + MemoryStream stream = new MemoryStream(byteArray); + BlobClient client = _containerClient.GetBlobClient(uploadpath + "/" + fileName); + path = uploadpath + "/" + fileName; + var result = await client.UploadAsync(stream, true); + counter1++; + } + else + path = item.url; + attachments.Add(new Models.DoculinkAttachments { docName = UserfileName, Path = path, IsAttachments = item.IsAttachments, CustomOrder = item.CustomOrder }); + } + Models.Doculink Documents = new Models.Doculink() + { + Id = documentInfo.Id, + linkTypeId = documentInfo.linkTypeId, + documentsTranslations = documentInfo.documentsTranslations, + IsActive = true, + IsDeleted = false, + CustomOrder = documentInfo.CustomOrder, + doclinksAttachments = attachments + }; + + return Documents; + } + + catch (Exception ex) + { + return new Models.Doculink(); + } } public async Task>> UploadFiles(List files) @@ -35,10 +144,52 @@ namespace DamageAssesment.Api.DocuLinks.Providers return azureResponse; } + public string getMovefilename(string movefilename) + { + var list = movefilename.Split('.'); + if (list.Length > 0) + list[list.Length - 1] = DateTime.Now.ToShortDateString().Replace("/", "_") +"_"+ DateTime.Now.ToShortTimeString().Replace("/", "_")+"." + list[list.Length - 1]; + return string.Join("_", list); + } + public void Movefile(string path) + { + try + { + if (path != "") + { + string MovePath = getMovefilename(path.Replace(uploadpath, Deletepath)); + // Get references to the source and destination blobs + BlobClient sourceBlobClient = _containerClient.GetBlobClient(path); + BlobClient destinationBlobClient = _containerClient.GetBlobClient(MovePath); + // Start the copy operation from the source to the destination + destinationBlobClient.StartCopyFromUri(sourceBlobClient.Uri); + + // Check if the copy operation completed successfully + WaitForCopyToComplete(destinationBlobClient); + + // Delete the source blob after a successful copy + sourceBlobClient.DeleteIfExists(); + } + } + catch(Exception ex) + { + + } + } + static void WaitForCopyToComplete(BlobClient blobClient) + { + BlobProperties properties = blobClient.GetProperties(); + + while (properties.CopyStatus == CopyStatus.Pending) + { + Task.Delay(TimeSpan.FromSeconds(1)); + properties = blobClient.GetProperties(); + } + } public void DeleteFile(string url) { - var blob = _containerClient.GetBlockBlobClient(url); - blob.DeleteIfExists(); + BlobClient sourceBlobClient = _containerClient.GetBlobClient(url); + sourceBlobClient.DeleteIfExists(); } } } \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs index 371b8b3..1228982 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs @@ -21,20 +21,22 @@ namespace DamageAssesment.Api.DocuLinks.Providers private DoculinkDbContext DocumentDbContext; private ILogger logger; private IUploadService uploadservice; + private IAzureBlobService azureBlobService; private IMapper mapper; - public DoculinkProvider(DoculinkDbContext DocumentDbContext, ILogger logger, IMapper mapper, IUploadService uploadservice) + public DoculinkProvider(DoculinkDbContext DocumentDbContext, ILogger logger, IMapper mapper, IUploadService uploadservice, IAzureBlobService azureBlobService) { this.DocumentDbContext = DocumentDbContext; this.logger = logger; this.mapper = mapper; this.uploadservice = uploadservice; - SeedData(); + this.azureBlobService = azureBlobService; + //SeedData(); } - private void SeedData() + private async Task SeedDataAsync() { if (!DocumentDbContext.LinkTypes.Any()) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs index 807a2e0..0e71850 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/UploadService.cs @@ -80,15 +80,16 @@ namespace DamageAssesment.Api.DocuLinks.Providers string path = "", UserfileName = ""; List attachments = new List(); + int counter1 = 1; foreach (var item in documentInfo.Files) { - counter++; if (item.IsAttachments) { UserfileName = Path.GetFileName(item.FileName); - var fileName = String.Format("Document_{0}{1}", counter, item.FileExtension); + var fileName = String.Format("Document_{0}_{1}{2}", document.Id, counter1, item.FileExtension); path = Path.Combine(fullDirectoryPath, fileName); File.WriteAllBytes(path, Convert.FromBase64String(item.FileContent)); + counter1++; } else path = item.url; diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.json index a513807..998c8de 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/appsettings.json @@ -1,4 +1,7 @@ { + "JwtSettings": { + "securitykey": "bWlhbWkgZGFkZSBzY2hvb2xzIHNlY3JldCBrZXk=" + }, "Logging": { "LogLevel": { "Default": "Information", @@ -7,13 +10,14 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - //"DoculinConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;", - //"DoculinConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;" - "DoculinConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" + "DoculinkConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"DoculinkConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" }, "Fileupload": { "folderpath": "DASA_Documents/Active", - "Deletepath": "DASA_Documents/Deleted" + "Deletepath": "DASA_Documents/Deleted", + "BlobConnectionString": "DefaultEndpointsProtocol=https;AccountName=damagedoculink;AccountKey=blynpwrAQtthEneXC5f4vFewJ3tPV+QZUt1AX3nefZScPPjkr5hMoC18B9ni6/ZYdhRiERPQw+hB+AStonf+iw==;EndpointSuffix=core.windows.net", + "BlobContainerName": "doculinks" } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Employees/Controllers/EmployeesController.cs b/DamageAssesmentApi/DamageAssesment.Api.Employees/Controllers/EmployeesController.cs index 05901c5..f247d17 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Employees/Controllers/EmployeesController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Employees/Controllers/EmployeesController.cs @@ -1,4 +1,5 @@ using DamageAssesment.Api.Employees.Interfaces; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -18,7 +19,7 @@ namespace DamageAssesment.Api.Employees.Controllers /// /// GET request for retrieving employees. /// - + [Authorize(Roles = "admin")] [HttpGet("employees")] public async Task GetEmployeesAsync() { @@ -35,7 +36,7 @@ namespace DamageAssesment.Api.Employees.Controllers /// /// GET request for retrieving an employee by ID. /// - + [Authorize(Roles = "admin")] [HttpGet("employees/{id}")] public async Task GetEmployeeByIdAsync(int id) { @@ -48,11 +49,12 @@ namespace DamageAssesment.Api.Employees.Controllers return NotFound(); } - + /// /// PUT request for updating an existing employee. /// /// The updated employee object. + [Authorize(Roles = "admin")] [HttpPut("employees/{id}")] public async Task UpdateEmployee(int id, Models.Employee Employee) { @@ -75,6 +77,7 @@ namespace DamageAssesment.Api.Employees.Controllers /// POST request for creating a new employee. /// /// The employee information for creating a new employee. + [Authorize(Roles = "admin")] [HttpPost("employees")] public async Task CreateEmployee(Models.Employee Employee) { @@ -93,6 +96,7 @@ namespace DamageAssesment.Api.Employees.Controllers /// DELETE request for deleting an existing employee. /// /// The ID of the employee to be deleted. + [Authorize(Roles = "admin")] [HttpDelete("employees/{id}")] public async Task DeleteEmployee(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs index 7d61871..0702b58 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Employees/Program.cs @@ -1,23 +1,74 @@ using DamageAssesment.Api.Employees.Db; using DamageAssesment.Api.Employees.Interfaces; using DamageAssesment.Api.Employees.Providers; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; using System.Reflection; +using System.Text; var builder = WebApplication.CreateBuilder(args); // Add services to the container. +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); +builder.Services.AddAuthentication(item => +{ + item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(item => +{ + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); -builder.Services.AddSwaggerGen(c => +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + + options.AddSecurityRequirement(securityRequirements); }); builder.Services.AddScoped(); @@ -43,6 +94,7 @@ if (app.Environment.IsDevelopment()) } } +app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.json index b442e2b..36ccc0e 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Employees/appsettings.json @@ -9,15 +9,9 @@ } }, "AllowedHosts": "*", - "settings": { - "endpoint1": "xxx", - "endpoint2": "xxx", - "endpoint3": "xxx" - }, "ConnectionStrings": { - //"EmployeeConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;", - //"EmployeeConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;" - "EmployeeConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" + "EmployeeConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"EmployeeConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/LocationsController.cs b/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/LocationsController.cs index cea800d..8de7678 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/LocationsController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/LocationsController.cs @@ -1,4 +1,5 @@ using DamageAssesment.Api.Locations.Interfaces; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -15,7 +16,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// Get all locations. /// - + [Authorize(Roles = "admin")] [HttpGet("locations")] public async Task GetLocationsAsync() { @@ -31,7 +32,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// Get all locations based on locationdId. /// - + [Authorize(Roles = "admin")] [HttpGet("locations/{id}")] public async Task GetLocationByIdAsync(int id) { @@ -47,7 +48,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// Update a Location. /// - + [Authorize(Roles = "admin")] [HttpPut("locations/{id}")] public async Task UpdateLocation(int id, Models.Location Location) { @@ -65,7 +66,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// Save a new location. /// - + [Authorize(Roles = "admin")] [HttpPost("locations")] public async Task CreateLocation(Models.Location Location) { @@ -83,7 +84,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// Delete an existing location. /// - + [Authorize(Roles = "admin")] [HttpDelete("locations/{id}")] public async Task DeleteLocation(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/RegionsController.cs b/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/RegionsController.cs index 172043c..d7fe03c 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/RegionsController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Locations/Controllers/RegionsController.cs @@ -1,4 +1,5 @@ using DamageAssesment.Api.Locations.Interfaces; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace DamageAssesment.Api.Locations.Controllers @@ -15,7 +16,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// Get all regions.2 /// - + [Authorize(Roles = "admin")] [HttpGet("regions")] public async Task GetRegionsAsync() { @@ -29,7 +30,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// GET request for retrieving a region by its ID. /// - + [Authorize(Roles = "admin")] [HttpGet("regions/{id}")] public async Task GetRegionAsync(int id) { @@ -43,7 +44,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// POST request for creating a new region. /// - + [Authorize(Roles = "admin")] [HttpPost("regions")] public async Task PostRegionAsync(Models.Region region) { @@ -57,7 +58,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// /// PUT request for updating an existing region. /// - + [Authorize(Roles = "admin")] [HttpPut("regions/{id}")] public async Task PutRegionAsync(int id, Models.Region region) { @@ -75,7 +76,7 @@ namespace DamageAssesment.Api.Locations.Controllers /// DELETE request for deleting a region based on ID. /// - + [Authorize(Roles = "admin")] [HttpDelete("regions/{id}")] public async Task DeleteRegionAsync(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs index f8136bd..cf4c0d2 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Locations/Program.cs @@ -1,23 +1,73 @@ using DamageAssesment.Api.Locations.Db; using DamageAssesment.Api.Locations.Interfaces; using DamageAssesment.Api.Locations.Providers; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; using System.Reflection; +using System.Text; var builder = WebApplication.CreateBuilder(args); // Add services to the container. - +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); +builder.Services.AddAuthentication(item => +{ + item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(item => +{ + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); -builder.Services.AddSwaggerGen(c => +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + + options.AddSecurityRequirement(securityRequirements); }); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -26,7 +76,10 @@ builder.Services.AddDbContext(option => { option.UseSqlServer("LocationConnection"); }); + + var app = builder.Build(); +// Add services to the container. // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) @@ -44,6 +97,7 @@ if (app.Environment.IsDevelopment()) } } +app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.json index 22611e3..bceef58 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Locations/appsettings.json @@ -9,10 +9,12 @@ } }, "AllowedHosts": "*", + //"ConnectionStrings": { + // "LocationConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //}, "ConnectionStrings": { - //"LocationConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;", - // "LocationConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;" - "LocationConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" + "LocationConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"LocationConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs index 7dec941..1171b0d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs @@ -1,4 +1,5 @@ using DamageAssesment.Api.Questions.Interfaces; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace DamageAssesment.Api.Questions.Controllers @@ -10,16 +11,13 @@ namespace DamageAssesment.Api.Questions.Controllers public QuestionsController(IQuestionsProvider questionsProvider) { - this.questionsProvider = questionsProvider; - } - /// /// GET request for retrieving questions. /// - - // get all questions + //get all questions + [Authorize(Roles = "admin,survey,user,report")] [Route("questions")] [Route("questions/{language:alpha}")] [HttpGet] @@ -37,6 +35,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// /// GET request for retrieving a question by ID. /// + [Authorize(Roles = "admin,survey,user,report")] [Route("questions/{id}/{language:alpha}")] [Route("questions/{id:int}")] [HttpGet] @@ -55,6 +54,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// GET request for retrieving survey questions based on a survey ID. /// Uri: {Optional language}/GetSurveyQuestions/{surveyId} :Default returns question in all languages /// + [Authorize(Roles = "admin,survey,user,report")] [Route("questions/bysurvey/{surveyId:int}")] [Route("questions/bysurvey/{surveyId:int}/{language:alpha}")] [HttpGet] @@ -71,6 +71,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// PUT request for updating a question (multilingual). /// + [Authorize(Roles = "admin")] [HttpPut("questions")] public async Task UpdateQuestion(Models.Question question) { @@ -92,6 +93,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// POST request for creating a new question (multilingual). /// + [Authorize(Roles = "admin")] [HttpPost("questions")] public async Task CreateQuestion(Models.Question question) { @@ -110,6 +112,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// DELETE request for deleting a question based on ID. /// + [Authorize(Roles = "admin")] [HttpDelete("questions/{id}")] public async Task DeleteQuestion(int id) { @@ -125,6 +128,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// GET request for retrieving question categories. /// + [Authorize(Roles = "admin,user,report")] [HttpGet("questions/categories")] [HttpGet("questions/categories/{language:alpha}")] public async Task GetQuestionCategoriesAsync(string? language) @@ -139,7 +143,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// /// GET request for retrieving a question category by ID. /// - + [Authorize(Roles = "admin,report")] [HttpGet("questions/categories/{id:int}")] [HttpGet("questions/categories/{id:int}/{language:alpha}")] public async Task GetQuestionCategoryAsync(int id,string? language) @@ -156,7 +160,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// /// PUT request for updating a question category. /// - + [Authorize(Roles = "admin,survey,report")] [HttpPut("questions/categories")] public async Task UpdateQuestionCategory(Models.QuestionCategory questionCategory) { @@ -178,6 +182,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// POST request for creating a new question category. /// + [Authorize(Roles = "admin")] [HttpPost("questions/categories")] public async Task CreateQuestionCategory(Models.QuestionCategory questionCategory) { @@ -196,6 +201,7 @@ namespace DamageAssesment.Api.Questions.Controllers /// DELETE request for deleting a question category based on ID. /// + [Authorize(Roles = "admin")] [HttpDelete("questions/categories/{id}")] public async Task DeleteQuestionCategory(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/Question.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/Question.cs index b6c1668..f7fe7fb 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/Question.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Models/Question.cs @@ -12,7 +12,7 @@ public bool IsRequired { get; set; } public bool Comment { get; set; } public bool Key { get; set; } - public int? SurveyId { get; set; } + public int SurveyId { get; set; } public int CategoryId { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs index c47a38d..dfd6a07 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Program.cs @@ -1,11 +1,33 @@ using DamageAssesment.Api.Questions.Db; using DamageAssesment.Api.Questions.Interfaces; using DamageAssesment.Api.Questions.Providers; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Models; using System.Reflection; +using System.Text; var builder = WebApplication.CreateBuilder(args); - +// Add services to the container. +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); +builder.Services.AddAuthentication(item => +{ + item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(item => +{ + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}); // Add services to the container. builder.Services.AddControllers(); @@ -17,13 +39,41 @@ builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); -builder.Services.AddSwaggerGen(c => +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + options.AddSecurityRequirement(securityRequirements); }); + builder.Services.AddDbContext(option => { option.UseSqlServer("QuestionConnection"); @@ -43,7 +93,7 @@ if (app.Environment.IsDevelopment()) questionProvider.SeedData(); } } - +app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.json index 3d3bbda..e59b6ea 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/appsettings.json @@ -10,9 +10,8 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - //"QuestionConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" - // "QuestionConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;" - "QuestionConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" + "QuestionConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"QuestionConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs index 48cec58..59c764d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs @@ -23,17 +23,16 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1); Assert.Equal(200, result.StatusCode); } - [Fact(DisplayName = "Get Responses - BadRequest case")] public async Task GetSurveyResponsesAsync_ShouldReturnStatusCode204() { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (BadRequestObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1); Assert.Equal(400, result.StatusCode); } @@ -43,9 +42,9 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1,1); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1, 1); Assert.Equal(200, result.StatusCode); } @@ -53,9 +52,9 @@ namespace DamageAssesment.SurveyResponses.Test public async Task GetSurveyResponsesBySurveyAsync_ShouldReturnStatusCode204() { var mockResponse = await MockData.getResponse(); - mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesAsync(1,1); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesAsync(1, 1); Assert.Equal(204, result.StatusCode); } @@ -67,9 +66,9 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1,1); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1); Assert.Equal(200, result.StatusCode); } @@ -78,7 +77,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1); Assert.Equal(204, result.StatusCode); } @@ -88,9 +87,9 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes",1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes",1); + mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes", 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes", 1); Assert.Equal(200, result.StatusCode); } @@ -99,8 +98,8 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes", 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes",1); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes", 1); Assert.Equal(204, result.StatusCode); } @@ -110,8 +109,8 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetAnswersByRegionAsync(1, 1); Assert.Equal(200, result.StatusCode); } @@ -121,7 +120,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (NoContentResult)await surveyResponseProvider.GetAnswersByRegionAsync(1, 1); Assert.Equal(204, result.StatusCode); } @@ -132,7 +131,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesByMaintenanceCenterAsync(1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetAnswersByMaintenaceCentersync(1, 1); Assert.Equal(200, result.StatusCode); } @@ -142,7 +141,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesByMaintenanceCenterAsync(1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (NoContentResult)await surveyResponseProvider.GetAnswersByMaintenaceCentersync(1, 1); Assert.Equal(204, result.StatusCode); } @@ -153,7 +152,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponseByIdAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponseByIdAsync(1); Assert.Equal(200, result.StatusCode); } @@ -163,7 +162,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponseByIdAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponseByIdAsync(1); Assert.Equal(204, result.StatusCode); } @@ -175,7 +174,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.PostSurveyResponseAsync(mockRequestObject)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); var result = (OkObjectResult)await surveyResponseController.PostSurveysAsync(mockRequestObject); Assert.Equal(200, result.StatusCode); } @@ -186,7 +185,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.PostSurveyResponseAsync(mockRequestObject)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); var result = (BadRequestObjectResult)await surveyResponseController.PostSurveysAsync(mockRequestObject); Assert.Equal(400, result.StatusCode); } @@ -197,7 +196,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.PutSurveyResponseAsync(1, mockRequestObject)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); var result = (OkObjectResult)await surveyResponseController.PutSurveyResponseAsync(1, mockRequestObject); Assert.Equal(200, result.StatusCode); } @@ -208,7 +207,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.PutSurveyResponseAsync(1, mockRequestObject)).ReturnsAsync(mockResponse); ; - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); var result = (BadRequestObjectResult)await surveyResponseController.PutSurveyResponseAsync(1, mockRequestObject); Assert.Equal(400, result.StatusCode); } @@ -219,7 +218,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.DeleteSurveyResponseAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); var result = (OkObjectResult)await surveyResponseController.DeleteSurveyResponseAsync(1); Assert.Equal(200, result.StatusCode); } @@ -229,7 +228,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.DeleteSurveyResponseAsync(1)).ReturnsAsync(mockResponse); ; - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); var result = (NotFoundResult)await surveyResponseController.DeleteSurveyResponseAsync(1); Assert.Equal(404, result.StatusCode); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/ResponsesController.cs similarity index 90% rename from DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs rename to DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/ResponsesController.cs index 55b7f5d..4cdeab6 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/ResponsesController.cs @@ -1,15 +1,16 @@ using DamageAssesment.Api.Responses.Interfaces; using DamageAssesment.Api.Responses.Models; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace DamageAssesment.Api.Responses.Controllers { [ApiController] - public class SurveyResponsesController : ControllerBase + public class ResponsesController : ControllerBase { private readonly ISurveysResponse surveyResponseProvider; - public SurveyResponsesController(ISurveysResponse surveyResponseProvider) + public ResponsesController(ISurveysResponse surveyResponseProvider) { this.surveyResponseProvider = surveyResponseProvider; } @@ -17,6 +18,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// GET request for retrieving survey responses. /// + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/{employeeid:int}")] [Route("responses")] [HttpGet] @@ -36,6 +38,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// /// GET request for retrieving survey responses by survey ID. /// + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/bysurvey/{surveyid:int}/{employeeid:int}")] [Route("responses/bysurvey/{surveyid:int}")] [HttpGet] @@ -54,12 +57,13 @@ namespace DamageAssesment.Api.Responses.Controllers /// The ID of the survey for which responses are to be retrieved. /// The ID of the location for which responses are to be retrieved. + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/{surveyid:int}/{locationid:int}/{employeeid:int}")] [Route("responses/{surveyid:int}/{locationid:int}")] [HttpGet] - public async Task GetSurveyResponsesBySurveyAndLocationAsync(int surveyid, int locationid,int? employeeid) + public async Task GetSurveyResponsesBySurveyAndLocationAsync(int surveyid, int locationid, int? employeeid) { - var result = await this.surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(surveyid, locationid,employeeid ?? 0); + var result = await this.surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(surveyid, locationid, employeeid ?? 0); if (result.IsSuccess) { return Ok(result.SurveyResponses); @@ -73,6 +77,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// The ID of the question for which responses are to be retrieved. /// The answer for which responses are to be retrieved. + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/byanswer/{surveyid:int}/{questionid:int}/{answer:alpha}/{employeeid:int}")] [Route("responses/byanswer/{surveyid:int}/{questionid:int}/{answer:alpha}")] [HttpGet] @@ -91,6 +96,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// /// The ID of the survey for which answers are to be retrieved. + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/byregion/{surveyid:int}")] [Route("responses/byregion/{surveyid:int}/{employeeid}")] [HttpGet] @@ -107,6 +113,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// GET request for retrieving survey responses by survey ID and maintenance center. /// /// The ID of the survey for which responses are to be retrieved. + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/bymaintenancecenter/{surveyid:int}/{employeeid:int}")] [Route("responses/bymaintenancecenter/{surveyid:int}")] [HttpGet] @@ -124,6 +131,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// /// The ID of the survey response to be retrieved. + [Authorize(Roles = "admin,survey,user,report")] [HttpGet("responses/{id}")] public async Task GetSurveyResponseByIdAsync(int id) { @@ -140,6 +148,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// /// The survey response object to be created. + [Authorize(Roles = "admin,survey,user,report")] [HttpPost("responses")] public async Task PostSurveysAsync(Models.SurveyResponse surveyResponse) { @@ -156,6 +165,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// The ID of the survey response to be updated. /// The updated survey response object. + [Authorize(Roles = "admin,survey,user,report")] [HttpPut("responses/{id}")] public async Task PutSurveyResponseAsync(int id, Models.SurveyResponse surveyResponse) { @@ -173,6 +183,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// DELETE request for deleting an existing survey response. /// + [Authorize(Roles = "admin,survey,user,report")] [HttpDelete("responses/{id}")] public async Task DeleteSurveyResponseAsync(int id) { @@ -188,6 +199,7 @@ namespace DamageAssesment.Api.Responses.Controllers /// /// The answers to be submitted for the survey. + [Authorize(Roles = "admin,survey,user,report")] [HttpPost("responses/answers")] public async Task PostSurveyAnswersAsync(Request request) { @@ -199,6 +211,7 @@ namespace DamageAssesment.Api.Responses.Controllers return BadRequest(result.ErrorMessage); } + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/surveys/active")] [Route("responses/surveys/active/{language:alpha}")] [Route("responses/surveys/active/{employeeid:int}")] @@ -214,6 +227,7 @@ namespace DamageAssesment.Api.Responses.Controllers return NoContent(); } + [Authorize(Roles = "admin,survey,user,report")] [Route("responses/surveys/historic")] [Route("responses/surveys/historic/{language:alpha}")] [Route("responses/surveys/historic/{employeeid:int}")] diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAnswerServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAnswerServiceProvider.cs index 43ba9a1..7c23f55 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAnswerServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAnswerServiceProvider.cs @@ -4,9 +4,9 @@ namespace DamageAssesment.Api.Responses.Interfaces { public interface IAnswerServiceProvider { - Task> getAnswersAsync(); - Task> GetAnswersByResponseIdAsync(int responseId); + Task> getAnswersAsync(string token); + Task> GetAnswersByResponseIdAsync(int responseId, string token); - Task PostAnswersAsync(Models.Answer answer); + Task PostAnswersAsync(Models.Answer answer, string token); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAttachmentServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAttachmentServiceProvider.cs index 7350071..15f76a5 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAttachmentServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IAttachmentServiceProvider.cs @@ -4,7 +4,7 @@ namespace DamageAssesment.Api.Responses.Interfaces { public interface IAttachmentServiceProvider { - Task> getAttachmentsAsync(); - Task> PostAttachmentsAsync(Models.AttachmentInfo attachmentInfo); + Task> getAttachmentsAsync(string token); + Task> PostAttachmentsAsync(Models.AttachmentInfo attachmentInfo, string token); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IEmployeeServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IEmployeeServiceProvider.cs index ef9eb00..797cea7 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IEmployeeServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IEmployeeServiceProvider.cs @@ -1,10 +1,10 @@ -using DamageAssesment.Api.Responses.Models; +using DamageAssesment.Api.Responses.Models; namespace DamageAssesment.Api.Responses.Interfaces { public interface IEmployeeServiceProvider { - Task> getEmployeesAsync(); - Task getEmployeeAsync(int employeeId); + Task> getEmployeesAsync(string token); + Task getEmployeeAsync(int employeeId, string token); } -} +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IHttpUtil.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IHttpUtil.cs index a8578e0..ae5620f 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IHttpUtil.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IHttpUtil.cs @@ -1,9 +1,9 @@ -using DamageAssesment.Api.Responses.Models; +using DamageAssesment.Api.Responses.Models; namespace DamageAssesment.Api.Responses.Interfaces { public interface IHttpUtil { - Task SendAsync(HttpMethod method, string url, string JsonInput); + Task SendAsync(HttpMethod method, string url, string JsonInput, string token); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ILocationServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ILocationServiceProvider.cs index 75945cd..75ab80e 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ILocationServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ILocationServiceProvider.cs @@ -4,6 +4,6 @@ namespace DamageAssesment.Api.Responses.Interfaces { public interface ILocationServiceProvider { - Task> getLocationsAsync(); + Task> getLocationsAsync(string token); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs index 5c54e57..b37a171 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs @@ -4,8 +4,8 @@ namespace DamageAssesment.Api.Responses.Interfaces { public interface IQuestionServiceProvider { - Task> getQuestionsAsync(); - Task> getSurveyQuestionsAsync(int surveyId); - Task getQuestionsAsync(int questionId); + Task> getQuestionsAsync(string token); + Task> getSurveyQuestionsAsync(int surveyId, string token); + Task getQuestionsAsync(int questionId, string token); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IRegionServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IRegionServiceProvider.cs index be3b1c3..a97193e 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IRegionServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IRegionServiceProvider.cs @@ -4,6 +4,6 @@ namespace DamageAssesment.Api.Responses.Interfaces { public interface IRegionServiceProvider { - Task> getRegionsAsync(); + Task> getRegionsAsync(string token); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveyServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveyServiceProvider.cs index 64252c9..8c66bda 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveyServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveyServiceProvider.cs @@ -4,7 +4,7 @@ namespace DamageAssesment.Api.Responses.Interfaces { public interface ISurveyServiceProvider { - Task> getSurveysAsync(string language); - Task getSurveyAsync(int surveyId); + Task> getSurveysAsync(string language,string token); + Task getSurveyAsync(int surveyId,string token); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Employee.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Employee.cs index 72ceffc..3a84d81 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Employee.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Employee.cs @@ -11,6 +11,6 @@ namespace DamageAssesment.Api.Responses.Models public string OfficePhoneNumber { get; set; } public string Email { get; set; } public bool IsActive { get; set; } - public string? PreferredLanguage { get; set; } + public string PreferredLanguage { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs index 1641e75..379caab 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs @@ -5,6 +5,10 @@ using DamageAssesment.Api.Responses.Providers; using Microsoft.EntityFrameworkCore; using Polly; using System.Reflection; +using Microsoft.OpenApi.Models; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.IdentityModel.Tokens; +using System.Text; var builder = WebApplication.CreateBuilder(args); const int maxApiCallRetries = 3; @@ -14,6 +18,24 @@ const int intervalForCircuitBraker = 5; //5 seconds // Add services to the container. +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); +builder.Services.AddAuthentication(item => +{ + item.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + item.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; +}).AddJwtBearer(item => +{ + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle @@ -26,6 +48,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpClient(). AddTransientHttpErrorPolicy(policy => policy.WaitAndRetryAsync(maxApiCallRetries, _ => TimeSpan.FromSeconds(intervalToRetry))). @@ -35,12 +58,40 @@ builder.Services.AddHttpClient(). builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddEndpointsApiExplorer(); //builder.Services.AddSwaggerGen(); -builder.Services.AddSwaggerGen(c => + +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + options.AddSecurityRequirement(securityRequirements); }); builder.Services.AddDbContext(option => { @@ -55,6 +106,7 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } +app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Properties/launchSettings.json b/DamageAssesmentApi/DamageAssesment.Api.Responses/Properties/launchSettings.json index 7bd92b0..f3cba3b 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Properties/launchSettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Properties/launchSettings.json @@ -1,6 +1,6 @@ { "profiles": { - "DamageAssesment.Api.SurveyResponses": { + "DamageAssesment.Api.Responses": { "commandName": "Project", "launchBrowser": true, "launchUrl": "swagger", diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs index 0c6c817..00f030e 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs @@ -18,8 +18,10 @@ namespace DamageAssesment.Api.Responses.Providers private readonly IQuestionServiceProvider questionServiceProvider; private readonly ISurveyServiceProvider surveyServiceProvider; private readonly IMapper mapper; + private readonly IHttpContextAccessor httpContextAccessor; + private string token; - public SurveyResponsesProvider(SurveyResponseDbContext surveyResponseDbContext, ILogger logger, IAnswerServiceProvider answerServiceProvider, IRegionServiceProvider regionServiceProvider, ILocationServiceProvider locationServiceProvider, IEmployeeServiceProvider employeeServiceProvider, IAttachmentServiceProvider attachmentServiceProvider, IQuestionServiceProvider questionServiceProvider, ISurveyServiceProvider surveyServiceProvider, IMapper mapper) + public SurveyResponsesProvider(SurveyResponseDbContext surveyResponseDbContext, ILogger logger, IAnswerServiceProvider answerServiceProvider, IRegionServiceProvider regionServiceProvider, ILocationServiceProvider locationServiceProvider, IEmployeeServiceProvider employeeServiceProvider, IAttachmentServiceProvider attachmentServiceProvider, IQuestionServiceProvider questionServiceProvider, ISurveyServiceProvider surveyServiceProvider, IMapper mapper, IHttpContextAccessor httpContextAccessor) { this.surveyResponseDbContext = surveyResponseDbContext; this.logger = logger; @@ -30,8 +32,20 @@ namespace DamageAssesment.Api.Responses.Providers this.attachmentServiceProvider = attachmentServiceProvider; this.questionServiceProvider = questionServiceProvider; this.surveyServiceProvider = surveyServiceProvider; + this.httpContextAccessor = httpContextAccessor; this.mapper = mapper; SeedData(); + + token = httpContextAccessor.HttpContext.Request.Headers.Authorization; + if (token != null) + { + token = token.Replace("Bearer ", string.Empty); + } + else + { + token = ""; + } + // seedData(); } public void SeedData() @@ -111,14 +125,13 @@ namespace DamageAssesment.Api.Responses.Providers return (false, null, ex.Message); } } - public async Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int? employeeid, string language) { try { logger?.LogInformation("Querying to get SurveyResponse object from DB"); //get all the survey that already taken by the employee - var surveys = await surveyServiceProvider.getSurveysAsync(language); + var surveys = await surveyServiceProvider.getSurveysAsync(language, token); surveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now).ToList(); if (employeeid == null || employeeid == 0) return (true, surveys, null); @@ -139,7 +152,7 @@ namespace DamageAssesment.Api.Responses.Providers { logger?.LogInformation("Querying to get SurveyResponse object from DB"); - var surveys = await surveyServiceProvider.getSurveysAsync(language); + var surveys = await surveyServiceProvider.getSurveysAsync(language,token); // returning only historic data: end date is less than current date. surveys = surveys.Where(s => s.EndDate < DateTime.Now).ToList(); if (employeeid == null || employeeid == 0) @@ -164,7 +177,7 @@ namespace DamageAssesment.Api.Responses.Providers try { logger?.LogInformation("Querying to get Survey object from microservice"); - var survey = await surveyServiceProvider.getSurveyAsync(surveyId); + var survey = await surveyServiceProvider.getSurveyAsync(surveyId,token); if (survey != null) { @@ -195,7 +208,7 @@ namespace DamageAssesment.Api.Responses.Providers try { logger?.LogInformation("Querying to get Survey object from microservice"); - var survey = await surveyServiceProvider.getSurveyAsync(surveyId); + var survey = await surveyServiceProvider.getSurveyAsync(surveyId, token); if (survey != null) { @@ -226,7 +239,7 @@ namespace DamageAssesment.Api.Responses.Providers try { logger?.LogInformation("Querying to get Survey object from microservice"); - var survey = await surveyServiceProvider.getSurveyAsync(surveyId); + var survey = await surveyServiceProvider.getSurveyAsync(surveyId, token); if (survey != null) { @@ -257,8 +270,8 @@ namespace DamageAssesment.Api.Responses.Providers try { logger?.LogInformation("Querying to get Survey object from microservice"); - var survey = await surveyServiceProvider.getSurveyAsync(surveyId); - var question = await questionServiceProvider.getQuestionsAsync(questionId); + var survey = await surveyServiceProvider.getSurveyAsync(surveyId, token); + var question = await questionServiceProvider.getQuestionsAsync(questionId,token); bool IsCorrectAnswer = answer.ToLower().Equals("yes") || answer.ToLower().Equals("no") ? true : false; @@ -399,7 +412,7 @@ namespace DamageAssesment.Api.Responses.Providers { try { - var answersList = await answerServiceProvider.getAnswersAsync(); + var answersList = await answerServiceProvider.getAnswersAsync(token); if (answersList == null || !answersList.Any()) return null; @@ -422,8 +435,8 @@ namespace DamageAssesment.Api.Responses.Providers if (surveyAnswers == null || !surveyAnswers.Any()) return null; - var regions = await regionServiceProvider.getRegionsAsync(); - var locations = await locationServiceProvider.getLocationsAsync(); + var regions = await regionServiceProvider.getRegionsAsync(token); + var locations = await locationServiceProvider.getLocationsAsync(token); if (regions == null || !regions.Any() || locations == null || !locations.Any()) return null; @@ -433,18 +446,18 @@ namespace DamageAssesment.Api.Responses.Providers var result = from answer in surveyAnswers from location in locations where answer.LocationId.Equals(location.Id) - select new + select new { - answer.Id, - answer.QuestionId, - answer.AnswerText, - answer.Comment, - location.RegionId, - LocationId = location.Id, - answer.SurveyResponseId + answer.Id, + answer.QuestionId, + answer.AnswerText, + answer.Comment, + location.RegionId, + LocationId = location.Id, + answer.SurveyResponseId }; - + //group records by answer and region var q = from e in result @@ -452,13 +465,13 @@ namespace DamageAssesment.Api.Responses.Providers select new { g.Key.RegionId, - Answers = new + Answers = new { g.Key.AnswerText, Counter = g.Count() } }; - + //build the result List resultList = new List(); @@ -466,9 +479,9 @@ namespace DamageAssesment.Api.Responses.Providers { var answers = from u in q.ToList() where u.RegionId.Equals(region.Id) - select u.Answers; - - resultList.Add(new { RegionId = region.Id, region.Name, region.Abbreviation, Answers = answers }); + select u.Answers; + + resultList.Add(new { RegionId = region.Id, region.Name, region.Abbreviation, Answers = answers}); } //return the object result return new { Regions = resultList }; @@ -485,11 +498,11 @@ namespace DamageAssesment.Api.Responses.Providers { try { - var employee = await employeeServiceProvider.getEmployeeAsync(surveyResponse.EmployeeId); - var answers = await answerServiceProvider.GetAnswersByResponseIdAsync(surveyResponse.Id); - var allQuestions = await questionServiceProvider.getQuestionsAsync(); + var employee = await employeeServiceProvider.getEmployeeAsync(surveyResponse.EmployeeId, token); + var answers = await answerServiceProvider.GetAnswersByResponseIdAsync(surveyResponse.Id, token); + var allQuestions = await questionServiceProvider.getQuestionsAsync(token); var questions = allQuestions.Where(s => s.SurveyId == surveyResponse.SurveyId); - var attachments = await attachmentServiceProvider.getAttachmentsAsync(); + var attachments = await attachmentServiceProvider.getAttachmentsAsync(token); var result = new { @@ -528,91 +541,41 @@ namespace DamageAssesment.Api.Responses.Providers { try { - List surveyResonses = null; - Employee employee = null; - List employees = null; - if (employeeid == 0) - { - surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId).ToListAsync(); - employees = await employeeServiceProvider.getEmployeesAsync(); - } - else - { - surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId && x.EmployeeId == employeeid).ToListAsync(); - employee = await employeeServiceProvider.getEmployeeAsync(employeeid); - } - - var answers = await answerServiceProvider.getAnswersAsync(); - var questions = await questionServiceProvider.getQuestionsAsync(); + var surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId).ToListAsync(); + var employees = await employeeServiceProvider.getEmployeesAsync(token); + var answers = await answerServiceProvider.getAnswersAsync(token); + var questions = await questionServiceProvider.getQuestionsAsync(token); var surveyQuestions = from q in questions where q.SurveyId == surveyId select q; //var surveyQuestions = await questionServiceProvider.getSurveyQuestionsAsync(surveyId); - var attachments = await attachmentServiceProvider.getAttachmentsAsync(); + var attachments = await attachmentServiceProvider.getAttachmentsAsync(token); + var result = from r in surveyResonses + select new + { + r.Id, + r.SurveyId, + r.LocationId, + r.EmployeeId, + r.ClientDevice, + r.KeyAnswerResult, + r.Longitute, + r.Latitude, + Employee = (from e in employees where e.Id == r.EmployeeId select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), + answers = from ans in answers + where ans.SurveyResponseId == r.Id + select new + { + ans.Id, + ans.QuestionId, + ans.AnswerText, + ans.Comment, + Questions = (from q in surveyQuestions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(), + Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } - if (employeeid == 0) - { - var result = from r in surveyResonses - select new - { - r.Id, - r.SurveyId, - r.LocationId, - r.EmployeeId, - r.ClientDevice, - r.KeyAnswerResult, - r.Longitute, - r.Latitude, - Employee = (from e in employees where e.Id == r.EmployeeId select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), - answers = from ans in answers - where ans.SurveyResponseId == r.Id - select new - { - ans.Id, - ans.QuestionId, - ans.AnswerText, - ans.Comment, - Questions = (from q in surveyQuestions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(), - Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } - - } - }; - return result; - } - else - { - object _employee = new { }; - if (employee != null) - { - _employee = new { employee.Id, employee.Name, employee.BirthDate, employee.Email, employee.OfficePhoneNumber }; - } - var result = from r in surveyResonses - select new - { - r.Id, - r.SurveyId, - r.LocationId, - r.EmployeeId, - r.ClientDevice, - r.KeyAnswerResult, - r.Longitute, - r.Latitude, - Employee = _employee, - answers = from ans in answers - where ans.SurveyResponseId == r.Id - select new - { - ans.Id, - ans.QuestionId, - ans.AnswerText, - ans.Comment, - Questions = (from q in questions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(), - Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } - } - }; - - return result; - } + } + }; + return result; } catch (Exception ex) { @@ -634,12 +597,12 @@ namespace DamageAssesment.Api.Responses.Providers if (employeeid == 0) { surveyResonses = await surveyResponseDbContext.SurveyResponses.ToListAsync(); - employees = await employeeServiceProvider.getEmployeesAsync(); + employees = await employeeServiceProvider.getEmployeesAsync(token); } else { surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).ToListAsync(); - employee = await employeeServiceProvider.getEmployeeAsync(employeeid); + employee = await employeeServiceProvider.getEmployeeAsync(employeeid, token); if (employee != null) { @@ -648,9 +611,9 @@ namespace DamageAssesment.Api.Responses.Providers } - var answers = await answerServiceProvider.getAnswersAsync(); - var questions = await questionServiceProvider.getQuestionsAsync(); - var attachments = await attachmentServiceProvider.getAttachmentsAsync(); + var answers = await answerServiceProvider.getAnswersAsync(token); + var questions = await questionServiceProvider.getQuestionsAsync(token); + var attachments = await attachmentServiceProvider.getAttachmentsAsync(token); var result = from r in surveyResonses select new @@ -677,8 +640,6 @@ namespace DamageAssesment.Api.Responses.Providers } }; return result; - - } catch (Exception ex) { @@ -702,8 +663,8 @@ namespace DamageAssesment.Api.Responses.Providers { surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId && x.EmployeeId == employeeid).ToListAsync(); } - var answers = await answerServiceProvider.getAnswersAsync(); - var locations = await locationServiceProvider.getLocationsAsync(); + var answers = await answerServiceProvider.getAnswersAsync(token); + var locations = await locationServiceProvider.getLocationsAsync(token); var maintenanceCenters = locations.DistinctBy(m => m.MaintenanceCenter); //get all the answers for the particular survey @@ -732,7 +693,7 @@ namespace DamageAssesment.Api.Responses.Providers select new { g.Key.MaintenanceCenter, - Answers = new + Answers = new { g.Key.AnswerText, Counter = g.Count() @@ -769,12 +730,12 @@ namespace DamageAssesment.Api.Responses.Providers if (employeeid == 0) { surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId && x.LocationId == locationId).ToListAsync(); - employees = await employeeServiceProvider.getEmployeesAsync(); + employees = await employeeServiceProvider.getEmployeesAsync(token); } else { surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId && x.EmployeeId == employeeid && x.LocationId == locationId).ToListAsync(); - employee = await employeeServiceProvider.getEmployeeAsync(employeeid); + employee = await employeeServiceProvider.getEmployeeAsync(employeeid, token); if (employee != null) { @@ -782,10 +743,10 @@ namespace DamageAssesment.Api.Responses.Providers } } - var answers = await answerServiceProvider.getAnswersAsync(); - var questions = await questionServiceProvider.getQuestionsAsync(); + var answers = await answerServiceProvider.getAnswersAsync(token); + var questions = await questionServiceProvider.getQuestionsAsync(token); var surveyQuestions = from q in questions where q.SurveyId == surveyId select q; - var attachments = await attachmentServiceProvider.getAttachmentsAsync(); + var attachments = await attachmentServiceProvider.getAttachmentsAsync(token); var result = from r in surveyResonses select new @@ -798,7 +759,7 @@ namespace DamageAssesment.Api.Responses.Providers r.KeyAnswerResult, r.Longitute, r.Latitude, - Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), + Employee = (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), answers = from ans in answers where ans.SurveyResponseId == r.Id @@ -813,7 +774,6 @@ namespace DamageAssesment.Api.Responses.Providers } }; return result; - } catch (Exception ex) { @@ -836,12 +796,12 @@ namespace DamageAssesment.Api.Responses.Providers if (employeeid == 0) { surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == survey.Id).ToListAsync(); - employees = await employeeServiceProvider.getEmployeesAsync(); + employees = await employeeServiceProvider.getEmployeesAsync(token); } else { surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == survey.Id && x.EmployeeId == employeeid).ToListAsync(); - employee = await employeeServiceProvider.getEmployeeAsync(employeeid); + employee = await employeeServiceProvider.getEmployeeAsync(employeeid, token); if (employee != null) { @@ -851,8 +811,8 @@ namespace DamageAssesment.Api.Responses.Providers //var surveyResponses = await surveyResponseDbContext.Responses.Where(x => x.SurveyId == survey.Id).ToListAsync(); // var employees = await employeeServiceProvider.getEmployeesAsync(); - var answers = await answerServiceProvider.getAnswersAsync(); - var attachments = await attachmentServiceProvider.getAttachmentsAsync(); + var answers = await answerServiceProvider.getAnswersAsync(token); + var attachments = await attachmentServiceProvider.getAttachmentsAsync(token); var result = from r in surveyResponses select new @@ -865,7 +825,7 @@ namespace DamageAssesment.Api.Responses.Providers r.KeyAnswerResult, r.Longitute, r.Latitude, - Employee = employeeid != 0 ? _employee : (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), + Employee = (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), answers = from ans in answers where ans.SurveyResponseId == r.Id && ans.QuestionId == question.Id @@ -895,12 +855,12 @@ namespace DamageAssesment.Api.Responses.Providers { if (answerRequest != null) { - var answer = await answerServiceProvider.PostAnswersAsync(new Models.Answer { QuestionId = answerRequest.QuestionId, AnswerText = answerRequest.AnswerText, Comment = answerRequest.Comment, SurveyResponseId = surveyResponseId }); + var answer = await answerServiceProvider.PostAnswersAsync(new Models.Answer { QuestionId = answerRequest.QuestionId, AnswerText = answerRequest.AnswerText, Comment = answerRequest.Comment, SurveyResponseId = surveyResponseId }, token); if (answer != null) { List listAnswerInfo = new List(); listAnswerInfo.Add(new AnswerInfo { AnswerId = answer.Id, postedFiles = answerRequest.PostedFiles }); - var attachments = attachmentServiceProvider.PostAttachmentsAsync(new AttachmentInfo { ResponseId = surveyResponseId, Answers = listAnswerInfo }); + var attachments = attachmentServiceProvider.PostAttachmentsAsync(new AttachmentInfo { ResponseId = surveyResponseId, Answers = listAnswerInfo }, token); string message = $"Answer for question {answerRequest.QuestionId} saved to the database"; logger?.LogInformation(message); @@ -921,14 +881,13 @@ namespace DamageAssesment.Api.Responses.Providers } } - public async Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyAnswersAsync(Models.Request request) { try { if (request != null) { - var response = await PostSurveyResponseAsync(new Models.SurveyResponse { SurveyId = request.SurveyId, EmployeeId = request.EmployeeId, LocationId = request.LocationId, ClientDevice = request.ClientDevice, KeyAnswerResult = request.KeyAnswerResult, Latitude = Convert.ToDouble(request.Latitude), Longitute = Convert.ToDouble(request.Longitute), CreatedDate = DateTime.Now }); + var response = await PostSurveyResponseAsync(new Models.SurveyResponse { SurveyId = request.SurveyId, EmployeeId = request.EmployeeId, LocationId = request.LocationId, ClientDevice = request.ClientDevice, KeyAnswerResult = request.KeyAnswerResult, Latitude = Convert.ToDouble(request.Latitude), Longitute = Convert.ToDouble(request.Longitute), CreatedDate=DateTime.Now }); if (response.IsSuccess) { var surveyResponse = response.SurveyResponse; diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AnswerServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AnswerServiceProvider.cs index 5b8eeeb..b550ff1 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AnswerServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AnswerServiceProvider.cs @@ -1,5 +1,6 @@ using DamageAssesment.Api.Responses.Interfaces; using DamageAssesment.Api.Responses.Models; +using Microsoft.Extensions.Primitives; using Newtonsoft.Json; @@ -10,11 +11,11 @@ namespace DamageAssesment.Api.Responses.Services public AnswerServiceProvider(IConfiguration configuration, IHttpUtil httpUtil, ILogger logger) : base(configuration, httpUtil, logger, configuration.GetValue("RessourceSettings:Answer"), configuration.GetValue("EndPointSettings:AnswerUrlBase")) { } - public async Task> getAnswersAsync() + public async Task> getAnswersAsync(string token) { try { - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var answers = JsonConvert.DeserializeObject>(responseJsonString); if (answers == null || !answers.Any()) @@ -28,12 +29,12 @@ namespace DamageAssesment.Api.Responses.Services } } - public async Task> GetAnswersByResponseIdAsync(int responseId) + public async Task> GetAnswersByResponseIdAsync(int responseId, string token) { try { url = urlBase + string.Format(configuration.GetValue("RessourceSettings:AnswerByResponse"), responseId); - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null,token); var answers = JsonConvert.DeserializeObject>(responseJsonString); if (answers == null || !answers.Any()) @@ -47,12 +48,12 @@ namespace DamageAssesment.Api.Responses.Services } } - public async Task PostAnswersAsync(Answer answer) + public async Task PostAnswersAsync(Answer answer, string token ) { try { var requestJsonString = JsonConvert.SerializeObject(answer); - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Post, url, requestJsonString); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Post, url, requestJsonString, token); var answers = JsonConvert.DeserializeObject(responseJsonString); if (answers == null) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AttachmentServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AttachmentServiceProvider.cs index bfbce94..9ace258 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AttachmentServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/AttachmentServiceProvider.cs @@ -10,11 +10,11 @@ namespace DamageAssesment.Api.Responses.Services { } - public async Task> getAttachmentsAsync() + public async Task> getAttachmentsAsync(string token) { try { - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null,token); var attachments = JsonConvert.DeserializeObject>(responseJsonString); if (attachments == null || !attachments.Any()) @@ -28,12 +28,12 @@ namespace DamageAssesment.Api.Responses.Services } } - public async Task> PostAttachmentsAsync(AttachmentInfo attachmentInfo) + public async Task> PostAttachmentsAsync(AttachmentInfo attachmentInfo, string token) { try { var requestJsonString = JsonConvert.SerializeObject(attachmentInfo); - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Post, url, requestJsonString); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Post, url, requestJsonString, token); var attachments = JsonConvert.DeserializeObject>(responseJsonString); if (attachments == null) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/EmployeeServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/EmployeeServiceProvider.cs index 22f63de..bcde62a 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/EmployeeServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/EmployeeServiceProvider.cs @@ -1,4 +1,4 @@ -using DamageAssesment.Api.Responses.Interfaces; +using DamageAssesment.Api.Responses.Interfaces; using DamageAssesment.Api.Responses.Models; using Microsoft.AspNetCore.Mvc.Routing; using Newtonsoft.Json; @@ -11,11 +11,11 @@ namespace DamageAssesment.Api.Responses.Services { } - public async Task> getEmployeesAsync() + public async Task> getEmployeesAsync(string token) { try { - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null,token); var employees = JsonConvert.DeserializeObject>(responseJsonString); if (employees == null || !employees.Any()) @@ -29,12 +29,12 @@ namespace DamageAssesment.Api.Responses.Services } } - public async Task getEmployeeAsync(int employeeId) + public async Task getEmployeeAsync(int employeeId, string token) { try { url = urlBase + string.Format(configuration.GetValue("RessourceSettings:EmployeeById"), employeeId); - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var employee = JsonConvert.DeserializeObject(responseJsonString); if (employee == null) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/HttpUtil.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/HttpUtil.cs index 053ffad..830c6c1 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/HttpUtil.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/HttpUtil.cs @@ -1,4 +1,5 @@ -using DamageAssesment.Api.Responses.Interfaces; +using DamageAssesment.Api.Responses.Interfaces; +using DamageAssesment.Api.Responses.Models; using System.Net.Http.Headers; using System.Text; @@ -14,20 +15,18 @@ namespace DamageAssesment.Api.Responses.Services this.httpClient = httpClient; this.logger = logger; } - public async Task SendAsync(HttpMethod method, string url, string JsonInput) + public async Task SendAsync(HttpMethod method, string url, string JsonInput, string token) { try { var request = new HttpRequestMessage(method, url); request.Headers.Accept.Clear(); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - - //request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); if (method == HttpMethod.Post) { request.Content = new StringContent(JsonInput, Encoding.UTF8, "application/json"); } - var response = await httpClient.SendAsync(request, CancellationToken.None); response.EnsureSuccessStatusCode(); var responseString = await response.Content.ReadAsStringAsync(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/LocationServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/LocationServiceProvider.cs index e6b36f6..2d38ca3 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/LocationServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/LocationServiceProvider.cs @@ -10,11 +10,11 @@ namespace DamageAssesment.Api.Responses.Services { } - public async Task> getLocationsAsync() + public async Task> getLocationsAsync(string token) { try { - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var locations = JsonConvert.DeserializeObject>(responseJsonString); if (locations == null || !locations.Any()) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs index 95086b8..4f2e75f 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs @@ -10,11 +10,11 @@ namespace DamageAssesment.Api.Responses.Services { } - public async Task> getQuestionsAsync() + public async Task> getQuestionsAsync(string token) { try { - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null,token); var questions = JsonConvert.DeserializeObject>(responseJsonString); if (questions == null || !questions.Any()) @@ -28,12 +28,12 @@ namespace DamageAssesment.Api.Responses.Services } } - public async Task> getSurveyQuestionsAsync(int surveyId) + public async Task> getSurveyQuestionsAsync(int surveyId, string token) { try { url = urlBase + string.Format(configuration.GetValue("RessourceSettings:SurveyQuestion"), surveyId); - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var questions = JsonConvert.DeserializeObject>(responseJsonString); if (questions == null || !questions.Any()) @@ -48,12 +48,12 @@ namespace DamageAssesment.Api.Responses.Services } - public async Task getQuestionsAsync(int questionId) + public async Task getQuestionsAsync(int questionId, string token) { try { url = urlBase + string.Format(configuration.GetValue("RessourceSettings:QuestionById"), questionId); - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var question = JsonConvert.DeserializeObject(responseJsonString); if (question == null) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/RegionServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/RegionServiceProvider.cs index 49d3e28..13de3d6 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/RegionServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/RegionServiceProvider.cs @@ -9,11 +9,11 @@ namespace DamageAssesment.Api.Responses.Services public RegionServiceProvider(IConfiguration configuration, IHttpUtil httpUtil, ILogger logger) : base(configuration, httpUtil, logger, configuration.GetValue("RessourceSettings:Region"), configuration.GetValue("EndPointSettings:LocationUrlBase")) { } - public async Task> getRegionsAsync() + public async Task> getRegionsAsync(string token) { try { - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var regions = JsonConvert.DeserializeObject>(responseJsonString); if (regions == null || !regions.Any()) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/SurveyServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/SurveyServiceProvider.cs index a77e1a7..1a30be0 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/SurveyServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/SurveyServiceProvider.cs @@ -4,19 +4,19 @@ using Newtonsoft.Json; namespace DamageAssesment.Api.Responses.Services { - public class SurveyServiceProvider : ServiceProviderBase, ISurveyServiceProvider + public class SurveyServiceProvider :ServiceProviderBase, ISurveyServiceProvider { public SurveyServiceProvider(IConfiguration configuration, IHttpUtil httpUtil, ILogger logger) : base(configuration, httpUtil, logger, configuration.GetValue("RessourceSettings:Survey"), configuration.GetValue("EndPointSettings:SurveyUrlBase")) { } - public async Task> getSurveysAsync(string language) + public async Task> getSurveysAsync(string language, string token) { try { if (!string.IsNullOrEmpty(language)) url = url + "/" + language; - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var surveys = JsonConvert.DeserializeObject>(responseJsonString); if (surveys == null || !surveys.Any()) @@ -30,15 +30,15 @@ namespace DamageAssesment.Api.Responses.Services } } - public async Task getSurveyAsync(int surveyId) + public async Task getSurveyAsync(int surveyId, string token) { try { url = urlBase + string.Format(configuration.GetValue("RessourceSettings:SurveyById"), surveyId); - var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null, token); var survey = JsonConvert.DeserializeObject(responseJsonString); - if (survey == null) + if (survey == null ) return null; else return survey; } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json index 8829c0b..e7152b6 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json @@ -6,7 +6,14 @@ } }, "AllowedHosts": "*", + "JwtSettings": { + "securitykey": "bWlhbWkgZGFkZSBzY2hvb2xzIHNlY3JldCBrZXk=" + }, + "ConnectionStrings": { + "ResponsesConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"ResponsesConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" + }, //"EndPointSettings": { // "AnswerUrlBase": "http://localhost:5200", // "LocationUrlBase": "http://localhost:5213", @@ -16,7 +23,6 @@ // "AttachmentUrlBase": "http://localhost:5243", // "SurveyUrlBase": "http://localhost:5009" //}, - //Endpoints for docker-container "EndPointSettings": { "AnswerUrlBase": "http://damageassesment.api.answers:80", "LocationUrlBase": "http://damageassesment.api.locations:80", @@ -39,10 +45,5 @@ "AnswerByResponse": "/answers/byresponse/{0}", "Location": "/locations", "Region": "/regions" - }, - "ConnectionStrings": { - //"SurveyResponseConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" - // "ResponsesConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;", - "ResponsesConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.Designer.cs b/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.Designer.cs deleted file mode 100644 index edec629..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.Designer.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -using DamageAssesment.Api.SurveyResponses.Db; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace DamageAssesment.Api.SurveyResponses.Migrations -{ - [DbContext(typeof(SurveyResponseDbContext))] - [Migration("20230817221348_InitialSurveyResponse")] - partial class InitialSurveyResponse - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.9") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("DamageAssesment.Api.SurveyResponses.Db.SurveyResponse", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("EmployeeId") - .IsRequired() - .HasMaxLength(6) - .HasColumnType("nvarchar(6)"); - - b.Property("LocationId") - .IsRequired() - .HasMaxLength(4) - .HasColumnType("nvarchar(4)"); - - b.Property("SurveyId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("SurveyResponses"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.cs b/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.cs deleted file mode 100644 index e886ab1..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/20230817221348_InitialSurveyResponse.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace DamageAssesment.Api.SurveyResponses.Migrations -{ - /// - public partial class InitialSurveyResponse : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "SurveyResponses", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - SurveyId = table.Column(type: "int", nullable: false), - LocationId = table.Column(type: "nvarchar(4)", maxLength: 4, nullable: false), - EmployeeId = table.Column(type: "nvarchar(6)", maxLength: 6, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SurveyResponses", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "SurveyResponses"); - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/SurveyResponseDbContextModelSnapshot.cs b/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/SurveyResponseDbContextModelSnapshot.cs deleted file mode 100644 index 1870d21..0000000 --- a/DamageAssesmentApi/DamageAssesment.Api.SurveyResponses/Migrations/SurveyResponseDbContextModelSnapshot.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -using DamageAssesment.Api.SurveyResponses.Db; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace DamageAssesment.Api.SurveyResponses.Migrations -{ - [DbContext(typeof(SurveyResponseDbContext))] - partial class SurveyResponseDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.9") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("DamageAssesment.Api.SurveyResponses.Db.SurveyResponse", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("EmployeeId") - .IsRequired() - .HasMaxLength(6) - .HasColumnType("nvarchar(6)"); - - b.Property("LocationId") - .IsRequired() - .HasMaxLength(4) - .HasColumnType("nvarchar(4)"); - - b.Property("SurveyId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("SurveyResponses"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Controllers/SurveysController.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Controllers/SurveysController.cs index b93120b..2a4415c 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Controllers/SurveysController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Controllers/SurveysController.cs @@ -1,4 +1,5 @@ using DamageAssesment.Api.Surveys.Interfaces; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace DamageAssesment.Api.Surveys.Controllers @@ -15,6 +16,7 @@ namespace DamageAssesment.Api.Surveys.Controllers /// /// GET request for retrieving surveys. /// + [Authorize(Roles ="admin,survey,user,report")] [Route("surveys")] [Route("surveys/{language:alpha}")] [HttpGet] @@ -31,6 +33,7 @@ namespace DamageAssesment.Api.Surveys.Controllers /// /// GET request for retrieving surveys by ID. /// + [Authorize(Roles = "admin,survey,user,report")] [Route("surveys/{id:int}")] [Route("surveys/{id:int}/{language:alpha}")] [HttpGet] @@ -46,6 +49,7 @@ namespace DamageAssesment.Api.Surveys.Controllers /// /// POST request for creating a new survey. /// + [Authorize(Roles = "admin,survey,user,report")] [HttpPost("surveys")] public async Task PostSurveysAsync(Models.Survey survey) { @@ -59,6 +63,8 @@ namespace DamageAssesment.Api.Surveys.Controllers /// /// PUT request for updating an existing survey (surveyId,Updated Survey data). /// + + [Authorize(Roles = "admin,survey")] [HttpPut("surveys/{id}")] public async Task PutSurveysAsync(int id, Models.Survey survey) { @@ -76,6 +82,7 @@ namespace DamageAssesment.Api.Surveys.Controllers /// /// DELETE request for deleting a survey by ID. /// + [Authorize(Roles = "admin,survey")] [HttpDelete("surveys/{id}")] public async Task DeleteSurveysAsync(int id) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs index 178b5fd..6d79d25 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Program.cs @@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using System.Text; using System.Reflection; +using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); @@ -34,14 +35,44 @@ builder.Services.AddControllers(); builder.Services.AddScoped(); builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); builder.Services.AddEndpointsApiExplorer(); -//builder.Services.AddSwaggerGen(); -builder.Services.AddSwaggerGen(c => + +builder.Services.AddSwaggerGen(options => { // Include XML comments from your assembly var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); - c.IncludeXmlComments(xmlPath); + options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + + options.AddSecurityRequirement(securityRequirements); }); + builder.Services.AddDbContext(option => { option.UseSqlServer("SurveyConnection"); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs index fe09798..5acb580 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs @@ -95,7 +95,6 @@ namespace DamageAssesment.Api.Surveys.Providers logger?.LogInformation("Get all Surveys from DB"); //checking is enabled in survey response var surveys = await surveyDbContext.Surveys.ToListAsync();//Where(s => s.IsEnabled == true) - if (surveys != null) { surveysList = from s in surveys diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.json index 99bf950..cba9277 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/appsettings.json @@ -10,8 +10,8 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - //"SurveyConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" - //"SurveyConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;", - "SurveyConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" + "SurveyConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"SurveyConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" + } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/DamageAssesment.Api.UsersAccess.Test.csproj b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/DamageAssesment.Api.UsersAccess.Test.csproj new file mode 100644 index 0000000..e655693 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/DamageAssesment.Api.UsersAccess.Test.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/MockData.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/MockData.cs new file mode 100644 index 0000000..b25ec9a --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/MockData.cs @@ -0,0 +1,44 @@ +using DamageAssesment.Api.UsersAccess.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit.Sdk; + +namespace DamageAssesment.Api.UsersAccess.Test +{ + public class MockData + { + public static async Task<(bool, Models.TokenResponse, string)> getTokenResponse(bool status, string message) + { + return (status, new Models.TokenResponse { jwttoken = "1234", refreshtoken = "12345" }, message); + } + + public static async Task<(bool, List, string)> getUsers(bool status, string message) + { + List users = new List(); + users.Add(new User { Id = 1, EmployeeCode = "Emp1", EmployeeId = 1, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }); + users.Add(new User { Id = 2, EmployeeCode = "Emp2", EmployeeId = 2, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }); + users.Add(new User { Id = 3, EmployeeCode = "Emp3", EmployeeId = 3, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }); + return (status, users, message); + } + + public static async Task<(bool, User, string)> getUser(bool status, string message) + { + User user = getUsers(status, message).Result.Item2.FirstOrDefault(); + return (status, user, message); + } + + public static async Task<(bool, List, string)> getRoles(bool status, string message) + { + List roles = new List(); + roles.Add(new Role { Id = 1, Name = "Role 1" }); + roles.Add(new Role { Id = 2, Name = "Role 2" }); + roles.Add(new Role { Id = 3, Name = "Role 3" }); + + return (status, roles, message); + } + + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/UsersAccessTest.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/UsersAccessTest.cs new file mode 100644 index 0000000..46165f3 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess.Test/UsersAccessTest.cs @@ -0,0 +1,194 @@ +using DamageAssesment.Api.UsersAccess.Controllers; +using DamageAssesment.Api.UsersAccess.Interfaces; +using Microsoft.AspNetCore.Mvc; +using Moq; +using Xunit; + +namespace DamageAssesment.Api.UsersAccess.Test +{ + public class UsersAccessTest + { + private Mock mockService; + + public UsersAccessTest() + { + mockService = new Mock(); + } + [Fact(DisplayName = "Get Token - Ok case")] + public async Task GetTokenAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getTokenResponse(true,null); + mockService.Setup(service => service.AuthenticateAsync("Emp1")).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.AuthenticateAsync("Emp1"); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Token - Unauthorized case")] + public async Task GetTokenAsync_ShouldReturnStatusCode401() + { + var response = await MockData.getTokenResponse(false, null); + mockService.Setup(service => service.AuthenticateAsync("Emp1")).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (UnauthorizedObjectResult)await controller.AuthenticateAsync("Emp1"); + Assert.Equal(401, result.StatusCode); + } + + + [Fact(DisplayName = "RefreshToken - Ok case")] + public async Task RefreshTokenAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getTokenResponse(true, null); + mockService.Setup(service => service.RefreshTokenAsync(null)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.RefreshTokenAsync(null); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "RefreshToken - Unauthorized case")] + public async Task RefreshTokenAsync_ShouldReturnStatusCode401() + { + var response = await MockData.getTokenResponse(false, null); + mockService.Setup(service => service.RefreshTokenAsync(null)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (UnauthorizedObjectResult)await controller.RefreshTokenAsync(null); + Assert.Equal(401, result.StatusCode); + } + + [Fact(DisplayName = "GetUsers - Ok case")] + public async Task GetUsersAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getUsers(true, null); + mockService.Setup(service => service.GetUsersAsync()).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.GetUsersAsync(); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "GetUsers - NoContent case")] + public async Task GetUsersAsync_ShouldReturnStatusCode204() + { + var response = await MockData.getUsers(false, null); + mockService.Setup(service => service.GetUsersAsync()).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (NoContentResult)await controller.GetUsersAsync(); + Assert.Equal(204, result.StatusCode); + } + + [Fact(DisplayName = "GetUser - Ok case")] + public async Task GetUserAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getUser(true, null); + mockService.Setup(service => service.GetUsersAsync(1)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.GetUsersAsync(1); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "GetUser - NotFound case")] + public async Task GetUserAsync_ShouldReturnStatusCode204() + { + var response = await MockData.getUser(false, null); + mockService.Setup(service => service.GetUsersAsync(1)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (NotFoundResult)await controller.GetUsersAsync(1); + Assert.Equal(404, result.StatusCode); + } + + [Fact(DisplayName = "GetRoles - Ok case")] + public async Task GetRolesAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getRoles(true, null); + mockService.Setup(service => service.GetRolesAsync()).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.GetRolesAsync(); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "GetRoles - NoContent case")] + public async Task GetRolesAsync_ShouldReturnStatusCode204() + { + var response = await MockData.getRoles(false, null); + mockService.Setup(service => service.GetRolesAsync()).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (NoContentResult)await controller.GetRolesAsync(); + Assert.Equal(204, result.StatusCode); + } + + [Fact(DisplayName = "PostUser - Ok case")] + public async Task PostUserAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getUser(true, null); + var user = new Models.User { Id = 1, EmployeeCode = "Emp1", EmployeeId = 1, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }; + mockService.Setup(service => service.PostUserAsync(user)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.PostUserAsync(user); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "PostUser - Bad Request case")] + public async Task PostUserAsync_ShouldReturnStatusCode400() + { + var response = await MockData.getUser(false, null); + var user = new Models.User { Id = 1, EmployeeCode = "Emp1", EmployeeId = 1, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }; + mockService.Setup(service => service.PostUserAsync(user)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (BadRequestObjectResult)await controller.PostUserAsync(user); + Assert.Equal(400, result.StatusCode); + } + + [Fact(DisplayName = "PutUser - Ok case")] + public async Task PutUserAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getUser(true, null); + var user = new Models.User { Id = 1, EmployeeCode = "Emp1", EmployeeId = 1, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }; + mockService.Setup(service => service.PutUserAsync(1,user)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.PutUserAsync(1,user); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "PutUser - BadRequest case")] + public async Task PutUserAsync_ShouldReturnStatusCode400() + { + var response = await MockData.getUser(false, null); + var user = new Models.User { Id = 1, EmployeeCode = "Emp1", EmployeeId = 1, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }; + mockService.Setup(service => service.PutUserAsync(1,user)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (BadRequestObjectResult)await controller.PutUserAsync(1,user); + Assert.Equal(400, result.StatusCode); + } + + [Fact(DisplayName = "PutUser - Not Found case")] + public async Task PutUserAsync_ShouldReturnStatusCode404() + { + var response = await MockData.getUser(false, "Not Found"); + var user = new Models.User { Id = 1, EmployeeCode = "Emp1", EmployeeId = 1, RoleId = 1, IsActive = true, CreateDate = DateTime.Now }; + mockService.Setup(service => service.PutUserAsync(1, user)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (NotFoundObjectResult)await controller.PutUserAsync(1,user); + Assert.Equal(404, result.StatusCode); + } + + + [Fact(DisplayName = "DeleteUser - Ok case")] + public async Task DeleteUserAsync_ShouldReturnStatusCode200() + { + var response = await MockData.getUser(true, null); + mockService.Setup(service => service.DeleteUserAsync(1)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (OkObjectResult)await controller.DeleteUserAsync(1); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "DeleteUser - Not Found case")] + public async Task DeleteUserAsync_ShouldReturnStatusCode404() + { + var response = await MockData.getUser(false, "Not Found"); + mockService.Setup(service => service.DeleteUserAsync(1)).ReturnsAsync(response); + var controller = new UsersAccessController(mockService.Object); + var result = (NotFoundResult)await controller.DeleteUserAsync(1); + Assert.Equal(404, result.StatusCode); + } + } +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs new file mode 100644 index 0000000..e0aae67 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs @@ -0,0 +1,117 @@ +using DamageAssesment.Api.UsersAccess.Interfaces; +using DamageAssesment.Api.UsersAccess.Models; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace DamageAssesment.Api.UsersAccess.Controllers +{ + [ApiController] + public class UsersAccessController : ControllerBase + { + private IUsersAccessProvider userAccessProvider; + + public UsersAccessController(IUsersAccessProvider userAccessProvider) + { + this.userAccessProvider = userAccessProvider; + } + [Authorize(Policy = "Dadeschools")] + [HttpPost("token/{employecode}")] + public async Task AuthenticateAsync(string employecode) + { + var result = await userAccessProvider.AuthenticateAsync(employecode); + if (result.IsSuccess) + { + return Ok(result.TokenResponse); + } + return Unauthorized(result.ErrorMessage); + } + + [Authorize(Policy = "Dadeschools")] + [HttpPost("refreshtoken")] + public async Task RefreshTokenAsync(TokenResponse tokenResponse) + { + var result = await userAccessProvider.RefreshTokenAsync(tokenResponse); + if (result.IsSuccess) + { + return Ok(result.TokenResponse); + } + return Unauthorized(result.ErrorMessage); + } + + [Authorize(Policy = "DamageApp", Roles ="admin")] + [HttpGet("users")] + public async Task GetUsersAsync() + { + var result = await userAccessProvider.GetUsersAsync(); + if (result.IsSuccess) + { + return Ok(result.Users); + } + return NoContent(); + } + + [Authorize(Policy = "DamageApp", Roles = "admin")] + [HttpGet("users/{Id}")] + public async Task GetUsersAsync(int Id) + { + var result = await userAccessProvider.GetUsersAsync(Id); + if (result.IsSuccess) + { + return Ok(result.User); + } + return NotFound(); + } + + [Authorize(Policy = "DamageApp", Roles = "admin")] + [HttpGet("roles")] + public async Task GetRolesAsync() + { + var result = await userAccessProvider.GetRolesAsync(); + if (result.IsSuccess) + { + return Ok(result.Roles); + } + return NoContent(); + } + [Authorize(Policy = "DamageApp", Roles = "admin")] + [HttpPost("users")] + public async Task PostUserAsync(User user) + { + var result = await userAccessProvider.PostUserAsync(user); + if (result.IsSuccess) + { + return Ok(result.User); + } + return BadRequest(result.ErrorMessage); + } + + [Authorize(Policy = "DamageApp", Roles = "admin")] + [HttpPut("users/{Id}")] + public async Task PutUserAsync(int Id, User user) + { + var result = await userAccessProvider.PutUserAsync(Id, user); + if (result.IsSuccess) + { + return Ok(result.User); + } + if (result.ErrorMessage == "Not Found") + return NotFound(result.ErrorMessage); + + return BadRequest(result.ErrorMessage); + } + + [Authorize(Policy = "DamageApp", Roles = "admin")] + [HttpDelete("users/{Id}")] + public async Task DeleteUserAsync(int Id) + { + var result = await userAccessProvider.DeleteUserAsync(Id); + if (result.IsSuccess) + { + return Ok(result.User); + } + return NotFound(); + } + + + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/DamageAssesment.Api.UsersAccess.csproj b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/DamageAssesment.Api.UsersAccess.csproj new file mode 100644 index 0000000..6c6eb21 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/DamageAssesment.Api.UsersAccess.csproj @@ -0,0 +1,29 @@ + + + + net6.0 + enable + enable + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Role.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Role.cs new file mode 100644 index 0000000..93e522a --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Role.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; + +namespace DamageAssesment.Api.UsersAccess.Db +{ + public class Role + { + [Key] + public int Id { get; set; } + + [StringLength(100)] + [Required] + public string Name { get; set; } + + // add a status field + + [StringLength(100)] + public string? Description { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Token.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Token.cs new file mode 100644 index 0000000..bdfe576 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/Token.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore.Metadata.Internal; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace DamageAssesment.Api.UsersAccess.Db +{ + public class Token + { + [Key] + public int Id { get; set; } + [Required] + [ForeignKey("User")] + public int UserId { get; set; } + public string? RefreshToken { get; set; } + public bool? IsActive { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/User.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/User.cs new file mode 100644 index 0000000..f99deb8 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/User.cs @@ -0,0 +1,31 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json.Serialization; + +namespace DamageAssesment.Api.UsersAccess.Db +{ + public class User + { + [Key] + public int Id { get; set; } + + [ForeignKey("Employee")] + public int EmployeeId { get; set; } + + [Required] + [StringLength(50)] + public string EmployeeCode { get; set; } + + [ForeignKey("Role")] + [Required] + public int RoleId { get; set; } + [Required] + public bool IsActive { get; set; } = true; + + [Required] + public DateTime CreateDate { get; set; } = DateTime.Now; + + public DateTime? UpdateDate { get; set; } + + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/UsersAccessDbContext.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/UsersAccessDbContext.cs new file mode 100644 index 0000000..157dfb3 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Db/UsersAccessDbContext.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; + +namespace DamageAssesment.Api.UsersAccess.Db +{ + public class UsersAccessDbContext : DbContext + { + public DbSet Users { get; set; } + public DbSet Roles { get; set; } + public DbSet Tokens { get; set; } + private IConfiguration _Configuration { get; set; } + public UsersAccessDbContext(DbContextOptions options, IConfiguration configuration) : base(options) + { + _Configuration = configuration; + } + protected override void OnConfiguring(DbContextOptionsBuilder options) + { + // connect to sql server with connection string from app settings + options.UseSqlServer(_Configuration.GetConnectionString("UsersAccessConnection")); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity() + .Property(item => item.Id) + .ValueGeneratedOnAdd(); + + modelBuilder.Entity() + .Property(item => item.Id) + .ValueGeneratedOnAdd(); + + modelBuilder.Entity() + .Property(item => item.Id) + .ValueGeneratedOnAdd(); + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IEmployeeServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IEmployeeServiceProvider.cs new file mode 100644 index 0000000..255a954 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IEmployeeServiceProvider.cs @@ -0,0 +1,10 @@ +using DamageAssesment.Api.UsersAccess.Models; + +namespace DamageAssesment.Api.UsersAccess.Interfaces +{ + public interface IEmployeeServiceProvider + { + Task> getEmployeesAsync(); + Task getEmployeeAsync(int employeeId); + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IRoleProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IRoleProvider.cs new file mode 100644 index 0000000..6ca0209 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IRoleProvider.cs @@ -0,0 +1,12 @@ +namespace DamageAssesment.Api.UsersAccess.Interfaces +{ + public interface IRoleProvider + { + Task<(bool IsSuccess, IEnumerable< Models.Role> Roles, string ErrorMessage)> GetRolesAsync(); + Task<(bool IsSuccess, Models.Role Roles, string ErrorMessage)> GetRolesAsync(int Id); + Task<(bool IsSuccess, Models.Role Role, string ErrorMessage)> PostRoleAsync(Models.Role Role); + Task<(bool IsSuccess, Models.Role Role, string ErrorMessage)> PutRoleAsync(int Id,Models.Role Role); + Task<(bool IsSuccess, Models.Role Role, string ErrorMessage)> DeleteRoleAsync(int Id); + + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/ITokenServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/ITokenServiceProvider.cs new file mode 100644 index 0000000..6115e7c --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/ITokenServiceProvider.cs @@ -0,0 +1,11 @@ +using DamageAssesment.Api.UsersAccess.Models; +using System.Security.Claims; + +namespace DamageAssesment.Api.UsersAccess.Interfaces +{ + public interface ITokenServiceProvider + { + Task GenerateToken(Models.User user); + Task TokenAuthenticate(Models.User user, Claim[] claims); + } +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs new file mode 100644 index 0000000..ea64376 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs @@ -0,0 +1,17 @@ +using DamageAssesment.Api.UsersAccess.Models; + +namespace DamageAssesment.Api.UsersAccess.Interfaces +{ + public interface IUsersAccessProvider + { + public Task<(bool IsSuccess, IEnumerable< Models.User> Users, string ErrorMessage)> GetUsersAsync(); + public Task<(bool IsSuccess, Models.User User, string ErrorMessage)> GetUsersAsync(int Id); + public Task<(bool IsSuccess, Models.User User, string ErrorMessage)> PostUserAsync(Models.User User); + public Task<(bool IsSuccess, Models.User User, string ErrorMessage)> PutUserAsync(int Id,Models.User User); + public Task<(bool IsSuccess, Models.User User, string ErrorMessage)> DeleteUserAsync(int Id); + public Task<(bool IsSuccess, IEnumerable Roles, string ErrorMessage)> GetRolesAsync(); + public Task<(bool IsSuccess, Models.TokenResponse TokenResponse, string ErrorMessage)> AuthenticateAsync(string employeCode); + public Task<(bool IsSuccess, Models.TokenResponse TokenResponse, string ErrorMessage)>RefreshTokenAsync(TokenResponse tokenResponse); + public void seedData(); + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/Interface.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/Interface.cs new file mode 100644 index 0000000..3d0a8ed --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/Interface.cs @@ -0,0 +1,7 @@ +namespace DamageAssesment.Api.UsersAccess.Interfaces +{ + public interface IHttpUtil + { + Task SendAsync(HttpMethod method, string url, string JsonInput); + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Employee.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Employee.cs new file mode 100644 index 0000000..b08d156 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Employee.cs @@ -0,0 +1,14 @@ +namespace DamageAssesment.Api.UsersAccess.Models +{ + public class Employee + { + public int Id { get; set; } + public string EmployeeCode { get; set; } + public string Name { get; set; } + public DateTime BirthDate { get; set; } + public string OfficePhoneNumber { get; set; } + public string Email { get; set; } + public bool IsActive { get; set; } + public string PreferredLanguage { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/JwtSettings.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/JwtSettings.cs new file mode 100644 index 0000000..3f9dadf --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/JwtSettings.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; +namespace DamageAssesment.Api.UsersAccess.Models +{ + + public class JwtSettings + { + public string securitykey { get; set; } + } +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Role.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Role.cs new file mode 100644 index 0000000..a275c60 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Role.cs @@ -0,0 +1,8 @@ +namespace DamageAssesment.Api.UsersAccess.Models +{ + public class Role { + public int Id { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Token.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Token.cs new file mode 100644 index 0000000..87f1ae3 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/Token.cs @@ -0,0 +1,10 @@ +namespace DamageAssesment.Api.UsersAccess.Models +{ + public class Token + { + public string Id { get; set; } + public int UserId { get; set; } + public string RefreshToken { get; set; } + public bool IsActive { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/TokenResponse.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/TokenResponse.cs new file mode 100644 index 0000000..4d0b6da --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/TokenResponse.cs @@ -0,0 +1,8 @@ +namespace DamageAssesment.Api.UsersAccess.Models +{ + public class TokenResponse + { + public string? jwttoken { get; set; } + public string? refreshtoken { get; set; } + } +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/User.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/User.cs new file mode 100644 index 0000000..e43bc20 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/User.cs @@ -0,0 +1,13 @@ +namespace DamageAssesment.Api.UsersAccess.Models +{ + public class User + { + public int Id { get; set; } + public int EmployeeId { get; set; } + public string EmployeeCode { get; set; } + public int RoleId { get; set; } + public bool IsActive { get; set; } + public DateTime CreateDate { get; set; } + public DateTime UpdateDate { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/UserCredentials.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/UserCredentials.cs new file mode 100644 index 0000000..cf01fa3 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/UserCredentials.cs @@ -0,0 +1,5 @@ +public class UserCredentials +{ + public string username { get; set; } + // public string? password { get; set; } +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Profiles/UsersAccessProfile.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Profiles/UsersAccessProfile.cs new file mode 100644 index 0000000..bf744eb --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Profiles/UsersAccessProfile.cs @@ -0,0 +1,14 @@ +namespace DamageAssesment.Api.UsersAccess.Profiles +{ + public class UsersAccessProfile : AutoMapper.Profile + { + public UsersAccessProfile() + { + CreateMap(); + CreateMap(); + + CreateMap(); + CreateMap(); + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Program.cs new file mode 100644 index 0000000..567e613 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Program.cs @@ -0,0 +1,146 @@ +using DamageAssesment.Api.UsersAccess.Db; +using DamageAssesment.Api.UsersAccess.Interfaces; +using DamageAssesment.Api.UsersAccess.Providers; +using DamageAssesment.Api.UsersAccess.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; +using System.Text; +using Polly; +using DamageAssesment.Api.UsersAccess.Services; +using Microsoft.OpenApi.Models; +using System.Reflection; +using Microsoft.AspNetCore.Authorization; + +const int maxApiCallRetries = 3; +const int intervalToRetry = 2; //2 seconds +const int maxRetryForCircuitBraker = 5; +const int intervalForCircuitBraker = 5; //5 seconds + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +var authkey = builder.Configuration.GetValue("JwtSettings:securitykey"); + + +builder.Services.AddAuthentication(). + AddJwtBearer("DamageApp", item => +{ + + item.RequireHttpsMetadata = true; + item.SaveToken = true; + item.TokenValidationParameters = new TokenValidationParameters() + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authkey)), + ValidateIssuer = false, + ValidateAudience = false, + ClockSkew = TimeSpan.Zero + }; +}).AddJwtBearer("Dadeschools", options => +{ + options.Authority = builder.Configuration["Dadeschools:Authority"]; + options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" }; + options.TokenValidationParameters.ValidateAudience = false; +}); + + +builder.Services.AddAuthorization(options => +{ + var DamageAppPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .AddAuthenticationSchemes("DamageApp") + .Build(); + var DadeschoolsPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .AddAuthenticationSchemes("Dadeschools") + .Build(); + var allPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .AddAuthenticationSchemes("DamageApp", "Dadeschools") + .Build(); + options.AddPolicy("DamageApp", DamageAppPolicy); + options.AddPolicy("Dadeschools", DadeschoolsPolicy); + options.AddPolicy("AllPolicies", allPolicy); + options.DefaultPolicy = options.GetPolicy("DamageApp")!; +}); + +var _jwtsettings = builder.Configuration.GetSection("JwtSettings"); +builder.Services.Configure(_jwtsettings); + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +builder.Services.AddHttpClient(). + AddTransientHttpErrorPolicy(policy => policy.WaitAndRetryAsync(maxApiCallRetries, _ => TimeSpan.FromSeconds(intervalToRetry))). + AddTransientHttpErrorPolicy(policy => policy.CircuitBreakerAsync(maxRetryForCircuitBraker, TimeSpan.FromSeconds(intervalForCircuitBraker))); + +builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); +builder.Services.AddEndpointsApiExplorer(); +//builder.Services.AddSwaggerGen(); + +builder.Services.AddSwaggerGen(options => +{ + + // Include XML comments from your assembly + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + //options.IncludeXmlComments(xmlPath); + + OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme() + { + Name = "Bearer", + BearerFormat = "JWT", + Scheme = "bearer", + Description = "Specify the authorization token.", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + }; + + options.AddSecurityDefinition("jwt_auth", securityDefinition); + + // Make sure swagger UI requires a Bearer token specified + OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference() + { + Id = "jwt_auth", + Type = ReferenceType.SecurityScheme + } + }; + + OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement() + { + {securityScheme, new string[] { }}, + }; + + options.AddSecurityRequirement(securityRequirements); +}); + +builder.Services.AddDbContext(option => +{ + option.UseSqlServer("UsersAccessConnection"); +}); +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); + + using (var serviceScope = app.Services.CreateScope()) + { + var services = serviceScope.ServiceProvider; + var usersAccessProvider = services.GetRequiredService(); + usersAccessProvider.seedData(); + } +} + +app.UseAuthentication(); +app.UseAuthorization(); + +app.MapControllers(); +app.Run(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Properties/launchSettings.json b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Properties/launchSettings.json new file mode 100644 index 0000000..859e680 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:28382", + "sslPort": 0 + } + }, + "profiles": { + "DamageAssesment.Api.Users": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5027", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs new file mode 100644 index 0000000..a599053 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs @@ -0,0 +1,305 @@ +using AutoMapper; +using DamageAssesment.Api.UsersAccess.Db; +using DamageAssesment.Api.UsersAccess.Interfaces; +using DamageAssesment.Api.UsersAccess.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; +using System.Data; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; + +namespace DamageAssesment.Api.UsersAccess.Providers +{ + public class UsersAccessProvider : IUsersAccessProvider + { + private readonly UsersAccessDbContext userAccessDbContext; + private readonly ILogger logger; + private readonly IMapper mapper; + //private readonly IEmployeeServiceProvider employeeServiceProvider; + private readonly JwtSettings jwtSettings; + private readonly ITokenServiceProvider tokenServiceProvider; + + public UsersAccessProvider(IOptions options, ITokenServiceProvider tokenServiceProvider, UsersAccessDbContext userAccessDbContext, IEmployeeServiceProvider employeeServiceProvider, ILogger logger, IMapper mapper) + { + this.userAccessDbContext = userAccessDbContext; + //this.employeeServiceProvider = employeeServiceProvider; + this.logger = logger; + this.mapper = mapper; + jwtSettings = options.Value; + this.tokenServiceProvider = tokenServiceProvider; + // seedData(); + } + + public void seedData() + { + if (!userAccessDbContext.Users.Any()) + { + userAccessDbContext.Users.Add(new Db.User { EmployeeId = 1, EmployeeCode = "Emp1", RoleId = 1, IsActive = true, CreateDate = DateTime.Now }); + userAccessDbContext.Users.Add(new Db.User { EmployeeId = 2, EmployeeCode = "Emp2", RoleId = 2, IsActive = true, CreateDate = DateTime.Now }); + //userAccessDbContext.Users.Add(new Db.User { EmployeeId = 3, EmployeeCode = "Emp3", RoleId = 3, IsActive = true, CreateDate = DateTime.Now }); + userAccessDbContext.SaveChanges(); + } + + if (!userAccessDbContext.Roles.Any()) + { + userAccessDbContext.Roles.Add(new Db.Role { Name = "admin", Description ="Administrator role have full access" }); + userAccessDbContext.Roles.Add(new Db.Role { Name = "user", Description =" User role"}); + userAccessDbContext.Roles.Add(new Db.Role { Name = "survey", Description ="Survey role" }); + userAccessDbContext.Roles.Add(new Db.Role { Name = "report", Description ="Report role"}); + userAccessDbContext.Roles.Add(new Db.Role { Name = "document", Description ="Document role" }); + userAccessDbContext.SaveChanges(); + } + } + + public async Task<(bool IsSuccess, IEnumerable Users, string ErrorMessage)> GetUsersAsync() + { + try + { + logger?.LogInformation("Gell all Users from DB"); + var users = await userAccessDbContext.Users.ToListAsync(); + if (users != null) + { + logger?.LogInformation($"{users.Count} Items(s) found"); + var result = mapper.Map, IEnumerable>(users); + return (true, result, null); + } + return (false, null, "Not found"); + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } + + public async Task<(bool IsSuccess, Models.User User, string ErrorMessage)> GetUsersAsync(int Id) + { + try + { + logger?.LogInformation("Querying Users table"); + var user = await userAccessDbContext.Users.SingleOrDefaultAsync(s => s.Id == Id); + if (user != null) + { + logger?.LogInformation($"User Id: {Id} found"); + var result = mapper.Map(user); + return (true, result, null); + } + return (false, null, "Not found"); + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } + + public async Task<(bool IsSuccess, Models.User User, string ErrorMessage)> PostUserAsync(Models.User user) + { + try + { + if (user != null) + { + var _user = mapper.Map(user); + userAccessDbContext.Users.Add(_user); + user.Id = _user.Id; + await userAccessDbContext.SaveChangesAsync(); + return (true, user, "Successful"); + } + else + { + logger?.LogInformation($"null object cannot be added"); + return (false, null, $"null object cannot be added"); + } + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } + + public async Task<(bool IsSuccess, Models.User User, string ErrorMessage)> PutUserAsync(int Id, Models.User user) + { + try + { + if (user != null) + { + var _user = await userAccessDbContext.Users.AsNoTracking().Where(s => s.Id == Id).SingleOrDefaultAsync(); + + if (_user != null) + { + int count = userAccessDbContext.Users.Where(u => u.Id != user.Id).Count(); + if (count == 0) + { + await userAccessDbContext.SaveChangesAsync(); + logger?.LogInformation($"Employee Id: {user.EmployeeId} updated successfuly"); + return (true, mapper.Map(_user), $"Employee Id: {_user.EmployeeId} updated successfuly"); + } + else + { + logger?.LogInformation($"Employee Id: {user.EmployeeId} is already exist"); + return (false, null, $"Employee Id: {user.EmployeeId} is already exist"); + } + } + else + { + logger?.LogInformation($"User Id : {Id} Not found"); + return (false, null, "Not Found"); + } + } + else + { + logger?.LogInformation($"User Id: {Id} Bad Request"); + return (false, null, "Bad request"); + } + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } + + public async Task<(bool IsSuccess, Models.User User, string ErrorMessage)> DeleteUserAsync(int Id) + { + try + { + var user = await userAccessDbContext.Users.Where(x => x.Id == Id).SingleOrDefaultAsync(); + + if (user != null) + { + userAccessDbContext.Users.Remove(user); + await userAccessDbContext.SaveChangesAsync(); + logger?.LogInformation($"User Id: {Id} deleted Successfuly"); + return (true, mapper.Map(user), $"User Id: {Id} deleted Successfuly"); + } + else + { + logger?.LogInformation($"User Id : {Id} Not found"); + return (false, null, "Not Found"); + } + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } + + public async Task<(bool IsSuccess, TokenResponse TokenResponse, string ErrorMessage)> AuthenticateAsync(string employecode) + { + + if (employecode != null) + { + //implementation for dadeschools authentication + // var employees = await employeeServiceProvider.getEmployeesAsync(); + // var employee = employees.Where(e=> e.EmployeeCode.ToLower() == employecode.ToLower()).SingleOrDefault(); + var user = userAccessDbContext.Users.Where(x => x.IsActive == true && x.EmployeeCode.ToLower() == employecode.ToLower()).SingleOrDefault(); + + if (user != null) + { + + var r = await GetRolesAsync(); + var role = r.Roles.Where(x => x.Id == user.RoleId).SingleOrDefault(); + + var authClaims = new List { + new Claim(ClaimTypes.Name, user.EmployeeCode), + new Claim(ClaimTypes.Role, role.Name), + new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()) + + }; + + /// Generate Token + var tokenhandler = new JwtSecurityTokenHandler(); + var tokenkey = Encoding.UTF8.GetBytes(jwtSettings.securitykey); + var tokendesc = new SecurityTokenDescriptor + { + Audience = "", + NotBefore = DateTime.Now, + Subject = new ClaimsIdentity(authClaims), + Expires = DateTime.Now.AddMinutes(30), + SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tokenkey), SecurityAlgorithms.HmacSha256) + }; + var token = tokenhandler.CreateToken(tokendesc); + string finaltoken = tokenhandler.WriteToken(token); + + var response = new TokenResponse() { jwttoken = finaltoken, refreshtoken = await tokenServiceProvider.GenerateToken(mapper.Map(user)) }; + return (true, response, "Authentication success and token issued."); + } + else + { + return (false, null, "user inactive or not exist."); + } + } + + else + { + return (false, null, "Credentials are required to authenticate."); + } + } + public async Task<(bool IsSuccess, IEnumerable Roles, string ErrorMessage)> GetRolesAsync() + { + try + { + logger?.LogInformation("Gell all Roles from DB"); + var roles = await userAccessDbContext.Roles.ToListAsync(); + if (roles != null) + { + logger?.LogInformation($"{roles.Count} Items(s) found"); + var result = mapper.Map, IEnumerable>(roles); + return (true, result, null); + } + return (false, null, "Not found"); + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } + + public async Task<(bool IsSuccess, Models.TokenResponse TokenResponse, string ErrorMessage)> RefreshTokenAsync(TokenResponse tokenResponse) + { + //Generate token + var tokenhandler = new JwtSecurityTokenHandler(); + var tokenkey = Encoding.UTF8.GetBytes(this.jwtSettings.securitykey); + SecurityToken securityToken; + var principal = tokenhandler.ValidateToken(tokenResponse.jwttoken, new TokenValidationParameters + { + ValidateIssuerSigningKey = true, + IssuerSigningKey = new SymmetricSecurityKey(tokenkey), + ValidateIssuer = false, + ValidateAudience = false, + + }, out securityToken); + + var token = securityToken as JwtSecurityToken; + if (token != null && !token.Header.Alg.Equals(SecurityAlgorithms.HmacSha256)) + { + return (false, null, "Unauthorized"); + } + var username = principal.Identity?.Name; + + var tokens = await userAccessDbContext.Tokens.ToListAsync(); + var users = await userAccessDbContext.Users.ToListAsync(); + + var user = (from u in users + join t in tokens + on u.Id equals t.UserId + where u.EmployeeId == 1 + && t.RefreshToken == tokenResponse.refreshtoken + select u).FirstOrDefault(); + + if (user == null) + return (false, null, "Invalid Token Response object provided"); + + var _user = mapper.Map(user); + var response = tokenServiceProvider.TokenAuthenticate(_user, principal.Claims.ToArray()).Result; + return (true, response, "Token authenticated and refreshed."); + } + + + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/EmployeeServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/EmployeeServiceProvider.cs new file mode 100644 index 0000000..a0364a0 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/EmployeeServiceProvider.cs @@ -0,0 +1,50 @@ +using DamageAssesment.Api.UsersAccess.Interfaces; +using DamageAssesment.Api.UsersAccess.Models; +using Newtonsoft.Json; + +namespace DamageAssesment.Api.UsersAccess.Services +{ + public class EmployeeServiceProvider : ServiceProviderBase, IEmployeeServiceProvider + { + public EmployeeServiceProvider(IConfiguration configuration, IHttpUtil httpUtil, ILogger logger) : base(configuration, httpUtil, logger, configuration.GetValue("RessourceSettings:Employee"), configuration.GetValue("EndPointSettings:EmployeeUrlBase")) + { + } + + public async Task> getEmployeesAsync() + { + try + { + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var employees = JsonConvert.DeserializeObject>(responseJsonString); + + if (employees == null || !employees.Any()) + return new List(); + else return employees; + } + catch (Exception ex) + { + logger?.LogError($"Exception Found : {ex.Message} - Ref: EmployeeServiceProvider.getEmployeesAsync()"); + return new List(); + } + } + + public async Task getEmployeeAsync(int employeeId) + { + try + { + url = urlBase + string.Format(configuration.GetValue("RessourceSettings:EmployeeById"), employeeId); + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var employee = JsonConvert.DeserializeObject(responseJsonString); + + if (employee == null) + return null; + else return employee; + } + catch (Exception ex) + { + logger?.LogError($"Exception Found : {ex.Message} - Ref: EmployeeServiceProvider.getEmployeeAsync()"); + return null; + } + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/HttpUtil.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/HttpUtil.cs new file mode 100644 index 0000000..a8b5c9f --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/HttpUtil.cs @@ -0,0 +1,42 @@ +using DamageAssesment.Api.UsersAccess.Interfaces; +using System.Net.Http.Headers; +using System.Text; + +namespace DamageAssesment.Api.UsersAccess.Services +{ + public class HttpUtil : IHttpUtil + { + private readonly HttpClient httpClient; + private readonly ILogger logger; + + public HttpUtil(HttpClient httpClient, ILogger logger) + { + this.httpClient = httpClient; + this.logger = logger; + } + public async Task SendAsync(HttpMethod method, string url, string JsonInput) + { + try + { + var request = new HttpRequestMessage(method, url); + request.Headers.Accept.Clear(); + request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + //request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + if (method == HttpMethod.Post) + { + request.Content = new StringContent(JsonInput, Encoding.UTF8, "application/json"); + } + var response = await httpClient.SendAsync(request, CancellationToken.None); + response.EnsureSuccessStatusCode(); + var responseString = await response.Content.ReadAsStringAsync(); + return responseString; + } + catch (Exception ex) + { + logger?.LogError($"Exception Message : {ex.Message} - Ref: HttpUtil.SendAsync()"); + return null; + } + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/ServiceProviderBase.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/ServiceProviderBase.cs new file mode 100644 index 0000000..a90b839 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/ServiceProviderBase.cs @@ -0,0 +1,25 @@ +using DamageAssesment.Api.UsersAccess.Interfaces; + +namespace DamageAssesment.Api.UsersAccess.Services +{ + public class ServiceProviderBase + { + protected readonly IConfiguration configuration; + protected readonly IHttpUtil httpUtil; + protected readonly ILogger logger; + protected string ressource; + protected string urlBase; + protected string url; + + + public ServiceProviderBase(IConfiguration configuration, IHttpUtil httpUtil, ILogger logger, string ressource, string urlBase) + { + this.configuration = configuration; + this.httpUtil = httpUtil; + this.logger = logger; + this.ressource = ressource; + this.urlBase = urlBase; + url = urlBase + ressource; + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/TokenServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/TokenServiceProvider.cs new file mode 100644 index 0000000..91645b9 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Services/TokenServiceProvider.cs @@ -0,0 +1,59 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Security.Cryptography; +using System.Text; +using DamageAssesment.Api.UsersAccess.Db; +using DamageAssesment.Api.UsersAccess.Interfaces; +using DamageAssesment.Api.UsersAccess.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; +using Microsoft.IdentityModel.Tokens; + +namespace DamageAssesment.Api.UsersAccess.Services +{ + public class TokenServiceProvider : ITokenServiceProvider + { + private readonly UsersAccessDbContext usersAccessDbContext; + private readonly JwtSettings jwtSettings; + public TokenServiceProvider(IOptions options, UsersAccessDbContext usersAccessDbContext) + { + this.usersAccessDbContext = usersAccessDbContext; + this.jwtSettings = options.Value; + } + public async Task GenerateToken(Models.User user) + { + var randomnumber = new byte[32]; + using (var ramdomnumbergenerator = RandomNumberGenerator.Create()) + { + ramdomnumbergenerator.GetBytes(randomnumber); + string refreshtoken = Convert.ToBase64String(randomnumber); + var token = await usersAccessDbContext.Tokens.FirstOrDefaultAsync(item => item.UserId == user.Id); + if (token != null) + { + token.RefreshToken = refreshtoken; + } + else + { + usersAccessDbContext.Tokens.Add(new Db.Token() + { + UserId = user.Id, + RefreshToken = refreshtoken, + IsActive = true + }); + } + await usersAccessDbContext.SaveChangesAsync(); + + return refreshtoken; + } + } + + public async Task TokenAuthenticate(Models.User user, Claim[] claims) + { + var token = new JwtSecurityToken(claims: claims, expires: DateTime.Now.AddSeconds(20), + signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.securitykey)), SecurityAlgorithms.HmacSha256) + ); + var jwttoken = new JwtSecurityTokenHandler().WriteToken(token); + return new TokenResponse() { jwttoken = jwttoken, refreshtoken = await GenerateToken(user) }; + } + } +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.Development.json b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json new file mode 100644 index 0000000..150b8f3 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json @@ -0,0 +1,41 @@ +{ + "JwtSettings": { + "securitykey": "bWlhbWkgZGFkZSBzY2hvb2xzIHNlY3JldCBrZXk=" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "EndPointSettings": { + "EmployeeUrlBase": "http://localhost:5135" + }, + "RessourceSettings": { + "Employee": "/Employees", + "EmployeeById": "/Employees/{0}" + }, + "AllowedHosts": "*", + "Dadeschools": { + "Authority": "https://dev-graph.dadeschools.net", + "TokenUrl": "https://dev-graph.dadeschools.net/connect/token", + "ClientId": "dmapi", + "ClientSecret": "bfce2c8d-2064-4a02-b19d-7f1d42b16eae", + "Name": "Dadeschools Identity Server" + }, + "Scopes": [ + { + "Name": "openid", + "Description": "Request an authentication token on your behalf" + }, + { + "Name": "profile", + "Description": "Read basic information about you such as your date of brith and full name" + } + ], + "ConnectionStrings": { + "UsersAccessConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" + //"UsersAccessConnection": "Server=tcp:da-dev.database.windows.net,1433;Initial Catalog=da-dev-db;Encrypt=True;User ID=admin-dev;Password=b3tgRABw8LGE75k;TrustServerCertificate=False;Connection Timeout=30;" + + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Responses.Test/DamageAssesment.Api.Responses.Test.csproj b/DamageAssesmentApi/DamageAssesment.Responses.Test/DamageAssesment.Api.Responses.Test.csproj new file mode 100644 index 0000000..5190942 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Responses.Test/DamageAssesment.Api.Responses.Test.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/DamageAssesmentApi/DamageAssesment.Responses.Test/MockData.cs b/DamageAssesmentApi/DamageAssesment.Responses.Test/MockData.cs new file mode 100644 index 0000000..c7a52de --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Responses.Test/MockData.cs @@ -0,0 +1,30 @@ + +using DamageAssesment.Api.Responses.Models; +using System.Collections.Generic; +using System.Text; + +namespace DamageAssesment.Api.Responses.Test +{ + public class MockData + { + public static async Task<(bool, SurveyResponse, string)> getOkResponse(SurveyResponse data) + { + return (true, data, null); + } + + public static async Task<(bool, dynamic, string)> getOkResponse() + { + return (true, new { }, null); + } + + public static async Task<(bool, Models.SurveyResponse, string)> getResponse() + { + return (false, null, null); + } + + public static async Task getSurveyResponseObject() + { + return new Models.SurveyResponse { EmployeeId = 1, LocationId = 1, SurveyId = 1, Id = 1 }; + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Responses.Test/ResponsesServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Responses.Test/ResponsesServiceTest.cs new file mode 100644 index 0000000..e586917 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Responses.Test/ResponsesServiceTest.cs @@ -0,0 +1,251 @@ +using DamageAssesment.Api.Responses.Controllers; +using DamageAssesment.Api.Responses.Interfaces; +using DamageAssesment.Api.Responses.Models; +using DamageAssesment.Api.Responses.Test; +using Microsoft.AspNetCore.Mvc; +using Moq; +using Xunit; + + +namespace DamageAssesment.SurveyResponses.Test +{ + public class ResponsesServiceTest + { + private Mock mockSurveyResponseService; + private string token { get; set; } + public ResponsesServiceTest() + { + mockSurveyResponseService = new Mock(); + token = Guid.NewGuid().ToString(); + } + + [Fact(DisplayName = "Get Responses - Ok case")] + public async Task GetSurveyResponsesAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(mockRequestObject); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesAsync()).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses - BadRequest case")] + public async Task GetSurveyResponsesAsync_ShouldReturnStatusCode204() + { + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesAsync()).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (BadRequestObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(); + Assert.Equal(400, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by surveyId - Ok case")] + public async Task GetSurveyResponsesBySurveyAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(); +<<<<<<<< HEAD:DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1,1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1,1); +======== + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1); +>>>>>>>> Azure-Integration:DamageAssesmentApi/DamageAssesment.Responses.Test/ResponsesServiceTest.cs + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by surveyId - NoContent case")] + public async Task GetSurveyResponsesBySurveyAsync_ShouldReturnStatusCode204() + { + var mockResponse = await MockData.getResponse(); +<<<<<<<< HEAD:DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1,1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesAsync(1,1); +======== + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesAsync(1); +>>>>>>>> Azure-Integration:DamageAssesmentApi/DamageAssesment.Responses.Test/ResponsesServiceTest.cs + Assert.Equal(204, result.StatusCode); + } + + + + + [Fact(DisplayName = "Get Responses by surveyId and locationId - Ok case")] + public async Task GetSurveyResponsesBySurveyLocationAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by surveyId and locationId - NoContent case")] + public async Task GetSurveyResponsesBySurveyLocationAsync_ShouldReturnStatusCode204() + { + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1); + Assert.Equal(204, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by surveyId and QuestionId and Answer - Ok case")] + public async Task GetSurveyResponsesBySurveyQuestionAnswerAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(); + mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes")).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes"); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by surveyId and QuestionId and Answer - NoContent case")] + public async Task GetSurveyResponsesBySurveyQuestionAnswerAsync_ShouldReturnStatusCode204() + { + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes")).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes"); + Assert.Equal(204, result.StatusCode); + } + + + [Fact(DisplayName = "Get Responses by region and surveyId - Ok case")] + public async Task GetSurveyResponsesByRegionSurveyAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(); + mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetAnswersByRegionAsync(1); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by region and surveyId - NoContent Case")] + public async Task GetSurveyResponsesByRegionSurveyAsync_ShouldReturnStatusCode204() + { + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetAnswersByRegionAsync(1); + Assert.Equal(204, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by maintenanceCenter and surveyId - Ok case")] + public async Task GetSurveyResponsesMaintenanceCenterSurveyAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesByMaintenanceCenterAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetAnswersByMaintenaceCentersync(1); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by maintenanceCenter and surveyId - No Content Case")] + public async Task GetSurveyResponsesMaintenanceCenterSurveyAsync_ShouldReturnStatusCode204() + { + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesByMaintenanceCenterAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetAnswersByMaintenaceCentersync(1); + Assert.Equal(204, result.StatusCode); + } + + [Fact(DisplayName = "Get SurveyResponse by responseId- Ok case")] + public async Task GetSurveyResponsesByResponseIdyAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(); + mockSurveyResponseService.Setup(service => service.GetSurveyResponseByIdAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponseByIdAsync(1); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Get Responses by maintenanceCenter and surveyId - NoContent Case")] + public async Task GetSurveyResponsesByResponseIdyAsync_ShouldReturnStatusCode204() + { + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.GetSurveyResponseByIdAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new ResponsesController(mockSurveyResponseService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponseByIdAsync(1); + Assert.Equal(204, result.StatusCode); + } + + + [Fact(DisplayName = "Post Responses - Ok case")] + public async Task PostSurveyAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(mockRequestObject); + mockSurveyResponseService.Setup(service => service.PostSurveyResponseAsync(mockRequestObject)).ReturnsAsync(mockResponse); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseController.PostSurveysAsync(mockRequestObject); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Post Responses - BadRequest case")] + public async Task PostSurveyAsync_ShouldReturnStatusCode400() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.PostSurveyResponseAsync(mockRequestObject)).ReturnsAsync(mockResponse); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); + var result = (BadRequestObjectResult)await surveyResponseController.PostSurveysAsync(mockRequestObject); + Assert.Equal(400, result.StatusCode); + } + + [Fact(DisplayName = "Put Responses - Ok case")] + public async Task PutSurveyAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(mockRequestObject); + mockSurveyResponseService.Setup(service => service.PutSurveyResponseAsync(1, mockRequestObject)).ReturnsAsync(mockResponse); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseController.PutSurveyResponseAsync(1, mockRequestObject); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Put Responses - BadRequest case")] + public async Task PutSurveyAsync_ShouldReturnStatusCode404() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.PutSurveyResponseAsync(1, mockRequestObject)).ReturnsAsync(mockResponse); ; + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); + var result = (BadRequestObjectResult)await surveyResponseController.PutSurveyResponseAsync(1, mockRequestObject); + Assert.Equal(400, result.StatusCode); + } + + [Fact(DisplayName = "Delete Responses - Ok case")] + public async Task DeleteSurveyAsync_ShouldReturnStatusCode200() + { + SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); + var mockResponse = await MockData.getOkResponse(mockRequestObject); + mockSurveyResponseService.Setup(service => service.DeleteSurveyResponseAsync(1)).ReturnsAsync(mockResponse); + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); + var result = (OkObjectResult)await surveyResponseController.DeleteSurveyResponseAsync(1); + Assert.Equal(200, result.StatusCode); + } + + [Fact(DisplayName = "Delete Responses - NotFound case")] + public async Task DeleteSurveyAsync_ShouldReturnStatusCode404() + { + var mockResponse = await MockData.getResponse(); + mockSurveyResponseService.Setup(service => service.DeleteSurveyResponseAsync(1)).ReturnsAsync(mockResponse); ; + var surveyResponseController = new ResponsesController(mockSurveyResponseService.Object); + var result = (NotFoundResult)await surveyResponseController.DeleteSurveyResponseAsync(1); + Assert.Equal(404, result.StatusCode); + } + } +} \ No newline at end of file diff --git a/DamageAssesmentApi/DamageAssesment.sln b/DamageAssesmentApi/DamageAssesment.sln index 23f7731..a6c9a8f 100644 --- a/DamageAssesmentApi/DamageAssesment.sln +++ b/DamageAssesmentApi/DamageAssesment.sln @@ -36,6 +36,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamageAssesment.Api.Employe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamageAssesment.Api.DocuLinks.Test", "DamageAssesment.Api.DocuLinks.Test\DamageAssesment.Api.DocuLinks.Test.csproj", "{A7F17ED7-71D2-4FD0-87E5-D83415078FC0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamageAssesment.Api.UsersAccess", "DamageAssesment.Api.UsersAccess\DamageAssesment.Api.UsersAccess.csproj", "{40240AD6-90D2-4128-BCDF-12C77D1B1B55}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamageAssesment.Api.UsersAccess.Test", "DamageAssesment.Api.UsersAccess.Test\DamageAssesment.Api.UsersAccess.Test.csproj", "{ADAF9385-262C-4A37-A603-A53B77EA515D}" +EndProject Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{0DD44934-6826-43C8-A438-320A05209967}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DamageAssesment.Api.DocuLinks", "DamageAssesment.Api.DocuLinks\DamageAssesment.Api.DocuLinks.csproj", "{B027FBB9-1357-4FD6-85B3-8ADCE11CAE05}" @@ -102,6 +106,14 @@ Global {A7F17ED7-71D2-4FD0-87E5-D83415078FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7F17ED7-71D2-4FD0-87E5-D83415078FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7F17ED7-71D2-4FD0-87E5-D83415078FC0}.Release|Any CPU.Build.0 = Release|Any CPU + {40240AD6-90D2-4128-BCDF-12C77D1B1B55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40240AD6-90D2-4128-BCDF-12C77D1B1B55}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40240AD6-90D2-4128-BCDF-12C77D1B1B55}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40240AD6-90D2-4128-BCDF-12C77D1B1B55}.Release|Any CPU.Build.0 = Release|Any CPU + {ADAF9385-262C-4A37-A603-A53B77EA515D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ADAF9385-262C-4A37-A603-A53B77EA515D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ADAF9385-262C-4A37-A603-A53B77EA515D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ADAF9385-262C-4A37-A603-A53B77EA515D}.Release|Any CPU.Build.0 = Release|Any CPU {0DD44934-6826-43C8-A438-320A05209967}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0DD44934-6826-43C8-A438-320A05209967}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DD44934-6826-43C8-A438-320A05209967}.Release|Any CPU.ActiveCfg = Release|Any CPU From 2182b9a6b38d0e8533c2197579d3c3a63db5f3a2 Mon Sep 17 00:00:00 2001 From: uppuv Date: Mon, 23 Oct 2023 11:39:56 -0400 Subject: [PATCH 33/40] added status field in survey micro service --- .../Models/Survey.cs | 7 +++++++ .../Providers/SurveysProvider.cs | 21 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs index 25f5405..38fa72a 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs @@ -2,9 +2,16 @@ namespace DamageAssesment.Api.Surveys.Models { + public enum SurveyStatus + { + PENDING, + ACTIVE, + INACTIVE + } public class MultiLanSurvey : BaseSurvey { public object Titles { get; set; } + public string Status { get; set; } } public class Survey : BaseSurvey { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs index 3332f6d..bb44cf2 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs @@ -26,9 +26,9 @@ namespace DamageAssesment.Api.Surveys.Providers { if (!surveyDbContext.Surveys.Any()) { - var survey1 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; - var survey2 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; - var survey3 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; + var survey1 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(10), EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; + var survey2 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(-10), EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now.AddDays(-10) }; + var survey3 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(-100), EndDate = DateTime.Now.AddDays(-10), CreatedDate = DateTime.Now.AddDays(-100) }; surveyDbContext.Surveys.Add(survey1); surveyDbContext.Surveys.Add(survey2); @@ -85,7 +85,15 @@ namespace DamageAssesment.Api.Surveys.Providers MultiLanguage = dict; return MultiLanguage; } - + public string GetStatus(DateTime StartDate,DateTime EndDate) + { + if (StartDate > DateTime.Now) + return SurveyStatus.PENDING.ToString(); + else if (StartDate <= DateTime.Now && EndDate > DateTime.Now) + return SurveyStatus.ACTIVE.ToString(); + else + return SurveyStatus.INACTIVE.ToString(); + } // Method to get surveys asynchronously with multi-language support public async Task<(bool IsSuccess, IEnumerable Surveys, string ErrorMessage)> GetSurveysAsync(string language) { @@ -105,6 +113,7 @@ namespace DamageAssesment.Api.Surveys.Providers EndDate = s.EndDate, IsEnabled = s.IsEnabled, CreatedDate = s.CreatedDate, + Status= GetStatus(s.StartDate,s.EndDate), Titles = CreateMultiLanguageObject(GetSurveyTranslations(s.Id, null, language)) }; @@ -139,6 +148,7 @@ namespace DamageAssesment.Api.Surveys.Providers EndDate = survey.EndDate, IsEnabled = survey.IsEnabled, CreatedDate = survey.CreatedDate, + Status = GetStatus(survey.StartDate, survey.EndDate), Titles = CreateMultiLanguageObject(GetSurveyTranslations(survey.Id, null, language)) }; logger?.LogInformation($"Survey Id: {id} found"); @@ -172,6 +182,7 @@ namespace DamageAssesment.Api.Surveys.Providers } await surveyDbContext.SaveChangesAsync(); var result = mapper.Map(_survey); + result.Status = GetStatus(_survey.StartDate, _survey.EndDate); result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(_survey.Id, survey.Titles, "")); return (true, result, "Successful"); } @@ -216,6 +227,7 @@ namespace DamageAssesment.Api.Surveys.Providers await surveyDbContext.SaveChangesAsync(); var result = mapper.Map(_survey); + result.Status = GetStatus(_survey.StartDate, _survey.EndDate); result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(_survey.Id, survey.Titles, "")); return (true, result, "Successful"); } @@ -248,6 +260,7 @@ namespace DamageAssesment.Api.Surveys.Providers if (survey != null) { var result = mapper.Map(survey); + result.Status = GetStatus(survey.StartDate, survey.EndDate); result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(survey.Id, null, "")); surveyDbContext.Surveys.Remove(survey); await surveyDbContext.SaveChangesAsync(); From 7b7e5c0ce80b1b1816b8850246fcf87f36a6fa5e Mon Sep 17 00:00:00 2001 From: uppuv Date: Mon, 23 Oct 2023 12:03:50 -0400 Subject: [PATCH 34/40] added status field in survey micro service --- .../Models/Survey.cs | 7 +++++++ .../Providers/SurveysProvider.cs | 21 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs index 25f5405..38fa72a 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs @@ -2,9 +2,16 @@ namespace DamageAssesment.Api.Surveys.Models { + public enum SurveyStatus + { + PENDING, + ACTIVE, + INACTIVE + } public class MultiLanSurvey : BaseSurvey { public object Titles { get; set; } + public string Status { get; set; } } public class Survey : BaseSurvey { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs index de945c6..e48efc1 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs @@ -26,9 +26,9 @@ namespace DamageAssesment.Api.Surveys.Providers { if (!surveyDbContext.Surveys.Any()) { - var survey1 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; - var survey2 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; - var survey3 = new Db.Survey { IsEnabled = false, StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; + var survey1 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(10), EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now }; + var survey2 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(-10), EndDate = DateTime.Now.AddDays(90), CreatedDate = DateTime.Now.AddDays(-10) }; + var survey3 = new Db.Survey { IsEnabled = true, StartDate = DateTime.Now.AddDays(-100), EndDate = DateTime.Now.AddDays(-10), CreatedDate = DateTime.Now.AddDays(-100) }; surveyDbContext.Surveys.Add(survey1); surveyDbContext.Surveys.Add(survey2); @@ -85,7 +85,15 @@ namespace DamageAssesment.Api.Surveys.Providers MultiLanguage = dict; return MultiLanguage; } - + public string GetStatus(DateTime StartDate,DateTime EndDate) + { + if (StartDate > DateTime.Now) + return SurveyStatus.PENDING.ToString(); + else if (StartDate <= DateTime.Now && EndDate > DateTime.Now) + return SurveyStatus.ACTIVE.ToString(); + else + return SurveyStatus.INACTIVE.ToString(); + } // Method to get surveys asynchronously with multi-language support public async Task<(bool IsSuccess, IEnumerable Surveys, string ErrorMessage)> GetSurveysAsync(string language) { @@ -106,6 +114,7 @@ namespace DamageAssesment.Api.Surveys.Providers EndDate = s.EndDate, IsEnabled = s.IsEnabled, CreatedDate = s.CreatedDate, + Status= GetStatus(s.StartDate,s.EndDate), Titles = CreateMultiLanguageObject(GetSurveyTranslations(s.Id, null, language)) }; @@ -140,6 +149,7 @@ namespace DamageAssesment.Api.Surveys.Providers EndDate = survey.EndDate, IsEnabled = survey.IsEnabled, CreatedDate = survey.CreatedDate, + Status = GetStatus(survey.StartDate, survey.EndDate), Titles = CreateMultiLanguageObject(GetSurveyTranslations(survey.Id, null, language)) }; logger?.LogInformation($"Survey Id: {id} found"); @@ -173,6 +183,7 @@ namespace DamageAssesment.Api.Surveys.Providers } await surveyDbContext.SaveChangesAsync(); var result = mapper.Map(_survey); + result.Status = GetStatus(_survey.StartDate, _survey.EndDate); result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(_survey.Id, survey.Titles, "")); return (true, result, "Successful"); } @@ -217,6 +228,7 @@ namespace DamageAssesment.Api.Surveys.Providers await surveyDbContext.SaveChangesAsync(); var result = mapper.Map(_survey); + result.Status = GetStatus(_survey.StartDate, _survey.EndDate); result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(_survey.Id, survey.Titles, "")); return (true, result, "Successful"); } @@ -249,6 +261,7 @@ namespace DamageAssesment.Api.Surveys.Providers if (survey != null) { var result = mapper.Map(survey); + result.Status = GetStatus(survey.StartDate, survey.EndDate); result.Titles = CreateMultiLanguageObject(GetSurveyTranslations(survey.Id, null, "")); surveyDbContext.Surveys.Remove(survey); await surveyDbContext.SaveChangesAsync(); From 499ac9248bff70d4da44535bc275cb5c5d793b6b Mon Sep 17 00:00:00 2001 From: uppuv Date: Tue, 24 Oct 2023 12:15:13 -0400 Subject: [PATCH 35/40] reverted doculinks grouping by linktype --- .../DoculinkServiceTest.cs | 6 +++--- .../DamageAssesment.Api.DocuLinks.Test/MockData.cs | 6 +++--- .../Interfaces/IDoculinkProvider.cs | 8 ++++---- .../Providers/DoculinkProvider.cs | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs index 14ddaaa..a8f45d1 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/DoculinkServiceTest.cs @@ -16,7 +16,7 @@ namespace DamageAssesment.Api.DocuLinks.Test { var mockDocumentService = new Mock(); var mockUploadService = new Mock(); - var mockResponse = await MockData.getNoContentResponses(); + var mockResponse = await MockData.getNoContentResponse(); mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms","en",null)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); @@ -30,7 +30,7 @@ namespace DamageAssesment.Api.DocuLinks.Test { var mockDocumentService = new Mock(); var mockUploadService = new Mock(); - var mockResponse = await MockData.getNoContentResponses(); + var mockResponse = await MockData.getNoContentResponse(); mockDocumentService.Setup(service => service.GetdocumentsByLinkAsync("forms", "en", true)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); @@ -83,7 +83,7 @@ namespace DamageAssesment.Api.DocuLinks.Test { var mockDocumentService = new Mock(); var mockUploadService = new Mock(); - var mockResponse = await MockData.getNoContentResponses(); + var mockResponse = await MockData.getNoContentResponse(); mockDocumentService.Setup(service => service.GetdocumentsByLinkTypeIdAsync(null, "en", true)).ReturnsAsync(mockResponse); var DocumentProvider = new DoculinkController(mockDocumentService.Object, mockUploadService.Object); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs index 23ffae4..843b4d3 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks.Test/MockData.cs @@ -11,7 +11,7 @@ namespace DamageAssesment.Api.DocuLinks.Test public class MockData { - public static async Task<(bool, List, string)> getOkResponses() + public static async Task<(bool, List, string)> getOkResponses() { List list = new List(); @@ -46,8 +46,8 @@ namespace DamageAssesment.Api.DocuLinks.Test doclinksAttachments= doclinksAttachments }); } - List doculinks = list.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); - return (true, doculinks, null); + // List doculinks = list.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); + return (true, list, null); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs index 6d271fd..e9717ee 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Interfaces/IDoculinkProvider.cs @@ -6,11 +6,11 @@ namespace DamageAssesment.Api.DocuLinks.Interfaces { Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> GetDocumentAsync(int id, string? linktype, string? language); Task<(bool IsSuccess, Models.Doculink Document, string ErrorMessage)> GetDocumentByidAsync(int id); - // Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetDocumnetsAsync(string? language); - Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive); - Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive); + // Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetDocumnetsAsync(string? language); + Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive); + 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, Models.Doculink Document); Task<(bool IsSuccess, Models.ResDoculink Document, string ErrorMessage)> DeleteDocumentAsync(int id); Task<(bool IsSuccess, int counter, string message)> GetDocumentCounter(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs index 81535ab..5eb57ae 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.DocuLinks/Providers/DoculinkProvider.cs @@ -171,7 +171,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers return MultiLanguage; } - public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive) + public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkTypeIdAsync(int? linkTypeId, string? language, bool? isactive) { try @@ -195,8 +195,8 @@ namespace DamageAssesment.Api.DocuLinks.Providers item.doclinksAttachments = mapper.Map, List>( DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == item.Id).ToList()); } - List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); - return (true, doculinks, null); + // List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); + return (true, result, null); } return (false, null, "Not found"); } @@ -207,7 +207,7 @@ namespace DamageAssesment.Api.DocuLinks.Providers } } - public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive) + public async Task<(bool IsSuccess, IEnumerable documents, string ErrorMessage)> GetdocumentsByLinkAsync(string? linkType, string? language, bool? isactive) { try @@ -231,8 +231,8 @@ namespace DamageAssesment.Api.DocuLinks.Providers item.doclinksAttachments = mapper.Map, List>( DocumentDbContext.DoclinksAttachments.AsNoTracking().Where(a => a.DocumentId == item.Id).ToList()); } - List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); - return (true, doculinks, null); + //List doculinks = result.GroupBy(a => a.linkTypeId).Select(a => new ResDoculinks() { linkTypeId = a.Key, doculinks = a.ToList() }).ToList(); + return (true, result, null); } return (false, null, "Not found"); } From fc166e65c910a5888d6c503641660c261ae9b730 Mon Sep 17 00:00:00 2001 From: uppuv Date: Tue, 31 Oct 2023 16:19:24 -0400 Subject: [PATCH 36/40] fixed survey put issue, amd added export excel in responses --- .../SurveyResponsesServiceTest.cs | 62 +++---- .../Controllers/SurveyResponsesController.cs | 44 ++++- .../DamageAssesment.Api.Responses.csproj | 2 + .../Interfaces/IExcelExportService.cs | 7 + .../Interfaces/IQuestionServiceProvider.cs | 3 +- .../Interfaces/ISurveysResponse.cs | 3 +- .../Models/Attachment.cs | 1 + .../Models/Location.cs | 1 + .../Models/QuestionCategory.cs | 10 ++ .../Models/SurveyExport.cs | 24 +++ .../DamageAssesment.Api.Responses/Program.cs | 1 + .../Providers/ExcelExportService.cs | 57 +++++++ .../Providers/SurveyResponsesProvider.cs | 161 +++++++++++++++++- .../Services/QuestionServiceProvider.cs | 27 ++- .../appsettings.json | 3 +- .../Providers/SurveysProvider.cs | 4 +- 16 files changed, 363 insertions(+), 47 deletions(-) create mode 100644 DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IExcelExportService.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.Responses/Models/QuestionCategory.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.Responses/Models/SurveyExport.cs create mode 100644 DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs index 48cec58..05b3e02 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses.Test/SurveyResponsesServiceTest.cs @@ -12,9 +12,11 @@ namespace DamageAssesment.SurveyResponses.Test public class SurveyResponsesServiceTest { Mock mockSurveyResponseService; + Mock mockExcelExportService; public SurveyResponsesServiceTest() { mockSurveyResponseService = new Mock(); + mockExcelExportService = new Mock(); } [Fact(DisplayName = "Get Responses - Ok case")] @@ -23,7 +25,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1); Assert.Equal(200, result.StatusCode); } @@ -33,7 +35,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (BadRequestObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1); Assert.Equal(400, result.StatusCode); } @@ -43,9 +45,9 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1,1); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesAsync(1, 1); Assert.Equal(200, result.StatusCode); } @@ -53,9 +55,9 @@ namespace DamageAssesment.SurveyResponses.Test public async Task GetSurveyResponsesBySurveyAsync_ShouldReturnStatusCode204() { var mockResponse = await MockData.getResponse(); - mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesAsync(1,1); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesAsync(1, 1); Assert.Equal(204, result.StatusCode); } @@ -67,9 +69,9 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1,1); + mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1); Assert.Equal(200, result.StatusCode); } @@ -78,7 +80,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(1, 1, 1); Assert.Equal(204, result.StatusCode); } @@ -88,9 +90,9 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes",1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes",1); + mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes", 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); + var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes", 1); Assert.Equal(200, result.StatusCode); } @@ -99,8 +101,8 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetResponsesByAnswerAsync(1, 1, "Yes", 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); - var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes",1); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); + var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponsesByAnswerAsyncAsync(1, 1, "Yes", 1); Assert.Equal(204, result.StatusCode); } @@ -110,8 +112,8 @@ namespace DamageAssesment.SurveyResponses.Test { SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); - mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1,1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1, 1)).ReturnsAsync(mockResponse); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetAnswersByRegionAsync(1, 1); Assert.Equal(200, result.StatusCode); } @@ -121,7 +123,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetAnswersByRegionAsync(1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (NoContentResult)await surveyResponseProvider.GetAnswersByRegionAsync(1, 1); Assert.Equal(204, result.StatusCode); } @@ -132,7 +134,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesByMaintenanceCenterAsync(1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetAnswersByMaintenaceCentersync(1, 1); Assert.Equal(200, result.StatusCode); } @@ -142,7 +144,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponsesByMaintenanceCenterAsync(1, 1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (NoContentResult)await surveyResponseProvider.GetAnswersByMaintenaceCentersync(1, 1); Assert.Equal(204, result.StatusCode); } @@ -153,7 +155,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponseByIdAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (OkObjectResult)await surveyResponseProvider.GetSurveyResponseByIdAsync(1); Assert.Equal(200, result.StatusCode); } @@ -163,7 +165,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.GetSurveyResponseByIdAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseProvider = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (NoContentResult)await surveyResponseProvider.GetSurveyResponseByIdAsync(1); Assert.Equal(204, result.StatusCode); } @@ -175,7 +177,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.PostSurveyResponseAsync(mockRequestObject)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (OkObjectResult)await surveyResponseController.PostSurveysAsync(mockRequestObject); Assert.Equal(200, result.StatusCode); } @@ -186,7 +188,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.PostSurveyResponseAsync(mockRequestObject)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (BadRequestObjectResult)await surveyResponseController.PostSurveysAsync(mockRequestObject); Assert.Equal(400, result.StatusCode); } @@ -197,7 +199,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.PutSurveyResponseAsync(1, mockRequestObject)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (OkObjectResult)await surveyResponseController.PutSurveyResponseAsync(1, mockRequestObject); Assert.Equal(200, result.StatusCode); } @@ -208,7 +210,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.PutSurveyResponseAsync(1, mockRequestObject)).ReturnsAsync(mockResponse); ; - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (BadRequestObjectResult)await surveyResponseController.PutSurveyResponseAsync(1, mockRequestObject); Assert.Equal(400, result.StatusCode); } @@ -219,7 +221,7 @@ namespace DamageAssesment.SurveyResponses.Test SurveyResponse mockRequestObject = await MockData.getSurveyResponseObject(); var mockResponse = await MockData.getOkResponse(mockRequestObject); mockSurveyResponseService.Setup(service => service.DeleteSurveyResponseAsync(1)).ReturnsAsync(mockResponse); - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (OkObjectResult)await surveyResponseController.DeleteSurveyResponseAsync(1); Assert.Equal(200, result.StatusCode); } @@ -229,7 +231,7 @@ namespace DamageAssesment.SurveyResponses.Test { var mockResponse = await MockData.getResponse(); mockSurveyResponseService.Setup(service => service.DeleteSurveyResponseAsync(1)).ReturnsAsync(mockResponse); ; - var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object); + var surveyResponseController = new SurveyResponsesController(mockSurveyResponseService.Object, mockExcelExportService.Object); var result = (NotFoundResult)await surveyResponseController.DeleteSurveyResponseAsync(1); Assert.Equal(404, result.StatusCode); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs index 55b7f5d..9fce5f8 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs @@ -8,10 +8,12 @@ namespace DamageAssesment.Api.Responses.Controllers public class SurveyResponsesController : ControllerBase { private readonly ISurveysResponse surveyResponseProvider; + private readonly IExcelExportService excelExportService; - public SurveyResponsesController(ISurveysResponse surveyResponseProvider) + public SurveyResponsesController(ISurveysResponse surveyResponseProvider, IExcelExportService excelExportService) { this.surveyResponseProvider = surveyResponseProvider; + this.excelExportService = excelExportService; } /// /// GET request for retrieving survey responses. @@ -57,9 +59,9 @@ namespace DamageAssesment.Api.Responses.Controllers [Route("responses/{surveyid:int}/{locationid:int}/{employeeid:int}")] [Route("responses/{surveyid:int}/{locationid:int}")] [HttpGet] - public async Task GetSurveyResponsesBySurveyAndLocationAsync(int surveyid, int locationid,int? employeeid) + public async Task GetSurveyResponsesBySurveyAndLocationAsync(int surveyid, int locationid, int? employeeid) { - var result = await this.surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(surveyid, locationid,employeeid ?? 0); + var result = await this.surveyResponseProvider.GetSurveyResponsesBySurveyAndLocationAsync(surveyid, locationid, employeeid ?? 0); if (result.IsSuccess) { return Ok(result.SurveyResponses); @@ -198,7 +200,9 @@ namespace DamageAssesment.Api.Responses.Controllers else return BadRequest(result.ErrorMessage); } - + /// + /// Get All active surveys . + /// [Route("responses/surveys/active")] [Route("responses/surveys/active/{language:alpha}")] [Route("responses/surveys/active/{employeeid:int}")] @@ -213,7 +217,39 @@ namespace DamageAssesment.Api.Responses.Controllers } return NoContent(); } + /// + /// Export surveys based on role . + /// + [HttpGet] + [Route("responses/surveys/export")] + public async Task GetExcelSurveysAsync(string language,bool IsAdmin=false) + { + var result = await this.surveyResponseProvider.ExportSurveyResponsesAsync(language, IsAdmin); + if (result.IsSuccess) + { + byte[] fileContents = excelExportService.ExportToExcel(result.surveyResponses); + return File(fileContents, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "data.xlsx"); + //return Ok(result.Surveys); + } + return NoContent(); + } + //[Route("responses/surveys/active")] + //[Route("responses/surveys/active/{language:alpha}")] + //[HttpGet] + //public async Task GetActiveSurveysAsync( string? language) + //{ + // var result = await this.surveyResponseProvider.GetActiveSurveysAsync(null, language); + // if (result.IsSuccess) + // { + // return Ok(result.Surveys); + // } + // return NoContent(); + //} + + /// + /// Get all historical surveys . + /// [Route("responses/surveys/historic")] [Route("responses/surveys/historic/{language:alpha}")] [Route("responses/surveys/historic/{employeeid:int}")] diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/DamageAssesment.Api.Responses.csproj b/DamageAssesmentApi/DamageAssesment.Api.Responses/DamageAssesment.Api.Responses.csproj index c704179..c9d3645 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/DamageAssesment.Api.Responses.csproj +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/DamageAssesment.Api.Responses.csproj @@ -11,6 +11,8 @@ + + all diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IExcelExportService.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IExcelExportService.cs new file mode 100644 index 0000000..31b832f --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IExcelExportService.cs @@ -0,0 +1,7 @@ +namespace DamageAssesment.Api.Responses.Interfaces +{ + public interface IExcelExportService + { + public byte[] ExportToExcel(List responses); + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs index 5c54e57..bbcec8b 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/IQuestionServiceProvider.cs @@ -4,8 +4,9 @@ namespace DamageAssesment.Api.Responses.Interfaces { public interface IQuestionServiceProvider { - Task> getQuestionsAsync(); + Task> getQuestionsAsync(string language); Task> getSurveyQuestionsAsync(int surveyId); Task getQuestionsAsync(int questionId); + Task> GetQuestionCategoriesAsync(string? language); } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs index 19893c8..ae5d380 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs @@ -7,8 +7,9 @@ namespace DamageAssesment.Api.Responses.Interfaces { Task<(bool IsSuccess, dynamic Answers, string ErrorMessage)> GetAnswersByRegionAsync(int surveyId, int employeeid); Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyResponseAsync(Models.SurveyResponse surveyResponse); - // Task<(bool IsSuccess,dynamic surveyResponses, string ErrorMessage)> GetSurveyResponseAsync(int responseId); + // Task<(bool IsSuccess,dynamic surveyResponses, string ErrorMessage)> GetSurveyResponseAsync(int responseId); Task<(bool IsSuccess, dynamic surveyResponses, string ErrorMessage)> GetSurveyResponsesAsync(int employeeid); + Task<(bool IsSuccess, List surveyResponses, string ErrorMessage)> ExportSurveyResponsesAsync(string language,bool IsAdmin); Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int? employeeid, string language); Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int? employeeid, string language); Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PutSurveyResponseAsync(int Id, Models.SurveyResponse surveyResponse); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Attachment.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Attachment.cs index 6194789..71a87d3 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Attachment.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Attachment.cs @@ -11,6 +11,7 @@ namespace DamageAssesment.Api.Responses.Models public int? AnswerId { get; set; } public bool IsDeleted { get; set; } + public string FileName { get; set; } public Attachment(int answerId, string uri) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Location.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Location.cs index d5996d2..e217a7b 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Location.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Location.cs @@ -4,6 +4,7 @@ { public int Id { get; set; } public int RegionId { get; set; } + public string LocationCode { get; set; } public string Name { get; set; } public string MaintenanceCenter { get; set; } public string SchoolType { get; set; } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/QuestionCategory.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/QuestionCategory.cs new file mode 100644 index 0000000..c7c9379 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/QuestionCategory.cs @@ -0,0 +1,10 @@ +namespace DamageAssesment.Api.Responses.Models +{ + public class QuestionCategory + { + public int Id { get; set; } + public string IconName { get; set; } + public string IconLibrary { get; set; } + public object Titles { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/SurveyExport.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/SurveyExport.cs new file mode 100644 index 0000000..be527f7 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/SurveyExport.cs @@ -0,0 +1,24 @@ +namespace DamageAssesment.Api.Responses.Models +{ + public class SurveyExport + { + public int Id { get; set; } + public string SurveyQuestion { get; set; } + public string Answer { get; set; } + public string Category { get; set; } + + public string School { get; set; } + public string Location { get; set; } + public string Region { get; set; } + + public string MC { get; set; } + public string ResponseDate { get; set; } + public string Notes { get; set; } + + public string Attachment1 { get; set; } + public string Attachment2 { get; set; } + public string Attachment3 { get; set; } + public string Attachment4 { get; set; } + public string Attachment5 { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs index 1641e75..8b25674 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Program.cs @@ -26,6 +26,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddHttpClient(). AddTransientHttpErrorPolicy(policy => policy.WaitAndRetryAsync(maxApiCallRetries, _ => TimeSpan.FromSeconds(intervalToRetry))). diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs new file mode 100644 index 0000000..b354b8d --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs @@ -0,0 +1,57 @@ +using ClosedXML.Excel; +using DamageAssesment.Api.Responses.Interfaces; +using DamageAssesment.Api.Responses.Models; +using OfficeOpenXml; +using System.Collections.Generic; + +namespace DamageAssesment.Api.Responses.Providers +{ + public class ExcelExportService: IExcelExportService + { + public byte[] ExportToExcel(List responses) + { + ExcelPackage.LicenseContext = LicenseContext.NonCommercial; + using (var package = new ExcelPackage()) + { + // Create the first worksheet and populate it with responses + var workSheet1 = package.Workbook.Worksheets.Add("responses"); + PopulateWorksheet(workSheet1, responses); + return package.GetAsByteArray(); + } + } + private void PopulateWorksheet(ExcelWorksheet worksheet, List data) + { + if (data.Count > 0) + { + var properties = data[0].GetType().GetProperties(); + List IsAttchments = new List(); + // Add column headers + for (int col = 1; col <= properties.Length; col++) + { + worksheet.Cells[1, col].Value = properties[col - 1].Name; + if(properties[col - 1].Name.ToLower().Contains("attachment")) + IsAttchments.Add(col); + } + + // Add data + for (int row = 2; row <= data.Count + 1; row++) + { + for (int col = 1; col <= properties.Length; col++) + { + string value = Convert.ToString(properties[col - 1].GetValue(data[row - 2])); + if (IsAttchments.Where(a => a == col).Count()>0&& !string.IsNullOrEmpty(value)) + { + List attachments = value.Split("##").ToList(); + Uri linkUri = new Uri(attachments[1]); + worksheet.Cells[row, col].Hyperlink = linkUri; + worksheet.Cells[row, col].Value = attachments[0]; + worksheet.Cells[row, col].Style.Font.UnderLine = true; + } + else + worksheet.Cells[row, col].Value = value; + } + } + } + } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs index 0c6c817..d007578 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs @@ -3,6 +3,9 @@ using DamageAssesment.Api.Responses.Db; using DamageAssesment.Api.Responses.Interfaces; using DamageAssesment.Api.Responses.Models; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Internal; +using System.Reflection; +using System.Text.Json; namespace DamageAssesment.Api.Responses.Providers { @@ -43,7 +46,6 @@ namespace DamageAssesment.Api.Responses.Providers // Create and save SurveyResponse records with references to existing Employee and Location records surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { SurveyId = 1, EmployeeId = 1, LocationId = 1, ClientDevice = "Mobile", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "true", CreatedDate = DateTime.Now }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { SurveyId = 1, EmployeeId = 2, LocationId = 2, ClientDevice = "Mobile", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "true", CreatedDate = DateTime.Now }); - surveyResponseDbContext.SaveChanges(); } } @@ -307,6 +309,26 @@ namespace DamageAssesment.Api.Responses.Providers return (false, null, ex.Message); } } + public async Task<(bool IsSuccess, List surveyResponses, string ErrorMessage)> ExportSurveyResponsesAsync(string language,bool isadmin) + { + try + { + var responses = await getAllSurveyResponsesExcelAsync(language, isadmin); + + if (responses != null) + return (true, responses, "Request Successful."); + else + { + responses = null; + return (true, responses, "Empty object returned"); + } + } + catch (Exception ex) + { + logger?.LogError(ex.ToString()); + return (false, null, ex.Message); + } + } public async Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyResponseAsync(Models.SurveyResponse surveyResponse) { @@ -487,7 +509,7 @@ namespace DamageAssesment.Api.Responses.Providers { var employee = await employeeServiceProvider.getEmployeeAsync(surveyResponse.EmployeeId); var answers = await answerServiceProvider.GetAnswersByResponseIdAsync(surveyResponse.Id); - var allQuestions = await questionServiceProvider.getQuestionsAsync(); + var allQuestions = await questionServiceProvider.getQuestionsAsync(null); var questions = allQuestions.Where(s => s.SurveyId == surveyResponse.SurveyId); var attachments = await attachmentServiceProvider.getAttachmentsAsync(); @@ -543,7 +565,7 @@ namespace DamageAssesment.Api.Responses.Providers } var answers = await answerServiceProvider.getAnswersAsync(); - var questions = await questionServiceProvider.getQuestionsAsync(); + var questions = await questionServiceProvider.getQuestionsAsync(null); var surveyQuestions = from q in questions where q.SurveyId == surveyId select q; //var surveyQuestions = await questionServiceProvider.getSurveyQuestionsAsync(surveyId); @@ -649,7 +671,7 @@ namespace DamageAssesment.Api.Responses.Providers var answers = await answerServiceProvider.getAnswersAsync(); - var questions = await questionServiceProvider.getQuestionsAsync(); + var questions = await questionServiceProvider.getQuestionsAsync(null); var attachments = await attachmentServiceProvider.getAttachmentsAsync(); var result = from r in surveyResonses @@ -686,7 +708,136 @@ namespace DamageAssesment.Api.Responses.Providers return null; } } + //Method to get All Survey Responses for excel export + private async Task> getAllSurveyResponsesExcelAsync(string language,bool isadmin) + { + try + { + if (string.IsNullOrEmpty(language)) language = "en"; + List surveyResonses; + surveyResonses = await surveyResponseDbContext.SurveyResponses.ToListAsync(); + var answers = await answerServiceProvider.getAnswersAsync(); + var Locations = await locationServiceProvider.getLocationsAsync(); + var regions = await regionServiceProvider.getRegionsAsync(); + var questions = await questionServiceProvider.getQuestionsAsync(language); + var categories = await questionServiceProvider.GetQuestionCategoriesAsync(language); + var attachments = await attachmentServiceProvider.getAttachmentsAsync(); + List questionLists = new List(); + var allques = from res in surveyResonses + join loc in Locations on res.LocationId equals loc.Id + join reg in regions on loc.RegionId equals reg.Id + join ans in answers on res.Id equals ans.SurveyResponseId + join q in questions on ans.QuestionId equals q.Id + join qc in categories on q.CategoryId equals qc.Id + select new + { + responseId = res.Id, + questionId = q.Id, + QuestionNumber = q.QuestionNumber, + Category = JsonSerializer.Deserialize>(qc.Titles.ToString())[language], + question = q.Text[language], + answerId = ans.Id, + AnswerText = ans.AnswerText, + Comment = ans.Comment, + Location=loc.LocationCode, + school=loc.Name, + Region=reg.Name, + MC=loc.MaintenanceCenter, + ResponseDate=res.CreatedDate, + EmployeeId=res.EmployeeId, + ClientDevice=res.ClientDevice, + Attachments = attachments.Where(a=>a.AnswerId==ans.Id).Select(a=>a.FileName+"##"+a.URI).ToList() + }; + List allresoponses = new List(); + foreach (var item in allques) + { + + List ansattachments=item.Attachments.ToList(); + //// Initialize the attachment dictionary + //var attachmentsobject = new Dictionary(); + //for (int i = 0; i < ansattachments.Count; i++) + //{ + // attachmentsobject["Attachment"+(i+1).ToString()] = ansattachments[i]; + //} + + + string[] variables = new string[5]; + for (int i = 0; i < 5; i++) // Assuming you want to assign 5 values + { + if (i < ansattachments.Count()) + { + variables[i] = ansattachments[i]; + } + else + { + variables[i] = string.Empty; // or null, or any other default value + } + } + + // Now, you can access the values using the variables + string att1 = variables[0],att2 = variables[1],att3 = variables[2],att4 = variables[3],att5 = variables[4]; + object response; + if (isadmin) + { + response = new + { + SurveyQuestion = item.question, + Answer = item.AnswerText, + Category = item.Category, + School = item.school, + Location = item.Location, + Region = item.Region, + MC = item.MC, + ResponseDate = item.ResponseDate.ToString(), + Notes = item.Comment, + Attachment1 = att1, + Attachment2 = att2, + Attachment3 = att3, + Attachment4 = att4, + Attachment5 = att5, + User = item.EmployeeId, + DeviceType = item.ClientDevice, + Reference = item.responseId + }; + // Add the attachment dictionary to the response object + // response = new { response, Attachments = attachments }; + } + else + { + response = new + { + SurveyQuestion = item.question, + Answer = item.AnswerText, + Category = item.Category, + School = item.school, + Location=item.Location, + Region = item.Region, + MC = item.MC, + ResponseDate = item.ResponseDate.ToString(), + Notes = item.Comment, + Attachment1 = att1, + Attachment2 = att2, + Attachment3 = att3, + Attachment4 = att4, + Attachment5 = att5 + }; + + // Add the attachment dictionary to the response object + // response = new { response, Attachments = attachments }; + } + allresoponses.Add(response); + } + return allresoponses; + + + } + catch (Exception ex) + { + logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResponseBySurveyIdAsync()"); + return null; + } + } //Method to get Answers By Maintenance Center by surveyId private async Task getResultsByMaintenanceCenterAsync(int surveyId, int employeeid) @@ -783,7 +934,7 @@ namespace DamageAssesment.Api.Responses.Providers } var answers = await answerServiceProvider.getAnswersAsync(); - var questions = await questionServiceProvider.getQuestionsAsync(); + var questions = await questionServiceProvider.getQuestionsAsync(null); var surveyQuestions = from q in questions where q.SurveyId == surveyId select q; var attachments = await attachmentServiceProvider.getAttachmentsAsync(); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs index 95086b8..bac4fbc 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Services/QuestionServiceProvider.cs @@ -10,10 +10,12 @@ namespace DamageAssesment.Api.Responses.Services { } - public async Task> getQuestionsAsync() + public async Task> getQuestionsAsync(string language) { try { + if (!string.IsNullOrEmpty(language)) + url = url + "/" + language; var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); var questions = JsonConvert.DeserializeObject>(responseJsonString); @@ -27,7 +29,28 @@ namespace DamageAssesment.Api.Responses.Services return new List(); } } + public async Task> GetQuestionCategoriesAsync(string? language) + { + try + { + url = urlBase + configuration.GetValue("RessourceSettings:QuestionCategory"); + + if (!string.IsNullOrEmpty(language)) + url = url + "/" + language; + var responseJsonString = await httpUtil.SendAsync(HttpMethod.Get, url, null); + var questions = JsonConvert.DeserializeObject>(responseJsonString); + if (questions == null || !questions.Any()) + return new List(); + else return questions; + } + catch (Exception ex) + { + logger?.LogError($"Exception Found : {ex.Message} - Ref: QuestionServiceProvider.GetQuestionCategoriesAsync()"); + return new List(); + } + } + public async Task> getSurveyQuestionsAsync(int surveyId) { try @@ -37,7 +60,7 @@ namespace DamageAssesment.Api.Responses.Services var questions = JsonConvert.DeserializeObject>(responseJsonString); if (questions == null || !questions.Any()) - return new List() ; + return new List(); else return questions; } catch (Exception ex) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json index 8829c0b..e156d59 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/appsettings.json @@ -31,6 +31,7 @@ "EmployeeById": "/employees/{0}", "Question": "/questions", "QuestionById": "/questions/{0}", + "QuestionCategory": "/questions/categories", "SurveyQuestion": "/questions/bysurvey/{0}", "Survey": "/surveys", "SurveyById": "/surveys/{0}", @@ -42,7 +43,7 @@ }, "ConnectionStrings": { //"SurveyResponseConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" - // "ResponsesConnection": "Server=localhost,1433;Database=da_survey_dev;User Id=sa;Password=Password123;TrustServerCertificate=True;", + //"ResponsesConnection": "Server=DESKTOP-OF5DPLQ\\SQLEXPRESS;Database=da_survey_dev;Trusted_Connection=True;TrustServerCertificate=True;" "ResponsesConnection": "Server=207.180.248.35;Database=da_survey_dev;User Id=sa;Password=YourStrongPassw0rd;TrustServerCertificate=True;" } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs index b639131..a6a111f 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs @@ -217,12 +217,10 @@ namespace DamageAssesment.Api.Surveys.Providers _survey = mapper.Map(survey); surveyDbContext.Surveys.Update(_survey); await surveyDbContext.SaveChangesAsync(); - List listSurveyTranslation = new List(); - Random random = new Random(); foreach (var title in survey.Titles) { - listSurveyTranslation.Add(new Db.SurveyTranslation { Id = random.Next(), SurveyId = _survey.Id, Language = title.Language, Title = title.Title }); + listSurveyTranslation.Add(new Db.SurveyTranslation { SurveyId = _survey.Id, Language = title.Language, Title = title.Title }); } surveyDbContext.SurveysTranslation.AddRange(listSurveyTranslation); await surveyDbContext.SaveChangesAsync(); From 8285588db9f5acb574a4a4bc041d3ad5cbf1d228 Mon Sep 17 00:00:00 2001 From: uppuv Date: Wed, 1 Nov 2023 14:29:47 -0400 Subject: [PATCH 37/40] fixed survey issue in response level, and added logic for start and end date as optional date. --- .../Controllers/SurveyResponsesController.cs | 12 +-- .../Interfaces/ISurveysResponse.cs | 2 +- .../Models/Survey.cs | 11 ++- .../Providers/ExcelExportService.cs | 17 +++-- .../Providers/SurveyResponsesProvider.cs | 76 +++++++++---------- .../DamageAssesment.Api.Surveys/Db/Survey.cs | 4 +- .../Models/Survey.cs | 6 +- .../Providers/SurveysProvider.cs | 22 ++++-- 8 files changed, 85 insertions(+), 65 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs index 9fce5f8..871106c 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Controllers/SurveyResponsesController.cs @@ -218,16 +218,16 @@ namespace DamageAssesment.Api.Responses.Controllers return NoContent(); } /// - /// Export surveys based on role . + /// Export all survey response data based on survey id. /// [HttpGet] - - [Route("responses/surveys/export")] - public async Task GetExcelSurveysAsync(string language,bool IsAdmin=false) + [Route("responses/surveys/export/{surveyid}")] + public async Task GetExcelSurveysAsync(int surveyid, string language, bool IsAdmin = false) { - var result = await this.surveyResponseProvider.ExportSurveyResponsesAsync(language, IsAdmin); - if (result.IsSuccess) + var result = await this.surveyResponseProvider.ExportSurveyResponsesAsync(surveyid, language, IsAdmin); + if (result.IsSuccess && result.surveyResponses.Count > 0) { + byte[] fileContents = excelExportService.ExportToExcel(result.surveyResponses); return File(fileContents, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "data.xlsx"); //return Ok(result.Surveys); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs index ae5d380..05a8eed 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Interfaces/ISurveysResponse.cs @@ -9,7 +9,7 @@ namespace DamageAssesment.Api.Responses.Interfaces Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyResponseAsync(Models.SurveyResponse surveyResponse); // Task<(bool IsSuccess,dynamic surveyResponses, string ErrorMessage)> GetSurveyResponseAsync(int responseId); Task<(bool IsSuccess, dynamic surveyResponses, string ErrorMessage)> GetSurveyResponsesAsync(int employeeid); - Task<(bool IsSuccess, List surveyResponses, string ErrorMessage)> ExportSurveyResponsesAsync(string language,bool IsAdmin); + Task<(bool IsSuccess, List surveyResponses, string ErrorMessage)> ExportSurveyResponsesAsync(int surveyId, string language, bool IsAdmin); Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetActiveSurveysAsync(int? employeeid, string language); Task<(bool IsSuccess, dynamic Surveys, string ErrorMessage)> GetHistoricSurveysAsync(int? employeeid, string language); Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PutSurveyResponseAsync(int Id, Models.SurveyResponse surveyResponse); diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Survey.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Survey.cs index 8265046..5419251 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Survey.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Models/Survey.cs @@ -2,13 +2,20 @@ namespace DamageAssesment.Api.Responses.Models { + public enum SurveyStatus + { + PENDING, + ACTIVE, + INACTIVE + } public class Survey { public int Id { get; set; } public bool IsEnabled { get; set; } - public DateTime StartDate { get; set; } - public DateTime EndDate { get; set; } + public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } public DateTime CreatedDate { get; set; } + public string Status { get; set; } public Dictionary Titles { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs index b354b8d..2fadd9d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/ExcelExportService.cs @@ -38,17 +38,22 @@ namespace DamageAssesment.Api.Responses.Providers { for (int col = 1; col <= properties.Length; col++) { - string value = Convert.ToString(properties[col - 1].GetValue(data[row - 2])); - if (IsAttchments.Where(a => a == col).Count()>0&& !string.IsNullOrEmpty(value)) + + string value = Convert.ToString(properties[col - 1].GetValue(data[row - 2])); + if (IsAttchments.Where(a => a == col).Count() > 0 && !string.IsNullOrEmpty(value)) { List attachments = value.Split("##").ToList(); - Uri linkUri = new Uri(attachments[1]); - worksheet.Cells[row, col].Hyperlink = linkUri; - worksheet.Cells[row, col].Value = attachments[0]; - worksheet.Cells[row, col].Style.Font.UnderLine = true; + try + { + Uri linkUri = new Uri(attachments[1]); + worksheet.Cells[row, col].Value = attachments[0]; + worksheet.Cells[row, col].Style.Font.UnderLine = true; + } + catch { worksheet.Cells[row, col].Value = attachments[1]; } } else worksheet.Cells[row, col].Value = value; + } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs index d007578..d52d153 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Responses/Providers/SurveyResponsesProvider.cs @@ -121,7 +121,7 @@ namespace DamageAssesment.Api.Responses.Providers logger?.LogInformation("Querying to get SurveyResponse object from DB"); //get all the survey that already taken by the employee var surveys = await surveyServiceProvider.getSurveysAsync(language); - surveys = surveys.Where(s => s.IsEnabled == true && s.StartDate <= DateTime.Now && s.EndDate >= DateTime.Now).ToList(); + surveys = surveys.Where(s => s.IsEnabled == true && s.Status == SurveyStatus.ACTIVE.ToString()).ToList(); if (employeeid == null || employeeid == 0) return (true, surveys, null); List listOfsurveysId = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid.Value).Select(y => y.SurveyId).ToListAsync(); @@ -143,7 +143,7 @@ namespace DamageAssesment.Api.Responses.Providers var surveys = await surveyServiceProvider.getSurveysAsync(language); // returning only historic data: end date is less than current date. - surveys = surveys.Where(s => s.EndDate < DateTime.Now).ToList(); + surveys = surveys.Where(s => s.Status == SurveyStatus.INACTIVE.ToString()).ToList(); if (employeeid == null || employeeid == 0) return (true, surveys, null); var surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.EmployeeId == employeeid).ToListAsync(); @@ -309,11 +309,11 @@ namespace DamageAssesment.Api.Responses.Providers return (false, null, ex.Message); } } - public async Task<(bool IsSuccess, List surveyResponses, string ErrorMessage)> ExportSurveyResponsesAsync(string language,bool isadmin) + public async Task<(bool IsSuccess, List surveyResponses, string ErrorMessage)> ExportSurveyResponsesAsync(int surveyId, string language, bool isadmin) { try { - var responses = await getAllSurveyResponsesExcelAsync(language, isadmin); + var responses = await getAllSurveyResponsesExcelAsync(surveyId, language, isadmin); if (responses != null) return (true, responses, "Request Successful."); @@ -709,13 +709,13 @@ namespace DamageAssesment.Api.Responses.Providers } } //Method to get All Survey Responses for excel export - private async Task> getAllSurveyResponsesExcelAsync(string language,bool isadmin) + private async Task> getAllSurveyResponsesExcelAsync(int surveyId, string language, bool isadmin) { try { if (string.IsNullOrEmpty(language)) language = "en"; List surveyResonses; - surveyResonses = await surveyResponseDbContext.SurveyResponses.ToListAsync(); + surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(a => a.SurveyId == surveyId).ToListAsync(); var answers = await answerServiceProvider.getAnswersAsync(); var Locations = await locationServiceProvider.getLocationsAsync(); var regions = await regionServiceProvider.getRegionsAsync(); @@ -726,33 +726,33 @@ namespace DamageAssesment.Api.Responses.Providers var allques = from res in surveyResonses join loc in Locations on res.LocationId equals loc.Id join reg in regions on loc.RegionId equals reg.Id - join ans in answers on res.Id equals ans.SurveyResponseId + join ans in answers on res.Id equals ans.SurveyResponseId join q in questions on ans.QuestionId equals q.Id join qc in categories on q.CategoryId equals qc.Id - select new - { - responseId = res.Id, - questionId = q.Id, - QuestionNumber = q.QuestionNumber, - Category = JsonSerializer.Deserialize>(qc.Titles.ToString())[language], - question = q.Text[language], - answerId = ans.Id, - AnswerText = ans.AnswerText, - Comment = ans.Comment, - Location=loc.LocationCode, - school=loc.Name, - Region=reg.Name, - MC=loc.MaintenanceCenter, - ResponseDate=res.CreatedDate, - EmployeeId=res.EmployeeId, - ClientDevice=res.ClientDevice, - Attachments = attachments.Where(a=>a.AnswerId==ans.Id).Select(a=>a.FileName+"##"+a.URI).ToList() - }; + select new + { + responseId = res.Id, + questionId = q.Id, + QuestionNumber = q.QuestionNumber, + Category = JsonSerializer.Deserialize>(qc.Titles.ToString())[language], + question = q.Text[language], + answerId = ans.Id, + AnswerText = ans.AnswerText, + Comment = ans.Comment, + Location = loc.LocationCode, + school = loc.Name, + Region = reg.Name, + MC = loc.MaintenanceCenter, + ResponseDate = res.CreatedDate, + EmployeeId = res.EmployeeId, + ClientDevice = res.ClientDevice, + Attachments = attachments.Where(a => a.AnswerId == ans.Id).Select(a => a.FileName + "##" + a.URI).ToList() + }; List allresoponses = new List(); foreach (var item in allques) { - - List ansattachments=item.Attachments.ToList(); + + List ansattachments = item.Attachments.ToList(); //// Initialize the attachment dictionary //var attachmentsobject = new Dictionary(); @@ -776,11 +776,11 @@ namespace DamageAssesment.Api.Responses.Providers } // Now, you can access the values using the variables - string att1 = variables[0],att2 = variables[1],att3 = variables[2],att4 = variables[3],att5 = variables[4]; + string att1 = variables[0], att2 = variables[1], att3 = variables[2], att4 = variables[3], att5 = variables[4]; object response; if (isadmin) { - response = new + response = new { SurveyQuestion = item.question, Answer = item.AnswerText, @@ -791,12 +791,12 @@ namespace DamageAssesment.Api.Responses.Providers MC = item.MC, ResponseDate = item.ResponseDate.ToString(), Notes = item.Comment, - Attachment1 = att1, - Attachment2 = att2, - Attachment3 = att3, - Attachment4 = att4, - Attachment5 = att5, - User = item.EmployeeId, + Attachment1 = att1, + Attachment2 = att2, + Attachment3 = att3, + Attachment4 = att4, + Attachment5 = att5, + User = item.EmployeeId, DeviceType = item.ClientDevice, Reference = item.responseId }; @@ -811,7 +811,7 @@ namespace DamageAssesment.Api.Responses.Providers Answer = item.AnswerText, Category = item.Category, School = item.school, - Location=item.Location, + Location = item.Location, Region = item.Region, MC = item.MC, ResponseDate = item.ResponseDate.ToString(), @@ -824,7 +824,7 @@ namespace DamageAssesment.Api.Responses.Providers }; // Add the attachment dictionary to the response object - // response = new { response, Attachments = attachments }; + // response = new { response, Attachments = attachments }; } allresoponses.Add(response); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Db/Survey.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Db/Survey.cs index aa49acc..2f19281 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Db/Survey.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Db/Survey.cs @@ -13,9 +13,9 @@ namespace DamageAssesment.Api.Surveys.Db public bool IsEnabled { get; set; } - public DateTime StartDate { get; set; } + public DateTime? StartDate { get; set; } - public DateTime EndDate { get; set; } + public DateTime? EndDate { get; set; } public DateTime CreatedDate { get; set; } = DateTime.Now; /* diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs index 38fa72a..746047c 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Models/Survey.cs @@ -21,8 +21,8 @@ namespace DamageAssesment.Api.Surveys.Models { public int Id { get; set; } public bool IsEnabled { get; set; } - public DateTime StartDate { get; set; } - public DateTime EndDate { get; set; } - public DateTime CreatedDate { get; set; } + public DateTime? StartDate { get; set; } + public DateTime? EndDate { get; set; } + public DateTime? CreatedDate { get; set; } } } diff --git a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs index a6a111f..72b4aff 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Surveys/Providers/SurveysProvider.cs @@ -85,14 +85,21 @@ namespace DamageAssesment.Api.Surveys.Providers MultiLanguage = dict; return MultiLanguage; } - public string GetStatus(DateTime StartDate,DateTime EndDate) + public string GetStatus(DateTime? StartDate,DateTime? EndDate) { - if (StartDate > DateTime.Now) - return SurveyStatus.PENDING.ToString(); - else if (StartDate <= DateTime.Now && EndDate > DateTime.Now) - return SurveyStatus.ACTIVE.ToString(); - else + try + { + if (StartDate > DateTime.Now) + return SurveyStatus.PENDING.ToString(); + else if (StartDate <= DateTime.Now && EndDate > DateTime.Now) + return SurveyStatus.ACTIVE.ToString(); + else + return SurveyStatus.INACTIVE.ToString(); + } + catch + { return SurveyStatus.INACTIVE.ToString(); + } } // Method to get surveys asynchronously with multi-language support public async Task<(bool IsSuccess, IEnumerable Surveys, string ErrorMessage)> GetSurveysAsync(string language) @@ -136,7 +143,8 @@ namespace DamageAssesment.Api.Surveys.Providers try { logger?.LogInformation("Query Survey"); - var survey = await surveyDbContext.Surveys.SingleOrDefaultAsync(s => s.Id == id && s.IsEnabled == true); + // removed is enabled becuase we are using it in responses to get response + var survey = await surveyDbContext.Surveys.SingleOrDefaultAsync(s => s.Id == id); if (survey != null) { From 3b9e13ad35cf0b72b70f4eec69be046969aedb14 Mon Sep 17 00:00:00 2001 From: Vijay Uppu <913468@dadeschools.net> Date: Mon, 13 Nov 2023 15:41:53 -0500 Subject: [PATCH 38/40] added new endpoint to generate dade school token --- .../Controllers/UsersAccessController.cs | 10 +++++ .../Interfaces/IUsersAccessProvider.cs | 1 + .../Models/DadeSchoolToken.cs | 10 +++++ .../Providers/UserAccessProvider.cs | 37 +++++++++++++++++-- .../appsettings.json | 4 ++ 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/DadeSchoolToken.cs diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs index e0aae67..755b21e 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Controllers/UsersAccessController.cs @@ -14,6 +14,16 @@ namespace DamageAssesment.Api.UsersAccess.Controllers { this.userAccessProvider = userAccessProvider; } + [HttpPost("dadeschooltoken")] + public async Task DadeSchoolAuthenticateAsync(string username, string password) + { + var result = await userAccessProvider.DadeSchoolAuthenticateAsync(username, password); + if (result.IsSuccess) + { + return Ok(result.TokenResponse); + } + return Unauthorized(result.ErrorMessage); + } [Authorize(Policy = "Dadeschools")] [HttpPost("token/{employecode}")] public async Task AuthenticateAsync(string employecode) diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs index ea64376..6a70a5b 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Interfaces/IUsersAccessProvider.cs @@ -11,6 +11,7 @@ namespace DamageAssesment.Api.UsersAccess.Interfaces public Task<(bool IsSuccess, Models.User User, string ErrorMessage)> DeleteUserAsync(int Id); public Task<(bool IsSuccess, IEnumerable Roles, string ErrorMessage)> GetRolesAsync(); public Task<(bool IsSuccess, Models.TokenResponse TokenResponse, string ErrorMessage)> AuthenticateAsync(string employeCode); + public Task<(bool IsSuccess, Models.DadeSchoolToken TokenResponse, string ErrorMessage)> DadeSchoolAuthenticateAsync(string username, string password); public Task<(bool IsSuccess, Models.TokenResponse TokenResponse, string ErrorMessage)>RefreshTokenAsync(TokenResponse tokenResponse); public void seedData(); } diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/DadeSchoolToken.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/DadeSchoolToken.cs new file mode 100644 index 0000000..6b88ea5 --- /dev/null +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Models/DadeSchoolToken.cs @@ -0,0 +1,10 @@ +namespace DamageAssesment.Api.UsersAccess.Models +{ + public class DadeSchoolToken + { + public string access_token { get; set; } + public int expires_in { get; set; } + public string token_type { get; set; } + public string scope { get; set; } + } +} diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs index a599053..939ca4e 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/Providers/UserAccessProvider.cs @@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using System.Data; +using Newtonsoft.Json; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; @@ -19,9 +20,10 @@ namespace DamageAssesment.Api.UsersAccess.Providers private readonly IMapper mapper; //private readonly IEmployeeServiceProvider employeeServiceProvider; private readonly JwtSettings jwtSettings; - private readonly ITokenServiceProvider tokenServiceProvider; + private readonly ITokenServiceProvider tokenServiceProvider; + private readonly IConfiguration configuration; - public UsersAccessProvider(IOptions options, ITokenServiceProvider tokenServiceProvider, UsersAccessDbContext userAccessDbContext, IEmployeeServiceProvider employeeServiceProvider, ILogger logger, IMapper mapper) + public UsersAccessProvider(IConfiguration configuration,IOptions options, ITokenServiceProvider tokenServiceProvider, UsersAccessDbContext userAccessDbContext, IEmployeeServiceProvider employeeServiceProvider, ILogger logger, IMapper mapper) { this.userAccessDbContext = userAccessDbContext; //this.employeeServiceProvider = employeeServiceProvider; @@ -29,7 +31,8 @@ namespace DamageAssesment.Api.UsersAccess.Providers this.mapper = mapper; jwtSettings = options.Value; this.tokenServiceProvider = tokenServiceProvider; - // seedData(); + this.configuration = configuration; + // seedData(); } public void seedData() @@ -187,7 +190,35 @@ namespace DamageAssesment.Api.UsersAccess.Providers return (false, null, ex.Message); } } + public async Task<(bool IsSuccess, DadeSchoolToken TokenResponse, string ErrorMessage)> DadeSchoolAuthenticateAsync(string username, string password) + { + try + { + var client = new HttpClient(); + var request = new HttpRequestMessage(HttpMethod.Post, configuration.GetValue("Dadeschools:TokenUrl")); + var collection = new List>(); + collection.Add(new("client_id", configuration.GetValue("Dadeschools:TokenClientId"))); + collection.Add(new("client_secret", configuration.GetValue("Dadeschools:TokenClientSecret"))); + collection.Add(new("scope", configuration.GetValue("Dadeschools:scope"))); + collection.Add(new("grant_type", configuration.GetValue("Dadeschools:grant_type"))); + collection.Add(new("username", username)); + collection.Add(new("password", password)); + var content = new FormUrlEncodedContent(collection); + request.Content = content; + var response = await client.SendAsync(request); + var responseString = await response.Content.ReadAsStringAsync(); + if (response.IsSuccessStatusCode) + { + return (true, JsonConvert.DeserializeObject(responseString), ""); + } + return (false, null, responseString); + } + catch (Exception ex) + { + return (false, null, ex.Message); + } + } public async Task<(bool IsSuccess, TokenResponse TokenResponse, string ErrorMessage)> AuthenticateAsync(string employecode) { diff --git a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json index 150b8f3..e506d8d 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json +++ b/DamageAssesmentApi/DamageAssesment.Api.UsersAccess/appsettings.json @@ -21,6 +21,10 @@ "TokenUrl": "https://dev-graph.dadeschools.net/connect/token", "ClientId": "dmapi", "ClientSecret": "bfce2c8d-2064-4a02-b19d-7f1d42b16eae", + "TokenClientId": "damage_assessment_postman", + "TokenClientSecret": "e4774164-f018-44c9-b9d2-3a29fc21db3c", + "scope": "openid profile", + "grant_type": "password", "Name": "Dadeschools Identity Server" }, "Scopes": [ From 9b88029a09b424f82a2c8bd1d9094f09ffc465c6 Mon Sep 17 00:00:00 2001 From: Vijay Uppu <913468@dadeschools.net> Date: Tue, 14 Nov 2023 15:36:33 -0500 Subject: [PATCH 39/40] Added new endpoint for creating multiple questions --- .../Controllers/QuestionsController.cs | 21 +++++++++ .../Interfaces/IQuestionsProvider.cs | 1 + .../Providers/QuestionsProvider.cs | 43 ++++++++++++++----- .../MockData.cs | 16 ++++++- .../QuestionsServiceTest.cs | 28 +++++++++++- 5 files changed, 96 insertions(+), 13 deletions(-) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs index 1171b0d..14df48f 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Controllers/QuestionsController.cs @@ -90,6 +90,27 @@ namespace DamageAssesment.Api.Questions.Controllers return CreatedAtRoute("DefaultApi", new { id = question.Id }, question); } /// + /// POST request for creating a multiple question (multilingual). + /// + [Authorize(Roles = "admin")] + [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/Providers/QuestionsProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs index 0122af7..e864294 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,38 @@ 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); + 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..94eb466 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/MockData.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.QuestionsTest/MockData.cs @@ -75,8 +75,20 @@ 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..dff4dfa 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() @@ -329,6 +356,5 @@ namespace DamageAssesment.Api.Questions.Test Assert.Equal(404, result.StatusCode); } - } } \ No newline at end of file From cd982d160a2e24f7aac47b966a9af04eb48af577 Mon Sep 17 00:00:00 2001 From: Vijay Uppu <913468@dadeschools.net> Date: Wed, 15 Nov 2023 12:36:13 -0500 Subject: [PATCH 40/40] fixed question translation issue --- .../DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs b/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs index e864294..de179ba 100644 --- a/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs +++ b/DamageAssesmentApi/DamageAssesment.Api.Questions/Providers/QuestionsProvider.cs @@ -349,6 +349,7 @@ namespace DamageAssesment.Api.Questions.Providers 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();