diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs index 166d4f9..f76b8ea 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/InventoryController.cs @@ -12,7 +12,8 @@ using Microsoft.AspNetCore.Authorization; #endregion -[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]")] +[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]"), + Authorize(AuthenticationSchemes = "Identity.Application")] public class InventoryController : Controller { #region Constants private const int AMOUNT_SCROLL = 5; diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/LoginController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/LoginController.cs new file mode 100644 index 0000000..b57cfa8 --- /dev/null +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/LoginController.cs @@ -0,0 +1,34 @@ +namespace GrossesMitainesAPI.Controllers; + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using GrossesMitainesAPI.Data; +using SignInResult = Microsoft.AspNetCore.Identity.SignInResult; +using Microsoft.AspNetCore.Authentication.Cookies; + +[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api"), + Authorize(AuthenticationSchemes = "Identity.Application")] +public class LoginController : Controller { + //private readonly UserManager _userMan; + private readonly SignInManager _signInMan; + + public LoginController(SignInManager signin) { + this._signInMan = signin; + } + + public class User { + public string username { get; set; } + public string password { get; set; } + } + + [HttpPost, Route("Login"), AllowAnonymous] + public async Task Login(User user, bool rememberMe = false) { + return await _signInMan.PasswordSignInAsync(user.username, user.password, rememberMe, false); + } + + [HttpPost, Route("Logout")] + public void Logout() { _signInMan.SignOutAsync(); } +} + diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs index fcc01d2..0a922bc 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/ProductController.cs @@ -20,7 +20,8 @@ using GrossesMitainesAPI.Services; /// qui sera effectuée dans les 10 secondes après /// l'éxécution d'une modification de la BD. /// -[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]")] +[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]"), + Authorize(AuthenticationSchemes = "Identity.Application")] public class ProductController : ControllerBase { #region DI Fields private readonly ILogger _logger; diff --git a/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs b/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs index 1a98775..227bce2 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Controllers/SearchController.cs @@ -13,7 +13,8 @@ using System.Collections.Immutable; #endregion -[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]")] +[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]"), + Authorize(AuthenticationSchemes = "Identity.Application")] public class SearchController : Controller { #region Constants private const int PREVIEW = 4; @@ -109,11 +110,11 @@ public class SearchController : Controller { sDesc = prod.Description.Replace(".", " ").Replace(",", " ").ToLower() + " "; if (sTitle.StartsWith(query)) products.Add(prod); - else if (sTitle.Contains(" " + query + " ")) + else if (sTitle.Contains(" " + query)) title.Add(prod); - else if (sDesc.Contains(" " + query + " ")) + else if (sDesc.Contains(" " + query)) desc.Add(prod); - else if (sCat.Contains(" " + query + " ")) + else if (sCat.Contains(" " + query)) cat.Add(prod); } products.AddRange(title); diff --git a/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs index 134addc..d442f54 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryContext.cs @@ -1,9 +1,11 @@ using Microsoft.EntityFrameworkCore; using GrossesMitainesAPI.Models; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.AspNetCore.Identity; namespace GrossesMitainesAPI.Data; -public class InventoryContext : DbContext { +public class InventoryContext : IdentityDbContext { public DbSet Products { get; set; } public InventoryContext(DbContextOptions options) : base(options) { } @@ -198,6 +200,10 @@ public class InventoryContext : DbContext { Quantity = 16, ImageName = $"mitaines2" }); + + InventoryUser admin = new InventoryUser() { NormalizedUserName = "admin", UserName = "Admin", NormalizedEmail = "admin@admin.com", Email = "admin@admin.com" }; + admin.PasswordHash = new PasswordHasher().HashPassword(admin, "Qwerty123!"); + modelBuilder.Entity().HasData(admin); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { var configuration = new ConfigurationBuilder() diff --git a/GrossesMitaines/GrossesMitainesAPI/Data/InventoryUser.cs b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryUser.cs new file mode 100644 index 0000000..86cc6a5 --- /dev/null +++ b/GrossesMitaines/GrossesMitainesAPI/Data/InventoryUser.cs @@ -0,0 +1,6 @@ +using Microsoft.AspNetCore.Identity; + +namespace GrossesMitainesAPI.Data; +public class InventoryUser : IdentityUser { +} + diff --git a/GrossesMitaines/GrossesMitainesAPI/GrossesMitainesAPI.csproj b/GrossesMitaines/GrossesMitainesAPI/GrossesMitainesAPI.csproj index 7e90e24..53a4756 100644 --- a/GrossesMitaines/GrossesMitainesAPI/GrossesMitainesAPI.csproj +++ b/GrossesMitaines/GrossesMitainesAPI/GrossesMitainesAPI.csproj @@ -7,7 +7,10 @@ + + + all diff --git a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221027160052_Initial-Db.cs b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221027160052_Initial-Db.cs deleted file mode 100644 index 58fda50..0000000 --- a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221027160052_Initial-Db.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace GrossesMitainesAPI.Migrations -{ - public partial class InitialDb : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Products", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Title = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: false), - Category = table.Column(type: "nvarchar(max)", nullable: false), - Description = table.Column(type: "nvarchar(max)", nullable: false), - Price = table.Column(type: "decimal(18,2)", nullable: false), - PromoPrice = table.Column(type: "decimal(18,2)", nullable: false), - Quantity = table.Column(type: "bigint", nullable: false), - Status = table.Column(type: "int", nullable: false), - Hits = table.Column(type: "bigint", nullable: false), - Sales = table.Column(type: "bigint", nullable: false), - LastSale = table.Column(type: "datetime2", nullable: true), - LastHit = table.Column(type: "datetime2", nullable: true), - ImageName = table.Column(type: "nvarchar(max)", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Products", x => x.Id); - }); - - migrationBuilder.InsertData( - table: "Products", - columns: new[] { "Id", "Category", "Description", "Hits", "ImageName", "LastHit", "LastSale", "Price", "PromoPrice", "Quantity", "Sales", "Status", "Title" }, - values: new object[,] - { - { 1, "Linge", "Pour faire votre propre bonhomme de 1837, comme dans le bon vieux temps.", 0L, "ceintureflechee", null, null, 85.86m, 29.99m, 1L, 0L, 4, "Ceinture flèchée" }, - { 2, "Linge", "Parce que ça sent la coupe!", 0L, "pantouflesCH", null, null, 15.64m, 9.99m, 54L, 0L, 0, "Pantoufles du Canadien en Phentex" }, - { 3, "Homme", "On ne lui ferait pas mal, en tout cas!!", 0L, "jeanlucmongrain", null, null, 1453.12m, 999.99m, 1L, 0L, 3, "Jean-Luc Mongrain" }, - { 4, "Linge", "Tellement simple et comfortable.", 0L, "tshirt", null, null, 12.12m, 9.99m, 143L, 0L, 0, "T-Shirt" }, - { 5, "Vêtement d'extérieur", "Deux pour un!", 0L, "mitaines", null, null, 8.18m, 6.99m, 1423L, 0L, 0, "Mitaines" }, - { 6, "Vêtement d'extérieur", "Deux pour un!", 0L, "foulard", null, null, 10.56m, 8.99m, 14L, 0L, 4, "Foulard" }, - { 7, "Sous-Vêtement", "Pour garder le p'tit bout au chaud.", 0L, "kokin", null, null, 15.45m, 12.99m, 144L, 0L, 4, "Jock-Strap en phentex" }, - { 8, "Sous-Vêtement", "Pour garder l'absence de p'tit bout au chaud.", 0L, "kokin", null, null, 15.45m, 12.99m, 224L, 0L, 4, "Jock-Strap féminin en phentex" }, - { 9, "Alien", "En chiffon.", 0L, "bibi", null, null, 1045.45m, 1023.99m, 1L, 0L, 3, "Bibi" }, - { 10, "Vêtement d'extérieur", "En chiffon.", 0L, "tuque", null, null, 15.45m, 12.99m, 1L, 0L, 0, "Tuque en laine" }, - { 11, "Vêtement d'extérieur", "Pour se faire taper dessus avec une poêle à frire tout en restant au chaud.", 0L, "bonhomme", null, null, 145.45m, 123.99m, 1L, 0L, 4, "Habit de Bonhomme Carnaval" }, - { 12, "Autre", "Pour se pêter la fiole avec style.", 0L, "gauze", null, null, 145.45m, 123.99m, 0L, 0L, 1, "Gauze en phentex" }, - { 13, "Homme", "En chiffon.", 0L, "jesus", null, null, 145.45m, 123.99m, 1L, 0L, 3, "Petit Jésus de plâtre" }, - { 14, "Autre", "À écouter dans l'habit de Bonhomme Carnaval tant que possible.", 0L, "vhs", null, null, 3.45m, 1.99m, 164363L, 0L, 3, "VHS de la Guerre des Tuques" }, - { 15, "Linge", "(N'est pas réellement pare-balle).", 0L, "chandailquetaine", null, null, 1435.45m, 1223.99m, 18L, 0L, 3, "Gilet pare-balle en laine" }, - { 16, "Autre", "Pour s'éffoirer le nez dedans.", 0L, "doudou", null, null, 14.45m, 13.99m, 14L, 0L, 0, "Doudou" }, - { 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" } - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Products"); - } - } -} diff --git a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221027160052_Initial-Db.Designer.cs b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.Designer.cs similarity index 55% rename from GrossesMitaines/GrossesMitainesAPI/Migrations/20221027160052_Initial-Db.Designer.cs rename to GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.Designer.cs index 0ebfbe0..5510b5d 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221027160052_Initial-Db.Designer.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.Designer.cs @@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace GrossesMitainesAPI.Migrations { [DbContext(typeof(InventoryContext))] - [Migration("20221027160052_Initial-Db")] + [Migration("20221030195130_Initial-Db")] partial class InitialDb { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -24,6 +24,89 @@ namespace GrossesMitainesAPI.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + modelBuilder.Entity("GrossesMitainesAPI.Data.InventoryUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + + b.HasData( + new + { + Id = "809dc5fd-c62f-4d93-abe4-275a55aabd33", + AccessFailedCount = 0, + ConcurrencyStamp = "f2e55d24-1ab5-441c-87e0-808f32045ab4", + Email = "admin@admin.com", + EmailConfirmed = false, + LockoutEnabled = false, + NormalizedEmail = "admin@admin.com", + NormalizedUserName = "admin", + PasswordHash = "AQAAAAEAACcQAAAAEKJtYKQ3fXHUA67KkZbzgDtxdg1UlFk3kFeNj3QSm3OfgsSoMtFExAq16W5arTVmRA==", + PhoneNumberConfirmed = false, + SecurityStamp = "56fc4076-5e9d-4bd1-91e7-b53abcc41fda", + TwoFactorEnabled = false, + UserName = "Admin" + }); + }); + modelBuilder.Entity("GrossesMitainesAPI.Models.Product", b => { b.Property("Id") @@ -316,6 +399,190 @@ namespace GrossesMitainesAPI.Migrations Title = "Mitaines pas de doigts" }); }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.cs b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.cs new file mode 100644 index 0000000..c19c249 --- /dev/null +++ b/GrossesMitaines/GrossesMitainesAPI/Migrations/20221030195130_Initial-Db.cs @@ -0,0 +1,277 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GrossesMitainesAPI.Migrations +{ + public partial class InitialDb : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AspNetRoles", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetUsers", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", 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), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUsers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Products", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: false), + Category = table.Column(type: "nvarchar(max)", nullable: false), + Description = table.Column(type: "nvarchar(max)", nullable: false), + Price = table.Column(type: "decimal(18,2)", nullable: false), + PromoPrice = table.Column(type: "decimal(18,2)", nullable: false), + Quantity = table.Column(type: "bigint", nullable: false), + Status = table.Column(type: "int", nullable: false), + Hits = table.Column(type: "bigint", nullable: false), + Sales = table.Column(type: "bigint", nullable: false), + LastSale = table.Column(type: "datetime2", nullable: true), + LastHit = table.Column(type: "datetime2", nullable: true), + ImageName = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Products", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "AspNetRoleClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserClaims", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); + table.ForeignKey( + name: "FK_AspNetUserClaims_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserLogins", + columns: table => new + { + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_AspNetUserLogins_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserRoles", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetRoles_RoleId", + column: x => x.RoleId, + principalTable: "AspNetRoles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_AspNetUserRoles_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AspNetUserTokens", + columns: table => new + { + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + 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" }); + + migrationBuilder.InsertData( + table: "Products", + columns: new[] { "Id", "Category", "Description", "Hits", "ImageName", "LastHit", "LastSale", "Price", "PromoPrice", "Quantity", "Sales", "Status", "Title" }, + values: new object[,] + { + { 1, "Linge", "Pour faire votre propre bonhomme de 1837, comme dans le bon vieux temps.", 0L, "ceintureflechee", null, null, 85.86m, 29.99m, 1L, 0L, 4, "Ceinture flèchée" }, + { 2, "Linge", "Parce que ça sent la coupe!", 0L, "pantouflesCH", null, null, 15.64m, 9.99m, 54L, 0L, 0, "Pantoufles du Canadien en Phentex" }, + { 3, "Homme", "On ne lui ferait pas mal, en tout cas!!", 0L, "jeanlucmongrain", null, null, 1453.12m, 999.99m, 1L, 0L, 3, "Jean-Luc Mongrain" }, + { 4, "Linge", "Tellement simple et comfortable.", 0L, "tshirt", null, null, 12.12m, 9.99m, 143L, 0L, 0, "T-Shirt" }, + { 5, "Vêtement d'extérieur", "Deux pour un!", 0L, "mitaines", null, null, 8.18m, 6.99m, 1423L, 0L, 0, "Mitaines" }, + { 6, "Vêtement d'extérieur", "Deux pour un!", 0L, "foulard", null, null, 10.56m, 8.99m, 14L, 0L, 4, "Foulard" }, + { 7, "Sous-Vêtement", "Pour garder le p'tit bout au chaud.", 0L, "kokin", null, null, 15.45m, 12.99m, 144L, 0L, 4, "Jock-Strap en phentex" }, + { 8, "Sous-Vêtement", "Pour garder l'absence de p'tit bout au chaud.", 0L, "kokin", null, null, 15.45m, 12.99m, 224L, 0L, 4, "Jock-Strap féminin en phentex" }, + { 9, "Alien", "En chiffon.", 0L, "bibi", null, null, 1045.45m, 1023.99m, 1L, 0L, 3, "Bibi" }, + { 10, "Vêtement d'extérieur", "En chiffon.", 0L, "tuque", null, null, 15.45m, 12.99m, 1L, 0L, 0, "Tuque en laine" }, + { 11, "Vêtement d'extérieur", "Pour se faire taper dessus avec une poêle à frire tout en restant au chaud.", 0L, "bonhomme", null, null, 145.45m, 123.99m, 1L, 0L, 4, "Habit de Bonhomme Carnaval" }, + { 12, "Autre", "Pour se pêter la fiole avec style.", 0L, "gauze", null, null, 145.45m, 123.99m, 0L, 0L, 1, "Gauze en phentex" }, + { 13, "Homme", "En chiffon.", 0L, "jesus", null, null, 145.45m, 123.99m, 1L, 0L, 3, "Petit Jésus de plâtre" }, + { 14, "Autre", "À écouter dans l'habit de Bonhomme Carnaval tant que possible.", 0L, "vhs", null, null, 3.45m, 1.99m, 164363L, 0L, 3, "VHS de la Guerre des Tuques" }, + { 15, "Linge", "(N'est pas réellement pare-balle).", 0L, "chandailquetaine", null, null, 1435.45m, 1223.99m, 18L, 0L, 3, "Gilet pare-balle en laine" }, + { 16, "Autre", "Pour s'éffoirer le nez dedans.", 0L, "doudou", null, null, 14.45m, 13.99m, 14L, 0L, 0, "Doudou" }, + { 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.CreateIndex( + name: "IX_AspNetRoleClaims_RoleId", + table: "AspNetRoleClaims", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "RoleNameIndex", + table: "AspNetRoles", + column: "NormalizedName", + unique: true, + filter: "[NormalizedName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserClaims_UserId", + table: "AspNetUserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserLogins_UserId", + table: "AspNetUserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_AspNetUserRoles_RoleId", + table: "AspNetUserRoles", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "AspNetUsers", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "AspNetUsers", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AspNetRoleClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserClaims"); + + migrationBuilder.DropTable( + name: "AspNetUserLogins"); + + migrationBuilder.DropTable( + name: "AspNetUserRoles"); + + migrationBuilder.DropTable( + name: "AspNetUserTokens"); + + migrationBuilder.DropTable( + name: "Products"); + + migrationBuilder.DropTable( + name: "AspNetRoles"); + + migrationBuilder.DropTable( + name: "AspNetUsers"); + } + } +} diff --git a/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs b/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs index bfc923b..1c36fd8 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Migrations/InventoryContextModelSnapshot.cs @@ -22,6 +22,89 @@ namespace GrossesMitainesAPI.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + modelBuilder.Entity("GrossesMitainesAPI.Data.InventoryUser", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("AspNetUsers", (string)null); + + b.HasData( + new + { + Id = "809dc5fd-c62f-4d93-abe4-275a55aabd33", + AccessFailedCount = 0, + ConcurrencyStamp = "f2e55d24-1ab5-441c-87e0-808f32045ab4", + Email = "admin@admin.com", + EmailConfirmed = false, + LockoutEnabled = false, + NormalizedEmail = "admin@admin.com", + NormalizedUserName = "admin", + PasswordHash = "AQAAAAEAACcQAAAAEKJtYKQ3fXHUA67KkZbzgDtxdg1UlFk3kFeNj3QSm3OfgsSoMtFExAq16W5arTVmRA==", + PhoneNumberConfirmed = false, + SecurityStamp = "56fc4076-5e9d-4bd1-91e7-b53abcc41fda", + TwoFactorEnabled = false, + UserName = "Admin" + }); + }); + modelBuilder.Entity("GrossesMitainesAPI.Models.Product", b => { b.Property("Id") @@ -314,6 +397,190 @@ namespace GrossesMitainesAPI.Migrations Title = "Mitaines pas de doigts" }); }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("RoleId") + .HasColumnType("nvarchar(450)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(450)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("GrossesMitainesAPI.Data.InventoryUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); #pragma warning restore 612, 618 } } diff --git a/GrossesMitaines/GrossesMitainesAPI/Program.cs b/GrossesMitaines/GrossesMitainesAPI/Program.cs index d697aed..2a16f38 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Program.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Program.cs @@ -1,6 +1,12 @@ using GrossesMitainesAPI.Data; using GrossesMitainesAPI.Services; +using Microsoft.AspNet.Identity; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using System.Net; var MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; var builder = WebApplication.CreateBuilder(args); @@ -17,6 +23,13 @@ builder.Services.AddCors(options => { }); builder.Services.AddControllers(); + +builder.Services.AddAuthentication("Cookies").AddIdentityCookies(); +builder.Services.AddIdentityCore() + .AddRoles() + .AddEntityFrameworkStores() + .AddSignInManager(); + // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -25,6 +38,9 @@ builder.Services.AddDbContextFactory(options => { options.UseS builder.Services.AddSingleton(); builder.Services.BuildServiceProvider().GetRequiredService(); + + + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -38,6 +54,7 @@ app.UseHttpsRedirection(); app.UseCors(MyAllowSpecificOrigins); app.UseAuthorization(); +app.UseAuthentication(); app.MapControllers(); diff --git a/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs b/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs index 1b0a2dc..8816985 100644 --- a/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs +++ b/GrossesMitaines/GrossesMitainesAPI/Services/DatabaseCacheService.cs @@ -7,6 +7,10 @@ using Microsoft.EntityFrameworkCore; #endregion +/// +/// Service pour copier la BD localement au +/// démarrage de l'API. +/// public class DatabaseCacheService { #region DI private readonly IServiceScopeFactory _contextFactory; // https://entityframeworkcore.com/knowledge-base/51939451/how-to-use-a-database-context-in-a-singleton-service-