WIP page leaf

broken/ef
Paul Schneider 2 years ago
parent 2dcf1a2806
commit 7f9984b059
28 changed files with 164 additions and 75 deletions

@ -1,6 +1,6 @@
{ {
"omnisharp.msbuild": false, "omnisharp.msbuild": true,
"dotnet-test-explorer.testProjectPath": "**/*.sln", "dotnet-test-explorer.testProjectPath": "**/*Tests.csproj",
"dotnet-test-explorer.runInParallel": false, "dotnet-test-explorer.runInParallel": false,
"dotnet-test-explorer.showCodeLens": true, "dotnet-test-explorer.showCodeLens": true,
"dotnet-test-explorer.testArguments": "", "dotnet-test-explorer.testArguments": "",
@ -46,5 +46,7 @@
"database": "isnd", "database": "isnd",
"username": "paul" "username": "paul"
} }
] ],
"omnisharp.disableMSBuildDiagnosticWarning": true,
"omnisharp.enableRoslynAnalyzers": false
} }

@ -76,3 +76,50 @@ sudo chown -R root.root /usr/local/lib/isn
```` ````
## TODO ## TODO
```json
{
"@id": "https://api.nuget.org/v3/registration5-semver1/",
"@type": "RegistrationsBaseUrl",
"comment": "Base URL of Azure storage where NuGet package registration info is stored"
},
{
"@id": "https://api.nuget.org/v3-flatcontainer/",
"@type": "PackageBaseAddress/3.0.0",
"comment": "Base URL of where NuGet packages are stored, in the format https://api.nuget.org/v3-flatcontainer/{id-lower}/{version-lower}/{id-lower}.{version-lower}.nupkg"
},
{
"@id": "https://api.nuget.org/v3/registration5-semver1/",
"@type": "RegistrationsBaseUrl/3.0.0-rc",
"comment": "Base URL of Azure storage where NuGet package registration info is stored used by RC clients. This base URL does not include SemVer 2.0.0 packages."
},
{
"@id": "https://api.nuget.org/v3/registration5-semver1/",
"@type": "RegistrationsBaseUrl/3.0.0-beta",
"comment": "Base URL of Azure storage where NuGet package registration info is stored used by Beta clients. This base URL does not include SemVer 2.0.0 packages."
},
{
"@id": "https://www.nuget.org/packages/{id}/{version}?_src=template",
"@type": "PackageDetailsUriTemplate/5.1.0",
"comment": "URI template used by NuGet Client to construct details URL for packages"
},
{
"@id": "https://api.nuget.org/v3/registration5-gz-semver2/",
"@type": "RegistrationsBaseUrl/3.6.0",
"comment": "Base URL of Azure storage where NuGet package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
},
````

@ -25,10 +25,8 @@ namespace isnd.Controllers
public IActionResult Index() public IActionResult Index()
{ {
return View(new HomeIndexViewModel{ return View(new HomeIndexViewModel{
PkgCount = _dbContext.Packages PkgCount = _dbContext.Packages
.Include(p => p.Versions)
.Where(p => p.Versions.Count > 0) .Where(p => p.Versions.Count > 0)
.Count(), .Count(),
UnleashClient = _unleashĈlient UnleashClient = _unleashĈlient

@ -1,6 +1,5 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using isnd.Data.Catalog;
using isnd.Helpers; using isnd.Helpers;
using isnd.Services; using isnd.Services;
using isnd.Entities; using isnd.Entities;
@ -20,7 +19,7 @@ namespace isnd.Controllers
{ {
return Ok(PackageManager.CurrentCatalogIndex); return Ok(PackageManager.CurrentCatalogIndex);
} }
[HttpGet(_pkgRootPrefix + ApiConfig.CatalogPage + "-{id}")] [HttpGet(_pkgRootPrefix + ApiConfig.CatalogPage + "-{id}")]
public IActionResult Index(string id) public IActionResult Index(string id)
{ {
@ -28,21 +27,20 @@ namespace isnd.Controllers
return Ok(PackageManager.CurrentCatalogPages[int.Parse(id)]); return Ok(PackageManager.CurrentCatalogPages[int.Parse(id)]);
} }
[HttpGet(_pkgRootPrefix + ApiConfig.Registration + "/{id}/{*lower}")] [HttpGet(_pkgRootPrefix + "{apiVersion}/" + ApiConfig.Registration + "/{id}/{*lower}")]
public async Task<IActionResult> CatalogRegistrationAsync(string id, string lower) public async Task<IActionResult> CatalogRegistrationAsync(string apiVersion, string id, string lower)
{ {
bool askForindex = lower != null && lower.EndsWith(ApiConfig.Base);
if (askForindex)
{
lower = lower.Substring(0, lower.Length - ApiConfig.Base.Length);
}
string pkgType = ParamHelpers.Optional(ref lower); string pkgType = ParamHelpers.Optional(ref lower);
var pkgVersion = await dbContext.PackageVersions var pkgFromname = packageManager.SearchByName(id, 0, 1);
.Include(v => v.LatestCommit) if (pkgFromname == null) return NotFound();
.SingleOrDefaultAsync( return Ok(pkgFromname);
v => v.PackageId == id && }
v.FullString == lower &&
v.Type == pkgType
);
if (pkgVersion == null) return NotFound();
return Ok();
}
[HttpGet(_pkgRootPrefix + ApiConfig.CatalogLeaf + "/{id}/{version}/{*lower}")] [HttpGet(_pkgRootPrefix + ApiConfig.CatalogLeaf + "/{id}/{version}/{*lower}")]
public async Task<IActionResult> CatalogLeafAsync(string id, string version, string lower) public async Task<IActionResult> CatalogLeafAsync(string id, string version, string lower)
@ -50,25 +48,27 @@ namespace isnd.Controllers
var pkgvs = this.packageManager.GetCatalogLeaf(id, version, lower) var pkgvs = this.packageManager.GetCatalogLeaf(id, version, lower)
.ToArray(); .ToArray();
if (pkgvs.Count()==0) return NotFound(); if (pkgvs.Count() == 0) return NotFound();
List <string> types = pkgvs.Select( List<string> types = pkgvs.Select(
v => v.Type ?? "Dependency" v => v.Type ?? "Dependency"
).Distinct().ToList(); ).Distinct().ToList();
if (!types.Contains("PackageDelete")) if (!types.Contains("PackageDelete"))
types.Add("PackageDetails"); types.Add("PackageDetails");
var pub = pkgvs.Last().Package.CommitTimeStamp;
var last = pkgvs.Last();
var pub = last.Package.CommitTimeStamp;
var firstpub = pkgvs.First().Package.CommitTimeStamp; var firstpub = pkgvs.First().Package.CommitTimeStamp;
return Ok(new CatalogLeaf return Ok(new Data.Packages.Catalog.CatalogLeaf
{ {
CommitId = id, CommitId = last.CommitId,
Id = id, Id = id,
CommitTimeStamp = firstpub, CommitTimeStamp = pub,
Version = version, Version = last.FullString,
Published = pub, Published = pub,
RefType = types.ToArray(), RefType = types.ToArray(),
}); });
} }

@ -32,7 +32,7 @@ namespace isnd.Controllers
} }
// Web get spec // Web get spec
[HttpGet(_pkgRootPrefix + ApiConfig.GetNuspec + "/{id}/{lower}/{idf}-{lowerf}." [HttpGet(_pkgRootPrefix + Constants.SpecFileEstension + "/{id}/{lower}/{idf}-{lowerf}."
+ Constants.SpecFileEstension)] + Constants.SpecFileEstension)]
public IActionResult GetNuspec( public IActionResult GetNuspec(
[FromRoute][SafeName][Required] string id, [FromRoute][SafeName][Required] string id,

@ -6,7 +6,7 @@ namespace isnd.Controllers
{ {
public partial class PackagesController public partial class PackagesController
{ {
[HttpGet(_pkgRootPrefix + ApiConfig.GetVersion + "/{id}/{lower}/index.json")] [HttpGet(_pkgRootPrefix + ApiConfig.GetVersion + "/{id}/{lower}/" + ApiConfig.Base)]
public IActionResult GetVersions( public IActionResult GetVersions(
string id, string id,
string lower, string lower,

@ -15,8 +15,8 @@ using isnd.Data;
using isnd.Helpers; using isnd.Helpers;
using isnd.Entities; using isnd.Entities;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using isnd.Data.Catalog;
using isn.abst; using isn.abst;
using isnd.Data.Packages;
namespace isnd.Controllers namespace isnd.Controllers
{ {

@ -6,8 +6,7 @@ using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using isnd.Data; using isnd.Data;
using isnd.Data.ApiKeys; using isnd.Data.ApiKeys;
using isnd.Data.Catalog; using isnd.Data.Packages;
using isnd.Data.Historic;
namespace isnd.Data namespace isnd.Data
{ {

@ -1,7 +1,8 @@
using System; using System;
using isnd.Interfaces;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.Data.Catalog namespace isnd.Data.Packages.Catalog
{ {
public class PageRef : IObject public class PageRef : IObject
{ {

@ -1,6 +1,7 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using isnd.Data.Catalog; using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
namespace isnd.Data.Historic namespace isnd.Data.Historic
{ {

@ -1,8 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json; using Newtonsoft.Json;
using isnd.Interfaces;
namespace isnd.Data.Catalog namespace isnd.Data.Packages.Catalog
{ {
public class CatalogIndex : IObject public class CatalogIndex : IObject
{ {

@ -1,8 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using isnd.Interfaces;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.Data.Catalog namespace isnd.Data.Packages.Catalog
{ {
public class CatalogLeaf : IObject public class CatalogLeaf : IObject
{ {

@ -1,7 +1,7 @@
using System; using System;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.Data.Catalog namespace isnd.Interfaces
{ {
public interface IObject public interface IObject
{ {

@ -1,4 +1,4 @@
namespace isnd.Data.Catalog namespace isnd.Data.Packages.Catalog
{ {
public class PackageDetail : CatalogLeaf public class PackageDetail : CatalogLeaf
{ {

@ -1,8 +1,9 @@
using System; using System;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using isnd.Interfaces;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.Data.Catalog namespace isnd.Data.Packages.Catalog
{ {
/// <summary> /// <summary>
/// An presence of package in a catalog, /// An presence of package in a catalog,

@ -1,8 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using isnd.Interfaces;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.Data.Catalog namespace isnd.Data.Packages.Catalog
{ {
public class Page : IObject public class Page : IObject
{ {

@ -3,8 +3,9 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json; using Newtonsoft.Json;
using isnd.Interfaces;
namespace isnd.Data.Catalog namespace isnd.Data.Packages
{ {
public enum PackageAction public enum PackageAction
{ {

@ -2,16 +2,16 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using isnd.Data.Catalog; using isnd.Interfaces;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.Data namespace isnd.Data.Packages
{ {
public class Package : IObject public class Package : IObject
{ {
[Key][Required] [Key][Required]
[StringLength(1024)] [StringLength(1024)]
public string Id { get; set; } public string Id { get; set; }
[Required] [Required]
[ForeignKey("Owner")] [ForeignKey("Owner")]

@ -1,7 +1,8 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using isn.abst; using isn.abst;
using isnd.Data.Catalog; using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.Data namespace isnd.Data

@ -3,7 +3,8 @@ using System.Threading.Tasks;
using isn.Abstract; using isn.Abstract;
using isnd.Controllers; using isnd.Controllers;
using isnd.Data; using isnd.Data;
using isnd.Data.Catalog; using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
using isnd.Services; using isnd.Services;
using isnd.ViewModels; using isnd.ViewModels;
using NuGet.Versioning; using NuGet.Versioning;

@ -6,7 +6,8 @@ using System.Threading.Tasks;
using isn.Abstract; using isn.Abstract;
using isnd.Controllers; using isnd.Controllers;
using isnd.Data; using isnd.Data;
using isnd.Data.Catalog; using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
using isnd.Entities; using isnd.Entities;
using isnd.Helpers; using isnd.Helpers;
using isnd.Interfaces; using isnd.Interfaces;
@ -23,7 +24,7 @@ namespace isnd.Services
public const string BASE_API_LEVEL = "3.5.0"; public const string BASE_API_LEVEL = "3.5.0";
ApplicationDbContext dbContext; ApplicationDbContext dbContext;
public PackageManager(ApplicationDbContext dbContext, public PackageManager(ApplicationDbContext dbContext,
IOptions<IsndSettings> siteConfigOptionsOptions) IOptions<IsndSettings> siteConfigOptionsOptions)
{ {
@ -48,15 +49,15 @@ namespace isnd.Services
Comment = "Package Publish service" Comment = "Package Publish service"
}); });
// under dev, only leash in release mode // under dev, only leash in release mode
if (unleashClient.IsEnabled("pkg-get", false)) if (unleashClient.IsEnabled("pkg-get", true))
res.Add( res.Add(
new Resource new Resource
{ {
Id = extUrl + ApiConfig.GetPackage, Id = extUrl + ApiConfig.GetPackage,
Type = "PackageBaseAddress/3.0.0" , Type = "PackageBaseAddress/3.0.0",
Comment = "Package Base Address service" Comment = "Package Base Address service"
}); });
if (unleashClient.IsEnabled("pkg-autocomplete", false)) if (unleashClient.IsEnabled("pkg-autocomplete", true))
res.Add( res.Add(
new Resource new Resource
{ {
@ -72,22 +73,51 @@ namespace isnd.Services
Type = "SearchQueryService/" + BASE_API_LEVEL, Type = "SearchQueryService/" + BASE_API_LEVEL,
Comment = "Search Query service" Comment = "Search Query service"
}); });
if (unleashClient.IsEnabled("pkg-catalog", false)) if (unleashClient.IsEnabled("pkg-catalog", true))
res.Add( res.Add(
new Resource new Resource
{ {
Id = extUrl + ApiConfig.Catalog, Id = extUrl + ApiConfig.Catalog,
Type = "Catalog/"+ BASE_API_LEVEL, Type = "Catalog/" + BASE_API_LEVEL,
Comment = "Package Catalog Index" Comment = "Package Catalog Index"
}); });
/* FIXME res.Add( /* FIXME */
res.Add(
new Resource new Resource
{ {
Id = extUrl + ApiConfig.Registration, Id = extUrl + "v" + BASE_API_LEVEL + "/" + ApiConfig.Registration,
Type = "RegistrationsBaseUrl/3.6.0", Type = "RegistrationsBaseUrl",
Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages." Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
}); */ });
res.Add(
new Resource
{
Id = extUrl + "v3.0.0-beta/" + ApiConfig.Registration,
Type = "RegistrationsBaseUrl/3.0.0-beta",
Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
});
res.Add(
new Resource
{
Id = extUrl + "v3.0.0-rc/" + ApiConfig.Registration,
Type = "RegistrationsBaseUrl/3.0.0-rc",
Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
});
res.Add(new Resource
{
Id = extUrl + "v3.4.0/" + ApiConfig.Registration,
Type = "RegistrationsBaseUrl/3.4.0",
Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
});
res.Add(new Resource
{
Id = extUrl + "v3.6.0/" + ApiConfig.Registration,
Type = "RegistrationsBaseUrl/3.6.0",
Comment = "Base URL of storage where isn package registration info is stored in GZIP format. This base URL includes SemVer 2.0.0 packages."
});
return res; return res;
} }
@ -97,7 +127,6 @@ namespace isnd.Services
{ {
var scope = dbContext.Packages var scope = dbContext.Packages
.Include(p => p.Versions)
.Where( .Where(
p => (PackageIdHelpers.CamelCaseMatch(p.Id, query) || PackageIdHelpers.SeparatedByMinusMatch(p.Id, query)) p => (PackageIdHelpers.CamelCaseMatch(p.Id, query) || PackageIdHelpers.SeparatedByMinusMatch(p.Id, query))
&& (prerelease || p.Versions.Any(v => !v.IsPrerelease)) && (prerelease || p.Versions.Any(v => !v.IsPrerelease))
@ -171,8 +200,8 @@ namespace isnd.Services
int p = 0; int p = 0;
var oldIndex = CurrentCatalogIndex; var oldIndex = CurrentCatalogIndex;
var oldPages = CurrentCatalogPages; var oldPages = CurrentCatalogPages;
string baseid= extUrl + ApiConfig.Catalog; string baseid = extUrl + ApiConfig.Catalog;
string basepageid= extUrl + ApiConfig.CatalogPage; string basepageid = extUrl + ApiConfig.CatalogPage;
CurrentCatalogIndex = new CatalogIndex CurrentCatalogIndex = new CatalogIndex
{ {
Id = baseid, Id = baseid,
@ -181,7 +210,7 @@ namespace isnd.Services
CurrentCatalogPages = new List<Page>(); CurrentCatalogPages = new List<Page>();
var scope = dbContext.Commits.OrderBy(c => c.TimeStamp); var scope = dbContext.Commits.OrderBy(c => c.TimeStamp);
PageRef pageRef = null; PageRef pageRef = null;
Page page = null; Page page = null;
i = isndSettings.CatalogPageLen; i = isndSettings.CatalogPageLen;
@ -217,14 +246,14 @@ namespace isnd.Services
foreach (var pkg in validPkgs) foreach (var pkg in validPkgs)
{ {
var v = pkg.Versions. var v = pkg.Versions.
Where (cv => cv.CommitId == commit.CommitId) Where(cv => cv.CommitId == commit.CommitId)
.OrderByDescending(vc => vc.CommitNId).First(); .OrderByDescending(vc => vc.CommitNId).First();
StringBuilder refid = new StringBuilder(extUrl); StringBuilder refid = new StringBuilder(extUrl);
refid.AppendFormat("{0}/{1}/{2}",ApiConfig.CatalogLeaf, v.PackageId refid.AppendFormat("{0}/{1}/{2}", ApiConfig.CatalogLeaf, v.PackageId
, v.FullString); , v.FullString);
if (v.Type!=null) if (v.Type != null)
refid.AppendFormat("/{0}",v.Type); refid.AppendFormat("/{0}", v.Type);
var pkgref = new PackageRef var pkgref = new PackageRef
{ {
@ -258,7 +287,8 @@ namespace isnd.Services
public async Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type) public async Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type)
{ {
// TODO deletion on disk // TODO deletion on disk
var commit = new Commit{ var commit = new Commit
{
Action = PackageAction.DeletePackage, Action = PackageAction.DeletePackage,
TimeStamp = DateTime.Now TimeStamp = DateTime.Now
}; };
@ -270,12 +300,12 @@ namespace isnd.Services
); );
if (pkg == null) if (pkg == null)
{ {
return new PackageDeletionReport{ Deleted = false }; return new PackageDeletionReport { Deleted = false };
} }
dbContext.PackageVersions.Remove(pkg); dbContext.PackageVersions.Remove(pkg);
await dbContext.SaveChangesAsync(); await dbContext.SaveChangesAsync();
ÛpdateCatalogFor(commit); ÛpdateCatalogFor(commit);
return new PackageDeletionReport{ Deleted = true, DeletedVersion = pkg }; return new PackageDeletionReport { Deleted = true, DeletedVersion = pkg };
} }
public async Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type) public async Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type)
@ -301,7 +331,7 @@ namespace isnd.Services
public IEnumerable<PackageVersion> GetCatalogLeaf(string id, string version, string lower) public IEnumerable<PackageVersion> GetCatalogLeaf(string id, string version, string lower)
{ {
return dbContext.PackageVersions return dbContext.PackageVersions
.Include(v=>v.Package) .Include(v => v.Package)
.Where(v => v.PackageId == id && v.FullString == version .Where(v => v.PackageId == id && v.FullString == version
&& (lower == null || lower == v.Type)); && (lower == null || lower == v.Type));
} }

@ -109,13 +109,14 @@ namespace isnd
Microsoft.AspNetCore.Hosting.IHostingEnvironment env, Microsoft.AspNetCore.Hosting.IHostingEnvironment env,
ApplicationDbContext dbContext) ApplicationDbContext dbContext)
{ {
// app.UseForwardedHeaders(); app.UseForwardedHeaders();
// .UseHttpsRedirection(); // if have a cert : app.UseHttpsRedirection();
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
app.UseMigrationsEndPoint(); app.UseMigrationsEndPoint();
app.UseBrowserLink();
} }
else else
{ {

@ -1,4 +1,5 @@
using isnd.Data; using isnd.Data;
using isnd.Data.Packages;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace isnd.ViewModels namespace isnd.ViewModels

@ -1,4 +1,5 @@
using isnd.Data; using isnd.Data;
using isnd.Data.Packages;
namespace isnd.Services namespace isnd.Services
{ {

@ -10,6 +10,7 @@ using isn.Abstract;
using System.Linq; using System.Linq;
using Xunit; using Xunit;
using isn.abst; using isn.abst;
using isnd.Entities;
namespace isn.tests namespace isn.tests
{ {
@ -47,7 +48,7 @@ dataTable.Rows.Add(dataRow);
[Fact] [Fact]
public async Task TestHttpClient() public async Task TestHttpClient()
{ {
string url = "http://isn.pschneider.fr/index.json"; string url = "http://isn.pschneider.fr/" + ApiConfig.Base;
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
// var json = await client.GetStringAsync(new System.Uri(url)); // var json = await client.GetStringAsync(new System.Uri(url));
var response = await client.GetAsync(url); var response = await client.GetAsync(url);

Loading…