Package deletion and types

main
Paul Schneider 5 months ago
parent 62a8bf27cb
commit 01405abdf2
14 changed files with 67 additions and 70 deletions

@ -20,7 +20,7 @@ namespace isnd.Controllers
int take=25, int take=25,
bool prerelease=false, bool prerelease=false,
string semVerLevel = "2.0.0", string semVerLevel = "2.0.0",
string packageType = null) string packageType = "Dependency")
{ {
PackageRegistrationQuery query = new PackageRegistrationQuery PackageRegistrationQuery query = new PackageRegistrationQuery
{ {

@ -77,8 +77,8 @@ namespace isnd.Controllers
} }
var packageVersion = await dbContext.PackageVersions.Include(p => p.Package) var packageVersion = await dbContext.PackageVersions.Include(p => p.Package)
.FirstOrDefaultAsync(m => m.PackageId == pkgid .FirstOrDefaultAsync(m => m.PackageId == pkgid && m.FullString == version
&& m.FullString == version && m.Type == pkgtype); && (pkgtype!=null && m.Type == pkgtype || m.Type != "Delete" ));
if (packageVersion == null) return NotFound(); if (packageVersion == null) return NotFound();
if (!User.IsOwner(packageVersion)) return Unauthorized(); if (!User.IsOwner(packageVersion)) return Unauthorized();
var pkg = await packageManager.GetPackageAsync(pkgid, version, pkgtype); var pkg = await packageManager.GetPackageAsync(pkgid, version, pkgtype);
@ -87,18 +87,18 @@ namespace isnd.Controllers
// POST: PackageVersion/Delete/5 // POST: PackageVersion/Delete/5
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken] [ValidateAntiForgeryToken][Authorize]
public async Task<IActionResult> DeleteConfirmed(string PackageId, string FullString, public async Task<IActionResult> DeleteConfirmed(string pkgid, string version,
string Type) string type)
{ {
PackageVersion packageVersion = await dbContext.PackageVersions var packageVersion = await dbContext.PackageVersions
.Include(pv => pv.Package) .Include(pv => pv.Package)
.FirstOrDefaultAsync(m => m.PackageId == PackageId .Where(m => m.PackageId == pkgid
&& m.FullString == FullString && m.Type == Type); && m.FullString == version && (type==null || m.Type == type))
if (packageVersion == null) return NotFound(); .ToArrayAsync();
if (!User.IsOwner(packageVersion)) return Unauthorized(); if (packageVersion.Length==0) return NotFound();
if (!User.IsOwner(packageVersion.First())) return Unauthorized();
await packageManager.DeletePackageAsync(PackageId, FullString, Type); await packageManager.DeletePackageAsync(pkgid, version, type);
return RedirectToAction(nameof(Index)); return RedirectToAction(nameof(Index));
} }
} }

@ -7,23 +7,23 @@ using NuGet.Versioning;
namespace isnd.Data.Catalog namespace isnd.Data.Catalog
{ {
public class CatalogPage : Permalink public class RegistrationPage : Permalink
{ {
private readonly string pkgid; private readonly string pkgid;
private readonly List<RegistrationLeave> items; private readonly List<RegistrationLeaf> items;
private readonly string apiBase; private readonly string apiBase;
public CatalogPage (string pkgid, string apiBase) : base(apiBase + $"/registration/{pkgid}/index.json") public RegistrationPage (string pkgid, string apiBase) : base(apiBase + $"/registration/{pkgid}/index.json")
{ {
Parent = apiBase + $"/registration/{pkgid}/index.json"; Parent = apiBase + $"/registration/{pkgid}/index.json";
this.items = new List<RegistrationLeave>(); this.items = new List<RegistrationLeaf>();
this.pkgid = pkgid; this.pkgid = pkgid;
this.apiBase = apiBase; this.apiBase = apiBase;
} }
public CatalogPage(string pkgid, string apiBase, IEnumerable<PackageVersion> versions) : this(pkgid, apiBase) public RegistrationPage(string pkgid, string apiBase, IEnumerable<PackageVersion> versions) : this(pkgid, apiBase)
{ {
AddVersionRange(versions); AddVersionRange(versions);
} }
@ -39,7 +39,7 @@ namespace isnd.Data.Catalog
/// <value></value> /// <value></value>
[JsonProperty("items")] [JsonProperty("items")]
public RegistrationLeave[] Items { get => items.ToArray(); } public RegistrationLeaf[] Items { get => items.ToArray(); }
public void AddVersionRange(IEnumerable<PackageVersion> vitems) public void AddVersionRange(IEnumerable<PackageVersion> vitems)
{ {

@ -26,12 +26,12 @@ namespace isnd.Data.Catalog
/// <returns></returns> /// <returns></returns>
public PackageDetails(PackageVersion pkg, string apiBase): base( apiBase + ApiConfig.Registration + "/" + pkg.PackageId + "/" + pkg.FullString + ".json") public PackageDetails(PackageVersion pkg, string apiBase): base( apiBase + ApiConfig.Registration + "/" + pkg.PackageId + "/" + pkg.FullString + ".json")
{ {
PackageId = pkg.Package.Id; Title = PackageId = pkg.Package.Id;
Version = pkg.FullString; Version = pkg.FullString;
Authors = $"{pkg.Package.Owner.FullName} <${pkg.Package.Owner.Email}>"; Authors = $"{pkg.Package.Owner.FullName} <${pkg.Package.Owner.Email}>";
packageContent = apiBase + pkg.NugetLink; packageContent = apiBase + pkg.NugetLink;
CommitId = pkg.CommitId; CommitId = pkg.CommitId;
CommitTimeStamp = pkg.LatestCommit.CommitTimeStamp; Published = CommitTimeStamp = pkg.LatestCommit.CommitTimeStamp;
IsListed = !pkg.IsDeleted && pkg.Package.Public; IsListed = !pkg.IsDeleted && pkg.Package.Public;
if (pkg.DependencyGroups!=null) if (pkg.DependencyGroups!=null)
{ {

@ -12,14 +12,14 @@ namespace isnd.Data.Catalog
public PackageRegistration(string url) : base(url) public PackageRegistration(string url) : base(url)
{ {
Items = new List<CatalogPage>(); Items = new List<RegistrationPage>();
} }
public PackageRegistration(string apiBase, string pkgId, IEnumerable<PackageVersion> versions) : base($"{apiBase}{ApiConfig.Registration}/{pkgId}/index.json") public PackageRegistration(string apiBase, string pkgId, IEnumerable<PackageVersion> versions) : base($"{apiBase}{ApiConfig.Registration}/{pkgId}/index.json")
{ {
Items = new List<CatalogPage> Items = new List<RegistrationPage>
{ {
new CatalogPage(pkgId, apiBase, versions) new RegistrationPage(pkgId, apiBase, versions)
}; };
} }
@ -27,7 +27,7 @@ namespace isnd.Data.Catalog
public int Count { get => Items.Count; } public int Count { get => Items.Count; }
[JsonProperty("items")] [JsonProperty("items")]
public List<CatalogPage> Items { get; set; } public List<RegistrationPage> Items { get; set; }
} }
} }

@ -9,9 +9,9 @@ namespace isnd.Data.Catalog
/// Hosts a catalog entry, /// Hosts a catalog entry,
/// the atomic content reference /// the atomic content reference
/// </summary> /// </summary>
public class RegistrationLeave public class RegistrationLeaf
{ {
public RegistrationLeave(string apiBase, string pkgId, string fullVersionString, PackageDetails entry) public RegistrationLeaf(string apiBase, string pkgId, string fullVersionString, PackageDetails entry)
{ {
this.registration = apiBase + ApiConfig.Registration + "/" + pkgId + "/" + fullVersionString + ".json"; this.registration = apiBase + ApiConfig.Registration + "/" + pkgId + "/" + fullVersionString + ".json";

@ -50,7 +50,7 @@ namespace isnd.Data.Packages
internal string GetLatestVersion() internal string GetLatestVersion()
{ {
return Versions.Max(v => v.NugetVersion).ToFullString(); return Versions.Max(v => v.NugetVersion)?.ToFullString();
} }
} }
} }

@ -74,9 +74,9 @@ namespace isnd.Data
public string SementicVersionString { get => $"{Major}.{Minor}.{Patch}"; } public string SementicVersionString { get => $"{Major}.{Minor}.{Patch}"; }
public NuGetVersion NugetVersion { get => new NuGetVersion(FullString); } public NuGetVersion NugetVersion { get => new NuGetVersion(FullString); }
public Catalog.RegistrationLeave ToPackage(string apiBase) public Catalog.RegistrationLeaf ToPackage(string apiBase)
{ {
return new Catalog.RegistrationLeave(apiBase, this.PackageId , FullString, new Catalog.PackageDetails(this, apiBase)); return new Catalog.RegistrationLeaf(apiBase, this.PackageId , FullString, new Catalog.PackageDetails(this, apiBase));
} }
public bool IsDeleted => LatestCommit?.Action == PackageAction.DeletePackage; public bool IsDeleted => LatestCommit?.Action == PackageAction.DeletePackage;

@ -22,8 +22,8 @@ namespace isnd.Interfaces
Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type); Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type);
Task<PackageDeletionReport> UserAskForPackageDeletionAsync(string userid, string pkgId, string lower, string type); Task<PackageDeletionReport> UserAskForPackageDeletionAsync(string userid, string pkgId, string lower, string type);
Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type); Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type);
Task<Data.Catalog.RegistrationLeave> GetCatalogEntryAsync(string pkgId, string version, string pkgType); Task<Data.Catalog.RegistrationLeaf> GetCatalogEntryAsync(string pkgId, string version, string pkgType);
IEnumerable<Data.Catalog.RegistrationLeave> SearchCatalogEntriesById(string pkgId, string semver, string pkgType, bool preRelease); IEnumerable<Data.Catalog.RegistrationLeaf> SearchCatalogEntriesById(string pkgId, string semver, string pkgType, bool preRelease);
Task<PackageRegistration> GetCatalogIndexAsync(); Task<PackageRegistration> GetCatalogIndexAsync();
Task<PackageRegistration> GetPackageRegistrationIndexAsync(PackageRegistrationQuery query); Task<PackageRegistration> GetPackageRegistrationIndexAsync(PackageRegistrationQuery query);

@ -164,22 +164,20 @@ namespace isnd.Services
i = isndSettings.CatalogPageLen; i = isndSettings.CatalogPageLen;
foreach (var commit in scope) foreach (var commit in scope)
{ {
var validPkgs = (await dbContext.Packages var validPkgs = (await dbContext.Packages
.Include(po => po.Owner) .Include(po => po.Owner)
.Include(pkg => pkg.Versions) .Include(pkg => pkg.Versions)
.Include(pkg => pkg.LatestCommit) .Include(pkg => pkg.LatestCommit)
.ToArrayAsync()) .ToArrayAsync())
.GroupBy((q) => q.Id); .GroupBy((q) => q.Id);
foreach (var pkgIdGroup in validPkgs) foreach (var pkgIdGroup in validPkgs)
{ {
CatalogPage page = index.Items.FirstOrDefault RegistrationPage page = index.Items.FirstOrDefault
(p => p.GetPackageId() == pkgIdGroup.Key); (p => p.GetPackageId() == pkgIdGroup.Key);
if (page == null) if (page == null)
{ {
page = new CatalogPage(pkgIdGroup.Key, apiBase); page = new RegistrationPage(pkgIdGroup.Key, apiBase);
index.Items.Add(page); index.Items.Add(page);
} }
@ -225,12 +223,12 @@ namespace isnd.Services
return await dbContext.PackageVersions.SingleOrDefaultAsync( return await dbContext.PackageVersions.SingleOrDefaultAsync(
v => v.PackageId == pkgId && v => v.PackageId == pkgId &&
v.FullString == version && v.FullString == version &&
v.Type == type (type==null || v.Type == type)
); );
} }
public async Task<Data.Catalog.RegistrationLeave> GetCatalogEntryAsync public async Task<Data.Catalog.RegistrationLeaf> GetCatalogEntryAsync
(string pkgId, string semver, string pkgType = null) (string pkgId, string semver, string pkgType = "Dependency")
{ {
var version = await dbContext.PackageVersions var version = await dbContext.PackageVersions
.Include(v => v.Package) .Include(v => v.Package)
@ -241,13 +239,12 @@ namespace isnd.Services
.Where(v => v.PackageId == pkgId .Where(v => v.PackageId == pkgId
&& v.FullString == semver && v.FullString == semver
&& v.LatestCommit != null && v.LatestCommit != null
&& (pkgType == null || pkgType == v.Type)
).SingleOrDefaultAsync(); ).SingleOrDefaultAsync();
foreach (var g in version.DependencyGroups) foreach (var g in version.DependencyGroups)
{ {
g.Dependencies = dbContext.Dependencies.Where(d => d.DependencyGroupId == g.Id).ToList(); g.Dependencies = dbContext.Dependencies.Where(d => d.DependencyGroupId == g.Id).ToList();
} }
return version.ToPackage(apiBase); return version.ToPackage(apiBase);
} }
@ -257,14 +254,14 @@ namespace isnd.Services
PackageVersion packageVersion = await dbContext.PackageVersions PackageVersion packageVersion = await dbContext.PackageVersions
.Include(pv => pv.Package) .Include(pv => pv.Package)
.FirstOrDefaultAsync(m => m.PackageId == id .FirstOrDefaultAsync(m => m.PackageId == id
&& m.FullString == lower && m.Type == type); && m.FullString == lower && (type==null || m.Type == type));
if (packageVersion == null) return null; if (packageVersion == null) return null;
if (packageVersion.Package.OwnerId != uid) return null; if (packageVersion.Package.OwnerId != uid) return null;
return new PackageDeletionReport { Deleted = true, DeletedVersion = packageVersion }; return new PackageDeletionReport { Deleted = true, DeletedVersion = packageVersion };
} }
public IEnumerable<Data.Catalog.RegistrationLeave> SearchCatalogEntriesById public IEnumerable<Data.Catalog.RegistrationLeaf> SearchCatalogEntriesById
(string pkgId, string semver, string pkgType, bool preRelease) (string pkgId, string semver, string pkgType, bool preRelease)
{ {
// PackageDependency // PackageDependency
@ -294,7 +291,6 @@ namespace isnd.Services
public async Task<PackageRegistration> GetPackageRegistrationIndexAsync public async Task<PackageRegistration> GetPackageRegistrationIndexAsync
(PackageRegistrationQuery query) (PackageRegistrationQuery query)
{ {
// RegistrationPageIndexAndQuery
if (string.IsNullOrWhiteSpace(query.Query)) return null; if (string.IsNullOrWhiteSpace(query.Query)) return null;
query.Query = query.Query.ToLower(); query.Query = query.Query.ToLower();
var scope = await dbContext.PackageVersions var scope = await dbContext.PackageVersions
@ -305,7 +301,6 @@ namespace isnd.Services
if (scope == null) return null; if (scope == null) return null;
if (scope.Length == 0) return null; if (scope.Length == 0) return null;
string bid = $"{apiBase}{ApiConfig.Registration}"; string bid = $"{apiBase}{ApiConfig.Registration}";
foreach (var version in scope) foreach (var version in scope)
{ {
version.DependencyGroups = dbContext.PackageDependencyGroups.Include(d => d.Dependencies) version.DependencyGroups = dbContext.PackageDependencyGroups.Include(d => d.Dependencies)
@ -313,9 +308,7 @@ namespace isnd.Services
.ToList(); .ToList();
version.LatestCommit = dbContext.Commits.Single(c => c.Id == version.CommitNId); version.LatestCommit = dbContext.Commits.Single(c => c.Id == version.CommitNId);
} }
return new PackageRegistration(apiBase, query.Query, scope);
return
new PackageRegistration(apiBase, query.Query, scope);
} }
public async Task<PackageSearchResult> SearchPackageAsync(PackageRegistrationQuery query) public async Task<PackageSearchResult> SearchPackageAsync(PackageRegistrationQuery query)
@ -325,19 +318,20 @@ namespace isnd.Services
query.Query = ""; query.Query = "";
var packages = await dbContext.Packages var packages = await dbContext.Packages
.Include(g => g.Versions) .Include(g => g.Versions).OrderBy(v=>v.CommitNId)
.Where(d => d.Id.StartsWith(query.Query) .Where(d => d.Id.StartsWith(query.Query)
&& (query.Prerelease || d.Versions.Any(v => !v.IsPrerelease))) && (query.Prerelease || d.Versions.Any(v => !v.IsPrerelease)))
.Where(p=>p.Versions.Count>=0)
.Skip(query.Skip).Take(query.Take).ToArrayAsync(); .Skip(query.Skip).Take(query.Take).ToArrayAsync();
foreach (var package in packages) foreach (var package in packages)
foreach (var version in package.Versions) foreach (var version in package.Versions)
{ {
version.DependencyGroups = dbContext.PackageDependencyGroups.Include(d => d.Dependencies) version.DependencyGroups = dbContext.PackageDependencyGroups.Include(d => d.Dependencies)
.Where(d => d.PackageVersionFullString == version.FullString && d.PackageId == version.PackageId) .Where(d => d.PackageVersionFullString == version.FullString && d.PackageId == version.PackageId)
.ToList(); .ToList();
} }
return new PackageSearchResult(packages, apiBase, packages.Count()); return new PackageSearchResult(packages, apiBase, packages.Count());
} }
public async Task<PackageVersion> PutPackageAsync(Stream packageStream, string ownerId) public async Task<PackageVersion> PutPackageAsync(Stream packageStream, string ownerId)
@ -370,17 +364,14 @@ namespace isnd.Services
var frameWorks = (dependencies ?? frameworkReferences) var frameWorks = (dependencies ?? frameworkReferences)
.Descendants().Where(x => x.Name.LocalName == "group") .Descendants().Where(x => x.Name.LocalName == "group")
.Select(x => NewFrameworkDependencyGroup(x)).ToArray(); .Select(x => NewFrameworkDependencyGroup(x)).ToArray();
var types = "Package"; // FIXME default package type or null
var types = "Dependency";
pkgId = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "id")?.Value; pkgId = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "id")?.Value;
string pkgVersion = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "version")?.Value; string pkgVersion = xMeta.Descendants().FirstOrDefault(x => x.Name.LocalName == "version")?.Value;
if (!NuGetVersion.TryParse(pkgVersion, out nugetVersion)) if (!NuGetVersion.TryParse(pkgVersion, out nugetVersion))
throw new InvalidPackageException("metadata/version"); throw new InvalidPackageException("metadata/version");
string packageIdPath = Path.Combine(isndSettings.PackagesRootDir, string packageIdPath = Path.Combine(isndSettings.PackagesRootDir,
pkgId); pkgId);
pkgPath = Path.Combine(packageIdPath, nugetVersion.ToFullString()); pkgPath = Path.Combine(packageIdPath, nugetVersion.ToFullString());
@ -397,21 +388,20 @@ namespace isnd.Services
if (pkg != null) if (pkg != null)
{ {
// Update // Update
pkg.Description = packageDescription;
pkg.LatestCommit = commit;
} }
else else
{ {
// First version // First version
pkg = new Data.Packages.Package pkg = new Package
{ {
Id = pkgId, Id = pkgId,
Description = packageDescription,
OwnerId = ownerId, OwnerId = ownerId,
LatestCommit = commit
}; };
dbContext.Packages.Add(pkg); dbContext.Packages.Add(pkg);
} }
pkg.Public = true;
pkg.LatestCommit = commit;
pkg.Description = packageDescription;
// here, the package is or new, or owned by the key owner // here, the package is or new, or owned by the key owner
if (!packageIdPathInfo.Exists) packageIdPathInfo.Create(); if (!packageIdPathInfo.Exists) packageIdPathInfo.Create();
@ -437,7 +427,6 @@ namespace isnd.Services
} }
string versionFullString = nugetVersion.ToFullString(); string versionFullString = nugetVersion.ToFullString();
// FIXME default package type or null
dbContext.PackageVersions.Add dbContext.PackageVersions.Add
(version = new PackageVersion (version = new PackageVersion
{ {

@ -6,6 +6,7 @@ using System.Text.Json.Serialization;
using isnd.Data; using isnd.Data;
using isnd.Data.Packages; using isnd.Data.Packages;
using isnd.Entities; using isnd.Entities;
using NuGet.Packaging.Core;
namespace isnd.ViewModels namespace isnd.ViewModels
{ {
@ -37,7 +38,11 @@ namespace isnd.ViewModels
{ {
version = package.GetLatestVersion(), version = package.GetLatestVersion(),
description = package.Description, description = package.Description,
versions = package.Versions.Select(v => new SearchVersionInfo(regId, v)).ToArray() versions = package.Versions.Select(v => new SearchVersionInfo(apiBase, v)).ToArray(),
packageTypes = package.Versions.Select(v=>new PackageType(v.Type, new System.Version(v.Major,v.Minor,v.Patch, v.Revision)))
.ToArray(),
}; };
} }

@ -1,11 +1,13 @@
using isnd.Data.Catalog; using isnd.Data.Catalog;
using isnd.Entities;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.ViewModels namespace isnd.ViewModels
{ {
public class SearchVersionInfo: Permalink public class SearchVersionInfo: Permalink
{ {
public SearchVersionInfo(string id, Data.PackageVersion v) : base(id, "VersionInfo") public SearchVersionInfo(string apiBase, Data.PackageVersion v) : base( $"{apiBase}{ApiConfig.Registration}/{v.PackageId}/{v.FullString}.json", "VersionInfo")
{ {
Version = v.FullString; Version = v.FullString;
} }

@ -42,12 +42,13 @@
@Html.DisplayFor(model => model.Package.Id) @Html.DisplayFor(model => model.Package.Id)
</dd> </dd>
</dl> </dl>
@if (Model!=null) {
<form asp-action="DeleteConfirmed"> <form asp-action="DeleteConfirmed">
<input type="hidden" asp-for="PackageId" /> <input type="hidden" name="pkgid" value="@Model.PackageId" />
<input type="hidden" asp-for="FullString" /> <input type="hidden" name="version" value="@Model.FullString" />
<input type="hidden" asp-for="Type" /> <input type="hidden" name="type" value="@Model.Type" />
<input type="submit" value="Delete" class="btn btn-default" /> | <input type="submit" value="Delete" class="btn btn-default" /> |
<a asp-action="Index">Back to List</a> <a asp-action="Index">Back to List</a>
</form> </form>
}
</div> </div>

@ -170,7 +170,7 @@ namespace isnd.host.tests
{ {
Console.WriteLine($"Found package {result.Identity.Id} {result.Identity.Version}"); Console.WriteLine($"Found package {result.Identity.Id} {result.Identity.Version}");
} }
Assert.True( results.Any(result => result.DependencySets.Any())); Assert.NotEmpty( results.Where(result => result.DependencySets.Any()));
} }
[Fact] [Fact]

Loading…