diff --git a/src/isnd/Controllers/Packages/PackagesController.WebViews.cs b/src/isnd/Controllers/Packages/PackagesController.WebViews.cs index 53dbdf8..bd14136 100644 --- a/src/isnd/Controllers/Packages/PackagesController.WebViews.cs +++ b/src/isnd/Controllers/Packages/PackagesController.WebViews.cs @@ -1,4 +1,5 @@ +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using isn.abst; @@ -8,6 +9,7 @@ using isnd.Entities; using isnd.Helpers; using isnd.ViewModels; using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Components.Web.Virtualization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -20,12 +22,22 @@ namespace isnd.Controllers public async Task Index(PackageRegistrationQuery model) { var pkgs = await packageManager.SearchPackageAsync(model); + var result = new RegistrationPageIndexQueryAndResult + { + Source = packageManager.CatalogBaseUrl+ApiConfig.Index, + Query = model + }; + List registrations = new List(); + foreach (var pk in pkgs.data.GroupBy(x => x.PackageId)) + { + registrations.Add(new PackageRegistration(apiBase, pk.Key, pkgs.GetResults().Single(p=>p.Id == pk.Key).Versions)); + } return View(new RegistrationPageIndexQueryAndResult { Source = packageManager.CatalogBaseUrl+ApiConfig.Index, Query = model, - Result = pkgs.GetResults().Select(p => new PackageRegistration(apiBase, p)).ToArray() + Result = registrations.ToArray() }); } diff --git a/src/isnd/Data/ApplicationDbContext.cs b/src/isnd/Data/ApplicationDbContext.cs index 511b3d2..68cad9f 100644 --- a/src/isnd/Data/ApplicationDbContext.cs +++ b/src/isnd/Data/ApplicationDbContext.cs @@ -2,6 +2,8 @@ using Microsoft.EntityFrameworkCore; using isnd.Data.ApiKeys; using isnd.Data.Packages; +using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages; +using Microsoft.DotNet.Scaffolding.Shared.ProjectModel; namespace isnd.Data { @@ -29,6 +31,9 @@ namespace isnd.Data _ = builder.Entity().HasOne(g=>g.PackageVersion) .WithMany(v => v.DependencyGroups).HasForeignKey(x => new { x.PackageId, x.PackageVersionFullString } ); + _ = builder.Entity().HasOne(d=>d.Group) + .WithMany(g=>g.Dependencies); + } diff --git a/src/isnd/Data/Catalog/CatalogPage.cs b/src/isnd/Data/Catalog/CatalogPage.cs index 739d20c..dfd5ece 100644 --- a/src/isnd/Data/Catalog/CatalogPage.cs +++ b/src/isnd/Data/Catalog/CatalogPage.cs @@ -10,7 +10,7 @@ namespace isnd.Data.Catalog public class CatalogPage : Permalink { private readonly string pkgid; - private readonly List items; + private readonly List items; private readonly string apiBase; @@ -18,12 +18,12 @@ namespace isnd.Data.Catalog public CatalogPage (string pkgid, string apiBase) : base(apiBase + $"/registration/{pkgid}/index.json") { Parent = apiBase + $"/registration/{pkgid}/index.json"; - this.items = new List(); + this.items = new List(); this.pkgid = pkgid; this.apiBase = apiBase; } - public CatalogPage(string pkgid, string apiBase, List versions) : this(pkgid, apiBase) + public CatalogPage(string pkgid, string apiBase, IEnumerable versions) : this(pkgid, apiBase) { AddVersionRange(versions); } @@ -39,7 +39,7 @@ namespace isnd.Data.Catalog /// [JsonProperty("items")] - public Package[] Items { get => items.ToArray(); } + public RegistrationLeave[] Items { get => items.ToArray(); } public void AddVersionRange(IEnumerable vitems) { diff --git a/src/isnd/Data/Catalog/PackageDetails.cs b/src/isnd/Data/Catalog/PackageDetails.cs index b0cba95..58d5177 100644 --- a/src/isnd/Data/Catalog/PackageDetails.cs +++ b/src/isnd/Data/Catalog/PackageDetails.cs @@ -23,7 +23,6 @@ namespace isnd.Data.Catalog /// /// package id /// api Base - /// package permalink /// public PackageDetails(PackageVersion pkg, string apiBase): base( apiBase + ApiConfig.Registration + "/" + pkg.PackageId + "/" + pkg.FullString + ".json") { @@ -38,7 +37,7 @@ namespace isnd.Data.Catalog { if (pkg.DependencyGroups.Count>0) { - dependencyGroups = pkg.DependencyGroups.ToArray(); + DependencySets = pkg.DependencyGroups.ToNugetDepSet(); } } PackageDetailsUrl = new Uri(this.id); @@ -49,6 +48,68 @@ namespace isnd.Data.Catalog [JsonProperty("@type")] public string[] RefType { get; protected set; } = new string[] { "PackageDetails" }; + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public PackageDetails(string apiBase, string pkgId, string pkgVersionString, string commitId, DateTimeOffset commitTimeStamp, string authors, Deprecation deprecation, string description, Uri iconUrl, string language, Uri licenseUrl, string licenseExpression, string minClientVersion, Uri projectUrl, bool requireLicenseAcceptance, string summary, string tags, string title, string packageContent, string version, PackageIdentity identity, Uri readmeUrl, Uri reportAbuseUrl, Uri packageDetailsUrl, string owners, bool isListed, bool prefixReserved, LicenseMetadata licenseMetadata) + : base( apiBase + ApiConfig.Registration + "/" + pkgId + "/" + pkgVersionString + ".json") + { + this.CommitId = commitId; + this.CommitTimeStamp = commitTimeStamp; + this.Authors = authors; + this.deprecation = deprecation; + this.Description = description; + this.IconUrl = iconUrl; + this.language = language; + this.LicenseUrl = licenseUrl; + this.licenseExpression = licenseExpression; + this.minClientVersion = minClientVersion; + this.ProjectUrl = projectUrl; + this.RequireLicenseAcceptance = requireLicenseAcceptance; + this.Summary = summary; + this.Tags = tags; + this.Title = title; + this.packageContent = packageContent; + this.Version = version; + this.Identity = identity; + this.ReadmeUrl = readmeUrl; + this.ReportAbuseUrl = reportAbuseUrl; + this.PackageDetailsUrl = packageDetailsUrl; + this.Owners = owners; + this.IsListed = isListed; + this.PrefixReserved = prefixReserved; + this.LicenseMetadata = licenseMetadata; + + } + [JsonProperty("commitId")] public string CommitId { get; set; } @@ -62,12 +123,6 @@ namespace isnd.Data.Catalog [JsonProperty("authors")] public string Authors { get; set; } - /// - /// The dependencies of the package, grouped by target framework - /// - /// array of objects - public PackageDependencyGroup[] dependencyGroups { get; set; } - /// /// The deprecation associated with the package /// @@ -137,9 +192,7 @@ namespace isnd.Data.Catalog [JsonProperty("id")] public string PackageId { get; set; } - public IEnumerable DependencySets { get; set; } - = Array.Empty(); - + public long? DownloadCount { get; set; } public PackageIdentity Identity{ get; set; } @@ -159,6 +212,8 @@ namespace isnd.Data.Catalog public LicenseMetadata LicenseMetadata { get; set; } + public IEnumerable DependencySets {get; set;} + public Task GetDeprecationMetadataAsync() { throw new NotImplementedException(); diff --git a/src/isnd/Data/Catalog/PackageRegistration.cs b/src/isnd/Data/Catalog/PackageRegistration.cs index e5f0afa..68b45e4 100644 --- a/src/isnd/Data/Catalog/PackageRegistration.cs +++ b/src/isnd/Data/Catalog/PackageRegistration.cs @@ -15,11 +15,11 @@ namespace isnd.Data.Catalog Items = new List(); } - public PackageRegistration(string apiBase, Packages.Package pkg) : base($"{apiBase}{ApiConfig.Registration}/{pkg.Id}/index.json") + public PackageRegistration(string apiBase, string pkgId, IEnumerable versions) : base($"{apiBase}{ApiConfig.Registration}/{pkgId}/index.json") { Items = new List { - new CatalogPage(pkg.Id, apiBase, pkg.Versions) + new CatalogPage(pkgId, apiBase, versions) }; } diff --git a/src/isnd/Data/Catalog/RegistratioinLeave.cs b/src/isnd/Data/Catalog/RegistratioinLeave.cs index 2fc7169..6a3c7b3 100644 --- a/src/isnd/Data/Catalog/RegistratioinLeave.cs +++ b/src/isnd/Data/Catalog/RegistratioinLeave.cs @@ -9,9 +9,9 @@ namespace isnd.Data.Catalog /// Hosts a catalog entry, /// the atomic content reference /// - public class Package + public class RegistrationLeave { - public Package(string apiBase, string pkgId, string fullVersionString, PackageDetails entry) + public RegistrationLeave(string apiBase, string pkgId, string fullVersionString, PackageDetails entry) { this.registration = apiBase + ApiConfig.Registration + "/" + pkgId + "/" + fullVersionString + ".json"; diff --git a/src/isnd/Data/Packages/Dependency.cs b/src/isnd/Data/Packages/Dependency.cs index 3fa8daa..ef2fd54 100644 --- a/src/isnd/Data/Packages/Dependency.cs +++ b/src/isnd/Data/Packages/Dependency.cs @@ -8,20 +8,23 @@ namespace isnd.Data { public class Dependency { - [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] + /// + /// Dependency Package Identifier + /// + /// + [Key] public string Id { get;set;} /// - /// Package Id - /// - /// + /// Dependency Group Id /// /// [Required] [ForeignKey("Group")] + [JsonIgnore] public string DependencyGroupId { set ; get ; } - + [JsonIgnore] public virtual PackageDependencyGroup Group{ get; set; } public string Version { get; set; } diff --git a/src/isnd/Data/Packages/PackageDependencyGroup.cs b/src/isnd/Data/Packages/PackageDependencyGroup.cs index 0b0ac2c..a47c39b 100644 --- a/src/isnd/Data/Packages/PackageDependencyGroup.cs +++ b/src/isnd/Data/Packages/PackageDependencyGroup.cs @@ -1,35 +1,53 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; using Microsoft.DotNet.Scaffolding.Shared.ProjectModel; using Microsoft.Identity.Client; using Newtonsoft.Json; using NuGet.Frameworks; using NuGet.Packaging; using NuGet.Packaging.Core; +using NuGet.ProjectModel; using NuGet.Versioning; namespace isnd.Data { + static class Helpers + { + public static NuGet.Packaging.PackageDependencyGroup[] ToNugetDepSet(this IEnumerable groups) + { + return groups.Select(group => new NuGet.Packaging.PackageDependencyGroup( + new NuGetFramework(group.TargetFramework), + group.Dependencies.Select(dep => new PackageDependency(dep.Id)) + )).ToArray(); + } + } public class PackageDependencyGroup { + [JsonIgnore] [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public string Id { get ; set;} [Required] + [JsonIgnore] public string PackageId { get ; set;} [Required] + [JsonIgnore] public string PackageVersionFullString { get ; set;} [JsonProperty("targetFramework")] + [Required] public string TargetFramework { get; set; } [JsonProperty("dependencies")] [ForeignKey("DependencyGroupId")] public virtual List Dependencies { get; set; } + [JsonIgnore] public virtual PackageVersion PackageVersion { get; set; } + } } \ No newline at end of file diff --git a/src/isnd/Data/Packages/PackageVersion.cs b/src/isnd/Data/Packages/PackageVersion.cs index 8d9ae0c..fb5d941 100644 --- a/src/isnd/Data/Packages/PackageVersion.cs +++ b/src/isnd/Data/Packages/PackageVersion.cs @@ -74,9 +74,9 @@ namespace isnd.Data public string SementicVersionString { get => $"{Major}.{Minor}.{Patch}"; } public NuGetVersion NugetVersion { get => new NuGetVersion(FullString); } - public Catalog.Package ToPackage(string apiBase) + public Catalog.RegistrationLeave ToPackage(string apiBase) { - return new Catalog.Package(apiBase, this.PackageId , FullString, new Catalog.PackageDetails(this, apiBase)); + return new Catalog.RegistrationLeave(apiBase, this.PackageId , FullString, new Catalog.PackageDetails(this, apiBase)); } public bool IsDeleted => LatestCommit?.Action == PackageAction.DeletePackage; diff --git a/src/isnd/Interfaces/IPackageManager.cs b/src/isnd/Interfaces/IPackageManager.cs index 4f88cda..e8ce502 100644 --- a/src/isnd/Interfaces/IPackageManager.cs +++ b/src/isnd/Interfaces/IPackageManager.cs @@ -22,8 +22,8 @@ namespace isnd.Interfaces Task DeletePackageAsync(string pkgid, string version, string type); Task UserAskForPackageDeletionAsync(string userid, string pkgId, string lower, string type); Task GetPackageAsync(string pkgid, string version, string type); - Task GetCatalogEntryAsync(string pkgId, string version, string pkgType); - IEnumerable SearchCatalogEntriesById(string pkgId, string semver, string pkgType, bool preRelease); + Task GetCatalogEntryAsync(string pkgId, string version, string pkgType); + IEnumerable SearchCatalogEntriesById(string pkgId, string semver, string pkgType, bool preRelease); Task GetCatalogIndexAsync(); Task GetPackageRegistrationIndexAsync(PackageRegistrationQuery query); diff --git a/src/isnd/Migrations/20240331152055_frameworks.Designer.cs b/src/isnd/Migrations/20240331152055_frameworks.Designer.cs new file mode 100644 index 0000000..6a8c5ca --- /dev/null +++ b/src/isnd/Migrations/20240331152055_frameworks.Designer.cs @@ -0,0 +1,531 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using isnd.Data; + +#nullable disable + +namespace isnd.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240331152055_frameworks")] + partial class frameworks + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidityPeriodInDays") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ApiKeys"); + }); + + modelBuilder.Entity("isnd.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("isnd.Data.Dependency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("DependencyGroupId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Exclude") + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("DependencyGroupId"); + + b.ToTable("Dependencies"); + }); + + modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("PackageId") + .IsRequired() + .HasColumnType("character varying(1024)"); + + b.Property("PackageVersionFullString") + .IsRequired() + .HasColumnType("character varying(256)"); + + b.Property("TargetFramework") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("PackageId", "PackageVersionFullString"); + + b.ToTable("PackageDependencyGroups"); + }); + + modelBuilder.Entity("isnd.Data.PackageVersion", b => + { + b.Property("PackageId") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("FullString") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("CommitNId") + .HasColumnType("bigint"); + + b.Property("IsPrerelease") + .HasColumnType("boolean"); + + b.Property("Major") + .HasColumnType("integer"); + + b.Property("Minor") + .HasColumnType("integer"); + + b.Property("Patch") + .HasColumnType("integer"); + + b.Property("Revision") + .HasColumnType("integer"); + + b.Property("Type") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("PackageId", "FullString"); + + b.HasIndex("CommitNId"); + + b.ToTable("PackageVersions"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Commit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer"); + + b.Property("TimeStamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Commits"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Package", b => + { + b.Property("Id") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("CommitNId") + .HasColumnType("bigint"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("CommitNId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Packages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b => + { + b.HasOne("isnd.Data.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("isnd.Data.Dependency", b => + { + b.HasOne("isnd.Data.PackageDependencyGroup", "Group") + .WithMany("Dependencies") + .HasForeignKey("DependencyGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => + { + b.HasOne("isnd.Data.PackageVersion", "PackageVersion") + .WithMany("DependencyGroups") + .HasForeignKey("PackageId", "PackageVersionFullString") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PackageVersion"); + }); + + modelBuilder.Entity("isnd.Data.PackageVersion", b => + { + b.HasOne("isnd.Data.Packages.Commit", "LatestCommit") + .WithMany("Versions") + .HasForeignKey("CommitNId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("isnd.Data.Packages.Package", "Package") + .WithMany("Versions") + .HasForeignKey("PackageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LatestCommit"); + + b.Navigation("Package"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Package", b => + { + b.HasOne("isnd.Data.Packages.Commit", "LatestCommit") + .WithMany() + .HasForeignKey("CommitNId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("isnd.Data.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LatestCommit"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => + { + b.Navigation("Dependencies"); + }); + + modelBuilder.Entity("isnd.Data.PackageVersion", b => + { + b.Navigation("DependencyGroups"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Commit", b => + { + b.Navigation("Versions"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Package", b => + { + b.Navigation("Versions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/isnd/Migrations/20240331152055_frameworks.cs b/src/isnd/Migrations/20240331152055_frameworks.cs new file mode 100644 index 0000000..b92aaf6 --- /dev/null +++ b/src/isnd/Migrations/20240331152055_frameworks.cs @@ -0,0 +1,169 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace isnd.Migrations +{ + /// + public partial class frameworks : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Depedencies_PackageDependencyGroups_DependencyGroupId", + table: "Depedencies"); + + migrationBuilder.DropForeignKey( + name: "FK_PackageDependencyGroups_PackageVersions_PackageVersionPacka~", + table: "PackageDependencyGroups"); + + migrationBuilder.DropIndex( + name: "IX_PackageDependencyGroups_PackageVersionPackageId_PackageVers~", + table: "PackageDependencyGroups"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Depedencies", + table: "Depedencies"); + + migrationBuilder.DropColumn( + name: "PackageVersionId", + table: "PackageDependencyGroups"); + + migrationBuilder.DropColumn( + name: "PackageVersionPackageId", + table: "PackageDependencyGroups"); + + migrationBuilder.RenameTable( + name: "Depedencies", + newName: "Dependencies"); + + migrationBuilder.RenameIndex( + name: "IX_Depedencies_DependencyGroupId", + table: "Dependencies", + newName: "IX_Dependencies_DependencyGroupId"); + + migrationBuilder.AlterColumn( + name: "PackageVersionFullString", + table: "PackageDependencyGroups", + type: "character varying(256)", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "character varying(256)", + oldNullable: true); + + migrationBuilder.AddColumn( + name: "PackageId", + table: "PackageDependencyGroups", + type: "character varying(1024)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddPrimaryKey( + name: "PK_Dependencies", + table: "Dependencies", + column: "Id"); + + migrationBuilder.CreateIndex( + name: "IX_PackageDependencyGroups_PackageId_PackageVersionFullString", + table: "PackageDependencyGroups", + columns: new[] { "PackageId", "PackageVersionFullString" }); + + migrationBuilder.AddForeignKey( + name: "FK_Dependencies_PackageDependencyGroups_DependencyGroupId", + table: "Dependencies", + column: "DependencyGroupId", + principalTable: "PackageDependencyGroups", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_PackageDependencyGroups_PackageVersions_PackageId_PackageVe~", + table: "PackageDependencyGroups", + columns: new[] { "PackageId", "PackageVersionFullString" }, + principalTable: "PackageVersions", + principalColumns: new[] { "PackageId", "FullString" }, + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Dependencies_PackageDependencyGroups_DependencyGroupId", + table: "Dependencies"); + + migrationBuilder.DropForeignKey( + name: "FK_PackageDependencyGroups_PackageVersions_PackageId_PackageVe~", + table: "PackageDependencyGroups"); + + migrationBuilder.DropIndex( + name: "IX_PackageDependencyGroups_PackageId_PackageVersionFullString", + table: "PackageDependencyGroups"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Dependencies", + table: "Dependencies"); + + migrationBuilder.DropColumn( + name: "PackageId", + table: "PackageDependencyGroups"); + + migrationBuilder.RenameTable( + name: "Dependencies", + newName: "Depedencies"); + + migrationBuilder.RenameIndex( + name: "IX_Dependencies_DependencyGroupId", + table: "Depedencies", + newName: "IX_Depedencies_DependencyGroupId"); + + migrationBuilder.AlterColumn( + name: "PackageVersionFullString", + table: "PackageDependencyGroups", + type: "character varying(256)", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(256)"); + + migrationBuilder.AddColumn( + name: "PackageVersionId", + table: "PackageDependencyGroups", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "PackageVersionPackageId", + table: "PackageDependencyGroups", + type: "character varying(1024)", + nullable: true); + + migrationBuilder.AddPrimaryKey( + name: "PK_Depedencies", + table: "Depedencies", + column: "Id"); + + migrationBuilder.CreateIndex( + name: "IX_PackageDependencyGroups_PackageVersionPackageId_PackageVers~", + table: "PackageDependencyGroups", + columns: new[] { "PackageVersionPackageId", "PackageVersionFullString" }); + + migrationBuilder.AddForeignKey( + name: "FK_Depedencies_PackageDependencyGroups_DependencyGroupId", + table: "Depedencies", + column: "DependencyGroupId", + principalTable: "PackageDependencyGroups", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_PackageDependencyGroups_PackageVersions_PackageVersionPacka~", + table: "PackageDependencyGroups", + columns: new[] { "PackageVersionPackageId", "PackageVersionFullString" }, + principalTable: "PackageVersions", + principalColumns: new[] { "PackageId", "FullString" }); + } + } +} diff --git a/src/isnd/Migrations/20240406181803_frameworkRefRequired.Designer.cs b/src/isnd/Migrations/20240406181803_frameworkRefRequired.Designer.cs new file mode 100644 index 0000000..920b310 --- /dev/null +++ b/src/isnd/Migrations/20240406181803_frameworkRefRequired.Designer.cs @@ -0,0 +1,532 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using isnd.Data; + +#nullable disable + +namespace isnd.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20240406181803_frameworkRefRequired")] + partial class frameworkRefRequired + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("text"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("text"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ValidityPeriodInDays") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("ApiKeys"); + }); + + modelBuilder.Entity("isnd.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FullName") + .HasColumnType("text"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("isnd.Data.Dependency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("DependencyGroupId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Exclude") + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("DependencyGroupId"); + + b.ToTable("Dependencies"); + }); + + modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text"); + + b.Property("PackageId") + .IsRequired() + .HasColumnType("character varying(1024)"); + + b.Property("PackageVersionFullString") + .IsRequired() + .HasColumnType("character varying(256)"); + + b.Property("TargetFramework") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("PackageId", "PackageVersionFullString"); + + b.ToTable("PackageDependencyGroups"); + }); + + modelBuilder.Entity("isnd.Data.PackageVersion", b => + { + b.Property("PackageId") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("FullString") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("CommitNId") + .HasColumnType("bigint"); + + b.Property("IsPrerelease") + .HasColumnType("boolean"); + + b.Property("Major") + .HasColumnType("integer"); + + b.Property("Minor") + .HasColumnType("integer"); + + b.Property("Patch") + .HasColumnType("integer"); + + b.Property("Revision") + .HasColumnType("integer"); + + b.Property("Type") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("PackageId", "FullString"); + + b.HasIndex("CommitNId"); + + b.ToTable("PackageVersions"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Commit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer"); + + b.Property("TimeStamp") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Commits"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Package", b => + { + b.Property("Id") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("CommitNId") + .HasColumnType("bigint"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("OwnerId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Public") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("CommitNId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Packages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("isnd.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b => + { + b.HasOne("isnd.Data.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("isnd.Data.Dependency", b => + { + b.HasOne("isnd.Data.PackageDependencyGroup", "Group") + .WithMany("Dependencies") + .HasForeignKey("DependencyGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => + { + b.HasOne("isnd.Data.PackageVersion", "PackageVersion") + .WithMany("DependencyGroups") + .HasForeignKey("PackageId", "PackageVersionFullString") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PackageVersion"); + }); + + modelBuilder.Entity("isnd.Data.PackageVersion", b => + { + b.HasOne("isnd.Data.Packages.Commit", "LatestCommit") + .WithMany("Versions") + .HasForeignKey("CommitNId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("isnd.Data.Packages.Package", "Package") + .WithMany("Versions") + .HasForeignKey("PackageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LatestCommit"); + + b.Navigation("Package"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Package", b => + { + b.HasOne("isnd.Data.Packages.Commit", "LatestCommit") + .WithMany() + .HasForeignKey("CommitNId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("isnd.Data.ApplicationUser", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LatestCommit"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => + { + b.Navigation("Dependencies"); + }); + + modelBuilder.Entity("isnd.Data.PackageVersion", b => + { + b.Navigation("DependencyGroups"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Commit", b => + { + b.Navigation("Versions"); + }); + + modelBuilder.Entity("isnd.Data.Packages.Package", b => + { + b.Navigation("Versions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/isnd/Migrations/20240406181803_frameworkRefRequired.cs b/src/isnd/Migrations/20240406181803_frameworkRefRequired.cs new file mode 100644 index 0000000..f7c584b --- /dev/null +++ b/src/isnd/Migrations/20240406181803_frameworkRefRequired.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace isnd.Migrations +{ + /// + public partial class frameworkRefRequired : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "TargetFramework", + table: "PackageDependencyGroups", + type: "text", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "TargetFramework", + table: "PackageDependencyGroups", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "text"); + } + } +} diff --git a/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs b/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs index 21346d0..c2e31ba 100644 --- a/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs @@ -177,7 +177,7 @@ namespace isnd.Migrations b.HasIndex("UserId"); - b.ToTable("ApiKeys"); + b.ToTable("ApiKeys", (string)null); }); modelBuilder.Entity("isnd.Data.ApplicationUser", b => @@ -267,7 +267,7 @@ namespace isnd.Migrations b.HasIndex("DependencyGroupId"); - b.ToTable("Depedencies"); + b.ToTable("Dependencies", (string)null); }); modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => @@ -276,24 +276,23 @@ namespace isnd.Migrations .ValueGeneratedOnAdd() .HasColumnType("text"); - b.Property("PackageVersionFullString") - .HasColumnType("character varying(256)"); - - b.Property("PackageVersionId") + b.Property("PackageId") .IsRequired() - .HasColumnType("text"); - - b.Property("PackageVersionPackageId") .HasColumnType("character varying(1024)"); + b.Property("PackageVersionFullString") + .IsRequired() + .HasColumnType("character varying(256)"); + b.Property("TargetFramework") + .IsRequired() .HasColumnType("text"); b.HasKey("Id"); - b.HasIndex("PackageVersionPackageId", "PackageVersionFullString"); + b.HasIndex("PackageId", "PackageVersionFullString"); - b.ToTable("PackageDependencyGroups"); + b.ToTable("PackageDependencyGroups", (string)null); }); modelBuilder.Entity("isnd.Data.PackageVersion", b => @@ -332,7 +331,7 @@ namespace isnd.Migrations b.HasIndex("CommitNId"); - b.ToTable("PackageVersions"); + b.ToTable("PackageVersions", (string)null); }); modelBuilder.Entity("isnd.Data.Packages.Commit", b => @@ -351,7 +350,7 @@ namespace isnd.Migrations b.HasKey("Id"); - b.ToTable("Commits"); + b.ToTable("Commits", (string)null); }); modelBuilder.Entity("isnd.Data.Packages.Package", b => @@ -380,7 +379,7 @@ namespace isnd.Migrations b.HasIndex("OwnerId"); - b.ToTable("Packages"); + b.ToTable("Packages", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => @@ -458,9 +457,13 @@ namespace isnd.Migrations modelBuilder.Entity("isnd.Data.PackageDependencyGroup", b => { - b.HasOne("isnd.Data.PackageVersion", null) + b.HasOne("isnd.Data.PackageVersion", "PackageVersion") .WithMany("DependencyGroups") - .HasForeignKey("PackageVersionPackageId", "PackageVersionFullString"); + .HasForeignKey("PackageId", "PackageVersionFullString") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PackageVersion"); }); modelBuilder.Entity("isnd.Data.PackageVersion", b => diff --git a/src/isnd/Services/FrameworkDependencyGroup.cs b/src/isnd/Services/FrameworkDependencyGroup.cs new file mode 100644 index 0000000..0333053 --- /dev/null +++ b/src/isnd/Services/FrameworkDependencyGroup.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace isnd.Services +{ + public class FrameworkDependencyGroup + { + internal string FrameworkName { get; set; } + + internal List Dependencies { get; set; } + } +} \ No newline at end of file diff --git a/src/isnd/Services/PackageManager.cs b/src/isnd/Services/PackageManager.cs index 0f236f0..f4797ae 100644 --- a/src/isnd/Services/PackageManager.cs +++ b/src/isnd/Services/PackageManager.cs @@ -21,6 +21,7 @@ using NuGet.Versioning; using System.Xml; using System.Xml.Linq; using System.Threading; +using NuGet.Protocol; namespace isnd.Services { @@ -228,19 +229,26 @@ namespace isnd.Services ); } - public async Task GetCatalogEntryAsync - (string pkgId, string semver = null, string pkgType = null) + public async Task GetCatalogEntryAsync + (string pkgId, string semver, string pkgType = null) { - return (await dbContext.PackageVersions + var version = await dbContext.PackageVersions .Include(v => v.Package) .Include(v => v.Package.LatestCommit) .Include(v => v.Package.Owner) + .Include(v => v.DependencyGroups) .Include(v => v.LatestCommit) .Where(v => v.PackageId == pkgId && v.FullString == semver && v.LatestCommit != null - ).SingleOrDefaultAsync()).ToPackage( - apiBase); + ).SingleOrDefaultAsync(); + + foreach (var g in version.DependencyGroups) + { + g.Dependencies = dbContext.Dependencies.Where(d => d.DependencyGroupId == g.Id).ToList(); + } + + return version.ToPackage(apiBase); } public async Task UserAskForPackageDeletionAsync @@ -256,7 +264,7 @@ namespace isnd.Services } - public IEnumerable SearchCatalogEntriesById + public IEnumerable SearchCatalogEntriesById (string pkgId, string semver, string pkgType, bool preRelease) { // PackageDependency @@ -278,6 +286,7 @@ namespace isnd.Services return dbContext.PackageVersions .Include(v => v.Package) .Include(v => v.LatestCommit) + .Include(v => v.DependencyGroups.Last().Dependencies) .Single(v => v.PackageId == pkgId && semver == v.FullString && (pkgType == null || pkgType == v.Type)); } @@ -288,18 +297,25 @@ namespace isnd.Services // RegistrationPageIndexAndQuery if (string.IsNullOrWhiteSpace(query.Query)) return null; query.Query = query.Query.ToLower(); - var scope = await dbContext.Packages - .Include(p => p.Versions) - .Include(p => p.Owner) + var scope = await dbContext.PackageVersions + .Include(p => p.Package) + .Include(p => p.Package.Owner) .Include(p => p.LatestCommit) - .SingleOrDefaultAsync(p => p.Id.ToLower() == query.Query); + .Where(p => p.PackageId.ToLower() == query.Query).ToArrayAsync(); if (scope == null) return null; - if (scope.Versions.Count == 0) return null; + if (scope.Length == 0) return null; string bid = $"{apiBase}{ApiConfig.Registration}"; - foreach (var version in scope.Versions) + + foreach (var version in scope) + { + version.DependencyGroups = dbContext.PackageDependencyGroups.Include(d => d.Dependencies) + .Where(d => d.PackageId == version.PackageId && d.PackageVersionFullString == version.FullString) + .ToList(); version.LatestCommit = dbContext.Commits.Single(c => c.Id == version.CommitNId); + } + return - new PackageRegistration(apiBase, scope); + new PackageRegistration(apiBase, query.Query, scope); } public async Task SearchPackageAsync(PackageRegistrationQuery query) @@ -307,19 +323,21 @@ namespace isnd.Services string bid = $"{apiBase}{ApiConfig.Registration}"; if (string.IsNullOrWhiteSpace(query.Query)) query.Query = ""; - var scope = dbContext.Packages - .Include(p => p.Owner) - .Include(p => p.Versions) - .Include(p => p.LatestCommit) - .Include(p => p.LatestCommit.Versions) - .Where(p => p.Id.StartsWith(query.Query) - && p.LatestCommit != null - && (query.Prerelease || p.Versions.Any(p => !p.IsPrerelease)) - && p.Versions.Count() > 0) - .OrderBy(p => p.CommitNId); - - return new PackageSearchResult(await scope.Skip(query.Skip).Take(query.Take) - .ToListAsync(), apiBase, scope.Count()); + + var packages = await dbContext.Packages + .Include(g => g.Versions) + .Where(d => d.Id.StartsWith(query.Query) + && (query.Prerelease || d.Versions.Any(v => !v.IsPrerelease))) + .Skip(query.Skip).Take(query.Take).ToArrayAsync(); + foreach (var package in packages) + foreach (var version in package.Versions) + { + version.DependencyGroups = dbContext.PackageDependencyGroups.Include(d => d.Dependencies) + .Where(d => d.PackageVersionFullString == version.FullString && d.PackageId == version.PackageId) + .ToList(); + } + return new PackageSearchResult(packages, apiBase, packages.Count()); + } public async Task PutPackageAsync(Stream packageStream, string ownerId) @@ -337,109 +355,130 @@ namespace isnd.Services string fullPath; using var specificationStream = spec.Open(); - - using XmlReader xmlReader = XmlReader.Create(specificationStream); - - var xMeta = XElement.Load(xmlReader, LoadOptions.None).Descendants().First(); - - string packageDescription = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "description")?.Value; - - var frameWorks = xMeta - .Descendants().FirstOrDefault(x => x.Name.LocalName =="frameworkReferences") - .Descendants().Where(x => x.Name.LocalName =="group") - .Select(x=> x.Attribute("targetFramework").Value).ToArray(); - var types = "Package"; - - pkgId = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName =="id")?.Value; - string pkgVersion = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName =="version")?.Value; - - if (!NuGetVersion.TryParse(pkgVersion, out nugetVersion)) - throw new InvalidPackageException("metadata/version"); - - var frameworkReferences = frameWorks.Select(g => new PackageDependencyGroup - { - TargetFramework = g - } - ).ToList(); - - string packageIdPath = Path.Combine(isndSettings.PackagesRootDir, - pkgId); - pkgPath = Path.Combine(packageIdPath, nugetVersion.ToFullString()); - string name = $"{pkgId}-{nugetVersion}." + Constants.PacketFileExtension; - fullPath = Path.Combine(pkgPath, name); - - var packageIdPathInfo = new DirectoryInfo(packageIdPath); - Data.Packages.Package pkg = dbContext.Packages.SingleOrDefault(p => p.Id == pkgId); - Commit commit = new Commit + + using XmlReader xmlReader = XmlReader.Create(specificationStream); + + var xMeta = XElement.Load(xmlReader, LoadOptions.None).Descendants().First(); + + string packageDescription = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "description")?.Value; + + var frameWorks = xMeta + .Descendants().FirstOrDefault(x => x.Name.LocalName == "frameworkReferences") + .Descendants().Where(x => x.Name.LocalName == "group") + .Select(x => NewFrameworkDependencyGroup(x)).ToArray(); + var types = "Package"; + + pkgId = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "id")?.Value; + string pkgVersion = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "version")?.Value; + + if (!NuGetVersion.TryParse(pkgVersion, out nugetVersion)) + throw new InvalidPackageException("metadata/version"); + + + + + string packageIdPath = Path.Combine(isndSettings.PackagesRootDir, + pkgId); + pkgPath = Path.Combine(packageIdPath, nugetVersion.ToFullString()); + string name = $"{pkgId}-{nugetVersion}." + Constants.PacketFileExtension; + fullPath = Path.Combine(pkgPath, name); + + var packageIdPathInfo = new DirectoryInfo(packageIdPath); + Data.Packages.Package pkg = dbContext.Packages.SingleOrDefault(p => p.Id == pkgId); + Commit commit = new Commit + { + Action = PackageAction.PublishPackage, + TimeStamp = DateTimeOffset.Now.ToUniversalTime() + }; + if (pkg != null) + { + // Update + pkg.Description = packageDescription; + pkg.LatestCommit = commit; + } + else + { + // First version + pkg = new Data.Packages.Package { - Action = PackageAction.PublishPackage, - TimeStamp = DateTimeOffset.Now.ToUniversalTime() + Id = pkgId, + Description = packageDescription, + OwnerId = ownerId, + LatestCommit = commit }; - if (pkg != null) - { - // Update - pkg.Description = packageDescription; - pkg.LatestCommit = commit; - } - else - { - // First version - pkg = new Data.Packages.Package - { - Id = pkgId, - Description = packageDescription, - OwnerId = ownerId, - LatestCommit = commit - }; - dbContext.Packages.Add(pkg); - } - - // here, the package is or new, or owned by the key owner - if (!packageIdPathInfo.Exists) packageIdPathInfo.Create(); + dbContext.Packages.Add(pkg); + } - var dest = new FileInfo(fullPath); - var destDir = new DirectoryInfo(dest.DirectoryName); - if (dest.Exists) dest.Delete(); - if (!destDir.Exists) destDir.Create(); + // here, the package is or new, or owned by the key owner + if (!packageIdPathInfo.Exists) packageIdPathInfo.Create(); - packageStream.Seek(0, SeekOrigin.Begin); - using (var fileStream = File.Create(fullPath)) - { - await packageStream.CopyToAsync(fileStream); - } + var dest = new FileInfo(fullPath); + var destDir = new DirectoryInfo(dest.DirectoryName); + if (dest.Exists) dest.Delete(); + if (!destDir.Exists) destDir.Create(); - string fullStringVersion = nugetVersion.ToFullString(); - var pkgVersions = dbContext.PackageVersions.Where - (v => v.PackageId == pkg.Id && v.FullString == fullStringVersion); - if (pkgVersions.Count() > 0) - { - foreach (var v in pkgVersions.ToArray()) - dbContext.PackageVersions.Remove(v); - } + packageStream.Seek(0, SeekOrigin.Begin); + using (var fileStream = File.Create(fullPath)) + { + await packageStream.CopyToAsync(fileStream); + } - // FIXME default type or null - dbContext.PackageVersions.Add - (version = new PackageVersion - { + string fullStringVersion = nugetVersion.ToFullString(); + var pkgVersions = dbContext.PackageVersions.Where + (v => v.PackageId == pkg.Id && v.FullString == fullStringVersion); + if (pkgVersions.Count() > 0) + { + foreach (var v in pkgVersions.ToArray()) + dbContext.PackageVersions.Remove(v); + } + string versionFullString = nugetVersion.ToFullString(); - Package = pkg, - Major = nugetVersion.Major, - Minor = nugetVersion.Minor, - Patch = nugetVersion.Patch, - Revision = nugetVersion.Revision, - IsPrerelease = nugetVersion.IsPrerelease, - FullString = nugetVersion.ToFullString(), - Type =types, - LatestCommit = commit - }); + // FIXME default package type or null + dbContext.PackageVersions.Add + (version = new PackageVersion + { + Package = pkg, + Major = nugetVersion.Major, + Minor = nugetVersion.Minor, + Patch = nugetVersion.Patch, + Revision = nugetVersion.Revision, + IsPrerelease = nugetVersion.IsPrerelease, + FullString = versionFullString, + Type = types, + LatestCommit = commit + }); + + dbContext.Commits.Add(commit); + + foreach (var group in dbContext.PackageDependencyGroups.Include(g => g.PackageVersion) + .Where(x => x.PackageId == pkgId && x.PackageVersionFullString == versionFullString) + .ToList()) + { + dbContext.PackageDependencyGroups.Remove(group); + } + version.DependencyGroups = new List(); + foreach (var framework in frameWorks) + { + var group = new PackageDependencyGroup + { + TargetFramework = framework.FrameworkName, + PackageId = pkgId, + PackageVersionFullString = versionFullString, + Dependencies = framework.Dependencies.Select( + d => new Dependency + { + Id = d.PackageId, + Version = d.PackageVersion, + }).ToList() + }; + version.DependencyGroups.Add(group); + dbContext.PackageDependencyGroups.Add(group); - dbContext.Commits.Add(commit); + } + await dbContext.SaveChangesAsync(); + await UpdateCatalogForAsync(commit); - await dbContext.SaveChangesAsync(); - version.DependencyGroups = frameworkReferences; - await UpdateCatalogForAsync(commit); - using (var shaCrypto = System.Security.Cryptography.SHA512.Create()) { using (var stream = System.IO.File.OpenRead(fullPath)) @@ -465,5 +504,22 @@ namespace isnd.Services } return version; } + + private FrameworkDependencyGroup NewFrameworkDependencyGroup(XElement x) + { + var view = x.ToJson(); + var frameworkReferences = x.Descendants(); + var framework = x.Attribute("targetFramework").Value; + return new FrameworkDependencyGroup + { + FrameworkName = framework, + Dependencies = frameworkReferences.Select(r => new ShortDependencyInfo + { + PackageId = r.Attribute("name").Value, + PackageVersion = r.Attribute("version")?.Value + }).ToList() + }; + + } } } \ No newline at end of file diff --git a/src/isnd/Services/ShortDependencyInfo.cs b/src/isnd/Services/ShortDependencyInfo.cs new file mode 100644 index 0000000..8867051 --- /dev/null +++ b/src/isnd/Services/ShortDependencyInfo.cs @@ -0,0 +1,8 @@ +namespace isnd.Services +{ + public class ShortDependencyInfo + { + internal string PackageId { get; set;} + internal string PackageVersion { get; set;} + } +} \ No newline at end of file diff --git a/src/isnd/ViewModels/PackageHit.cs b/src/isnd/ViewModels/PackageHit.cs index f9fa840..cfea0f9 100644 --- a/src/isnd/ViewModels/PackageHit.cs +++ b/src/isnd/ViewModels/PackageHit.cs @@ -8,9 +8,10 @@ namespace isnd.ViewModels { public class PackageHit : Permalink { - public PackageHit(string id, string packageId) : base(id, "Package") + public PackageHit(string registrationId, string packageId) : base(registrationId, "Package") { PackageId = packageId; + registration = registrationId; } /// @@ -36,7 +37,7 @@ namespace isnd.ViewModels /// The absolute URL to the associated registration index /// /// - public string registration { get; set; } + public string registration { get; } public string summary { get; set; } public string[] tags { get; set; } public string title { get; set; } diff --git a/src/isnd/ViewModels/PackageSearchResult.cs b/src/isnd/ViewModels/PackageSearchResult.cs index b018dd1..f3cd486 100644 --- a/src/isnd/ViewModels/PackageSearchResult.cs +++ b/src/isnd/ViewModels/PackageSearchResult.cs @@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Reflection.Metadata.Ecma335; using System.Text.Json.Serialization; +using isnd.Data; using isnd.Data.Packages; using isnd.Entities; @@ -25,7 +26,7 @@ namespace isnd.ViewModels { this.result = result; this.ApiBase = apiBase; - data=result.Select(r => NewPackageHit(apiBase, r)).ToArray(); + data=result.Select(p=> NewPackageHit(apiBase, p)).ToArray(); this.totalHits = totalHit; } @@ -36,10 +37,7 @@ namespace isnd.ViewModels { version = package.GetLatestVersion(), description = package.Description, - title = package.Id, - versions = package.Versions.Select(v => new SearchVersionInfo(regId, v)).ToArray(), - registration = regId, - + versions = package.Versions.Select(v => new SearchVersionInfo(regId, v)).ToArray() }; } diff --git a/test/data/test-isn/ANuGet.Config b/test/data/test-isn/ANuGet.Config deleted file mode 100644 index e778008..0000000 --- a/test/data/test-isn/ANuGet.Config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/test/data/test-isn/test-isn.csproj b/test/data/test-isn/test-isn.csproj index 85e5cf3..0247e7a 100644 --- a/test/data/test-isn/test-isn.csproj +++ b/test/data/test-isn/test-isn.csproj @@ -1,7 +1,7 @@ - + Exe - net8.0 + net7.0 test_isn enable enable diff --git a/test/isnd.tests/UnitTestWebHost.cs b/test/isnd.tests/UnitTestWebHost.cs index 6881211..f3571b0 100644 --- a/test/isnd.tests/UnitTestWebHost.cs +++ b/test/isnd.tests/UnitTestWebHost.cs @@ -155,10 +155,11 @@ namespace isnd.host.tests repository.PackageSource.AllowInsecureConnections=true; PackageSearchResource resource = await repository.GetResourceAsync(); + SearchFilter searchFilter = new SearchFilter(includePrerelease: true); IEnumerable results = await resource.SearchAsync( - "isn", + "isnd", searchFilter, skip: 0, take: 20, @@ -169,7 +170,7 @@ namespace isnd.host.tests { Console.WriteLine($"Found package {result.Identity.Id} {result.Identity.Version}"); } - + Assert.True( results.Any(result => result.DependencySets.Any())); } [Fact] @@ -182,6 +183,7 @@ namespace isnd.host.tests await pushRes.Push(new List{ "../../../../../src/isnd/bin/Release/isnd.1.1.4.nupkg" }, null, 5000, false, GetApiKey, GetSymbolsApiKey, false, false, symbolPackageResource, logger); + } [Fact]