Permalink
Browse files

Merge branch 'dev'

  • Loading branch information...
2 parents 357edce + 0b7007b commit 392d3dbd58089b137b6ef41f0d9b4e83887c58a9 cristinamanum committed Jan 6, 2017
Showing with 1,363 additions and 575 deletions.
  1. +5 −0 src/NuGetGallery/Configuration/AppConfiguration.cs
  2. +5 −0 src/NuGetGallery/Configuration/IAppConfiguration.cs
  3. +19 −4 src/NuGetGallery/Controllers/ApiController.cs
  4. +14 −0 src/NuGetGallery/Controllers/ODataV1FeedController.cs
  5. +21 −0 src/NuGetGallery/Controllers/ODataV2FeedController.cs
  6. +12 −20 src/NuGetGallery/Controllers/PackagesController.cs
  7. +9 −0 src/NuGetGallery/NuGetGallery.csproj
  8. +10 −0 src/NuGetGallery/OData/QueryAllowed/Data/apiv1packages.json
  9. +7 −0 src/NuGetGallery/OData/QueryAllowed/Data/apiv1search.json
  10. +12 −0 src/NuGetGallery/OData/QueryAllowed/Data/apiv2getupdates.json
  11. +32 −0 src/NuGetGallery/OData/QueryAllowed/Data/apiv2packages.json
  12. +16 −0 src/NuGetGallery/OData/QueryAllowed/Data/apiv2search.json
  13. +104 −0 src/NuGetGallery/OData/QueryAllowed/ODataQueryFilter.cs
  14. +17 −0 src/NuGetGallery/OData/QueryAllowed/ODataQueryRequest.cs
  15. +144 −0 src/NuGetGallery/OData/QueryAllowed/ODataQueryVerifier.cs
  16. +10 −1 src/NuGetGallery/Strings.Designer.cs
  17. +4 −1 src/NuGetGallery/Strings.resx
  18. +11 −0 src/NuGetGallery/ViewModels/PackageListSearchViewModel.cs
  19. +536 −535 src/NuGetGallery/Web.config
  20. +11 −1 src/NuGetGallery/WebApi/PlainTextResult.cs
  21. +3 −0 tests/NuGetGallery.Core.Facts/Packaging/PackageIdValidatorTest.cs
  22. +58 −1 tests/NuGetGallery.Facts/Controllers/ApiControllerFacts.cs
  23. +58 −3 tests/NuGetGallery.Facts/Controllers/PackagesControllerFacts.cs
  24. +1 −0 tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj
  25. +55 −0 tests/NuGetGallery.Facts/OData/Filter/ODataFilterFacts.cs
  26. +156 −3 tests/NuGetGallery.Facts/Services/FeedServiceFacts.cs
  27. +1 −0 tests/NuGetGallery.Facts/TestUtils/Infrastructure/FeedServiceHelpers.cs
  28. +13 −6 tests/NuGetGallery.FunctionalTests.Core/Helpers/ODataHelper.cs
  29. +19 −0 tests/NuGetGallery.FunctionalTests/ODataFeeds/V2FeedTests.cs
@@ -210,5 +210,10 @@ public class AppConfiguration : IAppConfiguration
/// Gets a string containing the PagerDuty Service key.
/// </summary>
public string PagerDutyServiceKey { get; set; }
+
+ /// <summary>
+ /// Gets/sets a bool that indicates if the OData requests will be filtered.
+ /// </summary>
+ public bool IsODataFilterEnabled { get; set; }
}
}
@@ -196,5 +196,10 @@ public interface IAppConfiguration
/// </summary>
// ReSharper disable once InconsistentNaming
string PagerDutyServiceKey { get; set; }
+
+ /// <summary>
+ /// Gets/sets a bool that indicates if the OData requests will be filtered.
+ /// </summary>
+ bool IsODataFilterEnabled { get; set; }
}
}
@@ -254,17 +254,32 @@ public virtual Task<ActionResult> CreatePackagePost()
using (var packageToPush = new PackageArchiveReader(packageStream, leaveStreamOpen: false))
{
- NuspecReader nuspec = null;
try
{
- nuspec = packageToPush.GetNuspecReader();
+ PackageService.EnsureValid(packageToPush);
}
catch (Exception ex)
{
+ ex.Log();
+
+ var message = Strings.FailedToReadUploadFile;
+ if (ex is InvalidPackageException || ex is InvalidDataException || ex is EntityException)
+ {
+ message = ex.Message;
+ }
+
+ return new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, message);
+ }
+
+ NuspecReader nuspec;
+ var errors = ManifestValidator.Validate(packageToPush.GetNuspec(), out nuspec).ToArray();
+ if (errors.Length > 0)
+ {
+ var errorsString = string.Join("', '", errors.Select(error => error.ErrorMessage));
return new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, string.Format(
CultureInfo.CurrentCulture,
- Strings.UploadPackage_InvalidNuspec,
- ex.Message));
+ errors.Length > 1 ? Strings.UploadPackage_InvalidNuspecMultiple : Strings.UploadPackage_InvalidNuspec,
+ errorsString));
}
if (nuspec.GetMinClientVersion() > Constants.MaxSupportedMinClientVersion)
@@ -8,8 +8,10 @@
using System.Web.Http;
using System.Web.Http.OData;
using System.Web.Http.OData.Query;
+using System.Web.Http.Results;
using NuGetGallery.Configuration;
using NuGetGallery.OData;
+using NuGetGallery.OData.QueryFilter;
using NuGetGallery.WebApi;
using WebApi.OutputCache.V2;
@@ -42,6 +44,12 @@ public class ODataV1FeedController
[CacheOutput(NoCache = true)]
public IHttpActionResult Get(ODataQueryOptions<V1FeedPackage> options)
{
+ if (!ODataQueryVerifier.AreODataOptionsAllowed(options, ODataQueryVerifier.V1Packages,
+ _configurationService.Current.IsODataFilterEnabled, nameof(Get)))
+ {
+ return BadRequest(ODataQueryVerifier.GetValidationFailedMessage(options));
+ }
+
var queryable = _packagesRepository.GetAll()
.Where(p => !p.IsPrerelease && !p.Deleted)
.WithoutVersionSort()
@@ -198,6 +206,12 @@ public IHttpActionResult GetPropertyFromPackages(string propertyName, string id,
SearchAdaptor.GetNextLink(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);
@@ -9,11 +9,13 @@
using System.Web.Http;
using System.Web.Http.OData;
using System.Web.Http.OData.Query;
+using System.Web.Http.Results;
using NuGet.Frameworks;
using NuGet.Versioning;
using NuGetGallery.Configuration;
using NuGetGallery.Infrastructure.Lucene;
using NuGetGallery.OData;
+using NuGetGallery.OData.QueryFilter;
using NuGetGallery.OData.QueryInterceptors;
using NuGetGallery.WebApi;
using QueryInterceptor;
@@ -89,6 +91,13 @@ public class ODataV2FeedController
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);
return QueryResult(options, queryable, MaxPageSize);
}
@@ -257,6 +266,12 @@ public IHttpActionResult GetPropertyFromPackages(string propertyName, string id,
return null;
});
}
+ //Reject only when try to reach database.
+ if (!ODataQueryVerifier.AreODataOptionsAllowed(options, ODataQueryVerifier.V2Search,
+ _configurationService.Current.IsODataFilterEnabled, nameof(Search)))
+ {
+ return BadRequest(ODataQueryVerifier.GetValidationFailedMessage(options));
+ }
// If not, just let OData handle things
var queryable = query.ToV2FeedPackageQuery(GetSiteRoot(), _configurationService.Features.FriendlyLicenses);
@@ -293,6 +308,12 @@ public IHttpActionResult GetPropertyFromPackages(string propertyName, string id,
return Ok(Enumerable.Empty<V2FeedPackage>().AsQueryable());
}
+ if (!ODataQueryVerifier.AreODataOptionsAllowed(options, ODataQueryVerifier.V2GetUpdates,
+ _configurationService.Current.IsODataFilterEnabled, nameof(GetUpdates)))
+ {
+ return BadRequest(ODataQueryVerifier.GetValidationFailedMessage(options));
+ }
+
// Workaround https://github.com/NuGet/NuGetGallery/issues/674 for NuGet 2.1 client.
// Can probably eventually be retired (when nobody uses 2.1 anymore...)
// Note - it was URI un-escaping converting + to ' ', undoing that is actually a pretty conservative substitution because
@@ -230,28 +230,17 @@ public virtual ActionResult UploadPackageProgress()
_packageService.EnsureValid(packageArchiveReader);
}
- catch (InvalidPackageException ipex)
- {
- ipex.Log();
- ModelState.AddModelError(String.Empty, ipex.Message);
- return View();
- }
- catch (InvalidDataException idex)
- {
- idex.Log();
- ModelState.AddModelError(String.Empty, idex.Message);
- return View();
- }
- catch (EntityException enex)
- {
- enex.Log();
- ModelState.AddModelError(String.Empty, enex.Message);
- return View();
- }
catch (Exception ex)
{
ex.Log();
- ModelState.AddModelError(String.Empty, Strings.FailedToReadUploadFile);
+
+ var message = Strings.FailedToReadUploadFile;
+ if (ex is InvalidPackageException || ex is InvalidDataException || ex is EntityException)
+ {
+ message = ex.Message;
+ }
+
+ ModelState.AddModelError(String.Empty, message);
return View();
}
finally
@@ -385,8 +374,11 @@ public virtual ActionResult UploadPackageProgress()
return View(model);
}
- public virtual async Task<ActionResult> ListPackages(string q, int page = 1)
+ public virtual async Task<ActionResult> ListPackages(PackageListSearchViewModel searchAndListModel)
{
+ var page = searchAndListModel.Page;
+ var q = searchAndListModel.Q;
+
if (page < 1)
{
page = 1;
@@ -827,6 +827,9 @@
<Compile Include="OData\Conventions\EntitySetPropertyRoutingConvention.cs" />
<Compile Include="OData\ODataServiceVersionHeaderPropagatingBatchHandler.cs" />
<Compile Include="OData\QueryInterceptors\NormalizeVersionInterceptor.cs" />
+ <Compile Include="OData\QueryAllowed\ODataQueryFilter.cs" />
+ <Compile Include="OData\QueryAllowed\ODataQueryVerifier.cs" />
+ <Compile Include="OData\QueryAllowed\ODataQueryRequest.cs" />
<Compile Include="OData\SearchService\SearchAdaptorResult.cs" />
<Compile Include="OData\SearchService\SearchHijacker.cs" />
<Compile Include="Diagnostics\DiagnosticsService.cs" />
@@ -1405,6 +1408,7 @@
<Compile Include="Infrastructure\Authentication\LegacyHasher.cs" />
<Compile Include="Infrastructure\Authentication\V3Hasher.cs" />
<Compile Include="Services\ReflowPackageService.cs" />
+ <Compile Include="ViewModels\PackageListSearchViewModel.cs" />
<Compile Include="WebApi\PlainTextResult.cs" />
<Compile Include="WebApi\QueryResult.cs" />
<Compile Include="WebApi\QueryResultExtensions.cs" />
@@ -1639,6 +1643,11 @@
<Content Include="Scripts\d3.v3.min.js" />
<Content Include="Areas\Admin\Views\SupportRequest\Index.cshtml" />
<Content Include="Areas\Admin\Views\SupportRequest\Admins.cshtml" />
+ <EmbeddedResource Include="OData\QueryAllowed\Data\apiv1packages.json" />
+ <EmbeddedResource Include="OData\QueryAllowed\Data\apiv1search.json" />
+ <EmbeddedResource Include="OData\QueryAllowed\Data\apiv2getupdates.json" />
+ <EmbeddedResource Include="OData\QueryAllowed\Data\apiv2packages.json" />
+ <EmbeddedResource Include="OData\QueryAllowed\Data\apiv2search.json" />
<None Include="Scripts\jquery-1.11.0.intellisense.js" />
<Content Include="Scripts\jquery-1.11.0.js" />
<Content Include="Scripts\jquery-1.11.0.min.js" />
@@ -0,0 +1,10 @@
+{
+ "AllowedOperatorPatterns": [
+ "filter, orderby, top",
+ "filter, top",
+ "filter, orderby, skip, top",
+ "filter, select",
+ "top",
+ "filter, orderby"
+ ]
+}
@@ -0,0 +1,7 @@
+{
+ "AllowedOperatorPatterns": [
+ "filter, orderby, skip, top",
+ "filter, skip, top",
+ "filter, top"
+
+ ] }
@@ -0,0 +1,12 @@
+{
+ "AllowedOperatorPatterns": [
+ "orderby, top",
+ "filter, orderby, top",
+ "filter",
+ "orderby, skip, top",
+ "filter, skip, top",
+ "skip",
+ "skiptoken",
+ "filter, orderby, skip, top"
+ ]
+}
@@ -0,0 +1,32 @@
+{
+ "AllowedOperatorPatterns": [
+ "filter",
+ "filter, orderby, top",
+ "filter, top",
+ "filter, orderby, skip",
+ "filter, orderby",
+ "filter, orderby, select, top",
+ "filter, skip",
+ "filter, orderby, skip, top",
+ "skip",
+ "filter, format, orderby, select, skip, top",
+ "filter, select",
+ "orderby, top",
+ "filter, inlinecount, orderby, skip, top",
+ "filter, orderby, skiptoken, top",
+ "filter, format, select",
+ "orderby, skip",
+ "filter, skip, top",
+ "filter, inlinecount, orderby, select, skip, top",
+ "filter, orderby, select, skip, top",
+ "filter, orderby, select",
+ "filter, select, skip, top",
+ "filter, format, select, top",
+ "orderby, skip, top",
+ "top",
+ "filter, orderby, select, skip",
+ "orderby",
+ "skip, top",
+ "filter, select, top",
+ "filter, inlinecount, select, top"]
+}
@@ -0,0 +1,16 @@
+{
+ "AllowedOperatorPatterns": [
+ "filter, skip, top",
+ "filter, orderby, skip, top",
+ "top",
+ "filter, orderby",
+ "filter, orderby, skip",
+ "filter, top",
+ "filter, inlinecount, orderby, skip, top",
+ "orderby, skip, top",
+ "skip, top",
+ "filter, orderby, top",
+ "filter, inlinecount, orderby, select, skip, top",
+ "orderby, top"
+ ]
+}
Oops, something went wrong.

0 comments on commit 392d3db

Please sign in to comment.