private string GetHttpsSiteRoot() { var siteRoot = UrlExtensions.MakeSecure(_httpSiteRootThunk.Value); if (siteRoot.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || siteRoot.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { return(siteRoot); } throw new InvalidOperationException("The configured HTTP site root must start with http:// or https://."); }
protected static Uri BuildLinkForStreamProperty(string routePrefix, string id, string version, HttpRequestMessage request) { var url = new UrlHelper(request); var result = url.Route(routePrefix + RouteName.DownloadPackage, new { id, version }); var builder = new UriBuilder(UrlExtensions.MakeSecure(request.RequestUri)); builder.Path = version == null?EnsureTrailingSlash(result) : result; builder.Query = string.Empty; return(builder.Uri); }
private string GetHttpSiteRoot() { var siteRoot = Current.SiteRoot; if (siteRoot == null) { // No SiteRoot configured in settings. // Fallback to detected site root. var request = GetCurrentRequest(); siteRoot = UrlExtensions.MakeSecure(request.Url.GetLeftPart(UriPartial.Authority) + '/'); } if (!siteRoot.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !siteRoot.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("The configured site root must start with either http:// or https://."); } return(UrlExtensions.MakeSecure(siteRoot)); }
public static async Task <SearchAdaptorResult> FindByIdAndVersionCore( ISearchService searchService, HttpRequestBase request, IQueryable <Package> packages, string id, string version, CuratedFeed curatedFeed, string semVerLevel) { SearchFilter searchFilter; // We can only use Lucene if: // a) The Index contains all versions of each package // b) The sort order is something Lucene can handle if (TryReadSearchFilter(searchService.ContainsAllVersions, UrlExtensions.MakeSecure(request.RawUrl), searchService.ContainsAllVersions, out searchFilter) && !string.IsNullOrWhiteSpace(id)) { var normalizedRegistrationId = id.Normalize(NormalizationForm.FormC); var searchTerm = string.Format(CultureInfo.CurrentCulture, "Id:\"{0}\"", normalizedRegistrationId); if (!string.IsNullOrEmpty(version)) { searchTerm = string.Format(CultureInfo.CurrentCulture, "Id:\"{0}\" AND Version:\"{1}\"", normalizedRegistrationId, version); searchFilter.Take = 1; // only one result is needed in this case } searchFilter.SearchTerm = searchTerm; searchFilter.SemVerLevel = semVerLevel; searchFilter.IncludePrerelease = true; searchFilter.CuratedFeed = curatedFeed; searchFilter.SupportedFramework = null; searchFilter.IncludeAllVersions = true; var results = await GetRawResultsFromSearchService(searchService, searchFilter); return(new SearchAdaptorResult(true, results)); } return(new SearchAdaptorResult(false, packages)); }
public static async Task <SearchAdaptorResult> SearchCore( ISearchService searchService, HttpRequestBase request, IQueryable <Package> packages, string searchTerm, string targetFramework, bool includePrerelease, CuratedFeed curatedFeed, string semVerLevel) { SearchFilter searchFilter; // We can only use Lucene if: // a) We are looking for the latest version of a package OR the Index contains all versions of each package // b) The sort order is something Lucene can handle if (TryReadSearchFilter(searchService.ContainsAllVersions, UrlExtensions.MakeSecure(request.RawUrl), false, out searchFilter)) { searchFilter.SearchTerm = searchTerm; searchFilter.IncludePrerelease = includePrerelease; searchFilter.CuratedFeed = curatedFeed; searchFilter.SupportedFramework = targetFramework; searchFilter.SemVerLevel = semVerLevel; var results = await GetResultsFromSearchService(searchService, searchFilter); return(new SearchAdaptorResult(true, results)); } if (!includePrerelease) { packages = packages.Where(p => !p.IsPrerelease); } packages = packages.Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)); return(new SearchAdaptorResult(false, packages.Search(searchTerm))); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext == null) { throw new ArgumentNullException(nameof(filterContext)); } if (!filterContext.HttpContext.Request.IsAuthenticated) { throw new InvalidOperationException("Requires account confirmation attribute is only valid on authenticated actions."); } var controller = ((AppController)filterContext.Controller); var user = controller.GetCurrentUser(); if (!user.Confirmed) { controller.TempData["ConfirmationRequiredMessage"] = string.Format( CultureInfo.CurrentCulture, "Before you can {0} you must first confirm your email address.", _inOrderTo); controller.HttpContext.SetConfirmationReturnUrl(UrlExtensions.MakeSecure(controller.Url.RequestContext.HttpContext.Request.RawUrl)); filterContext.Result = new RedirectResult(controller.Url.ConfirmationRequired(relativeUrl: false)); } }
public async Task <IHttpActionResult> Search( ODataQueryOptions <V2FeedPackage> options, string curatedFeedName, [FromODataUri] string searchTerm = "", [FromODataUri] string targetFramework = "", [FromODataUri] bool includePrerelease = false, [FromUri] string semVerLevel = null) { if (!_entities.CuratedFeeds.Any(cf => cf.Name == curatedFeedName)) { return(NotFound()); } // Handle OData-style |-separated list of frameworks. string[] targetFrameworkList = (targetFramework ?? "").Split(new[] { '\'', '|' }, StringSplitOptions.RemoveEmptyEntries); // For now, we'll just filter on the first one. if (targetFrameworkList.Length > 0) { // Until we support multiple frameworks, we need to prefer aspnet50 over aspnetcore50. if (targetFrameworkList.Contains("aspnet50")) { targetFramework = "aspnet50"; } else { targetFramework = targetFrameworkList[0]; } } // Perform actual search var curatedFeed = _curatedFeedService.GetFeedByName(curatedFeedName, includePackages: false); var packages = _curatedFeedService.GetPackages(curatedFeedName) .Where(p => p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)) .OrderBy(p => p.PackageRegistration.Id).ThenBy(p => p.Version); // todo: search hijack should take queryOptions instead of manually parsing query options var searchAdaptorResult = await SearchAdaptor.SearchCore( _searchService, GetTraditionalHttpContext().Request, packages, searchTerm, targetFramework, includePrerelease, curatedFeed : curatedFeed, semVerLevel : semVerLevel); // Packages provided by search service (even when not hijacked) var query = searchAdaptorResult.Packages; var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = query.LongCount(); var pagedQueryable = query .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => { // The nuget.exe 2.x list command does not like the next link at the bottom when a $top is passed. // Strip it of for backward compatibility. if (o.Top == null || (resultCount.HasValue && o.Top.Value >= resultCount.Value)) { return SearchAdaptor.GetNextLink( UrlExtensions.MakeSecure(Request.RequestUri), resultCount, new { searchTerm, targetFramework, includePrerelease }, o, s); } return null; })); } // If not, just let OData handle things var queryable = query.ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(QueryResult(options, queryable, MaxPageSize)); }
private async Task <IHttpActionResult> GetCore( ODataQueryOptions <V2FeedPackage> options, string curatedFeedName, string id, string normalizedVersion, bool return404NotFoundWhenNoResults, string semVerLevel) { var curatedFeed = _entities.CuratedFeeds.FirstOrDefault(cf => cf.Name == curatedFeedName); if (curatedFeed == null) { return(NotFound()); } var packages = _curatedFeedService .GetPackages(curatedFeedName) .Where(p => p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)) .Where(p => p.PackageRegistration.Id.Equals(id, StringComparison.OrdinalIgnoreCase)); if (!string.IsNullOrEmpty(normalizedVersion)) { packages = packages.Where(p => p.NormalizedVersion == normalizedVersion); } var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel); // try the search service try { var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( _searchService, GetTraditionalHttpContext().Request, packages, id, normalizedVersion, curatedFeed : curatedFeed, semVerLevel : semVerLevel); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); if (return404NotFoundWhenNoResults && totalHits == 0) { return(NotFound()); } var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV2FeedPackageQuery(UrlExtensions.MakeSecure(GetSiteRoot()), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(UrlExtensions.MakeSecure(Request.RequestUri), resultCount, new { id }, o, s))); } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } if (return404NotFoundWhenNoResults && !packages.Any()) { return(NotFound()); } var queryable = packages.ToV2FeedPackageQuery( UrlExtensions.MakeSecure(GetSiteRoot()), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(QueryResult(options, queryable, MaxPageSize)); }
public async Task <IHttpActionResult> Get( ODataQueryOptions <V2FeedPackage> options, [FromUri] string semVerLevel = null) { // Setup the search var packages = _packagesRepository.GetAll() .Where(p => p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsPackageCompliantWithSemVerLevelPredicate(semVerLevel)) .WithoutSortOnColumn(Version) .WithoutSortOnColumn(Id, ShouldIgnoreOrderById(options)) .InterceptWith(new NormalizeVersionInterceptor()); var semVerLevelKey = SemVerLevelKey.ForSemVerLevel(semVerLevel); // Try the search service try { HijackableQueryParameters hijackableQueryParameters = null; if (_searchService is ExternalSearchService && SearchHijacker.IsHijackable(options, out hijackableQueryParameters)) { var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( _searchService, GetTraditionalHttpContext().Request, packages, hijackableQueryParameters.Id, hijackableQueryParameters.Version, curatedFeed : null, semVerLevel : semVerLevel); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(UrlExtensions.MakeSecure(Request.RequestUri), resultCount, null, o, s))); } } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } // Reject only when try to reach database. if (!ODataQueryVerifier.AreODataOptionsAllowed(options, ODataQueryVerifier.V2Packages, _configurationService.Current.IsODataFilterEnabled, nameof(Get))) { return(BadRequest(ODataQueryVerifier.GetValidationFailedMessage(options))); } var queryable = packages.ToV2FeedPackageQuery( GetSiteRoot(), _configurationService.Features.FriendlyLicenses, semVerLevelKey); return(QueryResult(options, queryable, MaxPageSize)); }
private async Task <IHttpActionResult> GetCore(ODataQueryOptions <V1FeedPackage> options, string id, string version, bool return404NotFoundWhenNoResults) { var packages = _packagesRepository.GetAll() .Include(p => p.PackageRegistration) .Where(p => p.PackageRegistration.Id.Equals(id, StringComparison.OrdinalIgnoreCase) && !p.IsPrerelease && p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsUnknownPredicate()); if (!string.IsNullOrEmpty(version)) { packages = packages.Where(p => p.Version == version); } // try the search service try { var searchAdaptorResult = await SearchAdaptor.FindByIdAndVersionCore( _searchService, GetTraditionalHttpContext().Request, packages, id, version, curatedFeed : null, semVerLevel : null); // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { // Packages provided by search service packages = searchAdaptorResult.Packages; // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = packages.LongCount(); if (return404NotFoundWhenNoResults && totalHits == 0) { return(NotFound()); } var pagedQueryable = packages .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV1FeedPackageQuery(GetSiteRoot()); return(QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(UrlExtensions.MakeSecure(Request.RequestUri), resultCount, new { id }, o, s))); } } catch (Exception ex) { // Swallowing Exception intentionally. If *anything* goes wrong in search, just fall back to the database. // We don't want to break package restores. We do want to know if this happens, so here goes: QuietLog.LogHandledException(ex); } if (return404NotFoundWhenNoResults && !packages.Any()) { return(NotFound()); } var queryable = packages.ToV1FeedPackageQuery(GetSiteRoot()); return(QueryResult(options, queryable, MaxPageSize)); }
public async Task <IHttpActionResult> Search( ODataQueryOptions <V1FeedPackage> options, [FromODataUri] string searchTerm = "", [FromODataUri] string targetFramework = "") { // Handle OData-style |-separated list of frameworks. string[] targetFrameworkList = (targetFramework ?? "").Split(new[] { '\'', '|' }, StringSplitOptions.RemoveEmptyEntries); // For now, we'll just filter on the first one. if (targetFrameworkList.Length > 0) { // Until we support multiple frameworks, we need to prefer aspnet50 over aspnetcore50. if (targetFrameworkList.Contains("aspnet50")) { targetFramework = "aspnet50"; } else { targetFramework = targetFrameworkList[0]; } } // Perform actual search var packages = _packagesRepository.GetAll() .Include(p => p.PackageRegistration) .Include(p => p.PackageRegistration.Owners) .Where(p => p.Listed && !p.IsPrerelease && p.PackageStatusKey == PackageStatus.Available) .Where(SemVerLevelKey.IsUnknownPredicate()) .OrderBy(p => p.PackageRegistration.Id).ThenBy(p => p.Version) .AsNoTracking(); // todo: search hijack should take queryOptions instead of manually parsing query options var searchAdaptorResult = await SearchAdaptor.SearchCore( _searchService, GetTraditionalHttpContext().Request, packages, searchTerm, targetFramework, false, curatedFeed : null, semVerLevel : null); // Packages provided by search service (even when not hijacked) var query = searchAdaptorResult.Packages; // If intercepted, create a paged queryresult if (searchAdaptorResult.ResultsAreProvidedBySearchService) { // Add explicit Take() needed to limit search hijack result set size if $top is specified var totalHits = query.LongCount(); var pagedQueryable = query .Take(options.Top != null ? Math.Min(options.Top.Value, MaxPageSize) : MaxPageSize) .ToV1FeedPackageQuery(GetSiteRoot()); return(QueryResult(options, pagedQueryable, MaxPageSize, totalHits, (o, s, resultCount) => SearchAdaptor.GetNextLink(UrlExtensions.MakeSecure(Request.RequestUri), resultCount, new { searchTerm, targetFramework }, o, s))); } if (!ODataQueryVerifier.AreODataOptionsAllowed(options, ODataQueryVerifier.V1Search, _configurationService.Current.IsODataFilterEnabled, nameof(Search))) { return(BadRequest(ODataQueryVerifier.GetValidationFailedMessage(options))); } // If not, just let OData handle things var queryable = query.ToV1FeedPackageQuery(GetSiteRoot()); return(QueryResult(options, queryable, MaxPageSize)); }