diff --git a/backend/Dockerfile b/backend/Dockerfile index 5990f8d..7a65178 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,11 +1,11 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -FROM mcr.microsoft.com/dotnet/aspnet:7.0.10-alpine3.18 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY src/api/api.csproj src/api/ RUN dotnet restore "src/api/api.csproj" diff --git a/backend/src/api/Controllers/AuthenticationController.cs b/backend/src/api/Controllers/AuthenticationController.cs deleted file mode 100644 index de8b353..0000000 --- a/backend/src/api/Controllers/AuthenticationController.cs +++ /dev/null @@ -1,64 +0,0 @@ -using api.Constants; -using api.Data.DTO; -using api.Services.Users; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System.IdentityModel.Tokens.Jwt; - -namespace api.Controllers; - -[ApiController] -[Route("/api/auth")] -public class AuthenticationController : ControllerBase -{ - private readonly IUserService _userService; - private readonly ILogger _logger; - - public AuthenticationController(IUserService userService, ILogger logger) - { - _userService = userService; - _logger = logger; - } - - [HttpGet("create-user")] - [Authorize] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status400BadRequest)] - public async Task CreateUser() - { - var accessToken = Request.Headers["Authorization"].ToString().Replace("Bearer ", ""); - var jsonTokenData = new JwtSecurityTokenHandler().ReadJwtToken(accessToken); - var keycloakUuid = jsonTokenData.Subject; - var userEmail = jsonTokenData.Claims.FirstOrDefault(claim => claim.Type == "email")?.Value; - - if (userEmail == null) - { - _logger.LogInformation("User with keycloakUuid={keycloakUuid} tried to log in without email.", keycloakUuid); - return BadRequest("Required data missing"); - } - - var (isSuccess, error) = await _userService.CreateKeycloakUser( - new UserDTO - { - KeycloakUuid = keycloakUuid, - Email = userEmail - } - ); - - if (isSuccess) - { - _logger.LogInformation("The user {email} has been created successfully.", userEmail); - return Ok("User created"); - } - else - { - if (error == ErrorMessages.UserAlreadyExists) - { - _logger.LogInformation("The user {email} has already been created.", userEmail); - return Ok("User is already created"); - } - _logger.LogInformation("Failure during creation of {email} user.", userEmail); - return BadRequest(error); - } - } -} diff --git a/backend/src/api/Controllers/GreetingsController.cs b/backend/src/api/Controllers/GreetingsController.cs deleted file mode 100644 index 665bed0..0000000 --- a/backend/src/api/Controllers/GreetingsController.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -namespace api.Controllers; - -[ApiController] -[Route("/api/greetings")] -public class GreetingsController : ControllerBase -{ - [HttpGet] - [Authorize] - [ProducesResponseType(StatusCodes.Status200OK)] - [Route("user")] - public IActionResult Greet() - { - return Ok($"Hello {HttpContext?.User?.Identity?.Name ?? "World" }"); - } - - [HttpGet] - [ProducesResponseType(StatusCodes.Status200OK)] - [Route("HelloWorld")] - public IActionResult HelloWorld() - { - return Ok("Hello World!"); - } -} diff --git a/backend/src/api/Data/DAO/UserModel.cs b/backend/src/api/Data/DAO/UserModel.cs deleted file mode 100644 index 12253d3..0000000 --- a/backend/src/api/Data/DAO/UserModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace api.Data.DAO; - -public class UserModel -{ - [Key] - public int Id { get; set; } - public required string KeycloakUuid { get; set; } - [EmailAddress] - public required string Email { get; set; } -} diff --git a/backend/src/api/Data/DTO/UserDTO.cs b/backend/src/api/Data/DTO/UserDTO.cs deleted file mode 100644 index 7079db2..0000000 --- a/backend/src/api/Data/DTO/UserDTO.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace api.Data.DTO; - -public class UserDTO -{ - [Required] - public required string KeycloakUuid { get; set; } - [Required] - [EmailAddress] - public required string Email { get; set; } -} diff --git a/backend/src/api/Migrations/20240223084836_Init.Designer.cs b/backend/src/api/Migrations/20240223084836_Init.Designer.cs deleted file mode 100644 index a363f14..0000000 --- a/backend/src/api/Migrations/20240223084836_Init.Designer.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using api.Data; - -#nullable disable - -namespace api.Migrations -{ - [DbContext(typeof(ApplicationDbContext))] - [Migration("20240223084836_Init")] - partial class Init - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.2") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("api.Data.DAO.UserModel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Email") - .IsRequired() - .HasColumnType("text"); - - b.Property("KeycloakUuid") - .IsRequired() - .HasColumnType("text"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/src/api/Migrations/20240223084836_Init.cs b/backend/src/api/Migrations/20240223084836_Init.cs deleted file mode 100644 index 9f4ae7a..0000000 --- a/backend/src/api/Migrations/20240223084836_Init.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace api.Migrations -{ - /// - public partial class Init : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Users", - columns: table => new - { - Id = table.Column(type: "integer", nullable: false) - .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), - KeycloakUuid = table.Column(type: "text", nullable: false), - Email = table.Column(type: "text", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Users", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Users"); - } - } -} diff --git a/backend/src/api/Program.cs b/backend/src/api/Program.cs index 35b8666..9f9c12a 100644 --- a/backend/src/api/Program.cs +++ b/backend/src/api/Program.cs @@ -1,5 +1,4 @@ using api.Data; -using api.Services.Users; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; @@ -40,8 +39,6 @@ ValidateIssuer = true, ValidateLifetime = true }; - builder.Services.AddSingleton(tokenValidationParameters); - builder.Services.AddSingleton(keycloakJwtOptions); builder.Services.AddAuthentication(options => { @@ -60,7 +57,6 @@ { c.SwaggerDoc("v1", new OpenApiInfo { Title = "api", Version = "v1" }); }); - builder.Services.AddScoped(); builder.Services.AddCors(options => { diff --git a/backend/src/api/RequestExtensions.cs b/backend/src/api/RequestExtensions.cs new file mode 100644 index 0000000..2d45f01 --- /dev/null +++ b/backend/src/api/RequestExtensions.cs @@ -0,0 +1,20 @@ +using Microsoft.IdentityModel.JsonWebTokens; + +namespace api; + +public static class RequestExtensions +{ + public static string? UserId(this HttpRequest request) + { + try + { + var accessToken = request.Headers.Authorization.ToString().Split(' ')[1]; + var jsonTokenData = new JsonWebTokenHandler().ReadJsonWebToken(accessToken); + return jsonTokenData.Subject; + } + catch + { + return null; + } + } +} diff --git a/backend/src/api/Services/Users/IUserService.cs b/backend/src/api/Services/Users/IUserService.cs deleted file mode 100644 index 5b09ba7..0000000 --- a/backend/src/api/Services/Users/IUserService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using api.Data.DTO; - -namespace api.Services.Users; - -public interface IUserService -{ - Task<(bool isSuccess, string? error)> CreateKeycloakUser(UserDTO user); -} diff --git a/backend/src/api/Services/Users/UserService.cs b/backend/src/api/Services/Users/UserService.cs deleted file mode 100644 index 08d440f..0000000 --- a/backend/src/api/Services/Users/UserService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using api.Data; -using api.Data.DTO; -using api.Data.DAO; -using api.Constants; - -namespace api.Services.Users; - -public class UserService : IUserService -{ - private readonly ApplicationDbContext _applicationDbContext; - - public UserService(ApplicationDbContext applicationDbContext) - { - _applicationDbContext = applicationDbContext; - } - - public async Task<(bool isSuccess, string? error)> CreateKeycloakUser(UserDTO user) - { - var userInstance = _applicationDbContext.Users.FirstOrDefault(userInstance => userInstance.KeycloakUuid.Equals(user.KeycloakUuid)); - if (userInstance != null) - { - return (false, ErrorMessages.UserAlreadyExists); - } - var newUser = new UserModel() - { - KeycloakUuid = user.KeycloakUuid, - Email = user.Email - }; - await _applicationDbContext.Users.AddAsync(newUser); - await _applicationDbContext.SaveChangesAsync(); - return (true, null); - } -} diff --git a/backend/src/api/api.csproj b/backend/src/api/api.csproj index 6d537d7..50bdbc8 100644 --- a/backend/src/api/api.csproj +++ b/backend/src/api/api.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 f7cb2e8e-61a4-4a0a-9259-839230fcfe2d Linux enable @@ -9,18 +9,22 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - + + + + + diff --git a/frontend/src/helpers/RequireAuth.tsx b/frontend/src/helpers/RequireAuth.tsx index 3014338..8bfa471 100644 --- a/frontend/src/helpers/RequireAuth.tsx +++ b/frontend/src/helpers/RequireAuth.tsx @@ -7,21 +7,6 @@ import Constants from "./Constants"; export default function RequireAuth() { const { isLogin, keycloak } = useAuth(); - - const createUserInBackend = async () => { - const response = await fetch(`${Constants.BASE_URL}/auth/create-user`, { - headers: { Authorization: `Bearer ${keycloak!.token}` }, - }); - if (response.status !== 200) { - const errorMessage = await response.text(); - throw new Error(errorMessage); - } - }; - - if (isLogin) { - createUserInBackend(); - } - return isLogin ? :

Authenticating...

; }