Trying to integrate 2FA and messing it up
This commit is contained in:
parent
31dde9f33c
commit
8f54854822
@ -1,4 +1,4 @@
|
||||
namespace Project.Application.DTOs.Auth
|
||||
{
|
||||
public record LoginDto(string Username, string Password);
|
||||
public record LoginDto(string Email, string Password);
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
{
|
||||
public class CreatingUserDto
|
||||
{
|
||||
public string Email { get; set; }
|
||||
|
||||
public string UserName { get; set; }
|
||||
|
||||
public string FirstName { get; set; }
|
||||
|
||||
@ -4,6 +4,8 @@
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
|
||||
public string UserName { get; set; }
|
||||
|
||||
public string FirstName { get; set; }
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
namespace Project.Application.DTOs.TwoFactorAuth
|
||||
{
|
||||
public class TwoFactorVerificationDto
|
||||
{
|
||||
public string Email { get; set; }
|
||||
public string Code { get; set; }
|
||||
}
|
||||
}
|
||||
19
Project.Application/Interfaces/ITwoFactorAuthService.cs
Normal file
19
Project.Application/Interfaces/ITwoFactorAuthService.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Project.Application.DTOs.TwoFactorAuth;
|
||||
|
||||
namespace Project.Application.Interfaces
|
||||
{
|
||||
public interface ITwoFactorAuthService
|
||||
{
|
||||
// GENERATE TWO FACTOR AUTH SETUP
|
||||
public Task<TwoFactorSetupDto> GenerateSetupCodeAsync(string userEmail);
|
||||
|
||||
// VALIDATE OTP
|
||||
public Task<bool> ValidateCodeAsync(string userEmail, string code);
|
||||
|
||||
//// SAVE SECRET KEY
|
||||
//public Task SaveSecretKeyAsync(string userEmail, string userSecretKey);
|
||||
|
||||
// GET SECRET KEY
|
||||
public Task<string> GetSecretKeyAsync(string userEmail);
|
||||
}
|
||||
}
|
||||
@ -15,8 +15,8 @@ namespace Project.Application.Interfaces
|
||||
// READ BY ID
|
||||
Task<ReadingUserDto> GetByIdAsync(int id);
|
||||
|
||||
// READ BY USERNAME
|
||||
Task<ReadingUserDto> GetByUsernameAsync(string username);
|
||||
// READ BY EMAIL
|
||||
Task<ReadingUserDto> GetByEmailAsync(string email);
|
||||
|
||||
// UPDATE
|
||||
Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto);
|
||||
|
||||
@ -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
|
||||
|
||||
9
Project.Application/Options/AuthOptions.cs
Normal file
9
Project.Application/Options/AuthOptions.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GoogleAuthenticator" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />
|
||||
|
||||
@ -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<bool> ValidateAsync(string username, string password)
|
||||
public async Task<bool> 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<bool> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
97
Project.Application/Services/TwoFactorAuthService.cs
Normal file
97
Project.Application/Services/TwoFactorAuthService.cs
Normal file
@ -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<AuthOptions> 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<TwoFactorSetupDto> 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<bool> 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<string> GetSecretKeyAsync(string userEmail)
|
||||
{
|
||||
var secretKey = await _twoFactorAuthRepository.GetSecretKeyAsync(userEmail);
|
||||
|
||||
return secretKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -54,10 +54,10 @@ namespace Project.Application.Services
|
||||
return readDto;
|
||||
}
|
||||
|
||||
// READ BY USERNAME
|
||||
public async Task<ReadingUserDto> GetByUsernameAsync(string username)
|
||||
// READ BY EMAIL
|
||||
public async Task<ReadingUserDto> GetByEmailAsync(string email)
|
||||
{
|
||||
var user = await _userRepository.GetByUsernameAsync(username);
|
||||
var user = await _userRepository.GetByEmailAsync(email);
|
||||
var readDto = _mapper.Map<ReadingUserDto>(user);
|
||||
return readDto;
|
||||
}
|
||||
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GoogleAuthenticator" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
using Project.Domain.Entities;
|
||||
|
||||
namespace Project.Infrastructure.Interfaces
|
||||
{
|
||||
public interface ITwoFactorAuthRepository
|
||||
{
|
||||
// GET USER BY EMAIL
|
||||
Task<User> GetUserByEmailAsync(string email);
|
||||
|
||||
// GET SECRET KEY
|
||||
Task<string> GetSecretKeyAsync(string email);
|
||||
|
||||
// SAVE SECRET KEY
|
||||
Task<bool> SaveSecretKeyAsync(string email, string secretKey);
|
||||
}
|
||||
}
|
||||
@ -13,8 +13,8 @@ namespace Project.Infrastructure.Interfaces
|
||||
// READ BY ID
|
||||
Task<User?> GetByIdAsync(int id);
|
||||
|
||||
// READ BY USERNAME
|
||||
Task<User?> GetByUsernameAsync(string username);
|
||||
// READ BY EMAIL
|
||||
Task<User?> GetByEmailAsync(string email);
|
||||
|
||||
// UPDATE
|
||||
Task<bool> UpdateAsync(User user);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="13.0.1" />
|
||||
<PackageReference Include="GoogleAuthenticator" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />
|
||||
|
||||
@ -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<User> GetUserByEmailAsync(string email)
|
||||
{
|
||||
return await _context.Users.FirstAsync(user => user.Email == email);
|
||||
}
|
||||
|
||||
// GET SECRET KEY
|
||||
public async Task<string> GetSecretKeyAsync(string email)
|
||||
{
|
||||
return await _context.Users
|
||||
.Where(user => user.Email == email)
|
||||
.Select(user => user.SecretKey)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
// SAVE SECRET KEY
|
||||
public async Task<bool> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<User?> GetByUsernameAsync(string username)
|
||||
// READ BY EMAIL
|
||||
public async Task<User?> 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
|
||||
|
||||
@ -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<IActionResult> Login([FromBody] LoginDto login)
|
||||
public async Task<IActionResult> 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<Claim>
|
||||
{
|
||||
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<IActionResult> 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<Claim>
|
||||
{
|
||||
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<IActionResult> 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<IActionResult> SetupTwoFactorAuth([FromBody] SetupTwoFactorDto setupDto)
|
||||
//{
|
||||
// var result = await _twoFactorAuthService.GenerateSetupCodeAsync(setupDto.Email);
|
||||
// return Ok(result);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
52
Project.Web/Controllers/TwoFactorAuthController.cs
Normal file
52
Project.Web/Controllers/TwoFactorAuthController.cs
Normal file
@ -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<IActionResult> 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<IActionResult> Verify([FromBody] TwoFactorVerificationDto verifyDto)
|
||||
{
|
||||
var isValid = await _twoFactorAuthService.ValidateCodeAsync(verifyDto.Email, verifyDto.Code);
|
||||
|
||||
if (!isValid)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<IActionResult> GetUserByUsername(string username)
|
||||
public async Task<IActionResult> 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();
|
||||
|
||||
222
Project.Web/Migrations/20240813080158_Zehnte.Designer.cs
generated
Normal file
222
Project.Web/Migrations/20240813080158_Zehnte.Designer.cs
generated
Normal file
@ -0,0 +1,222 @@
|
||||
// <auto-generated />
|
||||
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
|
||||
{
|
||||
/// <inheritdoc />
|
||||
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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("CREATION_DATE");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("CATEGORY_NAME");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("CATEGORY", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("PRODUCT_NAME");
|
||||
|
||||
b.Property<decimal>("Price")
|
||||
.HasColumnType("decimal(18,2)")
|
||||
.HasColumnName("PRICE");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("QUANTITY");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("PRODUCT", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.Role", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("CREATION_DATE");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("ROLE");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ROLE", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("E-MAIL");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("FIRST_NAME");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("LAST_NAME");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("PASSWORD");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("SecretKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("SECRET KEY");
|
||||
|
||||
b.Property<string>("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
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Project.Web/Migrations/20240813080158_Zehnte.cs
Normal file
44
Project.Web/Migrations/20240813080158_Zehnte.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Project.Web.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Zehnte : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "E-MAIL",
|
||||
schema: "dbo",
|
||||
table: "USER",
|
||||
type: "nvarchar(max)",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "SECRET KEY",
|
||||
schema: "dbo",
|
||||
table: "USER",
|
||||
type: "nvarchar(max)",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "E-MAIL",
|
||||
schema: "dbo",
|
||||
table: "USER");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "SECRET KEY",
|
||||
schema: "dbo",
|
||||
table: "USER");
|
||||
}
|
||||
}
|
||||
}
|
||||
225
Project.Web/Migrations/20240813083139_Elfte.Designer.cs
generated
Normal file
225
Project.Web/Migrations/20240813083139_Elfte.Designer.cs
generated
Normal file
@ -0,0 +1,225 @@
|
||||
// <auto-generated />
|
||||
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
|
||||
{
|
||||
/// <inheritdoc />
|
||||
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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("CREATION_DATE");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("CATEGORY_NAME");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("CATEGORY", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("PRODUCT_NAME");
|
||||
|
||||
b.Property<decimal>("Price")
|
||||
.HasColumnType("decimal(18,2)")
|
||||
.HasColumnName("PRICE");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("QUANTITY");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("PRODUCT", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.Role", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("CREATION_DATE");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("ROLE");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ROLE", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("EMAIL");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("FIRST_NAME");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("LAST_NAME");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("PASSWORD");
|
||||
|
||||
b.Property<int?>("ROLE_ID")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("SecretKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("SECRET_KEY");
|
||||
|
||||
b.Property<string>("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
|
||||
}
|
||||
}
|
||||
}
|
||||
54
Project.Web/Migrations/20240813083139_Elfte.cs
Normal file
54
Project.Web/Migrations/20240813083139_Elfte.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Project.Web.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Elfte : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
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<int>(
|
||||
name: "ROLE_ID",
|
||||
schema: "dbo",
|
||||
table: "USER",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
226
Project.Web/Migrations/20240813083456_Zwoelfte.Designer.cs
generated
Normal file
226
Project.Web/Migrations/20240813083456_Zwoelfte.Designer.cs
generated
Normal file
@ -0,0 +1,226 @@
|
||||
// <auto-generated />
|
||||
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
|
||||
{
|
||||
/// <inheritdoc />
|
||||
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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("CREATION_DATE");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("CATEGORY_NAME");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("CATEGORY", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.CategoryRole", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("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<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("PRODUCT_NAME");
|
||||
|
||||
b.Property<decimal>("Price")
|
||||
.HasColumnType("decimal(18,2)")
|
||||
.HasColumnName("PRICE");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("QUANTITY");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("PRODUCT", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.Role", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime")
|
||||
.HasColumnName("CREATION_DATE");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("ROLE");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ROLE", "dbo");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Project.Domain.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ID");
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("EMAIL");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("FIRST_NAME");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("LAST_NAME");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("PASSWORD");
|
||||
|
||||
b.Property<int?>("ROLE")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ROLE_ID");
|
||||
|
||||
b.Property<string>("SecretKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("SECRET_KEY");
|
||||
|
||||
b.Property<string>("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
|
||||
}
|
||||
}
|
||||
}
|
||||
115
Project.Web/Migrations/20240813083456_Zwoelfte.cs
Normal file
115
Project.Web/Migrations/20240813083456_Zwoelfte.cs
Normal file
@ -0,0 +1,115 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Project.Web.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Zwoelfte : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
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<int>(
|
||||
name: "ROLE_ID",
|
||||
schema: "dbo",
|
||||
table: "USER",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
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);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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<int>(
|
||||
name: "ROLE_ID",
|
||||
schema: "dbo",
|
||||
table: "USER",
|
||||
type: "int",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,6 +133,11 @@ namespace Project.Web.Migrations
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("EMAIL");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
@ -148,9 +153,18 @@ namespace Project.Web.Migrations
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("PASSWORD");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
b.Property<int?>("ROLE")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("ROLE_ID");
|
||||
|
||||
b.Property<string>("SecretKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("SECRET_KEY");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
|
||||
@ -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<IProductService, ProductService>();
|
||||
builder.Services.AddScoped<IProductRepository, ProductRepository>();
|
||||
|
||||
// CategoryService, CategoryRepository
|
||||
builder.Services.AddScoped<ICategoryService, CategoryService>();
|
||||
builder.Services.AddScoped<ICategoryRepository, CategoryRepository>();
|
||||
|
||||
// UserService, UserRepository
|
||||
builder.Services.AddScoped<IUserService, UserService>();
|
||||
builder.Services.AddScoped<IUserRepository, UserRepository>();
|
||||
|
||||
// RoleService, RoleRepository
|
||||
builder.Services.AddScoped<IRoleService, RoleService>();
|
||||
builder.Services.AddScoped<IRoleRepository, RoleRepository>();
|
||||
|
||||
// AuthService
|
||||
builder.Services.AddScoped<IAuthService, AuthService>();
|
||||
//builder.Services.AddScoped<IAuthRepository, AuthRepository>();
|
||||
|
||||
// TwoFactorAuthService, TwoFactorAuthReposittory
|
||||
builder.Services.AddScoped<ITwoFactorAuthService, TwoFactorAuthService>();
|
||||
builder.Services.AddScoped<ITwoFactorAuthRepository, TwoFactorAuthRepository>();
|
||||
|
||||
// DatabaseContext
|
||||
builder.Services.AddDbContext<ApplicationDbContext>(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 =>
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GoogleAuthenticator" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user