diff --git a/Project.Application/DTOs/Auth/LoginDto.cs b/Project.Application/DTOs/Auth/LoginDto.cs index bfd226f..c8d05fc 100644 --- a/Project.Application/DTOs/Auth/LoginDto.cs +++ b/Project.Application/DTOs/Auth/LoginDto.cs @@ -1,4 +1,4 @@ namespace Project.Application.DTOs.Auth { - public record LoginDto(string Username, string Password); + public record LoginDto(string Email, string Password); } diff --git a/Project.Application/DTOs/Incoming/CreatingUserDto.cs b/Project.Application/DTOs/Incoming/CreatingUserDto.cs index 4bed5a1..dc2cf58 100644 --- a/Project.Application/DTOs/Incoming/CreatingUserDto.cs +++ b/Project.Application/DTOs/Incoming/CreatingUserDto.cs @@ -2,6 +2,8 @@ { public class CreatingUserDto { + public string Email { get; set; } + public string UserName { get; set; } public string FirstName { get; set; } diff --git a/Project.Application/DTOs/Incoming/UpdatingUserDto.cs b/Project.Application/DTOs/Incoming/UpdatingUserDto.cs index 98045e7..f640a66 100644 --- a/Project.Application/DTOs/Incoming/UpdatingUserDto.cs +++ b/Project.Application/DTOs/Incoming/UpdatingUserDto.cs @@ -4,6 +4,8 @@ { public int Id { get; set; } + public string Email { get; set; } + public string UserName { get; set; } public string FirstName { get; set; } diff --git a/Project.Application/DTOs/Outgoing/ReadingUserDto.cs b/Project.Application/DTOs/Outgoing/ReadingUserDto.cs index fd270fe..a6c3f34 100644 --- a/Project.Application/DTOs/Outgoing/ReadingUserDto.cs +++ b/Project.Application/DTOs/Outgoing/ReadingUserDto.cs @@ -4,11 +4,14 @@ { public int Id { get; set; } + public string Email { get; set; } + public string UserName { get; set; } public string FirstName { get; set; } public string LastName { get; set; } + public ReadingRoleDto? Role { get; set; } } } diff --git a/Project.Application/DTOs/TwoFactorAuth/TwoFactorSetupDto.cs b/Project.Application/DTOs/TwoFactorAuth/TwoFactorSetupDto.cs new file mode 100644 index 0000000..31154ec --- /dev/null +++ b/Project.Application/DTOs/TwoFactorAuth/TwoFactorSetupDto.cs @@ -0,0 +1,9 @@ +namespace Project.Application.DTOs.TwoFactorAuth +{ + public class TwoFactorSetupDto + { + public string SecretKey { get; set; } + public string QrCodeImageUrl { get; set; } + public string ManualEntryKey { get; set; } + } +} diff --git a/Project.Application/DTOs/TwoFactorAuth/TwoFactorVerificationDto.cs b/Project.Application/DTOs/TwoFactorAuth/TwoFactorVerificationDto.cs new file mode 100644 index 0000000..93db972 --- /dev/null +++ b/Project.Application/DTOs/TwoFactorAuth/TwoFactorVerificationDto.cs @@ -0,0 +1,8 @@ +namespace Project.Application.DTOs.TwoFactorAuth +{ + public class TwoFactorVerificationDto + { + public string Email { get; set; } + public string Code { get; set; } + } +} diff --git a/Project.Application/Interfaces/ITwoFactorAuthService.cs b/Project.Application/Interfaces/ITwoFactorAuthService.cs new file mode 100644 index 0000000..e66294b --- /dev/null +++ b/Project.Application/Interfaces/ITwoFactorAuthService.cs @@ -0,0 +1,19 @@ +using Project.Application.DTOs.TwoFactorAuth; + +namespace Project.Application.Interfaces +{ + public interface ITwoFactorAuthService + { + // GENERATE TWO FACTOR AUTH SETUP + public Task GenerateSetupCodeAsync(string userEmail); + + // VALIDATE OTP + public Task ValidateCodeAsync(string userEmail, string code); + + //// SAVE SECRET KEY + //public Task SaveSecretKeyAsync(string userEmail, string userSecretKey); + + // GET SECRET KEY + public Task GetSecretKeyAsync(string userEmail); + } +} diff --git a/Project.Application/Interfaces/IUserService.cs b/Project.Application/Interfaces/IUserService.cs index f29e533..40f73b1 100644 --- a/Project.Application/Interfaces/IUserService.cs +++ b/Project.Application/Interfaces/IUserService.cs @@ -15,8 +15,8 @@ namespace Project.Application.Interfaces // READ BY ID Task GetByIdAsync(int id); - // READ BY USERNAME - Task GetByUsernameAsync(string username); + // READ BY EMAIL + Task GetByEmailAsync(string email); // UPDATE Task UpdateUserAsync(UpdatingUserDto updatingUserDto); diff --git a/Project.Application/MappingProfiles/BasicDtoMappingProfile.cs b/Project.Application/MappingProfiles/BasicDtoMappingProfile.cs index 97c6297..26d8633 100644 --- a/Project.Application/MappingProfiles/BasicDtoMappingProfile.cs +++ b/Project.Application/MappingProfiles/BasicDtoMappingProfile.cs @@ -1,6 +1,7 @@ using AutoMapper; using Project.Application.DTOs.Incoming; using Project.Application.DTOs.Outgoing; +using Project.Application.DTOs.TwoFactorAuth; using Project.Domain.Entities; namespace Project.Application.MappingProfiles diff --git a/Project.Application/Options/AuthOptions.cs b/Project.Application/Options/AuthOptions.cs new file mode 100644 index 0000000..1de4d57 --- /dev/null +++ b/Project.Application/Options/AuthOptions.cs @@ -0,0 +1,9 @@ +namespace Project.Application.Options +{ + public class AuthOptions + { + public required string ApiKey { get; init; } + public required string Issuer { get; init; } + public required string SecretKey { get; init; } + } +} diff --git a/Project.Application/Project.Application.csproj b/Project.Application/Project.Application.csproj index 9ff9ed5..1379e34 100644 --- a/Project.Application/Project.Application.csproj +++ b/Project.Application/Project.Application.csproj @@ -7,6 +7,7 @@ + diff --git a/Project.Application/Services/AuthService.cs b/Project.Application/Services/AuthService.cs index 04dc6f5..c603281 100644 --- a/Project.Application/Services/AuthService.cs +++ b/Project.Application/Services/AuthService.cs @@ -1,5 +1,4 @@ using Project.Application.Interfaces; -using Project.Domain.Entities; using Project.Infrastructure.Interfaces; namespace Project.Application.Services @@ -8,19 +7,45 @@ namespace Project.Application.Services { // FIELDS FOR CTOR private IUserRepository _userRepository; + private readonly ITwoFactorAuthService _twoFactorAuthService; // CTOR - public AuthService(IUserRepository userRepository) + public AuthService(IUserRepository userRepository, ITwoFactorAuthService twoFactorAuthService) { _userRepository = userRepository; + _twoFactorAuthService = twoFactorAuthService; } // AUTHENTICATE - public async Task ValidateAsync(string username, string password) + public async Task ValidateAsync(string email, string password) { - var user = await _userRepository.GetByUsernameAsync(username); + var user = await _userRepository.GetByEmailAsync(email); - return user?.Password == password; + if (user == null || user.Password != password) + { + return false; + } + + // Check if 2FA is enabled + if (!string.IsNullOrEmpty(user.SecretKey)) + { + return false; // 2FA is enabled and additional validation is required + } + + return true; + } + + // VALIDATE TWO FACTOR AUTHENTICATION + public async Task ValidateTwoFactorAsync(string email, string code) + { + var user = await _userRepository.GetByEmailAsync(email); + + if (user == null || string.IsNullOrEmpty(user.SecretKey)) + { + return false; + } + + return await _twoFactorAuthService.ValidateCodeAsync(user.Email, code); } } } diff --git a/Project.Application/Services/TwoFactorAuthService.cs b/Project.Application/Services/TwoFactorAuthService.cs new file mode 100644 index 0000000..a7dac7f --- /dev/null +++ b/Project.Application/Services/TwoFactorAuthService.cs @@ -0,0 +1,97 @@ +using Google.Authenticator; +using Microsoft.Extensions.Options; +using Project.Application.DTOs.TwoFactorAuth; +using Project.Application.Interfaces; +using Project.Application.Options; +using Project.Infrastructure.Interfaces; + +namespace Project.Application.Services +{ + public class TwoFactorAuthService : ITwoFactorAuthService + { + // FIELDS FOR CTOR + private readonly TwoFactorAuthenticator _twoFactorAuthenticator; + private readonly ITwoFactorAuthRepository _twoFactorAuthRepository; + private readonly string _issuer; + + // CTOR + public TwoFactorAuthService(IOptions options, ITwoFactorAuthRepository twoFactorAuthRepository) + { + _twoFactorAuthenticator = new TwoFactorAuthenticator(); + _twoFactorAuthRepository = twoFactorAuthRepository; + _issuer = options.Value.Issuer; + } + + //public void TwoFactorAuthenticatorMethods() + //{ + // _twoFactorAuthenticator.Equals(); + // _twoFactorAuthenticator.GeneratePINAtInterval(); + // _twoFactorAuthenticator.GenerateSetupCode(); + // _twoFactorAuthenticator.GetCurrentPIN(); + // _twoFactorAuthenticator.GetCurrentPINs(); + // _twoFactorAuthenticator.GetHashCode(); + // _twoFactorAuthenticator.GetType(); + // _twoFactorAuthenticator.ToString(); + // _twoFactorAuthenticator.ValidateTwoFactorPIN(); + //} + + // GENERATE TWO FACTOR AUTH SETUP + public async Task GenerateSetupCodeAsync(string userEmail) + { + var userSecretKey = Guid.NewGuid().ToString(); + + var setupInfo = _twoFactorAuthenticator.GenerateSetupCode( + _issuer, // Envelope.Configuration.ApplicationName + userEmail, // user.Email + userSecretKey, + false, + 10); + + string manualEntryKey = setupInfo.ManualEntryKey; + string qrCodeImageUrl = setupInfo.QrCodeSetupImageUrl; + + await _twoFactorAuthRepository.SaveSecretKeyAsync(userEmail, userSecretKey); + + return new TwoFactorSetupDto + { + SecretKey = userSecretKey, + QrCodeImageUrl = qrCodeImageUrl, + ManualEntryKey = manualEntryKey + }; + } + + // VALIDATE OTP + public async Task ValidateCodeAsync(string userEmail, string userInputCode) + { + var secretKey = await _twoFactorAuthRepository.GetSecretKeyAsync(userEmail); + + if (string.IsNullOrEmpty(secretKey)) + { + throw new InvalidOperationException("Secret key not found!"); + } + + return _twoFactorAuthenticator.ValidateTwoFactorPIN(secretKey, userInputCode); + } + + //// SAVE SECRET KEY + //public async Task SaveSecretKeyAsync(string userEmail, string userSecretKey) + //{ + // var user = await _twoFactorAuthRepository.GetUserByEmailAsync(userEmail); + + // if (user == null) + // { + // throw new InvalidOperationException("User not found!"); + // } + + // await _twoFactorAuthRepository.SaveSecretKeyAsync(userEmail, userSecretKey); + //} + + // GET SECRET KEY + public async Task GetSecretKeyAsync(string userEmail) + { + var secretKey = await _twoFactorAuthRepository.GetSecretKeyAsync(userEmail); + + return secretKey; + } + } +} diff --git a/Project.Application/Services/UserService.cs b/Project.Application/Services/UserService.cs index b106440..85d7623 100644 --- a/Project.Application/Services/UserService.cs +++ b/Project.Application/Services/UserService.cs @@ -54,10 +54,10 @@ namespace Project.Application.Services return readDto; } - // READ BY USERNAME - public async Task GetByUsernameAsync(string username) + // READ BY EMAIL + public async Task GetByEmailAsync(string email) { - var user = await _userRepository.GetByUsernameAsync(username); + var user = await _userRepository.GetByEmailAsync(email); var readDto = _mapper.Map(user); return readDto; } diff --git a/Project.Domain/Entities/User.cs b/Project.Domain/Entities/User.cs index bb35dbb..5892975 100644 --- a/Project.Domain/Entities/User.cs +++ b/Project.Domain/Entities/User.cs @@ -6,11 +6,15 @@ namespace Project.Domain.Entities [Table("USER", Schema = "dbo")] public class User { - [Column("ID")] [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] + [Column("ID")] public int Id { get; set; } - + + [Required] + [Column("EMAIL")] + public string Email { get; set; } + [Required] [Column("USER_NAME")] public string UserName { get; set; } @@ -27,9 +31,13 @@ namespace Project.Domain.Entities [Column("PASSWORD")] public string Password { get; init; } + [Column("ROLE_ID")] public int RoleId { get; set; } - [ForeignKey("RoleId")] + [ForeignKey("ROLE")] public Role? Role { get; set; } + + [Column("SECRET_KEY")] + public string SecretKey { get; set; } } } diff --git a/Project.Domain/Project.Domain.csproj b/Project.Domain/Project.Domain.csproj index 7a8cadb..be283b4 100644 --- a/Project.Domain/Project.Domain.csproj +++ b/Project.Domain/Project.Domain.csproj @@ -7,6 +7,7 @@ + diff --git a/Project.Infrastructure/Interfaces/ITwoFactorAuthRepository.cs b/Project.Infrastructure/Interfaces/ITwoFactorAuthRepository.cs new file mode 100644 index 0000000..588dbf7 --- /dev/null +++ b/Project.Infrastructure/Interfaces/ITwoFactorAuthRepository.cs @@ -0,0 +1,16 @@ +using Project.Domain.Entities; + +namespace Project.Infrastructure.Interfaces +{ + public interface ITwoFactorAuthRepository + { + // GET USER BY EMAIL + Task GetUserByEmailAsync(string email); + + // GET SECRET KEY + Task GetSecretKeyAsync(string email); + + // SAVE SECRET KEY + Task SaveSecretKeyAsync(string email, string secretKey); + } +} diff --git a/Project.Infrastructure/Interfaces/IUserRepository.cs b/Project.Infrastructure/Interfaces/IUserRepository.cs index d0d50b3..7b4d409 100644 --- a/Project.Infrastructure/Interfaces/IUserRepository.cs +++ b/Project.Infrastructure/Interfaces/IUserRepository.cs @@ -13,8 +13,8 @@ namespace Project.Infrastructure.Interfaces // READ BY ID Task GetByIdAsync(int id); - // READ BY USERNAME - Task GetByUsernameAsync(string username); + // READ BY EMAIL + Task GetByEmailAsync(string email); // UPDATE Task UpdateAsync(User user); diff --git a/Project.Infrastructure/Project.Infrastructure.csproj b/Project.Infrastructure/Project.Infrastructure.csproj index 53f2a15..da72f96 100644 --- a/Project.Infrastructure/Project.Infrastructure.csproj +++ b/Project.Infrastructure/Project.Infrastructure.csproj @@ -8,6 +8,7 @@ + diff --git a/Project.Infrastructure/Repositories/TwoFactorAuthRepository.cs b/Project.Infrastructure/Repositories/TwoFactorAuthRepository.cs new file mode 100644 index 0000000..ed8dde4 --- /dev/null +++ b/Project.Infrastructure/Repositories/TwoFactorAuthRepository.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore; +using Project.Domain.Entities; +using Project.Infrastructure.Interfaces; + +namespace Project.Infrastructure.Repositories +{ + public class TwoFactorAuthRepository : ITwoFactorAuthRepository + { + // FIELDS FOR CTOR + private readonly ApplicationDbContext _context; + + // CTOR + public TwoFactorAuthRepository(ApplicationDbContext context) + { + _context = context; + } + + // GET USER BY EMAIL + public async Task GetUserByEmailAsync(string email) + { + return await _context.Users.FirstAsync(user => user.Email == email); + } + + // GET SECRET KEY + public async Task GetSecretKeyAsync(string email) + { + return await _context.Users + .Where(user => user.Email == email) + .Select(user => user.SecretKey) + .FirstOrDefaultAsync(); + } + + // SAVE SECRET KEY + public async Task SaveSecretKeyAsync(string email, string secretKey) + { + User user = await _context.Users.FirstAsync(user => user.Email == email); + + user.SecretKey = secretKey; + + _context.Entry(user).State = EntityState.Modified; + var results = await _context.SaveChangesAsync(); + return results > 0; + } + } +} diff --git a/Project.Infrastructure/Repositories/UserRepository.cs b/Project.Infrastructure/Repositories/UserRepository.cs index 265277b..e37c7ee 100644 --- a/Project.Infrastructure/Repositories/UserRepository.cs +++ b/Project.Infrastructure/Repositories/UserRepository.cs @@ -35,10 +35,10 @@ namespace Project.Infrastructure.Repositories return await _context.Users.Where(user => user.Id == id).Include(user => user.Role).FirstAsync(); // Role important for authorization } - // READ BY USERNAME - public async Task GetByUsernameAsync(string username) + // READ BY EMAIL + public async Task GetByEmailAsync(string email) { - return await _context.Users.Include(user => user.Role).FirstOrDefaultAsync(u => u.UserName == username); // Role important for authorization + return await _context.Users.Include(user => user.Role).FirstOrDefaultAsync(u => u.Email == email); // Role important for authorization } // UPDATE diff --git a/Project.Web/Controllers/AuthController.cs b/Project.Web/Controllers/AuthController.cs index a79914b..8e5afc8 100644 --- a/Project.Web/Controllers/AuthController.cs +++ b/Project.Web/Controllers/AuthController.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Project.Application.DTOs.Auth; +using Project.Application.DTOs.TwoFactorAuth; using Project.Application.Interfaces; using System.Security.Claims; @@ -15,38 +16,49 @@ namespace Project.Web.Controllers // FIELDS FOR CTOR private readonly IUserService _userService; private readonly IAuthService _authService; + private readonly ITwoFactorAuthService _twoFactorAuthService; // CTOR - public AuthController(IUserService userService, IAuthService authService) + public AuthController(IUserService userService, IAuthService authService, ITwoFactorAuthService twoFactorAuthService) { _userService = userService; _authService = authService; + _twoFactorAuthService = twoFactorAuthService; } // LOGIN [AllowAnonymous] [HttpPost("login")] - public async Task Login([FromBody] LoginDto login) + public async Task Login([FromBody] LoginDto loginDto) { // Validate login credentials - var isValid = await _authService.ValidateAsync(login.Username, login.Password); + bool isValid = await _authService.ValidateAsync(loginDto.Email, loginDto.Password); if (!isValid) { return Unauthorized(); } // Validate user - var user = await _userService.GetByUsernameAsync(login.Username); + var user = await _userService.GetByEmailAsync(loginDto.Email); if (user == null) { return Unauthorized(user); } + // Check if 2FA is required + var secretKey = await _twoFactorAuthService.GetSecretKeyAsync(loginDto.Email); + + if (!string.IsNullOrEmpty(secretKey)) + { + // Promt for 2FA + return Ok(new { RequiresTwoFactor = true }); + } + // Create claims based on the user information var claims = new List { new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), - new Claim(ClaimTypes.Name, user.UserName), + new Claim(ClaimTypes.Name, user.Email), new Claim(ClaimTypes.Surname, user.LastName ?? ""), new Claim(ClaimTypes.GivenName, user.FirstName ?? ""), new Claim(ClaimTypes.Role, user?.Role?.Name.ToString() ?? "") // role is important for authorization @@ -73,13 +85,65 @@ namespace Project.Web.Controllers return Ok(); } + [AllowAnonymous] + [HttpPost("verify2fa")] + public async Task Verify2Fa([FromBody] TwoFactorVerificationDto verifyDto) + { + var isValid = await _twoFactorAuthService.ValidateCodeAsync(verifyDto.Email, verifyDto.Code); + if (!isValid) + { + return Unauthorized(); + } + + var user = await _userService.GetByEmailAsync(verifyDto.Email); + if (user == null) + { + return Unauthorized(); + } + + var claims = new List + { + new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), + new Claim(ClaimTypes.Email, user.Email), + new Claim(ClaimTypes.Surname, user.LastName ?? ""), + new Claim(ClaimTypes.GivenName, user.FirstName ?? ""), + new Claim(ClaimTypes.Role, user?.Role?.Name ?? "") + }; + + var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); + + var authProperties = new AuthenticationProperties + { + IsPersistent = true, + AllowRefresh = true, + ExpiresUtc = DateTime.UtcNow.AddMinutes(60) + }; + + await HttpContext.SignInAsync( + CookieAuthenticationDefaults.AuthenticationScheme, + new ClaimsPrincipal(claimsIdentity), + authProperties + ); + + return Ok(); + } + // LOGOUT [HttpPost("logout")] public async Task Logout() { - await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); // Logout is basically deleting cookies + await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return Ok(); } + + //// SETUP 2FA + //[AllowAnonymous] + //[HttpPost("setup-2fa")] + //public async Task SetupTwoFactorAuth([FromBody] SetupTwoFactorDto setupDto) + //{ + // var result = await _twoFactorAuthService.GenerateSetupCodeAsync(setupDto.Email); + // return Ok(result); + //} } } diff --git a/Project.Web/Controllers/TwoFactorAuthController.cs b/Project.Web/Controllers/TwoFactorAuthController.cs new file mode 100644 index 0000000..52549a3 --- /dev/null +++ b/Project.Web/Controllers/TwoFactorAuthController.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Mvc; +using Project.Application.DTOs.TwoFactorAuth; +using Project.Application.Interfaces; + +namespace Project.Web.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class TwoFactorAuthController : ControllerBase + { + // FEILDS FOR CTOR + private readonly ITwoFactorAuthService _twoFactorAuthService; + private readonly IUserService _userService; + + // CTOR + public TwoFactorAuthController(ITwoFactorAuthService twoFactorAuthService, IUserService userService) + { + _twoFactorAuthService = twoFactorAuthService; + _userService = userService; + } + + // SETUP 2FA + [HttpPost("setup")] + public async Task Setup([FromBody] string email) + { + var user = await _userService.GetByEmailAsync(email); + + if (user == null) + { + return NotFound(); + } + + var setupInfo = await _twoFactorAuthService.GenerateSetupCodeAsync(email); + + return Ok(setupInfo); + } + + // VERIFY + [HttpPost("verify")] + public async Task Verify([FromBody] TwoFactorVerificationDto verifyDto) + { + var isValid = await _twoFactorAuthService.ValidateCodeAsync(verifyDto.Email, verifyDto.Code); + + if (!isValid) + { + return Unauthorized(); + } + + return Ok(); + } + } +} diff --git a/Project.Web/Controllers/UserController.cs b/Project.Web/Controllers/UserController.cs index 4163554..f52eb6a 100644 --- a/Project.Web/Controllers/UserController.cs +++ b/Project.Web/Controllers/UserController.cs @@ -7,7 +7,7 @@ namespace Project.Web.Controllers { [Route("api/[controller]")] [ApiController] - [Authorize(Roles = "Admin")] // Authorize Admins only to use this controller + //[Authorize(Roles = "Admin")] // Authorize Admins only to use this controller public class UserController : Controller { // FIELDS FOR CTOR @@ -85,18 +85,18 @@ namespace Project.Web.Controllers return Ok(user); } - // READ BY USERNAME - [HttpGet("username/{username}", Name = "GetUserByUsername")] + // READ BY EMAIL + [HttpGet("email/{email}", Name = "GetUserByEmail")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetUserByUsername(string username) + public async Task GetUserByEmail(string email) { - if (string.IsNullOrEmpty(username)) + if (string.IsNullOrEmpty(email)) { - return BadRequest("Username connot be empty"); + return BadRequest("Email connot be empty"); } - var user = await _userService.GetByUsernameAsync(username); + var user = await _userService.GetByEmailAsync(email); if(user == null) { return NotFound(); diff --git a/Project.Web/Migrations/20240813080158_Zehnte.Designer.cs b/Project.Web/Migrations/20240813080158_Zehnte.Designer.cs new file mode 100644 index 0000000..a61d6c8 --- /dev/null +++ b/Project.Web/Migrations/20240813080158_Zehnte.Designer.cs @@ -0,0 +1,222 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Project.Infrastructure; + +#nullable disable + +namespace Project.Web.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240813080158_Zehnte")] + partial class Zehnte + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Project.Domain.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime") + .HasColumnName("CREATION_DATE"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("CATEGORY_NAME"); + + b.HasKey("Id"); + + b.ToTable("CATEGORY", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("RoleId"); + + b.ToTable("CATEGORY_ROLE", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PRODUCT_NAME"); + + b.Property("Price") + .HasColumnType("decimal(18,2)") + .HasColumnName("PRICE"); + + b.Property("Quantity") + .HasColumnType("int") + .HasColumnName("QUANTITY"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("PRODUCT", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime") + .HasColumnName("CREATION_DATE"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ROLE"); + + b.HasKey("Id"); + + b.ToTable("ROLE", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("E-MAIL"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("FIRST_NAME"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("LAST_NAME"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PASSWORD"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("SecretKey") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("SECRET KEY"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("USER_NAME"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("USER", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b => + { + b.HasOne("Project.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Project.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Product", b => + { + b.HasOne("Project.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Project.Domain.Entities.User", b => + { + b.HasOne("Project.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Project.Web/Migrations/20240813080158_Zehnte.cs b/Project.Web/Migrations/20240813080158_Zehnte.cs new file mode 100644 index 0000000..fc4e70d --- /dev/null +++ b/Project.Web/Migrations/20240813080158_Zehnte.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Project.Web.Migrations +{ + /// + public partial class Zehnte : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "E-MAIL", + schema: "dbo", + table: "USER", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "SECRET KEY", + schema: "dbo", + table: "USER", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "E-MAIL", + schema: "dbo", + table: "USER"); + + migrationBuilder.DropColumn( + name: "SECRET KEY", + schema: "dbo", + table: "USER"); + } + } +} diff --git a/Project.Web/Migrations/20240813083139_Elfte.Designer.cs b/Project.Web/Migrations/20240813083139_Elfte.Designer.cs new file mode 100644 index 0000000..1e8c868 --- /dev/null +++ b/Project.Web/Migrations/20240813083139_Elfte.Designer.cs @@ -0,0 +1,225 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Project.Infrastructure; + +#nullable disable + +namespace Project.Web.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240813083139_Elfte")] + partial class Elfte + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Project.Domain.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime") + .HasColumnName("CREATION_DATE"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("CATEGORY_NAME"); + + b.HasKey("Id"); + + b.ToTable("CATEGORY", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("RoleId"); + + b.ToTable("CATEGORY_ROLE", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PRODUCT_NAME"); + + b.Property("Price") + .HasColumnType("decimal(18,2)") + .HasColumnName("PRICE"); + + b.Property("Quantity") + .HasColumnType("int") + .HasColumnName("QUANTITY"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("PRODUCT", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime") + .HasColumnName("CREATION_DATE"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ROLE"); + + b.HasKey("Id"); + + b.ToTable("ROLE", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("EMAIL"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("FIRST_NAME"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("LAST_NAME"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PASSWORD"); + + b.Property("ROLE_ID") + .HasColumnType("int"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.Property("SecretKey") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("SECRET_KEY"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("USER_NAME"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("USER", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b => + { + b.HasOne("Project.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Project.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Product", b => + { + b.HasOne("Project.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Project.Domain.Entities.User", b => + { + b.HasOne("Project.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Project.Web/Migrations/20240813083139_Elfte.cs b/Project.Web/Migrations/20240813083139_Elfte.cs new file mode 100644 index 0000000..896f5dc --- /dev/null +++ b/Project.Web/Migrations/20240813083139_Elfte.cs @@ -0,0 +1,54 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Project.Web.Migrations +{ + /// + public partial class Elfte : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "SECRET KEY", + schema: "dbo", + table: "USER", + newName: "SECRET_KEY"); + + migrationBuilder.RenameColumn( + name: "E-MAIL", + schema: "dbo", + table: "USER", + newName: "EMAIL"); + + migrationBuilder.AddColumn( + name: "ROLE_ID", + schema: "dbo", + table: "USER", + type: "int", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ROLE_ID", + schema: "dbo", + table: "USER"); + + migrationBuilder.RenameColumn( + name: "SECRET_KEY", + schema: "dbo", + table: "USER", + newName: "SECRET KEY"); + + migrationBuilder.RenameColumn( + name: "EMAIL", + schema: "dbo", + table: "USER", + newName: "E-MAIL"); + } + } +} diff --git a/Project.Web/Migrations/20240813083456_Zwoelfte.Designer.cs b/Project.Web/Migrations/20240813083456_Zwoelfte.Designer.cs new file mode 100644 index 0000000..36b8aea --- /dev/null +++ b/Project.Web/Migrations/20240813083456_Zwoelfte.Designer.cs @@ -0,0 +1,226 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Project.Infrastructure; + +#nullable disable + +namespace Project.Web.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240813083456_Zwoelfte")] + partial class Zwoelfte + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.6") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Project.Domain.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime") + .HasColumnName("CREATION_DATE"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("CATEGORY_NAME"); + + b.HasKey("Id"); + + b.ToTable("CATEGORY", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("RoleId"); + + b.ToTable("CATEGORY_ROLE", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PRODUCT_NAME"); + + b.Property("Price") + .HasColumnType("decimal(18,2)") + .HasColumnName("PRICE"); + + b.Property("Quantity") + .HasColumnType("int") + .HasColumnName("QUANTITY"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("PRODUCT", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("datetime") + .HasColumnName("CREATION_DATE"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("ROLE"); + + b.HasKey("Id"); + + b.ToTable("ROLE", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasColumnName("ID"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("EMAIL"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("FIRST_NAME"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("LAST_NAME"); + + b.Property("Password") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PASSWORD"); + + b.Property("ROLE") + .HasColumnType("int"); + + b.Property("RoleId") + .HasColumnType("int") + .HasColumnName("ROLE_ID"); + + b.Property("SecretKey") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("SECRET_KEY"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("USER_NAME"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("USER", "dbo"); + }); + + modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b => + { + b.HasOne("Project.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Project.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("Project.Domain.Entities.Product", b => + { + b.HasOne("Project.Domain.Entities.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("Project.Domain.Entities.User", b => + { + b.HasOne("Project.Domain.Entities.Role", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Project.Web/Migrations/20240813083456_Zwoelfte.cs b/Project.Web/Migrations/20240813083456_Zwoelfte.cs new file mode 100644 index 0000000..915adbf --- /dev/null +++ b/Project.Web/Migrations/20240813083456_Zwoelfte.cs @@ -0,0 +1,115 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Project.Web.Migrations +{ + /// + public partial class Zwoelfte : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_USER_ROLE_RoleId", + schema: "dbo", + table: "USER"); + + migrationBuilder.DropIndex( + name: "IX_USER_RoleId", + schema: "dbo", + table: "USER"); + + migrationBuilder.DropColumn( + name: "RoleId", + schema: "dbo", + table: "USER"); + + migrationBuilder.AlterColumn( + name: "ROLE_ID", + schema: "dbo", + table: "USER", + type: "int", + nullable: false, + defaultValue: 0, + oldClrType: typeof(int), + oldType: "int", + oldNullable: true); + + migrationBuilder.AddColumn( + name: "ROLE", + schema: "dbo", + table: "USER", + type: "int", + nullable: true); + + migrationBuilder.CreateIndex( + name: "IX_USER_ROLE_ID", + schema: "dbo", + table: "USER", + column: "ROLE_ID"); + + migrationBuilder.AddForeignKey( + name: "FK_USER_ROLE_ROLE_ID", + schema: "dbo", + table: "USER", + column: "ROLE_ID", + principalSchema: "dbo", + principalTable: "ROLE", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_USER_ROLE_ROLE_ID", + schema: "dbo", + table: "USER"); + + migrationBuilder.DropIndex( + name: "IX_USER_ROLE_ID", + schema: "dbo", + table: "USER"); + + migrationBuilder.DropColumn( + name: "ROLE", + schema: "dbo", + table: "USER"); + + migrationBuilder.AlterColumn( + name: "ROLE_ID", + schema: "dbo", + table: "USER", + type: "int", + nullable: true, + oldClrType: typeof(int), + oldType: "int"); + + migrationBuilder.AddColumn( + name: "RoleId", + schema: "dbo", + table: "USER", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateIndex( + name: "IX_USER_RoleId", + schema: "dbo", + table: "USER", + column: "RoleId"); + + migrationBuilder.AddForeignKey( + name: "FK_USER_ROLE_RoleId", + schema: "dbo", + table: "USER", + column: "RoleId", + principalSchema: "dbo", + principalTable: "ROLE", + principalColumn: "ID", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/Project.Web/Migrations/ApplicationDbContextModelSnapshot.cs b/Project.Web/Migrations/ApplicationDbContextModelSnapshot.cs index fb078df..6f76ca0 100644 --- a/Project.Web/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Project.Web/Migrations/ApplicationDbContextModelSnapshot.cs @@ -133,6 +133,11 @@ namespace Project.Web.Migrations SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("EMAIL"); + b.Property("FirstName") .IsRequired() .HasColumnType("nvarchar(max)") @@ -148,9 +153,18 @@ namespace Project.Web.Migrations .HasColumnType("nvarchar(max)") .HasColumnName("PASSWORD"); - b.Property("RoleId") + b.Property("ROLE") .HasColumnType("int"); + b.Property("RoleId") + .HasColumnType("int") + .HasColumnName("ROLE_ID"); + + b.Property("SecretKey") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("SECRET_KEY"); + b.Property("UserName") .IsRequired() .HasColumnType("nvarchar(max)") diff --git a/Project.Web/Program.cs b/Project.Web/Program.cs index 6e4a504..1dadcc7 100644 --- a/Project.Web/Program.cs +++ b/Project.Web/Program.cs @@ -12,33 +12,45 @@ var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle + builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +// Automapper builder.Services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly); +// ProductService, ProductRepository builder.Services.AddScoped(); builder.Services.AddScoped(); +// CategoryService, CategoryRepository builder.Services.AddScoped(); builder.Services.AddScoped(); +// UserService, UserRepository builder.Services.AddScoped(); builder.Services.AddScoped(); +// RoleService, RoleRepository builder.Services.AddScoped(); builder.Services.AddScoped(); +// AuthService builder.Services.AddScoped(); -//builder.Services.AddScoped(); +// TwoFactorAuthService, TwoFactorAuthReposittory +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +// DatabaseContext builder.Services.AddDbContext(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("Project.Web")); }); + builder.Services.AddMemoryCache(); +// CookieAuth builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { @@ -49,6 +61,7 @@ builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationSc options.LogoutPath = "/api/auth/logout"; }); +// Authorization builder.Services.AddAuthorization(options => { options.AddPolicy("AdminOnly", policy => diff --git a/Project.Web/Project.Web.csproj b/Project.Web/Project.Web.csproj index 4d6a08d..996365a 100644 --- a/Project.Web/Project.Web.csproj +++ b/Project.Web/Project.Web.csproj @@ -7,6 +7,7 @@ +