No release yet

This commit is contained in:
2023-04-16 23:47:55 +01:00
parent 3b7e286a5b
commit 58d1f26701
380 changed files with 69597 additions and 20486 deletions

16
src/isn.abst/ApiConfig.cs Normal file
View File

@ -0,0 +1,16 @@
using isn.abst;
namespace isnd.Entities
{
public static class ApiConfig
{
public const string Catalog = "/catalog";
public const string Package = "/package";
public const string Search = "/search";
public const string AutoComplete = "/autocomplete";
public const string Registration = "/registration";
public const string Nuspec = "/nuspec";
public const string Nuget = "/nuget";
}
}

View File

@ -0,0 +1,21 @@
using isnd.Data.Catalog;
using Newtonsoft.Json;
namespace isn.Abstract
{
public class ApiIndexViewModel : HappyIdOwner
{
public ApiIndexViewModel(string id) : base(id)
{
}
[JsonProperty("@id")]
public string Id { get => GetId(); }
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("resources")]
public Resource[] Resources { get; set; }
}
}

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 ApiVersion = "/v3";
}
}

View File

@ -0,0 +1,35 @@
using Newtonsoft.Json;
namespace isnd.Data.Catalog
{
public class HappyIdOwner
{
public HappyIdOwner(string id)
{
this.id = id;
}
private string id;
public string GetId() { return id; }
public override bool Equals(object obj)
{
if (obj!=null)
{
if (GetType().IsAssignableFrom(obj.GetType()))
{
var rpobj = (HappyIdOwner) obj;
return this.id == rpobj.id;
}
}
return base.Equals(obj);
}
public override int GetHashCode()
{
return id.GetHashCode();
}
}
}

24
src/isn.abst/Resource.cs Normal file
View File

@ -0,0 +1,24 @@
using isnd.Data.Catalog;
using Newtonsoft.Json;
namespace isn.Abstract
{
public class Resource : HappyIdOwner
{
public Resource(string id, string typename) : base(id)
{
Type = typename;
Id = id;
}
[JsonProperty("@id")]
public string Id {get; set; }
[JsonProperty("@type")]
public string Type {get; set; }
[JsonProperty("comment")]
public string Comment {get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace isnd.Attributes
{
public class SafeNameAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (!(value is string))
return false;
string str = value as string;
if (str.Length>126) return false;
if (str.Any(c => !char.IsLetterOrDigit(c)
&& !"-_.".Contains(c))) return false;
return true;
}
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageVersion>1.0.1</PackageVersion>
<Version>1.0.7</Version>
<TargetFrameworks>net7.0</TargetFrameworks>
<NoWarn>NETSDK1138</NoWarn>
<AssemblyVersion>1.0.7.0</AssemblyVersion>
<FileVersion>1.0.7.0</FileVersion>
<InformationalVersion>1.0.7+Branch.main.Sha.3695c1742965d93eba0ad851656cfaa3e44ba327</InformationalVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
</ItemGroup>
</Project>

7
src/isn/Constants.cs Normal file
View File

@ -0,0 +1,7 @@
namespace isn
{
internal static class Constants
{
internal const string ClientVersion = "isn v1.0";
}
}

47
src/isn/IDataProtector.cs Normal file
View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace isn
{
public interface IDataProtector
{
string Protect(string data);
string UnProtect(string data);
}
public class DefaultDataProtector : IDataProtector
{
private byte delta = 145;
public DefaultDataProtector()
{
}
public string Protect(string data)
{
List<Byte> protd = new List<byte>();
StringBuilder sb = new StringBuilder();
foreach (byte c in Encoding.UTF8.GetBytes(data))
{
protd.Add((byte) (c ^ delta));
}
return System.Convert.ToBase64String(protd.ToArray());
}
public string UnProtect(string data)
{
if (data==null) return null;
StringBuilder sb = new StringBuilder();
List<byte> unps = new List<byte>();
foreach (byte c in System.Convert.FromBase64CharArray(data.ToCharArray(),0,data.Length))
{
unps.Add((byte) (c ^ delta));
}
return Encoding.UTF8.GetString(unps.ToArray());
}
}
}

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; }
}
}

224
src/isn/Program.cs Normal file
View File

@ -0,0 +1,224 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Mono.Options;
using Newtonsoft.Json;
namespace isn
{
public partial class Program
{
public static void LoadConfig()
{
FileInfo cfgSettingIf = new FileInfo(_configFileName);
if (cfgSettingIf.Exists)
{
var json = File.ReadAllText(cfgSettingIf.FullName);
settings = JsonConvert.DeserializeObject<Settings>(json);
if (settings.DefaultSourceKey == null)
{
Settings.DefaultSourceKey = settings.Sources.Keys.FirstOrDefault();
}
CurrentSource = settings.DefaultSourceKey;
}
}
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 readonly string _configFileName =
Path.Combine(
Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile), ".isn"),
"config.json")
;
public const string push = "push";
static readonly OptionSet options = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowHelp = h != null },
{ "v|version", "show soft version info and exit", h => shouldShowVersion = h != null }
};
static string apiKey;
static readonly OptionSet pushoptions = new OptionSet {
{ "k|api-key=", "use api key", val => apiKey = apiKey ?? val },
{ "p|store-api-key", "store used api key", val => storApiKey = val != null },
{ "s|source=", "use source", val => CurrentSource = CurrentSource ?? val },
{ "h|help", "show this message and exit", h => shouldShowPushHelp = h != null },
};
static readonly OptionSet sourceoptions = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowSourceHelp = h != null },
};
static readonly OptionSet showOptions = new OptionSet {
{ "h|help", "show this message and exit", h => shouldShowSourceHelp = h != null },
};
private static bool shouldShowHelp;
private static bool shouldShowVersion;
private static bool shouldShowSourceHelp;
private static bool shouldShowPushHelp;
private static string currentSource = null;
private static bool storApiKey = false;
static Settings settings = null;
public static Settings Settings
{
get
{
if (settings == null)
LoadConfig();
if (settings == null)
{
settings = new Settings
{
DataProtectionTitle = "isn",
Sources = new Dictionary<string, SourceSettings>()
};
}
return settings;
}
}
public static string CurrentSource { get => currentSource; set => currentSource = value; }
static int Main(string[] args)
{
var commandSet = new CommandSet("isn");
var srclst = new Command("list")
{
Run = sargs => SourceList(sargs)
};
var showconfig = new Command("config")
{
Run = sargs => ShowConfig()
};
var srcadd = new Command("add")
{
Run = sargs => SourceAdd(sargs)
};
var srcsetdef = new Command("set-default")
{
Run = sargs => SetDefaultSource(sargs?.FirstOrDefault())
};
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 =>
{
var sourcesCmdSet = new CommandSet("sources")
{
srclst,
srcadd,
srcsetdef
};
var pargs = sourceoptions.Parse(sargs);
if (shouldShowSourceHelp)
{
// output the options
Console.WriteLine("Sources Options:");
sourceoptions.WriteOptionDescriptions(Console.Out);
return;
}
sourcesCmdSet.Run(pargs);
}
};
var add = new Command("add")
{
Run = sargs => Add(sargs)
};
commandSet.Add(add);
var pushCmd = new Command(push)
{
Run = sargs =>
{
var pargs = pushoptions.Parse(sargs);
if (args.Count()==0) shouldShowPushHelp=true;
if (shouldShowPushHelp)
{
// output the options
Console.Error.WriteLine("Push Options:");
pushoptions.WriteOptionDescriptions(Console.Out);
return;
}
List<PushReport> reports = PushPkg(pargs);
}
};
var setapikey = new Command("set-api-key")
{
Run = sargs => StoreApiKey(sargs)
};
commandSet.Add(pushCmd);
commandSet.Add(setapikey);
commandSet.Add(srcCmd);
commandSet.Add(showCommand);
List<string> extra;
try
{
// parse the command line
extra = options.Parse(args);
}
catch (OptionException e)
{
Console.Error.Write("isn: ");
Console.Error.WriteLine(e.Message);
Console.Error.WriteLine("Try `isn --help' for more information.");
return 2;
}
if (shouldShowHelp)
{
// output the options
Console.WriteLine("Options:");
options.WriteOptionDescriptions(Console.Out);
return 1;
}
if (shouldShowVersion)
{
Console.WriteLine("isn version " + GitVersionInformation.AssemblySemFileVer);
}
return commandSet.Run(args);
}
}
}

55
src/isn/Settings.cs Normal file
View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace isn
{
public class SourceSettings
{
public string ApiKey { get; set; }
public string Alias { get; set; }
public string GetClearApiKey()
{
return Protector.UnProtect(ApiKey);
}
public void SetApiKey(string key)
{
ApiKey = Protector.Protect(key);
}
public static IDataProtector Protector { get; set; } = new DefaultDataProtector();
}
public class Settings
{
public string DataProtectionTitle { get; set; }
public Dictionary<string, SourceSettings> Sources { get; set; }
public bool AutoUpdateApiKey { get; set; } = false;
private string defSourceKey;
/// <summary>
/// Default source by its alias
/// </summary>
/// <value></value>
public string DefaultSourceKey
{
get => defSourceKey;
set
{
if (!Sources.ContainsKey(value))
{
Sources[value]=new SourceSettings
{
Alias = defSourceKey
};
}
defSourceKey = value;
}
}
}
}

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

@ -0,0 +1,27 @@
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using isn.Abstract;
namespace isn
{
public static class SourceHelpers
{
public static ApiIndexViewModel GetServerResources(string url)
{
HttpClient client = new HttpClient();
ApiIndexViewModel result = null;
// var json = await client.GetStringAsync(new System.Uri(url));
Task.Run(async ()=> {
var response = await client.GetStringAsync(url);
result = JsonConvert.DeserializeObject<ApiIndexViewModel>(response);
}).Wait();
return result;
}
}
}

View File

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
namespace isn
{
public static class UploadFilesToServerUsingHttpClient
{
public static PushReport UploadFilesToServer(this HttpClient client, Uri uri, FileInfo fi,
string apikey)
{
return UploadFilesToServerAsync(client, uri, fi, apikey).Result;
}
public static async Task<PushReport> UploadFilesToServerAsync(this HttpClient client, Uri uri, FileInfo fi,
string apikey)
{
client.DefaultRequestHeaders.Add("X-NuGet-Client-Version", Constants.ClientVersion);
client.DefaultRequestHeaders.Add("X-NuGet-ApiKey", apikey);
using (var multipartFormDataContent = new MultipartFormDataContent())
{
/* var values = new[]
{
new KeyValuePair<string, string>("Id", Guid.NewGuid().ToString()),
new KeyValuePair<string, string>("Key", "awesome"),
new KeyValuePair<string, string>("From", "khalid@home.com")
//other values
};foreach (var keyValuePair in values)
{
multipartFormDataContent.Add(new StringContent(keyValuePair.Value),
String.Format("\"{0}\"", keyValuePair.Key));
} */
multipartFormDataContent.Add(new ByteArrayContent(File.ReadAllBytes(fi.FullName)),
'"' + "File" + '"',
'"' + fi.Name + '"');
var result = await client.PutAsync(uri, multipartFormDataContent);
if (result.IsSuccessStatusCode)
{
string report = await result.Content.ReadAsStringAsync();
Console.WriteLine(report);
}
else
{
string ereport = await result.Content.ReadAsStringAsync();
Console.WriteLine(ereport);
}
return new PushReport();
}
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace isn
{
public static class PushCommand
{
static public PushReport Run(string pkg, string source, string apikey)
{
if (source == null) source = Program.Settings.DefaultSourceKey;
if (source == null) throw new InvalidOperationException("source is null");
if (Program.Settings.Sources.Values.Any(s=>s.Alias==source))
source = Program.Settings.Sources.First(s=>s.Value.Alias==source).Key;
if (source==null) throw new InvalidOperationException("source is invalid");
var resources = SourceHelpers.GetServerResources(source);
if (resources.Resources == null)
throw new InvalidOperationException("source gave no resource");
if (!resources.Resources.Any(res => res.Type == "PackagePublish/2.0.0"))
throw new InvalidOperationException("Source won't serve the expected push command");
var pubRes = resources.Resources.First(res => res.Type == "PackagePublish/2.0.0");
FileInfo fi = new FileInfo(pkg);
if (!fi.Exists)
{
var report = new PushReport
{
PkgName = fi.Name,
Message = "Le fichier n'existe pas"
};
return report;
}
using (var client = new HttpClient())
try
{
Console.WriteLine("Connecting to "+ pubRes.Id);
return client.UploadFilesToServer(new Uri(pubRes.Id), fi, apikey);
}
catch (HttpRequestException hrex)
{
var report = new PushReport
{
PkgName = fi.Name,
Message = "HttpRequest: " + hrex.Message,
StackTrace = hrex.StackTrace,
StatusCode = hrex.HResult.ToString()
};
Console.Error.WriteLine(hrex.Message);
return report;
}
catch (Exception ex)
{
var report = new PushReport
{
PkgName = fi.Name,
Message = ex.Message,
StackTrace = ex.StackTrace
};
Console.Error.WriteLine(ex.Message);
return report;
}
}
}
}

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
{
public static List<PushReport> PushPkg(IEnumerable<string> pkgs)
{
List<PushReport> pushReports = new List<PushReport>();
foreach (string pkg in pkgs)
{
var report = PushCommand.Run(pkg, CurrentSource, apiKey);
Console.WriteLine(report.ToDoc());
pushReports.Add(report);
}
if (storApiKey)
{
EnsureKeyStored();
}
return pushReports;
}
private static object Add(IEnumerable<string> str)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,75 @@
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 (CurrentSource == null)
{
if (Settings.DefaultSourceKey == null)
return;
CurrentSource = Settings.DefaultSourceKey;
}
if (Settings.Sources.ContainsKey(CurrentSource))
{
if (apiKey == null)
{
// Une suppression
Settings.Sources.Remove(CurrentSource);
if (Settings.DefaultSourceKey == CurrentSource) Settings.DefaultSourceKey = null;
}
else
{
// Une mise À jour
Settings.Sources[CurrentSource].SetApiKey(apiKey);
if (Settings.DefaultSourceKey == null) Settings.DefaultSourceKey = CurrentSource;
}
}
else if (apiKey != null)
{
// une addition
var setting = new SourceSettings ();
setting.SetApiKey(apiKey);
Settings.Sources.Add(CurrentSource, setting);
}
SaveConfig();
}
public static void SaveConfig()
{
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, Formatting.Indented));
}
}
}

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,20 @@
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));
}
}
}
}

View File

@ -0,0 +1,21 @@
using System;
using System.Linq;
namespace isn
{
partial class Program
{
private static void SetDefaultSource(string arg)
{
SourceSettings settings =
Settings.Sources.ContainsKey(arg) ?
Settings.Sources[arg] :
Settings.Sources.Values.FirstOrDefault((s)=> s.Alias == arg) ;
if (settings==null) throw new InvalidOperationException(arg);
Settings.DefaultSourceKey = arg;
SaveConfig();
}
}
}

24
src/isn/isn.csproj Normal file
View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net7.0</TargetFrameworks>
<RootNamespace>nuget_cli</RootNamespace>
<UserSecretsId>45b74c62-05bc-4603-95b4-3e80ae2fdf50</UserSecretsId>
<Version>1.0.7</Version>
<PackageVersion>1.0.1</PackageVersion>
<IsPackable>true</IsPackable>
<PackageLicenseExpression>WTFPL</PackageLicenseExpression>
<IsTool>true</IsTool>
<NoWarn>NETSDK1138</NoWarn>
<AssemblyVersion>1.0.7.0</AssemblyVersion>
<FileVersion>1.0.7.0</FileVersion>
<InformationalVersion>1.0.7+Branch.main.Sha.3695c1742965d93eba0ad851656cfaa3e44ba327</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="GitVersion.MsBuild" Version="5.6.10*" />
<ProjectReference Include="../isn.abst/isn.abst.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,30 @@
using System.Net;
using System.Text;
namespace isn
{
public class PushReport
{
public string PkgName { get; set; }
public bool Executed { get; internal set; }
public bool OK { get; internal set; }
public bool AlreadyPresent { get; internal set; }
public string Message { get; internal set; }
public string StatusCode { get; internal set; }
public string StackTrace { get; internal set; }
public string ToDoc()
{
StringBuilder sb = new StringBuilder($"= Pushing {PkgName}\n\n");
if (Executed) sb.AppendLine("* Executed");
if (OK) sb.AppendLine("* OK");
if (!string.IsNullOrWhiteSpace(Message))
sb.AppendLine(Message);
if (!string.IsNullOrWhiteSpace(StatusCode))
sb.AppendLine($"* Status Code : ");
if (!string.IsNullOrWhiteSpace(StackTrace))
sb.AppendLine($"* StackTrace : ");
return sb.ToString();
}
}
}

View File

@ -0,0 +1,8 @@
using Microsoft.AspNetCore.Authorization;
namespace isnd.Authorization
{
internal class ValidApiKeyRequirement : IAuthorizationRequirement
{
}
}

View File

@ -0,0 +1,13 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
namespace isnd.Authorization
{
internal class ValidApiKeyRequirementHandler : AuthorizationHandler<ValidApiKeyRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidApiKeyRequirement requirement)
{
throw new System.NotImplementedException();
}
}
}

9
src/isnd/Constants.cs Normal file
View File

@ -0,0 +1,9 @@
namespace isnd
{
public static class IsndConstants
{
public const string AdministratorRoleName = "Admin";
public const string RequireAdminPolicyName = "RequireAdministratorRole";
public const string RequireValidApiKey = "RequireValideApiKey";
}
}

View File

@ -0,0 +1,258 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using isnd.Data;
using isnd.Data.Roles;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace isnd.Controllers
{
[AllowAnonymous]
public class AccountController : Controller
{
private readonly IAuthenticationSchemeProvider _schemeProvider;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly UserManager<ApplicationUser> _userManager;
private readonly AdminStartupList _startupAdminList;
public AccountController(
IAuthenticationSchemeProvider schemeProvider,
SignInManager<ApplicationUser> signInManager,
UserManager<ApplicationUser> userManager,
IOptions<AdminStartupList> startupAdminListConfig )
{
_schemeProvider = schemeProvider;
_signInManager = signInManager;
_userManager = userManager;
_startupAdminList = startupAdminListConfig.Value;
}
/// <summary>
/// Entry point into the login workflow
/// </summary>
[HttpGet]
public async Task<IActionResult> Login(string returnUrl)
{
// build a model so we know what to show on the login page
var vm = await BuildLoginViewModelAsync(returnUrl);
if (vm.IsExternalLoginOnly)
{
// we only have one option for logging in and it's an external provider
return RedirectToAction("Challenge", "External", new { scheme = vm.ExternalLoginScheme, returnUrl });
}
return View(vm);
}
/// <summary>
/// Handle postback from username/password login
/// </summary>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model, string button)
{
// the user clicked the "cancel" button
if (button != "login")
{
// since we don't have a valid context, then we just go back to the home page
return Redirect("~/");
}
if (ModelState.IsValid)
{
// validate username/password
var user = await _userManager.FindByNameAsync(model.Username);
var signResult = await _signInManager.CheckPasswordSignInAsync(user, model.Password, true);
if (signResult.Succeeded)
{
// only set explicit expiration here if user chooses "remember me".
// otherwise we rely upon expiration configured in cookie middleware.
AuthenticationProperties props = null;
if (AccountOptions.AllowRememberLogin && model.RememberLogin)
{
props = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
};
};
await _signInManager.SignInAsync(user, model.RememberLogin && AccountOptions.AllowRememberLogin);
if (Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
else if (string.IsNullOrEmpty(model.ReturnUrl))
{
return Redirect("~/");
}
else
{
// user might have clicked on a malicious link - should be logged
throw new Exception("invalid return URL");
}
}
ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
}
// something went wrong, show form with error
var vm = await BuildLoginViewModelAsync(model);
return View(vm);
}
/// <summary>
/// Show logout page
/// </summary>
[HttpGet]
public async Task<IActionResult> Logout(string logoutId)
{
// build a model so the logout page knows what to display
var vm = BuildLogoutViewModel(logoutId);
if (vm.ShowLogoutPrompt == false)
{
// if the request for logout was properly authenticated from IdentityServer, then
// we don't need to show the prompt and can just log the user out directly.
return await Logout(vm);
}
return View(vm);
}
/// <summary>
/// Handle logout page postback
/// </summary>
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout(LogoutInputModel model)
{
// build a model so the logged out page knows what to display
var vm = BuildLoggedOutViewModel(model.LogoutId);
if (User?.Identity.IsAuthenticated == true)
{
// delete local authentication cookie
await HttpContext.SignOutAsync();
}
// check if we need to trigger sign-out at an upstream identity provider
if (vm.TriggerExternalSignout)
{
// build a return URL so the upstream provider will redirect back
// to us after the user has logged out. this allows us to then
// complete our single sign-out processing.
string url = Url.Action("Logout", new { logoutId = vm.LogoutId });
// this triggers a redirect to the external provider for sign-out
return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
}
return View("LoggedOut", vm);
}
[HttpGet]
public IActionResult AccessDenied()
{
return new BadRequestObjectResult(403);
}
/*****************************************/
/* helper APIs for the AccountController */
/*****************************************/
private async Task<LoginViewModel> BuildLoginViewModelAsync(string returnUrl)
{
var schemes = await _schemeProvider.GetAllSchemesAsync();
var providers = schemes
.Where(x => x.DisplayName != null)
.Select(x => new ExternalProvider
{
DisplayName = x.DisplayName ?? x.Name,
AuthenticationScheme = x.Name
}).ToList();
var allowLocal = true;
return new LoginViewModel
{
AllowRememberLogin = AccountOptions.AllowRememberLogin,
EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin,
ReturnUrl = returnUrl,
ExternalProviders = providers.ToArray()
};
}
private async Task<LoginViewModel> BuildLoginViewModelAsync(LoginInputModel model)
{
var vm = await BuildLoginViewModelAsync(model.ReturnUrl);
vm.Username = model.Username;
vm.RememberLogin = model.RememberLogin;
return vm;
}
private LogoutViewModel BuildLogoutViewModel(string logoutId)
{
var vm = new LogoutViewModel { LogoutId = logoutId, ShowLogoutPrompt = AccountOptions.ShowLogoutPrompt };
if (User?.Identity.IsAuthenticated != true)
{
// if the user is not authenticated, then just show logged out page
vm.ShowLogoutPrompt = false;
return vm;
}
// show the logout prompt. this prevents attacks where the user
// is automatically signed out by another malicious web page.
return vm;
}
private LoggedOutViewModel BuildLoggedOutViewModel(string logoutId)
{
var vm = new LoggedOutViewModel
{
AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut,
LogoutId = logoutId
};
return vm;
}
[Authorize]
public async Task<IActionResult> GetAdminrole()
{
string username = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (_startupAdminList.Users.Contains(username))
{
var user = await _userManager.FindByNameAsync(username);
var roles = await _userManager.GetRolesAsync(user);
if (!roles.Contains(IsndConstants.AdministratorRoleName))
{
await _userManager.AddToRoleAsync(user, IsndConstants.AdministratorRoleName);
}
return Ok();
}
return BadRequest();
}
}
}

View File

@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using isnd.Data;
using isnd.Entities;
using isnd.Data.ApiKeys;
namespace isnd.Controllers
{
[Authorize]
public class ApiKeysController : Controller
{
private readonly ApplicationDbContext dbContext;
private readonly IsndSettings isndSettings;
private readonly UserManager<ApplicationUser> _userManager;
private readonly IDataProtector protector;
public ApiKeysController(ApplicationDbContext dbContext,
IOptions<IsndSettings> isndSettingsOptions,
IDataProtectionProvider provider,
UserManager<ApplicationUser> userManager)
{
this.dbContext = dbContext;
this.isndSettings = isndSettingsOptions.Value;
protector = provider.CreateProtector(isndSettings.ProtectionTitle);
_userManager = userManager;
}
[HttpGet]
public async Task<ActionResult> Index()
{
List<ApiKey> index = await GetUserKeys().ToListAsync();
IndexModel model = new IndexModel { ApiKey = index };
ViewData["Title"] = "Index";
return View("Index", model);
}
[HttpGet]
public async Task<ActionResult> Create()
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = await _userManager.FindByIdAsync(userId);
ViewBag.UserId = new SelectList(new List<ApplicationUser> { user });
return View(new CreateModel{ });
}
[HttpPost]
public async Task<ActionResult> Create(CreateModel model)
{
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
IQueryable<ApiKey> userKeys = GetUserKeys();
if (userKeys.Count() >= isndSettings.MaxUserKeyCount)
{
ModelState.AddModelError(null, "Maximum key count reached");
return View();
}
ApiKey newKey = new ApiKey { UserId = userid, Name = model.Name,
CreationDate = DateTime.Now };
_ = dbContext.ApiKeys.Add(newKey);
_ = await dbContext.SaveChangesAsync();
return View("Details", new DetailModel { Name = newKey.Name,
ProtectedValue = protector.Protect(newKey.Id),
ApiKey = newKey });
}
[HttpGet]
public async Task<ActionResult> Delete(string id)
{
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
ApiKey key = await dbContext.ApiKeys.FirstOrDefaultAsync(k => k.Id == id && k.UserId == userid);
return View(new DeleteModel { ApiKey = key });
}
[HttpPost]
public async Task<ActionResult> Delete(DeleteModel model)
{
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
ApiKey key = dbContext.ApiKeys.FirstOrDefault(k => k.Id == model.ApiKey.Id && k.UserId == userid);
if (key == null)
{
ModelState.AddModelError(null, "Key not found");
return View();
}
_ = dbContext.ApiKeys.Remove(key);
_ = await dbContext.SaveChangesAsync();
return View("Index", new IndexModel { ApiKey = GetUserKeys().ToList() } );
}
public async Task<ActionResult> Details(string id)
{
string userid = User.FindFirstValue(ClaimTypes.NameIdentifier);
ApiKey key = await dbContext.ApiKeys.FirstOrDefaultAsync(k => k.Id == id && k.UserId == userid);
if (key == null)
{
ModelState.AddModelError(null, "Key not found");
return View();
}
return View("Details", new DetailModel { ApiKey = key, Name = key.Name, ProtectedValue = protector.Protect(key.Id)});
}
public async Task<ActionResult> Edit(string id)
{
EditModel edit = new EditModel();
string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = await _userManager.FindByIdAsync(userId);
edit.ApiKey = await GetUserKeys().SingleOrDefaultAsync(k =>
k.UserId == userId && k.Id == id);
ViewBag.UserId = new SelectList(new List<ApplicationUser> { user });
return View(edit);
}
[HttpPost]
public async Task<ActionResult> Edit(EditModel model)
{
string userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var apiKey = await dbContext.ApiKeys.SingleOrDefaultAsync(k => k.UserId == userId && k.Id == model.ApiKey.Id);
apiKey.Name = model.ApiKey.Name;
apiKey.ValidityPeriodInDays = model.ApiKey.ValidityPeriodInDays;
await dbContext.SaveChangesAsync();
return View("Details", new DetailModel { ApiKey = apiKey });
}
public IQueryable<ApiKey> GetUserKeys()
{
return dbContext.ApiKeys.Include(k => k.User).Where(k => k.User.UserName == User.Identity.Name);
}
}
}

View File

@ -0,0 +1,78 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using isnd.Data;
using System.Linq;
using isnd.ViewModels;
using Unleash;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
namespace isnd.Controllers
{
/// <summary>
/// Home Controller
/// </summary>
public class HomeController : Controller
{
private readonly ApplicationDbContext _dbContext;
private readonly IUnleash _unleashĈlient;
/// <summary>
/// Home controller ctor
/// </summary>
/// <param name="dbContext"></param>
/// <param name="unleashĈlient"></param>
public HomeController(
ApplicationDbContext dbContext,
IUnleash unleashĈlient)
{
_dbContext = dbContext;
_unleashĈlient = unleashĈlient;
}
public IActionResult Index()
{
return View(new HomeIndexViewModel{
PkgCount = _dbContext.Packages
.Where(p => p.Versions.Count > 0)
.Count(),
UnleashClient = _unleashĈlient
});
}
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
var ass = typeof(isn.Abstract.Resource).GetType().Assembly;
var attrs = ass.GetCustomAttributes(true);
// ass.GetCustomAttributes(true);
System.Reflection.AssemblyFileVersionAttribute v = (AssemblyFileVersionAttribute)
GetType().Assembly.GetCustomAttribute(typeof(AssemblyFileVersionAttribute));
return View();
}
public IActionResult Privacy()
{
ViewData["Message"] = "Your Privacy page.";
return View(ViewData);
}
public IActionResult Error()
{
return View();
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using isnd.Data;
namespace isnd.Controllers
{
// TODO Web hook CI
public class NewUpdateController : Controller
{
[Authorize(Policy = IsndConstants.RequireAdminPolicyName)]
public IActionResult NewRelease(NewReleaseInfo release)
{
throw new NotImplementedException("web hook");
}
}
}

View File

@ -0,0 +1,54 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using isnd.Data;
using isnd.ViewModels;
using isnd.Helpers;
using isnd.Interfaces;
namespace isnd
{
[AllowAnonymous]
public class PackageVersionController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IPackageManager _pm;
public PackageVersionController(ApplicationDbContext context,
IPackageManager pm)
{
_context = context;
_pm = pm;
}
// GET: PackageVersion
public async Task<IActionResult> Index(PackageVersionIndexViewModel model)
{
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();
return View(model);
}
[Authorize]
public async Task<IActionResult> Mines(PackageVersionIndexViewModel model)
{
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var applicationDbContext = _context.PackageVersions
.Include(p => p.Package).Where(
p => (string.IsNullOrEmpty(model.PackageId) || p.PackageId.StartsWith(model.PackageId))
&& p.Package.OwnerId == userId);
model.Versions = await applicationDbContext.ToArrayAsync();
return View("Index", model);
}
}
}

View File

@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Mvc;
using isnd.Entities;
using isnd.Services;
using isn.Abstract;
using isn.abst;
using isnd.Interfaces;
using Unleash;
using System.Linq;
namespace isnd.Controllers
{
/// <summary>
/// Api Controller
/// </summary>
public class ApiController : Controller
{
private readonly IPackageManager packageManager;
private readonly Resource[] resources;
/// <summary>
/// Api Controller Constructor
/// </summary>
/// <param name="pm"></param>
/// <param name="unleashĈlient"></param>
public ApiController(IPackageManager pm, IUnleash unleashĈlient)
{
packageManager = pm;
resources = packageManager.GetResources(unleashĈlient).ToArray();
}
/// <summary>
/// API index
/// </summary>
/// <returns></returns>
[HttpGet("~" + Constants.ApiVersion + "/index")]
public IActionResult ApiIndex()
{
return Ok(new ApiIndexViewModel(packageManager.CatalogBaseUrl){ Version = PackageManager.BASE_API_LEVEL, Resources = resources });
}
}
}

View File

@ -0,0 +1,34 @@
using isnd.Services;
using isnd.Entities;
using Microsoft.AspNetCore.Mvc;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController
{
// GET /autocomplete?id=isn.protocol&prerelease=true
[HttpGet("~" + Constants.ApiVersion + ApiConfig.AutoComplete)]
public IActionResult AutoComplete(
string id,
string semVerLevel,
bool prerelease = false,
string packageType = null,
int skip = 0,
int take = 25)
{
if (take > maxTake)
{
ModelState.AddModelError("take", "Maximum exceeded");
}
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

@ -0,0 +1,51 @@
using System.Data.Common;
using System.Linq;
using System.Threading.Tasks;
using isnd.Services;
using isnd.Entities;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using NuGet.Versioning;
using isnd.Data.Packages.Catalog;
using isnd.Data.Catalog;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController
{
// https://docs.microsoft.com/en-us/nuget/api/catalog-resource#versioning
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Catalog)]
public async Task<IActionResult> CatalogIndex()
{
return Ok(await packageManager.GetCatalogIndexAsync());
}
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Registration + "/{id}/{version?}")]
public async Task<IActionResult> CatalogRegistration(string id, string version)
{
if (string.IsNullOrWhiteSpace(version))
{
var query = new Data.Catalog.RegistrationPageIndexQuery
{
Query = id,
Prerelease = true
};
var index = await packageManager.GetPackageRegistrationIndexAsync(query);
if (index == null) return NotFound();
// query.TotalHits = result.Items.Select(i=>i.Items.Length).Aggregate((a,b)=>a+b);
return Ok(index);
}
// return a Package
var leaf = await packageManager.GetCatalogEntryAsync(id, version, null);
if (null == leaf) return NotFound(new { id, version });
return Ok(leaf);
}
}
}

View File

@ -0,0 +1,25 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using isnd.Helpers;
using isnd.Entities;
using System.ComponentModel.DataAnnotations;
using isnd.Attributes;
using System.Security.Claims;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController
{
[HttpDelete("~" + Constants.ApiVersion + ApiConfig.Package + "/{id}/{lower?}/{type?}")]
public async Task<IActionResult> ApiDelete(
[FromRoute][SafeName][Required] string id,
[FromRoute][SafeName][Required] string lower,
[FromRoute] string type)
{
var uid = User.FindFirstValue(ClaimTypes.NameIdentifier);
var report = await packageManager.UserAskForPackageDeletionAsync(uid, id, lower, type);
return Ok(report);
}
}
}

View File

@ -0,0 +1,55 @@
using System.ComponentModel.DataAnnotations;
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 the paquet
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Package + "/{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}." + Constants.PaquetFileEstension
);
FileInfo pkgfi = new FileInfo(pkgpath);
if (!pkgfi.Exists)
{
return BadRequest("!pkgfi.Exists");
}
return File(pkgfi.OpenRead(), "application/zip; charset=binary");
}
// Web get spec
[HttpGet("~" + Constants.ApiVersion + Constants.SpecFileEstension + "/{id}/{lower}/{idf}-{lowerf}."
+ Constants.SpecFileEstension)]
public IActionResult GetNuspec(
[FromRoute][SafeName][Required] string id,
[FromRoute][SafeName][Required] string lower,
[FromRoute][SafeName][Required] string idf,
[FromRoute][SafeName][Required] string lowerf)
{
var pkgpath = Path.Combine(isndSettings.PackagesRootDir,
id, lower, $"{id}." + Constants.SpecFileEstension);
FileInfo pkgfi = new FileInfo(pkgpath);
if (!pkgfi.Exists)
{
return BadRequest("!pkgfi.Exists");
}
return File(pkgfi.OpenRead(), "text/xml; charset=utf-8");
}
}
}

View File

@ -0,0 +1,39 @@
using Microsoft.AspNetCore.Mvc;
using NuGet.Versioning;
using isnd.Entities;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController
{
public IActionResult GetVersions(
string id,
string lower,
bool prerelease = false,
string packageType = null,
int skip = 0,
int take = 25)
{
if (take > maxTake)
{
ModelState.AddModelError("take", "Maximum exceeded");
}
// NugetVersion
if (!NuGetVersion.TryParse(lower, out NuGetVersion parsedVersion))
{
ModelState.AddModelError("lower", "invalid version string");
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok(new
{
versions = packageManager.GetVersions(
id, parsedVersion, prerelease, packageType, skip, take)
});
}
}
}

View File

@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NuGet.Packaging.Core;
using NuGet.Versioning;
using isnd.Data;
using isnd.Helpers;
using isnd.Entities;
using Microsoft.AspNetCore.Http;
using isn.abst;
using isnd.Data.Packages;
using Microsoft.AspNetCore.Authorization;
namespace isnd.Controllers
{
public partial class PackagesController
{
// TODO [Authorize(Policy = IsndConstants.RequireValidApiKey)]
[HttpPut("~" + Constants.ApiVersion + ApiConfig.Package)]
public async Task<IActionResult> Put()
{
try
{
var clientVersionId = Request.Headers["X-NuGet-Client-Version"];
string apiKey = Request.Headers["X-NuGet-ApiKey"][0];
ViewData["versionId"] = typeof(PackagesController).Assembly.FullName;
var files = new List<string>();
ViewData["files"] = files;
var clearkey = protector.Unprotect(apiKey);
var apikey = dbContext.ApiKeys.SingleOrDefault(k => k.Id == clearkey);
if (apikey == null)
{
logger.LogError("403 : no api-key");
return Unauthorized();
}
Commit commit = new Commit
{
Action = PackageAction.PublishPackage,
TimeStamp = DateTime.Now
};
dbContext.Commits.Add(commit);
foreach (IFormFile file in Request.Form.Files)
{
string initpath = Path.Combine(Environment.GetEnvironmentVariable("TEMP") ??
Environment.GetEnvironmentVariable("TMP") ?? "/tmp",
$"isn-{Guid.NewGuid()}."+Constants.PaquetFileEstension);
using (FileStream fw = new FileStream(initpath, FileMode.Create))
{
file.CopyTo(fw);
}
using (FileStream fw = new FileStream(initpath, FileMode.Open))
{
var archive = new ZipArchive(fw);
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 = spec.Open())
{
NuspecCoreReader reader = new NuspecCoreReader(specstr);
string pkgdesc = reader.GetDescription();
var types = reader.GetPackageTypes();
pkgid = reader.GetId();
version = reader.GetVersion();
string pkgidpath = Path.Combine(isndSettings.PackagesRootDir,
pkgid);
pkgpath = Path.Combine(pkgidpath, version.ToFullString());
string name = $"{pkgid}-{version}."+Constants.PaquetFileEstension;
fullpath = Path.Combine(pkgpath, name);
var destpkgiddir = new DirectoryInfo(pkgidpath);
Package pkg = dbContext.Packages.SingleOrDefault(p => p.Id == pkgid);
if (pkg != null)
{
if (pkg.OwnerId != apikey.UserId)
{
return new ForbidResult();
}
pkg.Description = pkgdesc;
}
else
{
pkg = new Package
{
Id = pkgid,
Description = pkgdesc,
OwnerId = apikey.UserId,
LatestVersion = commit,
};
dbContext.Packages.Add(pkg);
}
if (!destpkgiddir.Exists) destpkgiddir.Create();
var source = new FileInfo(initpath);
var dest = new FileInfo(fullpath);
var destdir = new DirectoryInfo(dest.DirectoryName);
if (dest.Exists)
{
// La version existe sur le disque,
// 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 == pkg.Id
);
if (pkgv !=null && pkgv.Count()==0)
{
dest.Delete();
}
else {
logger.LogWarning("400 : pkgversion:existant");
ModelState.AddModelError("pkgversion", "existant" );
return BadRequest(ModelState);
}
}
{
if (!destdir.Exists) destdir.Create();
source.MoveTo(fullpath);
files.Add(name);
string fullstringversion = version.ToFullString();
var pkgvers = dbContext.PackageVersions.Where
(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 = pkg,
Major = version.Major,
Minor = version.Minor,
Patch = version.Patch,
Revision = version.Revision,
IsPrerelease = version.IsPrerelease,
FullString = version.ToFullString(),
Type = null,
LatestCommit = commit
});
else
foreach (var type in types)
{
var pkgver = new PackageVersion
{
Package = pkg,
Major = version.Major,
Minor = version.Minor,
Patch = version.Patch,
IsPrerelease = version.IsPrerelease,
FullString = version.ToFullString(),
Type = type.Name,
LatestCommit = commit
};
dbContext.PackageVersions.Add(pkgver);
}
await dbContext.SaveChangesAsync();
packageManager.ÛpdateCatalogForAsync(commit);
logger.LogInformation($"new paquet : {spec.Name}");
}
}
using (var shacrypto = System.Security.Cryptography.SHA512.Create())
{
using (var stream = System.IO.File.OpenRead(fullpath))
{
var hash = shacrypto.ComputeHash(stream);
var shafullname = fullpath + ".sha512";
var hashtext = Convert.ToBase64String(hash);
var hashtextbytes = Encoding.ASCII.GetBytes(hashtext);
using (var shafile = System.IO.File.OpenWrite(shafullname))
{
shafile.Write(hashtextbytes, 0, hashtextbytes.Length);
}
}
}
string nuspecfullpath = Path.Combine(pkgpath, pkgid + "." + Constants.SpecFileEstension);
FileInfo nfpi = new FileInfo(nuspecfullpath);
if (nfpi.Exists)
nfpi.Delete();
spec.ExtractToFile(nuspecfullpath);
}
}
return Ok(ViewData);
}
catch (Exception ex)
{
logger.LogError(ex.Message);
logger.LogError("Stack Trace: " + ex.StackTrace);
return new ObjectResult(new { ViewData, ex.Message })
{ StatusCode = 500 };
}
}
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using isnd.Entities;
using isn.abst;
namespace isnd.Controllers
{
public partial class PackagesController
{
// GET {@id}?q={QUERY}&skip={SKIP}&take={TAKE}&prerelease={PRERELEASE}&semVerLevel={SEMVERLEVEL}&packageType={PACKAGETYPE}
[HttpGet("~" + Constants.ApiVersion + ApiConfig.Search)]
public IActionResult Search(
string q,
int skip = 0,
int take = 25,
bool prerelease = false,
string semVerLevel = null,
string packageType = null
)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,92 @@
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;
namespace isnd.Controllers
{
public partial class PackagesController
{
// Web search
public async Task<IActionResult> Index(RegistrationPageIndexQuery model)
{
return View(new RegistrationPageIndexQueryAndResult{Query = model,
Result = await packageManager.SearchPackageAsync(model)});
}
public async Task<IActionResult> Details(string pkgid)
{
if (pkgid == null)
{
return NotFound();
}
var packageVersion = dbContext.PackageVersions
.Include(p => p.Package)
.Where(m => m.PackageId == pkgid)
.OrderByDescending(p => p)
;
if (packageVersion.Count() == 0)
{
return NotFound();
}
bool results = await packageVersion.AnyAsync();
var latest = await packageVersion.FirstAsync();
return View("Details", new PackageDetailViewModel
{
ExternalUrl = isndSettings.ExternalUrl,
latest = latest,
pkgid = pkgid,
totalHits = packageVersion.Count(),
data = packageVersion.Take(MAX_PKG_VERSION_LIST).ToArray()
});
}
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

@ -0,0 +1,52 @@
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NuGet.Versioning;
using isnd.Data;
using isnd.Entities;
using Unleash;
using isnd.Services;
using isnd.ViewModels;
using System.Threading.Tasks;
using isnd.Interfaces;
using isn.Abstract;
namespace isnd.Controllers
{
[AllowAnonymous]
public partial class PackagesController : Controller
{
const int maxTake = 100;
private readonly Resource[] resources;
private readonly ILogger<PackagesController> logger;
private readonly IDataProtector protector;
private readonly IsndSettings isndSettings;
readonly ApplicationDbContext dbContext;
private readonly IPackageManager packageManager;
private readonly IUnleash unleashĈlient;
public PackagesController(
ILoggerFactory loggerFactory,
IDataProtectionProvider provider,
IOptions<IsndSettings> isndOptions,
IUnleash unleashĈlient,
ApplicationDbContext dbContext,
IPackageManager pm)
{
logger = loggerFactory.CreateLogger<PackagesController>();
isndSettings = isndOptions.Value;
protector = provider.CreateProtector(isndSettings.ProtectionTitle);
this.dbContext = dbContext;
packageManager = pm;
this.unleashĈlient = unleashĈlient;
resources = packageManager.GetResources(unleashĈlient).ToArray();
}
}
}

View File

@ -0,0 +1,20 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using System;
namespace isnd.Data
{
public class AccountOptions
{
public static bool AllowLocalLogin = true;
public static bool AllowRememberLogin = true;
public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30);
public static bool ShowLogoutPrompt = true;
public static bool AutomaticRedirectAfterSignOut = false;
public static string InvalidCredentialsErrorMessage = "Invalid username or password";
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace isnd.Data
{
public class ExternalProvider
{
public string DisplayName { get; set; }
public string AuthenticationScheme { get; set; }
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace isnd.Data
{
public class LoggedOutViewModel
{
public string PostLogoutRedirectUri { get; set; }
public string ClientName { get; set; }
public string SignOutIframeUrl { get; set; }
public bool AutomaticRedirectAfterSignOut { get; set; }
public string LogoutId { get; set; }
public bool TriggerExternalSignout => ExternalAuthenticationScheme != null;
public string ExternalAuthenticationScheme { get; set; }
}
}

View File

@ -0,0 +1,18 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using System.ComponentModel.DataAnnotations;
namespace isnd.Data
{
public class LoginInputModel
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
public bool RememberLogin { get; set; }
public string ReturnUrl { get; set; }
}
}

View File

@ -0,0 +1,22 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace isnd.Data
{
public class LoginViewModel : LoginInputModel
{
public bool AllowRememberLogin { get; set; } = true;
public bool EnableLocalLogin { get; set; } = true;
public IEnumerable<ExternalProvider> ExternalProviders { get; set; } = Enumerable.Empty<ExternalProvider>();
public IEnumerable<ExternalProvider> VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName));
public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;
public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace isnd.Data
{
public class LogoutInputModel
{
public string LogoutId { get; set; }
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace isnd.Data
{
public class LogoutViewModel : LogoutInputModel
{
public bool ShowLogoutPrompt { get; set; } = true;
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
namespace isnd.Data
{
public class RedirectViewModel
{
public string RedirectUrl { get; set; }
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace isnd.Data
{
public class RegisterViewModel
{
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)]
[Display(Name = "FullName")]
public string FullName { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace isnd.Data.ApiKeys
{
public class ApiKey
{
[Required][Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }
[Required][ForeignKey("User")]
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
public string Name { get; set; }
public int ValidityPeriodInDays{ get; set; }
public DateTime CreationDate { get; set; }
public bool IsValid => CreationDate.AddDays(ValidityPeriodInDays) > DateTime.Now;
}
}

View File

@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace isnd.Data.ApiKeys
{
public class ApiKeyViewModel
{
[Display(Name = "Key Name")]
public string Name { get; set; }
[Display(Name = "Key Value")]
public string ProtectedValue { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace isnd.Data.ApiKeys
{
public class CreateModel
{
[Required][StringLength(255)]
[Display(Name = "Key Name")]
public string Name { get; set; }
public string UserId { get; set; }
}
}

View File

@ -0,0 +1,7 @@
namespace isnd.Data.ApiKeys
{
public class DeleteModel
{
public ApiKey ApiKey { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace isnd.Data.ApiKeys
{
public class DetailModel : ApiKeyViewModel
{
public ApiKey ApiKey { get; set; }
}
}

View File

@ -0,0 +1,12 @@
namespace isnd.Data.ApiKeys
{
public class EditModel
{
public EditModel()
{
if (ApiKey==null) ApiKey = new ApiKey();
}
public ApiKey ApiKey { get; set; }
}
}

View File

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace isnd.Data.ApiKeys
{
public class IndexModel
{
public List<ApiKey> ApiKey { get; set; }
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using isnd.Data;
using isnd.Data.ApiKeys;
using isnd.Data.Packages;
namespace isnd.Data
{
/// <summary>
/// Application Db Context
/// </summary>
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
/// <summary>
/// db context ctor
/// </summary>
/// <param name="options"></param>
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options) { }
/// <summary>
/// User API keys
/// </summary>
/// <value></value>
public DbSet<ApiKey> ApiKeys { get; set; }
/// <summary>
/// Packages
/// </summary>
/// <value></value>
public DbSet<Package> Packages { get; set; }
/// <summary>
/// Package Versions
/// </summary>
/// <value></value>
public DbSet<PackageVersion> PackageVersions { get; set; }
/// <summary>
/// Commits
/// </summary>
/// <value></value>
public DbSet<Commit> Commits { get; set; }
}
}

View File

@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Identity;
namespace isnd.Data
{
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser
{
public string FullName { get; set; }
}
}

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,119 @@
using System.Net.Sockets;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using isnd.Data.Packages;
using NuGet.Versioning;
using System.Collections.Generic;
using System;
using isnd.Interfaces;
namespace isnd.Data.Catalog
{
public class CatalogEntry : HappyIdOwner , IObject// , IPackageDetails
{
/// <summary>
/// Creates a catalog entry
/// </summary>
/// <param name="id">package details url</param>
/// <returns></returns>
public CatalogEntry(string id): base(id)
{
}
/// <summary>
/// The ID of the package
/// </summary>
/// <value></value>
[JsonProperty("id")]
public string Id { get; set; }
/// <summary>
/// The Package details url
/// </summary>
/// <returns></returns>
[JsonProperty("@id")]
public string refid { get => GetId(); }
[JsonProperty("@type")]
public string[] RefType { get; protected set; } = new string[] { "PackageDetail" };
[JsonProperty("commitId")]
public string CommitId { get; set; }
[JsonProperty("commitTimeStamp")]
public DateTime CommitTimeStamp { 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; }
public string language { 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; }
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 security vulnerabilities of the package
/// </summary>
/// <value></value>
public Vulnerabilitie[] vulnerabilities { get; set; }
public string packageContent { get; set; }
/// <summary>
/// A string containing a ISO 8601 timestamp of when the package was published
/// </summary>
/// <value></value>
[JsonProperty("published")]
public DateTime Published { get; set; }
/// <summary>
/// The full version string after normalization
/// </summary>
/// <value></value>
[Required,JsonRequired]
[JsonProperty("version")]
public string Version { 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

@ -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
*/
/// <summary>
/// The URL to the registration leaf
/// </summary>
/// <value></value>
[JsonProperty("@id")]
[Key][Required]
[StringLength(1024)]
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,100 @@
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 : HappyIdOwner
{
[JsonProperty("@id")]
public string Id { get => GetId(); }
private readonly string pkgid;
private readonly List<PackageVersion> items;
protected string Bid { get ; private set; }
protected string ExternalUrl { get; }
public RegistrationPage (string bid, string pkgid, string extUrl) : base(bid + "/" + pkgid + "/index.json")
{
Bid = bid;
Parent = Bid + $"/{pkgid}/index.json";
ExternalUrl = extUrl;
this.items = new List<PackageVersion>();
this.pkgid = pkgid;
}
public RegistrationPage(string bid, string pkgid, string extUrl, List<PackageVersion> versions) : this(bid, pkgid, extUrl)
{
AddVersionRange(versions);
}
public string GetPackageId()
{
return pkgid;
}
/// <summary>
/// The array of registration leaves and their associate metadata
/// </summary>
/// <value></value>
[JsonProperty("items")]
public CatalogEntry[] Items { get => items.Select((p) => p.ToLeave(Bid, ExternalUrl)).ToArray(); }
public void AddVersionRange(IEnumerable<PackageVersion> vitems)
{
if (vitems.Count() == 0) return;
NuGetVersion upper = null;
NuGetVersion lower = null;
if (Lower!=null) lower = new NuGetVersion(Lower);
if (Upper!=null) upper = new NuGetVersion(Upper);
// Assert.True(items.All(p=>p.Id == id));
long commitMax = 0;
foreach (var p in vitems)
{
if (items.Contains(p)) continue;
if (upper == null) upper = p.NugetVersion;
else if ( upper < p.NugetVersion) upper = p.NugetVersion;
if (lower == null) lower = p.NugetVersion;
else if (lower > p.NugetVersion) lower = p.NugetVersion;
if (p.CommitNId > commitMax) commitMax = p.CommitNId;
items.Add(p);
}
Upper = upper.ToFullString();
Lower = lower.ToFullString();
CommitId = commitMax.ToString();
}
/// <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 => items.Count; }
public string CommitId { get; internal set; }
public DateTime CommitTimeStamp { get; internal set; }
}
}

View File

@ -0,0 +1,53 @@
using isnd.Data.Packages;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
namespace isnd.Data.Catalog
{
public class RegistrationPageIndex : HappyIdOwner
{
public RegistrationPageIndex(string url) : base(url)
{
Items = new List<RegistrationPage>();
}
public RegistrationPageIndex(string bid, string id, string extUrl, IEnumerable<Package> pkgs) : base(bid + $"/{id}/index.json")
{
Items = new List<RegistrationPage>();
long cnid = 0;
var pkgsGroups = pkgs.GroupBy(l => l.Id);
// Pour tous les groupes par Id
foreach (var gsp in pkgsGroups)
{
var pkgsbi = gsp.ToArray();
List<PackageVersion> versions = new List<PackageVersion>();
foreach(var l in pkgsbi.Select(p => p.Versions))
{
versions.AddRange(l);
foreach (var pv in l)
{
if (pv.CommitNId> cnid)
{
cnid = pv.CommitNId;
}
}
}
Items.Add(new RegistrationPage(bid, gsp.Key, extUrl, versions));
}
CommitId = cnid.ToString();
}
[JsonProperty("count")]
public int Count { get => Items.Count; }
[JsonProperty("items")]
public List<RegistrationPage> Items { get; set; }
public string CommitId { get; set; }
public DateTime CommitTimeStamp { get; internal set; }
}
}

View File

@ -0,0 +1,25 @@
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;
}
}

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

@ -0,0 +1,31 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using isnd.Data.Packages;
using isnd.Data.Packages.Catalog;
namespace isnd.Data.Historic
{
public class PackageVersionCommit
{
public long CommitId { get; set; }
[StringLength(1024)]
public string PackageId { get; set; }
[StringLength(256)]
public string FullString { get; set; }
[StringLength(256)]
public string PackageType { get; set; }
[ForeignKey("CommitId")]
public virtual Commit Commit { get; set; }
[ForeignKey("PackageId")]
public virtual Package Package { get; set; }
[ForeignKey("PackageId,FullString,PackageType")]
public virtual PackageVersion PackageVersion { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using System;
using Newtonsoft.Json;
namespace isnd.Interfaces
{
public interface IObject
{
[JsonProperty("@type")]
public string Type { get => GetType().Name; }
[JsonProperty("commitId")]
string CommitId { get; }
[JsonProperty("commitTimeStamp")]
DateTime CommitTimeStamp { get; }
}
}

View File

@ -0,0 +1,52 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using isnd.Interfaces;
using Newtonsoft.Json;
namespace isnd.Data.Packages.Catalog
{
/// <summary>
/// An presence of package in a catalog,
/// for availability, or deletion,
///
/// </summary>
public class PackageRef : IObject
{
[JsonProperty("@id")]
public string RefId { get; set; }
/// <summary>
/// Reference type :
/// nuget:PackageDetails vs nuget:PackageDelete
/// </summary>
/// <value></value>
[JsonProperty("@type")]
public string RefType { get; set; }
/// <summary>
/// The NuGet Id
/// </summary>
/// <value></value>
[JsonProperty("nuget:id")]
public string Id { get; set; }
/// <summary>
/// The NuGet version
/// </summary>
/// <value></value>
[JsonProperty("nuget:version")]
public string Version { get; set; }
[JsonProperty("commitId")]
public string CommitId { get; set; }
[ForeignKey("CommitId"), JsonIgnore]
public virtual Commit LastCommit { get; set; }
[JsonProperty("commitTimeStamp")]
public DateTime CommitTimeStamp { get; set; }
}
}

View File

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

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
using isnd.Interfaces;
namespace isnd.Data.Packages
{
public enum PackageAction
{
DeletePackage,
PublishPackage
}
public class Commit : IObject
{
[Key,
DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public long Id { get; set; }
[Required][JsonIgnore]
public DateTime TimeStamp{ get; set; }
[Required]
public PackageAction Action { get; set; }
[NotMapped]
public string CommitId { get => Id.ToString(); }
[NotMapped]
public DateTime CommitTimeStamp { get => TimeStamp; }
[ForeignKey("CommitNId")]
public virtual List<PackageVersion> Versions { get; set; }
}
}

View File

@ -0,0 +1,66 @@
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.Packages
{
public interface IPackage
{
string Id { get; set; }
string OwnerId { get; set; }
string Description { get; set; }
bool Public { get; set; }
ApplicationUser Owner { get; set; }
List<PackageVersion> Versions { get; set; }
long CommitNId { get; set; }
string CommitId { get; }
Commit LatestVersion { get; set; }
DateTime CommitTimeStamp { get; set; }
}
public class Package : IObject, IPackage
{
[Key]
[Required]
[StringLength(1024)]
public string Id { get; set; }
[Required]
[ForeignKey("Owner")]
public string OwnerId { get; set; }
[StringLength(1024)]
public string Description { get; set; }
public bool Public { get; set; }
[JsonIgnore]
virtual public ApplicationUser Owner { get; set; }
[JsonIgnore]
public virtual List<PackageVersion> Versions { get; set; }
/// <summary>
/// Latest version at put, posted,
/// or even deletion when no more active version.
/// </summary>
/// <value></value>
[Required]
[JsonIgnore]
public long CommitNId { get; set; }
[NotMapped]
public string CommitId { get => CommitNId.ToString(); }
[ForeignKey("CommitNId")]
public virtual Commit LatestVersion { get; set; }
public DateTime CommitTimeStamp { get; set; }
}
}

View File

@ -0,0 +1,80 @@
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 CatalogEntry ToLeave(string bid, string extUrl)
{
return new CatalogEntry(bid + "/" + this.PackageId + "/" + FullString + ".json")
{
Id = PackageId,
Version = FullString,
authors = $"{this.Package.Owner.FullName} <${Package.Owner.Email}>",
packageContent = extUrl + this.NugetLink
};
}
}
}

View File

@ -0,0 +1,7 @@
namespace isnd.Data.Roles
{
public class AdminStartupList
{
public string [] Users { get; set;}
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace isnd.Entities
{
public class IsndSettings
{
public string ExternalUrl { get; set; }
public string ProtectionTitle {get; set;}
public string PackagesRootDir {get; set;}
public string CatalogDir {get; set;}
public int MaxUserKeyCount {get; set;}
public int CatalogPageLen {get; set;}
public TimeSpan DisplayDeletionLen {get; set;}
}
}

View File

@ -0,0 +1,11 @@
using System;
namespace isnd.Data
{
public class NewReleaseInfo
{
public string Version { get; set; }
public string ChangeLog { get; set; }
public DateTime BuildDate { get; set; }
}
}

View File

@ -0,0 +1,12 @@
namespace isnd.Entities
{
public class SmtpSettings
{
public string Server {get; set;}
public int Port {get; set;}
public string SenderName {get; set;}
public string SenderEMail {get; set;}
public string UserName {get; set;}
public string Password {get; set;}
}
}

View File

@ -0,0 +1,8 @@
namespace isnd.Entities
{
public class UnleashClientSettings
{
public string ClientApiKey { get; set; }
public string ApiUrl { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using Microsoft.AspNetCore.Mvc;
namespace isnd.Data
{
public static class Extensions
{
public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri)
{
controller.HttpContext.Response.StatusCode = 200;
controller.HttpContext.Response.Headers["Location"] = "";
return controller.View(viewName, new RedirectViewModel { RedirectUrl = redirectUri });
}
}
}

View File

@ -0,0 +1,16 @@
using System.Linq;
using System.Xml.Linq;
using NuGet.Packaging.Core;
namespace isnd.Helpers
{
public static class NuspecCoreReaderHelpers
{
public static string GetDescription(this NuspecCoreReader reader)
{
var meta = reader.GetMetadata();
var kv = meta.SingleOrDefault(i => i.Key == "description");
return kv.Value;
}
}
}

View File

@ -0,0 +1,17 @@
namespace isnd.Helpers
{
/// <summary>
/// Package Id Helpers
/// </summary>
public static class PackageIdHelpers
{
internal static bool SeparatedByMinusMatch(string id, string q)
{
foreach (var part in id.Split('-'))
{
if (part.Equals(q, System.StringComparison.InvariantCultureIgnoreCase)) return true;
}
return false;
}
}
}

View File

@ -0,0 +1,20 @@
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);
return v.Package.OwnerId == userId;
}
}
}

View File

@ -0,0 +1,16 @@
namespace isnd.Helpers
{
public static class ParamHelpers
{
public static string Optional(ref string prm)
{
int sopt = prm.IndexOf('/');
if (sopt>0)
{
prm = prm.Substring(0,sopt);
return prm.Substring(sopt + 1);
}
return null;
}
}
}

View File

@ -0,0 +1,13 @@
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

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using isnd.Entities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Unleash;
using Unleash.ClientFactory;
namespace isnd.Helpers
{
public static class UnleashHelpers
{
public static IUnleash CreateUnleahClient(this IHostingEnvironment env,
UnleashClientSettings unleashClientSettings)
{
var unleashSettings = new UnleashSettings
{
UnleashApi = new Uri(unleashClientSettings.ApiUrl),
AppName = "isnd",
Environment = env.EnvironmentName,
CustomHttpHeaders = new Dictionary<string, string>
{
{ "Authorization", unleashClientSettings.ClientApiKey }
}
};
UnleashClientFactory unleashClientFactory = new UnleashClientFactory();
return unleashClientFactory.CreateClient(unleashSettings);
}
}
}

View File

@ -0,0 +1,10 @@
using System.Threading.Tasks;
namespace isnd.Interfaces
{
public interface IMailer
{
Task SendMailAsync(string name, string email, string subjet, string body);
}
}

View File

@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Threading.Tasks;
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;
using Unleash;
namespace isnd.Interfaces
{
public interface IPackageManager
{
string CatalogBaseUrl { get; }
AutoCompleteResult AutoComplete(string pkgid, int skip, int take, bool prerelease = false, string packageType = null);
string[] GetVersions(string pkgid, NuGetVersion parsedVersion, bool prerelease = false, string packageType = null, int skip = 0, int take = 25);
IEnumerable<Resource> GetResources(IUnleash unleashĈlient);
Task<RegistrationPageIndex> ÛpdateCatalogForAsync(Commit commit);
Task<PackageDeletionReport> DeletePackageAsync(string pkgid, string version, string type);
Task<PackageDeletionReport> UserAskForPackageDeletionAsync(string userid, string pkgId, string lower, string type);
Task<PackageVersion> GetPackageAsync(string pkgid, string version, string type);
Task<CatalogEntry> GetCatalogEntryAsync(string pkgId, string version, string pkgType);
IEnumerable<CatalogEntry> SearchCatalogEntriesById(string pkgId, string semver, string pkgType);
Task<RegistrationPageIndex> GetCatalogIndexAsync();
Task<RegistrationPageIndex> GetPackageRegistrationIndexAsync(RegistrationPageIndexQuery query);
Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query);
}
}

View File

@ -0,0 +1,230 @@
// <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("20210424155323_init")]
partial class init
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
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("isn.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("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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("isn.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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,219 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace isndhost.Migrations
{
public partial class init : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false),
FullName = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(nullable: false),
ProviderKey = table.Column<string>(nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: false),
Value = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}

View File

@ -0,0 +1,253 @@
// <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("20210502153508_api-keys")]
partial class apikeys
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
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("isn.Data.ApiKey", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("ApiKeys");
});
modelBuilder.Entity("isn.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("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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("isn.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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.ApiKey", b =>
{
b.HasOne("isn.Data.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,39 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace isndhost.Migrations
{
public partial class apikeys : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ApiKeys",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiKeys", x => x.Id);
table.ForeignKey(
name: "FK_ApiKeys_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ApiKeys_UserId",
table: "ApiKeys",
column: "UserId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ApiKeys");
}
}
}

View File

@ -0,0 +1,259 @@
// <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("20210508012908_ApkiKey.CreationDate")]
partial class ApkiKeyCreationDate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
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("isn.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("isn.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("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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("isn.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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.ApiKeys.ApiKey", b =>
{
b.HasOne("isn.Data.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,43 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace isndhost.Migrations
{
public partial class ApkiKeyCreationDate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTime>(
name: "CreationDate",
table: "ApiKeys",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.AddColumn<string>(
name: "Name",
table: "ApiKeys",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "ValidityPeriodInDays",
table: "ApiKeys",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CreationDate",
table: "ApiKeys");
migrationBuilder.DropColumn(
name: "Name",
table: "ApiKeys");
migrationBuilder.DropColumn(
name: "ValidityPeriodInDays",
table: "ApiKeys");
}
}
}

View File

@ -0,0 +1,316 @@
// <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("20210516060430_packages")]
partial class packages
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
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("isn.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("isn.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("isn.Data.Package", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Description");
b.Property<string>("OwnerId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("OwnerId");
b.ToTable("Packages");
});
modelBuilder.Entity("isn.Data.PackageVersion", b =>
{
b.Property<string>("FullString")
.ValueGeneratedOnAdd()
.HasMaxLength(32);
b.Property<bool>("IsPrerelease");
b.Property<int>("Major");
b.Property<int>("Minor");
b.Property<string>("PackageId")
.IsRequired();
b.Property<int>("Patch");
b.HasKey("FullString");
b.HasIndex("PackageId");
b.ToTable("PackageVersions");
});
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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("isn.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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.ApiKeys.ApiKey", b =>
{
b.HasOne("isn.Data.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.Package", b =>
{
b.HasOne("isn.Data.ApplicationUser", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.PackageVersion", b =>
{
b.HasOne("isn.Data.Package", "Package")
.WithMany()
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,70 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace isndhost.Migrations
{
public partial class packages : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Packages",
columns: table => new
{
Id = table.Column<string>(nullable: false),
OwnerId = table.Column<string>(nullable: false),
Description = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Packages", x => x.Id);
table.ForeignKey(
name: "FK_Packages_AspNetUsers_OwnerId",
column: x => x.OwnerId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PackageVersions",
columns: table => new
{
FullString = table.Column<string>(maxLength: 32, nullable: false),
PackageId = table.Column<string>(nullable: false),
Major = table.Column<int>(nullable: false),
Minor = table.Column<int>(nullable: false),
Patch = table.Column<int>(nullable: false),
IsPrerelease = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PackageVersions", x => x.FullString);
table.ForeignKey(
name: "FK_PackageVersions_Packages_PackageId",
column: x => x.PackageId,
principalTable: "Packages",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Packages_OwnerId",
table: "Packages",
column: "OwnerId");
migrationBuilder.CreateIndex(
name: "IX_PackageVersions_PackageId",
table: "PackageVersions",
column: "PackageId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PackageVersions");
migrationBuilder.DropTable(
name: "Packages");
}
}
}

View File

@ -0,0 +1,312 @@
// <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("20210522194803_packageVersionKey")]
partial class packageVersionKey
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.SerialColumn)
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
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("isn.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("isn.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("isn.Data.Package", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Description");
b.Property<string>("OwnerId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("OwnerId");
b.ToTable("Packages");
});
modelBuilder.Entity("isn.Data.PackageVersion", b =>
{
b.Property<string>("PackageId");
b.Property<string>("FullString")
.HasMaxLength(256);
b.Property<bool>("IsPrerelease");
b.Property<int>("Major");
b.Property<int>("Minor");
b.Property<int>("Patch");
b.HasKey("PackageId", "FullString");
b.ToTable("PackageVersions");
});
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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("isn.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("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("isn.Data.ApplicationUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.ApiKeys.ApiKey", b =>
{
b.HasOne("isn.Data.ApplicationUser", "User")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.Package", b =>
{
b.HasOne("isn.Data.ApplicationUser", "Owner")
.WithMany()
.HasForeignKey("OwnerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("isn.Data.PackageVersion", b =>
{
b.HasOne("isn.Data.Package", "Package")
.WithMany()
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,56 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace isndhost.Migrations
{
public partial class packageVersionKey : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_PackageVersions",
table: "PackageVersions");
migrationBuilder.DropIndex(
name: "IX_PackageVersions_PackageId",
table: "PackageVersions");
migrationBuilder.AlterColumn<string>(
name: "FullString",
table: "PackageVersions",
maxLength: 256,
nullable: false,
oldClrType: typeof(string),
oldMaxLength: 32);
migrationBuilder.AddPrimaryKey(
name: "PK_PackageVersions",
table: "PackageVersions",
columns: new[] { "PackageId", "FullString" });
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_PackageVersions",
table: "PackageVersions");
migrationBuilder.AlterColumn<string>(
name: "FullString",
table: "PackageVersions",
maxLength: 32,
nullable: false,
oldClrType: typeof(string),
oldMaxLength: 256);
migrationBuilder.AddPrimaryKey(
name: "PK_PackageVersions",
table: "PackageVersions",
column: "FullString");
migrationBuilder.CreateIndex(
name: "IX_PackageVersions_PackageId",
table: "PackageVersions",
column: "PackageId");
}
}
}

Some files were not shown because too many files have changed in this diff Show More