From 5bfef4337dff11f37a369b5b66a01e9de3db5c5a Mon Sep 17 00:00:00 2001 From: Tohirjon-Odilov Date: Tue, 5 Mar 2024 00:25:54 +0500 Subject: [PATCH] update registratsiya --- .../Controllers/Identity/AuthController.cs | 31 ++- .../wwwroot/Users/coderr89.txt | 1 + .../wwwroot/Users/test.cs | 6 + .../Abstractions/IServices/IAuthService.cs | 1 - .../IServices/IHashingPassword.cs | 11 + .../Abstractions/IServices/IUserService.cs | 2 +- .../Services/AuthServices/AuthService.cs | 22 +- .../Services/HashingPassword.cs | 42 ++++ .../Services/UserService.cs | 14 +- .../Entities/DTOs/Auth/CheckEmail.cs | 8 +- .../Entities/DTOs/Auth/RegisterLogin.cs | 11 - .../Entities/DTOs/Auth/RequestLogin.cs | 4 + .../Entities/DTOs/Auth/RequestSignUp.cs | 11 + .../Entities/DTOs/ProductDTO.cs | 4 + .../Entities/DTOs/UserDTO.cs | 11 +- .../Entities/Models/Category.cs | 3 + .../Entities/Models/Product.cs | 8 +- .../Entities/Models/User.cs | 3 +- .../Entities/ViewModels/UserViewModel.cs | 2 +- .../DependencyInjection.cs | 3 - .../20240304162731_add-attribute.Designer.cs | 131 +++++++++++ .../20240304162731_add-attribute.cs | 210 ++++++++++++++++++ ...75433_change-type-for-password.Designer.cs | 130 +++++++++++ ...20240304175433_change-type-for-password.cs | 54 +++++ ...0304182915_update-colulmn-user.Designer.cs | 133 +++++++++++ .../20240304182915_update-colulmn-user.cs | 28 +++ .../StockManagementDbContextModelSnapshot.cs | 68 ++---- .../Configuration/CategoryConfig.cs | 15 ++ .../Configuration/ProductConfig.cs | 18 ++ .../Persistance/Configuration/UserConfig.cs | 21 ++ .../Persistance/StockManagementDbContext.cs | 8 + 31 files changed, 909 insertions(+), 105 deletions(-) create mode 100644 Exam.StockManagement.API/wwwroot/Users/coderr89.txt create mode 100644 Exam.StockManagement.API/wwwroot/Users/test.cs create mode 100644 Exam.StockManagement.Application/Abstractions/IServices/IHashingPassword.cs create mode 100644 Exam.StockManagement.Application/Services/HashingPassword.cs delete mode 100644 Exam.StockManagement.Domain/Entities/DTOs/Auth/RegisterLogin.cs create mode 100644 Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.Designer.cs create mode 100644 Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.cs create mode 100644 Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.Designer.cs create mode 100644 Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.cs create mode 100644 Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.Designer.cs create mode 100644 Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.cs create mode 100644 Exam.StockManagement.Infrastructure/Persistance/Configuration/CategoryConfig.cs create mode 100644 Exam.StockManagement.Infrastructure/Persistance/Configuration/ProductConfig.cs create mode 100644 Exam.StockManagement.Infrastructure/Persistance/Configuration/UserConfig.cs diff --git a/Exam.StockManagement.API/Controllers/Identity/AuthController.cs b/Exam.StockManagement.API/Controllers/Identity/AuthController.cs index 138ac38..765dca2 100644 --- a/Exam.StockManagement.API/Controllers/Identity/AuthController.cs +++ b/Exam.StockManagement.API/Controllers/Identity/AuthController.cs @@ -1,6 +1,5 @@ using Exam.StockManagement.Application.Abstractions.IServices; using Exam.StockManagement.Domain.Entities.DTOs.Auth; -using Exam.StockManagement.Domain.Exceptions; using Microsoft.AspNetCore.Mvc; namespace Exam.StockManagement.API.Controllers.Identity @@ -27,7 +26,16 @@ public AuthController(IAuthService authService, public async Task SignUp([FromForm] RequestSignUp model) { var result = await _authService.RegisterUser(model); - return Ok(result); + + if (result.Email == "501") + { + return BadRequest("Parol bir-biriga mos kelmadi."); + } else if (result.Email == "502") + { + return BadRequest("Email oldindan band qilingan."); + } + + return Ok("User muvaffaqiyatli ro'yxatdan o'tkazildi. Iltimos login qismidan qayta kiriting."); } [HttpPost] @@ -36,20 +44,29 @@ public async Task Login([FromForm] RequestLogin model) var result = await _authService.UserExist(model); if (result) { - string path = Path.Combine(_webHostEnvironment.WebRootPath, "code.txt"); + // emailga qarab fayl ochadi. + // coddan foydalanib bo'lganidan so'ng avtomatik o'chib ketadi. + string path = Path.Combine(_webHostEnvironment.WebRootPath, "Users", + $"{model.Email.Remove(model.Email.IndexOf("@"))}.txt"); await _emailSenderService.SendEmailAsync(model.Email, path); - return Ok(result); + return Ok("User Emailiga kod yuborildi. Iltimos tasdiqlash qismidan kodni kiriting."); } - throw new NotFoundException(); + return NotFound("Email topilmadi."); } [HttpPost] public async Task AcceptUser([FromForm] CheckEmail model) { - string path = Path.Combine(_webHostEnvironment.WebRootPath, "code.txt"); + string path = Path.Combine(_webHostEnvironment.WebRootPath, "Users", + $"{model.Email.Remove(model.Email.IndexOf("@"))}.txt"); + var result = await _authService.GenerateToken(model, path); - return Ok(result.Token); + if (result.Token == "503") + { + return BadRequest("User'ga yuborilgan kod bilan to'g'ri kelmadi."); + } + return StatusCode(201,result.Token); } } } diff --git a/Exam.StockManagement.API/wwwroot/Users/coderr89.txt b/Exam.StockManagement.API/wwwroot/Users/coderr89.txt new file mode 100644 index 0000000..81e52b9 --- /dev/null +++ b/Exam.StockManagement.API/wwwroot/Users/coderr89.txt @@ -0,0 +1 @@ +2453 \ No newline at end of file diff --git a/Exam.StockManagement.API/wwwroot/Users/test.cs b/Exam.StockManagement.API/wwwroot/Users/test.cs new file mode 100644 index 0000000..0c2f2bd --- /dev/null +++ b/Exam.StockManagement.API/wwwroot/Users/test.cs @@ -0,0 +1,6 @@ +namespace Exam.StockManagement.API.wwwroot.Users +{ + public class test + { + } +} diff --git a/Exam.StockManagement.Application/Abstractions/IServices/IAuthService.cs b/Exam.StockManagement.Application/Abstractions/IServices/IAuthService.cs index ddac5b1..c18d5e3 100644 --- a/Exam.StockManagement.Application/Abstractions/IServices/IAuthService.cs +++ b/Exam.StockManagement.Application/Abstractions/IServices/IAuthService.cs @@ -7,7 +7,6 @@ public interface IAuthService { public Task GenerateToken(CheckEmail model, string path); public Task UserExist(RequestLogin user); - public Task CorrectEmail(RegisterLogin user); public Task RegisterUser(RequestSignUp signUp); } } diff --git a/Exam.StockManagement.Application/Abstractions/IServices/IHashingPassword.cs b/Exam.StockManagement.Application/Abstractions/IServices/IHashingPassword.cs new file mode 100644 index 0000000..7b1709d --- /dev/null +++ b/Exam.StockManagement.Application/Abstractions/IServices/IHashingPassword.cs @@ -0,0 +1,11 @@ +namespace Exam.StockManagement.Application.Abstractions.IServices +{ + public interface IHashingPassword + { + public bool VerifyPassword( + string passwordFromUser, + string hashFromDB, + string saltAsStringFromDB); + public string HashPassword(string password, out byte[] salt); + } +} diff --git a/Exam.StockManagement.Application/Abstractions/IServices/IUserService.cs b/Exam.StockManagement.Application/Abstractions/IServices/IUserService.cs index 45a5195..1de6bc9 100644 --- a/Exam.StockManagement.Application/Abstractions/IServices/IUserService.cs +++ b/Exam.StockManagement.Application/Abstractions/IServices/IUserService.cs @@ -8,7 +8,7 @@ namespace Exam.StockManagement.Application.Abstractions.IServices { public interface IUserService { - public Task Create(RequestSignUp signUp); + public Task Create(RequestSignUp requestSignUp); public Task GetByEmail(string email); public Task> GetAll(); public Task Delete(Expression> expression); diff --git a/Exam.StockManagement.Application/Services/AuthServices/AuthService.cs b/Exam.StockManagement.Application/Services/AuthServices/AuthService.cs index 7696f26..bdef4b1 100644 --- a/Exam.StockManagement.Application/Services/AuthServices/AuthService.cs +++ b/Exam.StockManagement.Application/Services/AuthServices/AuthService.cs @@ -25,16 +25,6 @@ public AuthService(IConfiguration conf, IUserService userService) _userService = userService; } - public async Task CorrectEmail(RegisterLogin user) - { - var result = await _userService.GetByEmail(user.Email!); - if (result.Code == user.Code) - { - return "Login successfully!"; - } - throw new NotFoundException(); - } - public async Task GenerateToken(CheckEmail model, string path) { var login = new RequestLogin() @@ -44,11 +34,9 @@ public async Task GenerateToken(CheckEmail model, string path) if (File.ReadAllText(path) != model.Code && await UserExist(login)) { - throw new PasswordNotMatchException(); + return new ResponseLogin { Token = "503" }; } - File.WriteAllText(path, ""); - var result = await _userService.GetByEmail(model.Email); IEnumerable permissionsId = new List(); @@ -68,6 +56,8 @@ public async Task GenerateToken(CheckEmail model, string path) new Claim("permissions",permmisionJson) }; + File.Delete(path); + return await GenerateToken(claims); } @@ -106,14 +96,16 @@ public async Task GenerateToken(IEnumerable additionalClai public async Task UserExist(RequestLogin user) { - if (user.Email == null) + if (user.Email == null || user.Password == null) { throw new NotFoundException(); } var result = await _userService.GetByEmail(user.Email); + var hash = new HashingPassword(); - if (result != null) + if(result != null && hash.VerifyPassword( + user.Password, result.Password, result.Salt)) { return true; } diff --git a/Exam.StockManagement.Application/Services/HashingPassword.cs b/Exam.StockManagement.Application/Services/HashingPassword.cs new file mode 100644 index 0000000..916bfa5 --- /dev/null +++ b/Exam.StockManagement.Application/Services/HashingPassword.cs @@ -0,0 +1,42 @@ +using Exam.StockManagement.Application.Abstractions.IServices; +using System.Security.Cryptography; +using System.Text; + +namespace Exam.StockManagement.Application.Services +{ + public class HashingPassword : IHashingPassword + { + private readonly int keySize = 64; + private readonly int iterations = 350000; + private readonly HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA512; + + public string HashPassword(string password, out byte[] salt) + { + salt = RandomNumberGenerator.GetBytes(keySize); + + var hash = Rfc2898DeriveBytes.Pbkdf2( + Encoding.UTF8.GetBytes(password), + salt, + iterations, + hashAlgorithm, + keySize); + + return Convert.ToHexString(hash); + } + + public bool VerifyPassword(string passwordFromUser, string hashFromDB, string saltAsStringFromDB) + { + byte[] salt = Convert.FromHexString(saltAsStringFromDB); + + var hashToCompare = Rfc2898DeriveBytes.Pbkdf2( + password: passwordFromUser, + salt, + iterations: iterations, + hashAlgorithm: hashAlgorithm, + outputLength: keySize); + + return CryptographicOperations.FixedTimeEquals(hashToCompare, Convert.FromHexString(hashFromDB)); + + } + } +} diff --git a/Exam.StockManagement.Application/Services/UserService.cs b/Exam.StockManagement.Application/Services/UserService.cs index d8eef10..ce570f5 100644 --- a/Exam.StockManagement.Application/Services/UserService.cs +++ b/Exam.StockManagement.Application/Services/UserService.cs @@ -4,7 +4,6 @@ using Exam.StockManagement.Domain.Entities.DTOs.Auth; using Exam.StockManagement.Domain.Entities.Models; using Exam.StockManagement.Domain.Entities.ViewModels; -using Exam.StockManagement.Domain.Exceptions; using System.Linq.Expressions; namespace Exam.StockManagement.Application.Services @@ -24,24 +23,26 @@ public async Task Create(RequestSignUp requestSignUp) if (requestSignUp.Password != requestSignUp.ConfirmPassword) { - throw new PasswordNotMatchException(); + return new User { Email = "501" }; } if (hasEmail != null) { - throw new AlreadyExistException(); + return new User { Email = "502" }; } + var hash = new HashingPassword(); + User? user = new User() { Name = requestSignUp.Name, Email = requestSignUp.Email, - Password = requestSignUp.Password, + Password = hash.HashPassword(requestSignUp.Password, out byte[]? salt), + Salt = Convert.ToHexString(salt), Role = requestSignUp.Role - }; - User? result = await _userRepository.Create(user); + var result = await _userRepository.Create(user); return result; } @@ -104,7 +105,6 @@ public async Task Update(int Id, UserDTO userDTO) return result; } return new User(); - } } } diff --git a/Exam.StockManagement.Domain/Entities/DTOs/Auth/CheckEmail.cs b/Exam.StockManagement.Domain/Entities/DTOs/Auth/CheckEmail.cs index 70d4a96..78513fa 100644 --- a/Exam.StockManagement.Domain/Entities/DTOs/Auth/CheckEmail.cs +++ b/Exam.StockManagement.Domain/Entities/DTOs/Auth/CheckEmail.cs @@ -1,11 +1,15 @@ using DataAnnotationsExtensions; +using System.ComponentModel.DataAnnotations; namespace Exam.StockManagement.Domain.Entities.DTOs.Auth { public class CheckEmail { + [Required] [Email] - public string Email { get; set; } - public string Code { get; set; } + public string? Email { get; set; } + [Required] + [Length(4, 4)] + public string? Code { get; set; } } } diff --git a/Exam.StockManagement.Domain/Entities/DTOs/Auth/RegisterLogin.cs b/Exam.StockManagement.Domain/Entities/DTOs/Auth/RegisterLogin.cs deleted file mode 100644 index 9f3d01f..0000000 --- a/Exam.StockManagement.Domain/Entities/DTOs/Auth/RegisterLogin.cs +++ /dev/null @@ -1,11 +0,0 @@ -using DataAnnotationsExtensions; - -namespace Exam.StockManagement.Domain.Entities.DTOs.Auth -{ - public class RegisterLogin - { - [Email] - public string? Email { get; set; } - public string? Code { get; set; } - } -} diff --git a/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestLogin.cs b/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestLogin.cs index decdf62..d961261 100644 --- a/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestLogin.cs +++ b/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestLogin.cs @@ -1,11 +1,15 @@ using DataAnnotationsExtensions; +using System.ComponentModel.DataAnnotations; namespace Exam.StockManagement.Domain.Entities.DTOs.Auth { public class RequestLogin { + [Required] [Email] public string Email { get; set; } + [Required] + [Length(8, 16)] public string Password { get; set; } } } \ No newline at end of file diff --git a/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestSignUp.cs b/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestSignUp.cs index cc5e229..fa70e0b 100644 --- a/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestSignUp.cs +++ b/Exam.StockManagement.Domain/Entities/DTOs/Auth/RequestSignUp.cs @@ -1,11 +1,22 @@ +using DataAnnotationsExtensions; +using System.ComponentModel.DataAnnotations; + namespace Exam.StockManagement.Domain.Entities.DTOs.Auth { public class RequestSignUp { + [Required] public required string? Name { get; set; } + [Required] + [Email] public required string? Email { get; set; } + [Required] + [Length(8, 16)] public required string Password { get; set; } + [Required] + [Length(8, 16)] public required string ConfirmPassword { get; set; } + [Required] public required string Role { get; set; } } } diff --git a/Exam.StockManagement.Domain/Entities/DTOs/ProductDTO.cs b/Exam.StockManagement.Domain/Entities/DTOs/ProductDTO.cs index 401720d..d6ccfe7 100644 --- a/Exam.StockManagement.Domain/Entities/DTOs/ProductDTO.cs +++ b/Exam.StockManagement.Domain/Entities/DTOs/ProductDTO.cs @@ -1,11 +1,15 @@ using Microsoft.AspNetCore.Http; +using System.ComponentModel.DataAnnotations; namespace Exam.StockManagement.Domain.Entities.DTOs { public class ProductDTO { + [Required] public required string ProductName { get; set; } + [Required] public required int CategoryId { get; set; } + [Required] public required int ProductPrice { get; set; } public string? ProductDescription { get; set; } public required IFormFile ProductPicture { get; set; } diff --git a/Exam.StockManagement.Domain/Entities/DTOs/UserDTO.cs b/Exam.StockManagement.Domain/Entities/DTOs/UserDTO.cs index fc3b392..02f293e 100644 --- a/Exam.StockManagement.Domain/Entities/DTOs/UserDTO.cs +++ b/Exam.StockManagement.Domain/Entities/DTOs/UserDTO.cs @@ -1,13 +1,18 @@ -using DataAnnotationsExtensions; +using System.ComponentModel.DataAnnotations; namespace Exam.StockManagement.Domain.Entities.DTOs { public class UserDTO { + //required'larga tekshirdim lekin package'dan qandaydir ogohlantirish bor + + [Required] public string? Name { get; set; } - [Email] + [Required] public string? Email { get; set; } + [Required] public string Password { get; set; } - public string Role { get; set; } + [Required] + public string? Role { get; set; } } } diff --git a/Exam.StockManagement.Domain/Entities/Models/Category.cs b/Exam.StockManagement.Domain/Entities/Models/Category.cs index ed14b75..3815738 100644 --- a/Exam.StockManagement.Domain/Entities/Models/Category.cs +++ b/Exam.StockManagement.Domain/Entities/Models/Category.cs @@ -1,8 +1,11 @@ +using System.ComponentModel.DataAnnotations; + namespace Exam.StockManagement.Domain.Entities.Models { public class Category { public int CategoryId { get; set; } + [Required] public string CategoryName { get; set; } } } diff --git a/Exam.StockManagement.Domain/Entities/Models/Product.cs b/Exam.StockManagement.Domain/Entities/Models/Product.cs index dfb1df9..9041f77 100644 --- a/Exam.StockManagement.Domain/Entities/Models/Product.cs +++ b/Exam.StockManagement.Domain/Entities/Models/Product.cs @@ -1,14 +1,18 @@ using Exam.StockManagement.Domain.Entities.Common; +using System.ComponentModel.DataAnnotations; namespace Exam.StockManagement.Domain.Entities.Models { public class Product : Auditable { + [Required] public string ProductName { get; set; } + [Required] public int CategoryId { get; set; } + [Required] public int ProductPrice { get; set; } - public string ProductDescription { get; set; } - public string ProductPicture { get; set; } + public string? ProductDescription { get; set; } + public string? ProductPicture { get; set; } public Category Category { get; set; } } diff --git a/Exam.StockManagement.Domain/Entities/Models/User.cs b/Exam.StockManagement.Domain/Entities/Models/User.cs index 3b7352d..2d1b193 100644 --- a/Exam.StockManagement.Domain/Entities/Models/User.cs +++ b/Exam.StockManagement.Domain/Entities/Models/User.cs @@ -13,7 +13,8 @@ public class User : Auditable public string? Email { get; set; } [Required] public string Password { get; set; } - public string? Code { get; set; } + public string? Salt { get; set; } + [Required] public string? Role { get; set; } } } diff --git a/Exam.StockManagement.Domain/Entities/ViewModels/UserViewModel.cs b/Exam.StockManagement.Domain/Entities/ViewModels/UserViewModel.cs index cb256fd..d6b2f02 100644 --- a/Exam.StockManagement.Domain/Entities/ViewModels/UserViewModel.cs +++ b/Exam.StockManagement.Domain/Entities/ViewModels/UserViewModel.cs @@ -4,6 +4,6 @@ public class UserViewModel { public string? Name { get; set; } public string? Email { get; set; } - public string Role { get; set; } + public string? Role { get; set; } } } diff --git a/Exam.StockManagement.Infrastructure/DependencyInjection.cs b/Exam.StockManagement.Infrastructure/DependencyInjection.cs index cd81d77..169fb12 100644 --- a/Exam.StockManagement.Infrastructure/DependencyInjection.cs +++ b/Exam.StockManagement.Infrastructure/DependencyInjection.cs @@ -22,9 +22,6 @@ public static IServiceCollection AddInfrastructure(this IServiceCollection servi services.AddScoped(); services.AddScoped(); - - //services.AddScoped(); - //services.AddScoped, BaseRepository>(); return services; } } diff --git a/Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.Designer.cs b/Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.Designer.cs new file mode 100644 index 0000000..c66bc52 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.Designer.cs @@ -0,0 +1,131 @@ +// +using System; +using Exam.StockManagement.Infrastructure.Persistance; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Exam.StockManagement.Infrastructure.Migrations +{ + [DbContext(typeof(StockManagementDbContext))] + [Migration("20240304162731_add-attribute")] + partial class addattribute + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CategoryName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("CategoryId"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ProductDescription") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ProductName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ProductPicture") + .HasColumnType("text"); + + b.Property("ProductPrice") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(16) + .HasColumnType("character varying(16)") + .HasAnnotation("MinLength", 8); + + b.Property("Role") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Product", b => + { + b.HasOne("Exam.StockManagement.Domain.Entities.Models.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.cs b/Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.cs new file mode 100644 index 0000000..92510d3 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Migrations/20240304162731_add-attribute.cs @@ -0,0 +1,210 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Exam.StockManagement.Infrastructure.Migrations +{ + /// + public partial class addattribute : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Stats"); + + migrationBuilder.DropColumn( + name: "Code", + table: "Users"); + + migrationBuilder.AlterColumn( + name: "Role", + table: "Users", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Password", + table: "Users", + type: "character varying(16)", + maxLength: 16, + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "Name", + table: "Users", + type: "character varying(30)", + maxLength: 30, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Email", + table: "Users", + type: "character varying(50)", + maxLength: 50, + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProductPicture", + table: "Products", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "ProductName", + table: "Products", + type: "character varying(30)", + maxLength: 30, + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "ProductDescription", + table: "Products", + type: "character varying(100)", + maxLength: 100, + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "CategoryName", + table: "Categories", + type: "character varying(30)", + maxLength: 30, + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Role", + table: "Users", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "Password", + table: "Users", + type: "text", + nullable: false, + oldClrType: typeof(string), + oldType: "character varying(16)", + oldMaxLength: 16); + + migrationBuilder.AlterColumn( + name: "Name", + table: "Users", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(30)", + oldMaxLength: 30); + + migrationBuilder.AlterColumn( + name: "Email", + table: "Users", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(50)", + oldMaxLength: 50); + + migrationBuilder.AddColumn( + name: "Code", + table: "Users", + type: "text", + nullable: true); + + migrationBuilder.AlterColumn( + name: "ProductPicture", + table: "Products", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ProductName", + table: "Products", + type: "text", + nullable: false, + oldClrType: typeof(string), + oldType: "character varying(30)", + oldMaxLength: 30); + + migrationBuilder.AlterColumn( + name: "ProductDescription", + table: "Products", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(100)", + oldMaxLength: 100, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CategoryName", + table: "Categories", + type: "text", + nullable: false, + oldClrType: typeof(string), + oldType: "character varying(30)", + oldMaxLength: 30); + + migrationBuilder.CreateTable( + name: "Stats", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + ProductId = table.Column(type: "integer", nullable: false), + ProductCategoryQuantity = table.Column(type: "integer", nullable: false), + ProductCategorySum = table.Column(type: "integer", nullable: false), + ProductQuantity = table.Column(type: "integer", nullable: false), + ProductSum = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Stats", x => x.Id); + table.ForeignKey( + name: "FK_Stats_Products_ProductId", + column: x => x.ProductId, + principalTable: "Products", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Stats_ProductId", + table: "Stats", + column: "ProductId"); + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.Designer.cs b/Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.Designer.cs new file mode 100644 index 0000000..6848969 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.Designer.cs @@ -0,0 +1,130 @@ +// +using System; +using Exam.StockManagement.Infrastructure.Persistance; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Exam.StockManagement.Infrastructure.Migrations +{ + [DbContext(typeof(StockManagementDbContext))] + [Migration("20240304175433_change-type-for-password")] + partial class changetypeforpassword + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CategoryName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("CategoryId"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ProductDescription") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ProductName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ProductPicture") + .HasColumnType("text"); + + b.Property("ProductPrice") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("text"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Product", b => + { + b.HasOne("Exam.StockManagement.Domain.Entities.Models.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.cs b/Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.cs new file mode 100644 index 0000000..14871a4 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Migrations/20240304175433_change-type-for-password.cs @@ -0,0 +1,54 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Exam.StockManagement.Infrastructure.Migrations +{ + /// + public partial class changetypeforpassword : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Role", + table: "Users", + type: "character varying(20)", + maxLength: 20, + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + + migrationBuilder.AlterColumn( + name: "Password", + table: "Users", + type: "text", + nullable: false, + oldClrType: typeof(string), + oldType: "character varying(16)", + oldMaxLength: 16); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Role", + table: "Users", + type: "text", + nullable: false, + oldClrType: typeof(string), + oldType: "character varying(20)", + oldMaxLength: 20); + + migrationBuilder.AlterColumn( + name: "Password", + table: "Users", + type: "character varying(16)", + maxLength: 16, + nullable: false, + oldClrType: typeof(string), + oldType: "text"); + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.Designer.cs b/Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.Designer.cs new file mode 100644 index 0000000..5fd0746 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.Designer.cs @@ -0,0 +1,133 @@ +// +using System; +using Exam.StockManagement.Infrastructure.Persistance; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Exam.StockManagement.Infrastructure.Migrations +{ + [DbContext(typeof(StockManagementDbContext))] + [Migration("20240304182915_update-colulmn-user")] + partial class updatecolulmnuser + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Category", b => + { + b.Property("CategoryId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CategoryId")); + + b.Property("CategoryName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("CategoryId"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ProductDescription") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ProductName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ProductPicture") + .HasColumnType("text"); + + b.Property("ProductPrice") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("text"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Salt") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Product", b => + { + b.HasOne("Exam.StockManagement.Domain.Entities.Models.Category", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.cs b/Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.cs new file mode 100644 index 0000000..a34ee12 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Migrations/20240304182915_update-colulmn-user.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Exam.StockManagement.Infrastructure.Migrations +{ + /// + public partial class updatecolulmnuser : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Salt", + table: "Users", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Salt", + table: "Users"); + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Migrations/StockManagementDbContextModelSnapshot.cs b/Exam.StockManagement.Infrastructure/Migrations/StockManagementDbContextModelSnapshot.cs index d77a5b9..12c2a0e 100644 --- a/Exam.StockManagement.Infrastructure/Migrations/StockManagementDbContextModelSnapshot.cs +++ b/Exam.StockManagement.Infrastructure/Migrations/StockManagementDbContextModelSnapshot.cs @@ -32,7 +32,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CategoryName") .IsRequired() - .HasColumnType("text"); + .HasMaxLength(30) + .HasColumnType("character varying(30)"); b.HasKey("CategoryId"); @@ -54,15 +55,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp with time zone"); b.Property("ProductDescription") - .IsRequired() - .HasColumnType("text"); + .HasMaxLength(100) + .HasColumnType("character varying(100)"); b.Property("ProductName") .IsRequired() - .HasColumnType("text"); + .HasMaxLength(30) + .HasColumnType("character varying(30)"); b.Property("ProductPicture") - .IsRequired() .HasColumnType("text"); b.Property("ProductPrice") @@ -75,36 +76,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Products"); }); - modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Stats", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ProductCategoryQuantity") - .HasColumnType("integer"); - - b.Property("ProductCategorySum") - .HasColumnType("integer"); - - b.Property("ProductId") - .HasColumnType("integer"); - - b.Property("ProductQuantity") - .HasColumnType("integer"); - - b.Property("ProductSum") - .HasColumnType("integer"); - - b.HasKey("Id"); - - b.HasIndex("ProductId"); - - b.ToTable("Stats"); - }); - modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.User", b => { b.Property("Id") @@ -113,23 +84,29 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - b.Property("Code") - .HasColumnType("text"); - b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); b.Property("Email") - .HasColumnType("text"); + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); b.Property("Name") - .HasColumnType("text"); + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); b.Property("Password") .IsRequired() .HasColumnType("text"); b.Property("Role") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.Property("Salt") .HasColumnType("text"); b.HasKey("Id"); @@ -147,17 +124,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Category"); }); - - modelBuilder.Entity("Exam.StockManagement.Domain.Entities.Models.Stats", b => - { - b.HasOne("Exam.StockManagement.Domain.Entities.Models.Product", "Product") - .WithMany() - .HasForeignKey("ProductId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Product"); - }); #pragma warning restore 612, 618 } } diff --git a/Exam.StockManagement.Infrastructure/Persistance/Configuration/CategoryConfig.cs b/Exam.StockManagement.Infrastructure/Persistance/Configuration/CategoryConfig.cs new file mode 100644 index 0000000..227d8b4 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Persistance/Configuration/CategoryConfig.cs @@ -0,0 +1,15 @@ +using Exam.StockManagement.Domain.Entities.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Exam.StockManagement.Infrastructure.Persistance.Configuration +{ + public class CategoryConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.Property(x => x.CategoryName) + .HasMaxLength(30); + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Persistance/Configuration/ProductConfig.cs b/Exam.StockManagement.Infrastructure/Persistance/Configuration/ProductConfig.cs new file mode 100644 index 0000000..c62ec12 --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Persistance/Configuration/ProductConfig.cs @@ -0,0 +1,18 @@ +using Exam.StockManagement.Domain.Entities.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Exam.StockManagement.Infrastructure.Persistance.Configuration +{ + public class ProductConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.Property(x => x.ProductName) + .HasMaxLength(30); + + builder.Property(x => x.ProductDescription) + .HasMaxLength(100); + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Persistance/Configuration/UserConfig.cs b/Exam.StockManagement.Infrastructure/Persistance/Configuration/UserConfig.cs new file mode 100644 index 0000000..fb5cd9a --- /dev/null +++ b/Exam.StockManagement.Infrastructure/Persistance/Configuration/UserConfig.cs @@ -0,0 +1,21 @@ +using Exam.StockManagement.Domain.Entities.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Exam.StockManagement.Infrastructure.Persistance.Configuration +{ + public class UserConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.Property(x => x.Name) + .HasMaxLength(30); + + builder.Property(x => x.Email) + .HasMaxLength(50); + + builder.Property(x => x.Role) + .HasMaxLength(20); + } + } +} diff --git a/Exam.StockManagement.Infrastructure/Persistance/StockManagementDbContext.cs b/Exam.StockManagement.Infrastructure/Persistance/StockManagementDbContext.cs index c318de4..2c64341 100644 --- a/Exam.StockManagement.Infrastructure/Persistance/StockManagementDbContext.cs +++ b/Exam.StockManagement.Infrastructure/Persistance/StockManagementDbContext.cs @@ -1,5 +1,6 @@ using Exam.StockManagement.Domain.Entities.Models; using Microsoft.EntityFrameworkCore; +using System.Reflection; namespace Exam.StockManagement.Infrastructure.Persistance { @@ -15,5 +16,12 @@ public StockManagementDbContext(DbContextOptions optio public virtual DbSet Users { get; set; } public virtual DbSet Products { get; set; } public virtual DbSet Categories { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); + } } }