public async Task <BinaryMetadata> GetBinaryMetadata(string key)
        {
            var binaryMetadata = _memoryCache.Get <BinaryMetadata>(key);

            if (binaryMetadata != null)
            {
                return(binaryMetadata);
            }

            try
            {
                var metadataResponse = await _cephS3Client.GetObjectMetadataAsync(_filesBucketName, key);

                var metadataWrapper = MetadataCollectionWrapper.For(metadataResponse.Metadata);
                var filename        = metadataWrapper.Read <string>(MetadataElement.Filename);

                return(new BinaryMetadata(filename, metadataResponse.ContentLength));
            }
            catch (AmazonS3Exception ex) when(ex.StatusCode == HttpStatusCode.NotFound)
            {
                throw new ObjectNotFoundException($"Binary with the key '{key}' not found.");
            }
            catch (Exception ex)
            {
                throw new S3Exception(ex);
            }
        }
        public async Task VerifySessionExpirationForBinary(string key)
        {
            var sessionId = key.AsSessionId();

            var(_, _, expiresAt) = _memoryCache.Get <(SessionDescriptor, AuthorInfo, DateTime)>(sessionId);

            if (expiresAt == default)
            {
                GetObjectMetadataResponse response;
                try
                {
                    response = await _cephS3Client.GetObjectMetadataAsync(_filesBucketName, sessionId.AsS3ObjectKey(Tokens.SessionPostfix));
                }
                catch (AmazonS3Exception ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new ObjectNotFoundException($"Session '{sessionId}' does not exist");
                }
                catch (Exception ex)
                {
                    throw new S3Exception(ex);
                }

                var metadataWrapper = MetadataCollectionWrapper.For(response.Metadata);
                expiresAt = metadataWrapper.Read <DateTime>(MetadataElement.ExpiresAt);
            }

            if (SessionDescriptor.IsSessionExpired(expiresAt))
            {
                throw new SessionExpiredException(sessionId, expiresAt);
            }
        }
        public void ShouldWorkForAlmostJson()
        {
            var          wrapper = MetadataCollectionWrapper.For(new MetadataCollection());
            const string Value   = " { Вася Пупкин } ";

            wrapper.Write(MetadataElement.AuthorName, Value);
            var res = wrapper.Read <string>(MetadataElement.AuthorName);

            Assert.Equal(Value, res);
        }
        public void ShouldWorkForNonUsAsciiSymbols()
        {
            var wrapper = MetadataCollectionWrapper.For(new MetadataCollection());
            var value   = "Вася Пупкин";

            wrapper.Write(MetadataElement.AuthorName, value);
            var res = wrapper.Read <string>(MetadataElement.AuthorName);

            Assert.Equal(value, res);
        }
        public void ShouldWrapFilename()
        {
            var wrapper = MetadataCollectionWrapper.For(new MetadataCollection());
            var value   = "my_file.png";

            wrapper.Write(MetadataElement.Filename, value);
            var res = wrapper.Read <string>(MetadataElement.Filename);

            Assert.Equal(value, res);
        }
        public void ShouldWorkForAlreadyEncodedValue()
        {
            var wrapper      = MetadataCollectionWrapper.For(new MetadataCollection());
            var value        = "Вася Пупкин";
            var encodedValue = Uri.EscapeDataString(value);

            wrapper.Write(MetadataElement.AuthorName, "utf-8''" + encodedValue);
            var res = wrapper.Read <string>(MetadataElement.AuthorName);

            Assert.Equal(value, res);
        }
示例#7
0
        public async Task <(SessionDescriptor SessionDescriptor, AuthorInfo AuthorInfo, DateTime ExpiresAt)> GetSessionDescriptor(Guid sessionId)
        {
            var result =
                await _memoryCache.GetOrCreateAsync(
                    sessionId,
                    async entry =>
            {
                try
                {
                    using (var objectResponse = await _cephS3Client.GetObjectAsync(_filesBucketName, sessionId.AsS3ObjectKey(Tokens.SessionPostfix)))
                    {
                        var metadataWrapper = MetadataCollectionWrapper.For(objectResponse.Metadata);
                        var expiresAt       = metadataWrapper.Read <DateTime>(MetadataElement.ExpiresAt);
                        var author          = metadataWrapper.Read <string>(MetadataElement.Author);
                        var authorLogin     = metadataWrapper.Read <string>(MetadataElement.AuthorLogin);
                        var authorName      = metadataWrapper.Read <string>(MetadataElement.AuthorName);

                        string json;
                        using (var reader = new StreamReader(objectResponse.ResponseStream, Encoding.UTF8))
                        {
                            json = reader.ReadToEnd();
                        }

                        var sessionDescriptor = JsonConvert.DeserializeObject <SessionDescriptor>(json, SerializerSettings.Default);
                        var tuple             = (SessionDescriptor : sessionDescriptor, AuthorInfo : new AuthorInfo(author, authorLogin, authorName), ExpiresAt : expiresAt);

                        entry.SetValue(tuple)
                        .SetAbsoluteExpiration(expiresAt);

                        return(tuple);
                    }
                }
                catch (AmazonS3Exception ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new ObjectNotFoundException($"Session '{sessionId}' does not exist");
                }
                catch (SessionExpiredException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    throw new S3Exception(ex);
                }
            });

            if (SessionDescriptor.IsSessionExpired(result.ExpiresAt))
            {
                throw new SessionExpiredException(sessionId, result.ExpiresAt);
            }

            return(result);
        }
        public void ShouldWrapUsingInvariantCulture()
        {
            var wrapper = MetadataCollectionWrapper.For(new MetadataCollection());

            CultureInfo.CurrentCulture = new CultureInfo("en-US");
            var value = DateTime.UtcNow;

            wrapper.Write(MetadataElement.ExpiresAt, value);
            CultureInfo.CurrentCulture = new CultureInfo("ru-RU");
            var res = wrapper.Read <DateTime>(MetadataElement.ExpiresAt);

            Assert.Equal(value, res);
        }
        public async Task <IReadOnlyCollection <ObjectMetadataRecord> > GetObjectMetadatas(IReadOnlyCollection <long> ids)
        {
            var uniqueIds   = new HashSet <long>(ids);
            var partitioner = Partitioner.Create(uniqueIds);
            var result      = new ObjectMetadataRecord[uniqueIds.Count];
            var tasks       = partitioner
                              .GetOrderablePartitions(_degreeOfParallelism)
                              .Select(async x =>
            {
                while (x.MoveNext())
                {
                    var id = x.Current.Value;
                    ObjectMetadataRecord record;
                    try
                    {
                        var objectVersions = await GetObjectLatestVersions(id);
                        var versionId      = objectVersions.Where(v => v.Id.EndsWith(Tokens.ObjectPostfix))
                                             .Select(v => v.VersionId)
                                             .SingleOrDefault();
                        if (versionId == null)
                        {
                            record = null;
                        }
                        else
                        {
                            var response        = await _s3Client.GetObjectMetadataAsync(_bucketName, id.AsS3ObjectKey(Tokens.ObjectPostfix), versionId);
                            var metadataWrapper = MetadataCollectionWrapper.For(response.Metadata);
                            var author          = metadataWrapper.Read <string>(MetadataElement.Author);
                            var authorLogin     = metadataWrapper.Read <string>(MetadataElement.AuthorLogin);
                            var authorName      = metadataWrapper.Read <string>(MetadataElement.AuthorName);

                            record = new ObjectMetadataRecord(
                                id,
                                versionId,
                                response.LastModified,
                                new AuthorInfo(author, authorLogin, authorName));
                        }
                    }
                    catch (AmazonS3Exception ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                    {
                        record = null;
                    }

                    result[x.Current.Key] = record;
                }
            });
            await Task.WhenAll(tasks);

            return(result.Where(x => x != null).ToList());
        }
        public async Task <TemplateDescriptor> GetTemplateDescriptor(long id, string versionId)
        {
            var objectVersionId = string.IsNullOrEmpty(versionId) ? await GetTemplateLatestVersion(id) : versionId;

            var templateDescriptor = await _memoryCache.GetOrCreateAsync(
                id.AsCacheEntryKey(objectVersionId),
                async entry =>
            {
                try
                {
                    using (var response = await _s3Client.GetObjectAsync(_bucketName, id.ToString(), objectVersionId))
                    {
                        var metadataWrapper = MetadataCollectionWrapper.For(response.Metadata);
                        var author          = metadataWrapper.Read <string>(MetadataElement.Author);
                        var authorLogin     = metadataWrapper.Read <string>(MetadataElement.AuthorLogin);
                        var authorName      = metadataWrapper.Read <string>(MetadataElement.AuthorName);

                        string json;
                        using (var reader = new StreamReader(response.ResponseStream, Encoding.UTF8))
                        {
                            json = reader.ReadToEnd();
                        }

                        var descriptor = new TemplateDescriptor
                        {
                            Id           = id,
                            VersionId    = objectVersionId,
                            LastModified = response.LastModified,
                            Author       = author,
                            AuthorLogin  = authorLogin,
                            AuthorName   = authorName
                        };
                        JsonConvert.PopulateObject(json, descriptor, SerializerSettings.Default);

                        entry.SetValue(descriptor)
                        .SetPriority(CacheItemPriority.NeverRemove);

                        return(descriptor);
                    }
                }
                catch (AmazonS3Exception ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                {
                    throw new ObjectNotFoundException($"Template '{id}' version '{objectVersionId}' not found");
                }
            });

            return(templateDescriptor);
        }
        public async Task <IReadOnlyCollection <ObjectMetadataRecord> > GetTemplateMetadatas(IReadOnlyCollection <long> ids)
        {
            var uniqueIds   = new HashSet <long>(ids);
            var partitioner = Partitioner.Create(uniqueIds);
            var result      = new ObjectMetadataRecord[uniqueIds.Count];
            var tasks       = partitioner
                              .GetOrderablePartitions(_degreeOfParallelism)
                              .Select(async x =>
            {
                while (x.MoveNext())
                {
                    var templateId = x.Current.Value;
                    ObjectMetadataRecord record;
                    try
                    {
                        var versionId = await GetTemplateLatestVersion(templateId);

                        var response        = await _s3Client.GetObjectMetadataAsync(_bucketName, templateId.ToString(), versionId);
                        var metadataWrapper = MetadataCollectionWrapper.For(response.Metadata);
                        var author          = metadataWrapper.Read <string>(MetadataElement.Author);
                        var authorLogin     = metadataWrapper.Read <string>(MetadataElement.AuthorLogin);
                        var authorName      = metadataWrapper.Read <string>(MetadataElement.AuthorName);

                        record = new ObjectMetadataRecord(
                            templateId,
                            versionId,
                            response.LastModified,
                            new AuthorInfo(author, authorLogin, authorName));
                    }
                    catch (AmazonS3Exception ex) when(ex.StatusCode == HttpStatusCode.NotFound)
                    {
                        record = null;
                    }
                    catch (ObjectNotFoundException)
                    {
                        record = null;
                    }

                    result[x.Current.Key] = record;
                }
            });

            await Task.WhenAll(tasks);

            return(result.Where(x => x != null).ToList());
        }
示例#12
0
        public async Task <MultipartUploadSession> InitiateMultipartUpload(
            Guid sessionId,
            int templateCode,
            IUploadedFileMetadata uploadedFileMetadata)
        {
            if (string.IsNullOrEmpty(uploadedFileMetadata.FileName))
            {
                throw new MissingFilenameException($"Filename has not been provided for the item '{templateCode}'");
            }

            var(sessionDescriptor, _, expiresAt) = await _sessionStorageReader.GetSessionDescriptor(sessionId);

            if (sessionDescriptor.BinaryElementTemplateCodes.All(x => x != templateCode))
            {
                throw new InvalidTemplateException(
                          $"Binary content is not expected for the item '{templateCode}' within template '{sessionDescriptor.TemplateId}' " +
                          $"with version Id '{sessionDescriptor.TemplateVersionId}'.");
            }

            var elementDescriptor = await GetElementDescriptor(sessionDescriptor.TemplateId, sessionDescriptor.TemplateVersionId, templateCode);

            EnsureFileMetadataIsValid(elementDescriptor, sessionDescriptor.Language, uploadedFileMetadata);

            var fileKey = Guid.NewGuid().ToString();
            var key     = sessionId.AsS3ObjectKey(fileKey);
            var request = new InitiateMultipartUploadRequest
            {
                BucketName  = _filesBucketName,
                Key         = key,
                ContentType = uploadedFileMetadata.ContentType
            };
            var metadataWrapper = MetadataCollectionWrapper.For(request.Metadata);

            metadataWrapper.Write(MetadataElement.Filename, uploadedFileMetadata.FileName);

            var uploadResponse = await _cephS3Client.InitiateMultipartUploadAsync(request);

            return(new MultipartUploadSession(
                       sessionId,
                       sessionDescriptor,
                       expiresAt,
                       elementDescriptor,
                       uploadedFileMetadata,
                       fileKey,
                       uploadResponse.UploadId));
        }
        private async Task PutTemplate(long id, AuthorInfo authorInfo, ITemplateDescriptor templateDescriptor)
        {
            await VerifyElementDescriptorsConsistency(templateDescriptor.Elements);

            var putRequest = new PutObjectRequest
            {
                Key         = id.ToString(),
                BucketName  = _bucketName,
                ContentType = ContentType.Json,
                ContentBody = JsonConvert.SerializeObject(templateDescriptor, SerializerSettings.Default),
                CannedACL   = S3CannedACL.PublicRead,
            };
            var metadataWrapper = MetadataCollectionWrapper.For(putRequest.Metadata);

            metadataWrapper.Write(MetadataElement.Author, authorInfo.Author);
            metadataWrapper.Write(MetadataElement.AuthorLogin, authorInfo.AuthorLogin);
            metadataWrapper.Write(MetadataElement.AuthorName, authorInfo.AuthorName);

            await _s3Client.PutObjectAsync(putRequest);
        }
示例#14
0
        public async Task Setup(Guid sessionId, long templateId, string templateVersionId, Language language, AuthorInfo authorInfo)
        {
            if (language == Language.Unspecified)
            {
                throw new SessionCannotBeCreatedException("Language must be explicitly specified.");
            }

            var templateDescriptor = await _templatesStorageReader.GetTemplateDescriptor(templateId, templateVersionId);

            var sessionDescriptor = new SessionDescriptor
            {
                TemplateId                 = templateDescriptor.Id,
                TemplateVersionId          = templateDescriptor.VersionId,
                Language                   = language,
                BinaryElementTemplateCodes = templateDescriptor.GetBinaryElementTemplateCodes()
            };
            var request = new PutObjectRequest
            {
                BucketName  = _filesBucketName,
                Key         = sessionId.AsS3ObjectKey(Tokens.SessionPostfix),
                CannedACL   = S3CannedACL.PublicRead,
                ContentType = ContentType.Json,
                ContentBody = JsonConvert.SerializeObject(sessionDescriptor, SerializerSettings.Default)
            };

            var expiresAt       = SessionDescriptor.CurrentTime().Add(_sessionExpiration);
            var metadataWrapper = MetadataCollectionWrapper.For(request.Metadata);

            metadataWrapper.Write(MetadataElement.ExpiresAt, expiresAt);
            metadataWrapper.Write(MetadataElement.Author, authorInfo.Author);
            metadataWrapper.Write(MetadataElement.AuthorLogin, authorInfo.AuthorLogin);
            metadataWrapper.Write(MetadataElement.AuthorName, authorInfo.AuthorName);

            await _eventSender.SendAsync(_sessionsTopicName, new SessionCreatingEvent(sessionId, expiresAt));

            await _cephS3Client.PutObjectAsync(request);

            _createdSessionsMetric.Inc();
        }
        private async Task <IReadOnlyDictionary <int, IReadOnlyCollection <BinaryValidationError> > > VerifyObjectBinaryElementsConsistency(
            Language language,
            IReadOnlyCollection <IObjectElementDescriptor> elements)
        {
            var errors = new Dictionary <int, IReadOnlyCollection <BinaryValidationError> >();

            foreach (var binaryElement in elements.GetBinaryElements())
            {
                var elementErrors = new List <BinaryValidationError>();
                var constraints   = binaryElement.Constraints.For(language);
                var fileKeys      = binaryElement.Value.ExtractFileKeys();
                foreach (var fileKey in fileKeys)
                {
                    using (var getResponse = await _s3Client.GetObjectAsync(_filesBucketName, fileKey))
                    {
                        var memoryStream = new MemoryStream();
                        using (getResponse.ResponseStream)
                        {
                            await getResponse.ResponseStream.CopyToAsync(memoryStream);

                            memoryStream.Position = 0;
                        }

                        using (memoryStream)
                        {
                            var metadataWrapper = MetadataCollectionWrapper.For(getResponse.Metadata);
                            var fileName        = metadataWrapper.Read <string>(MetadataElement.Filename);
                            IUploadedFileMetadata binaryMetadata;
                            if (binaryElement.Value is ICompositeBitmapImageElementValue compositeBitmapImageElementValue &&
                                compositeBitmapImageElementValue.Raw != fileKey)
                            {
                                var image = compositeBitmapImageElementValue.SizeSpecificImages.First(x => x.Raw == fileKey);
                                binaryMetadata = new UploadedImageMetadata(
                                    fileName,
                                    getResponse.Headers.ContentType,
                                    getResponse.ContentLength,
                                    image.Size);
                            }
示例#16
0
        public async Task <(Stream, BinaryMetadata)> GetBinaryData(string fileKey)
        {
            try
            {
                using (var getResponse = await _cephS3Client.GetObjectAsync(_filesBucketName, fileKey))
                {
                    var memoryStream = new MemoryStream();
                    using (getResponse.ResponseStream)
                    {
                        await getResponse.ResponseStream.CopyToAsync(memoryStream);

                        memoryStream.Position = 0;
                    }

                    var metadataWrapper = MetadataCollectionWrapper.For(getResponse.Metadata);
                    var fileName        = metadataWrapper.Read <string>(MetadataElement.Filename);
                    return(memoryStream, new BinaryMetadata(fileName, getResponse.ContentLength, getResponse.Headers.ContentType));
                }
            }
            catch (AmazonS3Exception ex) when(ex.StatusCode == HttpStatusCode.NotFound)
            {
                throw new ObjectNotFoundException($"Binary with the key '{fileKey}' not found.");
            }
        }
示例#17
0
        public async Task <string> CompleteMultipartUpload(MultipartUploadSession uploadSession)
        {
            var uploadKey      = uploadSession.SessionId.AsS3ObjectKey(uploadSession.FileKey);
            var partETags      = uploadSession.Parts.Select(x => new PartETag(x.PartNumber, x.Etag)).ToList();
            var uploadResponse = await _cephS3Client.CompleteMultipartUploadAsync(
                new CompleteMultipartUploadRequest
            {
                BucketName = _filesBucketName,
                Key        = uploadKey,
                UploadId   = uploadSession.UploadId,
                PartETags  = partETags
            });

            uploadSession.Complete();

            if (SessionDescriptor.IsSessionExpired(uploadSession.SessionExpiresAt))
            {
                throw new SessionExpiredException(uploadSession.SessionId, uploadSession.SessionExpiresAt);
            }

            try
            {
                using (var getResponse = await _cephS3Client.GetObjectAsync(_filesBucketName, uploadKey))
                {
                    var memoryStream = new MemoryStream();
                    using (getResponse.ResponseStream)
                    {
                        getResponse.ResponseStream.CopyTo(memoryStream);
                        memoryStream.Position = 0;
                    }

                    using (memoryStream)
                    {
                        var sessionDescriptor = uploadSession.SessionDescriptor;
                        var elementDescriptor = uploadSession.ElementDescriptor;
                        EnsureFileContentIsValid(
                            elementDescriptor.TemplateCode,
                            elementDescriptor.Type,
                            elementDescriptor.Constraints.For(sessionDescriptor.Language),
                            memoryStream,
                            uploadSession.UploadedFileMetadata);
                    }

                    var metadataWrapper = MetadataCollectionWrapper.For(getResponse.Metadata);
                    var fileName        = metadataWrapper.Read <string>(MetadataElement.Filename);

                    var fileExtension = Path.GetExtension(fileName).ToLowerInvariant();
                    var fileKey       = Path.ChangeExtension(uploadSession.SessionId.AsS3ObjectKey(uploadResponse.ETag), fileExtension);
                    var copyRequest   = new CopyObjectRequest
                    {
                        ContentType       = uploadSession.UploadedFileMetadata.ContentType,
                        SourceBucket      = _filesBucketName,
                        SourceKey         = uploadKey,
                        DestinationBucket = _filesBucketName,
                        DestinationKey    = fileKey,
                        MetadataDirective = S3MetadataDirective.REPLACE,
                        CannedACL         = S3CannedACL.PublicRead
                    };
                    foreach (var metadataKey in getResponse.Metadata.Keys)
                    {
                        copyRequest.Metadata.Add(metadataKey, getResponse.Metadata[metadataKey]);
                    }

                    await _cephS3Client.CopyObjectAsync(copyRequest);

                    _uploadedBinariesMetric.Inc();

                    _memoryCache.Set(fileKey, new BinaryMetadata(fileName, getResponse.ContentLength), uploadSession.SessionExpiresAt);

                    return(fileKey);
                }
            }
            finally
            {
                await _cephS3Client.DeleteObjectAsync(_filesBucketName, uploadKey);
            }
        }
        public async Task CorrectJsonShouldBePassedToS3PutObjectForScalableBitmapImageElementWithoutAnchor()
        {
            const int      TemplateCode = 100;
            const Language Language     = Language.Ru;
            var            constraints  = new ScalableBitmapImageElementConstraints
            {
                SupportedFileFormats = new List <FileFormat> {
                    FileFormat.Png
                },
                ImageSizeRange = new ImageSizeRange {
                    Min = ImageSize.Empty, Max = new ImageSize {
                        Width = 500, Height = 500
                    }
                }
            };

            var templateDescriptor = new TemplateDescriptor
            {
                Id         = TemplateId,
                VersionId  = TemplateVersionId,
                Properties = new JObject(),
                Elements   = new[]
                {
                    new ElementDescriptor(
                        ElementDescriptorType.ScalableBitmapImage,
                        TemplateCode,
                        new JObject(),
                        new ConstraintSet(new[]
                    {
                        new ConstraintSetItem(Language, constraints)
                    }))
                }
            };

            _objectsStorageReaderMock.Setup(m => m.IsObjectExists(ObjectId))
            .ReturnsAsync(false);
            _templatesStorageReaderMock.Setup(m => m.GetTemplateDescriptor(TemplateId, TemplateVersionId))
            .ReturnsAsync(templateDescriptor);
            _objectsStorageReaderMock.Setup(m => m.GetObjectLatestVersion(It.IsAny <long>()))
            .ReturnsAsync(
                new VersionedObjectDescriptor <string>(
                    ObjectId.AsS3ObjectKey(Tokens.ObjectPostfix),
                    ObjectVersionId,
                    DateTime.UtcNow)
                );

            var response        = new GetObjectMetadataResponse();
            var metadataWrapper = MetadataCollectionWrapper.For(response.Metadata);

            metadataWrapper.Write(MetadataElement.ExpiresAt, DateTime.UtcNow.AddDays(1));

            _cephS3ClientMock.Setup(m => m.GetObjectMetadataAsync(It.IsAny <string>(), It.IsAny <string>()))
            .ReturnsAsync(response);

            var memoryStream = new MemoryStream();

            using (var stream = File.OpenRead(Path.Combine("images", "64x48.png")))
            {
                await stream.CopyToAsync(memoryStream);

                memoryStream.Position = 0;
            }

            var fileKey           = Guid.NewGuid().AsS3ObjectKey("key.raw");
            var getObjectResponse = new GetObjectResponse {
                ResponseStream = memoryStream
            };

            metadataWrapper = MetadataCollectionWrapper.For(getObjectResponse.Metadata);
            metadataWrapper.Write(MetadataElement.Filename, "file name.png");
            _s3ClientMock.Setup(m => m.GetObjectAsync(It.IsAny <string>(), fileKey, It.IsAny <CancellationToken>()))
            .ReturnsAsync(getObjectResponse);

            var requests = new List <PutObjectRequest>();

            _s3ClientMock.Setup(m => m.PutObjectAsync(It.IsAny <PutObjectRequest>()))
            .Callback <PutObjectRequest>(request => requests.Add(request))
            .ReturnsAsync(new PutObjectResponse());

            var objectDescriptor = new ObjectDescriptor
            {
                Language          = Language,
                TemplateId        = TemplateId,
                TemplateVersionId = TemplateVersionId,
                Properties        = new JObject(),
                Elements          = new[]
                {
                    new ObjectElementDescriptor
                    {
                        Type         = ElementDescriptorType.ScalableBitmapImage,
                        TemplateCode = TemplateCode,
                        Constraints  = new ConstraintSet(new[]
                        {
                            new ConstraintSetItem(Language, constraints)
                        }),
                        Value = new ScalableBitmapImageElementValue
                        {
                            Raw = fileKey
                        }
                    }
                }
            };

            await _objectsManagementService.Create(ObjectId, AuthorInfo, objectDescriptor);

            var elementContent = requests[0].ContentBody;
            var elementJson    = JObject.Parse(elementContent);
            var valueJson      = elementJson["value"];

            Assert.Equal(fileKey, valueJson["raw"]);
            Assert.NotNull(valueJson["filename"]);
            Assert.NotNull(valueJson["filesize"]);
            Assert.Equal(nameof(Anchor.Middle).ToLower(), valueJson["anchor"]);
        }
示例#19
0
        public async Task CorrectJsonShouldBePassedToS3PutObjectForScalableBitmapImageElementWithoutAnchor()
        {
            const int      TemplateCode = 100;
            const Language Language     = Language.Ru;
            var            constraints  = new ScalableBitmapImageElementConstraints();

            var templateDescriptor = new TemplateDescriptor
            {
                Id         = TemplateId,
                VersionId  = TemplateVersionId,
                Properties = new JObject(),
                Elements   = new[]
                {
                    new ElementDescriptor(
                        ElementDescriptorType.ScalableBitmapImage,
                        TemplateCode,
                        new JObject(),
                        new ConstraintSet(new[]
                    {
                        new ConstraintSetItem(Language, constraints)
                    }))
                }
            };

            _objectsStorageReaderMock.Setup(m => m.IsObjectExists(It.IsAny <long>()))
            .ReturnsAsync(() => false);
            _templatesStorageReaderMock.Setup(m => m.GetTemplateDescriptor(It.IsAny <long>(), It.IsAny <string>()))
            .ReturnsAsync(() => templateDescriptor);
            _templatesStorageReaderMock.Setup(m => m.GetTemplateLatestVersion(It.IsAny <long>()))
            .ReturnsAsync(() => TemplateVersionId);
            _objectsStorageReaderMock.Setup(m => m.GetObjectLatestVersions(It.IsAny <long>()))
            .ReturnsAsync(() => new[]
            {
                new VersionedObjectDescriptor <string>(
                    ObjectId.AsS3ObjectKey(Tokens.ObjectPostfix),
                    ObjectVersionId,
                    DateTime.UtcNow)
            });

            var response        = new GetObjectMetadataResponse();
            var metadataWrapper = MetadataCollectionWrapper.For(response.Metadata);

            metadataWrapper.Write(MetadataElement.ExpiresAt, DateTime.UtcNow.AddDays(1));

            _cephS3ClientMock.Setup(m => m.GetObjectMetadataAsync(It.IsAny <string>(), It.IsAny <string>()))
            .ReturnsAsync(() => response);

            var requests = new List <PutObjectRequest>();

            _s3ClientMock.Setup(m => m.PutObjectAsync(It.IsAny <PutObjectRequest>()))
            .Callback <PutObjectRequest>(request => requests.Add(request))
            .ReturnsAsync(new PutObjectResponse());

            var fileKey          = Guid.NewGuid().AsS3ObjectKey("key.raw");
            var objectDescriptor = new ObjectDescriptor
            {
                Language          = Language,
                TemplateId        = TemplateId,
                TemplateVersionId = TemplateVersionId,
                Properties        = new JObject(),
                Elements          = new[]
                {
                    new ObjectElementDescriptor
                    {
                        Type         = ElementDescriptorType.ScalableBitmapImage,
                        TemplateCode = TemplateCode,
                        Constraints  = new ConstraintSet(new[]
                        {
                            new ConstraintSetItem(Language, constraints)
                        }),
                        Value = new ScalableBitmapImageElementValue
                        {
                            Raw = fileKey
                        }
                    }
                }
            };

            await _objectsManagementService.Create(ObjectId, AuthorInfo, objectDescriptor);

            var elementContent = requests[0].ContentBody;
            var elementJson    = JObject.Parse(elementContent);
            var valueJson      = elementJson["value"];

            Assert.Equal(fileKey, valueJson["raw"]);
            Assert.NotNull(valueJson["filename"]);
            Assert.NotNull(valueJson["filesize"]);
            Assert.Equal(nameof(Anchor.Middle).ToLower(), valueJson["anchor"]);
        }
示例#20
0
        private async Task <string> PutObject(long id,
                                              string versionId,
                                              AuthorInfo authorInfo,
                                              IEnumerable <IObjectElementDescriptor> existingObjectElements,
                                              IObjectDescriptor objectDescriptor)
        {
            PreprocessObjectElements(objectDescriptor.Elements);
            await VerifyObjectElementsConsistency(id, objectDescriptor.Language, objectDescriptor.Elements);

            var metadataForBinaries = await RetrieveMetadataForBinaries(id, existingObjectElements, objectDescriptor.Elements);

            await _eventSender.SendAsync(_objectEventsTopic, new ObjectVersionCreatingEvent(id, versionId));

            var totalBinariesCount = 0;
            PutObjectRequest          putRequest;
            MetadataCollectionWrapper metadataWrapper;

            foreach (var elementDescriptor in objectDescriptor.Elements)
            {
                var(elementPersistenceValue, binariesCount) = ConvertToPersistenceValue(elementDescriptor.Value, metadataForBinaries);
                var elementPersistenceDescriptor = new ObjectElementPersistenceDescriptor(elementDescriptor, elementPersistenceValue);
                totalBinariesCount += binariesCount;
                putRequest          = new PutObjectRequest
                {
                    Key         = id.AsS3ObjectKey(elementDescriptor.Id),
                    BucketName  = _bucketName,
                    ContentType = ContentType.Json,
                    ContentBody = JsonConvert.SerializeObject(elementPersistenceDescriptor, SerializerSettings.Default),
                    CannedACL   = S3CannedACL.PublicRead
                };

                metadataWrapper = MetadataCollectionWrapper.For(putRequest.Metadata);
                metadataWrapper.Write(MetadataElement.Author, authorInfo.Author);
                metadataWrapper.Write(MetadataElement.AuthorLogin, authorInfo.AuthorLogin);
                metadataWrapper.Write(MetadataElement.AuthorName, authorInfo.AuthorName);

                await _s3Client.PutObjectAsync(putRequest);
            }

            var objectKey      = id.AsS3ObjectKey(Tokens.ObjectPostfix);
            var objectVersions = await _objectsStorageReader.GetObjectLatestVersions(id);

            var elementVersions             = objectVersions.Where(x => !x.Id.EndsWith(Tokens.ObjectPostfix)).ToList();
            var objectPersistenceDescriptor = new ObjectPersistenceDescriptor
            {
                TemplateId        = objectDescriptor.TemplateId,
                TemplateVersionId = objectDescriptor.TemplateVersionId,
                Language          = objectDescriptor.Language,
                Properties        = objectDescriptor.Properties,
                Elements          = elementVersions
            };

            putRequest = new PutObjectRequest
            {
                Key         = objectKey,
                BucketName  = _bucketName,
                ContentType = ContentType.Json,
                ContentBody = JsonConvert.SerializeObject(objectPersistenceDescriptor, SerializerSettings.Default),
                CannedACL   = S3CannedACL.PublicRead
            };

            metadataWrapper = MetadataCollectionWrapper.For(putRequest.Metadata);
            metadataWrapper.Write(MetadataElement.Author, authorInfo.Author);
            metadataWrapper.Write(MetadataElement.AuthorLogin, authorInfo.AuthorLogin);
            metadataWrapper.Write(MetadataElement.AuthorName, authorInfo.AuthorName);
            metadataWrapper.Write(
                MetadataElement.ModifiedElements,
                string.Join(Tokens.ModifiedElementsDelimiter.ToString(), objectDescriptor.Elements.Select(x => x.TemplateCode)));

            await _s3Client.PutObjectAsync(putRequest);

            _referencedBinariesMetric.Inc(totalBinariesCount);

            objectVersions = await _objectsStorageReader.GetObjectLatestVersions(id);

            return(objectVersions.Where(x => x.Id.EndsWith(Tokens.ObjectPostfix))
                   .Select(x => x.VersionId)
                   .Single());
        }
        public async Task CorrectJsonShouldBePassedToS3PutObjectForCompositeBitmapImageElement()
        {
            const int      TemplateCode = 100;
            const Language Language     = Language.Ru;
            var            constraints  = new CompositeBitmapImageElementConstraints
            {
                SupportedFileFormats = new List <FileFormat> {
                    FileFormat.Png
                },
                ImageSizeRange = new ImageSizeRange {
                    Min = ImageSize.Empty, Max = new ImageSize {
                        Width = 500, Height = 500
                    }
                }
            };

            var templateDescriptor = new TemplateDescriptor
            {
                Id         = TemplateId,
                VersionId  = TemplateVersionId,
                Properties = new JObject(),
                Elements   = new[]
                {
                    new ElementDescriptor(
                        ElementDescriptorType.CompositeBitmapImage,
                        TemplateCode,
                        new JObject(),
                        new ConstraintSet(new[]
                    {
                        new ConstraintSetItem(Language, constraints)
                    }))
                }
            };

            _objectsStorageReaderMock.Setup(m => m.IsObjectExists(It.IsAny <long>()))
            .ReturnsAsync(() => false);
            _templatesStorageReaderMock.Setup(m => m.GetTemplateDescriptor(It.IsAny <long>(), It.IsAny <string>()))
            .ReturnsAsync(() => templateDescriptor);
            _objectsStorageReaderMock.Setup(m => m.GetObjectLatestVersion(It.IsAny <long>()))
            .ReturnsAsync(new VersionedObjectDescriptor <long>(ObjectId, ObjectVersionId, DateTime.UtcNow));

            var response        = new GetObjectMetadataResponse();
            var metadataWrapper = MetadataCollectionWrapper.For(response.Metadata);

            metadataWrapper.Write(MetadataElement.ExpiresAt, DateTime.UtcNow.AddDays(1));

            _cephS3ClientMock.Setup(m => m.GetObjectMetadataAsync(It.IsAny <string>(), It.IsAny <string>()))
            .ReturnsAsync(() => response);

            var memoryStream = new MemoryStream();

            using (var stream = File.OpenRead(Path.Combine("images", "64x48.png")))
            {
                await stream.CopyToAsync(memoryStream);

                memoryStream.Position = 0;
            }

            var fileKey           = Guid.NewGuid().AsS3ObjectKey("key.raw");
            var getObjectResponse = new GetObjectResponse {
                ResponseStream = memoryStream
            };

            metadataWrapper = MetadataCollectionWrapper.For(getObjectResponse.Metadata);
            metadataWrapper.Write(MetadataElement.Filename, "file name.png");
            _cephS3ClientMock.Setup(m => m.GetObjectAsync(It.IsAny <string>(), fileKey, It.IsAny <CancellationToken>()))
            .ReturnsAsync(getObjectResponse);

            var objectDescriptor = new ObjectDescriptor
            {
                Language          = Language,
                TemplateId        = TemplateId,
                TemplateVersionId = TemplateVersionId,
                Properties        = new JObject(),
                Elements          = new[]
                {
                    new ObjectElementDescriptor
                    {
                        Type         = ElementDescriptorType.CompositeBitmapImage,
                        TemplateCode = TemplateCode,
                        Constraints  = new ConstraintSet(new[]
                        {
                            new ConstraintSetItem(Language, constraints)
                        }),
                        Value = new CompositeBitmapImageElementValue
                        {
                            Raw                = fileKey,
                            CropArea           = new CropArea(),
                            SizeSpecificImages = Array.Empty <SizeSpecificImage>()
                        }
                    }
                }
            };

            await _objectsManagementService.Create(ObjectId, AuthorInfo, objectDescriptor);

            Assert.True(await _inMemoryContext.Objects.AnyAsync());
            var element = await _inMemoryContext.ObjectElements.FirstOrDefaultAsync();

            Assert.NotNull(element);
            var elementJson = JObject.Parse(element.Data);
            var valueJson   = elementJson["value"];

            Assert.NotNull(valueJson);
            Assert.Equal(fileKey, valueJson["raw"]);
            Assert.NotNull(valueJson["filename"]);
            Assert.NotNull(valueJson["filesize"]);
            Assert.NotNull(valueJson["cropArea"]);
            Assert.NotNull(valueJson["sizeSpecificImages"]);
        }