a better result

main
Paul Schneider 1 year ago
parent 56e4b6c526
commit d3b96088ab
47 changed files with 268 additions and 238 deletions

@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace isn
{
public class APIKO
{
public string Context { get; set; }
public Dictionary<string, string[]> Errors { get; set; }
}
}

@ -3,15 +3,12 @@ using Newtonsoft.Json;
namespace isn.Abstract
{
public class ApiIndexViewModel : HappyIdOwner
public class ApiIndexViewModel : Permalink
{
public ApiIndexViewModel(string id) : base(id)
public ApiIndexViewModel(string id) : base(id, "ApiIndex")
{
}
[JsonProperty("@id")]
public string Id { get => GetId(); }
[JsonProperty("version")]
public string Version { get; set; }

@ -4,6 +4,6 @@ namespace isn.abst
{
public const string PaquetFileEstension = "nupkg";
public const string SpecFileEstension = "nuspec";
public const string ApiVersion = "/v3";
public const string ApiVersionPrefix = "/v3";
}
}

@ -2,15 +2,28 @@ using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
public class HappyIdOwner
public abstract class Permalink
{
public HappyIdOwner(string id)
public Permalink(string id, string type)
{
Type = type;
this.id = id;
}
public Permalink(string id)
{
Type = GetType().Name;
this.id = id;
}
[JsonProperty("@type")]
public virtual string Type { get; set; }
private string id;
[JsonProperty("@id")]
public string Id { get => GetId(); }
private readonly string id;
public string GetId() { return id; }
@ -20,7 +33,7 @@ namespace isnd.Data.Catalog
{
if (GetType().IsAssignableFrom(obj.GetType()))
{
var rpobj = (HappyIdOwner) obj;
var rpobj = (Permalink) obj;
return this.id == rpobj.id;
}
}

@ -3,19 +3,13 @@ using Newtonsoft.Json;
namespace isn.Abstract
{
public class Resource : HappyIdOwner
public class Resource : Permalink
{
public Resource(string id, string typename) : base(id)
{
Type = typename;
Id = id;
}
[JsonProperty("@id")]
public string Id {get; set; }
[JsonProperty("@type")]
public string Type {get; set; }
[JsonProperty("comment")]
public string Comment {get; set; }

@ -216,9 +216,6 @@ namespace isn
{
Console.WriteLine("isn version " + GitVersionInformation.AssemblySemFileVer);
}
return commandSet.Run(args);
}

@ -17,8 +17,21 @@ namespace isn
// var json = await client.GetStringAsync(new System.Uri(url));
Task.Run(async ()=> {
try {
var response = await client.GetStringAsync(url);
result = JsonConvert.DeserializeObject<ApiIndexViewModel>(response);
} catch (HttpRequestException ex)
{
if (ex.StatusCode==HttpStatusCode.NotFound)
{
Console.Error.WriteLine("Not found ... server's down ?");
}
else
{
Console.Error.WriteLine($"{ex.StatusCode} : {ex.Message}");
}
}
}).Wait();
return result;

@ -4,6 +4,7 @@ using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace isn
{
@ -24,35 +25,19 @@ namespace isn
using (var multipartFormDataContent = new MultipartFormDataContent())
{
/* var values = new[]
{
new KeyValuePair<string, string>("Id", Guid.NewGuid().ToString()),
new KeyValuePair<string, string>("Key", "awesome"),
new KeyValuePair<string, string>("From", "khalid@home.com")
//other values
};foreach (var keyValuePair in values)
{
multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
String.Format("\"{0}\"", keyValuePair.Key));
} */
multipartFormDataContent.Add(new ByteArrayContent(File.ReadAllBytes(fi.FullName)),
'"' + "File" + '"',
'"' + fi.Name + '"');
var result = await client.PutAsync(uri, multipartFormDataContent);
if (result.IsSuccessStatusCode)
{
string report = await result.Content.ReadAsStringAsync();
Console.WriteLine(report);
}
if (result.IsSuccessStatusCode) return
new PushReport() {
KO = JsonConvert.DeserializeObject<APIKO>(await result.Content.ReadAsStringAsync())
};
else
{
string ereport = await result.Content.ReadAsStringAsync();
Console.WriteLine(ereport);
}
return new PushReport();
return new PushReport() {
OK = true
};
}
}
}

@ -21,6 +21,7 @@ namespace isn
{
var resources = SourceHelpers.GetServerResources(source);
if (resources == null) return null;
if (resources.Resources == null)
throw new InvalidOperationException("source gave no resource");
if (!resources.Resources.Any(res => res.Type == "PackagePublish/2.0.0"))
@ -39,7 +40,6 @@ namespace isn
using (var client = new HttpClient())
try
{
Console.WriteLine("Connecting to "+ pubRes.Id);
return client.UploadFilesToServer(new Uri(pubRes.Id), fi, settings.Sources[source].GetClearApiKey());
}
catch (HttpRequestException hrex)

@ -19,7 +19,6 @@ namespace isn
foreach (string pkg in pkgs)
{
var report = cmd.Run(pkg, CurrentSource, apiKey);
Console.WriteLine(report.ToDoc());
pushReports.Add(report);
}
return pushReports;

@ -40,7 +40,7 @@ namespace isn
Settings,
Formatting.Indented
));
Console.WriteLine("config saved .");
}
}
}

@ -1,29 +1,41 @@
using System.Threading.Tasks.Dataflow;
using System.Net;
using System.Text;
using Newtonsoft.Json;
namespace isn
{
public class PushReport
{
public PushReport()
{
}
public string PkgName { get; set; }
public bool Executed { get; internal set; }
public bool OK { get; internal set; }
public bool AlreadyPresent { get; internal set; }
public string Message { get; internal set; }
public string StatusCode { get; internal set; }
public string StackTrace { get; internal set; }
public bool Executed { get; set; }
public bool OK { get; set; }
public bool AlreadyPresent { get; set; }
public string Message { get; set; }
public string StatusCode { get; set; }
public string StackTrace { get; set; }
public APIKO KO { get; set; }
public string ToDoc()
{
StringBuilder sb = new StringBuilder($"= Pushing {PkgName}\n\n");
StringBuilder sb = new StringBuilder($"= push {PkgName}\n\n");
if (Executed) sb.AppendLine("* Executed");
if (OK) sb.AppendLine("* OK");
if (!string.IsNullOrWhiteSpace(Message))
sb.AppendLine(Message);
sb.AppendLine("* Message :" + Message);
if (!string.IsNullOrWhiteSpace(StatusCode))
sb.AppendLine($"* Status Code : ");
if (!string.IsNullOrWhiteSpace(StackTrace))
sb.AppendLine($"* StackTrace : ");
sb.AppendLine($"* StackTrace : " + StackTrace);
if (KO!=null)
sb.AppendLine($"* KO : " + KO.Context);
return sb.ToString();
}
}

@ -33,7 +33,7 @@ namespace isnd.Controllers
/// API index
/// </summary>
/// <returns></returns>
[HttpGet("~" + Constants.ApiVersion + "/index")]
[HttpGet("~" + Constants.ApiVersionPrefix + "/index")]
public IActionResult ApiIndex()
{
return Ok(new ApiIndexViewModel(packageManager.CatalogBaseUrl){ Version = PackageManager.BASE_API_LEVEL, Resources = resources });

@ -9,7 +9,7 @@ namespace isnd.Controllers
{
// GET /autocomplete?id=isn.protocol&prerelease=true
[HttpGet("~" + Constants.ApiVersion + ApiConfig.AutoComplete)]
[HttpGet("~" + Constants.ApiVersionPrefix + ApiConfig.AutoComplete)]
public IActionResult AutoComplete(
string id,
string semVerLevel,

@ -16,19 +16,19 @@ namespace isnd.Controllers
{
// https://docs.microsoft.com/en-us/nuget/api/catalog-resource#versioning
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Catalog)]
[HttpGet("~" + Constants.ApiVersionPrefix + ApiConfig.Catalog)]
public async Task<IActionResult> CatalogIndex()
{
return Ok(await packageManager.GetCatalogIndexAsync());
}
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Registration + "/{id}/{version?}")]
[HttpGet("~" + Constants.ApiVersionPrefix + ApiConfig.Registration + "/{id}/{version}.json")]
public async Task<IActionResult> CatalogRegistration(string id, string version)
{
if (string.IsNullOrWhiteSpace(version))
if ("index" == version)
{
var query = new Data.Catalog.RegistrationPageIndexQuery
var query = new Data.Catalog.PackageRegistrationQuery
{
Query = id,
Prerelease = true

@ -11,7 +11,7 @@ namespace isnd.Controllers
{
public partial class PackagesController
{
[HttpDelete("~" + Constants.ApiVersion + ApiConfig.Package + "/{id}/{lower?}/{type?}")]
[HttpDelete("~" + Constants.ApiVersionPrefix + ApiConfig.Package + "/{id}/{lower?}/{type?}")]
public async Task<IActionResult> ApiDelete(
[FromRoute][SafeName][Required] string id,
[FromRoute][SafeName][Required] string lower,

@ -11,7 +11,7 @@ namespace isnd.Controllers
public partial class PackagesController
{
// Web get the paquet
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Package + "/{id}/{lower}/{idf}-{lowerf}."
[HttpGet("~" + Constants.ApiVersionPrefix + ApiConfig.Nuget + "/{id}/{lower}/{idf}-{lowerf}."
+ Constants.PaquetFileEstension)]
public IActionResult GetPackage(
[FromRoute][SafeName][Required] string id,
@ -32,7 +32,7 @@ namespace isnd.Controllers
}
// Web get spec
[HttpGet("~" + Constants.ApiVersion + Constants.SpecFileEstension + "/{id}/{lower}/{idf}-{lowerf}."
[HttpGet("~" + Constants.ApiVersionPrefix + ApiConfig.Nuspec + "/{id}/{lower}/{idf}-{lowerf}."
+ Constants.SpecFileEstension)]
public IActionResult GetNuspec(
[FromRoute][SafeName][Required] string id,

@ -1,3 +1,4 @@
using System.Linq.Expressions;
using System;
using System.Collections.Generic;
@ -18,14 +19,18 @@ using Microsoft.AspNetCore.Http;
using isn.abst;
using isnd.Data.Packages;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using isn;
namespace isnd.Controllers
{
public partial class PackagesController
{
// TODO [Authorize(Policy = IsndConstants.RequireValidApiKey)]
[HttpPut("~" + Constants.ApiVersion + ApiConfig.Package)]
// TODO [Authorize(Policy = IsndConstants.RequireValidApiKey)]
[HttpPut("~" + Constants.ApiVersionPrefix + ApiConfig.Package)]
public async Task<IActionResult> Put()
{
try
@ -130,7 +135,7 @@ namespace isnd.Controllers
else {
logger.LogWarning("400 : pkgversion:existant");
ModelState.AddModelError("pkgversion", "existant" );
return BadRequest(ModelState);
return BadRequest(CreateAPIKO("existant", ModelState));
}
}
{
@ -206,9 +211,8 @@ namespace isnd.Controllers
nfpi.Delete();
spec.ExtractToFile(nuspecfullpath);
}
}
return Ok(ViewData);
return Ok();
}
catch (Exception ex)
{
@ -218,5 +222,17 @@ namespace isnd.Controllers
{ StatusCode = 500 };
}
}
public APIKO CreateAPIKO(string context, ModelStateDictionary modelState)
{
Dictionary<string,string[]> 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 };
}
}
}

@ -11,7 +11,7 @@ namespace isnd.Controllers
public partial class PackagesController
{
// GET {@id}?q={QUERY}&skip={SKIP}&take={TAKE}&prerelease={PRERELEASE}&semVerLevel={SEMVERLEVEL}&packageType={PACKAGETYPE}
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Search)]
[HttpGet("~" + Constants.ApiVersionPrefix + ApiConfig.Search)]
public IActionResult Search(
string q,
int skip = 0,

@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using isn.abst;
using isnd.Data;
using isnd.Data.Catalog;
using isnd.Helpers;
@ -15,22 +16,22 @@ namespace isnd.Controllers
public partial class PackagesController
{
// Web search
public async Task<IActionResult> Index(RegistrationPageIndexQuery model)
public async Task<IActionResult> Index(PackageRegistrationQuery model)
{
return View(new RegistrationPageIndexQueryAndResult{Query = model,
Result = await packageManager.SearchPackageAsync(model)});
}
public async Task<IActionResult> Details(string pkgid)
public async Task<IActionResult> Details(PackageDetailViewModel model)
{
if (pkgid == null)
if (model.pkgid == null)
{
return NotFound();
}
var packageVersion = dbContext.PackageVersions
.Include(p => p.Package)
.Where(m => m.PackageId == pkgid)
.Where(m => m.PackageId == model.pkgid)
.OrderByDescending(p => p)
;
@ -39,17 +40,11 @@ namespace isnd.Controllers
return NotFound();
}
bool results = await packageVersion.AnyAsync();
var latest = await packageVersion.FirstAsync();
return View("Details", new PackageDetailViewModel
{
ExternalUrl = isndSettings.ExternalUrl,
latest = latest,
pkgid = pkgid,
totalHits = packageVersion.Count(),
data = packageVersion.Take(MAX_PKG_VERSION_LIST).ToArray()
});
model.latest = await packageVersion.FirstAsync();
model.totalHits = packageVersion.Count();
model.data = packageVersion.Take(MAX_PKG_VERSION_LIST).ToArray();
return View("Details", model);
}
const int MAX_PKG_VERSION_LIST = 50;
@ -60,7 +55,6 @@ namespace isnd.Controllers
{
return NotFound();
}
// var report = await packageManager.DeletePackageAsync(id, lower, type);
var packageVersion = await dbContext.PackageVersions.Include(p => p.Package)
.FirstOrDefaultAsync(m => m.PackageId == pkgid

@ -9,7 +9,7 @@ using isnd.Interfaces;
namespace isnd.Data.Catalog
{
public class CatalogEntry : HappyIdOwner , IObject// , IPackageDetails
public class CatalogEntry : Permalink, IObject// , IPackageDetails
{
/// <summary>
/// Creates a catalog entry
@ -20,25 +20,10 @@ namespace isnd.Data.Catalog
{
}
/// <summary>
/// The ID of the package
/// </summary>
/// <value></value>
[JsonProperty("id")]
public string Id { get; set; }
/// <summary>
/// The Package details url
/// </summary>
/// <returns></returns>
[JsonProperty("@id")]
public string refid { get => GetId(); }
[JsonProperty("@type")]
public string[] RefType { get; protected set; } = new string[] { "PackageDetail" };
public string[] RefType { get; protected set; } = new string[] { "PackageDetails" };
[JsonProperty("commitId")]
public string CommitId { get; set; }
@ -98,7 +83,6 @@ namespace isnd.Data.Catalog
public Vulnerabilitie[] vulnerabilities { get; set; }
public string packageContent { get; set; }
/// <summary>
/// A string containing a ISO 8601 timestamp of when the package was published

@ -6,17 +6,17 @@ using System.Linq;
namespace isnd.Data.Catalog
{
public class RegistrationPageIndex : HappyIdOwner
public class PackageRegistration : Permalink
{
public RegistrationPageIndex(string url) : base(url)
public PackageRegistration(string url) : base(url)
{
Items = new List<RegistrationPage>();
Items = new List<CatalogPage>();
}
public RegistrationPageIndex(string bid, string id, string extUrl, IEnumerable<Package> pkgs) : base(bid + $"/{id}/index.json")
public PackageRegistration(string bid, string id, string apiBase, IEnumerable<Packages.Package> pkgs) : base(bid + $"/{id}/index.json")
{
Items = new List<RegistrationPage>();
Items = new List<CatalogPage>();
long cnid = 0;
var pkgsGroups = pkgs.GroupBy(l => l.Id);
// Pour tous les groupes par Id
@ -36,7 +36,7 @@ namespace isnd.Data.Catalog
}
}
}
Items.Add(new RegistrationPage(bid, gsp.Key, extUrl, versions));
Items.Add(new CatalogPage(bid, gsp.Key, apiBase, versions));
}
CommitId = cnid.ToString();
}
@ -45,7 +45,7 @@ namespace isnd.Data.Catalog
public int Count { get => Items.Count; }
[JsonProperty("items")]
public List<RegistrationPage> Items { get; set; }
public List<CatalogPage> Items { get; set; }
public string CommitId { get; set; }
public DateTimeOffset CommitTimeStamp { get; internal set; }

@ -1,5 +1,7 @@
using System.ComponentModel.DataAnnotations;
using isnd.Entities;
using Newtonsoft.Json;
using isn.abst;
namespace isnd.Data.Catalog
{
@ -7,8 +9,16 @@ namespace isnd.Data.Catalog
/// Hosts a catalog entry,
/// the atomic content reference
/// </summary>
public class RegistrationLeaf
public class Package
{
public Package(string apiBase, string pkgId, string fullVersionString, CatalogEntry entry)
{
this.registration = apiBase + ApiConfig.Registration + "/" + pkgId + "/index.json";
this.PackageContent = apiBase + ApiConfig.Nuget + "/" + pkgId + "/" + fullVersionString
+ "/" + pkgId + "-" + fullVersionString + "." + Constants.PaquetFileEstension;
Entry = entry;
}
/*
@id string yes
catalogEntry object yes
@ -36,5 +46,7 @@ namespace isnd.Data.Catalog
/// <value></value>
[JsonProperty("packageContent")]
public string PackageContent { get; set; }
public string registration { get; set; }
}
}

@ -7,26 +7,23 @@ using NuGet.Versioning;
namespace isnd.Data.Catalog
{
public class RegistrationPage : HappyIdOwner
public class CatalogPage : Permalink
{
[JsonProperty("@id")]
public string Id { get => GetId(); }
private readonly string pkgid;
private readonly List<PackageVersion> items;
private readonly List<Package> items;
protected string Bid { get ; private set; }
protected string ExternalUrl { get; }
private readonly string apiBase;
public RegistrationPage (string bid, string pkgid, string extUrl) : base(bid + "/" + pkgid + "/index.json")
public CatalogPage (string pkgid, string apiBase) : base(apiBase + $"/registration/{pkgid}/index.json")
{
Bid = bid;
Parent = Bid + $"/{pkgid}/index.json";
ExternalUrl = extUrl;
this.items = new List<PackageVersion>();
Parent = apiBase + $"/registration/{pkgid}/index.json";
this.items = new List<Package>();
this.pkgid = pkgid;
this.apiBase = apiBase;
}
public RegistrationPage(string bid, string pkgid, string extUrl, List<PackageVersion> versions) : this(bid, pkgid, extUrl)
public CatalogPage(string bid, string pkgid, string apiBase, List<PackageVersion> versions) : this(pkgid, apiBase)
{
AddVersionRange(versions);
}
@ -42,13 +39,14 @@ namespace isnd.Data.Catalog
/// <value></value>
[JsonProperty("items")]
public CatalogEntry[] Items { get => items.Select((p) => p.ToLeave(Bid, ExternalUrl)).ToArray(); }
public Package[] Items { get => items.ToArray(); }
public void AddVersionRange(IEnumerable<PackageVersion> vitems)
{
if (vitems.Count() == 0) return;
NuGetVersion upper = null;
NuGetVersion lower = null;
PackageVersion latest = null;
if (Lower!=null) lower = new NuGetVersion(Lower);
if (Upper!=null) upper = new NuGetVersion(Upper);
@ -56,7 +54,8 @@ namespace isnd.Data.Catalog
long commitMax = 0;
foreach (var p in vitems)
{
if (items.Contains(p)) continue;
var pkg = p.ToPackage(apiBase);
if (items.Contains(pkg)) continue;
if (upper == null) upper = p.NugetVersion;
else if ( upper < p.NugetVersion) upper = p.NugetVersion;
@ -64,12 +63,19 @@ namespace isnd.Data.Catalog
if (lower == null) lower = p.NugetVersion;
else if (lower > p.NugetVersion) lower = p.NugetVersion;
if (p.CommitNId > commitMax) commitMax = p.CommitNId;
items.Add(p);
if (p.CommitNId > commitMax)
{
latest = p;
}
items.Add(pkg);
}
Upper = upper.ToFullString();
Lower = lower.ToFullString();
CommitId = commitMax.ToString();
if (latest != null)
{
CommitId = latest.CommitId;
CommitTimeStamp = latest.LatestCommit.CommitTimeStamp;
}
}
/// <summary>
@ -95,6 +101,6 @@ namespace isnd.Data.Catalog
[JsonProperty("count")]
public int Count { get => items.Count; }
public string CommitId { get; internal set; }
public DateTime CommitTimeStamp { get; internal set; }
public DateTimeOffset CommitTimeStamp { get; internal set; }
}
}

@ -4,9 +4,9 @@ using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
public class RegistrationPageIndexQuery
public class PackageRegistrationQuery
{
public RegistrationPageIndexQuery()
public PackageRegistrationQuery()
{
}

@ -10,10 +10,9 @@ namespace isnd.Data.Packages.Catalog
/// for availability, or deletion,
///
/// </summary>
public class PackageRef : IObject
public class PackageDetails : IObject
{
[JsonProperty("@id")]
public string RefId { get; set; }
@ -48,5 +47,6 @@ namespace isnd.Data.Packages.Catalog
[JsonProperty("commitTimeStamp")]
public DateTimeOffset CommitTimeStamp { get; set; }
}
}

@ -0,0 +1,12 @@
using System;
using isnd.Interfaces;
namespace isnd.Data.Packages.Catalog
{
public class PackageEntry : IObject
{
public string CommitId => throw new NotImplementedException();
public DateTimeOffset CommitTimeStamp => throw new NotImplementedException();
}
}

@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using isnd.Interfaces;
using Newtonsoft.Json;
namespace isnd.Data.Packages.Catalog
{
public class Page : IObject
{
[JsonProperty("@id")]
public string Id { get; set; }
[JsonProperty("parent")]
public string Parent { get; set; }
[JsonProperty("items")]
public virtual List<PackageRef> Items { get; set; }
public string CommitId { get; set; }
public DateTimeOffset CommitTimeStamp { get; set; }
}
}

@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using isnd.Data.Catalog;
using isnd.Data.Packages.Catalog;
using isnd.Interfaces;
using Newtonsoft.Json;
@ -62,5 +63,6 @@ namespace isnd.Data.Packages
public virtual Commit LatestVersion { get; set; }
public DateTimeOffset CommitTimeStamp { get; set; }
}
}

@ -5,13 +5,12 @@ using isn.abst;
using isnd.Data.Catalog;
using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
using isnd.Entities;
using Newtonsoft.Json;
using NuGet.Versioning;
namespace isnd.Data
{
public class PackageVersion
{
[Required]
@ -46,7 +45,7 @@ namespace isnd.Data
public string Type { get; set; }
[JsonIgnore]
public virtual Package Package { get; set; }
public virtual Packages.Package Package { get; set; }
[Required]
[JsonIgnore]
@ -58,23 +57,24 @@ namespace isnd.Data
public string CommitId { get => CommitNId.ToString(); }
public virtual Commit LatestCommit { get; set; }
public string NugetLink => $"{Constants.PaquetFileEstension}/{PackageId}/{FullString}/{PackageId}-{FullString}."
public string NugetLink => $"{ApiConfig.Nuget}/{PackageId}/{FullString}/{PackageId}-{FullString}."
+ Constants.PaquetFileEstension;
public string NuspecLink => $"{Constants.SpecFileEstension}/{PackageId}/{FullString}/{PackageId}-{FullString}."
public string NuspecLink => $"{ApiConfig.Nuspec}/{PackageId}/{FullString}/{PackageId}-{FullString}."
+ Constants.SpecFileEstension;
public string SementicVersionString { get => $"{Major}.{Minor}.{Patch}"; }
public NuGetVersion NugetVersion { get => new NuGetVersion(FullString); }
public CatalogEntry ToLeave(string bid, string extUrl)
public Catalog.Package ToPackage(string apiBase)
{
return new CatalogEntry(bid + "/" + this.PackageId + "/" + FullString + ".json")
return new Catalog.Package(apiBase ,this.PackageId , FullString,
new CatalogEntry(apiBase + ApiConfig.Registration + "/" + this.PackageId + "/" + FullString + ".json")
{
Id = PackageId,
Version = FullString,
authors = $"{this.Package.Owner.FullName} <${Package.Owner.Email}>",
packageContent = extUrl + this.NugetLink
};
packageContent = apiBase + this.NugetLink
}
);
}
}
}

@ -20,17 +20,17 @@ namespace isnd.Interfaces
string[] GetVersions(string pkgid, NuGetVersion parsedVersion, bool prerelease = false, string packageType = null, int skip = 0, int take = 25);
IEnumerable<Resource> GetResources(IUnleash unleashĈlient);
Task<RegistrationPageIndex> ÛpdateCatalogForAsync(Commit commit);
Task<PackageRegistration> ÛpdateCatalogForAsync(Commit commit);
Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type);
Task<PackageDeletionReport> UserAskForPackageDeletionAsync(string userid, string pkgId, string lower, string type);
Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type);
Task<CatalogEntry> GetCatalogEntryAsync(string pkgId, string version, string pkgType);
IEnumerable<CatalogEntry> SearchCatalogEntriesById(string pkgId, string semver, string pkgType);
Task<Data.Catalog.Package> GetCatalogEntryAsync(string pkgId, string version, string pkgType);
IEnumerable<Data.Catalog.Package> SearchCatalogEntriesById(string pkgId, string semver, string pkgType);
Task<RegistrationPageIndex> GetCatalogIndexAsync();
Task<RegistrationPageIndex> GetPackageRegistrationIndexAsync(RegistrationPageIndexQuery query);
Task<PackageRegistration> GetCatalogIndexAsync();
Task<PackageRegistration> GetPackageRegistrationIndexAsync(PackageRegistrationQuery query);
Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query);
Task<PackageRegistration> SearchPackageAsync(PackageRegistrationQuery query);
}
}

@ -9,26 +9,26 @@ namespace isnd
{
private int delautIdCounter;
Dictionary<string, HappyIdOwner> HappyIdOwners { get; set; }
Dictionary<string, Permalink> HappyIdOwners { get; set; }
Dictionary<int,object> Objects {get; set;}
internal NSJWebApiReferenceResolver()
{
delautIdCounter = 0;
HappyIdOwners = new Dictionary<string, HappyIdOwner>();
HappyIdOwners = new Dictionary<string, Permalink>();
Objects = new Dictionary<int, object>();
}
public void AddReference(object context, string reference, object value)
{
if (value is HappyIdOwner)
if (value is Permalink)
{
string hoi = (value as HappyIdOwner).GetId();
string hoi = (value as Permalink).GetId();
if (HappyIdOwners.ContainsKey(hoi))
{
return;
}
HappyIdOwners[hoi] = value as HappyIdOwner;
HappyIdOwners[hoi] = value as Permalink;
}
else
{
@ -45,9 +45,9 @@ namespace isnd
public string GetReference(object context, object value)
{
bool alreadyExists;
if (value is HappyIdOwner)
if (value is Permalink)
{
string oid = (value as HappyIdOwner).GetId();
string oid = (value as Permalink).GetId();
if (oid == null)
throw new System.Exception("HappyIdOwner Id property is null");
if (HappyIdOwners.ContainsKey(oid))

@ -27,7 +27,7 @@ namespace isnd.Services
{
this.dbContext = dbContext;
isndSettings = siteConfigOptionsOptions.Value;
apiBase = isndSettings.ExternalUrl + Constants.ApiVersion;
apiBase = isndSettings.ExternalUrl + Constants.ApiVersionPrefix;
}
public IEnumerable<Resource> GetResources(IUnleash unleashClient)
@ -126,19 +126,19 @@ namespace isnd.Services
private IsndSettings isndSettings;
private readonly string apiBase;
public virtual async Task<RegistrationPageIndex> GetCatalogIndexAsync()
public virtual async Task<PackageRegistration> GetCatalogIndexAsync()
{
return await ÛpdateCatalogForAsync(null);
}
public async Task<RegistrationPageIndex> ÛpdateCatalogForAsync
public async Task<PackageRegistration> ÛpdateCatalogForAsync
(Commit reason = null)
{
int i = 0;
string baseid = apiBase + ApiConfig.Catalog;
string bidreg = $"{apiBase}v3.4.0/{ApiConfig.Registration}";
RegistrationPageIndex index = new RegistrationPageIndex(baseid);
string bidreg = $"{apiBase}{ApiConfig.Registration}";
PackageRegistration index = new PackageRegistration(baseid);
var scope = await dbContext.Commits.OrderBy(c => c.TimeStamp).ToArrayAsync();
@ -157,11 +157,11 @@ namespace isnd.Services
foreach (var pkgid in validPkgs)
{
RegistrationPage page = index.Items.FirstOrDefault
CatalogPage page = index.Items.FirstOrDefault
(p => p.GetPackageId() == pkgid.Key);
if (page == null)
{
page = new RegistrationPage(bidreg, pkgid.Key, apiBase);
page = new CatalogPage(pkgid.Key, apiBase);
index.Items.Add(page);
}
@ -222,15 +222,13 @@ namespace isnd.Services
);
}
public async Task<CatalogEntry> GetCatalogEntryAsync
public async Task<Data.Catalog.Package> GetCatalogEntryAsync
(string pkgId, string semver = null, string pkgType = null)
{
return (await dbContext.PackageVersions
.Include(v => v.Package)
.Include(v => v.LatestCommit)
.Where(v => v.PackageId == pkgId
&& semver == v.SementicVersionString
&& (pkgType == null || pkgType == v.Type)).SingleOrDefaultAsync()).ToLeave(BID,
.Include(v => v.Package).Include(v => v.Package.Owner)
.Where(v => v.PackageId == pkgId
&& v.FullString == semver).SingleOrDefaultAsync()).ToPackage(
apiBase);
}
@ -246,9 +244,8 @@ namespace isnd.Services
return new PackageDeletionReport { Deleted = true, DeletedVersion = packageVersion };
}
public string BID { get => $"{apiBase}v3.4.0/{ApiConfig.Registration}"; }
public IEnumerable<CatalogEntry> SearchCatalogEntriesById
public IEnumerable<Data.Catalog.Package> SearchCatalogEntriesById
(string pkgId, string semver, string pkgType)
{
@ -259,7 +256,7 @@ namespace isnd.Services
.Where(v => v.PackageId == pkgId && semver == v.FullString
&& (pkgType == null || pkgType == v.Type))
.OrderByDescending(p => p.CommitNId)
.Select(p => p.ToLeave(BID, apiBase))
.Select(p => p.ToPackage(apiBase))
;
}
public PackageVersion GetPackage(string pkgId, string semver, string pkgType)
@ -271,25 +268,29 @@ namespace isnd.Services
&& (pkgType == null || pkgType == v.Type));
}
public async Task<RegistrationPageIndex> GetPackageRegistrationIndexAsync
(RegistrationPageIndexQuery query)
public async Task<PackageRegistration> GetPackageRegistrationIndexAsync
(PackageRegistrationQuery query)
{
// 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)
.Where(p => p.Id.ToLower() == query.Query).Skip(query.Skip).Take(query.Take).ToListAsync();
string bid = $"{apiBase}v3.4.0/{ApiConfig.Registration}";
string bid = $"{apiBase}{ApiConfig.Registration}";
return
new RegistrationPageIndex(bid, query.Query, apiBase, scope);
new PackageRegistration(bid, query.Query, apiBase, scope);
}
public async Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query)
public async Task<PackageRegistration> SearchPackageAsync(PackageRegistrationQuery query)
{
string bid = $"{apiBase}v3.4.0/{ApiConfig.Registration}";
string bid = $"{apiBase}{ApiConfig.Registration}";
if (query.Query == null) query.Query = "";
var scope = (await dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
var scope = (await dbContext.Packages
.Include(p => p.Versions)
.Include(p => p.Owner)
.Include(p=>p.LatestVersion)
.ToListAsync())
.Where(p => Matching(p, query))
;
@ -297,17 +298,17 @@ namespace isnd.Services
var pkgs = scope.Skip(query.Skip).Take(query.Take);
return
new RegistrationPageIndex(bid, query.Query, apiBase, pkgs);
new PackageRegistration(bid, query.Query, apiBase, pkgs);
}
private static bool MatchingExact(Package p, RegistrationPageIndexQuery query)
private static bool MatchingExact(Data.Packages.Package p, PackageRegistrationQuery query)
{
return
p.Id == query.Query
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease));
}
private static bool Matching(Package p, RegistrationPageIndexQuery query)
private static bool Matching(Data.Packages.Package p, PackageRegistrationQuery query)
{
return p.Id.StartsWith(query.Query)
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease));

@ -1,7 +1,11 @@
using isn.abst;
using isnd.Data;
using isnd.Entities;
using Microsoft.Extensions.Options;
namespace isnd.ViewModels
{
public class PackageDetailViewModel
{
public PackageVersion latest { get; set; }
@ -10,8 +14,5 @@ namespace isnd.ViewModels
public int totalHits { get; set; }
public PackageVersion[] data { get; set; }
public string ExternalUrl { get; set; }
}
}

@ -4,7 +4,7 @@ namespace isnd
{
public class RegistrationPageIndexQueryAndResult
{
public RegistrationPageIndexQuery Query { get; set; }
public RegistrationPageIndex Result { get; set; }
public PackageRegistrationQuery Query { get; set; }
public PackageRegistration Result { get; set; }
}
}

@ -10,5 +10,6 @@
</p>
</div>
<div style="text-align: center;">
<iframe width="560" height="315" src="https://crowdbunker.com/embed/BumpeEansBp" frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen scrolling="no" ></iframe>
<iframe width="560" height="315" src="https://crowdbunker.com/embed/admChkeiYFP" frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen scrolling="no" ></iframe>
</div>

@ -26,8 +26,8 @@
@Html.DisplayNameFor(model => model.FullString)
</dt>
<dd>
<a href="@Model.NugetLink" >@Html.DisplayFor(model => model.FullString)</a>
<a href="@Model.NuspecLink" >nuspec</a>
<a href="@Constants.ApiVersionPrefix@Model.NugetLink" >@Html.DisplayFor(model => model.FullString)</a>
<a href="@Constants.ApiVersionPrefix@Model.NuspecLink" >nuspec</a>
</dd>
</dl>
</div>

@ -2,6 +2,7 @@
@{
ViewData["Title"] = "Index";
var apiBaseUrl = "/v3";
}
<h2>Index</h2>
@ -44,11 +45,11 @@
<tr>
<td>
@Html.DisplayFor(modelItem => item.PackageId)
<a href="@item.NugetLink">
<a href="@apiBaseUrl@item.NugetLink">
nuget
</a>
<a href="@item.NuspecLink">
<a href="@apiBaseUrl@item.NuspecLink">
nuspec
</a>
</td>

@ -25,8 +25,8 @@
@Html.DisplayNameFor(model => model.latest.FullString)
</dt>
<dd>
<a href="@Model.ExternalUrl/@Model.latest.NugetLink" >@Html.DisplayFor(model => model.latest.FullString)</a>
<a href="@Model.ExternalUrl/@Model.latest.NuspecLink" >nuspec</a>
<a href="@Constants.ApiVersionPrefix@Model.latest.NugetLink" >@Html.DisplayFor(model => model.latest.FullString)</a>
<a href="@Constants.ApiVersionPrefix@Model.latest.NuspecLink" >nuspec</a>
<i class="extinfo">(version count : @Model.totalHits)</i>
</dd>
</dl>

@ -10,10 +10,10 @@
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Result.Items[0].Items[0].refid)
@Html.DisplayNameFor(model => model.Result.Items[0].Items[0].Id)
</th>
<th>
@Html.DisplayNameFor(model => model.Result.Items[0].Items[0].Description)
@Html.DisplayNameFor(model => model.Result.Items[0].Items[0].Entry.Description)
</th>
<th></th>
</tr>

@ -2,4 +2,6 @@
@using isnd.ViewModels
@using isnd.Helpers
@using isnd.Data.Catalog;
@using isn.abst;
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@ -17,27 +17,27 @@ namespace isnd
{
private int delautIdCounter;
Dictionary<string, HappyIdOwner> HappyIdOwners { get; set; }
Dictionary<string, Permalink> HappyIdOwners { get; set; }
Dictionary<int,object> Objects {get; set;}
public WebApiReferenceResolver()
{
delautIdCounter = 0;
HappyIdOwners = new Dictionary<string, HappyIdOwner>();
HappyIdOwners = new Dictionary<string, Permalink>();
Objects = new Dictionary<int, object>();
}
public override void AddReference(string referenceId, object value)
{
if (value is HappyIdOwner)
if (value is Permalink)
{
string hoi = (value as HappyIdOwner).GetId();
string hoi = (value as Permalink).GetId();
if (HappyIdOwners.ContainsKey(hoi))
{
return;
}
HappyIdOwners[hoi] = value as HappyIdOwner;
HappyIdOwners[hoi] = value as Permalink;
}
else
{
@ -53,9 +53,9 @@ namespace isnd
public override string GetReference(object value, out bool alreadyExists)
{
if (value is HappyIdOwner)
if (value is Permalink)
{
string oid = (value as HappyIdOwner).GetId();
string oid = (value as Permalink).GetId();
if (oid == null)
throw new System.Exception("HappyIdOwner Id property is null");
if (HappyIdOwners.ContainsKey(oid))

@ -3,8 +3,6 @@
<apikeys>
</apikeys>
<packageSources>
<add key="dev" value="http://localhost:5000/index.json" protocolVersion="3" />
<!-- <add key="isn-prod" value="https://isn.pschneider.fr/index.json" protocolVersion="3" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> -->
<add key="dev" value="http://localhost:5000/v3/index" protocolVersion="3" />
</packageSources>
</configuration>

@ -1 +1 @@
nuget install -NoCache -Verbosity detailed -ConfigFile ANuGet.Config Yavsc.Abstract
nuget install -NoCache -Verbosity detailed -ConfigFile ANuGet.Config isn.abst

@ -0,0 +1,4 @@
https://api.nuget.org/v3/registration5-gz-semver2/yavsc.abstract/index.json
https://api.nuget.org/v3/catalog0/data/2019.09.17.10.18.17/yavsc.abstract.1.0.6-rc07.json
http://localhost:5000/v3/index
http://localhost:5000/v3/registration/isn.abst/index.json

@ -33,7 +33,7 @@ namespace isn.tests
[Fact]
public async Task TestHttpClient()
{
string url = "https://isn.pschneider.fr/v3/index.json" ;
string url = "https://isn.pschneider.fr"+Constants.ApiVersionPrefix+"/index.json" ;
HttpClient client = new HttpClient();
// var json = await client.GetStringAsync(new System.Uri(url));
var response = await client.GetAsync(url);

@ -1,28 +1,24 @@
using System.Threading;
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore;
using Xunit;
using isnd.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Diagnostics;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.Configuration;
using isnd.tests;
using NuGet.Protocol;
using NuGet.Configuration;
using System.Threading.Tasks;
using NuGet.Protocol.Core.Types;
using isn.abst;
namespace isnd.host.tests
{
[Collection("Web server collection")]
public class UnitTestWebHost : IClassFixture<WebServerFixture>
{
const string apiindex = "/v3/index";
const string apiindex = Constants.ApiVersionPrefix + "/index";
WebServerFixture server;
public UnitTestWebHost(WebServerFixture server)
{
@ -88,7 +84,7 @@ namespace isnd.host.tests
PackageSource packageSource = new PackageSource(pkgSourceUrl);
HttpSource client = new HttpSource(packageSource, PkgSourceMessageHandler, throttle);
NuGet.Protocol.RegistrationResourceV3 res = new NuGet.Protocol.RegistrationResourceV3(client ,
new Uri(isnSettings.ExternalUrl + "/v3/registration"));
new Uri(isnSettings.ExternalUrl + Constants.ApiVersionPrefix + "/registration"));
}
}

Loading…