From cd37fd2c152fce45a587b29a1763255c5cc2a9b2 Mon Sep 17 00:00:00 2001 From: MarcEricMartel <74071476+MarcEricMartel@users.noreply.github.com> Date: Tue, 1 Nov 2022 10:33:08 -0700 Subject: [PATCH] =?UTF-8?q?Renvoit=20du=20r=C3=B4le=20au=20frontend=20avec?= =?UTF-8?q?=20Get=20Login=20(UPDATE-DATABASE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/InventoryController.cs | 30 +-- .../Controllers/LoginController.cs | 15 +- .../Controllers/ProductController.cs | 6 +- .../Controllers/SearchController.cs | 18 +- .../Data/InventoryContext.cs | 112 ++++++--- .../GrossesMitainesAPI/Data/InventoryUser.cs | 29 +-- ... => 20221101172005_Initial.Db.Designer.cs} | 223 +++++++++++++++++- ...ial-Db.cs => 20221101172005_Initial.Db.cs} | 142 ++++++++++- .../InventoryContextModelSnapshot.cs | 221 ++++++++++++++++- .../GrossesMitainesAPI/Models/AddressModel.cs | 22 ++ .../GrossesMitainesAPI/Models/InvoiceModel.cs | 34 ++- .../Models/{Product.cs => ProductModel.cs} | 2 +- .../Models/ProductViewModel.cs | 4 +- .../Models/ReturnUserViewModel.cs | 9 +- GrossesMitaines/GrossesMitainesAPI/Program.cs | 5 +- .../Services/DatabaseCacheService.cs | 14 +- 16 files changed, 761 insertions(+), 125 deletions(-) rename GrossesMitaines/GrossesMitainesAPI/Migrations/{20221030195130_Initial-Db.Designer.cs => 20221101172005_Initial.Db.Designer.cs} (73%) rename GrossesMitaines/GrossesMitainesAPI/Migrations/{20221030195130_Initial-Db.cs => 20221101172005_Initial.Db.cs} (66%) create mode 100644 GrossesMitaines/GrossesMitainesAPI/Models/AddressModel.cs rename GrossesMitaines/GrossesMitainesAPI/Models/{Product.cs => ProductModel.cs} (97%) diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs index dd61767..65484b1 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs @@ -63,35 +63,35 @@ public class InventoryController : Controller { } switch (filterState) { case "isAvailable": - ret = ret.Where(x => x.Status == Product.States.Available); + ret = ret.Where(x => x.Status == ProductModel.States.Available); break; case "isUnavailable": - ret = ret.Where(x => x.Status == Product.States.Unavailable); + ret = ret.Where(x => x.Status == ProductModel.States.Unavailable); break; case "isBackOrder": - ret = ret.Where(x => x.Status == Product.States.BackOrder); + ret = ret.Where(x => x.Status == ProductModel.States.BackOrder); break; ; case "isClearance": - ret = ret.Where(x => x.Status == Product.States.Clearance); + ret = ret.Where(x => x.Status == ProductModel.States.Clearance); break; case "isDiscontinued": - ret = ret.Where(x => x.Status == Product.States.Discontinued); + ret = ret.Where(x => x.Status == ProductModel.States.Discontinued); break; case "isPromoted": - ret = ret.Where(x => x.Status == Product.States.Clearance || - x.Status == Product.States.Promotion); + ret = ret.Where(x => x.Status == ProductModel.States.Clearance || + x.Status == ProductModel.States.Promotion); break; default: break; } switch (order) { case "Price": - ret = ret.OrderBy(x => x.Status == Product.States.Promotion || - x.Status == Product.States.Clearance ? + ret = ret.OrderBy(x => x.Status == ProductModel.States.Promotion || + x.Status == ProductModel.States.Clearance ? x.PromoPrice : x.Price); break; case "PriceDesc": - ret = ret.OrderByDescending(x => x.Status == Product.States.Promotion || - x.Status == Product.States.Clearance ? + ret = ret.OrderByDescending(x => x.Status == ProductModel.States.Promotion || + x.Status == ProductModel.States.Clearance ? x.PromoPrice : x.Price); break; case "Title": @@ -140,16 +140,16 @@ public class InventoryController : Controller { return BadRequest(); } try { - Product prod = _context.Products.First(x => x.Id == id); + ProductModel prod = _context.Products.First(x => x.Id == id); rid = prod.Id; if (prod.Quantity > 0) { prod.Quantity = prod.Quantity - 1; prod.Sales = prod.Sales + 1; prod.LastSale = DateTime.Now; if (prod.Quantity == 0) - prod.Status = prod.Status == Product.States.Clearance ? - Product.States.Discontinued : - Product.States.BackOrder; + prod.Status = prod.Status == ProductModel.States.Clearance ? + ProductModel.States.Discontinued : + ProductModel.States.BackOrder; } else { _logger.LogError(8, $"Vente de produit pas en stock. Id Produit: {prod.Id}"); return BadRequest(); diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/LoginController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/LoginController.cs index 0f5e2a7..7298bac 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Controllers/LoginController.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/LoginController.cs @@ -14,11 +14,13 @@ using GrossesMitainesAPI.Models; Authorize(AuthenticationSchemes = "Identity.Application")] public class LoginController : Controller { private readonly UserManager _userMan; + private readonly RoleManager _roleMan; private readonly SignInManager _signInMan; - public LoginController(SignInManager signin, UserManager userman) { + public LoginController(SignInManager signin, UserManager userman, RoleManager roleMan) { this._signInMan = signin; this._userMan = userman; + this._roleMan = roleMan; } public class LoginUser { @@ -28,9 +30,16 @@ public class LoginController : Controller { [HttpGet, Route("Login")] public ReturnUserViewModel WhoAmI() { - var user = _userMan.GetUserAsync(_signInMan.Context.User); + var user = _userMan.GetUserAsync(_signInMan.Context.User); user.Wait(); - return new ReturnUserViewModel(user.Result); + var roles = _userMan.GetRolesAsync(user.Result); + roles.Wait(); + + string role = ""; + if (roles.Result.Contains("Administrateur")) + role = "Administrateur"; + else role = "Client"; + return new ReturnUserViewModel(user.Result, role); } [HttpPost, Route("Login"), AllowAnonymous] diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs index a09f78c..05e8b20 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs @@ -44,7 +44,7 @@ public class ProductController : ControllerBase { #region API Methods [EnableCors("_myAllowSpecificOrigins"), HttpGet(Name = "Product"), AllowAnonymous] public ActionResult Get(int id) { - Product prod; + ProductModel prod; try { prod = _context.Products.Where(x => x.Id == id).First(); } @@ -57,7 +57,7 @@ public class ProductController : ControllerBase { } [EnableCors("_myAllowSpecificOrigins"), HttpPost(Name = "Product")] - public async Task> Post(Product prod) { + public async Task> Post(ProductModel prod) { if (prod.Price <= prod.PromoPrice) prod.PromoPrice = prod.Price - 0.01M; try { @@ -76,7 +76,7 @@ public class ProductController : ControllerBase { } [EnableCors("_myAllowSpecificOrigins"), HttpPatch(Name = "Product")] - public ActionResult Patch(Product prod) { + public ActionResult Patch(ProductModel prod) { try { _context.Products.Update(prod); _context.SaveChanges(); diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs index 227bce2..9d2704d 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs @@ -25,7 +25,7 @@ public class SearchController : Controller { private readonly ILogger _logger; private readonly InventoryContext _context; private readonly DatabaseCacheService _cache; - private IQueryable? _searchCache = null; + private IQueryable? _searchCache = null; #endregion @@ -81,22 +81,22 @@ public class SearchController : Controller { } switch (filterState) { case "isAvailable": - ret = ret.Where(x => x.Status == Product.States.Available); + ret = ret.Where(x => x.Status == ProductModel.States.Available); break; case "isUnavailable": - ret = ret.Where(x => x.Status == Product.States.Unavailable); + ret = ret.Where(x => x.Status == ProductModel.States.Unavailable); break; case "isBackOrder": - ret = ret.Where(x => x.Status == Product.States.BackOrder); + ret = ret.Where(x => x.Status == ProductModel.States.BackOrder); break; ; case "isClearance": - ret = ret.Where(x => x.Status == Product.States.Clearance); + ret = ret.Where(x => x.Status == ProductModel.States.Clearance); break; case "isDiscontinued": - ret = ret.Where(x => x.Status == Product.States.Discontinued); + ret = ret.Where(x => x.Status == ProductModel.States.Discontinued); break; case "isPromoted": - ret = ret.Where(x => x.Status == Product.States.Clearance || x.Status == Product.States.Promotion); + ret = ret.Where(x => x.Status == ProductModel.States.Clearance || x.Status == ProductModel.States.Promotion); break; default: break; } @@ -122,10 +122,10 @@ public class SearchController : Controller { products.AddRange(cat); break; case "Price": - ret = ret.OrderBy(x => x.Status == Product.States.Promotion || x.Status == Product.States.Clearance ? x.PromoPrice : x.Price); + ret = ret.OrderBy(x => x.Status == ProductModel.States.Promotion || x.Status == ProductModel.States.Clearance ? x.PromoPrice : x.Price); goto default; case "PriceDesc": - ret = ret.OrderByDescending(x => x.Status == Product.States.Promotion || x.Status == Product.States.Clearance ? x.PromoPrice : x.Price); + ret = ret.OrderByDescending(x => x.Status == ProductModel.States.Promotion || x.Status == ProductModel.States.Clearance ? x.PromoPrice : x.Price); goto default; case "Title": ret = ret.OrderBy(x => x.Title); diff --git a/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs index 234494f..e4a9730 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs @@ -6,205 +6,243 @@ using Microsoft.AspNetCore.Identity; namespace GrossesMitainesAPI.Data; public class InventoryContext : IdentityDbContext { - public DbSet Products { get; set; } + public DbSet Products { get; set; } + public DbSet Addresses { get; set; } + public DbSet Invoices { get; set; } + public InventoryContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { - base.OnModelCreating(modelBuilder); + // Pour partir la BD. - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 1, Title = $"Ceinture flèchée", Category = $"Linge", Description = $"Pour faire votre propre bonhomme de 1837, comme dans le bon vieux temps.", - Status = Product.States.Promotion, + Status = ProductModel.States.Promotion, Price = 85.86M, PromoPrice = 29.99M, Quantity = 1, ImageName = $"ceintureflechee" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 2, Title = $"Pantoufles du Canadien en Phentex", Category = $"Linge", Description = $"Parce que ça sent la coupe!", - Status = Product.States.Available, + Status = ProductModel.States.Available, Price = 15.64M, PromoPrice = 9.99M, Quantity = 54, ImageName = $"pantouflesCH" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 3, Title = $"Jean-Luc Mongrain", Category = $"Homme", Description = $"On ne lui ferait pas mal, en tout cas!!", - Status = Product.States.Clearance, + Status = ProductModel.States.Clearance, Price = 1453.12M, PromoPrice = 999.99M, Quantity = 1, ImageName = $"jeanlucmongrain" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 4, Title = $"T-Shirt", Category = $"Linge", Description = $"Tellement simple et comfortable.", - Status = Product.States.Available, + Status = ProductModel.States.Available, Price = 12.12M, PromoPrice = 9.99M, Quantity = 143, ImageName = $"tshirt" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 5, Title = $"Mitaines", Category = $"Vêtement d'extérieur", Description = $"Deux pour un!", - Status = Product.States.Available, + Status = ProductModel.States.Available, Price = 8.18M, PromoPrice = 6.99M, Quantity = 1423, ImageName = $"mitaines" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 6, Title = $"Foulard", Category = $"Vêtement d'extérieur", Description = $"Deux pour un!", - Status = Product.States.Promotion, + Status = ProductModel.States.Promotion, Price = 10.56M, PromoPrice = 8.99M, Quantity = 14, ImageName = $"foulard" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 7, Title = $"Jock-Strap en phentex", Category = $"Sous-Vêtement", Description = $"Pour garder le p'tit bout au chaud.", - Status = Product.States.Promotion, + Status = ProductModel.States.Promotion, Price = 15.45M, PromoPrice = 12.99M, Quantity = 144, ImageName = $"kokin" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 8, Title = $"Jock-Strap féminin en phentex", Category = $"Sous-Vêtement", Description = $"Pour garder l'absence de p'tit bout au chaud.", - Status = Product.States.Promotion, + Status = ProductModel.States.Promotion, Price = 15.45M, PromoPrice = 12.99M, Quantity = 224, ImageName = $"kokin" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 9, Title = $"Bibi", Category = $"Alien", Description = $"En chiffon.", - Status = Product.States.Clearance, + Status = ProductModel.States.Clearance, Price = 1045.45M, PromoPrice = 1023.99M, Quantity = 1, ImageName = $"bibi" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 10, Title = $"Tuque en laine", Category = $"Vêtement d'extérieur", Description = $"En chiffon.", - Status = Product.States.Available, + Status = ProductModel.States.Available, Price = 15.45M, PromoPrice = 12.99M, Quantity = 1, ImageName = $"tuque" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 11, Title = $"Habit de Bonhomme Carnaval", Category = $"Vêtement d'extérieur", Description = $"Pour se faire taper dessus avec une poêle à frire tout en restant au chaud.", - Status = Product.States.Promotion, + Status = ProductModel.States.Promotion, Price = 145.45M, PromoPrice = 123.99M, Quantity = 1, ImageName = $"bonhomme" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 12, Title = $"Gauze en phentex", Category = $"Autre", Description = $"Pour se pêter la fiole avec style.", - Status = Product.States.BackOrder, + Status = ProductModel.States.BackOrder, Price = 145.45M, PromoPrice = 123.99M, Quantity = 0, ImageName = $"gauze" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 13, Title = $"Petit Jésus de plâtre", Category = $"Homme", Description = $"En chiffon.", - Status = Product.States.Clearance, + Status = ProductModel.States.Clearance, Price = 145.45M, PromoPrice = 123.99M, Quantity = 1, ImageName = $"jesus" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 14, Title = $"VHS de la Guerre des Tuques", Category = $"Autre", Description = $"À écouter dans l'habit de Bonhomme Carnaval tant que possible.", - Status = Product.States.Clearance, + Status = ProductModel.States.Clearance, Price = 3.45M, PromoPrice = 1.99M, Quantity = 164363, ImageName = $"vhs" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 15, Title = $"Gilet pare-balle en laine", Category = $"Linge", Description = $"(N'est pas réellement pare-balle).", - Status = Product.States.Clearance, + Status = ProductModel.States.Clearance, Price = 1435.45M, PromoPrice = 1223.99M, Quantity = 18, ImageName = $"chandailquetaine" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 16, Title = $"Doudou", Category = $"Autre", Description = $"Pour s'éffoirer le nez dedans.", - Status = Product.States.Available, + Status = ProductModel.States.Available, Price = 14.45M, PromoPrice = 13.99M, Quantity = 14, ImageName = $"doudou" }); - modelBuilder.Entity().HasData(new Product { + modelBuilder.Entity().HasData(new ProductModel { Id = 17, Title = $"Mitaines pas de doigts", Category = $"Vêtements d'extérieur", Description = $"Pour avoir l'air thug en hiver.", - Status = Product.States.Available, + Status = ProductModel.States.Available, Price = 9.45M, PromoPrice = 8.99M, Quantity = 16, ImageName = $"mitaines2" }); - InventoryUser admin = new InventoryUser() { NormalizedUserName = "admin", UserName = "Admin", NormalizedEmail = "admin@admin.com", Email = "admin@admin.com" }; + // Source: Notre TP Web 4DW. + string AdministrateurID = "c9e08b20-d8a5-473f-9f52-572eb23c12af"; + string ClientID = "1b7b9c55-c746-493a-a24f-3d5ca937298e"; + string AdminID = "ecf7503a-591c-454e-a824-048e10bd0474"; + + InventoryUser admin = new InventoryUser() { + FirstName = "Roger", + LastName = "Admin", + NormalizedUserName = "ADMIN", + UserName = "Admin", + Id = AdminID, + NormalizedEmail = "ADMIN@ADMIN.COM", + Email = "admin@admin.com" + }; + + //admin.Adresses.Add(new AddressModel() { + // CivicNumber = 1234, + // Appartment = "B", + // Street = "Rue Pierre-Falardeau", + // City = "Saint-Chrysostome", + // PostalCode = "H0H0H0", + // Province = "QC", + // Country = "Canada" + //}); + admin.PasswordHash = new PasswordHasher().HashPassword(admin, "Qwerty123!"); modelBuilder.Entity().HasData(admin); + modelBuilder.Entity().HasData( + new IdentityRole { Id = AdministrateurID, Name = "Administrateur", NormalizedName = "ADMINISTRATEUR" }, + new IdentityRole { Id = ClientID, Name = "Client", NormalizedName = "CLIENT" } + ); + + modelBuilder.Entity>().HasData( + new IdentityUserRole { RoleId = AdministrateurID, UserId = AdminID }, + new IdentityUserRole { RoleId = ClientID, UserId = AdminID } + ); + + base.OnModelCreating(modelBuilder); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { var configuration = new ConfigurationBuilder() diff --git a/GrossesMitaines/GrossesMitainesAPI/Data/InventoryUser.cs b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryUser.cs index 4f25639..98ad9cb 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Data/InventoryUser.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryUser.cs @@ -1,28 +1,13 @@ using Microsoft.AspNetCore.Identity; using System.ComponentModel.DataAnnotations; +using GrossesMitainesAPI.Models; namespace GrossesMitainesAPI.Data; -public class InventoryUser : IdentityUser { - public class Address { - [Key] - public int Id { get; set; } - [Required, Range(1, int.MaxValue)] - public int CivicNumber { get; set; } - public string? Appartment { get; set; } - [Required, MinLength(3), MaxLength(50)] - public string Street { get; set; } - [Required, MinLength(4), MaxLength(50)] - public string City { get; set; } - [Required, MaxLength(2)] - public string Province { get; set; } - [Required, MinLength(4), MaxLength(30)] - public string Country { get; set; } - // Source pour regex: https://stackoverflow.com/questions/15774555/efficient-regex-for-canadian-postal-code-function - [Required, RegularExpression(@"/^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d$/i")] - public string PostalCode { get; set; } - } - - public List
Adresses { get; set; } - +public class InventoryUser : IdentityUser { + [Required, MinLength(2), MaxLength(30)] + public string FirstName { get; set; } + [Required, MinLength(1), MaxLength(30)] + public string LastName { get; set; } + public List Adresses { get; set; } } diff --git a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.Designer.cs b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221101172005_Initial.Db.Designer.cs similarity index 73% rename from GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.Designer.cs rename to GrossesMitaines/GrossesMitainesAPI/Migrations/20221101172005_Initial.Db.Designer.cs index 5510b5d..57be6e1 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.Designer.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221101172005_Initial.Db.Designer.cs @@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace GrossesMitainesAPI.Migrations { [DbContext(typeof(InventoryContext))] - [Migration("20221030195130_Initial-Db")] + [Migration("20221101172005_Initial.Db")] partial class InitialDb { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -43,6 +43,16 @@ namespace GrossesMitainesAPI.Migrations b.Property("EmailConfirmed") .HasColumnType("bit"); + b.Property("FirstName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + b.Property("LockoutEnabled") .HasColumnType("bit"); @@ -91,23 +101,143 @@ namespace GrossesMitainesAPI.Migrations b.HasData( new { - Id = "809dc5fd-c62f-4d93-abe4-275a55aabd33", + Id = "ecf7503a-591c-454e-a824-048e10bd0474", AccessFailedCount = 0, - ConcurrencyStamp = "f2e55d24-1ab5-441c-87e0-808f32045ab4", + ConcurrencyStamp = "6259a59c-35df-4662-84e5-a783e653a643", Email = "admin@admin.com", EmailConfirmed = false, + FirstName = "Roger", + LastName = "Admin", LockoutEnabled = false, - NormalizedEmail = "admin@admin.com", - NormalizedUserName = "admin", - PasswordHash = "AQAAAAEAACcQAAAAEKJtYKQ3fXHUA67KkZbzgDtxdg1UlFk3kFeNj3QSm3OfgsSoMtFExAq16W5arTVmRA==", + NormalizedEmail = "ADMIN@ADMIN.COM", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAEAACcQAAAAELHpALZdYcW7KzDcU2ovqwdWsfSx68md+LnjvL5ZgJ2OWuTFwJM3gPzQ1yP3RHCn9g==", PhoneNumberConfirmed = false, - SecurityStamp = "56fc4076-5e9d-4bd1-91e7-b53abcc41fda", + SecurityStamp = "c43f4d48-f1bb-4a24-8cd3-78422556cf85", TwoFactorEnabled = false, UserName = "Admin" }); }); - modelBuilder.Entity("GrossesMitainesAPI.Models.Product", b => + modelBuilder.Entity("GrossesMitainesAPI.Models.AddressModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("Appartment") + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CivicNumber") + .HasColumnType("int"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("InventoryUserId") + .HasColumnType("nvarchar(450)"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Province") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("nvarchar(3)"); + + b.Property("Street") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("InventoryUserId"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("Canceled") + .HasColumnType("bit"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("LinkedAccountId") + .HasColumnType("nvarchar(450)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ShippingAddressId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LinkedAccountId"); + + b.HasIndex("ShippingAddressId"); + + b.ToTable("Invoices"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel+ProductInvoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("InvoiceModelId") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceModelId"); + + b.HasIndex("ProductId"); + + b.ToTable("ProductInvoice"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.ProductModel", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -425,6 +555,22 @@ namespace GrossesMitainesAPI.Migrations .HasFilter("[NormalizedName] IS NOT NULL"); b.ToTable("AspNetRoles", (string)null); + + b.HasData( + new + { + Id = "c9e08b20-d8a5-473f-9f52-572eb23c12af", + ConcurrencyStamp = "56321382-1bb3-4dfe-87bf-6919c0791765", + Name = "Administrateur", + NormalizedName = "ADMINISTRATEUR" + }, + new + { + Id = "1b7b9c55-c746-493a-a24f-3d5ca937298e", + ConcurrencyStamp = "0e3b1bc2-f632-4f63-9bea-ac995e2e95a7", + Name = "Client", + NormalizedName = "CLIENT" + }); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -512,6 +658,18 @@ namespace GrossesMitainesAPI.Migrations b.HasIndex("RoleId"); b.ToTable("AspNetUserRoles", (string)null); + + b.HasData( + new + { + UserId = "ecf7503a-591c-454e-a824-048e10bd0474", + RoleId = "c9e08b20-d8a5-473f-9f52-572eb23c12af" + }, + new + { + UserId = "ecf7503a-591c-454e-a824-048e10bd0474", + RoleId = "1b7b9c55-c746-493a-a24f-3d5ca937298e" + }); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -533,6 +691,45 @@ namespace GrossesMitainesAPI.Migrations b.ToTable("AspNetUserTokens", (string)null); }); + modelBuilder.Entity("GrossesMitainesAPI.Models.AddressModel", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany("Adresses") + .HasForeignKey("InventoryUserId"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", "LinkedAccount") + .WithMany() + .HasForeignKey("LinkedAccountId"); + + b.HasOne("GrossesMitainesAPI.Models.AddressModel", "ShippingAddress") + .WithMany() + .HasForeignKey("ShippingAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LinkedAccount"); + + b.Navigation("ShippingAddress"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel+ProductInvoice", b => + { + b.HasOne("GrossesMitainesAPI.Models.InvoiceModel", null) + .WithMany("Products") + .HasForeignKey("InvoiceModelId"); + + b.HasOne("GrossesMitainesAPI.Models.ProductModel", "Product") + .WithMany() + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -583,6 +780,16 @@ namespace GrossesMitainesAPI.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("GrossesMitainesAPI.Data.InventoryUser", b => + { + b.Navigation("Adresses"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b => + { + b.Navigation("Products"); + }); #pragma warning restore 612, 618 } } diff --git a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.cs b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221101172005_Initial.Db.cs similarity index 66% rename from GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.cs rename to GrossesMitaines/GrossesMitainesAPI/Migrations/20221101172005_Initial.Db.cs index c19c249..5218e20 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221101172005_Initial.Db.cs @@ -28,6 +28,8 @@ namespace GrossesMitainesAPI.Migrations columns: table => new { Id = table.Column(type: "nvarchar(450)", nullable: false), + FirstName = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), + LastName = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), @@ -93,6 +95,31 @@ namespace GrossesMitainesAPI.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "Addresses", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CivicNumber = table.Column(type: "int", nullable: false), + Appartment = table.Column(type: "nvarchar(max)", nullable: true), + Street = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + City = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + Province = table.Column(type: "nvarchar(3)", maxLength: 3, nullable: false), + Country = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), + PostalCode = table.Column(type: "nvarchar(max)", nullable: false), + InventoryUserId = table.Column(type: "nvarchar(450)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Addresses", x => x.Id); + table.ForeignKey( + name: "FK_Addresses_AspNetUsers_InventoryUserId", + column: x => x.InventoryUserId, + principalTable: "AspNetUsers", + principalColumn: "Id"); + }); + migrationBuilder.CreateTable( name: "AspNetUserClaims", columns: table => new @@ -178,10 +205,75 @@ namespace GrossesMitainesAPI.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "Invoices", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + FirstName = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), + LastName = table.Column(type: "nvarchar(30)", maxLength: 30, nullable: false), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: false), + EmailAddress = table.Column(type: "nvarchar(max)", nullable: false), + LinkedAccountId = table.Column(type: "nvarchar(450)", nullable: true), + ShippingAddressId = table.Column(type: "int", nullable: false), + Canceled = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Invoices", x => x.Id); + table.ForeignKey( + name: "FK_Invoices_Addresses_ShippingAddressId", + column: x => x.ShippingAddressId, + principalTable: "Addresses", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Invoices_AspNetUsers_LinkedAccountId", + column: x => x.LinkedAccountId, + principalTable: "AspNetUsers", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "ProductInvoice", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ProductId = table.Column(type: "int", nullable: false), + Quantity = table.Column(type: "int", nullable: false), + InvoiceModelId = table.Column(type: "int", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ProductInvoice", x => x.Id); + table.ForeignKey( + name: "FK_ProductInvoice_Invoices_InvoiceModelId", + column: x => x.InvoiceModelId, + principalTable: "Invoices", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_ProductInvoice_Products_ProductId", + column: x => x.ProductId, + principalTable: "Products", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.InsertData( + table: "AspNetRoles", + columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, + values: new object[,] + { + { "1b7b9c55-c746-493a-a24f-3d5ca937298e", "0e3b1bc2-f632-4f63-9bea-ac995e2e95a7", "Client", "CLIENT" }, + { "c9e08b20-d8a5-473f-9f52-572eb23c12af", "56321382-1bb3-4dfe-87bf-6919c0791765", "Administrateur", "ADMINISTRATEUR" } + }); + migrationBuilder.InsertData( table: "AspNetUsers", - columns: new[] { "Id", "AccessFailedCount", "ConcurrencyStamp", "Email", "EmailConfirmed", "LockoutEnabled", "LockoutEnd", "NormalizedEmail", "NormalizedUserName", "PasswordHash", "PhoneNumber", "PhoneNumberConfirmed", "SecurityStamp", "TwoFactorEnabled", "UserName" }, - values: new object[] { "809dc5fd-c62f-4d93-abe4-275a55aabd33", 0, "f2e55d24-1ab5-441c-87e0-808f32045ab4", "admin@admin.com", false, false, null, "admin@admin.com", "admin", "AQAAAAEAACcQAAAAEKJtYKQ3fXHUA67KkZbzgDtxdg1UlFk3kFeNj3QSm3OfgsSoMtFExAq16W5arTVmRA==", null, false, "56fc4076-5e9d-4bd1-91e7-b53abcc41fda", false, "Admin" }); + columns: new[] { "Id", "AccessFailedCount", "ConcurrencyStamp", "Email", "EmailConfirmed", "FirstName", "LastName", "LockoutEnabled", "LockoutEnd", "NormalizedEmail", "NormalizedUserName", "PasswordHash", "PhoneNumber", "PhoneNumberConfirmed", "SecurityStamp", "TwoFactorEnabled", "UserName" }, + values: new object[] { "ecf7503a-591c-454e-a824-048e10bd0474", 0, "6259a59c-35df-4662-84e5-a783e653a643", "admin@admin.com", false, "Roger", "Admin", false, null, "ADMIN@ADMIN.COM", "ADMIN", "AQAAAAEAACcQAAAAELHpALZdYcW7KzDcU2ovqwdWsfSx68md+LnjvL5ZgJ2OWuTFwJM3gPzQ1yP3RHCn9g==", null, false, "c43f4d48-f1bb-4a24-8cd3-78422556cf85", false, "Admin" }); migrationBuilder.InsertData( table: "Products", @@ -207,6 +299,21 @@ namespace GrossesMitainesAPI.Migrations { 17, "Vêtements d'extérieur", "Pour avoir l'air thug en hiver.", 0L, "mitaines2", null, null, 9.45m, 8.99m, 16L, 0L, 0, "Mitaines pas de doigts" } }); + migrationBuilder.InsertData( + table: "AspNetUserRoles", + columns: new[] { "RoleId", "UserId" }, + values: new object[] { "1b7b9c55-c746-493a-a24f-3d5ca937298e", "ecf7503a-591c-454e-a824-048e10bd0474" }); + + migrationBuilder.InsertData( + table: "AspNetUserRoles", + columns: new[] { "RoleId", "UserId" }, + values: new object[] { "c9e08b20-d8a5-473f-9f52-572eb23c12af", "ecf7503a-591c-454e-a824-048e10bd0474" }); + + migrationBuilder.CreateIndex( + name: "IX_Addresses_InventoryUserId", + table: "Addresses", + column: "InventoryUserId"); + migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", table: "AspNetRoleClaims", @@ -245,6 +352,26 @@ namespace GrossesMitainesAPI.Migrations column: "NormalizedUserName", unique: true, filter: "[NormalizedUserName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_Invoices_LinkedAccountId", + table: "Invoices", + column: "LinkedAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_Invoices_ShippingAddressId", + table: "Invoices", + column: "ShippingAddressId"); + + migrationBuilder.CreateIndex( + name: "IX_ProductInvoice_InvoiceModelId", + table: "ProductInvoice", + column: "InvoiceModelId"); + + migrationBuilder.CreateIndex( + name: "IX_ProductInvoice_ProductId", + table: "ProductInvoice", + column: "ProductId"); } protected override void Down(MigrationBuilder migrationBuilder) @@ -265,11 +392,20 @@ namespace GrossesMitainesAPI.Migrations name: "AspNetUserTokens"); migrationBuilder.DropTable( - name: "Products"); + name: "ProductInvoice"); migrationBuilder.DropTable( name: "AspNetRoles"); + migrationBuilder.DropTable( + name: "Invoices"); + + migrationBuilder.DropTable( + name: "Products"); + + migrationBuilder.DropTable( + name: "Addresses"); + migrationBuilder.DropTable( name: "AspNetUsers"); } diff --git a/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs b/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs index 1c36fd8..7648011 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs @@ -41,6 +41,16 @@ namespace GrossesMitainesAPI.Migrations b.Property("EmailConfirmed") .HasColumnType("bit"); + b.Property("FirstName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + b.Property("LockoutEnabled") .HasColumnType("bit"); @@ -89,23 +99,143 @@ namespace GrossesMitainesAPI.Migrations b.HasData( new { - Id = "809dc5fd-c62f-4d93-abe4-275a55aabd33", + Id = "ecf7503a-591c-454e-a824-048e10bd0474", AccessFailedCount = 0, - ConcurrencyStamp = "f2e55d24-1ab5-441c-87e0-808f32045ab4", + ConcurrencyStamp = "6259a59c-35df-4662-84e5-a783e653a643", Email = "admin@admin.com", EmailConfirmed = false, + FirstName = "Roger", + LastName = "Admin", LockoutEnabled = false, - NormalizedEmail = "admin@admin.com", - NormalizedUserName = "admin", - PasswordHash = "AQAAAAEAACcQAAAAEKJtYKQ3fXHUA67KkZbzgDtxdg1UlFk3kFeNj3QSm3OfgsSoMtFExAq16W5arTVmRA==", + NormalizedEmail = "ADMIN@ADMIN.COM", + NormalizedUserName = "ADMIN", + PasswordHash = "AQAAAAEAACcQAAAAELHpALZdYcW7KzDcU2ovqwdWsfSx68md+LnjvL5ZgJ2OWuTFwJM3gPzQ1yP3RHCn9g==", PhoneNumberConfirmed = false, - SecurityStamp = "56fc4076-5e9d-4bd1-91e7-b53abcc41fda", + SecurityStamp = "c43f4d48-f1bb-4a24-8cd3-78422556cf85", TwoFactorEnabled = false, UserName = "Admin" }); }); - modelBuilder.Entity("GrossesMitainesAPI.Models.Product", b => + modelBuilder.Entity("GrossesMitainesAPI.Models.AddressModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("Appartment") + .HasColumnType("nvarchar(max)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("CivicNumber") + .HasColumnType("int"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("InventoryUserId") + .HasColumnType("nvarchar(450)"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Province") + .IsRequired() + .HasMaxLength(3) + .HasColumnType("nvarchar(3)"); + + b.Property("Street") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("InventoryUserId"); + + b.ToTable("Addresses"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("Canceled") + .HasColumnType("bit"); + + b.Property("EmailAddress") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("LinkedAccountId") + .HasColumnType("nvarchar(450)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ShippingAddressId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("LinkedAccountId"); + + b.HasIndex("ShippingAddressId"); + + b.ToTable("Invoices"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel+ProductInvoice", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("InvoiceModelId") + .HasColumnType("int"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("InvoiceModelId"); + + b.HasIndex("ProductId"); + + b.ToTable("ProductInvoice"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.ProductModel", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -423,6 +553,22 @@ namespace GrossesMitainesAPI.Migrations .HasFilter("[NormalizedName] IS NOT NULL"); b.ToTable("AspNetRoles", (string)null); + + b.HasData( + new + { + Id = "c9e08b20-d8a5-473f-9f52-572eb23c12af", + ConcurrencyStamp = "56321382-1bb3-4dfe-87bf-6919c0791765", + Name = "Administrateur", + NormalizedName = "ADMINISTRATEUR" + }, + new + { + Id = "1b7b9c55-c746-493a-a24f-3d5ca937298e", + ConcurrencyStamp = "0e3b1bc2-f632-4f63-9bea-ac995e2e95a7", + Name = "Client", + NormalizedName = "CLIENT" + }); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -510,6 +656,18 @@ namespace GrossesMitainesAPI.Migrations b.HasIndex("RoleId"); b.ToTable("AspNetUserRoles", (string)null); + + b.HasData( + new + { + UserId = "ecf7503a-591c-454e-a824-048e10bd0474", + RoleId = "c9e08b20-d8a5-473f-9f52-572eb23c12af" + }, + new + { + UserId = "ecf7503a-591c-454e-a824-048e10bd0474", + RoleId = "1b7b9c55-c746-493a-a24f-3d5ca937298e" + }); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -531,6 +689,45 @@ namespace GrossesMitainesAPI.Migrations b.ToTable("AspNetUserTokens", (string)null); }); + modelBuilder.Entity("GrossesMitainesAPI.Models.AddressModel", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany("Adresses") + .HasForeignKey("InventoryUserId"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", "LinkedAccount") + .WithMany() + .HasForeignKey("LinkedAccountId"); + + b.HasOne("GrossesMitainesAPI.Models.AddressModel", "ShippingAddress") + .WithMany() + .HasForeignKey("ShippingAddressId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LinkedAccount"); + + b.Navigation("ShippingAddress"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel+ProductInvoice", b => + { + b.HasOne("GrossesMitainesAPI.Models.InvoiceModel", null) + .WithMany("Products") + .HasForeignKey("InvoiceModelId"); + + b.HasOne("GrossesMitainesAPI.Models.ProductModel", "Product") + .WithMany() + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -581,6 +778,16 @@ namespace GrossesMitainesAPI.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); + + modelBuilder.Entity("GrossesMitainesAPI.Data.InventoryUser", b => + { + b.Navigation("Adresses"); + }); + + modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b => + { + b.Navigation("Products"); + }); #pragma warning restore 612, 618 } } diff --git a/GrossesMitaines/GrossesMitainesAPI/Models/AddressModel.cs b/GrossesMitaines/GrossesMitainesAPI/Models/AddressModel.cs new file mode 100644 index 0000000..38ec3ac --- /dev/null +++ b/GrossesMitaines/GrossesMitainesAPI/Models/AddressModel.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace GrossesMitainesAPI.Models; +public class AddressModel { + [Key] + public int Id { get; set; } + [Required, Range(1, int.MaxValue)] + public int CivicNumber { get; set; } + public string? Appartment { get; set; } + [Required, MinLength(3), MaxLength(50)] + public string Street { get; set; } + [Required, MinLength(4), MaxLength(50)] + public string City { get; set; } + [Required, MaxLength(3)] + public string Province { get; set; } + [Required, MinLength(4), MaxLength(30)] + public string Country { get; set; } + // Source pour regex: https://stackoverflow.com/questions/15774555/efficient-regex-for-canadian-postal-code-function + [Required, RegularExpression(@"/^[ABCEGHJ-NPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ -]?\d[ABCEGHJ-NPRSTV-Z]\d$/i")] + public string PostalCode { get; set; } +} + diff --git a/GrossesMitaines/GrossesMitainesAPI/Models/InvoiceModel.cs b/GrossesMitaines/GrossesMitainesAPI/Models/InvoiceModel.cs index 967ce71..f5fb985 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Models/InvoiceModel.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Models/InvoiceModel.cs @@ -1,12 +1,36 @@ using GrossesMitainesAPI.Data; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; namespace GrossesMitainesAPI.Models; public class InvoiceModel { - public InventoryUser Account { get; set; } - public DateTime PurchaseDate { get; set; } - public Dictionary Products { get; set; } - public InventoryUser.Address BillingAddress { get; set; } - public InventoryUser.Address ShippingAddress { get; set; } + public class ProductInvoice { + [Key] + public int Id { get; set; } + public ProductModel Product { get; set; } + public int Quantity { get; set; } + } + + [Key] + public int Id { get; set; } + [Required, MinLength(2), MaxLength(30)] + public string FirstName { get; set; } + [Required, MinLength(1), MaxLength(30)] + public string LastName { get; set; } + [Required, Phone] + public string PhoneNumber { get; set; } + [Required, EmailAddress] + public string EmailAddress { get; set; } + public InventoryUser? LinkedAccount { get; set; } + public DateTime PurchaseDate { get; } = DateTime.Now; + [Required] + public List Products { get; set; } + + //[Required, Column("BillingAddress")] + //public AddressModel BillingAddress { get; set; } + [Required] + public AddressModel ShippingAddress { get; set; } + public bool Canceled { get; set; } = false; } diff --git a/GrossesMitaines/GrossesMitainesAPI/Models/Product.cs b/GrossesMitaines/GrossesMitainesAPI/Models/ProductModel.cs similarity index 97% rename from GrossesMitaines/GrossesMitainesAPI/Models/Product.cs rename to GrossesMitaines/GrossesMitainesAPI/Models/ProductModel.cs index d9709f0..9365dd1 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Models/Product.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Models/ProductModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations.Schema; namespace GrossesMitainesAPI.Models; -public class Product { +public class ProductModel { public enum States { Available, BackOrder, diff --git a/GrossesMitaines/GrossesMitainesAPI/Models/ProductViewModel.cs b/GrossesMitaines/GrossesMitainesAPI/Models/ProductViewModel.cs index b8acb2c..97e7071 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Models/ProductViewModel.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Models/ProductViewModel.cs @@ -1,4 +1,4 @@ -using static GrossesMitainesAPI.Models.Product; +using static GrossesMitainesAPI.Models.ProductModel; using System.ComponentModel.DataAnnotations; namespace GrossesMitainesAPI.Models; @@ -13,7 +13,7 @@ public class ProductViewModel { public States Status { get; set; } = States.Available; public string? ImageName { get; set; } - public ProductViewModel(Product prod) { + public ProductViewModel(ProductModel prod) { this.Id = prod.Id; this.Title = prod.Title; this.Category = prod.Category; diff --git a/GrossesMitaines/GrossesMitainesAPI/Models/ReturnUserViewModel.cs b/GrossesMitaines/GrossesMitainesAPI/Models/ReturnUserViewModel.cs index 110d4f4..7f87306 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Models/ReturnUserViewModel.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Models/ReturnUserViewModel.cs @@ -1,20 +1,27 @@ using GrossesMitainesAPI.Data; +using Microsoft.AspNetCore.Identity; namespace GrossesMitainesAPI.Models; public class ReturnUserViewModel { public string Username { get; set; } public string Email { get; set; } public string Phone { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } public bool EmailConfirmed { get; set; } public bool PhoneConfirmed { get; set; } public bool TwoFactorEnable { get; set; } + public string Role { get; set; } - public ReturnUserViewModel(InventoryUser user) { + public ReturnUserViewModel(InventoryUser user, string role) { Username = user.UserName; Email = user.Email; Phone = user.PhoneNumber; EmailConfirmed = user.EmailConfirmed; PhoneConfirmed = user.PhoneNumberConfirmed; TwoFactorEnable = user.TwoFactorEnabled; + FirstName = user.FirstName; + LastName = user.LastName; + Role = role; } } diff --git a/GrossesMitaines/GrossesMitainesAPI/Program.cs b/GrossesMitaines/GrossesMitainesAPI/Program.cs index d45ed1c..26972a0 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Program.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Program.cs @@ -23,8 +23,6 @@ builder.Services.AddCors(options => { }); builder.Services.AddControllers(); -builder.Services.AddAuthorization(); -builder.Services.AddAuthentication().AddIdentityCookies(); // Source: https://github.com/dotnet/aspnetcore/issues/9039 builder.Services.ConfigureApplicationCookie(o => { @@ -48,6 +46,9 @@ builder.Services.AddIdentityCore() .AddRoles() .AddEntityFrameworkStores() .AddSignInManager(); +builder.Services.AddAuthorization(); +builder.Services.AddAuthentication().AddIdentityCookies(); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs b/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs index 419e705..a5b6330 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs @@ -19,7 +19,7 @@ public class DatabaseCacheService { #endregion #region Fields - private Product[] _cache = new Product[1]; + private ProductModel[] _cache = new ProductModel[1]; private Dictionary _hits = new(); private bool _ok = false, _needUpd = true; private PeriodicTimer _timer = new PeriodicTimer(TimeSpan.FromSeconds(10)); @@ -51,7 +51,7 @@ public class DatabaseCacheService { } private bool UpdateCache() { try { - Product[] prods; + ProductModel[] prods; using (var scope = _contextFactory.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); prods = db.Products.ToArray(); @@ -75,7 +75,7 @@ public class DatabaseCacheService { List ids = hits.Keys.ToList(); using (var scope = _contextFactory.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); - List lst = db.Products.Where(x => ids.Contains((uint)x.Id)).ToList(); + List lst = db.Products.Where(x => ids.Contains((uint)x.Id)).ToList(); foreach (var x in hits) lst.First(x => x.Id == x.Id).Hits += x.Value; db.UpdateRange(lst); @@ -101,13 +101,13 @@ public class DatabaseCacheService { } } - public Product[]? GetCacheCopy() { + public ProductModel[]? GetCacheCopy() { if (!_ok) return null; - Product[] copy; + ProductModel[] copy; try { lock (_cache) { - copy = new Product[_cache.Length]; + copy = new ProductModel[_cache.Length]; _cache.CopyTo(copy, 0); } } catch (Exception e) { @@ -116,7 +116,7 @@ public class DatabaseCacheService { } return copy; } - public IQueryable queryCache() { + public IQueryable queryCache() { if (!_ok) return null; try {