Skip to content
Snippets Groups Projects
Commit c7dbb436 authored by Abdelsamad, Mouaz R (UG - SISC)'s avatar Abdelsamad, Mouaz R (UG - SISC)
Browse files

Dockerize Gateway and improvments

parent b594de1b
Branches MA/Gateway
No related tags found
No related merge requests found
Showing with 169 additions and 40 deletions
# Image settings
IMAGE_TAG=0.0.1
MYSQL_IMAGE_TAG=8.0
# Database configuration
DB_PORT=3308
DB_NAME=AspNetCoreDb
DB_USER=root
DB_PASSWORD=
DB_PORT=3307
DB_NAME=myDB
DB_USER=user
DB_PASSWORD=user
DB_CHARSET=utf8mb4
# Service ports
USER_MICROSERVICE_PORT=5089 # This port will be used as the JWT issuer
USER_MICROSERVICE_PORT=5089
FLIGHT_MICROSERVICE_PORT=5175
GATEWAY_API_PORT=5267
CLIENT_PORT=4200
\ No newline at end of file
CREATE TABLE Users (
Id INT AUTO_INCREMENT PRIMARY KEY,
Username LONGTEXT NOT NULL,
Email LONGTEXT NOT NULL,
PasswordHash LONGTEXT NOT NULL,
Type INT NOT NULL
);
CREATE TABLE RefreshTokens (
Id INT AUTO_INCREMENT PRIMARY KEY,
UserId INT NOT NULL,
Token LONGTEXT NOT NULL,
ExpirationDate DATETIME(6) NOT NULL
);
CREATE TABLE Flights (
Id INT AUTO_INCREMENT PRIMARY KEY,
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
);
CREATE TABLE Seats (
Id INT AUTO_INCREMENT PRIMARY KEY,
FlightId INT NOT NULL,
SeatNumber LONGTEXT NOT NULL,
ClassType INT NOT NULL,
IsAvailable TINYINT(1) NOT NULL
);
......@@ -10,5 +10,6 @@ namespace GatewayAPI.Clients.UserService
Task<HttpResponseMessage> LoginUserAsync(UserLogin user);
Task<HttpResponseMessage> AuthorizeUserAsync();
Task<HttpResponseMessage> LogoutUserAsync();
Task<HttpResponseMessage> UpdateUserAsync(int id, UserUpdateInfo updateInfo);
}
}
......@@ -45,5 +45,10 @@ namespace GatewayAPI.Clients.UserService
return await httpClient.PostAsync($"{API_PATH}/logout", null);
}
public async Task<HttpResponseMessage> UpdateUserAsync(int id, UserUpdateInfo updateInfo)
{
return await httpClient.PatchAsJsonAsync($"{API_PATH}/{id}", updateInfo);
}
}
}
......@@ -56,5 +56,13 @@ namespace GatewayAPI.Controllers
HttpResponseMessage response = await userServiceClient.GetUserAsync(id);
return new HttpResponseMessageResult(response);
}
[HttpPatch("{id}")]
public async Task<IActionResult> UpdateUser(int id, [FromBody] UserUpdateInfo updateInfo)
{
HttpResponseMessage response = await userServiceClient.UpdateUserAsync(id, updateInfo);
return new HttpResponseMessageResult(response);
}
}
}
namespace GatewayAPI.Models
{
public class UserUpdateInfo
{
public string? Username { get; set; }
public string? Email { get; set; }
public string? Password { get; set; }
}
}
......@@ -21,7 +21,7 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
//app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
......@@ -10,14 +10,14 @@ namespace GatewayAPI
{
services.AddHttpClient<IUserServiceClient, UserServiceClient>(client =>
{
string? baseUrl = configurationManager["UserMicroservice:BaseUrl"];
client.BaseAddress = new Uri(baseUrl ?? throw new InvalidOperationException("UserMicroservice BaseUrl is not configured."));
string baseUrl = configurationManager["UserMicroservice:BaseUrl"] ?? throw new InvalidOperationException("UserMicroservice BaseUrl is not configured.");
client.BaseAddress = new Uri(baseUrl.EndsWith("/") ? baseUrl : baseUrl + "/");
}).AddHttpMessageHandler<RequestCookieHandler>();
services.AddHttpClient<IFlightServiceClient, FlightServiceClient>(client =>
{
string? baseUrl = configurationManager["FlightMicroservice:BaseUrl"];
client.BaseAddress = new Uri(baseUrl ?? throw new InvalidOperationException("FlightMicroservice BaseUrl is not configured."));
string baseUrl = configurationManager["FlightMicroservice:BaseUrl"] ?? throw new InvalidOperationException("FlightMicroservice BaseUrl is not configured.");
client.BaseAddress = new Uri(baseUrl.EndsWith("/") ? baseUrl : baseUrl + "/");
}).AddHttpMessageHandler<RequestCookieHandler>();
return services;
......
......@@ -7,9 +7,9 @@
},
"AllowedHosts": "*",
"UserMicroservice": {
"BaseUrl": "http://localhost:5089/"
"BaseUrl": "http://localhost:5089"
},
"FlightMicroservice": {
"BaseUrl": "http://localhost:5175/"
"BaseUrl": "http://localhost:5175"
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using UserMicroservice.Models;
using UserMicroservice.Services;
......@@ -31,9 +32,10 @@ namespace UserMicroservice.Controllers
if (user == null)
return BadRequest();
return authenticateUser(user.Id);
} catch (InvalidOperationException ex)
setAuthCookies(user.Id);
return Ok(new { user.Id, user.Username, user.Email, user.Type });
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
......@@ -57,7 +59,8 @@ namespace UserMicroservice.Controllers
if (!int.TryParse(userIdString, out int userId))
return BadRequest("User ID is invalid.");
return authenticateUser(userId);
setAuthCookies(userId);
return Ok();
}
// POST: api/User/login
......@@ -68,14 +71,15 @@ namespace UserMicroservice.Controllers
if(user == null)
return Unauthorized();
return authenticateUser(user.Id);
setAuthCookies(user.Id);
return Ok(new { user.Id, user.Username, user.Email, user.Type });
}
private IActionResult authenticateUser(int userId)
private void setAuthCookies(int userId)
{
AuthTokenPair authToken = _authService.AuthenticateUser(userId);
if (authToken == null)
return BadRequest();
throw new ArgumentNullException(nameof(authToken));
// Set the access token as an HttpOnly cookie
Response.Cookies.Append("AccessToken", authToken.AccessToken, new CookieOptions
......@@ -94,8 +98,6 @@ namespace UserMicroservice.Controllers
SameSite = SameSiteMode.Strict,
Expires = DateTimeOffset.UtcNow.AddDays(2)
});
return Ok();
}
// POST: api/User/logout
......@@ -153,8 +155,28 @@ namespace UserMicroservice.Controllers
User? user = _userService.GetUser(id);
if(user == null)
return NotFound($"User with {id} doesnt exist");
return Ok(user);
return Ok(new{ user.Id, user.Username, user.Email, user.Type });
}
// PUT: api/User/{id}
[Authorize]
[HttpPatch("{id}")]
public IActionResult UpdateUser(int id, [FromBody] UpdateUserModel model)
{
try
{
_userService.UpdateUser(id, model.Username, model.Email, model.Password);
return Ok();
}
catch (KeyNotFoundException exception)
{
return NotFound(exception.Message);
}
catch (DbUpdateException exception)
{
return BadRequest(exception.Message);
}
}
}
......
namespace UserMicroservice.Models
{
public class UpdateUserModel
{
public string? Username { get; set; }
public string? Email { get; set; }
public string? Password { get; set; }
}
}
......@@ -10,7 +10,7 @@ namespace UserMicroservice.Services
User? GetUser(string username, string password);
List<User> GetUsers();
User CreateUser(string email, string userName, string password, UserType UserType);
User UpdateUser(User updatedUser);
void UpdateUser(int id, string? username, string? email, string? password);
bool DeleteUser(string username);
User? GetUserByEmail(string email);
}
......
......@@ -80,17 +80,32 @@ namespace UserMicroservice.Services
return user;
}
public User UpdateUser(User updatedUser)
public void UpdateUser(int id, string? username, string? email, string? password)
{
_context.Users
.Where(user => user.Id == updatedUser.Id)
User? user = GetUser(id);
if(user == null)
throw new KeyNotFoundException($"A User with the provided Id {id} doesnt exist");
string updatedEmail = string.IsNullOrEmpty(email) ? user.Email : email;
string updatedUserName = string.IsNullOrEmpty(username) ? user.Username : username;
string updatedPassword = user.PasswordHash;
if (!string.IsNullOrEmpty(password)) {
user.SetPasswordHash(_passwordHasher, password);
updatedPassword = user.PasswordHash;
}
int affectedRows = _context.Users
.Where(user => user.Id == id)
.ExecuteUpdate(setters => setters
.SetProperty(user => user.Username, updatedUser.Username)
.SetProperty(user => user.PasswordHash, updatedUser.PasswordHash));
.SetProperty(user => user.Username, updatedUserName)
.SetProperty(user => user.Email, updatedEmail)
.SetProperty(user => user.PasswordHash, updatedPassword));
_context.SaveChanges();
return updatedUser;
if (affectedRows == 0)
throw new DbUpdateException("Operation was not able to update the Database");
}
}
}
version: '3.8'
services:
usermicroservice:
build:
......@@ -12,30 +11,52 @@ services:
- DOTNET_RUNNING_IN_CONTAINER=true
- ConnectionStrings__DefaultConnection=Server=host.docker.internal;Port=${DB_PORT};Database=${DB_NAME};User=${DB_USER};Password=${DB_PASSWORD};CharSet=${DB_CHARSET}
- Jwt__Key=0QTrd3jToEYj205k01A2R87Hc5YpqDNeywg7JzQpczs=
- Jwt__Issuer=http://localhost:${USER_MICROSERVICE_PORT}
- Jwt__Audience=http://localhost:${USER_MICROSERVICE_PORT}
- Jwt__Issuer=http://usermicroservice:8080
- Jwt__Audience=http://usermicroservice:8080
flightmicroservice:
build:
context: ./FlightMicroservice
image: flightmicroservice:${IMAGE_TAG}
ports:
- "5175:8080"
- "${FLIGHT_MICROSERVICE_PORT}:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Production
- DOTNET_RUNNING_IN_CONTAINER=true
- ConnectionStrings__DefaultConnection=Server=host.docker.internal;Port=${DB_PORT};Database=${DB_NAME};User=${DB_USER};Password=${DB_PASSWORD};CharSet=${DB_CHARSET}
- Jwt__Key=0QTrd3jToEYj205k01A2R87Hc5YpqDNeywg7JzQpczs=
- Jwt__Issuer=http://localhost:${USER_MICROSERVICE_PORT}
- Jwt__Audience=http://localhost:${USER_MICROSERVICE_PORT}
- Jwt__Issuer=http://usermicroservice:8080
- Jwt__Audience=http://usermicroservice:8080
gatewayapi:
build:
context: ./GatewayAPI
image: gatewayapi:${IMAGE_TAG}
ports:
- "${GATEWAY_API_PORT}:8080"
environment:
- ASPNETCORE_ENVIRONMENT=Production
- DOTNET_RUNNING_IN_CONTAINER=true
- UserMicroservice__BaseUrl=http://usermicroservice:8080
- FlightMicroservice__BaseUrl=http://flightmicroservice:8080
client:
build:
context: ./client
image: client:${IMAGE_TAG}
ports:
- "4200:4200"
- "${CLIENT_PORT}:4200"
# ... other services
db:
image: mysql:${MYSQL_IMAGE_TAG}
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- ./Database:/docker-entrypoint-initdb.d
ports:
- "${DB_PORT}:3306"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment