diff --git a/services/Directory/FilterLists.Directory.Application/Commands/CreateList.cs b/services/Directory/FilterLists.Directory.Application/Commands/CreateList.cs index a2cf59608..157d4f688 100644 --- a/services/Directory/FilterLists.Directory.Application/Commands/CreateList.cs +++ b/services/Directory/FilterLists.Directory.Application/Commands/CreateList.cs @@ -1,5 +1,9 @@ using FilterLists.Directory.Domain.Aggregates.FilterLists; +using FilterLists.Directory.Domain.Aggregates.Languages; using FilterLists.Directory.Domain.Aggregates.Licenses; +using FilterLists.Directory.Domain.Aggregates.Maintainers; +using FilterLists.Directory.Domain.Aggregates.Syntaxes; +using FilterLists.Directory.Domain.Aggregates.Tags; using FilterLists.Directory.Infrastructure.Persistence.Commands.Context; using FluentValidation; using MediatR; @@ -146,10 +150,14 @@ public async Task Handle(Command request, CancellationToken cancellati .WhereIsDefaultForFilterList() .SingleAsync(cancellationToken); + // TODO: accept IDs and fetch additional related aggregates var filterList = FilterList.CreatePendingApproval( request.Name, request.Description, license, + new HashSet(), + new HashSet(), + new HashSet(), request.ViewUrls.Select(u => (u.SegmentNumber, u.Primariness, u.Url)), request.HomeUrl, request.OnionUrl, @@ -160,6 +168,13 @@ public async Task Handle(Command request, CancellationToken cancellati request.ChatUrl, request.EmailAddress, request.DonateUrl, + new HashSet(), + new HashSet(), + new HashSet(), + new HashSet(), + new HashSet(), + new HashSet(), + new HashSet(), request.CreateReason); _commandContext.FilterLists.Add(filterList); @@ -167,9 +182,7 @@ public async Task Handle(Command request, CancellationToken cancellati return new Response { - ChangeId = - filterList.Changes.Single() - .Id + ChangeId = filterList.Changes.Select(c => c.Id).Single() }; } } diff --git a/services/Directory/FilterLists.Directory.Domain/Aggregates/FilterLists/FilterList.cs b/services/Directory/FilterLists.Directory.Domain/Aggregates/FilterLists/FilterList.cs index 06c9d0f26..9ae4c96a8 100644 --- a/services/Directory/FilterLists.Directory.Domain/Aggregates/FilterLists/FilterList.cs +++ b/services/Directory/FilterLists.Directory.Domain/Aggregates/FilterLists/FilterList.cs @@ -42,6 +42,9 @@ public static FilterList CreatePendingApproval( string name, string? description, License license, + IEnumerable syntaxes, + IEnumerable languages, + IEnumerable tags, IEnumerable<(short SegmentNumber, short Primariness, Uri Url)> viewUrls, Uri? homeUrl, Uri? onionUrl, @@ -52,21 +55,47 @@ public static FilterList CreatePendingApproval( Uri? chatUrl, string? emailAddress, Uri? donateUrl, + IEnumerable maintainers, + IEnumerable upstreamFilterLists, + IEnumerable forkFilterLists, + IEnumerable includedInFilterLists, + IEnumerable includesFilterLists, + IEnumerable dependencyFilterLists, + IEnumerable dependentFilterLists, string? createReason) { - var urls = viewUrls.Select(u => FilterListViewUrl.Create(u.SegmentNumber, u.Primariness, u.Url)) + var urls = viewUrls.DistinctBy(u => new { u.SegmentNumber, u.Primariness, u.Url }) + .Select(u => FilterListViewUrl.Create(u.SegmentNumber, u.Primariness, u.Url)) .ToList(); if (urls.Count == 0) { throw new ArgumentException("At lest one view URL is required.", nameof(viewUrls)); } - if (urls.GroupBy(u => new { u.SegmentNumber, u.Primariness }) - .Any(g => g.Count() > 1)) + if (urls.GroupBy(u => new { u.SegmentNumber, u.Primariness }).Any(g => g.Count() > 1)) { - throw new ArgumentException( - "The segment number and primariness pair must be unique for each view URL.", - nameof(viewUrls)); + throw new ArgumentException("The segment number and primariness pair must be unique for each view URL.", nameof(viewUrls)); + } + + var upstreamFilterListsSet = new HashSet(upstreamFilterLists); + var forkFilterListsSet = new HashSet(forkFilterLists); + if (upstreamFilterListsSet.Intersect(forkFilterListsSet).Any()) + { + throw new ArgumentException("A FilterList cannot be both an Upstream and a Fork of the same FilterList."); + } + + var includedInFilterListsSet = new HashSet(includedInFilterLists); + var includesFilterListSet = new HashSet(includesFilterLists); + if (includedInFilterListsSet.Intersect(includesFilterListSet).Any()) + { + throw new ArgumentException("A FilterList cannot be both included in and including of the same FilterList."); + } + + var dependencyFilterListSet = new HashSet(dependencyFilterLists); + var dependentFilterListSet = new HashSet(dependentFilterLists); + if (dependencyFilterListSet.Intersect(dependentFilterListSet).Any()) + { + throw new ArgumentException("A FilterList cannot be both a dependency of and dependent upon the same FilterList."); } var list = new FilterList @@ -74,6 +103,10 @@ public static FilterList CreatePendingApproval( Name = name, Description = description, License = license, + Syntaxes = new HashSet(syntaxes), + Languages = new HashSet(languages), + Tags = new HashSet(tags), + ViewUrls = urls, HomeUrl = homeUrl, OnionUrl = onionUrl, PolicyUrl = policyUrl, @@ -83,7 +116,13 @@ public static FilterList CreatePendingApproval( ChatUrl = chatUrl, EmailAddress = emailAddress, DonateUrl = donateUrl, - ViewUrls = urls, + Maintainers = new HashSet(maintainers), + UpstreamFilterLists = upstreamFilterListsSet, + ForkFilterLists = forkFilterListsSet, + IncludedInFilterLists = includedInFilterListsSet, + IncludesFilterLists = includesFilterListSet, + DependencyFilterLists = dependencyFilterListSet, + DependentFilterLists = dependentFilterListSet, IsApproved = false }; list.Changes = new HashSet(new[] { FilterListChange.Create(list, createReason) });