From 5cf8cdcae887da56e2db67f45215c33a8737d969 Mon Sep 17 00:00:00 2001 From: Mouaz Abdelsamad <ma03081@surrey.ac.uk> Date: Sat, 6 Apr 2024 23:16:20 +0100 Subject: [PATCH] improvemenets --- Database/InitTables.sql | 5 ++- .../Controllers/FlightController.cs | 19 ++++++++- FlightMicroservice/FlightMicroservice.csproj | 2 +- .../Handler/ExceptionHandler.cs | 40 ++++++++++++++++++ FlightMicroservice/Models/Flight.cs | 5 ++- FlightMicroservice/Program.cs | 2 + FlightMicroservice/Services/FlightService.cs | 11 ++++- FlightMicroservice/Services/IFlightService.cs | 3 +- .../FlightService/FlightServiceClient.cs | 6 +++ .../FlightService/IFlightServiceClient.cs | 1 + GatewayAPI/Controllers/FlightController.cs | 8 ++++ UserMicroservice/Handlers/ExceptionHandler.cs | 41 +++++++++++++++++++ UserMicroservice/Program.cs | 2 + 13 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 FlightMicroservice/Handler/ExceptionHandler.cs create mode 100644 UserMicroservice/Handlers/ExceptionHandler.cs diff --git a/Database/InitTables.sql b/Database/InitTables.sql index 6805d23..dd06e9e 100644 --- a/Database/InitTables.sql +++ b/Database/InitTables.sql @@ -15,14 +15,15 @@ CREATE TABLE RefreshTokens ( CREATE TABLE Flights ( Id INT AUTO_INCREMENT PRIMARY KEY, + AirlineId INT NOT NULL, Origin LONGTEXT NOT NULL, Destination LONGTEXT NOT NULL, DepartureTime DATETIME(6) NOT NULL, ArrivalTime DATETIME(6) NOT NULL, EconomyCapacity INT NOT NULL, BusinessCapacity INT NOT NULL, - EconomyPrice DECIMAL(65, 30) NOT NULL, - BusinessPrice DECIMAL(65, 30) NOT NULL + EconomyPrice DECIMAL(19, 2) NOT NULL, + BusinessPrice DECIMAL(19, 2) NOT NULL ); CREATE TABLE Seats ( diff --git a/FlightMicroservice/Controllers/FlightController.cs b/FlightMicroservice/Controllers/FlightController.cs index 4e1dc43..ea3411b 100644 --- a/FlightMicroservice/Controllers/FlightController.cs +++ b/FlightMicroservice/Controllers/FlightController.cs @@ -2,6 +2,7 @@ using FlightMicroservice.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using System.Security.Claims; namespace FlightMicroservice.Controllers { @@ -40,8 +41,12 @@ namespace FlightMicroservice.Controllers [HttpPost()] public ActionResult AddFlight([FromBody] FlightCreationModel model) { + string? airlineIdValue = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; + if (!int.TryParse(airlineIdValue, out int airlineId)) + return BadRequest("Unable to get Airline Id from Token"); + Flight flight = flightService.CreateFlight( - model.Origin, model.Destination, model.DepartureTime, model.ArrivalTime, + airlineId, model.Origin, model.Destination, model.DepartureTime, model.ArrivalTime, model.EconomyCapacity, model.BusinessCapacity, model.EconomyPrice, model.BusinessPrice); if (flight == null) @@ -50,7 +55,6 @@ namespace FlightMicroservice.Controllers return Ok(flight); } - [Authorize] [HttpGet("{flightId}/capacity")] public ActionResult GetFlightCapacity([FromRoute] int flightId, [FromQuery] ClassType classType) { @@ -64,5 +68,16 @@ namespace FlightMicroservice.Controllers } + [HttpGet("{flightId}/seats")] + public IActionResult GetFlightSeats([FromRoute] int flightId) + { + List<Seat>? seats = flightService.GetSeatsByFlightId(flightId); + if (seats == null) + return NotFound($"Flight with Id {flightId} does not exist or could not be found."); + + return Ok(seats); + } + + } } diff --git a/FlightMicroservice/FlightMicroservice.csproj b/FlightMicroservice/FlightMicroservice.csproj index 8b66623..ba9f074 100644 --- a/FlightMicroservice/FlightMicroservice.csproj +++ b/FlightMicroservice/FlightMicroservice.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk.Web"> +<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> diff --git a/FlightMicroservice/Handler/ExceptionHandler.cs b/FlightMicroservice/Handler/ExceptionHandler.cs new file mode 100644 index 0000000..ef916a7 --- /dev/null +++ b/FlightMicroservice/Handler/ExceptionHandler.cs @@ -0,0 +1,40 @@ +using System.Net; +using System.Text.Json; + +namespace FlightMicroservice.Handler +{ + public class ExceptionHandler + { + private readonly RequestDelegate next; + + public ExceptionHandler(RequestDelegate next) + { + this.next = next; + } + + public async Task Invoke(HttpContext context) + { + try + { + await next(context); + } + catch (Exception ex) + { + if (!context.Response.HasStarted) + { + var response = context.Response; + response.ContentType = "application/json"; + response.StatusCode = (int)HttpStatusCode.InternalServerError; + + var result = JsonSerializer.Serialize(new + { + response.StatusCode, + ex.Message + }); + + await response.WriteAsync(result); + } + } + } + } +} diff --git a/FlightMicroservice/Models/Flight.cs b/FlightMicroservice/Models/Flight.cs index 257bdef..73a66ac 100644 --- a/FlightMicroservice/Models/Flight.cs +++ b/FlightMicroservice/Models/Flight.cs @@ -6,6 +6,7 @@ internal static readonly int ECONOMY_SEATS_PER_ROW = 6; public int Id { get; private set; } + public int AirlineId { get; internal set; } public string Origin { get; internal set; } public string Destination { get; internal set; } public DateTime DepartureTime { get; internal set; } @@ -18,7 +19,8 @@ public Flight() => Seats = new List<Seat>(); - public Flight(string origin, + public Flight(int airlineId, + string origin, string destination, DateTime departureTime, DateTime arrivalTime, @@ -34,6 +36,7 @@ if (!IsCapacityValid(businessCapacity, BUSINESS_SEATS_PER_ROW)) throw new ArgumentException($"Capacity of Business seats must be a multiple of {BUSINESS_SEATS_PER_ROW}"); + AirlineId = airlineId; Origin = origin; Destination = destination; DepartureTime = departureTime; diff --git a/FlightMicroservice/Program.cs b/FlightMicroservice/Program.cs index 82fabff..151b9c8 100644 --- a/FlightMicroservice/Program.cs +++ b/FlightMicroservice/Program.cs @@ -1,3 +1,4 @@ +using FlightMicroservice.Handler; using FlightMicroservice.Models; using FlightMicroservice.Services; using Microsoft.AspNetCore.Authentication.JwtBearer; @@ -47,6 +48,7 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } +app.UseMiddleware<ExceptionHandler>(); app.UseHttpsRedirection(); // Middleware for handling the access token in cookies diff --git a/FlightMicroservice/Services/FlightService.cs b/FlightMicroservice/Services/FlightService.cs index aa905a1..91e30b8 100644 --- a/FlightMicroservice/Services/FlightService.cs +++ b/FlightMicroservice/Services/FlightService.cs @@ -1,4 +1,5 @@ using FlightMicroservice.Models; +using Microsoft.EntityFrameworkCore; namespace FlightMicroservice.Services { @@ -37,6 +38,7 @@ namespace FlightMicroservice.Services } public Flight CreateFlight( + int airlineId, string origin, string destination, DateTime departureTime, @@ -46,7 +48,7 @@ namespace FlightMicroservice.Services decimal economyPrice, decimal businessPrice) { - Flight flight = new Flight(origin, destination, departureTime, arrivalTime, economyCapacity, businessCapacity, economyPrice, businessPrice); + Flight flight = new Flight(airlineId, origin, destination, departureTime, arrivalTime, economyCapacity, businessCapacity, economyPrice, businessPrice); InitializeSeatsForFlight(flight); @@ -68,6 +70,13 @@ namespace FlightMicroservice.Services return true; } + public List<Seat> GetSeatsByFlightId(int flightId) + { + return dbContext.Seats + .Where(seat => seat.FlightId == flightId) + .ToList(); + } + private void InitializeSeatsForFlight(Flight flight) { int businessRows = flight.BusinessCapacity / Flight.BUSINESS_SEATS_PER_ROW; diff --git a/FlightMicroservice/Services/IFlightService.cs b/FlightMicroservice/Services/IFlightService.cs index c9e9a03..f3bed26 100644 --- a/FlightMicroservice/Services/IFlightService.cs +++ b/FlightMicroservice/Services/IFlightService.cs @@ -6,7 +6,8 @@ namespace FlightMicroservice.Services { Flight? GetFlight(int flightId); List<Flight> GetFlights(string? origin, string? destination, DateTime? departureTime, DateTime? arrivalTime); - Flight CreateFlight(string origin, string destination, DateTime departureTime, DateTime arrivalTime, int economyCapacity, int businessCapacity, decimal economyPrice, decimal businessPrice); + Flight CreateFlight(int airlineId, string origin, string destination, DateTime departureTime, DateTime arrivalTime, int economyCapacity, int businessCapacity, decimal economyPrice, decimal businessPrice); bool RemoveFlight(int flightId); + List<Seat> GetSeatsByFlightId(int flightId); } } diff --git a/GatewayAPI/Clients/FlightService/FlightServiceClient.cs b/GatewayAPI/Clients/FlightService/FlightServiceClient.cs index cdf5f3a..82e4ca7 100644 --- a/GatewayAPI/Clients/FlightService/FlightServiceClient.cs +++ b/GatewayAPI/Clients/FlightService/FlightServiceClient.cs @@ -49,6 +49,12 @@ namespace GatewayAPI.Clients.FlightService return await httpClient.GetAsync($"{FLIGHT_API_PATH}/{flightId}/capacity?ClassType={classType}"); } + public async Task<HttpResponseMessage> GetFlightSeatsAsync(int flightId) + { + return await httpClient.GetAsync($"{FLIGHT_API_PATH}/{flightId}/seats"); + } + + diff --git a/GatewayAPI/Clients/FlightService/IFlightServiceClient.cs b/GatewayAPI/Clients/FlightService/IFlightServiceClient.cs index def17a9..ac86b80 100644 --- a/GatewayAPI/Clients/FlightService/IFlightServiceClient.cs +++ b/GatewayAPI/Clients/FlightService/IFlightServiceClient.cs @@ -8,6 +8,7 @@ namespace GatewayAPI.Clients.FlightService Task<HttpResponseMessage> GetFlightsAsync(string? origin = null, string? destination = null, DateTime? departureTime = null, DateTime? arrivalTime = null); Task<HttpResponseMessage> AddFlightAsync(FlightCreation flight); Task<HttpResponseMessage> GetFlightCapacityAsync(int flightId, int classType); + Task<HttpResponseMessage> GetFlightSeatsAsync(int flightId); Task<HttpResponseMessage> GetSeatsAsync(); diff --git a/GatewayAPI/Controllers/FlightController.cs b/GatewayAPI/Controllers/FlightController.cs index e335bd1..c567683 100644 --- a/GatewayAPI/Controllers/FlightController.cs +++ b/GatewayAPI/Controllers/FlightController.cs @@ -43,5 +43,13 @@ namespace GatewayAPI.Controllers HttpResponseMessage response = await flightServiceClient.GetFlightCapacityAsync(id, classType); return new HttpResponseMessageResult(response); } + + [HttpGet("{id}/seats")] + public async Task<IActionResult> GetFlightSeats([FromRoute] int id) + { + HttpResponseMessage response = await flightServiceClient.GetFlightSeatsAsync(id); + return new HttpResponseMessageResult(response); + } + } } diff --git a/UserMicroservice/Handlers/ExceptionHandler.cs b/UserMicroservice/Handlers/ExceptionHandler.cs new file mode 100644 index 0000000..fec7e76 --- /dev/null +++ b/UserMicroservice/Handlers/ExceptionHandler.cs @@ -0,0 +1,41 @@ +using System.Net; +using System.Text.Json; + +namespace UserMicroservice.Handlers +{ + public class ExceptionHandler + { + private readonly RequestDelegate next; + + public ExceptionHandler(RequestDelegate next) + { + this.next = next; + } + + public async Task Invoke(HttpContext context) + { + try + { + await next(context); + } + catch (Exception ex) + { + if (!context.Response.HasStarted) + { + var response = context.Response; + response.ContentType = "application/json"; + response.StatusCode = (int)HttpStatusCode.InternalServerError; + + var result = JsonSerializer.Serialize(new + { + response.StatusCode, + ex.Message + }); + + await response.WriteAsync(result); + } + } + } + + } +} diff --git a/UserMicroservice/Program.cs b/UserMicroservice/Program.cs index cbfa241..f42cffd 100644 --- a/UserMicroservice/Program.cs +++ b/UserMicroservice/Program.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; using Microsoft.AspNetCore.Identity; +using UserMicroservice.Handlers; var builder = WebApplication.CreateBuilder(args); @@ -46,6 +47,7 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } +app.UseMiddleware<ExceptionHandler>(); app.UseHttpsRedirection(); // Middleware to check for the access token in cookies -- GitLab