Merge branch 'react-version' of https://github.com/MarcEricMartel/420-5DW-HY-TP into react-version

This commit is contained in:
Jean-Daniel Lamontagne 2022-11-01 11:25:03 -04:00
commit 9d84aa9e9b
19 changed files with 856 additions and 163 deletions

View File

@ -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":
@ -132,37 +132,37 @@ public class InventoryController : Controller {
}
}
// Inventory/Delete => Décrémenter un produit. Va aller chercher directement dans la BD.
[EnableCors("_myAllowSpecificOrigins"), HttpDelete(Name = "Inventory"), AllowAnonymous]
public ActionResult<int> Delete(int? id) {
int rid = 0;
if (!id.HasValue) {
_logger.LogError(8, "Tentative de vente sans Id.");
return BadRequest();
}
try {
Product 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;
} else {
_logger.LogError(8, $"Vente de produit pas en stock. Id Produit: {prod.Id}");
return BadRequest();
}
_context.Products.Update(prod);
_context.SaveChanges();
} catch (Exception e) {
_logger.LogError(8, e.Message);
return BadRequest();
}
_cache.askForRefresh();
return rid;
}
//[EnableCors("_myAllowSpecificOrigins"), HttpDelete(Name = "Inventory"), AllowAnonymous]
//public ActionResult<int> Delete(int? id) {
// int rid = 0;
// if (!id.HasValue) {
// _logger.LogError(8, "Tentative de vente sans Id.");
// return BadRequest();
// }
// try {
// 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 == 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();
// }
// _context.Products.Update(prod);
// _context.SaveChanges();
// } catch (Exception e) {
// _logger.LogError(8, e.Message);
// return BadRequest();
// }
// _cache.askForRefresh();
// return rid;
//}
#endregion
}

View File

@ -0,0 +1,21 @@
using GrossesMitainesAPI.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
namespace GrossesMitainesAPI.Controllers;
[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]"),
Authorize(AuthenticationSchemes = "Identity.Application", Roles = "Administrateur")]
public class InvoiceController : Controller {
private readonly ILogger<InvoiceController> _logger;
private readonly InventoryContext _context;
public InvoiceController(ILogger<InvoiceController> logger, InventoryContext context) {
this._logger = logger;
this._context = context;
}
}

View File

@ -1,5 +1,6 @@
namespace GrossesMitainesAPI.Controllers;
#region Dependencies
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Authorization;
@ -10,35 +11,54 @@ using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Principal;
using GrossesMitainesAPI.Models;
#endregion
[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api"),
Authorize(AuthenticationSchemes = "Identity.Application")]
public class LoginController : Controller {
#region DI Fields
private readonly UserManager<InventoryUser> _userMan;
private readonly SignInManager<InventoryUser> _signInMan;
#endregion
#region Ctor
public LoginController(SignInManager<InventoryUser> signin, UserManager<InventoryUser> userman) {
this._signInMan = signin;
this._userMan = userman;
}
#endregion
#region Utility Classes
public class LoginUser {
public string email { get; set; } = "";
public string password { get; set; } = "";
}
[HttpGet, Route("Login")]
public ReturnUserViewModel WhoAmI() {
var user = _userMan.GetUserAsync(_signInMan.Context.User);
user.Wait();
return new ReturnUserViewModel(user.Result);
#endregion
#region API Methods
[HttpGet, Route("WhoAmI")]
public async Task<ReturnUserViewModel> WhoAmI() {
var user = await _userMan.GetUserAsync(_signInMan.Context.User);
var roles = await _userMan.GetRolesAsync(user);
string role = "";
if (roles.Contains("Administrateur"))
role = "Administrateur";
else role = "Client";
return new ReturnUserViewModel(user, role);
}
[HttpPost, Route("Login"), AllowAnonymous]
public async Task<SignInResult> Login(LoginUser user, bool rememberMe = false) {
return await _signInMan.PasswordSignInAsync(await _userMan.FindByEmailAsync(user.email), user.password, rememberMe, false);
var User = await _userMan.FindByEmailAsync(user.email);
return await _signInMan.PasswordSignInAsync(User, user.password, rememberMe, false);
}
[HttpPost, Route("Logout")]
public void Logout() => _signInMan.SignOutAsync();
#endregion
}

View File

@ -21,7 +21,7 @@ using GrossesMitainesAPI.Services;
/// l'éxécution d'une modification de la BD.
/// </summary>
[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]"),
Authorize(AuthenticationSchemes = "Identity.Application")]
Authorize(AuthenticationSchemes = "Identity.Application", Roles = "Administrateur")]
public class ProductController : ControllerBase {
#region DI Fields
private readonly ILogger<ProductController> _logger;
@ -44,7 +44,7 @@ public class ProductController : ControllerBase {
#region API Methods
[EnableCors("_myAllowSpecificOrigins"), HttpGet(Name = "Product"), AllowAnonymous]
public ActionResult<ProductViewModel> 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<ActionResult<Product>> Post(Product prod) {
public async Task<ActionResult<ProductModel>> 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<Product> Patch(Product prod) {
public ActionResult<ProductModel> Patch(ProductModel prod) {
try {
_context.Products.Update(prod);
_context.SaveChanges();

View File

@ -25,7 +25,7 @@ public class SearchController : Controller {
private readonly ILogger<SearchController> _logger;
private readonly InventoryContext _context;
private readonly DatabaseCacheService _cache;
private IQueryable<Product>? _searchCache = null;
private IQueryable<ProductModel>? _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);

View File

@ -0,0 +1,25 @@
using GrossesMitainesAPI.Data;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
namespace GrossesMitainesAPI.Controllers;
[EnableCors("_myAllowSpecificOrigins"), ApiController, Route("api/[controller]"),
Authorize(AuthenticationSchemes = "Identity.Application", Roles = "Administrateur")]
public class UserController : Controller {
private readonly UserManager<InventoryUser> _userMan;
private readonly SignInManager<InventoryUser> _signInMan;
public UserController(SignInManager<InventoryUser> signin, UserManager<InventoryUser> userman) {
this._signInMan = signin;
this._userMan = userman;
}
}

View File

@ -6,205 +6,243 @@ using Microsoft.AspNetCore.Identity;
namespace GrossesMitainesAPI.Data;
public class InventoryContext : IdentityDbContext<InventoryUser> {
public DbSet<Product> Products { get; set; }
public DbSet<ProductModel> Products { get; set; }
public DbSet<AddressModel> Addresses { get; set; }
public DbSet<InvoiceModel> Invoices { get; set; }
public InventoryContext(DbContextOptions<InventoryContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
// Pour partir la BD.
modelBuilder.Entity<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<Product>().HasData(new Product {
modelBuilder.Entity<ProductModel>().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<InventoryUser>().HashPassword(admin, "Qwerty123!");
modelBuilder.Entity<InventoryUser>().HasData(admin);
modelBuilder.Entity<IdentityRole>().HasData(
new IdentityRole { Id = AdministrateurID, Name = "Administrateur", NormalizedName = "ADMINISTRATEUR" },
new IdentityRole { Id = ClientID, Name = "Client", NormalizedName = "CLIENT" }
);
modelBuilder.Entity<IdentityUserRole<string>>().HasData(
new IdentityUserRole<string> { RoleId = AdministrateurID, UserId = AdminID },
new IdentityUserRole<string> { RoleId = ClientID, UserId = AdminID }
);
base.OnModelCreating(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
var configuration = new ConfigurationBuilder()

View File

@ -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<Address> 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<AddressModel> Adresses { get; set; }
}

View File

@ -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<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<bool>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<string>("Appartment")
.HasColumnType("nvarchar(max)");
b.Property<string>("City")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("CivicNumber")
.HasColumnType("int");
b.Property<string>("Country")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("InventoryUserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("PostalCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Province")
.IsRequired()
.HasMaxLength(3)
.HasColumnType("nvarchar(3)");
b.Property<string>("Street")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("InventoryUserId");
b.ToTable("Addresses");
});
modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<bool>("Canceled")
.HasColumnType("bit");
b.Property<string>("EmailAddress")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("LinkedAccountId")
.HasColumnType("nvarchar(450)");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("ShippingAddressId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("LinkedAccountId");
b.HasIndex("ShippingAddressId");
b.ToTable("Invoices");
});
modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel+ProductInvoice", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<int?>("InvoiceModelId")
.HasColumnType("int");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<int>("Quantity")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("InvoiceModelId");
b.HasIndex("ProductId");
b.ToTable("ProductInvoice");
});
modelBuilder.Entity("GrossesMitainesAPI.Models.ProductModel", b =>
{
b.Property<int>("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<string>", 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<string>", 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<string>", 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
}
}

View File

@ -28,6 +28,8 @@ namespace GrossesMitainesAPI.Migrations
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
FirstName = table.Column<string>(type: "nvarchar(30)", maxLength: 30, nullable: false),
LastName = table.Column<string>(type: "nvarchar(30)", maxLength: 30, nullable: false),
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(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<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
CivicNumber = table.Column<int>(type: "int", nullable: false),
Appartment = table.Column<string>(type: "nvarchar(max)", nullable: true),
Street = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
City = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
Province = table.Column<string>(type: "nvarchar(3)", maxLength: 3, nullable: false),
Country = table.Column<string>(type: "nvarchar(30)", maxLength: 30, nullable: false),
PostalCode = table.Column<string>(type: "nvarchar(max)", nullable: false),
InventoryUserId = table.Column<string>(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<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
FirstName = table.Column<string>(type: "nvarchar(30)", maxLength: 30, nullable: false),
LastName = table.Column<string>(type: "nvarchar(30)", maxLength: 30, nullable: false),
PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: false),
EmailAddress = table.Column<string>(type: "nvarchar(max)", nullable: false),
LinkedAccountId = table.Column<string>(type: "nvarchar(450)", nullable: true),
ShippingAddressId = table.Column<int>(type: "int", nullable: false),
Canceled = table.Column<bool>(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<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ProductId = table.Column<int>(type: "int", nullable: false),
Quantity = table.Column<int>(type: "int", nullable: false),
InvoiceModelId = table.Column<int>(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");
}

View File

@ -41,6 +41,16 @@ namespace GrossesMitainesAPI.Migrations
b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<bool>("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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<string>("Appartment")
.HasColumnType("nvarchar(max)");
b.Property<string>("City")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<int>("CivicNumber")
.HasColumnType("int");
b.Property<string>("Country")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("InventoryUserId")
.HasColumnType("nvarchar(450)");
b.Property<string>("PostalCode")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Province")
.IsRequired()
.HasMaxLength(3)
.HasColumnType("nvarchar(3)");
b.Property<string>("Street")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("InventoryUserId");
b.ToTable("Addresses");
});
modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<bool>("Canceled")
.HasColumnType("bit");
b.Property<string>("EmailAddress")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("LinkedAccountId")
.HasColumnType("nvarchar(450)");
b.Property<string>("PhoneNumber")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("ShippingAddressId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("LinkedAccountId");
b.HasIndex("ShippingAddressId");
b.ToTable("Invoices");
});
modelBuilder.Entity("GrossesMitainesAPI.Models.InvoiceModel+ProductInvoice", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"), 1L, 1);
b.Property<int?>("InvoiceModelId")
.HasColumnType("int");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<int>("Quantity")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("InvoiceModelId");
b.HasIndex("ProductId");
b.ToTable("ProductInvoice");
});
modelBuilder.Entity("GrossesMitainesAPI.Models.ProductModel", b =>
{
b.Property<int>("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<string>", 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<string>", 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<string>", 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
}
}

View File

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

View File

@ -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<Product, int> 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<ProductInvoice> Products { get; set; }
//[Required, Column("BillingAddress")]
//public AddressModel BillingAddress { get; set; }
[Required]
public AddressModel ShippingAddress { get; set; }
public bool Canceled { get; set; } = false;
}

View File

@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace GrossesMitainesAPI.Models;
public class Product {
public class ProductModel {
public enum States {
Available,
BackOrder,

View File

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

View File

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

View File

@ -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<InventoryUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<InventoryContext>()
.AddSignInManager();
builder.Services.AddAuthorization();
builder.Services.AddAuthentication().AddIdentityCookies();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();

View File

@ -19,7 +19,7 @@ public class DatabaseCacheService {
#endregion
#region Fields
private Product[] _cache = new Product[1];
private ProductModel[] _cache = new ProductModel[1];
private Dictionary<uint, uint> _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<InventoryContext>();
prods = db.Products.ToArray();
@ -75,7 +75,7 @@ public class DatabaseCacheService {
List<uint> ids = hits.Keys.ToList();
using (var scope = _contextFactory.CreateScope()) {
var db = scope.ServiceProvider.GetRequiredService<InventoryContext>();
List<Product> lst = db.Products.Where(x => ids.Contains((uint)x.Id)).ToList();
List<ProductModel> 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<Product> queryCache() {
public IQueryable<ProductModel> queryCache() {
if (!_ok)
return null;
try {

View File

@ -3,7 +3,7 @@ import { Button } from "react-bootstrap";
const Login = () => {
const [adresse, setAdresse] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [returnmess, returnMessage] = useState("");
@ -17,14 +17,13 @@ const Login = () => {
'Accept': 'text/json',
'Content-Type': 'text/json'
},
//body: JSON.stringify({ username, password })
body: JSON.stringify({ email, password })
});
// Partie de display d'erreur ou de redirection (faudrait checker pour se faire un state de connexion avec un cookie pour react).
if (response.status === 200) {
var rep = await response.json();
if (rep.succeeded === true) {
const confirm = await fetch(`https://localhost:7292/api/Login`, {
const confirm = await fetch(`https://localhost:7292/api/WhoAmI`, {
method: 'GET',
credentials: 'include',
headers: {
@ -32,6 +31,7 @@ const Login = () => {
'Content-Type': 'text/json'
}
});
// TODO: Redirection vers Home et ajout du cookie pour React pour le layout.
console.log(await confirm.json())
returnMessage("WOOHOO!");
}
@ -52,8 +52,8 @@ const Login = () => {
<label>Adresse courriel </label>
<input className="form-control form-input" type='text'
placeholder="Adresse..."
value={adresse}
onChange={(e) => setAdresse(e.target.value)} />
value={email}
onChange={(e) => setEmail(e.target.value)} />
</div>
<div className="form-group">
<label>Mot de passe: </label>