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

View File

@ -0,0 +1,57 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Hosting;
using MailKit.Net.Smtp;
using MimeKit;
using System;
using isnd.Interfaces;
using isnd.Entities;
namespace isnd.Services
{
public class EmailSender : IEmailSender, IMailer
{
public EmailSender(IOptions<SmtpSettings> smtpSettings,
IHostingEnvironment env)
{
Options = smtpSettings.Value;
Env = env;
}
public SmtpSettings Options { get; } //set only via Secret Manager
public IHostingEnvironment Env { get; }
public Task SendEmailAsync(string email, string subject, string message)
{
return Execute(Options.SenderName, subject, message, email);
}
public async Task Execute(string name, string subject, string message, string email)
{
await SendMailAsync(name, email, subject, message);
}
public async Task SendMailAsync(string name, string email, string subjet, string body)
{
try {
var message = new MimeMessage();
message.From.Add(new MailboxAddress(Options.SenderName, Options.SenderEMail));
message.To.Add(new MailboxAddress(name??email, email));
message.Body = new TextPart("html") { Text = body };
using (var client = new SmtpClient())
{
client.ServerCertificateValidationCallback = (s,c,h,e)=>true;
await client.ConnectAsync(Options.Server);
await client.AuthenticateAsync(Options.UserName, Options.Password);
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
}
catch (Exception e)
{
throw new InvalidOperationException(e.Message);
}
}
}
}

View File

@ -0,0 +1,316 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using isn.abst;
using isn.Abstract;
using isnd.Data;
using isnd.Data.Catalog;
using isnd.Data.Packages;
using isnd.Entities;
using isnd.Interfaces;
using isnd.ViewModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using NuGet.Versioning;
using Unleash;
namespace isnd.Services
{
public class PackageManager : IPackageManager
{
public const string BASE_API_LEVEL = "3.0.0";
readonly ApplicationDbContext dbContext;
public PackageManager(ApplicationDbContext dbContext,
IOptions<IsndSettings> siteConfigOptionsOptions)
{
this.dbContext = dbContext;
isndSettings = siteConfigOptionsOptions.Value;
apiBase = isndSettings.ExternalUrl + Constants.ApiVersion;
}
public IEnumerable<Resource> GetResources(IUnleash unleashClient)
{
var res = new List<Resource>
{
new Resource(apiBase + ApiConfig.Package,
"PackagePublish/2.0.0")
{
Comment = "Package Publish service"
},
// under dev, only leash in release mode
new Resource(apiBase + ApiConfig.Package + "/{id}/{version}",
"PackageDetailsUriTemplate/5.1.0")
{
Comment = "URI template used by NuGet Client to construct details URL for packages"
},
new Resource(apiBase + ApiConfig.Nuget,
"PackageBaseAddress/3.0.0")
{
Comment = "Package Base Address service - " +
"Base URL of where NuGet packages are stored, in the format " +
"https://<host>/nupkg/{id-lower}/{version-lower}/{id-lower}.{version-lower}.nupkg"
},
new Resource(apiBase + ApiConfig.AutoComplete,
"SearchAutocompleteService/" + BASE_API_LEVEL)
{
Comment = "Auto complete service"
},
new Resource(apiBase + ApiConfig.Search,
"SearchQueryService/" + BASE_API_LEVEL)
{
Comment = "Search Query service"
},
new Resource(apiBase + ApiConfig.Registration,
"RegistrationsBaseUrl/Versioned")
{
Comment = "Base URL of storage where package registration info is stored. " +
"This base URL includes SemVer 2.0.0 packages."
}
};
// TODO ? RegistrationsBaseUrl RegistrationsBaseUrl/v* Catalog
return res;
}
public AutoCompleteResult AutoComplete(string id,
int skip, int take, bool prerelease = false,
string packageType = null)
{
var scope = dbContext.PackageVersions.Where(
v => v.PackageId == id
&& (prerelease || !v.IsPrerelease)
&& (packageType == null || v.Type == packageType)
)
.OrderBy(v => v.FullString);
return new AutoCompleteResult
{
totalHits = scope.Count(),
data = scope.Select(v => v.FullString)
.Skip(skip).Take(take).ToArray()
};
}
public string[] GetVersions(
string id,
NuGetVersion parsedVersion,
bool prerelease = false,
string packageType = null,
int skip = 0,
int take = 25)
{
return dbContext.PackageVersions.Where(
v => v.PackageId == id
&& (prerelease || !v.IsPrerelease)
&& (packageType == null || v.Type == packageType)
&& (parsedVersion.CompareTo
(new SemanticVersion(v.Major, v.Minor, v.Patch)) < 0)
)
.OrderBy(v => v.NugetVersion)
.Select(v => v.FullString)
.Skip(skip).Take(take).ToArray();
}
public string CatalogBaseUrl => apiBase;
private IsndSettings isndSettings;
private readonly string apiBase;
public virtual async Task<RegistrationPageIndex> GetCatalogIndexAsync()
{
return await ÛpdateCatalogForAsync(null);
}
public async Task<RegistrationPageIndex> ÛpdateCatalogForAsync
(Commit reason = null)
{
int i = 0;
string baseid = apiBase + ApiConfig.Catalog;
string bidreg = $"{apiBase}v3.4.0/{ApiConfig.Registration}";
RegistrationPageIndex index = new RegistrationPageIndex(baseid);
var scope = await dbContext.Commits.OrderBy(c => c.TimeStamp).ToArrayAsync();
i = isndSettings.CatalogPageLen;
foreach (var commit in scope)
{
var validPkgs = (await dbContext.Packages
.Include(po => po.Owner)
.Include(pkg => pkg.Versions)
.Include(pkg => pkg.LatestVersion)
.ToArrayAsync())
.GroupBy((q) => q.Id);
foreach (var pkgid in validPkgs)
{
RegistrationPage page = index.Items.FirstOrDefault
(p => p.GetPackageId() == pkgid.Key);
if (page == null)
{
page = new RegistrationPage(bidreg, pkgid.Key, apiBase);
index.Items.Add(page);
}
foreach (var pkgv in pkgid)
{
page.AddVersionRange(pkgv.Versions);
}
}
reason = commit;
i++;
}
if (reason != null)
{
index.CommitId = reason.CommitId;
index.CommitTimeStamp = reason.CommitTimeStamp;
}
else
{
// From a fresh db
index.CommitId = "none";
}
return index;
}
public async Task<PackageDeletionReport> DeletePackageAsync
(string pkgid, string version, string type)
{
// TODO deletion on disk
var commit = new Commit
{
Action = PackageAction.DeletePackage,
TimeStamp = DateTime.Now
};
dbContext.Commits.Add(commit);
var pkg = await dbContext.PackageVersions.SingleOrDefaultAsync(
v => v.PackageId == pkgid &&
v.FullString == version &&
v.Type == type
);
if (pkg == null)
{
return new PackageDeletionReport { Deleted = false };
}
dbContext.PackageVersions.Remove(pkg);
await dbContext.SaveChangesAsync();
await ÛpdateCatalogForAsync(commit);
return new PackageDeletionReport { Deleted = true, DeletedVersion = pkg };
}
public async Task<PackageVersion> GetPackageAsync
(string pkgid, string version, string type)
{
return await dbContext.PackageVersions.SingleOrDefaultAsync(
v => v.PackageId == pkgid &&
v.FullString == version &&
v.Type == type
);
}
public async Task<CatalogEntry> GetCatalogEntryAsync
(string pkgId, string semver = null, string pkgType = null)
{
return (await dbContext.PackageVersions
.Include(v => v.Package)
.Include(v => v.LatestCommit)
.Where(v => v.PackageId == pkgId
&& semver == v.SementicVersionString
&& (pkgType == null || pkgType == v.Type)).SingleOrDefaultAsync()).ToLeave(BID,
apiBase);
}
public async Task<PackageDeletionReport> UserAskForPackageDeletionAsync
(string uid, string id, string lower, string type)
{
PackageVersion packageVersion = await dbContext.PackageVersions
.Include(pv => pv.Package)
.FirstOrDefaultAsync(m => m.PackageId == id
&& m.FullString == lower && m.Type == type);
if (packageVersion == null) return null;
if (packageVersion.Package.OwnerId != uid) return null;
return new PackageDeletionReport { Deleted = true, DeletedVersion = packageVersion };
}
public string BID { get => $"{apiBase}v3.4.0/{ApiConfig.Registration}"; }
public IEnumerable<CatalogEntry> SearchCatalogEntriesById
(string pkgId, string semver, string pkgType)
{
return dbContext.PackageVersions
.Include(v => v.Package)
.Include(v => v.Package.Owner)
.Include(v => v.LatestCommit)
.Where(v => v.PackageId == pkgId && semver == v.FullString
&& (pkgType == null || pkgType == v.Type))
.OrderByDescending(p => p.CommitNId)
.Select(p => p.ToLeave(BID, apiBase))
;
}
public PackageVersion GetPackage(string pkgId, string semver, string pkgType)
{
return dbContext.PackageVersions
.Include(v => v.Package)
.Include(v => v.LatestCommit)
.Single(v => v.PackageId == pkgId && semver == v.FullString
&& (pkgType == null || pkgType == v.Type));
}
public async Task<RegistrationPageIndex> GetPackageRegistrationIndexAsync
(RegistrationPageIndexQuery query)
{
// RegistrationPageIndexAndQuery
if (string.IsNullOrWhiteSpace(query.Query)) return null;
query.Query = query.Query.ToLower();
var scope = await dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
.Where(p => p.Id.ToLower() == query.Query).Skip(query.Skip).Take(query.Take).ToListAsync();
string bid = $"{apiBase}v3.4.0/{ApiConfig.Registration}";
return
new RegistrationPageIndex(bid, query.Query, apiBase, scope);
}
public async Task<RegistrationPageIndex> SearchPackageAsync(RegistrationPageIndexQuery query)
{
string bid = $"{apiBase}v3.4.0/{ApiConfig.Registration}";
if (query.Query == null) query.Query = "";
var scope = (await dbContext.Packages.Include(p => p.Versions).Include(p => p.Owner)
.ToListAsync())
.Where(p => Matching(p, query))
;
var total = scope.Count();
var pkgs = scope.Skip(query.Skip).Take(query.Take);
return
new RegistrationPageIndex(bid, query.Query, apiBase, pkgs);
}
private static bool MatchingExact(Package p, RegistrationPageIndexQuery query)
{
return
p.Id == query.Query
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease));
}
private static bool Matching(Package p, RegistrationPageIndexQuery query)
{
return p.Id.StartsWith(query.Query)
&& (query.Prerelease || p.Versions.Any(v => !v.IsPrerelease));
}
}
}