Trying to integrate 2FA and messing it up

This commit is contained in:
OlgunR 2024-08-14 10:34:57 +02:00
parent 31dde9f33c
commit 8f54854822
33 changed files with 1312 additions and 35 deletions

View File

@ -1,4 +1,4 @@
namespace Project.Application.DTOs.Auth namespace Project.Application.DTOs.Auth
{ {
public record LoginDto(string Username, string Password); public record LoginDto(string Email, string Password);
} }

View File

@ -2,6 +2,8 @@
{ {
public class CreatingUserDto public class CreatingUserDto
{ {
public string Email { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string FirstName { get; set; } public string FirstName { get; set; }

View File

@ -4,6 +4,8 @@
{ {
public int Id { get; set; } public int Id { get; set; }
public string Email { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string FirstName { get; set; } public string FirstName { get; set; }

View File

@ -4,11 +4,14 @@
{ {
public int Id { get; set; } public int Id { get; set; }
public string Email { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string FirstName { get; set; } public string FirstName { get; set; }
public string LastName { get; set; } public string LastName { get; set; }
public ReadingRoleDto? Role { get; set; } public ReadingRoleDto? Role { get; set; }
} }
} }

View File

@ -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; }
}
}

View File

@ -0,0 +1,8 @@
namespace Project.Application.DTOs.TwoFactorAuth
{
public class TwoFactorVerificationDto
{
public string Email { get; set; }
public string Code { get; set; }
}
}

View 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);
}
}

View File

@ -15,8 +15,8 @@ namespace Project.Application.Interfaces
// READ BY ID // READ BY ID
Task<ReadingUserDto> GetByIdAsync(int id); Task<ReadingUserDto> GetByIdAsync(int id);
// READ BY USERNAME // READ BY EMAIL
Task<ReadingUserDto> GetByUsernameAsync(string username); Task<ReadingUserDto> GetByEmailAsync(string email);
// UPDATE // UPDATE
Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto); Task<bool> UpdateUserAsync(UpdatingUserDto updatingUserDto);

View File

@ -1,6 +1,7 @@
using AutoMapper; using AutoMapper;
using Project.Application.DTOs.Incoming; using Project.Application.DTOs.Incoming;
using Project.Application.DTOs.Outgoing; using Project.Application.DTOs.Outgoing;
using Project.Application.DTOs.TwoFactorAuth;
using Project.Domain.Entities; using Project.Domain.Entities;
namespace Project.Application.MappingProfiles namespace Project.Application.MappingProfiles

View 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; }
}
}

View File

@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="GoogleAuthenticator" Version="3.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />

View File

@ -1,5 +1,4 @@
using Project.Application.Interfaces; using Project.Application.Interfaces;
using Project.Domain.Entities;
using Project.Infrastructure.Interfaces; using Project.Infrastructure.Interfaces;
namespace Project.Application.Services namespace Project.Application.Services
@ -8,19 +7,45 @@ namespace Project.Application.Services
{ {
// FIELDS FOR CTOR // FIELDS FOR CTOR
private IUserRepository _userRepository; private IUserRepository _userRepository;
private readonly ITwoFactorAuthService _twoFactorAuthService;
// CTOR // CTOR
public AuthService(IUserRepository userRepository) public AuthService(IUserRepository userRepository, ITwoFactorAuthService twoFactorAuthService)
{ {
_userRepository = userRepository; _userRepository = userRepository;
_twoFactorAuthService = twoFactorAuthService;
} }
// AUTHENTICATE // 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);
} }
} }
} }

View 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;
}
}
}

View File

@ -54,10 +54,10 @@ namespace Project.Application.Services
return readDto; return readDto;
} }
// READ BY USERNAME // READ BY EMAIL
public async Task<ReadingUserDto> GetByUsernameAsync(string username) 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); var readDto = _mapper.Map<ReadingUserDto>(user);
return readDto; return readDto;
} }

View File

@ -6,11 +6,15 @@ namespace Project.Domain.Entities
[Table("USER", Schema = "dbo")] [Table("USER", Schema = "dbo")]
public class User public class User
{ {
[Column("ID")]
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("ID")]
public int Id { get; set; } public int Id { get; set; }
[Required]
[Column("EMAIL")]
public string Email { get; set; }
[Required] [Required]
[Column("USER_NAME")] [Column("USER_NAME")]
public string UserName { get; set; } public string UserName { get; set; }
@ -27,9 +31,13 @@ namespace Project.Domain.Entities
[Column("PASSWORD")] [Column("PASSWORD")]
public string Password { get; init; } public string Password { get; init; }
[Column("ROLE_ID")]
public int RoleId { get; set; } public int RoleId { get; set; }
[ForeignKey("RoleId")] [ForeignKey("ROLE")]
public Role? Role { get; set; } public Role? Role { get; set; }
[Column("SECRET_KEY")]
public string SecretKey { get; set; }
} }
} }

View File

@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="GoogleAuthenticator" Version="3.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />

View File

@ -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);
}
}

View File

@ -13,8 +13,8 @@ namespace Project.Infrastructure.Interfaces
// READ BY ID // READ BY ID
Task<User?> GetByIdAsync(int id); Task<User?> GetByIdAsync(int id);
// READ BY USERNAME // READ BY EMAIL
Task<User?> GetByUsernameAsync(string username); Task<User?> GetByEmailAsync(string email);
// UPDATE // UPDATE
Task<bool> UpdateAsync(User user); Task<bool> UpdateAsync(User user);

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <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.AspNetCore.Authentication.Cookies" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />

View File

@ -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;
}
}
}

View File

@ -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 return await _context.Users.Where(user => user.Id == id).Include(user => user.Role).FirstAsync(); // Role important for authorization
} }
// READ BY USERNAME // READ BY EMAIL
public async Task<User?> GetByUsernameAsync(string username) 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 // UPDATE

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Project.Application.DTOs.Auth; using Project.Application.DTOs.Auth;
using Project.Application.DTOs.TwoFactorAuth;
using Project.Application.Interfaces; using Project.Application.Interfaces;
using System.Security.Claims; using System.Security.Claims;
@ -15,38 +16,49 @@ namespace Project.Web.Controllers
// FIELDS FOR CTOR // FIELDS FOR CTOR
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IAuthService _authService; private readonly IAuthService _authService;
private readonly ITwoFactorAuthService _twoFactorAuthService;
// CTOR // CTOR
public AuthController(IUserService userService, IAuthService authService) public AuthController(IUserService userService, IAuthService authService, ITwoFactorAuthService twoFactorAuthService)
{ {
_userService = userService; _userService = userService;
_authService = authService; _authService = authService;
_twoFactorAuthService = twoFactorAuthService;
} }
// LOGIN // LOGIN
[AllowAnonymous] [AllowAnonymous]
[HttpPost("login")] [HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginDto login) public async Task<IActionResult> Login([FromBody] LoginDto loginDto)
{ {
// Validate login credentials // Validate login credentials
var isValid = await _authService.ValidateAsync(login.Username, login.Password); bool isValid = await _authService.ValidateAsync(loginDto.Email, loginDto.Password);
if (!isValid) if (!isValid)
{ {
return Unauthorized(); return Unauthorized();
} }
// Validate user // Validate user
var user = await _userService.GetByUsernameAsync(login.Username); var user = await _userService.GetByEmailAsync(loginDto.Email);
if (user == null) if (user == null)
{ {
return Unauthorized(user); 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 // Create claims based on the user information
var claims = new List<Claim> var claims = new List<Claim>
{ {
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), 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.Surname, user.LastName ?? ""),
new Claim(ClaimTypes.GivenName, user.FirstName ?? ""), new Claim(ClaimTypes.GivenName, user.FirstName ?? ""),
new Claim(ClaimTypes.Role, user?.Role?.Name.ToString() ?? "") // role is important for authorization new Claim(ClaimTypes.Role, user?.Role?.Name.ToString() ?? "") // role is important for authorization
@ -73,13 +85,65 @@ namespace Project.Web.Controllers
return Ok(); 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 // LOGOUT
[HttpPost("logout")] [HttpPost("logout")]
public async Task<IActionResult> Logout() public async Task<IActionResult> Logout()
{ {
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); // Logout is basically deleting cookies await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok(); 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);
//}
} }
} }

View 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();
}
}
}

View File

@ -7,7 +7,7 @@ namespace Project.Web.Controllers
{ {
[Route("api/[controller]")] [Route("api/[controller]")]
[ApiController] [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 public class UserController : Controller
{ {
// FIELDS FOR CTOR // FIELDS FOR CTOR
@ -85,18 +85,18 @@ namespace Project.Web.Controllers
return Ok(user); return Ok(user);
} }
// READ BY USERNAME // READ BY EMAIL
[HttpGet("username/{username}", Name = "GetUserByUsername")] [HttpGet("email/{email}", Name = "GetUserByEmail")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [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) if(user == null)
{ {
return NotFound(); return NotFound();

View 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
}
}
}

View 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");
}
}
}

View 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
}
}
}

View 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");
}
}
}

View 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
}
}
}

View 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);
}
}
}

View File

@ -133,6 +133,11 @@ namespace Project.Web.Migrations
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id")); SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("EMAIL");
b.Property<string>("FirstName") b.Property<string>("FirstName")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
@ -148,9 +153,18 @@ namespace Project.Web.Migrations
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")
.HasColumnName("PASSWORD"); .HasColumnName("PASSWORD");
b.Property<int>("RoleId") b.Property<int?>("ROLE")
.HasColumnType("int"); .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") b.Property<string>("UserName")
.IsRequired() .IsRequired()
.HasColumnType("nvarchar(max)") .HasColumnType("nvarchar(max)")

View File

@ -12,33 +12,45 @@ var builder = WebApplication.CreateBuilder(args);
// Add services to the container. // Add services to the container.
builder.Services.AddControllers(); builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); builder.Services.AddSwaggerGen();
// Automapper
builder.Services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly); builder.Services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly);
// ProductService, ProductRepository
builder.Services.AddScoped<IProductService, ProductService>(); builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddScoped<IProductRepository, ProductRepository>(); builder.Services.AddScoped<IProductRepository, ProductRepository>();
// CategoryService, CategoryRepository
builder.Services.AddScoped<ICategoryService, CategoryService>(); builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddScoped<ICategoryRepository, CategoryRepository>(); builder.Services.AddScoped<ICategoryRepository, CategoryRepository>();
// UserService, UserRepository
builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IUserRepository, UserRepository>(); builder.Services.AddScoped<IUserRepository, UserRepository>();
// RoleService, RoleRepository
builder.Services.AddScoped<IRoleService, RoleService>(); builder.Services.AddScoped<IRoleService, RoleService>();
builder.Services.AddScoped<IRoleRepository, RoleRepository>(); builder.Services.AddScoped<IRoleRepository, RoleRepository>();
// AuthService
builder.Services.AddScoped<IAuthService, 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 => builder.Services.AddDbContext<ApplicationDbContext>(options =>
{ {
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("Project.Web")); options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("Project.Web"));
}); });
builder.Services.AddMemoryCache(); builder.Services.AddMemoryCache();
// CookieAuth
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => .AddCookie(options =>
{ {
@ -49,6 +61,7 @@ builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationSc
options.LogoutPath = "/api/auth/logout"; options.LogoutPath = "/api/auth/logout";
}); });
// Authorization
builder.Services.AddAuthorization(options => builder.Services.AddAuthorization(options =>
{ {
options.AddPolicy("AdminOnly", policy => options.AddPolicy("AdminOnly", policy =>

View File

@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="GoogleAuthenticator" Version="3.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.6" />