diff --git a/Props/server/Data/ApplicationDbContext.cs b/Props/server/Data/ApplicationDbContext.cs index 76cceaf..aea10d4 100644 --- a/Props/server/Data/ApplicationDbContext.cs +++ b/Props/server/Data/ApplicationDbContext.cs @@ -1,14 +1,16 @@ -using Props.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Threading.Tasks; using IdentityServer4.EntityFramework.Options; using Microsoft.AspNetCore.ApiAuthorization.IdentityServer; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.Text.Json; using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.Extensions.Options; +using Props.Models; +using Props.Shared.Models; +using Props.Shop.Framework; namespace Props.Data { @@ -20,30 +22,42 @@ namespace Props.Data { } - protected override void OnModelCreating(ModelBuilder modelBuilder) { + protected override void OnModelCreating(ModelBuilder modelBuilder) + { base.OnModelCreating(modelBuilder); - + modelBuilder.Entity() .Property(e => e.Order) .HasConversion( - v => JsonSerializer.Serialize(v, null), - v => JsonSerializer.Deserialize>(v, null), + v => JsonSerializer.Serialize(v, null), + v => JsonSerializer.Deserialize>(v, null), new ValueComparer>( (a, b) => a.SequenceEqual(b), c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())), - c => (IList) c.ToList() + c => (IList)c.ToList() ) ); modelBuilder.Entity() .Property(e => e.ShopStates) .HasConversion( - v => JsonSerializer.Serialize(v, null), + v => JsonSerializer.Serialize(v, null), v => JsonSerializer.Deserialize(v, null), new ValueComparer( (a, b) => a.Equals(b), c => c.GetHashCode(), - c => c.Clone() + c => c.Copy() + ) + ); + modelBuilder.Entity() + .Property(e => e.Filters) + .HasConversion( + v => JsonSerializer.Serialize(v, null), + v => JsonSerializer.Deserialize(v, null), + new ValueComparer( + (a, b) => a.Equals(b), + c => c.GetHashCode(), + c => c.Copy() ) ); } diff --git a/Props/server/Data/Migrations/20210712080053_InitialCreate.Designer.cs b/Props/server/Data/Migrations/20210714061021_InitialCreate.Designer.cs similarity index 91% rename from Props/server/Data/Migrations/20210712080053_InitialCreate.Designer.cs rename to Props/server/Data/Migrations/20210714061021_InitialCreate.Designer.cs index d0ca1bb..1d3cd7c 100644 --- a/Props/server/Data/Migrations/20210712080053_InitialCreate.Designer.cs +++ b/Props/server/Data/Migrations/20210714061021_InitialCreate.Designer.cs @@ -9,7 +9,7 @@ using Props.Data; namespace Props.Data.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20210712080053_InitialCreate")] + [Migration("20210714061021_InitialCreate")] partial class InitialCreate { protected override void BuildTargetModel(ModelBuilder modelBuilder) @@ -324,6 +324,7 @@ namespace Props.Data.Migrations .HasColumnType("INTEGER"); b.Property("ApplicationUserId") + .IsRequired() .HasColumnType("TEXT"); b.Property("Order") @@ -345,54 +346,19 @@ namespace Props.Data.Migrations .HasColumnType("INTEGER"); b.Property("ApplicationUserId") + .IsRequired() .HasColumnType("TEXT"); - b.Property("Currency") - .HasColumnType("INTEGER"); - - b.Property("EnableMaxShippingFee") - .HasColumnType("INTEGER"); - - b.Property("EnableUpperPrice") - .HasColumnType("INTEGER"); - - b.Property("KeepUnknownPurchaseCount") - .HasColumnType("INTEGER"); - - b.Property("KeepUnknownRatingCount") - .HasColumnType("INTEGER"); - - b.Property("KeepUnknownShipping") - .HasColumnType("INTEGER"); - - b.Property("KeepUnrated") - .HasColumnType("INTEGER"); - - b.Property("LowerPrice") - .HasColumnType("INTEGER"); + b.Property("Filters") + .HasColumnType("TEXT"); b.Property("MaxResults") .HasColumnType("INTEGER"); - b.Property("MaxShippingFee") - .HasColumnType("INTEGER"); - - b.Property("MinPurchases") - .HasColumnType("INTEGER"); - - b.Property("MinRating") - .HasColumnType("REAL"); - - b.Property("MinReviews") - .HasColumnType("INTEGER"); - b.Property("ShopStates") .IsRequired() .HasColumnType("TEXT"); - b.Property("UpperPrice") - .HasColumnType("INTEGER"); - b.HasKey("Id"); b.HasIndex("ApplicationUserId") @@ -408,6 +374,7 @@ namespace Props.Data.Migrations .HasColumnType("INTEGER"); b.Property("ApplicationUserId") + .IsRequired() .HasColumnType("TEXT"); b.Property("CacheCommonSearches") @@ -482,21 +449,27 @@ namespace Props.Data.Migrations { b.HasOne("Props.Models.ApplicationUser", null) .WithOne("ResultsPreferences") - .HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId"); + .HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Props.Models.SearchOutline", b => { b.HasOne("Props.Models.ApplicationUser", null) .WithOne("SearchOutline") - .HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId"); + .HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Props.Shared.Models.ApplicationPreferences", b => { b.HasOne("Props.Models.ApplicationUser", null) .WithOne("ApplicationPreferences") - .HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId"); + .HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Props.Models.ApplicationUser", b => diff --git a/Props/server/Data/Migrations/20210712080053_InitialCreate.cs b/Props/server/Data/Migrations/20210714061021_InitialCreate.cs similarity index 92% rename from Props/server/Data/Migrations/20210712080053_InitialCreate.cs rename to Props/server/Data/Migrations/20210714061021_InitialCreate.cs index 5deb1a5..f33e5a0 100644 --- a/Props/server/Data/Migrations/20210712080053_InitialCreate.cs +++ b/Props/server/Data/Migrations/20210714061021_InitialCreate.cs @@ -112,7 +112,7 @@ namespace Props.Data.Migrations { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - ApplicationUserId = table.Column(type: "TEXT", nullable: true), + ApplicationUserId = table.Column(type: "TEXT", nullable: false), DarkMode = table.Column(type: "INTEGER", nullable: false), CacheCommonSearches = table.Column(type: "INTEGER", nullable: false), EnableSearchHistory = table.Column(type: "INTEGER", nullable: false) @@ -125,7 +125,7 @@ namespace Props.Data.Migrations column: x => x.ApplicationUserId, principalTable: "AspNetUsers", principalColumn: "Id", - onDelete: ReferentialAction.Restrict); + onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -219,7 +219,7 @@ namespace Props.Data.Migrations { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - ApplicationUserId = table.Column(type: "TEXT", nullable: true), + ApplicationUserId = table.Column(type: "TEXT", nullable: false), Order = table.Column(type: "TEXT", nullable: false) }, constraints: table => @@ -230,7 +230,7 @@ namespace Props.Data.Migrations column: x => x.ApplicationUserId, principalTable: "AspNetUsers", principalColumn: "Id", - onDelete: ReferentialAction.Restrict); + onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -239,21 +239,9 @@ namespace Props.Data.Migrations { Id = table.Column(type: "INTEGER", nullable: false) .Annotation("Sqlite:Autoincrement", true), - ApplicationUserId = table.Column(type: "TEXT", nullable: true), - Currency = table.Column(type: "INTEGER", nullable: false), + ApplicationUserId = table.Column(type: "TEXT", nullable: false), + Filters = table.Column(type: "TEXT", nullable: true), MaxResults = table.Column(type: "INTEGER", nullable: false), - MinRating = table.Column(type: "REAL", nullable: false), - KeepUnrated = table.Column(type: "INTEGER", nullable: false), - EnableUpperPrice = table.Column(type: "INTEGER", nullable: false), - UpperPrice = table.Column(type: "INTEGER", nullable: false), - LowerPrice = table.Column(type: "INTEGER", nullable: false), - MinPurchases = table.Column(type: "INTEGER", nullable: false), - KeepUnknownPurchaseCount = table.Column(type: "INTEGER", nullable: false), - MinReviews = table.Column(type: "INTEGER", nullable: false), - KeepUnknownRatingCount = table.Column(type: "INTEGER", nullable: false), - EnableMaxShippingFee = table.Column(type: "INTEGER", nullable: false), - MaxShippingFee = table.Column(type: "INTEGER", nullable: false), - KeepUnknownShipping = table.Column(type: "INTEGER", nullable: false), ShopStates = table.Column(type: "TEXT", nullable: false) }, constraints: table => @@ -264,7 +252,7 @@ namespace Props.Data.Migrations column: x => x.ApplicationUserId, principalTable: "AspNetUsers", principalColumn: "Id", - onDelete: ReferentialAction.Restrict); + onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateIndex( diff --git a/Props/server/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/Props/server/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 273f8c5..ed6c300 100644 --- a/Props/server/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Props/server/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -322,6 +322,7 @@ namespace Props.Data.Migrations .HasColumnType("INTEGER"); b.Property("ApplicationUserId") + .IsRequired() .HasColumnType("TEXT"); b.Property("Order") @@ -343,54 +344,19 @@ namespace Props.Data.Migrations .HasColumnType("INTEGER"); b.Property("ApplicationUserId") + .IsRequired() .HasColumnType("TEXT"); - b.Property("Currency") - .HasColumnType("INTEGER"); - - b.Property("EnableMaxShippingFee") - .HasColumnType("INTEGER"); - - b.Property("EnableUpperPrice") - .HasColumnType("INTEGER"); - - b.Property("KeepUnknownPurchaseCount") - .HasColumnType("INTEGER"); - - b.Property("KeepUnknownRatingCount") - .HasColumnType("INTEGER"); - - b.Property("KeepUnknownShipping") - .HasColumnType("INTEGER"); - - b.Property("KeepUnrated") - .HasColumnType("INTEGER"); - - b.Property("LowerPrice") - .HasColumnType("INTEGER"); + b.Property("Filters") + .HasColumnType("TEXT"); b.Property("MaxResults") .HasColumnType("INTEGER"); - b.Property("MaxShippingFee") - .HasColumnType("INTEGER"); - - b.Property("MinPurchases") - .HasColumnType("INTEGER"); - - b.Property("MinRating") - .HasColumnType("REAL"); - - b.Property("MinReviews") - .HasColumnType("INTEGER"); - b.Property("ShopStates") .IsRequired() .HasColumnType("TEXT"); - b.Property("UpperPrice") - .HasColumnType("INTEGER"); - b.HasKey("Id"); b.HasIndex("ApplicationUserId") @@ -406,6 +372,7 @@ namespace Props.Data.Migrations .HasColumnType("INTEGER"); b.Property("ApplicationUserId") + .IsRequired() .HasColumnType("TEXT"); b.Property("CacheCommonSearches") @@ -480,21 +447,27 @@ namespace Props.Data.Migrations { b.HasOne("Props.Models.ApplicationUser", null) .WithOne("ResultsPreferences") - .HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId"); + .HasForeignKey("Props.Models.ResultsPreferences", "ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Props.Models.SearchOutline", b => { b.HasOne("Props.Models.ApplicationUser", null) .WithOne("SearchOutline") - .HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId"); + .HasForeignKey("Props.Models.SearchOutline", "ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Props.Shared.Models.ApplicationPreferences", b => { b.HasOne("Props.Models.ApplicationUser", null) .WithOne("ApplicationPreferences") - .HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId"); + .HasForeignKey("Props.Shared.Models.ApplicationPreferences", "ApplicationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("Props.Models.ApplicationUser", b => diff --git a/Props/server/Models/ApplicationPreferences.cs b/Props/server/Models/ApplicationPreferences.cs index 942c75f..3fe25e0 100644 --- a/Props/server/Models/ApplicationPreferences.cs +++ b/Props/server/Models/ApplicationPreferences.cs @@ -1,9 +1,12 @@ +using System.ComponentModel.DataAnnotations; + namespace Props.Shared.Models { public class ApplicationPreferences { public int Id { get; set; } - + + [Required] public string ApplicationUserId { get; set; } public bool DarkMode { get; set; } diff --git a/Props/server/Models/ApplicationUser.cs b/Props/server/Models/ApplicationUser.cs index dcc7664..f536939 100644 --- a/Props/server/Models/ApplicationUser.cs +++ b/Props/server/Models/ApplicationUser.cs @@ -1,22 +1,36 @@ -using Microsoft.AspNetCore.Identity; -using Props.Shared.Models; -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Props.Shared.Models; namespace Props.Models { public class ApplicationUser : IdentityUser { [Required] - public virtual SearchOutline SearchOutline { get; private set; } = new SearchOutline(); + public virtual SearchOutline SearchOutline { get; private set; } [Required] - public virtual ResultsPreferences ResultsPreferences { get; private set; } = new ResultsPreferences(); + public virtual ResultsPreferences ResultsPreferences { get; private set; } [Required] - public virtual ApplicationPreferences ApplicationPreferences {get; private set; } = new ApplicationPreferences(); + public virtual ApplicationPreferences ApplicationPreferences { get; private set; } + + public ApplicationUser() + { + SearchOutline = new SearchOutline(); + ResultsPreferences = new ResultsPreferences(); + ApplicationPreferences = new ApplicationPreferences(); + } + + public ApplicationUser(SearchOutline searchOutline, ResultsPreferences resultsPreferences, ApplicationPreferences applicationPreferences) + { + this.SearchOutline = searchOutline; + this.ResultsPreferences = resultsPreferences; + this.ApplicationPreferences = applicationPreferences; + } } } diff --git a/Props/server/Models/ResultsPreferences.cs b/Props/server/Models/ResultsPreferences.cs index 88d9ccc..22f3a2b 100644 --- a/Props/server/Models/ResultsPreferences.cs +++ b/Props/server/Models/ResultsPreferences.cs @@ -9,8 +9,9 @@ namespace Props.Models public class ResultsPreferences { public int Id { get; set; } + [Required] public string ApplicationUserId { get; set; } - + [Required] public IList Order { get; set; } diff --git a/Props/server/Models/SearchOutline.cs b/Props/server/Models/SearchOutline.cs index f4cbd42..212538c 100644 --- a/Props/server/Models/SearchOutline.cs +++ b/Props/server/Models/SearchOutline.cs @@ -9,46 +9,11 @@ namespace Props.Models public class SearchOutline { public int Id { get; set; } + [Required] public string ApplicationUserId { get; set; } - public Currency Currency { get; set; } = Currency.CAD; + public Filters Filters { get; set; } public int MaxResults { get; set; } = 100; - public float MinRating { get; set; } = 0.8f; - public bool KeepUnrated { get; set; } = true; - public bool EnableUpperPrice { get; set; } = false; - private int _upperPrice; - - public int UpperPrice - { - get - { - return _upperPrice; - } - set - { - if (EnableUpperPrice) _upperPrice = value; - } - } - public int LowerPrice { get; set; } - public int MinPurchases { get; set; } - public bool KeepUnknownPurchaseCount { get; set; } = true; - public int MinReviews { get; set; } - public bool KeepUnknownRatingCount { get; set; } = true; - public bool EnableMaxShippingFee { get; set; } - private int _maxShippingFee; - - public int MaxShippingFee - { - get - { - return _maxShippingFee; - } - set - { - if (EnableMaxShippingFee) _maxShippingFee = value; - } - } - public bool KeepUnknownShipping { get; set; } = true; [Required] public ShopToggler ShopStates { get; set; } = new ShopToggler(); @@ -56,11 +21,14 @@ namespace Props.Models public sealed class ShopToggler : HashSet { public int TotalShops { get; set; } - public bool this[string name] { - get { + public bool this[string name] + { + get + { return !this.Contains(name); } - set { + set + { if (value == false && TotalShops - Count <= 1) return; if (value) { @@ -73,10 +41,11 @@ namespace Props.Models } } - public ShopToggler Clone() { - ShopToggler clone = new ShopToggler(); - clone.Union(this); - return clone; + public ShopToggler Copy() + { + ShopToggler copy = new ShopToggler(); + copy.Union(this); + return copy; } public bool IsShopToggleable(string shop) @@ -91,35 +60,17 @@ namespace Props.Models { return false; } - SearchOutline other = (SearchOutline) obj; - return - Id == other.Id && - Currency == other.Currency && - MaxResults == other.MaxResults && - MinRating == other.MinRating && - KeepUnrated == other.KeepUnrated && - EnableUpperPrice == other.EnableUpperPrice && - UpperPrice == other.UpperPrice && - LowerPrice == other.LowerPrice && - MinPurchases == other.MinPurchases && - KeepUnknownPurchaseCount == other.KeepUnknownPurchaseCount && - MinReviews == other.MinReviews && - KeepUnknownRatingCount == other.KeepUnknownRatingCount && - EnableMaxShippingFee == other.EnableMaxShippingFee && - MaxShippingFee == other.MaxShippingFee && - KeepUnknownShipping == other.KeepUnknownShipping && + SearchOutline other = (SearchOutline)obj; + return + Id == other.Id && + MaxResults == other.MaxResults && + Filters.Equals(other.Filters) && ShopStates.Equals(other.ShopStates); } - + public override int GetHashCode() { return Id; } - - public SearchOutline DeepCopy() { - SearchOutline profile = (SearchOutline)MemberwiseClone(); - profile.ShopStates = ShopStates.Clone(); - return profile; - } } } \ No newline at end of file diff --git a/Props/server/Program.cs b/Props/server/Program.cs index 0b8c677..937115a 100644 --- a/Props/server/Program.cs +++ b/Props/server/Program.cs @@ -11,7 +11,6 @@ namespace Props { public class Program { - // TODO: Rename project to Props public static void Main(string[] args) { CreateHostBuilder(args).Build().Run();