diff --git a/Database/InitTables.sql b/Database/InitTables.sql index 6805d233e8cd62079b3e81de3c91104ab1e61098..dd06e9e1cf83cfba34888ade63dc7cf2cc0d8399 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 4e1dc43a334a3223363fe50b9f6af9aa49028642..ea3411bda1e1510ea3269969c853d6844a58e385 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 8b66623a08690d39384f8a829f915df01b3fd2cc..ba9f074844691188d7418b82529b36a10b1e0069 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 0000000000000000000000000000000000000000..ef916a74658b8849e34d53c5d27666187c09600f --- /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 257bdefc3afa6d1f4862257fa10fa4ea322b76ce..73a66ac9e200a444653622a132e0c83f31b9b592 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 82fabffe2f353337b3d5ae7bf32b20c60791d73c..151b9c8ed383d7f537b3f85cf931b41ede39c2cd 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 aa905a165e3e24e2bfcf44ed0e61657ab7348eb8..91e30b89143172ab5fe60391b5cf2f98ad234afa 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 c9e9a03f9a3cb6a5d1654f74e53ce7e2c6399d8d..f3bed26d5dad7e96846f67db8593dc0c809c0749 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 cdf5f3a75248f64842cd7cc1bde1d9a0879f1a66..82e4ca76e9c3f5a932be90366aff634ee9832223 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 def17a9d8dc494c5e1dd6242f36ff299e3b954a2..ac86b80d8cf8bf3bb2ca54de3b9c6563d01fcbf0 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 e335bd102327e36d733c4b3e59b23020fa25182a..c567683c5f5f67a7826b772be0055d050d5f9934 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 0000000000000000000000000000000000000000..fec7e76d923c4b84052091a13aed60e81c316c8c --- /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 cbfa241f33c33ebbac83347fd69f505826cd1ea9..f42cffdfd575f033112cd1158c998ccd8074c6e8 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