From 2ccec617a59a712428e67340dc46bebefb152aca Mon Sep 17 00:00:00 2001 From: ElenitaMLG Date: Sun, 7 Apr 2024 02:49:34 +0300 Subject: [PATCH] pushed api files pushed middlewares --- backend/API/API.csproj | 4 - backend/API/Controllers/BaseController.cs | 11 +- backend/API/Controllers/ChatController.cs | 18 ++- backend/API/Controllers/DoctorsController.cs | 114 ++++++++++++++---- .../Controllers/MedicalHistoryController.cs | 66 +++++++++- backend/API/Controllers/PacientsController.cs | 114 +++++++++++++++++- .../Middlewares/ApiKeyValidationMiddleware.cs | 42 +++++++ .../API/Middlewares/BodyCheckMiddleware.cs | 35 ++++++ backend/API/Program.cs | 33 ++++- backend/API/appsettings.json | 3 +- backend/Application/Application.csproj | 4 + 11 files changed, 390 insertions(+), 54 deletions(-) create mode 100644 backend/API/Middlewares/ApiKeyValidationMiddleware.cs create mode 100644 backend/API/Middlewares/BodyCheckMiddleware.cs diff --git a/backend/API/API.csproj b/backend/API/API.csproj index 5c6b3b0..59e8b4c 100644 --- a/backend/API/API.csproj +++ b/backend/API/API.csproj @@ -10,10 +10,6 @@ - - - - diff --git a/backend/API/Controllers/BaseController.cs b/backend/API/Controllers/BaseController.cs index 32d2a7c..2587bc2 100644 --- a/backend/API/Controllers/BaseController.cs +++ b/backend/API/Controllers/BaseController.cs @@ -1,10 +1,9 @@ using Microsoft.AspNetCore.Mvc; -namespace HealthcareManager.API.Controllers +namespace HealthcareManager.API.Controllers; + +[Route("api/v1/[controller]")] +[ApiController] +public abstract class BaseApiController : ControllerBase { - [Route("api/v1/[controller]")] - [ApiController] - public abstract class BaseApiController : ControllerBase - { - } } \ No newline at end of file diff --git a/backend/API/Controllers/ChatController.cs b/backend/API/Controllers/ChatController.cs index fcf543e..f9d3256 100644 --- a/backend/API/Controllers/ChatController.cs +++ b/backend/API/Controllers/ChatController.cs @@ -1,16 +1,14 @@ using Infrastructure.Services.MongoDB; -using Microsoft.AspNetCore.Mvc; -namespace HealthcareManager.API.Controllers +namespace HealthcareManager.API.Controllers; + +public class ChatController : BaseApiController { - public class ChatController : BaseApiController + private readonly MongoDbService _mongoDbService; + + public ChatController(MongoDbService mongoDbService) { - private readonly MongoDbService _mongoDbService; - - public ChatController(MongoDbService mongoDbService) - { - _mongoDbService = mongoDbService; - } - + _mongoDbService = mongoDbService; } + } diff --git a/backend/API/Controllers/DoctorsController.cs b/backend/API/Controllers/DoctorsController.cs index 9d3d60a..62a3874 100644 --- a/backend/API/Controllers/DoctorsController.cs +++ b/backend/API/Controllers/DoctorsController.cs @@ -2,50 +2,116 @@ using Core.Entities; using Application.Endpoints.Doctors.Login; using Application.Services.Database; +using Application.Endpoints.Doctors.Registration; +using Application.Endpoints.Doctors.ResetPassword; +using Application.Endpoints.Doctors.Profile; -namespace HealthcareManager.API.Controllers +namespace HealthcareManager.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class DoctorsController : ControllerBase { - [ApiController] - [Route("api/[controller]")] - public class DoctorsController : ControllerBase + private readonly IDoctorRepository _database; + + public DoctorsController(IDoctorRepository database) { - private readonly IDoctorRepository _database; + _database = database ?? throw new ArgumentNullException(nameof(database)); + } - public DoctorsController(IDoctorRepository database) + [HttpGet] + public async Task> GetAllDoctors() + { + var handler = new DoctorProfileHandler(_database); + var response = await handler.HandleGetAll(); + if (!response.Success) { - _database = database ?? throw new ArgumentNullException(nameof(database)); + return BadRequest(response); } - [HttpGet("{id}")] - public async Task> GetDoctor(int id) + return Ok(response.Data); + } + + [HttpGet("{id}")] + public async Task> GetDoctor(Guid id) + { + var handler = new DoctorProfileHandler(_database); + var response = await handler.HandleGet(id); + if (!response.Success) { - return NotFound(); + return BadRequest(response); } - [HttpPost] - public async Task> Login(DoctorLoginDTO doctor) + return Ok(response.Data); + } + + [HttpPost("login")] + public async Task> Login(DoctorLoginDTO doctor) + { + var handler = new DoctorLoginHandler(_database); + var response = await handler.Handle(doctor).ConfigureAwait(false); + + if(!response.Success) { - var handler = new DoctorLoginHandler(_database); - var response = handler.Handle(doctor).Result; + return Unauthorized(response); + } - if(!response.Success) - { - return Unauthorized(response); - } + return Ok(response); + } + [HttpPost("register")] + public async Task> Register(DoctorRegistrationDto doctor) + { + var handler = new DoctorRegistrationHandler(_database); + var response = await handler.Handle(doctor).ConfigureAwait(false); + + if (!response.Success) + { + return Unauthorized(response); + } + + return Ok(response); + } + + [HttpPost("resetPassword")] + public async Task ResetPassword(DoctorLoginDTO resetDoctorDto) + { + var handler = new DoctorResetPasswordHandler(_database); + var response = await handler.Handle(resetDoctorDto).ConfigureAwait(false); + + if (response.Success) + { return Ok(response); } - [HttpPut("{id}")] - public async Task PutDoctor(int id, Doctor doctor) + return BadRequest(response); + } + + [HttpPut("{id}/profile")] + public async Task UpdateDoctorProfile(Guid id, [FromBody]DoctorProfileDTO doctorDto) + { + var handler = new DoctorProfileHandler(_database); + var response = await handler.HandleUpdate(id, doctorDto).ConfigureAwait(false); + + if (response.Success) { - return NotFound(); + return Ok(response); } - [HttpDelete("{id}")] - public async Task DeleteDoctor(int id) + return BadRequest(response); + } + + [HttpDelete("{id}/profile")] + public async Task DeleteDoctorProfile(Guid id) + { + var handler = new DoctorProfileHandler(_database); + var response = await handler.HandleDelete(id).ConfigureAwait(false); + + if (response.Success) { - return NotFound(); + return NoContent(); } + + return BadRequest(response); } } diff --git a/backend/API/Controllers/MedicalHistoryController.cs b/backend/API/Controllers/MedicalHistoryController.cs index cb5bc22..e124c24 100644 --- a/backend/API/Controllers/MedicalHistoryController.cs +++ b/backend/API/Controllers/MedicalHistoryController.cs @@ -1,9 +1,67 @@ -using Microsoft.AspNetCore.Mvc; +using Application.Endpoints.MedicalHistories; +using Application.Services.Database; +using Core.Entities; +using Microsoft.AspNetCore.Mvc; -namespace HealthcareManager.API.Controllers +namespace HealthcareManager.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class MedicalHistoryController : ControllerBase { - public class MedicalHistoryController : BaseApiController - { + private readonly IMedicalHistoryRepository _medicalHistoryRepository; + private readonly IPacientRepository _pacientRepository; + public MedicalHistoryController(IMedicalHistoryRepository medicalHistoryRepository, IPacientRepository pacientRepository) + { + _medicalHistoryRepository = medicalHistoryRepository ?? throw new ArgumentNullException(nameof(medicalHistoryRepository)); + _pacientRepository = pacientRepository ?? throw new ArgumentNullException(nameof(pacientRepository)); + } + + [HttpGet("{id}")] + public async Task> GetAsync(Guid id) + { + var handler = new MedicalHistoryHandler(_medicalHistoryRepository, _pacientRepository); + var response = await handler.HandleGet(id); + if (!response.Success) + { + return BadRequest(response); + } + + return Ok(response.Data); + } + + [HttpPost("{id}")] + public async Task> PostAsync(Guid id, [FromBody] byte[] description) + { + var handler = new MedicalHistoryHandler(_medicalHistoryRepository, _pacientRepository); + var response = await handler.HandleCreate(id, description).ConfigureAwait(false); + + if (!response.Success) + { + return Unauthorized(response); + } + + return Ok(response); + } + + [HttpPut("{id}")] + public async Task UpdateAsync(Guid id, [FromBody] MedicalHistoryDTO medicalHistoryDTO) + { + var handler = new MedicalHistoryHandler(_medicalHistoryRepository, _pacientRepository); + var response = await handler.HandleUpdate(id, medicalHistoryDTO).ConfigureAwait(false); + + if (response.Success) + { + return Ok(response); + } + + return BadRequest(response); + } + + [HttpPut("grant_access")] + public async Task GrantAccessToMedicalHistory(Guid id) + { + return NotFound(); } } diff --git a/backend/API/Controllers/PacientsController.cs b/backend/API/Controllers/PacientsController.cs index fb0113c..2ec98b4 100644 --- a/backend/API/Controllers/PacientsController.cs +++ b/backend/API/Controllers/PacientsController.cs @@ -1,9 +1,117 @@ using Microsoft.AspNetCore.Mvc; +using Core.Entities; +using Application.Endpoints.Pacients.Login; +using Application.Services.Database; +using Application.Endpoints.Pacients.Registration; +using Application.Endpoints.Pacients.ResetPassword; +using Application.Endpoints.Pacients.Profile; -namespace HealthcareManager.API.Controllers +namespace HealthcareManager.API.Controllers; + +[ApiController] +[Route("api/[controller]")] +public class PacientsController : ControllerBase { - public class PacientsController : BaseApiController + private readonly IPacientRepository _database; + + public PacientsController(IPacientRepository database) { - + _database = database ?? throw new ArgumentNullException(nameof(database)); + } + + [HttpGet] + public async Task> GetAllPacients() + { + var handler = new PacientProfileHandler(_database); + var response = await handler.HandleGetAll(); + if (!response.Success) + { + return BadRequest(response); + } + + return Ok(response.Data); + } + + [HttpGet("{id}")] + public async Task> GetPacient(Guid id) + { + var handler = new PacientProfileHandler(_database); + var response = await handler.HandleGet(id); + if (!response.Success) + { + return BadRequest(response); + } + + return Ok(response.Data); + } + + [HttpPost("login")] + public async Task> Login(PacientLoginDTO pacient) + { + var handler = new PacientLoginHandler(_database); + var response = await handler.Handle(pacient).ConfigureAwait(false); + + if (!response.Success) + { + return Unauthorized(response); + } + + return Ok(response); + } + + [HttpPost("register")] + public async Task> Register(PacientRegistrationDto pacient) + { + var handler = new PacientRegistrationHandler(_database); + var response = await handler.Handle(pacient).ConfigureAwait(false); + + if (!response.Success) + { + return Unauthorized(response); + } + + return Ok(response); + } + + [HttpPost("resetPassword")] + public async Task ResetPassword(PacientLoginDTO resetPacientDto) + { + var handler = new PacientResetPasswordHandler(_database); + var response = await handler.Handle(resetPacientDto).ConfigureAwait(false); + + if (response.Success) + { + return Ok(response); + } + + return BadRequest(response); + } + + [HttpPut("{id}/profile")] + public async Task UpdatePacientProfile(Guid id, [FromBody] PacientProfileDTO pacientDto) + { + var handler = new PacientProfileHandler(_database); + var response = await handler.HandleUpdate(id, pacientDto).ConfigureAwait(false); + + if (response.Success) + { + return Ok(response); + } + + return BadRequest(response); + } + + [HttpDelete("{id}/profile")] + public async Task DeletePacientProfile(Guid id) + { + var handler = new PacientProfileHandler(_database); + var response = await handler.HandleDelete(id).ConfigureAwait(false); + + if (response.Success) + { + return NoContent(); + } + + return BadRequest(response); } } diff --git a/backend/API/Middlewares/ApiKeyValidationMiddleware.cs b/backend/API/Middlewares/ApiKeyValidationMiddleware.cs new file mode 100644 index 0000000..142ea4c --- /dev/null +++ b/backend/API/Middlewares/ApiKeyValidationMiddleware.cs @@ -0,0 +1,42 @@ +namespace API.Middlewares; + +public class ApiKeyValidationMiddleware +{ + private readonly RequestDelegate _next; + private const string APIKEYNAME = "ApiKey"; + + public ApiKeyValidationMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + if (!context.Request.Headers.TryGetValue(APIKEYNAME, out var extractedApiKey)) + { + context.Response.StatusCode = 401; + await context.Response.WriteAsync("API Key was not provided."); + return; + } + + var appSettings = context.RequestServices.GetRequiredService(); + + var apiKey = appSettings.GetValue("ApiKey"); + + if (string.IsNullOrEmpty(apiKey)) + { + context.Response.StatusCode = 400; + await context.Response.WriteAsync("Unable to retrieve API key."); + return; + } + + if (!apiKey.Equals(extractedApiKey)) + { + context.Response.StatusCode = 401; + await context.Response.WriteAsync("Unauthorized client."); + return; + } + + await _next(context); + } +} diff --git a/backend/API/Middlewares/BodyCheckMiddleware.cs b/backend/API/Middlewares/BodyCheckMiddleware.cs new file mode 100644 index 0000000..557290d --- /dev/null +++ b/backend/API/Middlewares/BodyCheckMiddleware.cs @@ -0,0 +1,35 @@ +using System.Net; +using System.Text; + +namespace API.Middlewares; + +public class BodyCheckMiddleware(RequestDelegate next) +{ + private readonly RequestDelegate _next = next; + + public async Task InvokeAsync(HttpContext context) + { + // Only check the body for POST and PUT requests + if (context.Request.Method == HttpMethods.Post || context.Request.Method == HttpMethods.Put) + { + // Enable buffering so we can read the stream without issues downstream + context.Request.EnableBuffering(); + + var buffer = new byte[Convert.ToInt32(context.Request.ContentLength)]; + await context.Request.Body.ReadAsync(buffer, 0, buffer.Length); + string requestBody = Encoding.UTF8.GetString(buffer); + context.Request.Body.Seek(0, SeekOrigin.Begin); // Reset the stream for next middleware + + // Check if the body is empty + if (string.IsNullOrEmpty(requestBody)) + { + context.Response.StatusCode = (int)HttpStatusCode.BadRequest; + await context.Response.WriteAsync("Request body cannot be empty."); + return; + } + } + + await _next(context); + } +} + diff --git a/backend/API/Program.cs b/backend/API/Program.cs index 1177da2..db3649c 100644 --- a/backend/API/Program.cs +++ b/backend/API/Program.cs @@ -1,7 +1,8 @@ +using API.Middlewares; using Infrastructure; using Infrastructure.Data; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); @@ -9,7 +10,31 @@ builder.Services.AddControllers(); builder.Services.AddInfrastructureServices(builder.Configuration); builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(); +builder.Services.AddSwaggerGen(c => +{ + c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme + { + Description = "ApiKey must appear in header", + Type = SecuritySchemeType.ApiKey, + Name = "ApiKey", + In = ParameterLocation.Header, + Scheme = "ApiKeyScheme" + }); + var key = new OpenApiSecurityScheme() + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "ApiKey" + }, + In = ParameterLocation.Header + }; + var requirement = new OpenApiSecurityRequirement + { + { key, new List() } + }; + c.AddSecurityRequirement(requirement); +}); var app = builder.Build(); @@ -25,6 +50,10 @@ app.UseAuthorization(); app.MapControllers(); +// Middlewares +app.UseMiddleware(); +app.UseMiddleware(); + using (var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; diff --git a/backend/API/appsettings.json b/backend/API/appsettings.json index 292fe14..b3317b4 100644 --- a/backend/API/appsettings.json +++ b/backend/API/appsettings.json @@ -10,5 +10,6 @@ "MongoDBDatabase": "mongodb+srv://andrei_cerbu:andrei_cerbu@cluster0.v80skg6.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0" }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ApiKey": "testapikey" } diff --git a/backend/Application/Application.csproj b/backend/Application/Application.csproj index f31b960..31564e9 100644 --- a/backend/Application/Application.csproj +++ b/backend/Application/Application.csproj @@ -10,4 +10,8 @@ + + + +