public async Task <Membership> AddMemberAsync(Organization organization, string memberName, string confirmationToken)
        {
            organization = organization ?? throw new ArgumentNullException(nameof(organization));

            var request = FindMembershipRequestByUsername(organization, memberName);

            if (request == null || request.ConfirmationToken != confirmationToken)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_MissingRequest, memberName));
            }

            var member = request.NewMember;

            organization.MemberRequests.Remove(request);

            if (!member.Confirmed)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_UserNotConfirmed, memberName));
            }

            if (member is Organization)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_UserIsOrganization, memberName));
            }

            var membership = FindMembershipByUsername(organization, memberName);

            if (membership == null)
            {
                // Ensure that the new member meets the AAD tenant policy for this organization.
                var policyResult = await SecurityPolicyService.EvaluateOrganizationPoliciesAsync(
                    SecurityPolicyAction.JoinOrganization, organization, member);

                if (policyResult != SecurityPolicyResult.SuccessResult)
                {
                    throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                            Strings.AddMember_PolicyFailure, policyResult.ErrorMessage));
                }

                membership = new Membership()
                {
                    Member  = member,
                    IsAdmin = request.IsAdmin
                };
                organization.Members.Add(membership);
            }
            else
            {
                // If the user is already a member, update the existing membership.
                // If the request grants admin but this member is not an admin, grant admin to the member.
                membership.IsAdmin = membership.IsAdmin || request.IsAdmin;
            }

            await EntitiesContext.SaveChangesAsync();

            return(membership);
        }
        public virtual async Task <JsonResult> AddCertificate(string accountName, HttpPostedFileBase uploadFile)
        {
            if (uploadFile == null)
            {
                return(Json(HttpStatusCode.BadRequest, new[] { Strings.CertificateFileIsRequired }));
            }

            var currentUser = GetCurrentUser();
            var account     = GetAccount(accountName);

            if (currentUser == null)
            {
                return(Json(HttpStatusCode.Unauthorized));
            }

            if (account == null)
            {
                return(Json(HttpStatusCode.NotFound));
            }

            if (ActionsRequiringPermissions.ManageAccount.CheckPermissions(currentUser, account)
                != PermissionsCheckResult.Allowed || !User.WasMultiFactorAuthenticated())
            {
                return(Json(HttpStatusCode.Forbidden, new { Strings.Unauthorized }));
            }

            Certificate certificate;

            try
            {
                using (var uploadStream = uploadFile.InputStream)
                {
                    certificate = await CertificateService.AddCertificateAsync(uploadFile);
                }

                await CertificateService.ActivateCertificateAsync(certificate.Thumbprint, account);
            }
            catch (UserSafeException ex)
            {
                ex.Log();

                return(Json(HttpStatusCode.BadRequest, new[] { ex.Message }));
            }

            var activeCertificateCount = CertificateService.GetCertificates(account).Count();

            if (activeCertificateCount == 1 &&
                SecurityPolicyService.IsSubscribed(account, AutomaticallyOverwriteRequiredSignerPolicy.PolicyName))
            {
                await PackageService.SetRequiredSignerAsync(account);
            }

            return(Json(HttpStatusCode.Created, new { certificate.Thumbprint }));
        }
        private async Task SubscribeOrganizationToTenantPolicyIfTenantIdIsSupported(User organization, User adminUser, bool commitChanges = true)
        {
            var tenantId = adminUser.Credentials.GetAzureActiveDirectoryCredential()?.TenantId;

            if (string.IsNullOrWhiteSpace(tenantId) ||
                !ContentObjectService.LoginDiscontinuationConfiguration.IsTenantIdPolicySupportedForOrganization(organization.EmailAddress ?? organization.UnconfirmedEmailAddress, tenantId))
            {
                return;
            }

            var tenantPolicy = RequireOrganizationTenantPolicy.Create(tenantId);
            await SecurityPolicyService.SubscribeAsync(organization, tenantPolicy, commitChanges);
        }
示例#4
0
        public async Task <Membership> AddMemberAsync(Organization organization, string memberName, bool isAdmin)
        {
            organization = organization ?? throw new ArgumentNullException(nameof(organization));

            var membership = FindMembershipByUsername(organization, memberName);

            if (membership != null)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_AlreadyAMember, memberName));
            }

            var member = FindByUsername(memberName);

            if (member == null)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_UserNotFound, memberName));
            }

            if (!member.Confirmed)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_UserNotConfirmed, memberName));
            }

            // Ensure that the new member meets the AAD tenant policy for this organization.
            var policyResult = await SecurityPolicyService.EvaluateOrganizationPoliciesAsync(
                SecurityPolicyAction.JoinOrganization, organization, member);

            if (policyResult != SecurityPolicyResult.SuccessResult)
            {
                throw new EntityException(policyResult.ErrorMessage);
            }

            membership = new Membership()
            {
                Member  = member,
                IsAdmin = isAdmin
            };
            organization.Members.Add(membership);

            await EntitiesContext.SaveChangesAsync();

            return(membership);
        }
示例#5
0
        private async Task <bool> SubscribeOrganizationToTenantPolicy(User organization, User adminUser, bool commitChanges = true)
        {
            var tenantId = GetAzureActiveDirectoryCredentialTenant(adminUser);

            if (string.IsNullOrWhiteSpace(tenantId))
            {
                return(false);
            }

            var tenantPolicy = RequireOrganizationTenantPolicy.Create(tenantId);

            if (!await SecurityPolicyService.SubscribeAsync(organization, tenantPolicy, commitChanges))
            {
                return(false);
            }

            return(true);
        }
示例#6
0
        private async Task SubscribeOrganizationToTenantPolicyIfTenantIdIsSupported(User organization, User adminUser, bool commitChanges = true)
        {
            var tenantId = adminUser.Credentials.GetAzureActiveDirectoryCredential()?.TenantId;

            if (string.IsNullOrEmpty(tenantId))
            {
                DiagnosticsSource.LogInformation("Will not apply tenant policy to organization because admin user does not have an AAD credential.");
                return;
            }

            if (!ContentObjectService.LoginDiscontinuationConfiguration.IsTenantIdPolicySupportedForOrganization(
                    organization.EmailAddress ?? organization.UnconfirmedEmailAddress,
                    tenantId))
            {
                DiagnosticsSource.LogInformation("Will not apply tenant policy to organization because policy is not supported for email-tenant pair.");
                return;
            }

            DiagnosticsSource.LogInformation("Applying tenant policy to organization.");
            var tenantPolicy = RequireOrganizationTenantPolicy.Create(tenantId);
            await SecurityPolicyService.SubscribeAsync(organization, tenantPolicy, commitChanges);
        }
示例#7
0
        public async virtual Task <ActionResult> VerifyPackageKeyAsync(string id, string version)
        {
            var policyResult = await SecurityPolicyService.EvaluateAsync(SecurityPolicyAction.PackageVerify, HttpContext);

            if (!policyResult.Success)
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, policyResult.ErrorMessage));
            }

            var user       = GetCurrentUser();
            var credential = user.GetCurrentApiKeyCredential(User.Identity);

            var result = await VerifyPackageKeyInternalAsync(user, credential, id, version);

            // Expire and delete verification key after first use to avoid growing the database tables.
            if (CredentialTypes.IsPackageVerificationApiKey(credential.Type))
            {
                await AuthenticationService.RemoveCredential(user, credential);
            }

            TelemetryService.TrackVerifyPackageKeyEvent(id, version, user, User.Identity, result?.StatusCode ?? 200);

            return((ActionResult)result ?? new EmptyResult());
        }
示例#8
0
        private async Task <ActionResult> CreatePackageInternal()
        {
            var policyResult = await SecurityPolicyService.EvaluateAsync(SecurityPolicyAction.PackagePush, HttpContext);

            if (!policyResult.Success)
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, policyResult.ErrorMessage));
            }

            // Get the user
            var currentUser = GetCurrentUser();

            using (var packageStream = ReadPackageFromRequest())
            {
                try
                {
                    using (var archive = new ZipArchive(packageStream, ZipArchiveMode.Read, leaveOpen: true))
                    {
                        var reference = DateTime.UtcNow.AddDays(1); // allow "some" clock skew

                        var entryInTheFuture = archive.Entries.FirstOrDefault(
                            e => e.LastWriteTime.UtcDateTime > reference);

                        if (entryInTheFuture != null)
                        {
                            return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, string.Format(
                                                                        CultureInfo.CurrentCulture,
                                                                        Strings.PackageEntryFromTheFuture,
                                                                        entryInTheFuture.Name)));
                        }
                    }

                    using (var packageToPush = new PackageArchiveReader(packageStream, leaveStreamOpen: false))
                    {
                        try
                        {
                            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,
                                                                        errors.Length > 1 ? Strings.UploadPackage_InvalidNuspecMultiple : Strings.UploadPackage_InvalidNuspec,
                                                                        errorsString)));
                        }

                        if (nuspec.GetMinClientVersion() > Constants.MaxSupportedMinClientVersion)
                        {
                            return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, string.Format(
                                                                        CultureInfo.CurrentCulture,
                                                                        Strings.UploadPackage_MinClientVersionOutOfRange,
                                                                        nuspec.GetMinClientVersion())));
                        }

                        User owner;

                        // Ensure that the user can push packages for this partialId.
                        var id                  = nuspec.GetId();
                        var version             = nuspec.GetVersion();
                        var packageRegistration = PackageService.FindPackageRegistrationById(id);
                        if (packageRegistration == null)
                        {
                            // Check if the current user's scopes allow pushing a new package ID
                            var apiScopeEvaluationResult = EvaluateApiScope(ActionsRequiringPermissions.UploadNewPackageId, new ActionOnNewPackageContext(id, ReservedNamespaceService), NuGetScopes.PackagePush);
                            owner = apiScopeEvaluationResult.Owner;
                            if (!apiScopeEvaluationResult.IsSuccessful())
                            {
                                // User cannot push a new package ID as the current user's scopes does not allow it
                                return(GetHttpResultFromFailedApiScopeEvaluationForPush(apiScopeEvaluationResult, id, version));
                            }
                        }
                        else
                        {
                            // Check if the current user's scopes allow pushing a new version of an existing package ID
                            var apiScopeEvaluationResult = EvaluateApiScope(ActionsRequiringPermissions.UploadNewPackageVersion, packageRegistration, NuGetScopes.PackagePushVersion, NuGetScopes.PackagePush);
                            owner = apiScopeEvaluationResult.Owner;
                            if (!apiScopeEvaluationResult.IsSuccessful())
                            {
                                // User cannot push a package as the current user's scopes does not allow it
                                await AuditingService.SaveAuditRecordAsync(
                                    new FailedAuthenticatedOperationAuditRecord(
                                        currentUser.Username,
                                        AuditedAuthenticatedOperationAction.PackagePushAttemptByNonOwner,
                                        attemptedPackage : new AuditedPackageIdentifier(
                                            id, version.ToNormalizedStringSafe())));

                                return(GetHttpResultFromFailedApiScopeEvaluationForPush(apiScopeEvaluationResult, id, version));
                            }

                            if (packageRegistration.IsLocked)
                            {
                                return(new HttpStatusCodeWithBodyResult(
                                           HttpStatusCode.Forbidden,
                                           string.Format(CultureInfo.CurrentCulture, Strings.PackageIsLocked, packageRegistration.Id)));
                            }

                            // Check if a particular Id-Version combination already exists. We eventually need to remove this check.
                            string normalizedVersion = version.ToNormalizedString();
                            bool   packageExists     =
                                packageRegistration.Packages.Any(
                                    p => string.Equals(
                                        p.NormalizedVersion,
                                        normalizedVersion,
                                        StringComparison.OrdinalIgnoreCase));

                            if (packageExists)
                            {
                                return(new HttpStatusCodeWithBodyResult(
                                           HttpStatusCode.Conflict,
                                           string.Format(CultureInfo.CurrentCulture, Strings.PackageExistsAndCannotBeModified,
                                                         id, nuspec.GetVersion().ToNormalizedStringSafe())));
                            }
                        }

                        var packageStreamMetadata = new PackageStreamMetadata
                        {
                            HashAlgorithm = Constants.Sha512HashAlgorithmId,
                            Hash          = CryptographyService.GenerateHash(packageStream.AsSeekableStream()),
                            Size          = packageStream.Length
                        };

                        var package = await PackageUploadService.GeneratePackageAsync(
                            id,
                            packageToPush,
                            packageStreamMetadata,
                            owner,
                            currentUser);

                        await AutoCuratePackage.ExecuteAsync(package, packageToPush, commitChanges : false);

                        PackageCommitResult commitResult;
                        using (Stream uploadStream = packageStream)
                        {
                            uploadStream.Position = 0;
                            commitResult          = await PackageUploadService.CommitPackageAsync(
                                package,
                                uploadStream.AsSeekableStream());
                        }

                        switch (commitResult)
                        {
                        case PackageCommitResult.Success:
                            break;

                        case PackageCommitResult.Conflict:
                            return(new HttpStatusCodeWithBodyResult(
                                       HttpStatusCode.Conflict,
                                       Strings.UploadPackage_IdVersionConflict));

                        default:
                            throw new NotImplementedException($"The package commit result {commitResult} is not supported.");
                        }

                        IndexingService.UpdatePackage(package);

                        // Write an audit record
                        await AuditingService.SaveAuditRecordAsync(
                            new PackageAuditRecord(package, AuditedPackageAction.Create, PackageCreatedVia.Api));

                        if (!(ConfigurationService.Current.AsynchronousPackageValidationEnabled && ConfigurationService.Current.BlockingAsynchronousPackageValidationEnabled))
                        {
                            // Notify user of push unless async validation in blocking mode is used
                            MessageService.SendPackageAddedNotice(package,
                                                                  Url.Package(package.PackageRegistration.Id, package.NormalizedVersion, relativeUrl: false),
                                                                  Url.ReportPackage(package.PackageRegistration.Id, package.NormalizedVersion, relativeUrl: false),
                                                                  Url.AccountSettings(relativeUrl: false));
                        }

                        TelemetryService.TrackPackagePushEvent(package, currentUser, User.Identity);

                        if (package.SemVerLevelKey == SemVerLevelKey.SemVer2)
                        {
                            return(new HttpStatusCodeWithServerWarningResult(HttpStatusCode.Created, Strings.WarningSemVer2PackagePushed));
                        }

                        return(new HttpStatusCodeResult(HttpStatusCode.Created));
                    }
                }
                catch (InvalidPackageException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
                catch (InvalidDataException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
                catch (EntityException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
                catch (FrameworkException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
            }
        }
示例#9
0
        public async Task <MembershipRequest> AddMembershipRequestAsync(Organization organization, string memberName, bool isAdmin)
        {
            organization = organization ?? throw new ArgumentNullException(nameof(organization));

            var membership = FindMembershipByUsername(organization, memberName);

            if (membership != null)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_AlreadyAMember, memberName));
            }

            var request = FindMembershipRequestByUsername(organization, memberName);

            if (request != null)
            {
                // If there is already an existing request, return it.
                // If the existing request grants collaborator but we are trying to create a request that grants admin, update the request to grant admin.
                request.IsAdmin = isAdmin || request.IsAdmin;
                await EntitiesContext.SaveChangesAsync();

                return(request);
            }

            if (Regex.IsMatch(memberName, GalleryConstants.EmailValidationRegex, RegexOptions.None, GalleryConstants.EmailValidationRegexTimeout))
            {
                throw new EntityException(Strings.AddMember_NameIsEmail);
            }

            var member = FindByUsername(memberName);

            if (member == null)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_UserNotFound, memberName));
            }

            if (!member.Confirmed)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_UserNotConfirmed, memberName));
            }

            if (member is Organization)
            {
                throw new EntityException(string.Format(CultureInfo.CurrentCulture,
                                                        Strings.AddMember_UserIsOrganization, memberName));
            }

            // Ensure that the new member meets the AAD tenant policy for this organization.
            var policyResult = await SecurityPolicyService.EvaluateOrganizationPoliciesAsync(
                SecurityPolicyAction.JoinOrganization, organization, member);

            if (policyResult != SecurityPolicyResult.SuccessResult)
            {
                throw new EntityException(policyResult.ErrorMessage);
            }

            request = new MembershipRequest()
            {
                Organization      = organization,
                NewMember         = member,
                IsAdmin           = isAdmin,
                ConfirmationToken = Crypto.GenerateToken(),
                RequestDate       = DateTime.UtcNow,
            };
            organization.MemberRequests.Add(request);

            await EntitiesContext.SaveChangesAsync();

            return(request);
        }
        private async Task <ActionResult> CreatePackageInternal()
        {
            var policyResult = await SecurityPolicyService.EvaluateAsync(SecurityPolicyAction.PackagePush, HttpContext);

            if (!policyResult.Success)
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, policyResult.ErrorMessage));
            }

            // Get the user
            var user = GetCurrentUser();

            using (var packageStream = ReadPackageFromRequest())
            {
                try
                {
                    using (var archive = new ZipArchive(packageStream, ZipArchiveMode.Read, leaveOpen: true))
                    {
                        var reference = DateTime.UtcNow.AddDays(1); // allow "some" clock skew

                        var entryInTheFuture = archive.Entries.FirstOrDefault(
                            e => e.LastWriteTime.UtcDateTime > reference);

                        if (entryInTheFuture != null)
                        {
                            return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, string.Format(
                                                                        CultureInfo.CurrentCulture,
                                                                        Strings.PackageEntryFromTheFuture,
                                                                        entryInTheFuture.Name)));
                        }
                    }

                    using (var packageToPush = new PackageArchiveReader(packageStream, leaveStreamOpen: false))
                    {
                        try
                        {
                            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,
                                                                        errors.Length > 1 ? Strings.UploadPackage_InvalidNuspecMultiple : Strings.UploadPackage_InvalidNuspec,
                                                                        errorsString)));
                        }

                        if (nuspec.GetMinClientVersion() > Constants.MaxSupportedMinClientVersion)
                        {
                            return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, string.Format(
                                                                        CultureInfo.CurrentCulture,
                                                                        Strings.UploadPackage_MinClientVersionOutOfRange,
                                                                        nuspec.GetMinClientVersion())));
                        }

                        // Ensure that the user can push packages for this partialId.
                        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: 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
                        {
                            // Is the user allowed to push this Id?
                            if (!packageRegistration.IsOwner(user))
                            {
                                // Audit that a non-owner tried to push the package
                                await AuditingService.SaveAuditRecordAsync(
                                    new FailedAuthenticatedOperationAuditRecord(
                                        user.Username,
                                        AuditedAuthenticatedOperationAction.PackagePushAttemptByNonOwner,
                                        attemptedPackage : new AuditedPackageIdentifier(
                                            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,
                                                                                      id)));
                            }

                            // Check if API key allows pushing the current package id
                            if (!ApiKeyScopeAllows(
                                    packageRegistration.Id,
                                    NuGetScopes.PackagePushVersion, NuGetScopes.PackagePush))
                            {
                                // User cannot push a package as the API key scope does not allow it
                                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.Unauthorized, Strings.ApiKeyNotAuthorized));
                            }

                            // Check if a particular Id-Version combination already exists. We eventually need to remove this check.
                            string normalizedVersion = nuspec.GetVersion().ToNormalizedString();
                            bool   packageExists     =
                                packageRegistration.Packages.Any(
                                    p => string.Equals(
                                        p.NormalizedVersion,
                                        normalizedVersion,
                                        StringComparison.OrdinalIgnoreCase));

                            if (packageExists)
                            {
                                return(new HttpStatusCodeWithBodyResult(
                                           HttpStatusCode.Conflict,
                                           string.Format(CultureInfo.CurrentCulture, Strings.PackageExistsAndCannotBeModified,
                                                         id, nuspec.GetVersion().ToNormalizedStringSafe())));
                            }
                        }

                        var packageStreamMetadata = new PackageStreamMetadata
                        {
                            HashAlgorithm = Constants.Sha512HashAlgorithmId,
                            Hash          = CryptographyService.GenerateHash(packageStream.AsSeekableStream()),
                            Size          = packageStream.Length
                        };

                        var package = await PackageUploadService.GeneratePackageAsync(
                            id,
                            packageToPush,
                            packageStreamMetadata,
                            user,
                            commitChanges : false);

                        await AutoCuratePackage.ExecuteAsync(package, packageToPush, commitChanges : false);

                        using (Stream uploadStream = packageStream)
                        {
                            uploadStream.Position = 0;

                            try
                            {
                                await PackageFileService.SavePackageFileAsync(package, uploadStream.AsSeekableStream());
                            }
                            catch (InvalidOperationException ex)
                            {
                                ex.Log();

                                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.Conflict, Strings.UploadPackage_IdVersionConflict));
                            }
                        }

                        try
                        {
                            await EntitiesContext.SaveChangesAsync();
                        }
                        catch
                        {
                            // If saving to the DB fails for any reason, we need to delete the package we just saved.
                            await PackageFileService.DeletePackageFileAsync(nuspec.GetId(), nuspec.GetVersion().ToNormalizedString());

                            throw;
                        }

                        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.Package(package.PackageRegistration.Id, package.NormalizedVersion, relativeUrl: false),
                                                              Url.ReportPackage(package.PackageRegistration.Id, package.NormalizedVersion, relativeUrl: false),
                                                              Url.AccountSettings(relativeUrl: false));

                        TelemetryService.TrackPackagePushEvent(package, user, User.Identity);

                        if (package.SemVerLevelKey == SemVerLevelKey.SemVer2)
                        {
                            return(new HttpStatusCodeWithServerWarningResult(HttpStatusCode.Created, Strings.WarningSemVer2PackagePushed));
                        }

                        return(new HttpStatusCodeResult(HttpStatusCode.Created));
                    }
                }
                catch (InvalidPackageException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
                catch (InvalidDataException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
                catch (EntityException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
                catch (FrameworkException ex)
                {
                    return(BadRequestForExceptionMessage(ex));
                }
            }
        }