This commit is contained in:
2022-04-09 19:53:26 +01:00
parent df55836c58
commit 1befc2e053
38 changed files with 427 additions and 309 deletions

View File

@ -0,0 +1,13 @@
using Newtonsoft.Json;
namespace isn.Abstract
{
public class ApiIndexViewModel
{
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("resources")]
public Resource[] Resources { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace isn.abst
{
public static class Constants
{
public const string PublishCommandId = "PackagePublish/2.0.0";
}
}

View File

@ -1,17 +1,17 @@
using Newtonsoft.Json;
namespace isnd.Controllers
{
public class Resource
{
[JsonProperty("@id")]
public string Id {get; set; }
[JsonProperty("@type")]
public string Type {get; set; }
[JsonProperty("comment")]
public string Comment {get; set; }
}
using Newtonsoft.Json;
namespace isn.Abstract
{
public class Resource
{
[JsonProperty("@id")]
public string Id {get; set; }
[JsonProperty("@type")]
public string Type {get; set; }
[JsonProperty("comment")]
public string Comment {get; set; }
}
}

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net4.7.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.1"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
namespace isn
{
public class IsnSourceSettings
{
internal string Source { get; set; }
internal string[] Keys { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace isn
{
public class IsndErrorMessage
{
public int ecode { get; set; }
public string msg { get; set; }
}
}

View File

@ -1,126 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Mono.Options;
using Newtonsoft.Json;
namespace isn
{
partial class Program
{
private static void SourceList(IEnumerable<string> sargs)
{
throw new NotImplementedException();
}
private static object SourceAdd(IEnumerable<string> str)
{
throw new NotImplementedException();
}
private static object Add(IEnumerable<string> str)
{
throw new NotImplementedException();
}
private static async Task<List<PushReport>> PushPkgAsync(IEnumerable<string> pkgs)
{
List<PushReport> pushReports = new List<PushReport>();
foreach (string pkg in pkgs)
{
var report = await PushCommand.RunAsync(pkg, source, apiKey);
pushReports.Add(report);
}
if (storApiKey)
{
EnsureKeyStored();
}
return pushReports;
}
static OptionSet storeoptions = new OptionSet {
{ "s|source=", "use source", val => source = source ?? val },
{ "h|help", "show this message and exit", h => shouldShowPushHelp = h != null },
};
private static string _configFileName =
Path.Combine(
Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile), ".isn"),
"config.json")
;
public class IsnSourceSettings
{
internal string Source { get; set; }
internal string[] Keys { get; set; }
}
public static IEnumerable<IsnSourceSettings> Sources { get; protected set; }
private static void StoreApiKey(IEnumerable<string> storeArgs)
{
var args = storeoptions.Parse(storeArgs);
if (shouldShowPushHelp)
{
// output the options
Console.Error.WriteLine("Push Options:");
storeoptions.WriteOptionDescriptions(Console.Out);
}
else
{
apiKey = args[0];
EnsureKeyStored();
}
}
public static void EnsureKeyStored()
{
if (source == null) return;
if (Settings.Sources.ContainsKey(source))
{
if (apiKey == null)
{
// Une suppression
Settings.Sources.Remove(source);
if (Settings.DefaultSource == source) Settings.DefaultSource = null;
}
else
{
// Une mise À jour
string ptd = Protector.Protect(apiKey);
Settings.Sources[source].ApiKey = ptd;
if (Settings.DefaultSource == null) Settings.DefaultSource = source;
}
}
else if (apiKey != null)
{
// une addition
string ptd = Protector.Protect(apiKey);
Settings.Sources.Add(source, new SourceSettings { ApiKey = ptd });
}
else return;
FileInfo cfgSettingIf = new FileInfo(_configFileName);
if (!cfgSettingIf.Directory.Exists) cfgSettingIf.Directory.Create();
File.WriteAllText(
cfgSettingIf.FullName,
JsonConvert.SerializeObject(
Settings,
Formatting.Indented
));
}
public static void LoadConfig()
{
FileInfo cfgSettingIf = new FileInfo(_configFileName);
if (cfgSettingIf.Exists)
{
var json = File.ReadAllText(cfgSettingIf.FullName);
settings = JsonConvert.DeserializeObject<Settings>(json);
}
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Mono.Options;
using Newtonsoft.Json;
@ -8,6 +9,29 @@ namespace isn
{
partial class Program
{
public static IEnumerable<IsnSourceSettings> Sources { get; protected set; }
public static void LoadConfig()
{
FileInfo cfgSettingIf = new FileInfo(_configFileName);
if (cfgSettingIf.Exists)
{
var json = File.ReadAllText(cfgSettingIf.FullName);
settings = JsonConvert.DeserializeObject<Settings>(json);
}
}
static OptionSet storeoptions = new OptionSet {
{ "s|source=", "use source", val => source = source ?? val },
{ "h|help", "show this message and exit", h => shouldShowPushHelp = h != null },
};
private static string _configFileName =
Path.Combine(
Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile), ".isn"),
"config.json")
;
public const string push = "push";
static OptionSet options = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowHelp = h != null },
@ -23,6 +47,9 @@ namespace isn
{ "h|help", "show this message and exit", h => shouldShowSourceHelp = h != null },
};
static OptionSet showOptions = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowSourceHelp = h != null },
};
private static bool shouldShowHelp;
private static bool shouldShowSourceHelp;
@ -59,10 +86,37 @@ namespace isn
{
Run = sargs => SourceList(sargs)
};
var showconfig = new Command("config")
{
Run = sargs => ShowConfig()
};
var srcadd = new Command("add")
{
Run = sargs => SourceAdd(sargs)
};
var showCommand = new Command("show")
{
Run = sargs =>
{
var showCommandSet = new CommandSet("show")
{
showconfig
};
var pargs = showOptions.Parse(sargs);
if (shouldShowSourceHelp)
{
// output the options
Console.WriteLine("Sources Options:");
showOptions.WriteOptionDescriptions(Console.Out);
return;
}
showCommandSet.Run(pargs);
}
};
var srcCmd = new Command("sources")
{
Run = sargs =>
@ -73,6 +127,8 @@ namespace isn
srclst,
srcadd
};
var pargs = sourceoptions.Parse(sargs);
if (shouldShowSourceHelp)
{
@ -116,6 +172,7 @@ namespace isn
};
commandSet.Add(setapikey);
commandSet.Add(srcCmd);
commandSet.Add(showCommand);
List<string> extra;
try

View File

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
@ -28,10 +29,16 @@ namespace isn
if (source == null)
{
source = Program.Settings.DefaultSource;
apikey = Program.Settings.Sources[source].ApiKey;
if (apikey is null) if (source!=null)
apikey = Program.Protector.UnProtect(Program.Settings.Sources[source].ApiKey);
}
if (apikey is null) if (source!=null)
if (Program.Settings.Sources.ContainsKey(source))
if (apikey is null) apikey = Program.Protector.UnProtect(Program.Settings.Sources[source].ApiKey);
apikey = Program.Protector.UnProtect(Program.Settings.Sources[source].ApiKey);
if (source == null) throw new InvalidOperationException("source is null");
var resources = await SourceHelpers.GetServerResourcesAsync(source);
if (resources.Resources==null || resources.Resources.Any(res => res.Id == "" ))
throw new InvalidOperationException("Source won't serve the expected push command");
wrqueryHandler.UploadFilesToServer(report, new Uri(source), fi, apikey);
}
catch (WebException ex)
@ -43,7 +50,7 @@ namespace isn
{
StreamReader sr = new StreamReader(respStream);
string json = sr.ReadToEnd();
var res = JsonConvert.DeserializeObject<NugetdErrorMessage>(json);
var res = JsonConvert.DeserializeObject<IsndErrorMessage>(json);
// ecode == 1 => package already present server side.
report.AlreadyPresent = res.ecode == 1;
report.Message = res.msg;

21
src/isn/SourceHelpers.cs Normal file
View File

@ -0,0 +1,21 @@
using System.Net.Http;
using System.Threading.Tasks;
using isn.Abstract;
using Newtonsoft.Json;
namespace isn
{
public static class SourceHelpers
{
public static async Task<ApiIndexViewModel> GetServerResourcesAsync(string url)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("content-type","application/json; utf-8");
using (var indexResponse = await client.GetAsync(url))
{
var json = await indexResponse.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<ApiIndexViewModel>(json);
}
}
}
}

View File

@ -7,12 +7,7 @@ using Newtonsoft.Json;
namespace isn
{
public class NugetdErrorMessage
{
public string versionId { get; set; }
public int ecode { get; set; }
public string msg { get; set; }
}
public class UploadFilesToServerUsingWebRequest
{
internal void UploadFilesToServer(PushReport report, Uri uri, FileInfo fi,

35
src/isn/commands/push.cs Normal file
View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace isn
{
partial class Program
{
private static async Task<List<PushReport>> PushPkgAsync(IEnumerable<string> pkgs)
{
List<PushReport> pushReports = new List<PushReport>();
foreach (string pkg in pkgs)
{
var report = await PushCommand.RunAsync(pkg, source, apiKey);
pushReports.Add(report);
}
if (storApiKey)
{
EnsureKeyStored();
}
return pushReports;
}
private static object Add(IEnumerable<string> str)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace isn
{
partial class Program
{
private static void StoreApiKey(IEnumerable<string> storeArgs)
{
var args = storeoptions.Parse(storeArgs);
if (shouldShowPushHelp)
{
// output the options
Console.Error.WriteLine("Push Options:");
storeoptions.WriteOptionDescriptions(Console.Out);
}
else
{
apiKey = args[0];
EnsureKeyStored();
}
}
public static void EnsureKeyStored()
{
if (source == null) return;
if (Settings.Sources.ContainsKey(source))
{
if (apiKey == null)
{
// Une suppression
Settings.Sources.Remove(source);
if (Settings.DefaultSource == source) Settings.DefaultSource = null;
}
else
{
// Une mise À jour
string ptd = Protector.Protect(apiKey);
Settings.Sources[source].ApiKey = ptd;
if (Settings.DefaultSource == null) Settings.DefaultSource = source;
}
}
else if (apiKey != null)
{
// une addition
string ptd = Protector.Protect(apiKey);
Settings.Sources.Add(source, new SourceSettings { ApiKey = ptd });
}
else return;
FileInfo cfgSettingIf = new FileInfo(_configFileName);
if (!cfgSettingIf.Directory.Exists) cfgSettingIf.Directory.Create();
File.WriteAllText(
cfgSettingIf.FullName,
JsonConvert.SerializeObject(
Settings,
Formatting.Indented
));
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace isn
{
partial class Program
{
private static void ShowConfig()
{
Console.WriteLine(JsonConvert.SerializeObject(Settings));
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace isn
{
partial class Program
{
private static void SourceAdd(IEnumerable<string> str)
{
foreach (string arg in str)
{
if (Settings.Sources.ContainsKey(arg))
{
SourceSettings setting = Settings.Sources[arg];
throw new InvalidOperationException
(setting.Alias);
}
throw new NotImplementedException();
}
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
namespace isn
{
partial class Program
{
private static void SourceList(IEnumerable<string> sargs)
{
IEnumerable<string> spec = sargs.Count()>0 ? sargs : Settings.Sources.Keys;
foreach (string arg in spec)
{
SourceSettings setting = Settings.Sources[arg];
Console.WriteLine(JsonConvert.SerializeObject(setting));
}
}
}
}

Binary file not shown.

View File

@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
<TargetFramework>net6</TargetFramework>
<RootNamespace>nuget_cli</RootNamespace>
<UserSecretsId>45b74c62-05bc-4603-95b4-3e80ae2fdf50</UserSecretsId>
<PackageVersion>1.0.1</PackageVersion>
@ -9,10 +10,16 @@
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
<IsTool>true</IsTool>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Mono.Options" Version="5.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.1"/>
<PackageReference Include="unleash.client" Version="1.6.1" />
<Reference Include="System.Net.Http" Version="4.0.0"/>
</ItemGroup>
<PackageReference Include="Mono.Options" Version="5.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
<PackageReference Include="unleash.client" Version="1.6.1" />
<Reference Include="System.Net.Http" Version="4.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../isn.abst/isn.abst.csproj" />
</ItemGroup>
</Project>

View File

@ -1,6 +1,6 @@
namespace isnd
{
public static class Constants
public static class IsndConstants
{
public const string AdministratorRoleName = "Admin";
public const string RequireAdminPolicyName = "RequireAdministratorRole";

View File

@ -245,9 +245,9 @@ namespace isnd.Controllers
{
var user = await _userManager.FindByNameAsync(username);
var roles = await _userManager.GetRolesAsync(user);
if (!roles.Contains(Constants.AdministratorRoleName))
if (!roles.Contains(IsndConstants.AdministratorRoleName))
{
await _userManager.AddToRoleAsync(user, Constants.AdministratorRoleName);
await _userManager.AddToRoleAsync(user, IsndConstants.AdministratorRoleName);
}
return Ok();

View File

@ -9,7 +9,7 @@ namespace isnd.Controllers
// TODO Web hook CI
public class NewUpdateController : Controller
{
[Authorize(Policy = Constants.RequireAdminPolicyName)]
[Authorize(Policy = IsndConstants.RequireAdminPolicyName)]
public IActionResult NewRelease(NewReleaseInfo version)
{
throw new NotImplementedException("web hook");

View File

@ -15,6 +15,7 @@ using isnd.Services;
using isnd.ViewModels;
using System.Threading.Tasks;
using isnd.Interfaces;
using isn.Abstract;
namespace isnd.Controllers
{
@ -54,7 +55,7 @@ namespace isnd.Controllers
[HttpGet(_pkgRootPrefix + ApiConfig.Base)]
public IActionResult ApiIndex()
{
return Ok(new { version = "3.0.0", resources = _resources });
return Ok(new ApiIndexViewModel{ Version = "3.0.0", Resources = _resources });
}
// GET /autocomplete?id=isn.protocol&prerelease=true

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using isn.Abstract;
using isnd.Controllers;
using isnd.Data;
using isnd.Data.Catalog;

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using isn.abst;
using isn.Abstract;
using isnd.Controllers;
using isnd.Data;
using isnd.Data.Catalog;
@ -41,7 +43,7 @@ namespace isnd.Services
new Resource
{
Id = extUrl + ApiConfig.Publish,
Type = "PackagePublish/2.0.0",
Type = Constants.PublishCommandId,
Comment = "Package Publish service"
});
// under dev, only leash in release mode

View File

@ -58,9 +58,9 @@ namespace isnd
services.AddAuthorization(options =>
{
options.AddPolicy(Constants.RequireAdminPolicyName,
policy => policy.RequireRole(Constants.AdministratorRoleName));
options.AddPolicy(Constants.RequireValidApiKey, policy =>
options.AddPolicy(IsndConstants.RequireAdminPolicyName,
policy => policy.RequireRole(IsndConstants.AdministratorRoleName));
options.AddPolicy(IsndConstants.RequireValidApiKey, policy =>
policy.Requirements.Add(new ValidApiKeyRequirement()));
})

View File

@ -25,6 +25,10 @@
<PackageReference Include="unleash.client" Version="1.6.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../isn.abst/isn.abst.csproj" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.1" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.1.0-preview1-final" />