using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NuGet.Packaging.Core; using nuget_host.Data; using nuget_host.Entities; using nuget_host.Helpers; namespace nuget_host.Controllers { [AllowAnonymous] public class PackagesController : Controller { private readonly ILogger logger; private readonly IDataProtector protector; private readonly NugetSettings nugetSettings; ApplicationDbContext dbContext; public PackagesController( ILoggerFactory loggerFactory, IDataProtectionProvider provider, IOptions nugetOptions, ApplicationDbContext dbContext) { logger = loggerFactory.CreateLogger(); nugetSettings = nugetOptions.Value; protector = provider.CreateProtector(nugetSettings.ProtectionTitle); this.dbContext = dbContext; } [HttpPut("packages")] public async Task Put() { try { var clientVersionId = Request.Headers["X-NuGet-Client-Version"]; var apiKey = Request.Headers["X-NuGet-ApiKey"]; ViewData["versionId"] = typeof(PackagesController).Assembly.FullName; var files = new List(); ViewData["files"] = files; var clearkey = protector.Unprotect(apiKey); var apikey = dbContext.ApiKeys.SingleOrDefault(k => k.Id == clearkey); if (apikey == null) { logger.LogInformation("403 : no api-key"); return Unauthorized(); } foreach (var file in Request.Form.Files) { string initpath = Path.Combine(Environment.GetEnvironmentVariable("TEMP") ?? Environment.GetEnvironmentVariable("TMP") ?? "/tmp", $"nuget_host-{Guid.NewGuid()}.nupkg"); using (FileStream fw = new FileStream(initpath, FileMode.Create)) { file.CopyTo(fw); } using (FileStream fw = new FileStream(initpath, FileMode.Open)) { var archive = new ZipArchive(fw); foreach (var entry in archive.Entries) { if (entry.FullName.EndsWith(".nuspec")) { // var entry = archive.GetEntry(filename); var specstr = entry.Open(); NuGet.Packaging.Core.NuspecCoreReader reader = new NuspecCoreReader(specstr); string pkgdesc = reader.GetDescription(); string pkgid = reader.GetId(); var version = reader.GetVersion(); string pkgidpath = Path.Combine(nugetSettings.PackagesRootDir, pkgid); string pkgpath = Path.Combine(pkgidpath, version.Version.ToString()); string name = $"{pkgid}-{version}.nupkg"; string fullpath = Path.Combine(pkgpath, name); var source = new FileInfo(initpath); var dest = new FileInfo(fullpath); var destdir = new DirectoryInfo(dest.DirectoryName); if (dest.Exists) { ViewData["error"] = "existe déjà"; logger.LogInformation("400 : existe déjà"); return BadRequest(ViewData); } destdir.Create(); source.MoveTo(fullpath); files.Add(name); var newpkg = new Package { Id = pkgid, Description = pkgdesc, OwnerId = apikey.UserId }; dbContext.Packages.Add(newpkg); var newversion = new PackageVersion { Package = newpkg, Major = version.Major, Minor = version.Minor, Patch = version.Patch, IsPrerelease = version.IsPrerelease, FullString = version.ToFullString() }; dbContext.PackageVersions.Add(newversion); await dbContext.SaveChangesAsync(); logger.LogInformation($"new package : {entry.Name}"); } } } } return Ok(ViewData); } catch (Exception ex) { return new ObjectResult(new { ViewData, ex.Message, ex.StackTrace }) { StatusCode = 500 }; } } [HttpGet("packages/{spec}")] public IActionResult Index(string spec) { if (string.IsNullOrEmpty(spec)) { ViewData["warn"] = "no spec"; } else { ViewData["spec"] = spec; // TODO Assert valid sem ver spec var filelst = new DirectoryInfo(nugetSettings.PackagesRootDir); var fi = new FileInfo(spec); var lst = filelst.GetDirectories(spec); ViewData["lst"] = lst.Select(entry => entry.Name); } return Ok(ViewData); } [Authorize] [HttpGet("api/get-key/{*apikey}")] public IActionResult GetApiKey(string apiKey) { return Ok(protector.Protect(apiKey)); } } }