From a95c0641a9626f06f6228aa8998bb5d238ee6dd6 Mon Sep 17 00:00:00 2001 From: Auros Nexus Date: Wed, 19 Jul 2023 14:43:50 -0400 Subject: [PATCH 1/2] Fixed and improved link serialization Changed the Link property from a tuple to an actual type. This should fix the serialization issue (where it just didn't serialize) without needing to enable field serialization, as well as make it easier to understand. --- src/Hive.Tests/Endpoints/UploadController.cs | 2 +- src/Hive/Controllers/UploadController.cs | 2 +- src/Hive/Graphing/Types/LinkType.cs | 9 +-- src/Hive/Models/Link.cs | 60 +++++++++++++++++++ src/Hive/Models/Mod.cs | 2 +- src/Hive/Models/Serialized/SerializedMod.cs | 6 +- .../Models/Serialized/SerializedModUpdate.cs | 5 ++ src/Hive/Services/Common/ModService.cs | 3 +- 8 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 src/Hive/Models/Link.cs diff --git a/src/Hive.Tests/Endpoints/UploadController.cs b/src/Hive.Tests/Endpoints/UploadController.cs index dabbd347..b33b0306 100644 --- a/src/Hive.Tests/Endpoints/UploadController.cs +++ b/src/Hive.Tests/Endpoints/UploadController.cs @@ -108,7 +108,7 @@ public async Task ValidUploadProcess() Name = "Test Mod 1", Description = "The first uploaded test mod" }, - Links = ImmutableList.Create(("project-home", "https://test-mod.bsmg.wiki/")), + Links = ImmutableList.Create(new Link("project-home", new Uri("https://test-mod.bsmg.wiki/"))), ChannelName = "newly-uploaded", SupportedGameVersions = ImmutableList.Create("1.12.1", "1.13.0"), Dependencies = ImmutableList.Create(new ModReference("bsipa", new VersionRange("^4.0.0"))), diff --git a/src/Hive/Controllers/UploadController.cs b/src/Hive/Controllers/UploadController.cs index 4f02687d..154cc88a 100644 --- a/src/Hive/Controllers/UploadController.cs +++ b/src/Hive/Controllers/UploadController.cs @@ -482,7 +482,7 @@ public async Task> CompleteUpload([FromForm] string f Uploader = user, Dependencies = finalMetadata.Dependencies?.ToList() ?? new(), // if deps is null, default to empty list (it's allowed) Conflicts = finalMetadata.ConflictsWith?.ToList() ?? new(), // same as above - Links = finalMetadata.Links?.Select(t => (t.Item1, new Uri(t.Item2))).ToList() ?? new(), // defaults to empty list + Links = finalMetadata.Links?.ToList() ?? new(), // defaults to empty list Authors = new List(), // both of these default to empty lists Contributors = new List(), }; diff --git a/src/Hive/Graphing/Types/LinkType.cs b/src/Hive/Graphing/Types/LinkType.cs index 7cac87b6..e7c04d5c 100644 --- a/src/Hive/Graphing/Types/LinkType.cs +++ b/src/Hive/Graphing/Types/LinkType.cs @@ -1,13 +1,14 @@ using System; using System.Collections.Generic; using GraphQL.Types; +using Hive.Models; namespace Hive.Graphing.Types { /// /// The GQL representation of a link on a . Specifically from . /// - public class LinkType : ObjectGraphType<(string, Uri)> + public class LinkType : ObjectGraphType { /// /// Setup a LinkType for GQL. @@ -20,14 +21,14 @@ public LinkType(IEnumerable> customGraphs) Name = "Link"; Description = Resources.GraphQL.Link; - _ = Field(l => l.Item1) + _ = Field(l => l.Name) .Name("name") .Description(Resources.GraphQL.Link_Name); _ = Field( - "url", + "location", Resources.GraphQL.Link_URL, - resolve: context => context.Source.Item2.ToString() + resolve: context => context.Source.Location.ToString() ); foreach (var graph in customGraphs) diff --git a/src/Hive/Models/Link.cs b/src/Hive/Models/Link.cs new file mode 100644 index 00000000..f25325c6 --- /dev/null +++ b/src/Hive/Models/Link.cs @@ -0,0 +1,60 @@ +using System; +using System.Text.Json.Serialization; + +namespace Hive.Models; + +/// +/// Represented a named link, something with a readable identifier and a Uri location +/// +public readonly struct Link : IEquatable +{ + /// + /// The name of the link. + /// + public string Name { get; } = string.Empty; + + /// + /// The location (uRI) of the link. + /// + public Uri Location { get; } = null!; + + /// + /// Construct a Link object with a name and Uri + /// + /// + /// + [JsonConstructor] + public Link(string name, Uri location) + { + Name = name; + Location = location; + } + + /// + public override string ToString() => $"({Name})[{Location}]"; + + /// + public bool Equals(Link other) => Name == other.Name && Location.Equals(other.Location); + + /// + public override bool Equals(object? obj) => obj is Link other && Equals(other); + + /// + public override int GetHashCode() => HashCode.Combine(Name, Location); + + /// + /// Equals operator + /// + /// + /// + /// + public static bool operator ==(Link left, Link right) => left.Equals(right); + + /// + /// Not equals operator + /// + /// + /// + /// + public static bool operator !=(Link left, Link right) => !left.Equals(right); +} diff --git a/src/Hive/Models/Mod.cs b/src/Hive/Models/Mod.cs index efbe5e86..f01c4d34 100644 --- a/src/Hive/Models/Mod.cs +++ b/src/Hive/Models/Mod.cs @@ -104,7 +104,7 @@ public class Mod /// [Column(TypeName = "jsonb")] // use jsonb here because that will let the db handle it sanely [SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "EF wants a setter")] - public IList<(string Name, Uri Url)> Links { get; set; } = new List<(string, Uri)>(); + public IList Links { get; set; } = new List(); /// /// The download link of the mod. diff --git a/src/Hive/Models/Serialized/SerializedMod.cs b/src/Hive/Models/Serialized/SerializedMod.cs index 27b6f4a1..a599c5d3 100644 --- a/src/Hive/Models/Serialized/SerializedMod.cs +++ b/src/Hive/Models/Serialized/SerializedMod.cs @@ -73,9 +73,9 @@ public record SerializedMod public ImmutableList SupportedGameVersions { get; init; } = null!; /// - /// The links provided of the , with the left hand side as the name and the right hand side as the url. + /// The links provided of the . /// - public ImmutableList<(string, string)> Links { get; init; } = null!; + public ImmutableList Links { get; init; } = null!; /// /// The dependencies (a list of objects) of the . @@ -117,7 +117,7 @@ public static SerializedMod Serialize([DisallowNull] Mod toSerialize, LocalizedM Authors = toSerialize.Authors.Select(x => x.Username).ToImmutableList(), Contributors = toSerialize.Contributors.Select(x => x.Username).ToImmutableList(), SupportedGameVersions = toSerialize.SupportedVersions.Select(x => x.Name!).ToImmutableList(), - Links = toSerialize.Links.Select(x => (x.Name, x.Url.ToString()))!.ToImmutableList(), + Links = toSerialize.Links.ToImmutableList(), Dependencies = toSerialize.Dependencies.ToImmutableList(), ConflictsWith = toSerialize.Conflicts.ToImmutableList() }; diff --git a/src/Hive/Models/Serialized/SerializedModUpdate.cs b/src/Hive/Models/Serialized/SerializedModUpdate.cs index 0415f7e6..c950231c 100644 --- a/src/Hive/Models/Serialized/SerializedModUpdate.cs +++ b/src/Hive/Models/Serialized/SerializedModUpdate.cs @@ -36,5 +36,10 @@ public class SerializedModUpdate /// The conflicts (a list of objects) of the /// public ImmutableList ConflictsWith { get; init; } = null!; + + /// + /// The links of the + /// + public ImmutableList Links { get; init; } = null!; } } diff --git a/src/Hive/Services/Common/ModService.cs b/src/Hive/Services/Common/ModService.cs index 52b6dbad..c4c87324 100644 --- a/src/Hive/Services/Common/ModService.cs +++ b/src/Hive/Services/Common/ModService.cs @@ -326,6 +326,7 @@ public async Task> UpdateMod(User? user, SerializedModUpdat var versions = await context.GameVersions.AsTracking().Where(g => update.SupportedGameVersions.Contains(g.Name)).ToArrayAsync().ConfigureAwait(false); + databaseMod.Links = update.Links; databaseMod.SupportedVersions = versions; databaseMod.Dependencies = update.Dependencies; databaseMod.Conflicts = update.ConflictsWith; @@ -345,7 +346,7 @@ private async Task> GetFilteredModList(string[]? channelIds, st var mods = CreateModQuery(); // Perform various filtering on our mods - if (channelIds != null && channelIds.Length > 0) + if (channelIds is { Length: > 0 }) { var filteredChannels = context.Channels.Where(c => channelIds.Contains(c.Name)); From 70388da787d47c28c7eb7163b2124839b5357c21 Mon Sep 17 00:00:00 2001 From: Auros Nexus Date: Wed, 19 Jul 2023 14:45:42 -0400 Subject: [PATCH 2/2] Fix failing test --- src/Hive.Tests/Endpoints/ModsController.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Hive.Tests/Endpoints/ModsController.cs b/src/Hive.Tests/Endpoints/ModsController.cs index 17c56ae7..f2895888 100644 --- a/src/Hive.Tests/Endpoints/ModsController.cs +++ b/src/Hive.Tests/Endpoints/ModsController.cs @@ -448,7 +448,8 @@ public async Task EditModStandard() ConflictsWith = new ModReference[] { new("TrickSaber", new VersionRange("^2.5.1")) // Add new conflict - }.ToImmutableList() + }.ToImmutableList(), + Links = Array.Empty().ToImmutableList() }; await using var stringStream = TestHelpers.GenerateStreamFromString(JsonSerializer.Serialize(identifier));