diff --git a/src/isnd/Controllers/Packages/PackagesController.Put.cs b/src/isnd/Controllers/Packages/PackagesController.Put.cs index 172d261..b87b6bd 100644 --- a/src/isnd/Controllers/Packages/PackagesController.Put.cs +++ b/src/isnd/Controllers/Packages/PackagesController.Put.cs @@ -1,3 +1,4 @@ +using Microsoft.VisualBasic.CompilerServices; using System.Linq.Expressions; using System; @@ -21,6 +22,8 @@ using isnd.Data.Packages; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.ModelBinding; using isn; +using isnd.Helpers; +using Microsoft.EntityFrameworkCore; namespace isnd.Controllers { @@ -52,7 +55,7 @@ namespace isnd.Controllers TimeStamp = DateTimeOffset.Now.ToUniversalTime() }; - dbContext.Commits.Add(commit); + foreach (IFormFile file in Request.Form.Files) { @@ -108,7 +111,7 @@ namespace isnd.Controllers Id = pkgid, Description = pkgdesc, OwnerId = apikey.UserId, - LatestVersion = commit + LatestCommit = commit }; dbContext.Packages.Add(pkg); } @@ -119,22 +122,26 @@ namespace isnd.Controllers var destdir = new DirectoryInfo(dest.DirectoryName); if (dest.Exists) { + logger.LogWarning($"Existant package in disk : {dest.FullName}"); // La version existe sur le disque, // mais si elle ne l'est pas en base de donnéés, // on remplace la version sur disque. string exFullString = version.ToFullString(); - var pkgv = dbContext.PackageVersions.Where( + var pkgv = dbContext.PackageVersions. + Include(v=>v.LatestCommit) + .Single( v => v.PackageId == pkg.Id && v.FullString == exFullString ); - if (pkgv !=null && !pkgv.Any()) + if (pkgv!=null && pkgv.IsDeleted) { dest.Delete(); } - else { - string msg = $"existant {pkg.Id}-{exFullString}"; + else if (pkgv != null) + { + string msg = $"existant : {pkg.Id}-{exFullString}"; logger.LogWarning("400 : {msg}", msg); ModelState.AddModelError("pkgversion", msg); - return BadRequest(CreateAPIKO("existant", ModelState)); + return BadRequest(this.CreateAPIKO("existant")); } } { @@ -182,8 +189,9 @@ namespace isnd.Controllers dbContext.PackageVersions.Add(pkgver); } + dbContext.Commits.Add(commit); await dbContext.SaveChangesAsync(); - packageManager.ÛpdateCatalogForAsync(commit); + await packageManager.ÛpdateCatalogForAsync(commit); logger.LogInformation($"new paquet : {spec.Name}"); } @@ -204,7 +212,7 @@ namespace isnd.Controllers } } string nuspecfullpath = Path.Combine(pkgpath, pkgid + "." + Constants.SpecFileEstension); - FileInfo nfpi = new FileInfo(nuspecfullpath); + FileInfo nfpi = new(nuspecfullpath); if (nfpi.Exists) nfpi.Delete(); @@ -215,23 +223,12 @@ namespace isnd.Controllers } catch (Exception ex) { - logger.LogError(ex.Message); - logger.LogError("Stack Trace: " + ex.StackTrace); + logger.LogError("PUT exception : " + ex.Message); + logger.LogError("Stack Trace : " + ex.StackTrace); return new ObjectResult(new { ViewData, ex.Message }) { StatusCode = 500 }; } } - public APIKO CreateAPIKO(string context, ModelStateDictionary modelState) - { - Dictionary errors = new(); - - foreach (var elt in modelState) - { - errors[elt.Key] = elt.Value.Errors.Select( e => e.ErrorMessage).ToArray(); - } - return new APIKO{ Context = context, Errors = errors }; - } - } } diff --git a/src/isnd/Data/Catalog/CatalogEntry.cs b/src/isnd/Data/Catalog/CatalogEntry.cs index 0067936..2edfbbc 100644 --- a/src/isnd/Data/Catalog/CatalogEntry.cs +++ b/src/isnd/Data/Catalog/CatalogEntry.cs @@ -9,19 +9,21 @@ using isnd.Interfaces; namespace isnd.Data.Catalog { - public class CatalogEntry : Permalink, IObject// , IPackageDetails + public class PackageDetails : Permalink, IObject { /// /// Creates a catalog entry /// /// package details url /// - public CatalogEntry(string id): base(id) - { - + public PackageDetails(PackageVersion pkg, string apiBase, string uri): base(uri) + { + PackageId = pkg.Package.Id; + Version = pkg.FullString; + authors = $"{pkg.Package.Owner.FullName} <${pkg.Package.Owner.Email}>"; + packageContent = apiBase + pkg.NugetLink; } - [JsonProperty("@type")] public string[] RefType { get; protected set; } = new string[] { "PackageDetails" }; @@ -99,5 +101,8 @@ namespace isnd.Data.Catalog [JsonProperty("version")] public string Version { get; set; } + [Required,JsonRequired] + [JsonProperty("id")] + public string PackageId { get; set; } } } \ No newline at end of file diff --git a/src/isnd/Data/Catalog/PackageRegistration.cs b/src/isnd/Data/Catalog/PackageRegistration.cs index 9fefbec..33b96a4 100644 --- a/src/isnd/Data/Catalog/PackageRegistration.cs +++ b/src/isnd/Data/Catalog/PackageRegistration.cs @@ -14,18 +14,17 @@ namespace isnd.Data.Catalog Items = new List(); } - public PackageRegistration(string bid, string id, string apiBase, Packages.Package pkg) : base(bid + $"/{id}/index.json") + public PackageRegistration(string bid, string apiBase, Packages.Package pkg) : base(bid + $"/{pkg.Id}/index.json") { Items = new List { - new CatalogPage(bid, id, apiBase, pkg.Versions) + new CatalogPage(bid, pkg.Id, apiBase, pkg.Versions) }; - if (pkg.Versions.Count>0) - { - CommitId = pkg.Versions.Max(v=>v.CommitNId).ToString(); - CommitTimeStamp = pkg.Versions.Max(v=>v.LatestCommit.CommitTimeStamp); - } + + CommitId = pkg.LatestCommit.CommitId; + CommitTimeStamp = pkg.LatestCommit.CommitTimeStamp; + } [JsonProperty("count")] diff --git a/src/isnd/Data/Catalog/RegistratioinLeave.cs b/src/isnd/Data/Catalog/RegistratioinLeave.cs index c604cbb..f617059 100644 --- a/src/isnd/Data/Catalog/RegistratioinLeave.cs +++ b/src/isnd/Data/Catalog/RegistratioinLeave.cs @@ -11,9 +11,11 @@ namespace isnd.Data.Catalog /// public class Package { - public Package(string apiBase, string pkgId, string fullVersionString, CatalogEntry entry) + public Package(string apiBase, string pkgId, string fullVersionString, PackageDetails entry) { - this.registration = apiBase + ApiConfig.Registration + "/" + pkgId + "/index.json"; + + this.registration = apiBase + ApiConfig.Registration + "/" + pkgId + "/" + fullVersionString + ".json"; + Id = registration; this.PackageContent = apiBase + ApiConfig.Nuget + "/" + pkgId + "/" + fullVersionString + "/" + pkgId + "-" + fullVersionString + "." + Constants.PaquetFileEstension; Entry = entry; @@ -38,7 +40,7 @@ namespace isnd.Data.Catalog /// /// [JsonProperty("catalogEntry")] - public CatalogEntry Entry { get; set; } + public PackageDetails Entry { get; set; } /// /// The URL to the package content (.nupkg) diff --git a/src/isnd/Data/Packages/Package.cs b/src/isnd/Data/Packages/Package.cs index 21e37ee..c140f08 100644 --- a/src/isnd/Data/Packages/Package.cs +++ b/src/isnd/Data/Packages/Package.cs @@ -20,7 +20,7 @@ namespace isnd.Data.Packages List Versions { get; set; } long CommitNId { get; set; } string CommitId { get; } - Commit LatestVersion { get; set; } + Commit LatestCommit { get; set; } DateTimeOffset CommitTimeStamp { get; set; } } @@ -61,7 +61,7 @@ namespace isnd.Data.Packages [ForeignKey("CommitNId")] - public virtual Commit LatestVersion { get; set; } + public virtual Commit LatestCommit { get; set; } public DateTimeOffset CommitTimeStamp { get; set; } } diff --git a/src/isnd/Data/Packages/PackageVersion.cs b/src/isnd/Data/Packages/PackageVersion.cs index a96e061..77940d5 100644 --- a/src/isnd/Data/Packages/PackageVersion.cs +++ b/src/isnd/Data/Packages/PackageVersion.cs @@ -6,11 +6,13 @@ using isnd.Data.Catalog; using isnd.Data.Packages; using isnd.Data.Packages.Catalog; using isnd.Entities; +using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using NuGet.Versioning; namespace isnd.Data { + [PrimaryKey("PackageId", "FullString")] public class PackageVersion { [Required] @@ -37,7 +39,6 @@ namespace isnd.Data /// [StringLength(256)] [Required] - [Key] public string FullString { get; set; } public bool IsPrerelease { get; set; } @@ -67,14 +68,8 @@ namespace isnd.Data public Catalog.Package ToPackage(string apiBase) { - return new Catalog.Package(apiBase ,this.PackageId , FullString, - new CatalogEntry(apiBase + ApiConfig.Registration + "/" + this.PackageId + "/" + FullString + ".json") - { - Version = FullString, - authors = $"{this.Package.Owner.FullName} <${Package.Owner.Email}>", - packageContent = apiBase + this.NugetLink - } - ); + return new Catalog.Package(apiBase, this.PackageId , FullString, + new Catalog.PackageDetails(this, apiBase, apiBase + ApiConfig.Registration + "/" + this.PackageId + "/" + FullString + ".json")); } public bool IsDeleted => LatestCommit.Action == PackageAction.DeletePackage; } diff --git a/src/isnd/Helpers/ApiHelpers.cs b/src/isnd/Helpers/ApiHelpers.cs new file mode 100644 index 0000000..c83d2be --- /dev/null +++ b/src/isnd/Helpers/ApiHelpers.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using System.Linq; +using isn; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace isnd.Helpers +{ + public static class ApiHelpers + { + + static public APIKO CreateAPIKO(this Controller controller, string context) + { + Dictionary errors = new(); + + foreach (var elt in controller.ModelState) + { + errors[elt.Key] = elt.Value.Errors.Select( e => e.ErrorMessage).ToArray(); + } + return new APIKO{ Context = context, Errors = errors }; + } + } +} \ No newline at end of file diff --git a/src/isnd/Migrations/20230430192411_pkgversions.Designer.cs b/src/isnd/Migrations/20230430192411_pkgversions.Designer.cs new file mode 100644 index 0000000..22455e0 --- /dev/null +++ b/src/isnd/Migrations/20230430192411_pkgversions.Designer.cs @@ -0,0 +1,455 @@ +// +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("20230430192411_pkgversions")] + partial class pkgversions + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.4") + .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.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("CommitTimeStamp") + .HasColumnType("timestamp with time zone"); + + 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.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.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/20230430192411_pkgversions.cs b/src/isnd/Migrations/20230430192411_pkgversions.cs new file mode 100644 index 0000000..a4ac060 --- /dev/null +++ b/src/isnd/Migrations/20230430192411_pkgversions.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace isnd.Migrations +{ + /// + public partial class pkgversions : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_PackageVersions", + table: "PackageVersions"); + + migrationBuilder.DropIndex( + name: "IX_PackageVersions_PackageId", + table: "PackageVersions"); + + migrationBuilder.AddPrimaryKey( + name: "PK_PackageVersions", + table: "PackageVersions", + columns: new[] { "PackageId", "FullString" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_PackageVersions", + table: "PackageVersions"); + + migrationBuilder.AddPrimaryKey( + name: "PK_PackageVersions", + table: "PackageVersions", + column: "FullString"); + + migrationBuilder.CreateIndex( + name: "IX_PackageVersions_PackageId", + table: "PackageVersions", + column: "PackageId"); + } + } +} diff --git a/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs b/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs index 49000ab..a71c386 100644 --- a/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/isnd/Migrations/ApplicationDbContextModelSnapshot.cs @@ -160,7 +160,7 @@ namespace isnd.Migrations .ValueGeneratedOnAdd() .HasColumnType("text"); - b.Property("CreationDate") + b.Property("CreationDate") .HasColumnType("timestamp with time zone"); b.Property("Name") @@ -249,6 +249,10 @@ namespace isnd.Migrations modelBuilder.Entity("isnd.Data.PackageVersion", b => { + b.Property("PackageId") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + b.Property("FullString") .HasMaxLength(256) .HasColumnType("character varying(256)"); @@ -265,11 +269,6 @@ namespace isnd.Migrations b.Property("Minor") .HasColumnType("integer"); - b.Property("PackageId") - .IsRequired() - .HasMaxLength(1024) - .HasColumnType("character varying(1024)"); - b.Property("Patch") .HasColumnType("integer"); @@ -280,12 +279,10 @@ namespace isnd.Migrations .HasMaxLength(256) .HasColumnType("character varying(256)"); - b.HasKey("FullString"); + b.HasKey("PackageId", "FullString"); b.HasIndex("CommitNId"); - b.HasIndex("PackageId"); - b.ToTable("PackageVersions"); }); @@ -423,7 +420,7 @@ namespace isnd.Migrations modelBuilder.Entity("isnd.Data.Packages.Package", b => { - b.HasOne("isnd.Data.Packages.Commit", "LatestVersion") + b.HasOne("isnd.Data.Packages.Commit", "LatestCommit") .WithMany() .HasForeignKey("CommitNId") .OnDelete(DeleteBehavior.Cascade) @@ -435,7 +432,7 @@ namespace isnd.Migrations .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("LatestVersion"); + b.Navigation("LatestCommit"); b.Navigation("Owner"); }); diff --git a/src/isnd/NSJWebApiReferenceResolver.cs b/src/isnd/NSJWebApiReferenceResolver.cs index 07d4bb7..7e8864b 100644 --- a/src/isnd/NSJWebApiReferenceResolver.cs +++ b/src/isnd/NSJWebApiReferenceResolver.cs @@ -7,7 +7,7 @@ namespace isnd { internal class NSJWebApiReferenceResolver : IReferenceResolver { - private int delautIdCounter; + private int delautIdCounter; Dictionary HappyIdOwners { get; set; } diff --git a/src/isnd/Services/PackageManager.cs b/src/isnd/Services/PackageManager.cs index ec9890b..dcf7e65 100644 --- a/src/isnd/Services/PackageManager.cs +++ b/src/isnd/Services/PackageManager.cs @@ -150,7 +150,7 @@ namespace isnd.Services var validPkgs = (await dbContext.Packages .Include(po => po.Owner) .Include(pkg => pkg.Versions) - .Include(pkg => pkg.LatestVersion) + .Include(pkg => pkg.LatestCommit) .ToArrayAsync()) .GroupBy((q) => q.Id); @@ -274,13 +274,15 @@ 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) - .Include(p=>p.LatestVersion) + var scope = await dbContext.Packages + .Include(p => p.Versions) + .Include(p => p.Owner) + .Include(p=>p.LatestCommit) .SingleAsync(p => p.Id.ToLower() == query.Query); if (scope.Versions.Count==0) return null; string bid = $"{apiBase}{ApiConfig.Registration}"; return - new PackageRegistration(bid, query.Query, apiBase, scope); + new PackageRegistration(bid, apiBase, scope); } public async Task> SearchPackageAsync(PackageRegistrationQuery query) { @@ -288,17 +290,16 @@ namespace isnd.Services if (query.Query == null) query.Query = ""; var scope = (await dbContext.Packages - .Include(p => p.Versions) .Include(p => p.Owner) - .Include(p=>p.LatestVersion) - .Where(p => p.Id == query.Query - && (p.Versions.Any() && query.Prerelease || p.Versions.Any(v => !v.IsPrerelease))) - - .ToListAsync()); - var total = scope.Count(); - var pkgs = scope.Skip(query.Skip).Take(query.Take); - - return pkgs.Select(p => new PackageRegistration(bid, query.Query, apiBase, p)); + .Include(p => p.Versions) + .Include(p => p.LatestCommit) + .Where(p => p.Id.StartsWith(query.Query) + && (query.Prerelease || p.Versions.Any(p => !p.IsPrerelease))) + .Skip(query.Skip).Take(query.Take) + .ToListAsync() + ); + var pkgs = scope; + return pkgs.Select(p => new PackageRegistration(bid, apiBase, p)); } diff --git a/src/isnd/WebApiIdsNamingPolicy.cs b/src/isnd/WebApiIdsNamingPolicy.cs deleted file mode 100644 index ec34669..0000000 --- a/src/isnd/WebApiIdsNamingPolicy.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Text.Json; - -namespace isnd -{ - internal class TypeIdNamingPolicy : JsonNamingPolicy - { - public override string ConvertName(string name) - { - if (name == "Id") return "@id"; - if (name == "Type") return "@type"; - return "" + char.ToLower(name[0]) + name[1..]; - } - } -} \ No newline at end of file diff --git a/src/isnd/WebApiReferenceResolver.cs b/src/isnd/WebApiReferenceResolver.cs deleted file mode 100644 index f6a4b11..0000000 --- a/src/isnd/WebApiReferenceResolver.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text.Json.Serialization; -using isnd.Data.Catalog; - -namespace isnd -{ - class WebApiReferenceHandler : ReferenceHandler -{ - public WebApiReferenceHandler() => Reset(); - private ReferenceResolver? _rootedResolver; - public override ReferenceResolver CreateResolver() => _rootedResolver!; - public void Reset() => _rootedResolver = new WebApiReferenceResolver(); -} - - public class WebApiReferenceResolver : ReferenceResolver - { - private int delautIdCounter; - - Dictionary HappyIdOwners { get; set; } - - Dictionary Objects {get; set;} - - public WebApiReferenceResolver() - { - delautIdCounter = 0; - HappyIdOwners = new Dictionary(); - Objects = new Dictionary(); - } - - public override void AddReference(string referenceId, object value) - { - if (value is Permalink) - { - string hoi = (value as Permalink).GetId(); - if (HappyIdOwners.ContainsKey(hoi)) - { - return; - } - HappyIdOwners[hoi] = value as Permalink; - } - else - { - if (Objects.ContainsValue(value)) - { - return; - } - - delautIdCounter++; - Objects[delautIdCounter] = value; - } - } - - public override string GetReference(object value, out bool alreadyExists) - { - if (value is Permalink) - { - string oid = (value as Permalink).GetId(); - if (oid == null) - throw new System.Exception("HappyIdOwner Id property is null"); - if (HappyIdOwners.ContainsKey(oid)) - { - alreadyExists=true; - return oid; - } - alreadyExists=false; - AddReference(oid, value); - return oid; - } - alreadyExists=false; - - if (Objects.ContainsValue(value)) - { - alreadyExists=true; - return Objects.First( ode => ode.Value ==value).Key.ToString(); - } - alreadyExists=false; - delautIdCounter++; - Objects[delautIdCounter]=value; - return delautIdCounter.ToString(); - } - - public override object ResolveReference(string referenceId) - { - if (HappyIdOwners.ContainsKey(referenceId)) - return HappyIdOwners[referenceId]; - int refNId; - if (int.TryParse(referenceId, out refNId)) - { - if (Objects.ContainsKey(refNId)) - { - return Objects[refNId]; - } - } - return null; - } - } -} \ No newline at end of file