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_host.Data; using nuget_host.Entities; namespace nuget_host.Controllers { [AllowAnonymous] public partial 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; } const string defaultSemVer = "2.0.0"; // dotnet add . package -s http://localhost:5000/packages nuget-cli // packages/FindPackagesById()?id='nuget-cli'&semVerLevel=2.0.0 // Search // GET {@id}?q={QUERY}&skip={SKIP}&take={TAKE}&prerelease={PRERELEASE}&semVerLevel={SEMVERLEVEL}&packageType={PACKAGETYPE} [HttpGet("~/search/index.json")] public IActionResult Index( string q, string semVerLevel = defaultSemVer, bool prerelease = false, string packageType = null, int skip = 0, int take = 25) { if (string.IsNullOrEmpty(q)) { ModelState.AddModelError("q", "no value"); return NotFound(ModelState); } else { var scope = dbContext.Packages .Include(p => p.Versions) .Where( p => (CamelCaseMatch(p.Id, q) || SeparatedByMinusMatch(p.Id, q)) && (prerelease || p.Versions.Any(v => !v.IsPrerelease)) && (packageType == null || p.Versions.Any(v => v.Type == packageType)) ); var result = new { totalHits = scope.Count(), data = scope.Skip(skip).Take(take).ToArray() }; return Ok(result); } } protected static bool CamelCaseMatch(string id, string q) { // Assert.False (q==null); string query = q; if (query.Length == 0) return false; while (id.Length > 0) { int i = 0; while (id.Length > i && char.IsLower(id[i])) i++; if (i == 0) break; id = id.Substring(i); if (id.StartsWith(q, System.StringComparison.OrdinalIgnoreCase)) return true; } return false; } protected static bool SeparatedByMinusMatch(string id, string q) { foreach (var part in id.Split('-')) { if (part.StartsWith(q, System.StringComparison.OrdinalIgnoreCase)) return true; } return false; } // GET /autocomplete?id=nuget.protocol&prerelease=true [HttpGet("~/autocomplete")] public IActionResult AutoComplete( string id, string semVerLevel = defaultSemVer, bool prerelease = false, string packageType = null, int skip = 0, int take = 25) { return Ok(new { data = dbContext.PackageVersions.Where( v => v.PackageId == id && (prerelease || !v.IsPrerelease) && (packageType == null || v.Type == packageType) ).Select(v => v.FullString) .Skip(skip).Take(take).ToArray() }); } } }