18 Commits
1.0.0 ... 1.0.1

Author SHA1 Message Date
58f77a06ea A valid package index page 2022-10-15 18:26:55 +01:00
88c8480911 A valid registration page Index 2022-10-15 18:25:40 +01:00
c147eaf54a by Nuget version 2022-09-27 00:39:43 +01:00
e49db8e1a1 re_Vision 2022-09-26 23:34:13 +01:00
9aac183e2c Merge branch 'broken/ef' 2022-09-26 23:30:58 +01:00
037559a0b7 layout 2022-09-26 23:30:54 +01:00
9c4d45b97c + Revsion 2022-09-26 21:54:22 +01:00
9aa3140a11 WIP 2022-09-25 17:07:56 +01:00
7f9344d437 add a vscode task for ef db update 2022-09-25 16:47:31 +01:00
f46ca00de9 REORG 2022-09-25 02:24:21 +01:00
fcea41f8c1 Catalog++ 2022-09-24 12:32:00 +01:00
58f49af5f0 publish 2022-09-23 22:16:12 +01:00
fececb327e WIP reg page 2022-09-23 20:34:51 +01:00
14206ac477 catalog impl 2022-08-20 17:44:33 +01:00
fa9a12ad49 WIP Page leaf 2022-07-29 09:06:59 +01:00
7f9984b059 WIP page leaf 2022-07-10 17:05:16 +01:00
2dcf1a2806 refacts 2022-07-03 14:50:57 +01:00
a84e1d9750 Corrige la suppression de paquets 2022-06-19 21:40:31 +01:00
86 changed files with 1889 additions and 547 deletions

4
.gitignore vendored
View File

@ -17,3 +17,7 @@ appsettings.Development.json
/src/isn.abst/bin
/src/isn.abst/obj
/src/isnd/packages/
/test/data/test-isn/bin/
/test/data/test-isn/obj
.fake
artifacts/

View File

@ -1,33 +1,23 @@
<Properties StartupConfiguration="{9D758F00-17FF-433D-B088-F9C2D97C9BD1}|Default">
<MonoDevelop.Ide.Workbench ActiveDocument="src/isn/Program.cs">
<MonoDevelop.Ide.Workbench ActiveDocument="src/isnd/isnd.csproj">
<Files>
<File FileName="src/isn/Program.cs" Line="66" Column="10" />
<File FileName="src/isn/Program.cs" Line="55" Column="48" />
<File FileName="src/isnd/isnd.csproj" Line="15" Column="56" />
</Files>
<Pads>
<Pad Id="ProjectPad">
<State name="__root__">
<Node name="isn" expanded="True">
<Node name="src" expanded="True">
<Node name="isn" expanded="True" selected="True" />
<Node name="isn.abst" expanded="True" />
</Node>
<Node name="test" expanded="True">
<Node name="isnd.tests" expanded="True" />
</Node>
</Node>
</State>
</Pad>
<Pad Id="MonoDevelop.UnitTesting.TestPad">
<State name="__root__">
<Node name="isn" expanded="True">
<Node name="test" expanded="True">
<Node name="isn.tests" selected="True" />
<Node name="isnd" selected="True" />
</Node>
<Node name="test" expanded="True" />
</Node>
</State>
</Pad>
</Pads>
</MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.ItemProperties.src.isnd PreferredExecutionTarget="MonoDevelop.Default" />
<MonoDevelop.Ide.DebuggingService.PinnedWatches />
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
<MonoDevelop.Ide.ItemProperties.test.isnd.tests PreferredExecutionTarget="MonoDevelop.Default" />
@ -35,4 +25,5 @@
<BreakpointStore />
</MonoDevelop.Ide.DebuggingService.Breakpoints>
<MultiItemStartupConfigurations />
<MonoDevelop.Ide.ItemProperties.src.isn PreferredExecutionTarget="MonoDevelop.Default" />
</Properties>

View File

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

41
.vscode/tasks.json vendored
View File

@ -26,6 +26,26 @@
],
"problemMatcher": "$msCompile"
},
{
"label": "db-upgrade",
"command": "dotnet",
"type": "process",
"args": [
"ef",
"database",
"update"
],
"problemMatcher": "$msCompile",
"options": {
"cwd": "${workspaceFolder}/src/isnd",
"env": {
"ASPNETCORE_ENV": "Development"
}
}
},
{
"label": "buildcli",
"command": "msbuild",
@ -45,8 +65,25 @@
"type": "process",
"args": [
"publish",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
"/p:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary",
"/p:TargetFramework=netcoreapp2.1",
"/p:RuntimeIdentifier=linux-x64",
"/p:PublishDir=${workspaceFolder}/artifacts"
],
"problemMatcher": "$msCompile",
"options": {
"cwd": "${workspaceFolder}"
}
},
{
"label": "monopublish",
"command": "msbuild",
"type": "process",
"args": [
"/t:publish",
"/p:TargetFramework=netcoreapp2.1;PublishDir=${workspaceFolder}/artiffacts;RuntimeIdentifier=linux-x64",
],
"problemMatcher": "$msCompile"
},

View File

@ -25,7 +25,7 @@ dotnet build /restore -c Release
dotnet publish -c Release
````
### Déployer le serveur
### Déploiement
````bash
sudo mkdir -p /srv/www/isnd
@ -44,14 +44,14 @@ sudo systemctl daemon-reload
sudo systemctl start isnd
````
* Activer le serveur :
* Activation du serveur :
````bash
sudo systemctl enable isnd
````
### Installer le client
### Installation du client
````bash
sudo mkdir /usr/local/lib/isn
@ -74,5 +74,52 @@ sudo systemctl start isnd
sudo cp -a src/isn/bin/Release/netcoreapp2.1/* /usr/local/lib/isn
sudo chown -R root.root /usr/local/lib/isn
````
## 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."
},
````

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<apikeys>
</apikeys>
<packageSources>
<add key="myIsnDev" value="http://localhost:5000/index.json" protocolVersion="3" />
</packageSources>
</configuration>

View File

@ -0,0 +1,2 @@
nuget install -Verbosity detailed -Source http://localhost:5000/index.json -Prerelease Yavsc.Abstract
nuget locals all -clear

View File

@ -0,0 +1,4 @@
= URL's
<http://localhost:5000/v3.4.0/registration/yavsc.abstract/index.json>

View File

@ -1,11 +1,13 @@
#!/bin/bash
set -e
# compiler tout
dotnet publish -c Release
dotnet build -c Release
dotnet publish -c Release -f netcoreapp2.1 src/isnd
# MAJ du serveur
sudo systemctl stop isnd
sudo cp -a src/isnd/bin/Release/netcoreapp2.1/publish/* /srv/www/isnd
sudo systemctl start isnd
# MAJ du client
sudo cp -a src/isn/bin/Release/net472/* /usr/local/lib/isn
sudo chmod +x /usr/local/lib/isn/isn.exe
sudo cp -a src/isn/bin/Release/netcoreapp2.1/* /usr/local/lib/isn
sudo chown -R root.root /usr/local/lib/isn

22
omnisharp.json Normal file
View File

@ -0,0 +1,22 @@
{
"dotnet": {
"enabled": false
},
"msbuild": {
"enabled": true
},
"Dnx": {
"enabled": false
},
"Script": {
"enabled": false
},
"fileOptions": {
"systemExcludeSearchPatterns": [
"**/bin/**/*",
"**/obj/**/*",
"**/node_modules/**/*"
],
"userExcludeSearchPatterns": []
}
}

View File

@ -1,21 +1,21 @@
using isn.abst;
namespace isnd.Entities
{
public static class ApiConfig
{
public const string Publish = "put";
public const string Base = "index.json";
public const string Index = "index";
public const string IndexDotJson = Index + ".json";
public const string Catalog = "catalog";
public const string CatalogPage = "catalog-page";
public const string Get = "package";
public const string GetPackage = Constants.PaquetFileEstension;
public const string GetVersion = "version";
public const string Search = "search";
public const string AutoComplete = "autocomplete";
public const string CatalogLeaf = "catalog-leaf";
public const string CatalogPackageDetail = "package-detail";
public const string Delete = "delete";
public const string Registration = "registration";
internal const string GetNuspec = Constants.SpecFileEstension;
}
}

View File

@ -0,0 +1,9 @@
namespace isn.abst
{
public static class Constants
{
public const string PaquetFileEstension = "nupkg";
public const string SpecFileEstension = "nuspec";
public const string JsonFileEstension = "json";
}
}

View File

@ -4,7 +4,7 @@ using System.Linq;
namespace isnd.Attributes
{
internal class SafeNameAttribute : ValidationAttribute
public class SafeNameAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{

View File

@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageVersion>1.0.1</PackageVersion>
<Version>0.1.175</Version>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Version>1.0.5</Version>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<NoWarn>NETSDK1138</NoWarn>
<AssemblyVersion>0.1.175.0</AssemblyVersion>
<FileVersion>0.1.175.0</FileVersion>
<InformationalVersion>0.1.175+Branch.main.Sha.3e09afcbfe0eff74c0b3aa0fb974e0801f4708b6</InformationalVersion>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<InformationalVersion>1.0.5+Branch.main.Sha.14206ac477d0f07566d5e8125dc52cbd7f474ca2</InformationalVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />

View File

@ -20,11 +20,11 @@ namespace isn
currentSource = settings.DefaultSource;
}
}
static OptionSet storeoptions = new OptionSet {
static readonly OptionSet storeoptions = new OptionSet {
{ "s|source=", "use source", val => currentSource = currentSource ?? val },
{ "h|help", "show this message and exit", h => shouldShowPushHelp = h != null },
};
private static string _configFileName =
private static readonly string _configFileName =
Path.Combine(
Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile), ".isn"),
@ -32,21 +32,21 @@ namespace isn
;
public const string push = "push";
static OptionSet options = new OptionSet {
static readonly OptionSet options = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowHelp = h != null },
};
static OptionSet pushoptions = new OptionSet {
static readonly OptionSet pushoptions = new OptionSet {
{ "k|api-key=", "use api key", val => apiKey = apiKey ?? val },
{ "p|store-api-key", "store used api key (=<true|false>)", val => storApiKey = val != null },
{ "s|source=", "use source", val => currentSource = currentSource ?? val },
{ "h|help", "show this message and exit", h => shouldShowPushHelp = h != null },
};
static OptionSet sourceoptions = new OptionSet {
static readonly OptionSet sourceoptions = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowSourceHelp = h != null },
};
static OptionSet showOptions = new OptionSet {
static readonly OptionSet showOptions = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowSourceHelp = h != null },
};
@ -154,7 +154,7 @@ namespace isn
var pushCmd = new Command(push)
{
Run = async sargs =>
Run = sargs =>
{
var pargs = pushoptions.Parse(sargs);
if (shouldShowPushHelp)

View File

@ -23,37 +23,5 @@ namespace isn
return result;
}
public static async Task<ApiIndexViewModel> GetServerResourcesUsingWebRequestAsync(string url)
{
ApiIndexViewModel viewModel=null;
var uri = new Uri(url);
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.Method = "GET";
httpWebRequest.AllowAutoRedirect = false;
try{
using (var resp = await httpWebRequest.GetResponseAsync())
{
using (var stream = resp.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
var json = await reader.ReadToEndAsync();
Console.Write("got json : "+json);
viewModel = JsonConvert.DeserializeObject<ApiIndexViewModel>(json);
}
}
}
}
catch(Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
return viewModel;
}
}
}

View File

@ -4,22 +4,22 @@
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<RootNamespace>nuget_cli</RootNamespace>
<UserSecretsId>45b74c62-05bc-4603-95b4-3e80ae2fdf50</UserSecretsId>
<Version>0.1.175</Version>
<Version>1.0.5</Version>
<PackageVersion>1.0.1</PackageVersion>
<IsPackable>true</IsPackable>
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
<IsTool>true</IsTool>
<NoWarn>NETSDK1138</NoWarn>
<AssemblyVersion>0.1.175.0</AssemblyVersion>
<FileVersion>0.1.175.0</FileVersion>
<InformationalVersion>0.1.175+Branch.main.Sha.3e09afcbfe0eff74c0b3aa0fb974e0801f4708b6</InformationalVersion>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<InformationalVersion>1.0.5+Branch.main.Sha.14206ac477d0f07566d5e8125dc52cbd7f474ca2</InformationalVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mono.Options" Version="5.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="unleash.client" Version="1.6.1" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<Reference Include="System.Net.Http" Version="4.0.0" />
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../isn.abst/isn.abst.csproj" />

View File

@ -6,7 +6,7 @@ using System.Linq;
using isnd.ViewModels;
using Unleash;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
namespace isnd.Controllers
{
@ -25,9 +25,10 @@ namespace isnd.Controllers
public IActionResult Index()
{
return View(new HomeIndexViewModel{
PkgCount = _dbContext.Packages.Count(),
PkgCount = _dbContext.Packages
.Where(p => p.Versions.Count > 0)
.Count(),
UnleashClient = _unleashĈlient
});
}

View File

@ -27,7 +27,10 @@ namespace isnd
// GET: PackageVersion
public async Task<IActionResult> Index(PackageVersionIndexViewModel model)
{
var applicationDbContext = _context.PackageVersions.Include(p => p.Package).Where(
var applicationDbContext = _context.PackageVersions.Include(p => p.Package)
.Include(p => p.Package.Owner)
.Include(p => p.Package.Versions)
.Where(
p => (model.Prerelease || !p.IsPrerelease)
&& ((model.PackageId == null) || p.PackageId.StartsWith(model.PackageId)));
model.Versions = await applicationDbContext.ToArrayAsync();
@ -47,60 +50,5 @@ namespace isnd
return View("Index", model);
}
// GET: PackageVersion/Details/5
public async Task<IActionResult> Details(string pkgid, string version)
{
if (pkgid == null || version == null)
{
return NotFound();
}
var packageVersion = await _context.PackageVersions
.Include(p => p.Package)
.FirstOrDefaultAsync(m => m.PackageId == pkgid && m.FullString == version);
if (packageVersion == null)
{
return NotFound();
}
return View(packageVersion);
}
[Authorize]
public async Task<IActionResult> Delete(string pkgid, string version, string pkgtype)
{
if (pkgid == null || version == null)
{
return NotFound();
}
var packageVersion = await _context.PackageVersions.Include(p => p.Package)
.FirstOrDefaultAsync(m => m.PackageId == pkgid
&& m.FullString == version && m.Type == pkgtype);
if (packageVersion == null) return NotFound();
if (!User.IsOwner(packageVersion)) return Unauthorized();
var pkg = await _pm.GetPackageAsync(pkgid, version, pkgtype);
return View(pkg);
}
// POST: PackageVersion/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(string PackageId, string FullString,
string Type)
{
PackageVersion packageVersion = await _context.PackageVersions
.FirstOrDefaultAsync(m => m.PackageId == PackageId
&& m.FullString == FullString && m.Type == Type);
if (packageVersion == null) return NotFound();
if (!User.IsOwner(packageVersion)) return Unauthorized();
await _pm.DeletePackageAsync(PackageId, FullString, Type);
return RedirectToAction(nameof(Index));
}
}
}

View File

@ -16,12 +16,13 @@ using isnd.ViewModels;
using System.Threading.Tasks;
using isnd.Interfaces;
using isn.Abstract;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController : Controller
{
[HttpGet(_pkgRootPrefix + ApiConfig.Base)]
[HttpGet(_pkgRootPrefix + ApiConfig.IndexDotJson)]
public IActionResult ApiIndex()
{
return Ok(new ApiIndexViewModel{ Version = PackageManager.BASE_API_LEVEL, Resources = resources });

View File

@ -17,26 +17,17 @@ namespace isnd.Controllers
int skip = 0,
int take = 25)
{
CheckParams(take, semVerLevel);
if (ModelState.ErrorCount > 0) return BadRequest(ModelState);
return Ok(packageManager.AutoComplete(id,skip,take,prerelease,packageType));
}
protected void CheckParams(int maxTake)
{
if (maxTake > maxTake)
if (take > maxTake)
{
ModelState.AddModelError("take", "Maximum exceeded");
}
}
protected void CheckParams(int take, string semVerLevel)
{
CheckParams(take);
if (semVerLevel != PackageManager.BASE_API_LEVEL)
{
ModelState.AddModelError("semVerLevel", PackageManager.BASE_API_LEVEL + " expected");
}
if (ModelState.ErrorCount > 0) return BadRequest(ModelState);
return Ok(packageManager.AutoComplete(id,skip,take,prerelease,packageType));
}
}
}

View File

@ -1,25 +1,22 @@
using System.Linq;
using System.Threading.Tasks;
using isnd.Data.Catalog;
using isnd.Helpers;
using isnd.Services;
using isnd.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using NuGet.Versioning;
namespace isnd.Controllers
{
public partial class PackagesController
{
// https://docs.microsoft.com/en-us/nuget/api/catalog-resource#versioning
[HttpGet(_pkgRootPrefix + ApiConfig.Catalog)]
public IActionResult CatalogIndex()
{
return Ok(PackageManager.CurrentCatalogIndex);
}
[HttpGet(_pkgRootPrefix + ApiConfig.CatalogPage + "-{id}")]
public IActionResult Index(string id)
{
@ -27,35 +24,50 @@ namespace isnd.Controllers
return Ok(PackageManager.CurrentCatalogPages[int.Parse(id)]);
}
[HttpGet(_pkgRootPrefix + ApiConfig.CatalogLeaf + "/{id}/{*lower}")]
public async Task<IActionResult> CatalogLeafAsync(string id, string lower)
[HttpGet(_pkgRootPrefix + "{apiVersion}/" + ApiConfig.Registration + "/{id}/{lower}.json")]
public IActionResult CatalogRegistration(string apiVersion, string id, string lower)
{
string pkgType = ParamHelpers.Optional(ref lower);
var pkgVersion = await dbContext.PackageVersions
.Include(v => v.LatestCommit)
.SingleOrDefaultAsync(
v => v.PackageId == id &&
v.FullString == lower &&
v.Type == pkgType
);
if (pkgVersion == null) return NotFound();
var pub = await dbContext.Commits
.Include(c => c.Versions)
.OrderBy(c => c.CommitTimeStamp)
.SingleOrDefaultAsync
(
c => c.Action == PackageAction.PublishPackage
&& c.Versions.Contains(pkgVersion)
);
return Ok(new CatalogLeaf
if (lower.Equals("index", System.StringComparison.OrdinalIgnoreCase))
{
CommitId = id,
Id = pkgVersion.PackageId,
CommitTimeStamp = pkgVersion.LatestCommit.CommitTimeStamp
});
var query = new Data.Catalog.RegistrationPageIndexQuery
{
Query = id,
Prerelease = true
};
var index = packageManager.GetPackageRegistrationIndex(query);
if (index == null) return NotFound();
// query.TotalHits = result.Items.Select(i=>i.Items.Length).Aggregate((a,b)=>a+b);
return Ok(index);
}
var leaf = packageManager.SearchById(id,lower,null);
if (leaf.Count()==0) return NotFound(new { id, lower });
return Ok(leaf.First());
}
[HttpGet(_pkgRootPrefix + ApiConfig.CatalogLeaf + "/{id}/{version}/{lower}/index.json")]
public IActionResult CatalogLeaf(string id, string pversion, string lower)
{
bool askForindex = lower == null;
var pkgvs = this.packageManager.GetCatalogLeaf(id, pversion, lower).ToArray();
if (pkgvs.Count() == 0) return NotFound();
List<string> types = pkgvs.Select(
v => v.Type ?? "Dependency"
).Distinct().ToList();
if (!types.Contains("PackageDelete"))
types.Add("PackageDetails");
var last = pkgvs.Last();
var pub = last.LatestCommit.CommitTimeStamp;
return Ok(new Data.Packages.Catalog.CatalogLeaf
{
CommitId = last.CommitId,
Id = id,
CommitTimeStamp = pub,
Version = last.FullString,
Published = pub,
RefType = types.ToArray()
});
}
}
}

View File

@ -4,17 +4,20 @@ using isnd.Helpers;
using isnd.Entities;
using System.ComponentModel.DataAnnotations;
using isnd.Attributes;
using System.Security.Claims;
namespace isnd.Controllers
{
public partial class PackagesController
{
[HttpDelete(_pkgRootPrefix + ApiConfig.Delete + "/{id}/{*lower}")]
public async Task<IActionResult> Delete(
[HttpDelete(_pkgRootPrefix + ApiConfig.Delete + "/{id}/{lower?}/{type?}")]
public async Task<IActionResult> ApiDelete(
[FromRoute][SafeName][Required] string id,
[FromRoute][SafeName][Required] string lower)
[FromRoute][SafeName][Required] string lower,
[FromRoute] string type)
{
string pkgtype = ParamHelpers.Optional(ref lower);
var report = await packageManager.DeletePackageAsync(id, lower, pkgtype);
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
var report = await packageManager.UserAskForPackageDeletionAsync(uid, id, lower, type);
return Ok(report);
}
}

View File

@ -3,20 +3,23 @@ using System.IO;
using Microsoft.AspNetCore.Mvc;
using isnd.Attributes;
using isnd.Entities;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController
{
// Web get nupkg
[HttpGet(_pkgRootPrefix + ApiConfig.Get + "/{id}/{lower}/{idf}-{lowerf}.nupkg")]
// Web get the paquet
[HttpGet(_pkgRootPrefix + ApiConfig.GetPackage + "/{id}/{lower}/{idf}-{lowerf}."
+ Constants.PaquetFileEstension)]
public IActionResult GetPackage(
[FromRoute][SafeName][Required] string id,
[FromRoute][SafeName][Required] string lower,
[FromRoute] string idf, [FromRoute] string lowerf)
{
var pkgpath = Path.Combine(isndSettings.PackagesRootDir,
id, lower, $"{id}-{lower}.nupkg"
id, lower, $"{id}-{lower}." + Constants.PaquetFileEstension
);
FileInfo pkgfi = new FileInfo(pkgpath);
@ -29,7 +32,8 @@ namespace isnd.Controllers
}
// Web get spec
[HttpGet(_pkgRootPrefix + ApiConfig.Get + "/{id}/{lower}/{idf}-{lowerf}.nuspec")]
[HttpGet(_pkgRootPrefix + Constants.SpecFileEstension + "/{id}/{lower}/{idf}-{lowerf}."
+ Constants.SpecFileEstension)]
public IActionResult GetNuspec(
[FromRoute][SafeName][Required] string id,
[FromRoute][SafeName][Required] string lower,
@ -37,7 +41,7 @@ namespace isnd.Controllers
[FromRoute][SafeName][Required] string lowerf)
{
var pkgpath = Path.Combine(isndSettings.PackagesRootDir,
id, lower, $"{id}.nuspec");
id, lower, $"{id}." + Constants.SpecFileEstension);
FileInfo pkgfi = new FileInfo(pkgpath);
if (!pkgfi.Exists)

View File

@ -1,12 +1,13 @@
using Microsoft.AspNetCore.Mvc;
using NuGet.Versioning;
using isnd.Entities;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController
public partial class PackagesController
{
[HttpGet(_pkgRootPrefix + ApiConfig.Get + "/{id}/{lower}/index.json")]
[HttpGet(_pkgRootPrefix + ApiConfig.GetVersion + "/{id}/{lower}/" + ApiConfig.IndexDotJson)]
public IActionResult GetVersions(
string id,
string lower,

View File

@ -15,7 +15,8 @@ using isnd.Data;
using isnd.Helpers;
using isnd.Entities;
using Microsoft.AspNetCore.Http;
using isnd.Data.Catalog;
using isn.abst;
using isnd.Data.Packages;
namespace isnd.Controllers
{
@ -52,7 +53,7 @@ namespace isnd.Controllers
{
string initpath = Path.Combine(Environment.GetEnvironmentVariable("TEMP") ??
Environment.GetEnvironmentVariable("TMP") ?? "/tmp",
$"isn-{Guid.NewGuid()}.nupkg");
$"isn-{Guid.NewGuid()}."+Constants.PaquetFileEstension);
using (FileStream fw = new FileStream(initpath, FileMode.Create))
{
@ -63,14 +64,14 @@ namespace isnd.Controllers
{
var archive = new ZipArchive(fw);
var nuspec = archive.Entries.FirstOrDefault(e => e.FullName.EndsWith(".nuspec"));
if (nuspec == null) return BadRequest(new { error = "no nuspec from archive" });
var spec = archive.Entries.FirstOrDefault(e => e.FullName.EndsWith("." + Constants.SpecFileEstension));
if (spec == null) return BadRequest(new { error = "no " + Constants.SpecFileEstension + " from archive" });
string pkgpath;
NuGetVersion version;
string pkgid;
string fullpath;
using (var specstr = nuspec.Open())
using (var specstr = spec.Open())
{
NuspecCoreReader reader = new NuspecCoreReader(specstr);
@ -82,29 +83,29 @@ namespace isnd.Controllers
string pkgidpath = Path.Combine(isndSettings.PackagesRootDir,
pkgid);
pkgpath = Path.Combine(pkgidpath, version.ToFullString());
string name = $"{pkgid}-{version}.nupkg";
string name = $"{pkgid}-{version}."+Constants.PaquetFileEstension;
fullpath = Path.Combine(pkgpath, name);
var destpkgiddir = new DirectoryInfo(pkgidpath);
Package package = dbContext.Packages.SingleOrDefault(p => p.Id == pkgid);
if (package != null)
Package pkg = dbContext.Packages.SingleOrDefault(p => p.Id == pkgid);
if (pkg != null)
{
if (package.OwnerId != apikey.UserId)
if (pkg.OwnerId != apikey.UserId)
{
return new ForbidResult();
}
package.Description = pkgdesc;
pkg.Description = pkgdesc;
}
else
{
package = new Package
pkg = new Package
{
Id = pkgid,
Description = pkgdesc,
OwnerId = apikey.UserId,
LatestVersion = commit
LatestVersion = commit,
};
dbContext.Packages.Add(package);
dbContext.Packages.Add(pkg);
}
if (!destpkgiddir.Exists) destpkgiddir.Create();
@ -117,7 +118,7 @@ namespace isnd.Controllers
// mais si elle ne l'est pas en base de donnéés,
// on remplace la version sur disque.
var pkgv = dbContext.PackageVersions.Where(
v => v.PackageId == package.Id
v => v.PackageId == pkg.Id
);
if (pkgv !=null && pkgv.Count()==0)
@ -136,21 +137,23 @@ namespace isnd.Controllers
files.Add(name);
string fullstringversion = version.ToFullString();
var pkgvers = dbContext.PackageVersions.Where
(v => v.PackageId == package.Id && v.FullString == fullstringversion);
(v => v.PackageId == pkg.Id && v.FullString == fullstringversion);
if (pkgvers.Count() > 0)
{
foreach (var v in pkgvers.ToArray())
dbContext.PackageVersions.Remove(v);
}
// FIXME default type or null
if (types==null || types.Count==0)
dbContext.PackageVersions.Add
(new PackageVersion{
Package = package,
Package = pkg,
Major = version.Major,
Minor = version.Minor,
Patch = version.Patch,
Revision = version.Revision,
IsPrerelease = version.IsPrerelease,
FullString = version.ToFullString(),
Type = null,
@ -161,7 +164,7 @@ namespace isnd.Controllers
{
var pkgver = new PackageVersion
{
Package = package,
Package = pkg,
Major = version.Major,
Minor = version.Minor,
Patch = version.Patch,
@ -176,7 +179,7 @@ namespace isnd.Controllers
await dbContext.SaveChangesAsync();
packageManager.ÛpdateCatalogFor(commit);
logger.LogInformation($"new package : {nuspec.Name}");
logger.LogInformation($"new paquet : {spec.Name}");
}
}
using (var shacrypto = System.Security.Cryptography.SHA512.Create())
@ -194,12 +197,12 @@ namespace isnd.Controllers
}
}
}
string nuspecfullpath = Path.Combine(pkgpath, pkgid + ".nuspec");
string nuspecfullpath = Path.Combine(pkgpath, pkgid + "." + Constants.SpecFileEstension);
FileInfo nfpi = new FileInfo(nuspecfullpath);
if (nfpi.Exists)
nfpi.Delete();
nuspec.ExtractToFile(nuspecfullpath);
spec.ExtractToFile(nuspecfullpath);
}
}

View File

@ -0,0 +1,10 @@
using isnd.Data.Catalog;
namespace isnd
{
public class RegistrationPageIndexQueryAndResult
{
public RegistrationPageIndexQuery Query { get; set; }
public RegistrationPageIndex Result { get; set; }
}
}

View File

@ -11,7 +11,7 @@ namespace isnd.Controllers
{
// GET {@id}?q={QUERY}&skip={SKIP}&take={TAKE}&prerelease={PRERELEASE}&semVerLevel={SEMVERLEVEL}&packageType={PACKAGETYPE}
[HttpGet(_pkgRootPrefix + ApiConfig.Search)]
public async Task<IActionResult> Search(
public IActionResult Search(
string q,
int skip = 0,
int take = 25,

View File

@ -1,7 +1,11 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using isnd.Data;
using isnd.Data.Catalog;
using isnd.Helpers;
using isnd.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -11,15 +15,12 @@ namespace isnd.Controllers
public partial class PackagesController
{
// Web search
public async Task<IActionResult> Index(PackageIndexViewModel model)
public async Task<IActionResult> Index(RegistrationPageIndexQuery model)
{
var applicationDbContext = dbContext.Packages.Include(p => p.Versions).Where(
p => ( model.Prerelease || p.Versions.Any(v => !v.IsPrerelease))
&& ((model.Query == null) || p.Id.StartsWith(model.Query)));
model.Data = await applicationDbContext.ToArrayAsync();
return View(model);
return View(new RegistrationPageIndexQueryAndResult{Query = model,
Result = packageManager.GetPackageRegistrationIndex(model)});
}
public async Task<IActionResult> Details(string pkgid)
{
if (pkgid == null)
@ -50,6 +51,41 @@ namespace isnd.Controllers
}
const int MAX_PKG_VERSION_LIST = 50;
[Authorize]
public async Task<IActionResult> Delete(string pkgid, string version, string pkgtype)
{
if (pkgid == null || version == null)
{
return NotFound();
}
// var report = await packageManager.DeletePackageAsync(id, lower, type);
var packageVersion = await dbContext.PackageVersions.Include(p => p.Package)
.FirstOrDefaultAsync(m => m.PackageId == pkgid
&& m.FullString == version && m.Type == pkgtype);
if (packageVersion == null) return NotFound();
if (!User.IsOwner(packageVersion)) return Unauthorized();
var pkg = await packageManager.GetPackageAsync(pkgid, version, pkgtype);
return View(pkg);
}
// POST: PackageVersion/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(string PackageId, string FullString,
string Type)
{
PackageVersion packageVersion = await dbContext.PackageVersions
.Include(pv => pv.Package)
.FirstOrDefaultAsync(m => m.PackageId == PackageId
&& m.FullString == FullString && m.Type == Type);
if (packageVersion == null) return NotFound();
if (!User.IsOwner(packageVersion)) return Unauthorized();
await packageManager.DeletePackageAsync(PackageId, FullString, Type);
return RedirectToAction(nameof(Index));
}
}
}

View File

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

View File

@ -0,0 +1,11 @@
using NuGet.Versioning;
namespace isnd.Data.Catalog
{
public class AlternatePackage
{
public string id { get ; set; }
public VersionRange range { get ; set; }
}
}

View File

@ -0,0 +1,82 @@
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
public class CatalogEntry
{
/// <summary>
/// The URL to the document used to produce this object
/// </summary>
/// <value></value>
[Key][Required,JsonRequired]
[StringLength(1024)]
[JsonProperty("@id")]
public string Id { get; set; }
/// <summary>
/// Authors
/// </summary>
/// <value>string or array of strings</value>
public string authors { get; set; }
/// <summary>
/// The dependencies of the package, grouped by target framework
/// </summary>
/// <value>array of objects</value>
public DependencyGroup[] dependencyGroups { get; set; }
/// <summary>
/// The deprecation associated with the package
/// </summary>
/// <value></value>
public Deprecation deprecation { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
public string iconUrl { get; set; }
/// <summary>
/// The ID of the package
/// </summary>
/// <value></value>
public string idp { get; set; }
public string licenseUrl { get; set; }
public string licenseExpression { get; set; }
/// <summary>
/// Should be considered as listed if absent
/// </summary>
/// <value></value>
public bool listed { get; set; }
public string minClientVersion { get; set; }
public string projectUrl { get; set; }
/// <summary>
/// A string containing a ISO 8601 timestamp of when the package was published
/// </summary>
/// <value></value>
public string published { get; set; }
public bool requireLicenseAcceptance { get; set; }
public string summary { get; set; }
/// <summary>
/// The tags
/// </summary>
/// <value></value>
public string tags { get; set; }
public string title { get; set; }
/// <summary>
/// The full version string after normalization
/// </summary>
/// <value></value>
[Required,JsonRequired]
public string version { get; set; } // string yes
/// <summary>
/// The security vulnerabilities of the package
/// </summary>
/// <value></value>
public Vulnerabilitie[] vulnerabilities { get; set; }
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
public class CatalogIndex : IObject
{
[JsonProperty("@id")]
public string Id { get; set ; }
[JsonProperty("items")]
public List<PageRef> Items { get; set; }
[JsonProperty("count")]
public int Count { get => Items?.Count ?? 0; }
public string CommitId { get; set; }
public DateTime CommitTimeStamp { get; set; }
}
}

View File

@ -0,0 +1,6 @@
namespace isnd.Data.Catalog
{
public class DependencyGroup
{
}
}

View File

@ -0,0 +1,14 @@
namespace isnd.Data.Catalog
{
public class Deprecation
{
/*
Legacy The package is no longer maintained
CriticalBugs The package has bugs which make it unsuitable for usage
Other The package is deprecated due to a reason not on this list
*/
public string[] reasons { get; set; } // array of strings yes The reasons why the package was deprecated
public string message { get; set; } // The additional details about this deprecation
public AlternatePackage alternatePackage { get; set; } // object no The alternate package that should be used instead
}
}

View File

@ -1,26 +0,0 @@
using System;
using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
public class PageRef : IObject
{
/// <summary>
/// Page Url
/// </summary>
/// <value></value>
[JsonProperty("@id")]
public string Id { get; set; }
/// <summary>
/// Page entry count
/// </summary>
/// <value></value>
[JsonProperty("count")]
public int Count { get; set; }
public string CommitId { get; set; }
public DateTime CommitTimeStamp { get; set; }
}
}

View File

@ -0,0 +1,40 @@
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
/// <summary>
/// Hosts a catalog entry,
/// the atomic content reference
/// </summary>
public class RegistrationLeaf
{
/*
@id string yes
catalogEntry object yes
packageContent string yes
*/
[JsonProperty("@id")]
[Key][Required]
[StringLength(1024)]
/// <summary>
/// The URL to the registration leaf
/// </summary>
/// <value></value>
public string Id { get; set; }
/// <summary>
/// The catalog entry containing the package metadata
/// </summary>
/// <value></value>
[JsonProperty("catalogEntry")]
public CatalogEntry Entry { get; set; }
/// <summary>
/// The URL to the package content (.nupkg)
/// </summary>
/// <value></value>
[JsonProperty("packageContent")]
public string PackageContent { get; set; }
}
}

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using isnd.Data.Packages;
using Newtonsoft.Json;
using NuGet.Versioning;
namespace isnd.Data.Catalog
{
public class RegistrationPage
{
[JsonProperty("@id")]
[JsonRequired]
public string Id { get; protected set;}
private List<PackageVersion> items;
protected string Bid { get ; private set; }
public string DlBase { get; }
public RegistrationPage (string bid, string dlBase)
{
Bid = bid;
DlBase = dlBase;
this.items = new List<PackageVersion>();
}
public RegistrationPage (string bid, string pkgid, string dlBase, IEnumerable<PackageVersion> items)
{
Bid = bid;
Parent = Bid + "/index.json";
DlBase = dlBase;
this.items = new List<PackageVersion>(items);
SetPackageId(pkgid);
UpdateCompact();
}
protected void SetPackageId(string pkgid)
{
this.Id = Bid + "/" + pkgid + "/index.json";
}
private void UpdateCompact()
{
NuGetVersion upper = new NuGetVersion(0,0,0);
// Assert.True(items.All(p=>p.Id == id));
foreach (var p in items)
{
if (upper < p.NugetVersion) upper = p.NugetVersion;
}
Upper = upper.ToFullString();
NuGetVersion lower = upper;
foreach (var p in items)
{
if (lower > p.NugetVersion) lower = p.NugetVersion;
}
Lower = lower.ToFullString();
}
/// <summary>
/// no The array of registration leaves and their associate metadata
/// </summary>
/// <value></value>
[JsonProperty("items")]
public RegistrationLeaf[] Items { get => items.Select((p) => p.ToLeave(Bid, DlBase)).ToArray(); }
public void AddVersionRange(IEnumerable<PackageVersion> vitems)
{
if (vitems.Count() == 0) return;
items.AddRange(vitems);
UpdateCompact();
}
/// <summary>
/// The highest SemVer 2.0.0 version in the page (inclusive)
/// </summary>
/// <value></value>
[JsonProperty("upper"), JsonRequired]
public string Upper { get; private set; }
/// <summary>
/// The lowest SemVer 2.0.0 version in the page (inclusive)
/// </summary>
/// <value></value>
[JsonProperty("lower"), JsonRequired]
public string Lower { get; private set; }
/// <summary>
/// The URL to the registration index
/// </summary>
/// <value></value>
[JsonProperty("parent")]
public string Parent { get; set; }
[JsonProperty("count")]
public int Count { get; internal set; }
public string CommitId { get; internal set; }
public DateTime CommitTimeStamp { get; internal set; }
}
}

View File

@ -0,0 +1,43 @@
using isnd.Data.Packages;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
namespace isnd.Data.Catalog
{
public class RegistrationPageIndex
{
/// <summary>
/// Page Url
/// </summary>
/// <value></value>
[JsonProperty("@id")]
public string Id { get; protected set; }
public RegistrationPageIndex(string bid, string id)
{
Id = bid + "/" + id + "/index.json";
Items = new List<RegistrationPage>();
}
public RegistrationPageIndex(string bid, string id, string dlBase, IEnumerable<Package> pkgs) : this(bid, id)
{
// leaves;
this.Items = new List<RegistrationPage>
(pkgs.GroupBy(l => l.Id)
.Select(lg => new RegistrationPage
(bid, lg.Key, dlBase, lg.ToArray()
.Select(p => p.Versions).Aggregate
((l, m) => { l.AddRange(m); return l.ToList(); })
)));
}
[JsonProperty("count")]
public int Count { get => Items?.Count ?? 0; }
[JsonProperty("items")]
public List<RegistrationPage> Items { get; set; }
public string CommitId { get; set; }
}
}

View File

@ -0,0 +1,28 @@
using System.Collections.Generic;
using isnd.Data.Packages;
using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
public class RegistrationPageIndexQuery
{
public RegistrationPageIndexQuery()
{
}
[JsonProperty("query")]
public string Query { get; set; }
[JsonProperty("prerelease")]
public bool Prerelease { get; set; } = true;
[JsonProperty("skip")]
public int Skip { get; set; } = 0;
[JsonProperty("take")]
public int Take { get; set; } = 25;
[JsonProperty("totalHits")]
public int TotalHits { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace isnd.Data.Catalog
{
public class Vulnerabilitie
{
public string advisoryUrl { get; set; } // string yes Location of security advisory for the package
public string severity { get; set; } // string yes Severity of advisory: "0" = Low, "1" = Moderate, "2" = High, "3" = Critical
}
}

View File

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

View File

@ -1,48 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using isnd.Data.Catalog;
using Newtonsoft.Json;
namespace isnd.Data
{
public class PackageVersion
{
[Required]
[ForeignKey("Package")]
[StringLength(1024)]
public string PackageId { get; set; }
[Required]
public int Major { get; set; }
[Required]
public int Minor { get; set; }
[Required]
public int Patch { get; set; }
[StringLength(256)]
[Required][Key]
public string FullString { get; set; }
public bool IsPrerelease { get; set; }
[StringLength(256)]
public string Type { get; set; }
[JsonIgnore]
public virtual Package Package { get; set; }
[Required][JsonIgnore]
[ForeignKey("LatestCommit")]
public long CommitNId { get; set ; }
[NotMapped]
public string CommitId { get => CommitNId.ToString(); }
public virtual Commit LatestCommit{ get; set; }
public string NugetLink => $"/package/{PackageId}/{FullString}/{PackageId}-{FullString}.nupkg";
public string NuspecLink => $"/package/{PackageId}/{FullString}/{PackageId}-{FullString}.nuspec";
}
}

View File

@ -1,14 +1,15 @@
using System;
using System.Collections.Generic;
using isnd.Interfaces;
using Newtonsoft.Json;
namespace isnd.Data.Catalog
namespace isnd.Data.Packages.Catalog
{
public class CatalogLeaf : IObject
{
[JsonProperty("@type")]
public List<string> RefType { get; set; }
public string[] RefType { get; set; }
[JsonProperty("commitId")]
public string CommitId { get; set; }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,10 +2,12 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using isnd.Data.Catalog;
using isnd.Interfaces;
using Newtonsoft.Json;
namespace isnd.Data
namespace isnd.Data.Packages
{
public class Package : IObject
{
@ -30,8 +32,8 @@ namespace isnd.Data
public virtual List<PackageVersion> Versions { get; set; }
/// <summary>
/// Latest package version put, or post,
/// or { delete when no more active version }.
/// Latest version at put, posted,
/// or even deletion when no more active version.
/// </summary>
/// <value></value>
[Required][JsonIgnore]
@ -44,5 +46,28 @@ namespace isnd.Data
public virtual Commit LatestVersion{ get; set; }
public DateTime CommitTimeStamp { get; set; }
/// <summary>
/// Returns the leaf
/// </summary>
/// <param name="bid">base url tu use for building the id property</param>
/// <returns></returns>
public RegistrationLeaf ToLeave(string bid)
{
if (Versions.Count == 0) throw new Exception("NO VERSION");
var v = Versions.OrderBy(w => w.NugetVersion).First();
RegistrationLeaf leave = new RegistrationLeaf
{
Id = bid + Id + "/" + v.FullString + ".json",
PackageContent = v.NugetLink,
Entry = new CatalogEntry
{
Id = bid + Id + ".json",
idp = Id,
version = v.FullString,
authors = $"{Owner.FullName} <${Owner.Email}>"
}
};
return leave;
}
}
}

View File

@ -0,0 +1,83 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using isn.abst;
using isnd.Data.Catalog;
using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
using Newtonsoft.Json;
using NuGet.Versioning;
namespace isnd.Data
{
public class PackageVersion
{
[Required]
[ForeignKey("Package")]
[StringLength(1024)]
[JsonProperty("id")]
public string PackageId { get; set; }
[Required]
public int Major { get; set; }
[Required]
public int Minor { get; set; }
[Required]
public int Patch { get; set; }
public int Revision { get; set; }
/// <summary>
/// Full version string
/// </summary>
/// <value></value>
[StringLength(256)]
[Required][Key]
public string FullString { get; set; }
public bool IsPrerelease { get; set; }
[StringLength(256)]
public string Type { get; set; }
[JsonIgnore]
public virtual Package Package { get; set; }
[Required][JsonIgnore]
[ForeignKey("LatestCommit")]
public long CommitNId { get; set; }
[NotMapped]
public string CommitId { get => CommitNId.ToString(); }
public virtual Commit LatestCommit {get; set; }
public string NugetLink => $"{Constants.PaquetFileEstension}/{PackageId}/{FullString}/{PackageId}-{FullString}."
+ Constants.PaquetFileEstension;
public string NuspecLink => $"{Constants.SpecFileEstension}/{PackageId}/{FullString}/{PackageId}-{FullString}."
+ Constants.SpecFileEstension;
public string SementicVersionString { get => $"{Major}.{Minor}.{Patch}"; }
public NuGetVersion NugetVersion { get => new NuGetVersion(FullString); }
public RegistrationLeaf ToLeave(string bid, string dlbase)
{
string leaveid = bid + "/" + this.PackageId + "/" + FullString + ".json";
return new RegistrationLeaf
{
Id = leaveid,
PackageContent = dlbase + NugetLink,
Entry = new CatalogEntry
{
Id = leaveid,
idp = PackageId,
version = FullString,
authors = $"{this.Package.Owner.FullName} <${Package.Owner.Email}>"
}
};
}
}
}

View File

@ -2,12 +2,11 @@ namespace isnd.Helpers
{
public static class PackageIdHelpers
{
internal static bool SeparatedByMinusMatch(string id, string q)
{
foreach (var part in id.Split('-'))
{
if (part.StartsWith(q, System.StringComparison.OrdinalIgnoreCase)) return true;
if (part.Equals(q, System.StringComparison.OrdinalIgnoreCase)) return true;
}
return false;
}
@ -24,7 +23,7 @@ namespace isnd.Helpers
while (id.Length > i && char.IsLower(id[i])) i++;
if (i == 0) break;
id = id.Substring(i);
if (id.StartsWith(query, System.StringComparison.OrdinalIgnoreCase)) return true;
if (id.Equals(query, System.StringComparison.OrdinalIgnoreCase)) return true;
}
return false;
}

View File

@ -1,14 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using isn.abst;
using isnd.Data;
using isnd.Data.Catalog;
using isnd.Entities;
namespace isnd.Helpers
{
public static class PackageVersionHelpers
{
public static bool IsOwner(this ClaimsPrincipal user, PackageVersion v)
{
var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);
var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);
return v.Package.OwnerId == userId;
}
}

View File

@ -2,6 +2,10 @@ namespace isnd.Helpers
{
public static class SiteHelpers
{
/// <summary>
/// The Git Sementic version (from GitVersion.MsBuild)[published]
/// </summary>
/// <value></value>
public static string SemVer {
get => GitVersionInformation.SemVer;
}

View File

@ -10,7 +10,7 @@ namespace isnd.Helpers
{
public static class UnleashHelpers
{
public static IUnleash CreateUnleahClient(this IHostingEnvironment env,
UnleashClientSettings unleashClientSettings)
{

View File

@ -4,6 +4,8 @@ using isn.Abstract;
using isnd.Controllers;
using isnd.Data;
using isnd.Data.Catalog;
using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
using isnd.Services;
using isnd.ViewModels;
using NuGet.Versioning;
@ -13,15 +15,20 @@ namespace isnd.Interfaces
{
public interface IPackageManager
{
string CatalogBaseUrl { get; }
AutoCompleteResult AutoComplete(string pkgid, int skip, int take, bool prerelease = false, string packageType = null);
CatalogIndex GetCatalogIndex();
string[] GetVersions(string pkgid, NuGetVersion parsedVersion, bool prerelease = false, string packageType = null, int skip = 0, int take = 25);
PackageIndexViewModel SearchByName(string query, int skip, int take, bool prerelease = false, string packageType = null);
IEnumerable<Resource> GetResources(IUnleash unleashĈlient);
void ÛpdateCatalogFor(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);
IEnumerable<PackageVersion> GetCatalogLeaf(string pkgId, string semver, string pkgType);
IEnumerable<RegistrationLeaf> SearchById(string pkgId, string semver, string pkgType);
RegistrationPageIndex GetCatalogIndex();
RegistrationPageIndex GetPackageRegistrationIndex(RegistrationPageIndexQuery query);
}
}

View File

@ -0,0 +1,358 @@
// <auto-generated />
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;
namespace isndhost.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20220926205013_revision")]
partial class revision
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.1.14-servicing-32113")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationDate");
b.Property<string>("Name");
b.Property<string>("UserId")
.IsRequired();
b.Property<int>("ValidityPeriodInDays");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ApiKeys");
});
modelBuilder.Entity("isnd.Data.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<string>("FullName");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("isnd.Data.Packages.Commit", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("Action");
b.Property<DateTime>("TimeStamp");
b.HasKey("Id");
b.ToTable("Commits");
});
modelBuilder.Entity("isnd.Data.Packages.Package", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasMaxLength(1024);
b.Property<long>("CommitNId");
b.Property<DateTime>("CommitTimeStamp");
b.Property<string>("Description")
.HasMaxLength(1024);
b.Property<string>("OwnerId")
.IsRequired();
b.Property<bool>("Public");
b.HasKey("Id");
b.HasIndex("CommitNId");
b.HasIndex("OwnerId");
b.ToTable("Packages");
});
modelBuilder.Entity("isnd.Data.PackageVersion", b =>
{
b.Property<string>("FullString")
.ValueGeneratedOnAdd()
.HasMaxLength(256);
b.Property<long>("CommitNId");
b.Property<bool>("IsPrerelease");
b.Property<int>("Major");
b.Property<int>("Minor");
b.Property<string>("PackageId")
.IsRequired()
.HasMaxLength(1024);
b.Property<int>("Patch");
b.Property<string>("Type")
.HasMaxLength(256);
b.HasKey("FullString");
b.HasIndex("CommitNId");
b.HasIndex("PackageId");
b.ToTable("PackageVersions");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider");
b.Property<string>("ProviderKey");
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider");
b.Property<string>("Name");
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b =>
{
b.HasOne("isnd.Data.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isnd.Data.Packages.Package", b =>
{
b.HasOne("isnd.Data.Packages.Commit", "LatestVersion")
.WithMany()
.HasForeignKey("CommitNId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("isnd.Data.ApplicationUser", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isnd.Data.PackageVersion", b =>
{
b.HasOne("isnd.Data.Packages.Commit", "LatestCommit")
.WithMany("Versions")
.HasForeignKey("CommitNId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("isnd.Data.Packages.Package", "Package")
.WithMany("Versions")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,17 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace isndhost.Migrations
{
public partial class revision : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@ -0,0 +1,360 @@
// <auto-generated />
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;
namespace isndhost.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20220926223321_Re_Vision")]
partial class Re_Vision
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.1.14-servicing-32113")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("CreationDate");
b.Property<string>("Name");
b.Property<string>("UserId")
.IsRequired();
b.Property<int>("ValidityPeriodInDays");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ApiKeys");
});
modelBuilder.Entity("isnd.Data.ApplicationUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<string>("FullName");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("isnd.Data.Packages.Commit", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("Action");
b.Property<DateTime>("TimeStamp");
b.HasKey("Id");
b.ToTable("Commits");
});
modelBuilder.Entity("isnd.Data.Packages.Package", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasMaxLength(1024);
b.Property<long>("CommitNId");
b.Property<DateTime>("CommitTimeStamp");
b.Property<string>("Description")
.HasMaxLength(1024);
b.Property<string>("OwnerId")
.IsRequired();
b.Property<bool>("Public");
b.HasKey("Id");
b.HasIndex("CommitNId");
b.HasIndex("OwnerId");
b.ToTable("Packages");
});
modelBuilder.Entity("isnd.Data.PackageVersion", b =>
{
b.Property<string>("FullString")
.ValueGeneratedOnAdd()
.HasMaxLength(256);
b.Property<long>("CommitNId");
b.Property<bool>("IsPrerelease");
b.Property<int>("Major");
b.Property<int>("Minor");
b.Property<string>("PackageId")
.IsRequired()
.HasMaxLength(1024);
b.Property<int>("Patch");
b.Property<int>("Revision");
b.Property<string>("Type")
.HasMaxLength(256);
b.HasKey("FullString");
b.HasIndex("CommitNId");
b.HasIndex("PackageId");
b.ToTable("PackageVersions");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider");
b.Property<string>("ProviderKey");
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider");
b.Property<string>("Name");
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("isnd.Data.ApiKeys.ApiKey", b =>
{
b.HasOne("isnd.Data.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isnd.Data.Packages.Package", b =>
{
b.HasOne("isnd.Data.Packages.Commit", "LatestVersion")
.WithMany()
.HasForeignKey("CommitNId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("isnd.Data.ApplicationUser", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isnd.Data.PackageVersion", b =>
{
b.HasOne("isnd.Data.Packages.Commit", "LatestCommit")
.WithMany("Versions")
.HasForeignKey("CommitNId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("isnd.Data.Packages.Package", "Package")
.WithMany("Versions")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("isnd.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace isndhost.Migrations
{
public partial class Re_Vision : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Revision",
table: "PackageVersions",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Revision",
table: "PackageVersions");
}
}
}

View File

@ -92,7 +92,7 @@ namespace isndhost.Migrations
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("isnd.Data.Catalog.Commit", b =>
modelBuilder.Entity("isnd.Data.Packages.Commit", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd();
@ -106,7 +106,7 @@ namespace isndhost.Migrations
b.ToTable("Commits");
});
modelBuilder.Entity("isnd.Data.Package", b =>
modelBuilder.Entity("isnd.Data.Packages.Package", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
@ -153,6 +153,8 @@ namespace isndhost.Migrations
b.Property<int>("Patch");
b.Property<int>("Revision");
b.Property<string>("Type")
.HasMaxLength(256);
@ -280,9 +282,9 @@ namespace isndhost.Migrations
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isnd.Data.Package", b =>
modelBuilder.Entity("isnd.Data.Packages.Package", b =>
{
b.HasOne("isnd.Data.Catalog.Commit", "LatestVersion")
b.HasOne("isnd.Data.Packages.Commit", "LatestVersion")
.WithMany()
.HasForeignKey("CommitNId")
.OnDelete(DeleteBehavior.Cascade);
@ -295,12 +297,12 @@ namespace isndhost.Migrations
modelBuilder.Entity("isnd.Data.PackageVersion", b =>
{
b.HasOne("isnd.Data.Catalog.Commit", "LatestCommit")
b.HasOne("isnd.Data.Packages.Commit", "LatestCommit")
.WithMany("Versions")
.HasForeignKey("CommitNId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("isnd.Data.Package", "Package")
b.HasOne("isnd.Data.Packages.Package", "Package")
.WithMany("Versions")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade);

View File

@ -3,7 +3,6 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using MailKit.Net.Smtp;
using MimeKit;
@ -16,13 +15,13 @@ namespace isnd.Services
public class EmailSender : IEmailSender, IMailer
{
public EmailSender(IOptions<SmtpSettings> smtpSettings,
Microsoft.AspNetCore.Hosting.IHostingEnvironment env)
IHostingEnvironment env)
{
Options = smtpSettings.Value;
Env = env;
}
public SmtpSettings Options { get; } //set only via Secret Manager
public Microsoft.AspNetCore.Hosting.IHostingEnvironment Env { get; }
public IHostingEnvironment Env { get; }
public Task SendEmailAsync(string email, string subject, string message)
{
return Execute(Options.SenderName, subject, message, email);

View File

@ -6,6 +6,8 @@ using System.Threading.Tasks;
using isn.Abstract;
using isnd.Data;
using isnd.Data.Catalog;
using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
using isnd.Entities;
using isnd.Helpers;
using isnd.Interfaces;
@ -22,7 +24,7 @@ namespace isnd.Services
public const string BASE_API_LEVEL = "3.5.0";
ApplicationDbContext dbContext;
public PackageManager(ApplicationDbContext dbContext,
IOptions<IsndSettings> siteConfigOptionsOptions)
{
@ -47,15 +49,15 @@ namespace isnd.Services
Comment = "Package Publish service"
});
// under dev, only leash in release mode
if (unleashClient.IsEnabled("pkg-get", false))
if (unleashClient.IsEnabled("pkg-get", true))
res.Add(
new Resource
{
Id = extUrl + ApiConfig.Base,
Type = "PackageBaseAddress/" + BASE_API_LEVEL,
Id = extUrl + ApiConfig.GetPackage,
Type = "PackageBaseAddress/3.0.0",
Comment = "Package Base Address service"
});
if (unleashClient.IsEnabled("pkg-autocomplete", false))
if (unleashClient.IsEnabled("pkg-autocomplete", true))
res.Add(
new Resource
{
@ -71,47 +73,55 @@ namespace isnd.Services
Type = "SearchQueryService/" + BASE_API_LEVEL,
Comment = "Search Query service"
});
if (unleashClient.IsEnabled("pkg-catalog", false))
if (unleashClient.IsEnabled("pkg-catalog", true))
res.Add(
new Resource
{
Id = extUrl + ApiConfig.Catalog,
Type = "Catalog/"+ BASE_API_LEVEL,
Type = "Catalog/" + BASE_API_LEVEL,
Comment = "Package Catalog Index"
});
if (unleashClient.IsEnabled("pkg-registration", false))
res.Add(
/* FIXME */
res.Add(
new Resource
{
Id = extUrl + ApiConfig.Registration,
Type = "Catalog/" + BASE_API_LEVEL,
Id = extUrl + "v" + BASE_API_LEVEL + "/" + ApiConfig.Registration,
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."
});
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;
}
public PackageIndexViewModel SearchByName(string query,
int skip, int take, bool prerelease = false,
string packageType = null)
{
var scope = dbContext.Packages
.Include(p => p.Versions)
.Where(
p => (PackageIdHelpers.CamelCaseMatch(p.Id, query) || PackageIdHelpers.SeparatedByMinusMatch(p.Id, query))
&& (prerelease || p.Versions.Any(v => !v.IsPrerelease))
&& (packageType == null || p.Versions.Any(v => v.Type == packageType))
);
var total = scope.Count();
var pkgs = scope.Skip(skip).Take(take).ToArray();
return new PackageIndexViewModel
{
Query = query,
TotalHits = total,
Data = pkgs
};
}
public AutoCompleteResult AutoComplete(string id,
int skip, int take, bool prerelease = false,
string packageType = null)
@ -146,17 +156,20 @@ namespace isnd.Services
&& (packageType == null || v.Type == packageType)
&& (parsedVersion.CompareTo(new SemanticVersion(v.Major, v.Minor, v.Patch)) < 0)
)
.OrderBy(v => v.FullString)
.OrderBy(v => v.NugetVersion)
.Select(v => v.FullString)
.Skip(skip).Take(take).ToArray();
}
public static CatalogIndex CurrentCatalogIndex { get; protected set; }
public static List<Page> CurrentCatalogPages { get; protected set; }
public static RegistrationPageIndex CurrentCatalogIndex { get; protected set; }
public static List<RegistrationPage> CurrentCatalogPages { get; protected set; }
public string CatalogBaseUrl => extUrl;
private IsndSettings isndSettings;
private string extUrl;
public virtual CatalogIndex GetCatalogIndex()
public virtual RegistrationPageIndex GetCatalogIndex()
{
if (CurrentCatalogIndex == null)
{
@ -170,36 +183,29 @@ namespace isnd.Services
int p = 0;
var oldIndex = CurrentCatalogIndex;
var oldPages = CurrentCatalogPages;
string baseid= extUrl + ApiConfig.Catalog;
string basepageid= extUrl + ApiConfig.CatalogPage;
CurrentCatalogIndex = new CatalogIndex
{
Id = baseid,
Items = new List<PageRef>()
};
CurrentCatalogPages = new List<Page>();
string baseid = extUrl + ApiConfig.Catalog;
string bidreg = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
string basepageid = extUrl + ApiConfig.CatalogPage;
CurrentCatalogIndex = new RegistrationPageIndex(baseid,"index");
CurrentCatalogPages = new List<RegistrationPage>();
var scope = dbContext.Commits.OrderBy(c => c.TimeStamp);
PageRef pageRef = null;
Page page = null;
RegistrationPage page = null;
i = isndSettings.CatalogPageLen;
foreach (var commit in scope)
{
if (i >= this.isndSettings.CatalogPageLen)
{
page = new Page
page = new RegistrationPage(basepageid, extUrl)
{
Id = basepageid + "-" + p++,
Parent = baseid,
CommitId = commit.CommitId,
CommitTimeStamp = commit.CommitTimeStamp,
Items = new List<PackageRef>()
CommitTimeStamp = commit.CommitTimeStamp
};
CurrentCatalogPages.Add(page);
pageRef = new PageRef
var pageRef = new RegistrationPage(page.Id, extUrl)
{
Id = page.Id,
CommitId = commit.CommitId,
CommitTimeStamp = commit.CommitTimeStamp
};
@ -207,37 +213,32 @@ namespace isnd.Services
i = 0;
}
var validPkgs = dbContext.Packages
.Include(po => po.Owner)
.Include(pkg => pkg.Versions)
.Include(pkg => pkg.LatestVersion)
.Where(
pkg => pkg.Versions.Count(v => v.CommitId == commit.CommitId) > 0
);
).GroupBy((q) => q.Id);
// pkg.Versions.OrderByDescending(vi => vi.CommitNId).First().FullString
foreach (var pkg in validPkgs)
foreach (var pkgid in validPkgs)
{
var v = pkg.Versions.
Where (cv => cv.CommitId == commit.CommitId)
.OrderByDescending(vc => vc.CommitNId).First();
StringBuilder refid = new StringBuilder(extUrl);
refid.AppendFormat("{0}/{1}/{2}",ApiConfig.CatalogLeaf, v.PackageId
, v.FullString);
if (v.Type!=null)
refid.AppendFormat("/{0}",v.Type);
var pkgref = new PackageRef
{
Version = v.FullString,
LastCommit = v.LatestCommit,
CommitId = v.LatestCommit.CommitId,
CommitTimeStamp = v.LatestCommit.CommitTimeStamp,
RefId = refid.ToString(),
Id = v.PackageId,
RefType = v.LatestCommit.Action == PackageAction.PublishPackage
? "nuget:PackageDetails" :
"nuget:PackageDelete"
};
page.Items.Add(pkgref);
StringBuilder refid = new StringBuilder(bidreg);
refid.AppendFormat("{0}/",
pkgid.Key);
/* var pkgref = new PackageRef
{
Version = v.FullString,
LastCommit = v.LatestCommit,
CommitId = v.LatestCommit.CommitId,
CommitTimeStamp = v.LatestCommit.CommitTimeStamp,
RefId = refid.ToString(),
Id = v.PackageId,
RefType = v.LatestCommit.Action == PackageAction.PublishPackage
? "nuget:PackageDetails" :
"nuget:PackageDelete"
}; */
foreach (var pkgv in pkgid)
page.AddVersionRange(pkgv.Versions);
}
reason = commit;
i++;
@ -256,8 +257,9 @@ namespace isnd.Services
public async Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type)
{
// TODO package deletion on disk
var commit = new Commit{
// TODO deletion on disk
var commit = new Commit
{
Action = PackageAction.DeletePackage,
TimeStamp = DateTime.Now
};
@ -269,12 +271,12 @@ namespace isnd.Services
);
if (pkg == null)
{
return new PackageDeletionReport{ Deleted = false };
return new PackageDeletionReport { Deleted = false };
}
dbContext.PackageVersions.Remove(pkg);
await dbContext.SaveChangesAsync();
Û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)
@ -285,5 +287,63 @@ namespace isnd.Services
v.Type == type
);
}
public IEnumerable<PackageVersion> GetCatalogLeaf(string pkgId, string semver, string pkgType)
{
return dbContext.PackageVersions
.Include(v => v.Package)
.Include(v => v.LatestCommit)
.Where(v => v.PackageId == pkgId
&& (semver == null ||
semver.StartsWith(v.SementicVersionString))
&& (pkgType == null || pkgType == v.Type));
}
public async Task<PackageDeletionReport> UserAskForPackageDeletionAsync(string uid, string id, string lower, string type)
{
PackageVersion packageVersion = await dbContext.PackageVersions
.Include(pv => pv.Package)
.FirstOrDefaultAsync(m => m.PackageId == id
&& m.FullString == lower && m.Type == type);
if (packageVersion == null) return null;
if (packageVersion.Package.OwnerId != uid) return null;
return new PackageDeletionReport { Deleted = true, DeletedVersion = packageVersion };
}
public IEnumerable<Data.Catalog.RegistrationLeaf> SearchById(string pkgId, string semver, string pkgType)
{
string bid = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
return dbContext.PackageVersions
.Include(v => v.Package)
.Include(v => v.Package.Owner)
.Include(v => v.LatestCommit)
.Where(v => v.PackageId == pkgId && semver.Equals(v.FullString, StringComparison.OrdinalIgnoreCase)
&& (pkgType == null || pkgType == v.Type))
.OrderByDescending(p=> p.CommitId)
.Select(p => p.Package.ToLeave(bid))
;
}
public PackageVersion GetPackage(string pkgId, string semver, string pkgType)
{
return dbContext.PackageVersions
.Include(v => v.Package)
.Include(v => v.LatestCommit)
.Single(v => v.PackageId == pkgId && semver == v.FullString
&& (pkgType == null || pkgType == v.Type));
}
public RegistrationPageIndex GetPackageRegistrationIndex(RegistrationPageIndexQuery query)
{
// RegistrationPageIndexAndQuery
var scope = dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
.Where(p => (PackageIdHelpers.CamelCaseMatch(p.Id, query.Query)
|| PackageIdHelpers.SeparatedByMinusMatch(p.Id, query.Query))
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease)));
var total = scope.Count();
var pkgs = scope.Skip(query.Skip).Take(query.Take).ToArray();
string bid = $"{extUrl}v3.4.0/{ApiConfig.Registration}";
return
new RegistrationPageIndex(bid, query.Query, extUrl, pkgs);
}
}
}

View File

@ -22,13 +22,14 @@ namespace isnd
{
public class Startup
{
public static string ExternalAddress { get; internal set; }
public Startup(IConfiguration config)
{
Configuration = config;
}
public IConfiguration Configuration { get; }
public static IConfiguration Configuration { get; private set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
@ -81,25 +82,19 @@ namespace isnd
throw new System.Exception("No unleash client ClientApiKey");
return s.GetRequiredService<Microsoft.AspNetCore.Hosting.IHostingEnvironment>().CreateUnleahClient(config.Value);
});
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:5001";
options.Authority = ExternalAddress;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
}
public static IUnleash UnleashClient { get; private set; }
public static string ExternalAddress { get; internal set; }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
Microsoft.AspNetCore.Hosting.IHostingEnvironment env,
@ -117,7 +112,7 @@ namespace isnd
dbContext.Database.Migrate();
}
app.UseHttpsRedirection();
// app.UseHttpsRedirection();
app.UseStatusCodePages().UseStaticFiles().UseAuthentication().UseMvc(routes =>
{
routes.MapRoute(

View File

@ -0,0 +1,38 @@
using System;
using Newtonsoft.Json;
namespace isnd.ViewModels
{
public class CatalogRegistration
{
[JsonProperty("@id")]
public string Id { get; set; }
/*
"@id": "https://api.nuget.org/v3/registration3/nuget.versioning/4.3.0.json",
"catalogEntry": "https://api.nuget.org/v3/catalog0/data/2017.08.11.18.24.22/nuget.versioning.4.3.0.json",
"listed": true,
"packageContent": "https://api.nuget.org/v3-flatcontainer/nuget.versioning/4.3.0/nuget.versioning.4.3.0.nupkg",
"published": "2017-08-11T18:24:14.36+00:00",
"registration": "https://api.nuget.org/v3/registration3/nuget.versioning/index.json"
*/
[JsonProperty("catalogEntry")]
public string CatalogEntry { get; set; }
[JsonProperty("listed")]
public bool Listed { get; set; } = true;
[JsonProperty("packageContent")]
public string PackageContent { get; set; }
[JsonProperty("published")]
public DateTime CommitTimeStamp { get; set; }
[JsonProperty("registration")]
public string registration { get; set; }
}
}

View File

@ -1,20 +0,0 @@
using isnd.Data;
using Newtonsoft.Json;
namespace isnd.ViewModels
{
public class PackageIndexViewModel
{
[JsonProperty("prerelease")]
public bool Prerelease { get; set; }
[JsonProperty("data")]
public Package[] Data {get; set;}
[JsonProperty("query")]
public string Query { get; set; }
[JsonProperty("totalHits")]
public int TotalHits { get; internal set; }
}
}

View File

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

View File

@ -4,9 +4,6 @@
}
<div class="text-center">
<h1 class="display-4">Bienvenue</h1>
<h1>
<img src="~/icon.png" >
Bienvenue dans isnd
</h1>
<h1>Bienvenue dans isn</h1>
<strong>@Model.PkgCount identifiant(s) de paquet dans le SI</strong>
</div>

View File

@ -28,7 +28,7 @@
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Versions[0].Package.Id)
@Html.DisplayNameFor(model => model.Versions[0].PackageId)
</th>
<th>
@Html.DisplayNameFor(model => model.Versions[0].FullString)
@ -43,7 +43,7 @@
@foreach (var item in Model.Versions) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Package.Id)
@Html.DisplayFor(modelItem => item.PackageId)
<a href="@item.NugetLink">
nuget
</a>

View File

@ -38,7 +38,8 @@
<pre><code id="code" >&lt;PackageReference Include="@Model.pkgid" Version="@Model.latest.FullString" /&gt;</code></pre>
</div>
<div>
@Html.ActionLink("Edit", "Edit", new { pkgid = Model.pkgid, version = Model.latest.FullString }) |
@Html.ActionLink("Edit", "Edit", new { pkgid = Model.pkgid, version = Model.latest.FullString }) |
@Html.ActionLink("Delete", "Delete", new { pkgid = Model.pkgid, version= Model.latest.FullString }) |
<a asp-action="Index">Back to List</a>
</div>
</div>

View File

@ -1,4 +1,4 @@
@model PackageIndexViewModel
@model isnd.RegistrationPageIndexQueryAndResult
@{
ViewData["Title"] = "Index";
@ -11,9 +11,9 @@
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Query" class="control-label"></label>
<input asp-for="Query" class="form-control" />
<label asp-for="TotalHits" class="control-label"></label>
<label asp-for="Query.Query" class="control-label"></label>
<input asp-for="Query.Query" class="form-control" />
<label asp-for="Query.TotalHits" class="control-label"></label>
</div>
<div class="form-group">
<input type="submit" value="Find" class="btn btn-default" />
@ -25,29 +25,29 @@
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Data[0].Id)
@Html.DisplayNameFor(model => model.Result.Items[0].Id)
</th>
<th>
@Html.DisplayNameFor(model => model.Data[0].Description)
@Html.DisplayNameFor(model => model.Result.Items[0].CommitId)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Data) {
@foreach (var page in Model.Result.Items) {
@foreach (var item in page.Items) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Id)
</td>
<td>
@Html.DisplayFor(modelItem => item.Description)
@Html.DisplayFor(modelItem => item.Entry.Description)
</td>
<td>
@Html.ActionLink("Details", "Details", new { pkgid = item.Id }) |
@Html.ActionLink("Delete", "Delete", new { pkgid = item.Id })
@Html.ActionLink("Details", "Details", new { pkgid = item.Id })
</td>
</tr>
}
}}
</tbody>
</table>

View File

@ -3,15 +3,16 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - isnd</title>
<title>@ViewData["Title"] - isn</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="~/css/site.css" />
<link rel="shortcut icon" href="favicon.ico#1" >
</head>
<body>
<header>
<nav class="navbar navbar-dark bg-dark navbar-expand-sm" >
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">isnd</a>
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index"><img src="~/icon.png" alt="isn"></a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
@ -24,10 +25,15 @@
<a class="nav-link" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0" asp-action="Index" asp-controller="Packages">
<input name="Query" id="Query" class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
<div class="navbar-nav mr-auto">
<div class="navbar-item">
<form class="form-inline my-2 my-lg-0" asp-action="Index" asp-controller="Packages">
<input style="margin:.3em;" name="Query" id="Query" class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<input style="margin:.3em;" name="IsPrerelease" id="IsPrerelease" class="form-control mr-sm-2" type="checkbox" checked><label for="IsPrerelease"> <i>Pre-release </i></Label>
<button style="margin:.3em;" class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</div>
<partial name="_LoginPartial" />
</div>
</div>

View File

@ -1,4 +1,5 @@
@using isnd.Data
@using isnd.ViewModels
@using isnd.Helpers
@using isnd.Data.Catalog;
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

View File

@ -1,39 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<UserSecretsId>85fd766d-5d23-4476-aed1-463b2942e86a</UserSecretsId>
<PackageVersion>1.0.1</PackageVersion>
<Version>0.1.175</Version>
<IsPackable>true</IsPackable>
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
<NoWarn>NETSDK1138</NoWarn>
<AssemblyVersion>0.1.175.0</AssemblyVersion>
<FileVersion>0.1.175.0</FileVersion>
<InformationalVersion>0.1.175+Branch.main.Sha.3e09afcbfe0eff74c0b3aa0fb974e0801f4708b6</InformationalVersion>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<InformationalVersion>1.0.5+Branch.main.Sha.14206ac477d0f07566d5e8125dc52cbd7f474ca2</InformationalVersion>
<Version>1.0.5</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.6" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="2.1.2" />
<PackageReference Include="Microsoft.AspNetCore.All" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="NuGet.Packaging.Core" Version="5.9.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.1" />
<PackageReference Include="MailKit" Version="2.11.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.1.1" IncludeAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" IncludeAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" IncludeAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.1" />
<PackageReference Include="NuGet.Packaging.Core" Version="5.6.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.30" />
<PackageReference Include="MailKit" Version="2.8.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.1.2" IncludeAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.2" IncludeAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.3" IncludeAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.2" />
<PackageReference Include="unleash.client" Version="1.6.1" />
<PackageReference Include="GitVersion.MsBuild" Version="5.6.10*">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="4.6.0" />
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../isn.abst/isn.abst.csproj" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.1" />
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.2" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.1.0-preview1-final" />
</ItemGroup>
<ItemGroup>

View File

@ -7843,7 +7843,11 @@ a.text-dark:hover, a.text-dark:focus {
border: 1px solid #333;
box-shadow: 8px 8px 5px #444;
padding: 8px 12px;
background-image: linear-gradient(180deg, #fff, #ddd 40%, #ccc); }
background-image: linear-gradient(180deg, #fff, #ddd 40%, #ccc);
margin: 1em; }
.fa-copy {
cursor: copy; }
.border-top.footer.text-muted {
padding: 1em; }

View File

@ -105,8 +105,14 @@ background-color: black;
box-shadow: 8px 8px 5px #444;
padding: 8px 12px;
background-image: linear-gradient(180deg, #fff, #ddd 40%, #ccc);
margin: 1em;
}
.fa-copy {
cursor: copy;
}
}
.border-top.footer.text-muted {
padding: 1em;
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<apikeys>
</apikeys>
<packageSources>
<add key="isn-dev" value="http://localhost:5000/index.json" protocolVersion="3" />
</packageSources>
</configuration>

View File

@ -0,0 +1,2 @@
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

4
test/data/test-isn/isn-test.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
nuget locals all -clear && dotnet nuget locals all --clear && nuget add Yavsc.Abstract -Config NuGet.Config -Source isn-dev

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>test_isn</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<InformationalVersion>1.0.5+Branch.main.Sha.14206ac477d0f07566d5e8125dc52cbd7f474ca2</InformationalVersion>
<Version>1.0.5</Version>
</PropertyGroup>
</Project>

View File

@ -0,0 +1 @@
nuget install -NoCache -Verbosity detailed -ConfigFile NuGet.Config Yavsc.Abstract

View File

@ -9,6 +9,8 @@ using Newtonsoft.Json;
using isn.Abstract;
using System.Linq;
using Xunit;
using isn.abst;
using isnd.Entities;
namespace isn.tests
{
@ -25,52 +27,53 @@ namespace isn.tests
string unprotectedpass = _protector.UnProtect(protectedpass);
Console.WriteLine(protectedpass);
Assert.Equal(pass, unprotectedpass);
Assert.True(protectedpass!=null);
Assert.True(protectedpass.Length>0);
Assert.True(protectedpass != null);
Assert.True(protectedpass.Length > 0);
}
[Fact]
public void Test()
{
System.Data.DataTable dataTable = new System.Data.DataTable();
dataTable.Columns.Add(new DataColumn("x"));
dataTable.Columns.Add(new DataColumn("y"));
dataRow = dataTable.NewRow();
dataRow[0]= 1;
dataRow[1]= 2;
dataTable.Columns.Add(new DataColumn("x"));
dataTable.Columns.Add(new DataColumn("y"));
dataRow = dataTable.NewRow();
dataRow[0] = 1;
dataRow[1] = 2;
dataTable.Rows.Add(dataRow);
dataTable.Rows.Add(dataRow);
}
[Fact]
public async Task TestHttpClient()
{
string url = "http://isn.pschneider.fr/index.json";
string url = "http://isn.pschneider.fr/" + ApiConfig.IndexDotJson;
HttpClient client = new HttpClient();
// var json = await client.GetStringAsync(new System.Uri(url));
var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
var vm = JsonConvert.DeserializeObject<ApiIndexViewModel>(json);
Console.WriteLine( JsonConvert.SerializeObject(vm));
Console.WriteLine(JsonConvert.SerializeObject(vm));
Assert.NotNull(vm);
Assert.NotNull(vm.Resources);
}
[Fact]
[Fact]
public void TestPush()
{
Program.LoadConfig();
var report = Program.PushPkg(new string[] { "/home/paul/Nupkgs/Yavsc.Abstract.1.0.8.nupkg" });
Program.LoadConfig();
var report = Program.PushPkg(new string[] { "/home/paul/Nupkgs/Yavsc.Abstract.1.0.8."
+ Constants.PaquetFileEstension });
}
[Fact]
[Fact]
public async Task GetServerResourcesUsingHttpClientAsyncTest()
{
var model = SourceHelpers.GetServerResources("Http://isn.pschneider.fr/index.json");
Console.WriteLine(JsonConvert.SerializeObject(model));
Assert.NotNull(model.Resources);
var pub = model.Resources.FirstOrDefault((r) => r.Type.StartsWith("PackagePublish/"));
Assert.True(pub!=null);
Assert.True(pub != null);
}
}

View File

@ -3,10 +3,10 @@
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<IsPackable>false</IsPackable>
<NoWarn>NETSDK1138</NoWarn>
<AssemblyVersion>0.1.175.0</AssemblyVersion>
<FileVersion>0.1.175.0</FileVersion>
<InformationalVersion>0.1.175+Branch.main.Sha.3e09afcbfe0eff74c0b3aa0fb974e0801f4708b6</InformationalVersion>
<Version>0.1.175</Version>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<InformationalVersion>1.0.5+Branch.main.Sha.14206ac477d0f07566d5e8125dc52cbd7f474ca2</InformationalVersion>
<Version>1.0.5</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />

View File

@ -1,33 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<IsPackable>false</IsPackable>
<UserSecretsId>d7144e46-4e63-4391-ba86-64b61f6e7be4</UserSecretsId>
<NoWarn>NETSDK1138</NoWarn>
<AssemblyVersion>0.1.175.0</AssemblyVersion>
<FileVersion>0.1.175.0</FileVersion>
<InformationalVersion>0.1.175+Branch.main.Sha.3e09afcbfe0eff74c0b3aa0fb974e0801f4708b6</InformationalVersion>
<Version>0.1.175</Version>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<InformationalVersion>1.0.5+Branch.main.Sha.14206ac477d0f07566d5e8125dc52cbd7f474ca2</InformationalVersion>
<Version>1.0.5</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="XunitXml.TestLogger" Version="3.0.70"/>
<PackageReference Include="XunitXml.TestLogger" Version="3.0.70" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
<PackageReference Include="xunit.runner.reporters" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageToolReference Include="xunit.runner.console" Version="2.4.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\isnd\isnd.csproj" />
<ProjectReference Include="..\..\src\isn\isn.csproj" />
</ItemGroup>
<ItemGroup>
<MyTestingConfigFiles Include="appsettings.Testing.json" />
</ItemGroup>
<!--
<Target Name="CopyTestConfig" AfterTargets="Build">
<Copy SourceFiles="@(MyTestingConfigFiles)" DestinationFolder="$(OutputPath)" />
</Target>-->
</Project>