diff --git a/FilterLists.sln b/FilterLists.sln
index 8b345386c..8534690c4 100644
--- a/FilterLists.sln
+++ b/FilterLists.sln
@@ -12,6 +12,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FilterLists.Web", "src\Filt
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "data", "data", "{8C3C7C63-F5EF-4E4E-B9BF-47F6EA7D2CBD}"
ProjectSection(SolutionItems) = preProject
+ data\Dependent.json = data\Dependent.json
data\FilterList.json = data\FilterList.json
data\FilterListLanguage.json = data\FilterListLanguage.json
data\FilterListMaintainer.json = data\FilterListMaintainer.json
diff --git a/data/Dependent.json b/data/Dependent.json
new file mode 100644
index 000000000..385d7b1e1
--- /dev/null
+++ b/data/Dependent.json
@@ -0,0 +1,14 @@
+[
+ {
+ "dependentFilterListId": 344,
+ "dependencyFilterListId": 30
+ },
+ {
+ "dependentFilterListId": 344,
+ "dependencyFilterListId": 301
+ },
+ {
+ "dependentFilterListId": 344,
+ "dependencyFilterListId": 479
+ }
+]
\ No newline at end of file
diff --git a/src/FilterLists.Api/Migrations/20180909161810_AddDependent.Designer.cs b/src/FilterLists.Api/Migrations/20180909161810_AddDependent.Designer.cs
new file mode 100644
index 000000000..5548ef9bf
--- /dev/null
+++ b/src/FilterLists.Api/Migrations/20180909161810_AddDependent.Designer.cs
@@ -0,0 +1,676 @@
+//
+
+using System;
+using FilterLists.Data;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace FilterLists.Api.Migrations
+{
+ [DbContext(typeof(FilterListsDbContext))]
+ [Migration("20180909161810_AddDependent")]
+ partial class AddDependent
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "2.1.2-rtm-30932")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ modelBuilder.Entity("FilterLists.Data.Entities.FilterList", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("SMALLINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("ChatUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("Description")
+ .HasColumnType("TEXT");
+
+ b.Property("DescriptionSourceUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("DiscontinuedDate")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("DATE")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("DonateUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("EmailAddress")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(126)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("ForumUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("HomeUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("IssuesUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("LicenseId")
+ .ValueGeneratedOnAdd()
+ .HasDefaultValue((byte)5);
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("VARCHAR(126)");
+
+ b.Property("PolicyUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("PublishedDate")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("DATE")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("SubmissionUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("SyntaxId");
+
+ b.Property("ViewUrl")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LicenseId");
+
+ b.HasIndex("SyntaxId");
+
+ b.ToTable("filterlists");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Dependent", b =>
+ {
+ b.Property("DependentFilterListId");
+
+ b.Property("DependencyFilterListId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("DependentFilterListId", "DependencyFilterListId");
+
+ b.HasIndex("DependencyFilterListId");
+
+ b.ToTable("dependents");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
+ {
+ b.Property("FilterListId");
+
+ b.Property("LanguageId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("FilterListId", "LanguageId");
+
+ b.HasIndex("LanguageId");
+
+ b.ToTable("filterlists_languages");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListMaintainer", b =>
+ {
+ b.Property("FilterListId");
+
+ b.Property("MaintainerId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("FilterListId", "MaintainerId");
+
+ b.HasIndex("MaintainerId");
+
+ b.ToTable("filterlists_maintainers");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListTag", b =>
+ {
+ b.Property("FilterListId");
+
+ b.Property("TagId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("FilterListId", "TagId");
+
+ b.HasIndex("TagId");
+
+ b.ToTable("filterlists_tags");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Fork", b =>
+ {
+ b.Property("ForkFilterListId");
+
+ b.Property("UpstreamFilterListId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("ForkFilterListId", "UpstreamFilterListId");
+
+ b.HasIndex("UpstreamFilterListId");
+
+ b.ToTable("forks");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Merge", b =>
+ {
+ b.Property("MergeFilterListId");
+
+ b.Property("UpstreamFilterListId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("MergeFilterListId", "UpstreamFilterListId");
+
+ b.HasIndex("UpstreamFilterListId");
+
+ b.ToTable("merges");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SnapshotRule", b =>
+ {
+ b.Property("SnapshotId");
+
+ b.Property("RuleId");
+
+ b.HasKey("SnapshotId", "RuleId");
+
+ b.HasIndex("RuleId");
+
+ b.ToTable("snapshots_rules");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SoftwareSyntax", b =>
+ {
+ b.Property("SyntaxId");
+
+ b.Property("SoftwareId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("SyntaxId", "SoftwareId");
+
+ b.HasIndex("SoftwareId");
+
+ b.ToTable("software_syntaxes");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Language", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("SMALLINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("Iso6391")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(2)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("Iso6392")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(3)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("Iso6392B")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(3)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("Iso6392T")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(3)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("Iso6393")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(3)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("LocalName")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(126)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("Name")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(126)")
+ .HasDefaultValueSql("NULL");
+
+ b.HasKey("Id");
+
+ b.ToTable("languages");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.License", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TINYINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("DescriptionUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("VARCHAR(126)");
+
+ b.Property("PermissiveAdaptation");
+
+ b.Property("PermissiveCommercial");
+
+ b.HasKey("Id");
+
+ b.ToTable("licenses");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Maintainer", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("SMALLINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("EmailAddress")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(126)")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("HomeUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("VARCHAR(126)");
+
+ b.Property("TwitterHandle")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("VARCHAR(126)")
+ .HasDefaultValueSql("NULL");
+
+ b.HasKey("Id");
+
+ b.ToTable("maintainers");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Rule", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("Raw")
+ .IsRequired()
+ .HasColumnType("LONGTEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("rules");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Snapshot", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("MEDIUMINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("FilterListId");
+
+ b.Property("HttpStatusCode")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("SMALLINT")
+ .HasDefaultValueSql("NULL");
+
+ b.Property("Md5Checksum")
+ .HasColumnType("BINARY(16)");
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("WasSuccessful");
+
+ b.Property("WasUpdated");
+
+ b.Property("WaybackTimestamp")
+ .HasColumnType("TIMESTAMP");
+
+ b.Property("WaybackUrl")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("FilterListId");
+
+ b.ToTable("snapshots");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Software", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TINYINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("DownloadUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("HomeUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("VARCHAR(126)");
+
+ b.HasKey("Id");
+
+ b.ToTable("software");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Syntax", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TINYINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("DefinitionUrl")
+ .HasColumnType("TEXT");
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("VARCHAR(126)");
+
+ b.HasKey("Id");
+
+ b.ToTable("syntaxes");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Tag", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TINYINT UNSIGNED")
+ .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn);
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.Property("Description")
+ .HasColumnType("TEXT");
+
+ b.Property("ModifiedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAddOrUpdate()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp() ON UPDATE current_timestamp()");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("VARCHAR(126)");
+
+ b.HasKey("Id");
+
+ b.ToTable("tags");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.FilterList", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.License", "License")
+ .WithMany("FilterLists")
+ .HasForeignKey("LicenseId");
+
+ b.HasOne("FilterLists.Data.Entities.Syntax", "Syntax")
+ .WithMany("FilterLists")
+ .HasForeignKey("SyntaxId");
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Dependent", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "DependencyFilterList")
+ .WithMany("DependencyFilterLists")
+ .HasForeignKey("DependencyFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.FilterList", "DependentFilterList")
+ .WithMany("DependentFilterLists")
+ .HasForeignKey("DependentFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
+ .WithMany("FilterListLanguages")
+ .HasForeignKey("FilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.Language", "Language")
+ .WithMany("FilterListLanguages")
+ .HasForeignKey("LanguageId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListMaintainer", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
+ .WithMany("FilterListMaintainers")
+ .HasForeignKey("FilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.Maintainer", "Maintainer")
+ .WithMany("FilterListMaintainers")
+ .HasForeignKey("MaintainerId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListTag", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
+ .WithMany("FilterListTags")
+ .HasForeignKey("FilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.Tag", "Tag")
+ .WithMany("FilterListTags")
+ .HasForeignKey("TagId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Fork", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "ForkFilterList")
+ .WithMany("ForkFilterLists")
+ .HasForeignKey("ForkFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.FilterList", "UpstreamFilterList")
+ .WithMany("UpstreamForkFilterLists")
+ .HasForeignKey("UpstreamFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Merge", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "MergeFilterList")
+ .WithMany("MergeFilterLists")
+ .HasForeignKey("MergeFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.FilterList", "UpstreamFilterList")
+ .WithMany("UpstreamMergeFilterLists")
+ .HasForeignKey("UpstreamFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SnapshotRule", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.Rule", "Rule")
+ .WithMany("SnapshotRules")
+ .HasForeignKey("RuleId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.Snapshot", "Snapshot")
+ .WithMany("SnapshotRules")
+ .HasForeignKey("SnapshotId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.SoftwareSyntax", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.Software", "Software")
+ .WithMany("SoftwareSyntaxes")
+ .HasForeignKey("SoftwareId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.Syntax", "Syntax")
+ .WithMany("SoftwareSyntaxes")
+ .HasForeignKey("SyntaxId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
+ modelBuilder.Entity("FilterLists.Data.Entities.Snapshot", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
+ .WithMany("Snapshots")
+ .HasForeignKey("FilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FilterLists.Api/Migrations/20180909161810_AddDependent.cs b/src/FilterLists.Api/Migrations/20180909161810_AddDependent.cs
new file mode 100644
index 000000000..c2dfc1f28
--- /dev/null
+++ b/src/FilterLists.Api/Migrations/20180909161810_AddDependent.cs
@@ -0,0 +1,48 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace FilterLists.Api.Migrations
+{
+ public partial class AddDependent : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ "dependents",
+ table => new
+ {
+ CreatedDateUtc = table.Column("TIMESTAMP", nullable: false,
+ defaultValueSql: "current_timestamp()"),
+ DependentFilterListId = table.Column(nullable: false),
+ DependencyFilterListId = table.Column(nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_dependents", x => new {x.DependentFilterListId, x.DependencyFilterListId});
+ table.ForeignKey(
+ "FK_dependents_filterlists_DependencyFilterListId",
+ x => x.DependencyFilterListId,
+ "filterlists",
+ "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ "FK_dependents_filterlists_DependentFilterListId",
+ x => x.DependentFilterListId,
+ "filterlists",
+ "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ "IX_dependents_DependencyFilterListId",
+ "dependents",
+ "DependencyFilterListId");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ "dependents");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FilterLists.Api/Migrations/FilterListsDbContextModelSnapshot.cs b/src/FilterLists.Api/Migrations/FilterListsDbContextModelSnapshot.cs
index 6a6f363f5..9559210b6 100644
--- a/src/FilterLists.Api/Migrations/FilterListsDbContextModelSnapshot.cs
+++ b/src/FilterLists.Api/Migrations/FilterListsDbContextModelSnapshot.cs
@@ -101,6 +101,25 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("filterlists");
});
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Dependent", b =>
+ {
+ b.Property("DependentFilterListId");
+
+ b.Property("DependencyFilterListId");
+
+ b.Property("CreatedDateUtc")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("TIMESTAMP")
+ .HasDefaultValueSql("current_timestamp()");
+
+ b.HasKey("DependentFilterListId", "DependencyFilterListId");
+
+ b.HasIndex("DependencyFilterListId");
+
+ b.ToTable("dependents");
+ });
+
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
{
b.Property("FilterListId");
@@ -538,6 +557,19 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasForeignKey("SyntaxId");
});
+ modelBuilder.Entity("FilterLists.Data.Entities.Junctions.Dependent", b =>
+ {
+ b.HasOne("FilterLists.Data.Entities.FilterList", "DependencyFilterList")
+ .WithMany("DependencyFilterLists")
+ .HasForeignKey("DependencyFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+
+ b.HasOne("FilterLists.Data.Entities.FilterList", "DependentFilterList")
+ .WithMany("DependentFilterLists")
+ .HasForeignKey("DependentFilterListId")
+ .OnDelete(DeleteBehavior.Cascade);
+ });
+
modelBuilder.Entity("FilterLists.Data.Entities.Junctions.FilterListLanguage", b =>
{
b.HasOne("FilterLists.Data.Entities.FilterList", "FilterList")
diff --git a/src/FilterLists.Api/V1/Controllers/DependentsController.cs b/src/FilterLists.Api/V1/Controllers/DependentsController.cs
new file mode 100644
index 000000000..433c76c79
--- /dev/null
+++ b/src/FilterLists.Api/V1/Controllers/DependentsController.cs
@@ -0,0 +1,25 @@
+using System.Threading.Tasks;
+using FilterLists.Data.Entities.Junctions;
+using FilterLists.Services.Seed;
+using FilterLists.Services.Seed.Models.Junctions;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Caching.Memory;
+
+namespace FilterLists.Api.V1.Controllers
+{
+ public class DependentsController : BaseController
+ {
+ public DependentsController(IMemoryCache memoryCache, SeedService seedService) : base(memoryCache, seedService)
+ {
+ }
+
+ [HttpGet("seed")]
+ public async Task Seed() =>
+ Json(await MemoryCache.GetOrCreate("DependentsController_Seed", entry =>
+ {
+ entry.AbsoluteExpirationRelativeToNow = FourHoursFromNow;
+ return SeedService.GetAllAsync(typeof(Dependent).GetProperty("DependentFilterListId"),
+ typeof(Dependent).GetProperty("DependencyFilterListId"));
+ }));
+ }
+}
\ No newline at end of file
diff --git a/src/FilterLists.Data/Entities/FilterList.cs b/src/FilterLists.Data/Entities/FilterList.cs
index 48d30207a..136dab258 100644
--- a/src/FilterLists.Data/Entities/FilterList.cs
+++ b/src/FilterLists.Data/Entities/FilterList.cs
@@ -9,6 +9,8 @@ namespace FilterLists.Data.Entities
public class FilterList : BaseEntity
{
public string ChatUrl { get; set; }
+ public ICollection DependentFilterLists { get; set; }
+ public ICollection DependencyFilterLists { get; set; }
public string Description { get; set; }
public string DescriptionSourceUrl { get; set; }
public DateTime? DiscontinuedDate { get; set; }
diff --git a/src/FilterLists.Data/Entities/Junctions/Dependent.cs b/src/FilterLists.Data/Entities/Junctions/Dependent.cs
new file mode 100644
index 000000000..b330a27d2
--- /dev/null
+++ b/src/FilterLists.Data/Entities/Junctions/Dependent.cs
@@ -0,0 +1,10 @@
+namespace FilterLists.Data.Entities.Junctions
+{
+ public class Dependent : BaseJunctionEntity
+ {
+ public uint DependentFilterListId { get; set; }
+ public FilterList DependentFilterList { get; set; }
+ public uint DependencyFilterListId { get; set; }
+ public FilterList DependencyFilterList { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/FilterLists.Data/EntityTypeConfigurations/Junctions/DependentTypeConfiguration.cs b/src/FilterLists.Data/EntityTypeConfigurations/Junctions/DependentTypeConfiguration.cs
new file mode 100644
index 000000000..23716717b
--- /dev/null
+++ b/src/FilterLists.Data/EntityTypeConfigurations/Junctions/DependentTypeConfiguration.cs
@@ -0,0 +1,22 @@
+using FilterLists.Data.Entities.Junctions;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace FilterLists.Data.EntityTypeConfigurations.Junctions
+{
+ public class DependentTypeConfiguration : BaseJunctionTypeConfiguration
+ {
+ public override void Configure(EntityTypeBuilder entityTypeBuilder)
+ {
+ base.Configure(entityTypeBuilder);
+ entityTypeBuilder.ToTable("dependents");
+ entityTypeBuilder.HasKey(x => new {x.DependentFilterListId, x.DependencyFilterListId});
+ entityTypeBuilder.HasOne(x => x.DependentFilterList)
+ .WithMany(x => x.DependentFilterLists)
+ .HasForeignKey(x => x.DependentFilterListId);
+ entityTypeBuilder.HasOne(x => x.DependencyFilterList)
+ .WithMany(x => x.DependencyFilterLists)
+ .HasForeignKey(x => x.DependencyFilterListId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/FilterLists.Data/FilterListsDbContext.cs b/src/FilterLists.Data/FilterListsDbContext.cs
index 2585bc48c..4970f6443 100644
--- a/src/FilterLists.Data/FilterListsDbContext.cs
+++ b/src/FilterLists.Data/FilterListsDbContext.cs
@@ -22,6 +22,7 @@ public FilterListsDbContext(DbContextOptions options) : base(options)
public DbSet Syntaxes { get; set; }
public DbSet Tags { get; set; }
+ public DbSet Dependents { get; set; }
public DbSet FilterListLanguages { get; set; }
public DbSet FilterListMaintainers { get; set; }
public DbSet FilterListTags { get; set; }
@@ -48,6 +49,7 @@ private static void ApplyConfigurations(ModelBuilder modelBuilder)
modelBuilder.ApplyConfiguration(new SyntaxTypeConfiguration());
modelBuilder.ApplyConfiguration(new TagTypeConfiguration());
+ modelBuilder.ApplyConfiguration(new DependentTypeConfiguration());
modelBuilder.ApplyConfiguration(new FilterListLanguageTypeConfiguration());
modelBuilder.ApplyConfiguration(new FilterListMaintainerTypeConfiguration());
modelBuilder.ApplyConfiguration(new FilterListTagTypeConfiguration());
diff --git a/src/FilterLists.Data/Seed/Extensions/SeedFilterListsDbContext.cs b/src/FilterLists.Data/Seed/Extensions/SeedFilterListsDbContext.cs
index 0bc4b116d..ed88dc51d 100644
--- a/src/FilterLists.Data/Seed/Extensions/SeedFilterListsDbContext.cs
+++ b/src/FilterLists.Data/Seed/Extensions/SeedFilterListsDbContext.cs
@@ -24,6 +24,7 @@ public static void SeedOrUpdate(this FilterListsDbContext dbContext, string data
dbContext.InsertOnDuplicateKeyUpdate(dataPath);
dbContext.InsertOnDuplicateKeyUpdate(dataPath);
dbContext.InsertOnDuplicateKeyUpdate(dataPath);
+ dbContext.InsertOnDuplicateKeyUpdate(dataPath);
dbContext.InsertOnDuplicateKeyUpdate(dataPath);
dbContext.InsertOnDuplicateKeyUpdate(dataPath);
dbContext.InsertOnDuplicateKeyUpdate(dataPath);
diff --git a/src/FilterLists.Services/Seed/Models/Junctions/DependentSeedDto.cs b/src/FilterLists.Services/Seed/Models/Junctions/DependentSeedDto.cs
new file mode 100644
index 000000000..665df8fab
--- /dev/null
+++ b/src/FilterLists.Services/Seed/Models/Junctions/DependentSeedDto.cs
@@ -0,0 +1,11 @@
+using JetBrains.Annotations;
+
+namespace FilterLists.Services.Seed.Models.Junctions
+{
+ [UsedImplicitly]
+ public class DependentSeedDto
+ {
+ public uint DependentFilterListId { get; set; }
+ public uint DependencyFilterListId { get; set; }
+ }
+}
\ No newline at end of file