Permalink
Browse files

Merge pull request #4672 from NuGet/dev

[ReleasePrep][2017.09.11]RI of dev into master
  • Loading branch information...
2 parents 9eb4bc4 + 79cae74 commit 1da0ddecdae6536bdc964baa0326aa384b0f0a9f @scottbommarito scottbommarito committed Sep 13, 2017
Showing with 3,026 additions and 951 deletions.
  1. +0 −1 src/Bootstrap/dist/css/bootstrap-theme.css
  2. +1 −2 src/Bootstrap/less/theme/common-list-packages.less
  3. +27 −0 src/NuGetGallery/App_Code/ViewHelpers.cshtml
  4. +7 −0 src/NuGetGallery/App_Start/DefaultDependenciesModule.cs
  5. +7 −10 src/NuGetGallery/Configuration/ConfigurationService.cs
  6. +0 −1 src/NuGetGallery/Content/gallery/css/bootstrap-theme.css
  7. +50 −30 src/NuGetGallery/Controllers/ApiController.cs
  8. +6 −2 src/NuGetGallery/Controllers/AppController.cs
  9. +2 −4 src/NuGetGallery/Controllers/AuthenticationController.cs
  10. +1 −1 src/NuGetGallery/Controllers/JsonApiController.cs
  11. +73 −46 src/NuGetGallery/Controllers/PackagesController.cs
  12. +6 −0 src/NuGetGallery/Infrastructure/AddPackageLicenseReport2.Down.sql
  13. +133 −0 src/NuGetGallery/Infrastructure/AddPackageLicenseReport2.Up.sql
  14. +29 −0 src/NuGetGallery/Migrations/201709072246362_AddPackageLicenseReport2Sproc.Designer.cs
  15. +13 −0 src/NuGetGallery/Migrations/201709072246362_AddPackageLicenseReport2Sproc.cs
  16. +126 −0 src/NuGetGallery/Migrations/201709072246362_AddPackageLicenseReport2Sproc.resx
  17. +33 −9 src/NuGetGallery/Migrations/SqlResourceMigration.cs
  18. +11 −0 src/NuGetGallery/NuGetGallery.csproj
  19. +8 −3 src/NuGetGallery/Services/CloudBlobWrapper.cs
  20. +0 −33 src/NuGetGallery/Services/FormsAuthenticationService.cs
  21. +0 −2 src/NuGetGallery/Services/IFormsAuthenticationService.cs
  22. +2 −1 src/NuGetGallery/Services/IPackageService.cs
  23. +14 −0 src/NuGetGallery/Services/IPackageUploadService.cs
  24. +19 −0 src/NuGetGallery/Services/IReservedNamespaceService.cs
  25. +5 −4 src/NuGetGallery/Services/PackageService.cs
  26. +47 −0 src/NuGetGallery/Services/PackageUploadService.cs
  27. +5 −3 src/NuGetGallery/Services/ReportPackageRequest.cs
  28. +60 −8 src/NuGetGallery/Services/ReservedNamespaceService.cs
  29. +9 −0 src/NuGetGallery/Strings.Designer.cs
  30. +3 −0 src/NuGetGallery/Strings.resx
  31. +485 −83 src/NuGetGallery/UrlExtensions.cs
  32. +10 −1 src/NuGetGallery/ViewModels/PackageViewModel.cs
  33. +1 −1 src/NuGetGallery/Views/Authentication/Register.cshtml
  34. +1 −1 src/NuGetGallery/Views/Authentication/SignIn.cshtml
  35. +1 −1 src/NuGetGallery/Views/Authentication/_Register.cshtml
  36. +1 −1 src/NuGetGallery/Views/CuratedFeeds/CuratedFeed.cshtml
  37. +1 −1 src/NuGetGallery/Views/Packages/Delete.cshtml
  38. +15 −11 src/NuGetGallery/Views/Packages/DisplayPackage.cshtml
  39. +4 −4 src/NuGetGallery/Views/Packages/ManagePackageOwners.cshtml
  40. +1 −1 src/NuGetGallery/Views/Packages/ReportAbuse.cshtml
  41. +4 −4 src/NuGetGallery/Views/Packages/UploadPackage.cshtml
  42. +2 −2 src/NuGetGallery/Views/Shared/Gallery/Header.cshtml
  43. +3 −3 src/NuGetGallery/Views/Shared/LayoutFooter.cshtml
  44. +14 −0 src/NuGetGallery/Views/Shared/ListPackages.cshtml
  45. +3 −3 src/NuGetGallery/Views/Shared/SiteMenu.cshtml
  46. +1 −1 src/NuGetGallery/Views/Shared/UserDisplay.cshtml
  47. +1 −1 src/NuGetGallery/Views/Statistics/PackageDownloadsByVersion.cshtml
  48. +1 −1 src/NuGetGallery/Views/Statistics/PackageDownloadsDetail.cshtml
  49. +1 −1 src/NuGetGallery/Views/Users/Account.cshtml
  50. +1 −1 src/NuGetGallery/Views/Users/_UserPackagesList.cshtml
  51. +3 −18 tests/NuGetGallery.Facts/App_Start/ConfigurationServiceFacts.cs
  52. +15 −15 tests/NuGetGallery.Facts/Authentication/AuthenticationServiceFacts.cs
  53. +9 −7 tests/NuGetGallery.Facts/Authentication/AuthenticatorFacts.cs
  54. +1 −1 tests/NuGetGallery.Facts/Authentication/Providers/ApiKey/ApiKeyAuthenticationHandlerFacts.cs
  55. +231 −91 tests/NuGetGallery.Facts/Controllers/ApiControllerFacts.cs
  56. +30 −2 tests/NuGetGallery.Facts/Controllers/AppControllerFacts.cs
  57. +42 −50 tests/NuGetGallery.Facts/Controllers/AuthenticationControllerFacts.cs
  58. +5 −4 tests/NuGetGallery.Facts/Controllers/CuratedFeedsControllerFacts.cs
  59. +7 −10 tests/NuGetGallery.Facts/Controllers/JsonApiControllerFacts.cs
  60. +354 −113 tests/NuGetGallery.Facts/Controllers/PackagesControllerFacts.cs
  61. +5 −6 tests/NuGetGallery.Facts/Controllers/StatisticsControllerFacts.cs
  62. +13 −15 tests/NuGetGallery.Facts/Controllers/UsersControllerFacts.cs
  63. +8 −4 tests/NuGetGallery.Facts/Filters/RequiresAccountConfirmationAttributeFacts.cs
  64. +1 −1 tests/NuGetGallery.Facts/Framework/Fakes.cs
  65. +13 −7 tests/NuGetGallery.Facts/Framework/TestContainer.cs
  66. +2 −1 tests/NuGetGallery.Facts/Framework/TestGalleryConfigurationService.cs
  67. +22 −2 tests/NuGetGallery.Facts/Framework/UnitTestBindings.cs
  68. +3 −0 tests/NuGetGallery.Facts/NuGetGallery.Facts.csproj
  69. +125 −83 tests/NuGetGallery.Facts/Services/MessageServiceFacts.cs
  70. +79 −152 tests/NuGetGallery.Facts/Services/PackageServiceFacts.cs
  71. +142 −0 tests/NuGetGallery.Facts/Services/PackageUploadServiceFacts.cs
  72. +250 −73 tests/NuGetGallery.Facts/Services/ReservedNamespaceServiceFacts.cs
  73. +50 −0 tests/NuGetGallery.Facts/TestUtils/TestDataUtility.cs
  74. +113 −1 tests/NuGetGallery.Facts/TestUtils/TestServiceUtility.cs
  75. +18 −5 tests/NuGetGallery.Facts/TestUtils/TestUtility.cs
  76. +8 −7 tests/NuGetGallery.Facts/ViewModels/DisplayPackageViewModelFacts.cs
  77. +16 −1 tests/NuGetGallery.Facts/ViewModels/ListPackageItemViewModelFacts.cs
  78. +112 −0 tests/NuGetGallery.Facts/ViewModels/PackageViewModelFacts.cs
  79. +101 −0 tests/NuGetGallery.Facts/Views/UrlHelperFacts.cs
@@ -374,7 +374,6 @@ img.package-icon {
}
}
.pager {
- float: right;
margin-top: 75px;
margin-bottom: 0;
}
@@ -66,5 +66,4 @@
.pager {
margin-top: 75px;
margin-bottom: 0px;
- float: right;
-}
+}
@@ -61,6 +61,33 @@
@Alert(htmlContent, "danger", "ErrorBadge", isAlertRole)
}
+@helper AlertIsSemVer2Package(bool hasSemVer2Version, bool hasSemVer2Dependency)
+{
+ string warningHeader = null;
+ if (hasSemVer2Version)
+ {
+ warningHeader = "This package has a SemVer 2.0.0 package version.";
+ }
+ else if (hasSemVer2Dependency)
+ {
+ warningHeader = "This package is considered a SemVer 2.0.0 package as it has a package dependency on SemVer 2.0.0 package(s).";
+ }
+
+ if (warningHeader != null)
+ {
+ @AlertWarning(
+ @<text>
+ @warningHeader<br />
+ <em>
+ This package will only be available to download with SemVer 2.0.0 compatible NuGet clients, such as Visual
+ Studio 2017 (version 15.3) and above or NuGet client 4.3.0 and above.
+ <a href="https://go.microsoft.com/fwlink/?linkid=852248" alt="Read more">Read more</a><br />
+ </em>
+ </text>
+ )
+ }
+}
+
@helper ErrorPage(UrlHelper url, System.Web.Mvc.HtmlHelper html, string errorNumber, string errorName, Func<MvcHtmlString, HelperResult> errorTextMain, Func<MvcHtmlString, HelperResult> errorTextSub = null)
{
<section role="main" class="container main-container">
@@ -44,6 +44,8 @@ protected override void Load(ContainerBuilder builder)
var configuration = new ConfigurationService(new SecretReaderFactory(diagnosticsService));
+ UrlExtensions.SetConfigurationService(configuration);
+
builder.RegisterInstance(configuration)
.AsSelf()
.As<PoliteCaptcha.IConfigurationSource>();
@@ -196,6 +198,11 @@ protected override void Load(ContainerBuilder builder)
.As<IReservedNamespaceService>()
.InstancePerLifetimeScope();
+ builder.RegisterType<PackageUploadService>()
+ .AsSelf()
+ .As<IPackageUploadService>()
+ .InstancePerLifetimeScope();
+
builder.RegisterType<SecurePushSubscription>()
.SingleInstance();
@@ -122,7 +122,7 @@ public string GetSiteRoot(bool useHttps)
}
return instance;
}
-
+
public async Task<string> ReadSetting(string settingName)
{
string value;
@@ -152,7 +152,6 @@ protected virtual HttpRequestBase GetCurrentRequest()
return new HttpRequestWrapper(HttpContext.Current.Request);
}
-
private ISecretInjector InitSecretInjector()
{
return _secretReaderFactory.CreateSecretInjector(_secretReaderFactory.CreateSecretReader(new ConfigurationService(new EmptySecretReaderFactory())));
@@ -210,20 +209,18 @@ protected virtual ConnectionStringSettings GetConnectionString(string settingNam
{
return WebConfigurationManager.ConnectionStrings[settingName];
}
-
+
private string GetHttpSiteRoot()
{
- var request = GetCurrentRequest();
- string siteRoot;
+ var siteRoot = Current.SiteRoot;
- if (request.IsLocal)
+ if (siteRoot == null)
{
+ // No SiteRoot configured in settings.
+ // Fallback to detected site root.
+ var request = GetCurrentRequest();
siteRoot = request.Url.GetLeftPart(UriPartial.Authority) + '/';
}
- else
- {
- siteRoot = Current.SiteRoot;
- }
if (!siteRoot.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
&& !siteRoot.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
@@ -374,7 +374,6 @@ img.package-icon {
}
}
.pager {
- float: right;
margin-top: 75px;
margin-bottom: 0;
}
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
@@ -49,6 +50,8 @@ public partial class ApiController
public AuthenticationService AuthenticationService { get; set; }
public ICredentialBuilder CredentialBuilder { get; set; }
protected ISecurityPolicyService SecurityPolicyService { get; set; }
+ public IReservedNamespaceService ReservedNamespaceService { get; set; }
+ public IPackageUploadService PackageUploadService { get; set; }
protected ApiController()
{
@@ -72,7 +75,9 @@ protected ApiController()
ITelemetryService telemetryService,
AuthenticationService authenticationService,
ICredentialBuilder credentialBuilder,
- ISecurityPolicyService securityPolicies)
+ ISecurityPolicyService securityPolicies,
+ IReservedNamespaceService reservedNamespaceService,
+ IPackageUploadService packageUploadService)
{
EntitiesContext = entitiesContext;
PackageService = packageService;
@@ -91,6 +96,8 @@ protected ApiController()
AuthenticationService = authenticationService;
CredentialBuilder = credentialBuilder;
SecurityPolicyService = securityPolicies;
+ ReservedNamespaceService = reservedNamespaceService;
+ PackageUploadService = packageUploadService;
StatisticsService = null;
}
@@ -112,10 +119,13 @@ protected ApiController()
ITelemetryService telemetryService,
AuthenticationService authenticationService,
ICredentialBuilder credentialBuilder,
- ISecurityPolicyService securityPolicies)
+ ISecurityPolicyService securityPolicies,
+ IReservedNamespaceService reservedNamespaceService,
+ IPackageUploadService packageUploadService)
: this(entitiesContext, packageService, packageFileService, userService, nugetExeDownloaderService, contentService,
indexingService, searchService, autoCuratePackage, statusService, messageService, auditingService,
- configurationService, telemetryService, authenticationService, credentialBuilder, securityPolicies)
+ configurationService, telemetryService, authenticationService, credentialBuilder, securityPolicies,
+ reservedNamespaceService, packageUploadService)
{
StatisticsService = statisticsService;
}
@@ -151,14 +161,14 @@ protected ApiController()
try
{
var package = PackageService.FindPackageByIdAndVersion(
- id,
- version,
- SemVerLevelKey.SemVer2,
+ id,
+ version,
+ SemVerLevelKey.SemVer2,
allowPrerelease: false);
if (package == null)
{
- return new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version));
+ return new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version));
}
version = package.NormalizedVersion;
@@ -174,7 +184,7 @@ protected ApiController()
{
QuietLog.LogHandledException(e);
- // Database was unavailable and we don't have a version, return a 503
+ // Database was unavailable and we don't have a version, return a 503
return new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion);
}
}
@@ -261,7 +271,7 @@ public ActionResult HealthProbe()
{
await AuthenticationService.RemoveCredential(user, credential);
}
-
+
TelemetryService.TrackVerifyPackageKeyEvent(id, version, user, User.Identity, result?.StatusCode ?? 200);
return (ActionResult)result ?? new EmptyResult();
@@ -285,7 +295,7 @@ public ActionResult HealthProbe()
{
return new HttpStatusCodeWithBodyResult(HttpStatusCode.Forbidden, Strings.ApiKeyNotAuthorized);
}
-
+
if (CredentialTypes.IsPackageVerificationApiKey(credential.Type))
{
// Secure path: verify that verification key matches package scope.
@@ -370,7 +380,7 @@ public virtual Task<ActionResult> CreatePackagePost()
{
message = ex.Message;
}
-
+
return new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, message);
}
@@ -394,17 +404,26 @@ public virtual Task<ActionResult> CreatePackagePost()
}
// Ensure that the user can push packages for this partialId.
- var packageRegistration = PackageService.FindPackageRegistrationById(nuspec.GetId());
+ var id = nuspec.GetId();
+ var packageRegistration = PackageService.FindPackageRegistrationById(id);
+ IReadOnlyCollection<ReservedNamespace> userOwnedNamespaces = null;
if (packageRegistration == null)
{
// Check if API key allows pushing a new package id
if (!ApiKeyScopeAllows(
- subject: nuspec.GetId(),
+ subject: id,
requestedActions: NuGetScopes.PackagePush))
{
// User cannot push a new package ID as the API key scope does not allow it
return new HttpStatusCodeWithBodyResult(HttpStatusCode.Unauthorized, Strings.ApiKeyNotAuthorized);
}
+
+ // For a new package id verify that the user is allowed to push to the matching namespaces, if any.
+ var isPushAllowed = ReservedNamespaceService.IsPushAllowed(id, user, out userOwnedNamespaces);
+ if (!isPushAllowed)
+ {
+ return new HttpStatusCodeWithBodyResult(HttpStatusCode.Conflict, Strings.UploadPackage_IdNamespaceConflict);
+ }
}
else
{
@@ -414,20 +433,20 @@ public virtual Task<ActionResult> CreatePackagePost()
// Audit that a non-owner tried to push the package
await AuditingService.SaveAuditRecordAsync(
new FailedAuthenticatedOperationAuditRecord(
- user.Username,
- AuditedAuthenticatedOperationAction.PackagePushAttemptByNonOwner,
+ user.Username,
+ AuditedAuthenticatedOperationAction.PackagePushAttemptByNonOwner,
attemptedPackage: new AuditedPackageIdentifier(
- nuspec.GetId(), nuspec.GetVersion().ToNormalizedStringSafe())));
+ id, nuspec.GetVersion().ToNormalizedStringSafe())));
// User cannot push a package to an ID owned by another user.
return new HttpStatusCodeWithBodyResult(HttpStatusCode.Conflict,
string.Format(CultureInfo.CurrentCulture, Strings.PackageIdNotAvailable,
- nuspec.GetId()));
+ id));
}
// Check if API key allows pushing the current package id
if (!ApiKeyScopeAllows(
- packageRegistration.Id,
+ packageRegistration.Id,
NuGetScopes.PackagePushVersion, NuGetScopes.PackagePush))
{
// User cannot push a package as the API key scope does not allow it
@@ -448,7 +467,7 @@ public virtual Task<ActionResult> CreatePackagePost()
return new HttpStatusCodeWithBodyResult(
HttpStatusCode.Conflict,
string.Format(CultureInfo.CurrentCulture, Strings.PackageExistsAndCannotBeModified,
- nuspec.GetId(), nuspec.GetVersion().ToNormalizedStringSafe()));
+ id, nuspec.GetVersion().ToNormalizedStringSafe()));
}
}
@@ -459,8 +478,9 @@ public virtual Task<ActionResult> CreatePackagePost()
Size = packageStream.Length
};
- var package = await PackageService.CreatePackageAsync(
- packageToPush,
+ var package = await PackageUploadService.GeneratePackageAsync(
+ id,
+ packageToPush,
packageStreamMetadata,
user,
commitChanges: false);
@@ -495,16 +515,16 @@ public virtual Task<ActionResult> CreatePackagePost()
}
IndexingService.UpdatePackage(package);
-
+
// Write an audit record
await AuditingService.SaveAuditRecordAsync(
new PackageAuditRecord(package, AuditedPackageAction.Create, PackageCreatedVia.Api));
// Notify user of push
MessageService.SendPackageAddedNotice(package,
- Url.Action("DisplayPackage", "Packages", routeValues: new { id = package.PackageRegistration.Id, version = package.NormalizedVersion }, protocol: Request.Url.Scheme),
- Url.Action("ReportMyPackage", "Packages", routeValues: new { id = package.PackageRegistration.Id, version = package.NormalizedVersion }, protocol: Request.Url.Scheme),
- Url.Action("Account", "Users", routeValues: null, protocol: Request.Url.Scheme));
+ Url.Package(package.PackageRegistration.Id, package.NormalizedVersion, Request.Url.Scheme),
+ Url.ReportPackage(package.PackageRegistration.Id, package.NormalizedVersion, Request.Url.Scheme),
+ Url.AccountSettings(Request.Url.Scheme));
TelemetryService.TrackPackagePushEvent(package, user, User.Identity);
@@ -570,7 +590,7 @@ private static ActionResult BadRequestForExceptionMessage(Exception ex)
// Check if API key allows listing/unlisting the current package id
if (!ApiKeyScopeAllows(
- subject: id,
+ subject: id,
requestedActions: NuGetScopes.PackageUnlist))
{
return new HttpStatusCodeWithBodyResult(HttpStatusCode.Forbidden, Strings.ApiKeyNotAuthorized);
@@ -602,7 +622,7 @@ private static ActionResult BadRequestForExceptionMessage(Exception ex)
// Check if API key allows listing/unlisting the current package id
if (!ApiKeyScopeAllows(
- subject: id,
+ subject: id,
requestedActions: NuGetScopes.PackageUnlist))
{
return new HttpStatusCodeWithBodyResult(HttpStatusCode.Forbidden, Strings.ApiKeyNotAuthorized);
@@ -657,7 +677,7 @@ protected internal virtual Stream ReadPackageFromRequest()
[HttpGet]
[ActionName("PackageIDs")]
public virtual async Task<ActionResult> GetPackageIds(
- string partialId,
+ string partialId,
bool? includePrerelease,
string semVerLevel = null)
{
@@ -672,7 +692,7 @@ protected internal virtual Stream ReadPackageFromRequest()
[HttpGet]
[ActionName("PackageVersions")]
public virtual async Task<ActionResult> GetPackageVersions(
- string id,
+ string id,
bool? includePrerelease,
string semVerLevel = null)
{
@@ -701,7 +721,7 @@ protected internal virtual Stream ReadPackageFromRequest()
item.Add("PackageId", row.PackageId);
item.Add("PackageVersion", row.PackageVersion);
- item.Add("Gallery", Url.PackageGallery(row.PackageId, row.PackageVersion));
+ item.Add("Gallery", Url.Package(row.PackageId, row.PackageVersion));
item.Add("PackageTitle", row.PackageTitle ?? row.PackageId);
item.Add("PackageDescription", row.PackageDescription);
item.Add("PackageIconUrl", row.PackageIconUrl ?? Url.PackageDefaultIcon());
@@ -54,17 +54,21 @@ protected internal virtual ActionResult SafeRedirect(string returnUrl)
/// <param name="statusCode">HTTP status code for response</param>
/// <param name="obj">Object to Jsonify and return</param>
/// <returns></returns>
- protected internal JsonResult Json(int statusCode, object obj)
+ protected internal JsonResult Json(int statusCode, object obj, JsonRequestBehavior jsonRequestBehavior)
{
Response.StatusCode = statusCode;
if (statusCode >= 400)
{
Response.TrySkipIisCustomErrors = true;
}
- return Json(obj);
+ return Json(obj, jsonRequestBehavior);
}
+ protected internal JsonResult Json(int statusCode, object obj)
+ {
+ return Json(statusCode, obj, JsonRequestBehavior.DenyGet);
+ }
/// <summary>
/// Called before the action method is invoked.
Oops, something went wrong.

0 comments on commit 1da0dde

Please sign in to comment.