Ejemplo n.º 1
0
            public async Task UpdatesTheStreamMetadata()
            {
                // Arrange
                var package = new Package
                {
                    Hash             = "hash-before",
                    HashAlgorithm    = "hash-algorithm-before",
                    PackageFileSize  = 23,
                    LastUpdated      = new DateTime(2017, 1, 1, 8, 30, 0),
                    LastEdited       = new DateTime(2017, 1, 1, 7, 30, 0),
                    PackageStatusKey = PackageStatus.Available,
                };
                var metadata = new PackageStreamMetadata
                {
                    Hash          = "hash-after",
                    HashAlgorithm = "hash-algorithm-after",
                    Size          = 42,
                };
                var service = CreateService();

                // Act
                var before = DateTime.UtcNow;
                await service.UpdatePackageStreamMetadataAsync(package, metadata, commitChanges : true);

                var after = DateTime.UtcNow;

                // Assert
                Assert.Equal("hash-after", package.Hash);
                Assert.Equal("hash-algorithm-after", package.HashAlgorithm);
                Assert.Equal(42, package.PackageFileSize);
                Assert.InRange(package.LastUpdated, before, after);
                Assert.NotNull(package.LastEdited);
                Assert.InRange(package.LastEdited.Value, before, after);
                Assert.Equal(package.LastUpdated, package.LastEdited);
            }
            public async Task SetsPackageStreamMetadataIfChanged()
            {
                var content                  = "Hello, world.";
                var expectedHash             = "rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4uWpoxUERddvFwjgRSGw7gNPCwuvJg==";
                var stream                   = new MemoryStream(Encoding.ASCII.GetBytes(content));
                PackageStreamMetadata actual = null;

                PackageFileServiceMock
                .Setup(x => x.DownloadPackageFileToDiskAsync(ValidationSet))
                .ReturnsAsync(stream);
                var streamMetadata = new PackageStreamMetadata()
                {
                    Size          = stream.Length,
                    Hash          = expectedHash,
                    HashAlgorithm = CoreConstants.Sha512HashAlgorithmId
                };

                PackageFileServiceMock
                .Setup(x => x.UpdatePackageBlobMetadataAsync(It.IsAny <PackageValidationSet>()))
                .ReturnsAsync(streamMetadata);
                PackageServiceMock
                .Setup(x => x.UpdateMetadataAsync(Package, It.IsAny <PackageStreamMetadata>(), false))
                .Returns(Task.CompletedTask)
                .Callback <Package, PackageStreamMetadata, bool>((_, m, __) => actual = m);

                await Target.SetStatusAsync(PackageValidatingEntity, ValidationSet, PackageStatus.Available);

                Assert.NotNull(actual);
                Assert.Equal(content.Length, actual.Size);
                Assert.Equal(expectedHash, actual.Hash);
                Assert.Equal("SHA512", actual.HashAlgorithm);
                PackageServiceMock.Verify(
                    x => x.UpdateMetadataAsync(Package, actual, false),
                    Times.Once);
            }
            public async Task DoesNotSetPackageStreamMetadataIfNotChanged()
            {
                var content = "Hello, world.";

                Package.PackageFileSize = content.Length;
                Package.HashAlgorithm   = "SHA512";
                Package.Hash            = "rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4uWpoxUERddvFwjgRSGw7gNPCwuvJg==";
                var stream = new MemoryStream(Encoding.ASCII.GetBytes(content));

                var corePackageService          = new Mock <ICorePackageService>();
                var mockPackageEntityRepository = new Mock <IEntityRepository <Package> >();
                var entityPackageService        = new PackageEntityService(corePackageService.Object, mockPackageEntityRepository.Object);

                PackageFileServiceMock
                .Setup(x => x.DownloadPackageFileToDiskAsync(ValidationSet))
                .ReturnsAsync(stream);

                var streamMetadata = new PackageStreamMetadata()
                {
                    Size          = Package.PackageFileSize,
                    Hash          = Package.Hash,
                    HashAlgorithm = Package.HashAlgorithm
                };

                PackageFileServiceMock
                .Setup(x => x.UpdatePackageBlobMetadataAsync(It.IsAny <PackageValidationSet>()))
                .ReturnsAsync(streamMetadata);

                await Target.SetStatusAsync(PackageValidatingEntity, ValidationSet, PackageStatus.Available);

                corePackageService.Verify(
                    x => x.UpdatePackageStreamMetadataAsync(It.IsAny <Package>(), It.IsAny <PackageStreamMetadata>(), It.IsAny <bool>()),
                    Times.Never);
            }
Ejemplo n.º 4
0
            public void MetadataChangeInvokeICoreService()
            {
                // Arrange
                var package = CreatePackage();

                package.PackageFileSize = 100;
                package.HashAlgorithm   = "SHA512";
                package.Hash            = "rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4uWpoxUERddvFwjgRSGw7gNPCwuvJg==";
                var metadata = new PackageStreamMetadata()
                {
                    Hash          = package.Hash,
                    HashAlgorithm = package.HashAlgorithm,
                    Size          = package.PackageFileSize * 2
                };

                var mockCorePackageService       = new Mock <ICorePackageService>();
                var mockIPackageEntityRepository = new Mock <IEntityRepository <Package> >();

                mockCorePackageService.Setup(c => c.UpdatePackageStreamMetadataAsync(package, metadata, true)).Returns(Task.CompletedTask);
                var service = new PackageEntityService(mockCorePackageService.Object, mockIPackageEntityRepository.Object);

                // Act & Assert
                var result = service.UpdateMetadataAsync(package, metadata, true);

                mockCorePackageService
                .Verify(s => s.UpdatePackageStreamMetadataAsync(package, metadata, true), Times.Once);
            }
Ejemplo n.º 5
0
            public void WillCreateAndReturnSymbolPackageButNotCommit()
            {
                // Arrange
                var symbolPackageStreamMetadata = new PackageStreamMetadata()
                {
                    Size          = 12312,
                    Hash          = "01asdf2130",
                    HashAlgorithm = "VerySecureAlogrithm"
                };
                var package = new Package();
                var mockSymbolPackageRepository = new Mock <IEntityRepository <SymbolPackage> >();

                mockSymbolPackageRepository
                .Setup(x => x.InsertOnCommit(It.IsAny <SymbolPackage>()));

                var service = CreateService(mockSymbolPackageRepository);

                // Act
                var symbolPackage = service.CreateSymbolPackage(package, symbolPackageStreamMetadata);

                // Assert
                mockSymbolPackageRepository.Verify(x => x.InsertOnCommit(It.IsAny <SymbolPackage>()), Times.Once);
                mockSymbolPackageRepository.Verify(x => x.CommitChangesAsync(), Times.Never);
                Assert.NotNull(symbolPackage);
                Assert.Equal(symbolPackageStreamMetadata.Hash, symbolPackage.Hash);
                Assert.Equal(symbolPackageStreamMetadata.HashAlgorithm, symbolPackage.HashAlgorithm);
                Assert.Equal(symbolPackageStreamMetadata.Size, symbolPackage.FileSize);
                Assert.Equal(package, symbolPackage.Package);
            }
        public async Task <Package> ReflowAsync(string id, string version)
        {
            var package = _packageService.FindPackageByIdAndVersionStrict(id, version);

            if (package == null)
            {
                return(null);
            }

            EntitiesConfiguration.SuspendExecutionStrategy = true;
            using (var transaction = _entitiesContext.GetDatabase().BeginTransaction())
            {
                // 1) Download package binary to memory
                using (var packageStream = await _packageFileService.DownloadPackageFileAsync(package))
                {
                    using (var packageArchive = new PackageArchiveReader(packageStream, leaveStreamOpen: false))
                    {
                        // 2) Determine package metadata from binary
                        var packageStreamMetadata = new PackageStreamMetadata
                        {
                            HashAlgorithm = Constants.Sha512HashAlgorithmId,
                            Hash          = CryptographyService.GenerateHash(packageStream.AsSeekableStream()),
                            Size          = packageStream.Length,
                        };

                        var packageMetadata = PackageMetadata.FromNuspecReader(packageArchive.GetNuspecReader());

                        // 3) Clear referenced objects that will be reflowed
                        ClearSupportedFrameworks(package);
                        ClearAuthors(package);
                        ClearDependencies(package);

                        // 4) Reflow the package
                        var listed = package.Listed;

                        package = _packageService.EnrichPackageFromNuGetPackage(
                            package,
                            packageArchive,
                            packageMetadata,
                            packageStreamMetadata,
                            package.User);

                        package.LastEdited = DateTime.UtcNow;
                        package.Listed     = listed;

                        // 5) Update IsLatest so that reflow can correct concurrent updates (see Gallery #2514)
                        await _packageService.UpdateIsLatestAsync(package.PackageRegistration, commitChanges : false);

                        // 6) Save and profit
                        await _entitiesContext.SaveChangesAsync();
                    }
                }

                // Commit transaction
                transaction.Commit();
            }
            EntitiesConfiguration.SuspendExecutionStrategy = false;

            return(package);
        }
Ejemplo n.º 7
0
        public async Task <Package> GeneratePackageAsync(
            string id,
            PackageArchiveReader nugetPackage,
            PackageStreamMetadata packageStreamMetadata,
            User user)
        {
            var isPushAllowed        = _reservedNamespaceService.IsPushAllowed(id, user, out IReadOnlyCollection <ReservedNamespace> userOwnedNamespaces);
            var shouldMarkIdVerified = isPushAllowed && userOwnedNamespaces != null && userOwnedNamespaces.Any();

            var package = await _packageService.CreatePackageAsync(
                nugetPackage,
                packageStreamMetadata,
                user,
                isVerified : shouldMarkIdVerified);

            await _validationService.StartValidationAsync(package);

            if (shouldMarkIdVerified)
            {
                // Add all relevant package registrations to the applicable namespaces
                foreach (var rn in userOwnedNamespaces)
                {
                    _reservedNamespaceService.AddPackageRegistrationToNamespace(
                        rn.Value,
                        package.PackageRegistration);
                }
            }

            return(package);
        }
Ejemplo n.º 8
0
            public async Task SetsPackageStreamMetadataIfChanged()
            {
                var content                  = "Hello, world.";
                var expectedHash             = "rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4uWpoxUERddvFwjgRSGw7gNPCwuvJg==";
                var stream                   = new MemoryStream(Encoding.ASCII.GetBytes(content));
                PackageStreamMetadata actual = null;

                PackageFileServiceMock
                .Setup(x => x.DownloadPackageFileToDiskAsync(Package))
                .ReturnsAsync(stream);
                PackageServiceMock
                .Setup(x => x.UpdatePackageStreamMetadataAsync(Package, It.IsAny <PackageStreamMetadata>(), false))
                .Returns(Task.CompletedTask)
                .Callback <Package, PackageStreamMetadata, bool>((_, m, __) => actual = m);

                await Target.SetPackageStatusAsync(Package, ValidationSet, PackageStatus.Available);

                Assert.NotNull(actual);
                Assert.Equal(content.Length, actual.Size);
                Assert.Equal(expectedHash, actual.Hash);
                Assert.Equal("SHA512", actual.HashAlgorithm);
                PackageServiceMock.Verify(
                    x => x.UpdatePackageStreamMetadataAsync(Package, actual, false),
                    Times.Once);
                TelemetryServiceMock.Verify(
                    x => x.TrackDurationToHashPackage(
                        It.Is <TimeSpan>(y => y > TimeSpan.Zero),
                        Package.PackageRegistration.Id,
                        Package.NormalizedVersion,
                        "SHA512",
                        "System.IO.MemoryStream"),
                    Times.Once);
            }
Ejemplo n.º 9
0
        public virtual async Task UpdatePackageStreamMetadataAsync(
            Package package,
            PackageStreamMetadata metadata,
            bool commitChanges = true)
        {
            if (package == null)
            {
                throw new ArgumentNullException(nameof(package));
            }

            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            package.Hash            = metadata.Hash;
            package.HashAlgorithm   = metadata.HashAlgorithm;
            package.PackageFileSize = metadata.Size;

            var now = DateTime.UtcNow;

            package.LastUpdated = now;

            /// If the package is available, consider this change as an "edit" so that the package appears for cursors
            /// on the <see cref="Package.LastEdited"/> field.
            if (package.PackageStatusKey == PackageStatus.Available)
            {
                package.LastEdited = now;
            }

            if (commitChanges)
            {
                await _packageRepository.CommitChangesAsync();
            }
        }
Ejemplo n.º 10
0
        /// <remarks>
        /// This method will create the symbol package entity. The caller should validate the ownership of packages and
        /// metadata for the symbols associated for this package. Its the caller's responsibility to commit as well.
        /// </remarks>
        public SymbolPackage CreateSymbolPackage(Package nugetPackage, PackageStreamMetadata symbolPackageStreamMetadata)
        {
            if (nugetPackage == null)
            {
                throw new ArgumentNullException(nameof(nugetPackage));
            }

            if (symbolPackageStreamMetadata == null)
            {
                throw new ArgumentNullException(nameof(symbolPackageStreamMetadata));
            }

            try
            {
                var symbolPackage = new SymbolPackage()
                {
                    Package       = nugetPackage,
                    PackageKey    = nugetPackage.Key,
                    Created       = DateTime.UtcNow,
                    FileSize      = symbolPackageStreamMetadata.Size,
                    HashAlgorithm = symbolPackageStreamMetadata.HashAlgorithm,
                    Hash          = symbolPackageStreamMetadata.Hash
                };

                _symbolPackageRepository.InsertOnCommit(symbolPackage);

                return(symbolPackage);
            }
            catch (Exception ex) when(ex is EntityException)
            {
                throw new InvalidPackageException(ex.Message, ex);
            }
        }
Ejemplo n.º 11
0
        public async Task <Package> GeneratePackageAsync(
            string id,
            PackageArchiveReader nugetPackage,
            PackageStreamMetadata packageStreamMetadata,
            User owner,
            User currentUser)
        {
            var shouldMarkIdVerified = _reservedNamespaceService.ShouldMarkNewPackageIdVerified(owner, id, out var ownedMatchingReservedNamespaces);

            var package = await _packageService.CreatePackageAsync(
                nugetPackage,
                packageStreamMetadata,
                owner,
                currentUser,
                isVerified : shouldMarkIdVerified);

            if (shouldMarkIdVerified)
            {
                // Add all relevant package registrations to the applicable namespaces
                foreach (var rn in ownedMatchingReservedNamespaces)
                {
                    _reservedNamespaceService.AddPackageRegistrationToNamespace(
                        rn.Value,
                        package.PackageRegistration);
                }
            }

            _vulnerabilityService.ApplyExistingVulnerabilitiesToPackage(package);

            return(package);
        }
Ejemplo n.º 12
0
            public async Task RejectsNullStreamMetadata()
            {
                // Arrange
                var package = new Package();
                PackageStreamMetadata metadata = null;
                var service = CreateService();

                // Act & Assert
                await Assert.ThrowsAsync <ArgumentNullException>(
                    () => service.UpdatePackageStreamMetadataAsync(package, metadata, commitChanges: true));
            }
        private async Task <PackageStatus> MarkPackageAsAvailableAsync(
            PackageValidationSet validationSet,
            IValidatingEntity <T> validatingEntity,
            PackageStreamMetadata streamMetadata,
            bool copied)
        {
            // Use whatever package made it into the packages container. This is what customers will consume so the DB
            // record must match.

            // We don't immediately commit here. Later, we will commit these changes as well as the new package
            // status as part of the same transaction.
            await _galleryPackageService.UpdateMetadataAsync(
                validatingEntity.EntityRecord,
                streamMetadata,
                commitChanges : false);

            _logger.LogInformation("Marking package {PackageId} {PackageVersion}, validation set {ValidationSetId} as {PackageStatus} in DB",
                                   validationSet.PackageId,
                                   validationSet.PackageNormalizedVersion,
                                   validationSet.ValidationTrackingId,
                                   PackageStatus.Available);

            var fromStatus = validatingEntity.Status;

            try
            {
                // Make the package available and commit any other pending changes (e.g. updated hash).
                await _galleryPackageService.UpdateStatusAsync(validatingEntity.EntityRecord, PackageStatus.Available, commitChanges : true);
            }
            catch (Exception e)
            {
                _logger.LogError(
                    Error.UpdatingPackageDbStatusFailed,
                    e,
                    "Failed to update package status in Gallery Db. Package {PackageId} {PackageVersion}, validation set {ValidationSetId}",
                    validationSet.PackageId,
                    validationSet.PackageNormalizedVersion,
                    validationSet.ValidationTrackingId);

                // If this execution was not the one to copy the package, then don't delete the package on failure.
                // This prevents a missing passing in the (unlikely) case where two actors attempt the DB update, one
                // succeeds and one fails. We don't want an available package record with nothing in the packages
                // container!
                if (copied && fromStatus != PackageStatus.Available)
                {
                    await _packageFileService.DeletePackageFileAsync(validationSet);
                    await OnCleanupAfterDatabaseUpdateFailure(validatingEntity, validationSet);
                }

                throw;
            }

            return(fromStatus);
        }
            public BaseFacts()
            {
                Package = new Package
                {
                    PackageRegistration = new PackageRegistration(),
                    PackageStatusKey    = PackageStatus.Validating,
                };
                ValidationSet = new PackageValidationSet
                {
                    PackageValidations = new List <PackageValidation>
                    {
                        new PackageValidation {
                            Type = "SomeValidator"
                        },
                    }
                };

                PackageServiceMock         = new Mock <IEntityService <Package> >();
                PackageFileServiceMock     = new Mock <IValidationFileService>();
                ValidatorProviderMock      = new Mock <IValidatorProvider>();
                TelemetryServiceMock       = new Mock <ITelemetryService>();
                LoggerMock                 = new Mock <ILogger <EntityStatusProcessor <Package> > >();
                CoreLicenseFileServiceMock = new Mock <ICoreLicenseFileService>();
                CoreReadmeFileServiceMock  = new Mock <ICoreReadmeFileService>();

                var streamMetadata = new PackageStreamMetadata()
                {
                    Size          = 1,
                    Hash          = "hash",
                    HashAlgorithm = CoreConstants.Sha512HashAlgorithmId
                };

                SasDefinitionConfiguration = new SasDefinitionConfiguration()
                {
                    PackageStatusProcessorSasDefinition = "PackageStatusProcessorSasDefinition"
                };
                SasDefinitionConfigurationMock = new Mock <IOptionsSnapshot <SasDefinitionConfiguration> >();
                SasDefinitionConfigurationMock.Setup(x => x.Value).Returns(() => SasDefinitionConfiguration);

                Target = new PackageStatusProcessor(
                    PackageServiceMock.Object,
                    PackageFileServiceMock.Object,
                    ValidatorProviderMock.Object,
                    TelemetryServiceMock.Object,
                    SasDefinitionConfigurationMock.Object,
                    LoggerMock.Object,
                    CoreLicenseFileServiceMock.Object,
                    CoreReadmeFileServiceMock.Object);

                PackageValidatingEntity = new PackageValidatingEntity(Package);
            }
Ejemplo n.º 15
0
        public async Task UpdateMetadataAsync(Package entity, object metadata, bool commitChanges = true)
        {
            PackageStreamMetadata typedMetadata = metadata == null ? null : metadata as PackageStreamMetadata;

            if (typedMetadata != null)
            {
                if (typedMetadata.Size != entity.PackageFileSize ||
                    typedMetadata.Hash != entity.Hash ||
                    typedMetadata.HashAlgorithm != entity.HashAlgorithm)
                {
                    await _galleryEntityService.UpdatePackageStreamMetadataAsync(entity, typedMetadata, commitChanges);
                }
            }
        }
Ejemplo n.º 16
0
            public async Task CommitsTheCorrectNumberOfTimes(bool commitChanges, int commitCount)
            {
                // Arrange
                var packageRepository = new Mock <IEntityRepository <Package> >();
                var package           = new Package();
                var metadata          = new PackageStreamMetadata();
                var service           = CreateService(packageRepository: packageRepository);

                // Act
                await service.UpdatePackageStreamMetadataAsync(package, metadata, commitChanges);

                // Assert
                packageRepository.Verify(x => x.CommitChangesAsync(), Times.Exactly(commitCount));
            }
            public BaseFacts()
            {
                Package = new Package
                {
                    PackageRegistration = new PackageRegistration(),
                    PackageStatusKey    = PackageStatus.Validating,
                };
                ValidationSet = new PackageValidationSet
                {
                    PackageValidations = new List <PackageValidation>
                    {
                        new PackageValidation {
                            Type = "SomeValidator"
                        },
                    }
                };

                PackageServiceMock         = new Mock <IEntityService <Package> >();
                PackageFileServiceMock     = new Mock <IValidationFileService>();
                ValidatorProviderMock      = new Mock <IValidatorProvider>();
                TelemetryServiceMock       = new Mock <ITelemetryService>();
                LoggerMock                 = new Mock <ILogger <EntityStatusProcessor <Package> > >();
                CoreLicenseFileServiceMock = new Mock <ICoreLicenseFileService>();

                var streamMetadata = new PackageStreamMetadata()
                {
                    Size          = 1,
                    Hash          = "hash",
                    HashAlgorithm = CoreConstants.Sha512HashAlgorithmId
                };

                PackageFileServiceMock
                .Setup(x => x.UpdatePackageBlobMetadataAsync(It.IsAny <PackageValidationSet>()))
                .ReturnsAsync(streamMetadata);

                Target = new PackageStatusProcessor(
                    PackageServiceMock.Object,
                    PackageFileServiceMock.Object,
                    ValidatorProviderMock.Object,
                    TelemetryServiceMock.Object,
                    LoggerMock.Object,
                    CoreLicenseFileServiceMock.Object);

                PackageValidatingEntity = new PackageValidatingEntity(Package);
            }
Ejemplo n.º 18
0
            public async Task DoesNotUpdateLastEditedWhenNotAvailable(PackageStatus packageStatus)
            {
                // Arrange
                var originalLastEdited = new DateTime(2017, 1, 1, 7, 30, 0);
                var package            = new Package
                {
                    LastEdited       = originalLastEdited,
                    PackageStatusKey = packageStatus,
                };
                var metadata = new PackageStreamMetadata();
                var service  = CreateService();

                // Act
                await service.UpdatePackageStreamMetadataAsync(package, metadata, commitChanges : true);

                // Assert
                Assert.Equal(originalLastEdited, package.LastEdited);
            }
Ejemplo n.º 19
0
        public async Task <PackageStreamMetadata> UpdatePackageBlobMetadataAsync(PackageValidationSet validationSet)
        {
            var fileName = BuildFileName(
                validationSet,
                _fileMetadataService.FileSavePathTemplate,
                _fileMetadataService.FileExtension);

            PackageStreamMetadata streamMetadata = null;

            // This will throw if the ETag changes between read and write operations,
            // so streamMetadata will never be null.
            await _fileStorageService.SetMetadataAsync(
                _fileMetadataService.FileFolderName,
                fileName,
                async (lazyStream, metadata) =>
            {
                var packageStream = await lazyStream.Value;
                string hash;

                using (_telemetryService.TrackDurationToHashPackage(
                           validationSet.PackageId,
                           validationSet.PackageNormalizedVersion,
                           validationSet.ValidationTrackingId,
                           packageStream.Length,
                           CoreConstants.Sha512HashAlgorithmId,
                           packageStream.GetType().FullName))
                {
                    hash = CryptographyService.GenerateHash(packageStream, CoreConstants.Sha512HashAlgorithmId);
                }

                metadata[CoreConstants.Sha512HashAlgorithmId] = hash;

                streamMetadata = new PackageStreamMetadata()
                {
                    Size          = packageStream.Length,
                    Hash          = hash,
                    HashAlgorithm = CoreConstants.Sha512HashAlgorithmId
                };

                return(true);
            });

            return(streamMetadata);
        }
Ejemplo n.º 20
0
        public Package CreatePackage(PackageReader nugetPackage, PackageStreamMetadata packageStreamMetadata, User user, bool commitChanges = true)
        {
            var packageMetadata = PackageMetadata.FromNuspecReader(nugetPackage.GetNuspecReader());

            ValidateNuGetPackageMetadata(packageMetadata);

            var packageRegistration = CreateOrGetPackageRegistration(user, packageMetadata);

            var package = CreatePackageFromNuGetPackage(packageRegistration, nugetPackage, packageMetadata, packageStreamMetadata, user);

            packageRegistration.Packages.Add(package);
            UpdateIsLatest(packageRegistration, false);

            if (commitChanges)
            {
                _packageRegistrationRepository.CommitChanges();
                NotifyIndexingService();
            }

            return(package);
        }
Ejemplo n.º 21
0
            public void WillThrowInvalidPackageExceptionForDbFail()
            {
                // Arrange
                var symbolPackageStreamMetadata = new PackageStreamMetadata()
                {
                    Size          = 12312,
                    Hash          = "01asdf2130",
                    HashAlgorithm = "VerySecureAlogrithm"
                };

                var mockSymbolPackageRepository = new Mock <IEntityRepository <SymbolPackage> >();

                mockSymbolPackageRepository
                .Setup(x => x.InsertOnCommit(It.IsAny <SymbolPackage>()))
                .Throws(new EntityException("MyException"))
                .Verifiable();

                var service = CreateService(mockSymbolPackageRepository);

                // Act and Assert
                Assert.Throws <InvalidPackageException>(() => service.CreateSymbolPackage(new Package(), symbolPackageStreamMetadata));
                mockSymbolPackageRepository.Verify();
            }
Ejemplo n.º 22
0
        private async Task <bool> IsValidAsync(
            IPackageService packageService,
            RequirePackageMetadataState state,
            string packagePath)
        {
            if (!File.Exists(packagePath) && !Directory.Exists(packagePath))
            {
                OutputColor(
                    ConsoleColor.Red,
                    () =>
                {
                    _console.WriteLine("INVALID.");
                    _console.WriteLine(packagePath);
                    _console.WriteLine("The path does not exist.");
                });
                return(false);
            }

            if (File.GetAttributes(packagePath).HasFlag(FileAttributes.Directory))
            {
                OutputColor(
                    ConsoleColor.Red,
                    () =>
                {
                    _console.WriteLine("INVALID.");
                    _console.WriteLine(packagePath);
                    _console.WriteLine("The path is a directory, not a file.");
                });
                return(false);
            }

            Package package;

            using (var packageStream = File.OpenRead(packagePath))
            {
                var packageArchiveReader = new PackageArchiveReader(packageStream);

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

                var owner       = new User();
                var currentUser = owner;
                var isVerified  = true;

                package = await packageService.CreatePackageAsync(
                    packageArchiveReader,
                    packageStreamMetadata,
                    owner,
                    currentUser,
                    isVerified);
            }

            var isCompliant = RequirePackageMetadataComplianceUtility.IsPackageMetadataCompliant(
                package,
                state,
                out var complianceFailures);

            if (isCompliant)
            {
                OutputColor(
                    ConsoleColor.Green,
                    () =>
                {
                    _console.WriteLine("VALID.");
                    _console.WriteLine(packagePath);
                    _console.WriteLine($"The package {package.Id} {package.Version} is compliant.");
                });
                return(true);
            }
            else
            {
                OutputColor(
                    ConsoleColor.Red,
                    () =>
                {
                    var single = complianceFailures.Count == 1;
                    _console.WriteLine("INVALID.");
                    _console.WriteLine(packagePath);
                    _console.WriteLine($"The package {package.Id} {package.Version} is not compliant.");
                    _console.WriteLine($"There {(single ? "is" : "are")} {complianceFailures.Count} problem{(single ? string.Empty : "s")}.");
                    foreach (var failure in complianceFailures)
                    {
                        _console.WriteLine($"  - {failure}");
                    }
                });
                return(false);
            }
        }
Ejemplo n.º 23
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));
                }
            }
        }
Ejemplo n.º 24
0
        private async Task <ActionResult> CreatePackageInternal()
        {
            // 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))
                    {
                        NuspecReader nuspec = null;
                        try
                        {
                            nuspec = packageToPush.GetNuspecReader();
                        }
                        catch (Exception ex)
                        {
                            return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, string.Format(
                                                                        CultureInfo.CurrentCulture,
                                                                        Strings.UploadPackage_InvalidNuspec,
                                                                        ex.Message)));
                        }

                        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 packageRegistration = PackageService.FindPackageRegistrationById(nuspec.GetId());
                        if (packageRegistration != null)
                        {
                            if (!packageRegistration.IsOwner(user))
                            {
                                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.Forbidden,
                                                                        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,
                                                         nuspec.GetId(), nuspec.GetVersion().ToNormalizedStringSafe())));
                            }
                        }

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

                        var package = await PackageService.CreatePackageAsync(
                            packageToPush,
                            packageStreamMetadata,
                            user,
                            commitChanges : false);

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

                        await EntitiesContext.SaveChangesAsync();

                        using (Stream uploadStream = packageStream)
                        {
                            uploadStream.Position = 0;
                            await PackageFileService.SavePackageFileAsync(package, uploadStream.AsSeekableStream());

                            IndexingService.UpdatePackage(package);
                        }

                        MessageService.SendPackageAddedNotice(package,
                                                              Url.Action("DisplayPackage", "Packages", routeValues: new { id = package.PackageRegistration.Id, version = package.Version }, protocol: Request.Url.Scheme),
                                                              Url.Action("ReportMyPackage", "Packages", routeValues: new { id = package.PackageRegistration.Id, version = package.Version }, protocol: Request.Url.Scheme),
                                                              Url.Action("Account", "Users", routeValues: null, protocol: Request.Url.Scheme));

                        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));
                }
            }
        }
Ejemplo n.º 25
0
        private async Task <ActionResult> CreatePackageInternal()
        {
            // Get the user
            var user = GetCurrentUser();

            using (var packageStream = ReadPackageFromRequest())
            {
                try
                {
                    using (var packageToPush = new PackageArchiveReader(packageStream, leaveStreamOpen: false))
                    {
                        NuspecReader nuspec = null;
                        try
                        {
                            nuspec = packageToPush.GetNuspecReader();
                        }
                        catch (Exception ex)
                        {
                            return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, string.Format(
                                                                        CultureInfo.CurrentCulture,
                                                                        Strings.UploadPackage_InvalidNuspec,
                                                                        ex.Message)));
                        }

                        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 packageRegistration = PackageService.FindPackageRegistrationById(nuspec.GetId());
                        if (packageRegistration != null)
                        {
                            if (!packageRegistration.IsOwner(user))
                            {
                                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.Forbidden, 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,
                                                         nuspec.GetId(), nuspec.GetVersion().ToNormalizedStringSafe())));
                            }
                        }

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

                        var package = await PackageService.CreatePackageAsync(packageToPush, packageStreamMetadata, user, commitChanges : false);

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

                        await EntitiesContext.SaveChangesAsync();

                        using (Stream uploadStream = packageStream)
                        {
                            uploadStream.Position = 0;
                            await PackageFileService.SavePackageFileAsync(package, uploadStream.AsSeekableStream());

                            IndexingService.UpdatePackage(package);
                        }

                        return(new HttpStatusCodeResult(HttpStatusCode.Created));
                    }
                }
                catch (InvalidDataException ex)
                {
                    return(new HttpStatusCodeWithBodyResult(
                               HttpStatusCode.BadRequest,
                               string.Format(CultureInfo.CurrentCulture, Strings.UploadPackage_InvalidPackage, ex.Message)));
                }
            }
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Validates and creates a <see cref="Package"/> entity from a NuGet package archive.
        /// </summary>
        /// <param name="nugetPackage">A <see cref="PackageArchiveReader"/> instance from which package metadata can be read.</param>
        /// <param name="packageStreamMetadata">The <see cref="PackageStreamMetadata"/> instance providing metadata about the package stream.</param>
        /// <param name="owner">The <see cref="User"/> creating the package.</param>
        /// <param name="commitChanges"><c>True</c> to commit the changes to the data store and notify the indexing service; otherwise <c>false</c>.</param>
        /// <returns>Returns the created <see cref="Package"/> entity.</returns>
        /// <exception cref="InvalidPackageException">
        /// This exception will be thrown when a package metadata property violates a data validation constraint.
        /// </exception>
        public async Task <Package> CreatePackageAsync(PackageArchiveReader nugetPackage, PackageStreamMetadata packageStreamMetadata, User owner, User currentUser, bool isVerified)
        {
            PackageMetadata     packageMetadata;
            PackageRegistration packageRegistration;

            try
            {
                packageMetadata = PackageMetadata.FromNuspecReader(
                    nugetPackage.GetNuspecReader(),
                    strict: true);

                ValidateNuGetPackageMetadata(packageMetadata);

                ValidatePackageTitle(packageMetadata);

                packageRegistration = CreateOrGetPackageRegistration(owner, currentUser, packageMetadata, isVerified);
            }
            catch (Exception exception) when(exception is EntityException || exception is PackagingException)
            {
                // Wrap the exception for consistency of this API.
                throw new InvalidPackageException(exception.Message, exception);
            }

            var package = CreatePackageFromNuGetPackage(packageRegistration, nugetPackage, packageMetadata, packageStreamMetadata, currentUser);

            packageRegistration.Packages.Add(package);
            await UpdateIsLatestAsync(packageRegistration, commitChanges : false);

            return(package);
        }
Ejemplo n.º 27
0
        public virtual Package EnrichPackageFromNuGetPackage(
            Package package,
            PackageArchiveReader packageArchive,
            PackageMetadata packageMetadata,
            PackageStreamMetadata packageStreamMetadata,
            User user)
        {
            // Version must always be the exact string from the nuspec, which OriginalVersion will return to us.
            // However, we do also store a normalized copy for looking up later.
            package.Version           = packageMetadata.Version.OriginalVersion;
            package.NormalizedVersion = packageMetadata.Version.ToNormalizedString();

            package.Description               = packageMetadata.Description;
            package.ReleaseNotes              = packageMetadata.ReleaseNotes;
            package.HashAlgorithm             = packageStreamMetadata.HashAlgorithm;
            package.Hash                      = packageStreamMetadata.Hash;
            package.PackageFileSize           = packageStreamMetadata.Size;
            package.Language                  = packageMetadata.Language;
            package.Copyright                 = packageMetadata.Copyright;
            package.FlattenedAuthors          = packageMetadata.Authors.Flatten();
            package.IsPrerelease              = packageMetadata.Version.IsPrerelease;
            package.Listed                    = true;
            package.RequiresLicenseAcceptance = packageMetadata.RequireLicenseAcceptance;
            package.Summary                   = packageMetadata.Summary;
            package.Tags                      = PackageHelper.ParseTags(packageMetadata.Tags);
            package.Title                     = packageMetadata.Title;
            package.User                      = user;

            package.IconUrl          = packageMetadata.IconUrl.ToEncodedUrlStringOrNull();
            package.LicenseUrl       = packageMetadata.LicenseUrl.ToEncodedUrlStringOrNull();
            package.ProjectUrl       = packageMetadata.ProjectUrl.ToEncodedUrlStringOrNull();
            package.MinClientVersion = packageMetadata.MinClientVersion.ToStringOrNull();

#pragma warning disable 618 // TODO: remove Package.Authors completely once production services definitely no longer need it
            foreach (var author in packageMetadata.Authors)
            {
                package.Authors.Add(new PackageAuthor {
                    Name = author
                });
            }
#pragma warning restore 618

            var supportedFrameworks = GetSupportedFrameworks(packageArchive)
                                      .ToArray();

            if (!supportedFrameworks.Any(fx => fx != null && fx.IsAny))
            {
                var supportedFrameworkNames = supportedFrameworks
                                              .Select(fn => fn.ToShortNameOrNull())
                                              .Where(fn => fn != null)
                                              .ToArray();

                ValidateSupportedFrameworks(supportedFrameworkNames);

                foreach (var supportedFramework in supportedFrameworkNames)
                {
                    package.SupportedFrameworks.Add(new PackageFramework {
                        TargetFramework = supportedFramework
                    });
                }
            }

            package.Dependencies = packageMetadata
                                   .GetDependencyGroups()
                                   .AsPackageDependencyEnumerable()
                                   .ToList();

            package.PackageTypes = packageMetadata
                                   .GetPackageTypes()
                                   .AsPackageTypeEnumerable()
                                   .ToList();

            package.FlattenedDependencies = package.Dependencies.Flatten();

            package.FlattenedPackageTypes = package.PackageTypes.Flatten();

            // Identify the SemVerLevelKey using the original package version string and package dependencies
            package.SemVerLevelKey = SemVerLevelKey.ForPackage(packageMetadata.Version, package.Dependencies);

            return(package);
        }
Ejemplo n.º 28
0
        private Package CreatePackageFromNuGetPackage(PackageRegistration packageRegistration, PackageArchiveReader nugetPackage, PackageMetadata packageMetadata, PackageStreamMetadata packageStreamMetadata, User user)
        {
            var package = packageRegistration.Packages.SingleOrDefault(pv => pv.Version == packageMetadata.Version.OriginalVersion);

            if (package != null)
            {
                throw new EntityException(
                          "A package with identifier '{0}' and version '{1}' already exists.", packageRegistration.Id, package.Version);
            }

            package = new Package();
            package.PackageRegistration = packageRegistration;

            package = EnrichPackageFromNuGetPackage(package, nugetPackage, packageMetadata, packageStreamMetadata, user);

            return(package);
        }
Ejemplo n.º 29
0
        private async Task <ActionResult> CreatePackageInternal()
        {
            // 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 packageRegistration = PackageService.FindPackageRegistrationById(nuspec.GetId());
                        if (packageRegistration == null)
                        {
                            // Check if API key allows pushing a new package id
                            if (!ApiKeyScopeAllows(
                                    subject: nuspec.GetId(),
                                    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));
                            }
                        }
                        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.SaveAuditRecord(
                                    new FailedAuthenticatedOperationAuditRecord(
                                        user.Username,
                                        AuditedAuthenticatedOperationAction.PackagePushAttemptByNonOwner,
                                        attemptedPackage : new AuditedPackageIdentifier(
                                            nuspec.GetId(), 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())));
                            }

                            // 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,
                                                         nuspec.GetId(), nuspec.GetVersion().ToNormalizedStringSafe())));
                            }
                        }

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

                        var package = await PackageService.CreatePackageAsync(
                            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.SaveAuditRecord(
                            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.Version }, protocol: Request.Url.Scheme),
                                                              Url.Action("ReportMyPackage", "Packages", routeValues: new { id = package.PackageRegistration.Id, version = package.Version }, protocol: Request.Url.Scheme),
                                                              Url.Action("Account", "Users", routeValues: null, protocol: Request.Url.Scheme));

                        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));
                }
            }
        }
Ejemplo n.º 30
0
        [ValidateInput(false)] // Security note: Disabling ASP.Net input validation which does things like disallow angle brackets in submissions. See http://go.microsoft.com/fwlink/?LinkID=212874
        public virtual async Task <ActionResult> VerifyPackage(VerifyPackageRequest formData)
        {
            var currentUser = GetCurrentUser();

            Package package;

            using (Stream uploadFile = await _uploadFileService.GetUploadFileAsync(currentUser.Key))
            {
                if (uploadFile == null)
                {
                    TempData["Message"] = "Your attempt to verify the package submission failed, because we could not find the uploaded package file. Please try again.";
                    return(new RedirectResult(Url.UploadPackage()));
                }

                var nugetPackage = await SafeCreatePackage(currentUser, uploadFile);

                if (nugetPackage == null)
                {
                    // Send the user back
                    return(new RedirectResult(Url.UploadPackage()));
                }
                Debug.Assert(nugetPackage != null);

                var packageMetadata = PackageMetadata.FromNuspecReader(
                    nugetPackage.GetNuspecReader());

                // Rule out problem scenario with multiple tabs - verification request (possibly with edits) was submitted by user
                // viewing a different package to what was actually most recently uploaded
                if (!(String.IsNullOrEmpty(formData.Id) || String.IsNullOrEmpty(formData.Version)))
                {
                    if (!(String.Equals(packageMetadata.Id, formData.Id, StringComparison.OrdinalIgnoreCase) &&
                          String.Equals(packageMetadata.Version.ToNormalizedString(), formData.Version, StringComparison.OrdinalIgnoreCase)))
                    {
                        TempData["Message"] = "Your attempt to verify the package submission failed, because the package file appears to have changed. Please try again.";
                        return(new RedirectResult(Url.VerifyPackage()));
                    }
                }

                bool pendEdit = false;
                if (formData.Edit != null)
                {
                    pendEdit = pendEdit || formData.Edit.RequiresLicenseAcceptance != packageMetadata.RequireLicenseAcceptance;

                    pendEdit = pendEdit || IsDifferent(formData.Edit.IconUrl, packageMetadata.IconUrl.ToEncodedUrlStringOrNull());
                    pendEdit = pendEdit || IsDifferent(formData.Edit.ProjectUrl, packageMetadata.ProjectUrl.ToEncodedUrlStringOrNull());

                    pendEdit = pendEdit || IsDifferent(formData.Edit.Authors, packageMetadata.Authors.Flatten());
                    pendEdit = pendEdit || IsDifferent(formData.Edit.Copyright, packageMetadata.Copyright);
                    pendEdit = pendEdit || IsDifferent(formData.Edit.Description, packageMetadata.Description);
                    pendEdit = pendEdit || IsDifferent(formData.Edit.ReleaseNotes, packageMetadata.ReleaseNotes);
                    pendEdit = pendEdit || IsDifferent(formData.Edit.Summary, packageMetadata.Summary);
                    pendEdit = pendEdit || IsDifferent(formData.Edit.Tags, packageMetadata.Tags);
                    pendEdit = pendEdit || IsDifferent(formData.Edit.VersionTitle, packageMetadata.Title);
                }

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

                // update relevant database tables
                try
                {
                    package = await _packageService.CreatePackageAsync(nugetPackage, packageStreamMetadata, currentUser, commitChanges : false);

                    Debug.Assert(package.PackageRegistration != null);
                }
                catch (EntityException ex)
                {
                    TempData["Message"] = ex.Message;
                    return(Redirect(Url.UploadPackage()));
                }

                await _packageService.PublishPackageAsync(package, commitChanges : false);

                if (pendEdit)
                {
                    // Add the edit request to a queue where it will be processed in the background.
                    _editPackageService.StartEditPackageRequest(package, formData.Edit, currentUser);
                }

                if (!formData.Listed)
                {
                    await _packageService.MarkPackageUnlistedAsync(package, commitChanges : false);
                }

                await _autoCuratedPackageCmd.ExecuteAsync(package, nugetPackage, commitChanges : false);

                // save package to blob storage
                uploadFile.Position = 0;
                await _packageFileService.SavePackageFileAsync(package, uploadFile.AsSeekableStream());

                // commit all changes to database as an atomic transaction
                await _entitiesContext.SaveChangesAsync();

                // tell Lucene to update index for the new package
                _indexingService.UpdateIndex();

                _messageService.SendPackageAddedNotice(package,
                                                       Url.Action("DisplayPackage", "Packages", routeValues: new { id = package.PackageRegistration.Id, version = package.Version }, protocol: Request.Url.Scheme),
                                                       Url.Action("ReportMyPackage", "Packages", routeValues: new { id = package.PackageRegistration.Id, version = package.Version }, protocol: Request.Url.Scheme),
                                                       Url.Action("Account", "Users", routeValues: null, protocol: Request.Url.Scheme));
            }

            // delete the uploaded binary in the Uploads container
            await _uploadFileService.DeleteUploadFileAsync(currentUser.Key);

            TempData["Message"] = String.Format(
                CultureInfo.CurrentCulture, Strings.SuccessfullyUploadedPackage, package.PackageRegistration.Id, package.Version);

            return(RedirectToRoute(RouteName.DisplayPackage, new { package.PackageRegistration.Id, package.Version }));
        }