From c9d3cabf2f5a8a597e93eb3052e9aefbfa1b9919 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 16 Jan 2020 15:03:24 +0100 Subject: [PATCH] Fake seek stream. --- .../HandleRules/EventEnricher.cs | 2 +- .../GraphQL/Types/AppQueriesGraphType.cs | 2 +- .../Assets/AmazonS3AssetStore.cs | 18 ++-- .../Assets/SeekFakerStream.cs | 85 +++++++++++++++++++ .../Assets/GoogleCloudAssetStore.cs | 2 +- .../Assets/MongoGridFsAssetStore.cs | 2 +- .../Assets/HasherStream.cs | 5 ++ .../Assets/AmazonS3AssetStoreFixture.cs | 5 +- 8 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 backend/src/Squidex.Infrastructure.Amazon/Assets/SeekFakerStream.cs diff --git a/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EventEnricher.cs b/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EventEnricher.cs index d9116e485..aa71f0c01 100644 --- a/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EventEnricher.cs +++ b/backend/src/Squidex.Domain.Apps.Core.Operations/HandleRules/EventEnricher.cs @@ -50,7 +50,7 @@ namespace Squidex.Domain.Apps.Core.HandleRules private Task FindUserAsync(RefToken actor) { - var key = $"EventEnrichers_Users_${actor.Identifier}"; + var key = $"EventEnrichers_Users_{actor.Identifier}"; return userCache.GetOrCreateAsync(key, async x => { diff --git a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppQueriesGraphType.cs b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppQueriesGraphType.cs index b079e203e..e33dc376d 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppQueriesGraphType.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Contents/GraphQL/Types/AppQueriesGraphType.cs @@ -246,7 +246,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL.Types string.Join("&", c.Arguments .Select(x => new { x.Key, Value = x.Value.ToString() }).Where(x => !string.IsNullOrWhiteSpace(x.Value)) - .Select(x => $"${x.Key}={x.Value}")); + .Select(x => $"{x.Key}={x.Value}")); return odataQuery; } diff --git a/backend/src/Squidex.Infrastructure.Amazon/Assets/AmazonS3AssetStore.cs b/backend/src/Squidex.Infrastructure.Amazon/Assets/AmazonS3AssetStore.cs index 01ef7d45d..e379b154b 100644 --- a/backend/src/Squidex.Infrastructure.Amazon/Assets/AmazonS3AssetStore.cs +++ b/backend/src/Squidex.Infrastructure.Amazon/Assets/AmazonS3AssetStore.cs @@ -5,6 +5,7 @@ // All rights reserved. Licensed under the MIT license. // ========================================================================== +using System; using System.IO; using System.Net; using System.Threading; @@ -65,12 +66,12 @@ namespace Squidex.Infrastructure.Assets if (!exists) { - throw new ConfigurationException($"Cannot connect to Amazon S3 bucket '${options.Bucket}'."); + throw new ConfigurationException($"Cannot connect to Amazon S3 bucket '{options.Bucket}'."); } } catch (AmazonS3Exception ex) { - throw new ConfigurationException($"Cannot connect to Amazon S3 bucket '${options.Bucket}'.", ex); + throw new ConfigurationException($"Cannot connect to Amazon S3 bucket '{options.Bucket}'.", ex); } } @@ -142,12 +143,13 @@ namespace Squidex.Infrastructure.Assets var request = new TransferUtilityUploadRequest { - AutoCloseStream = false, - BucketName = options.Bucket, - InputStream = stream, Key = GetKey(fileName) }; + ConfigureDefaults(request); + + request.InputStream = new SeekFakerStream(stream); + await transferUtility.UploadAsync(request, ct); } catch (AmazonS3Exception ex) when (ex.StatusCode == HttpStatusCode.PreconditionFailed) @@ -197,5 +199,11 @@ namespace Squidex.Infrastructure.Assets throw new AssetAlreadyExistsException(fileName); } + + private void ConfigureDefaults(TransferUtilityUploadRequest request) + { + request.AutoCloseStream = false; + request.BucketName = options.Bucket; + } } } \ No newline at end of file diff --git a/backend/src/Squidex.Infrastructure.Amazon/Assets/SeekFakerStream.cs b/backend/src/Squidex.Infrastructure.Amazon/Assets/SeekFakerStream.cs new file mode 100644 index 000000000..58e0a1809 --- /dev/null +++ b/backend/src/Squidex.Infrastructure.Amazon/Assets/SeekFakerStream.cs @@ -0,0 +1,85 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.IO; + +namespace Squidex.Infrastructure.Assets +{ + public sealed class SeekFakerStream : Stream + { + private readonly Stream inner; + + public override bool CanRead + { + get { return inner.CanRead; } + } + + public override bool CanSeek + { + get { return true; } + } + + public override bool CanWrite + { + get { return false; } + } + + public override long Length + { + get { return inner.Length; } + } + + public override long Position + { + get { return inner.Position; } + set { throw new NotSupportedException(); } + } + + public SeekFakerStream(Stream inner) + { + Guard.NotNull(inner); + + if (!inner.CanRead) + { + throw new ArgumentException("Inner stream must be readable."); + } + + this.inner = inner; + } + + public override int Read(byte[] buffer, int offset, int count) + { + return inner.Read(buffer, offset, count); + } + + public override void Flush() + { + throw new NotSupportedException(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + if (offset != 0 || origin != SeekOrigin.Begin) + { + throw new NotSupportedException(); + } + + return 0; + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + } +} diff --git a/backend/src/Squidex.Infrastructure.GoogleCloud/Assets/GoogleCloudAssetStore.cs b/backend/src/Squidex.Infrastructure.GoogleCloud/Assets/GoogleCloudAssetStore.cs index 947c7c222..0eeb7af71 100644 --- a/backend/src/Squidex.Infrastructure.GoogleCloud/Assets/GoogleCloudAssetStore.cs +++ b/backend/src/Squidex.Infrastructure.GoogleCloud/Assets/GoogleCloudAssetStore.cs @@ -39,7 +39,7 @@ namespace Squidex.Infrastructure.Assets } catch (Exception ex) { - throw new ConfigurationException($"Cannot connect to google cloud bucket '${bucketName}'.", ex); + throw new ConfigurationException($"Cannot connect to google cloud bucket '{bucketName}'.", ex); } } diff --git a/backend/src/Squidex.Infrastructure.MongoDb/Assets/MongoGridFsAssetStore.cs b/backend/src/Squidex.Infrastructure.MongoDb/Assets/MongoGridFsAssetStore.cs index cc8f2861e..391ac7781 100644 --- a/backend/src/Squidex.Infrastructure.MongoDb/Assets/MongoGridFsAssetStore.cs +++ b/backend/src/Squidex.Infrastructure.MongoDb/Assets/MongoGridFsAssetStore.cs @@ -35,7 +35,7 @@ namespace Squidex.Infrastructure.Assets } catch (MongoException ex) { - throw new ConfigurationException($"Cannot connect to Mongo GridFS bucket '${bucket.Options.BucketName}'.", ex); + throw new ConfigurationException($"Cannot connect to Mongo GridFS bucket '{bucket.Options.BucketName}'.", ex); } } diff --git a/backend/src/Squidex.Infrastructure/Assets/HasherStream.cs b/backend/src/Squidex.Infrastructure/Assets/HasherStream.cs index 314466fa7..40b366ffd 100644 --- a/backend/src/Squidex.Infrastructure/Assets/HasherStream.cs +++ b/backend/src/Squidex.Infrastructure/Assets/HasherStream.cs @@ -46,6 +46,11 @@ namespace Squidex.Infrastructure.Assets { Guard.NotNull(inner); + if (!inner.CanRead) + { + throw new ArgumentException("Inner stream must be readable."); + } + this.inner = inner; hasher = IncrementalHash.CreateHash(hashAlgorithmName); diff --git a/backend/tests/Squidex.Infrastructure.Tests/Assets/AmazonS3AssetStoreFixture.cs b/backend/tests/Squidex.Infrastructure.Tests/Assets/AmazonS3AssetStoreFixture.cs index d5aca5065..1851bb00c 100644 --- a/backend/tests/Squidex.Infrastructure.Tests/Assets/AmazonS3AssetStoreFixture.cs +++ b/backend/tests/Squidex.Infrastructure.Tests/Assets/AmazonS3AssetStoreFixture.cs @@ -13,14 +13,15 @@ namespace Squidex.Infrastructure.Assets public AmazonS3AssetStoreFixture() { + // From: https://console.aws.amazon.com/iam/home?region=eu-central-1#/users/s3?section=security_credentials AssetStore = new AmazonS3AssetStore(new AmazonS3Options { - AccessKey = "secret", + AccessKey = "AKIAYR4IRKRWJVE7BEUV", Bucket = "squidex-test", BucketFolder = "squidex-assets", ForcePathStyle = false, RegionName = "eu-central-1", - SecretKey = "secret", + SecretKey = "m7fJ0QzqcQ+2RGaYM7eGRs2QC0efOD+0oHn5UUho", ServiceUrl = null }); AssetStore.InitializeAsync().Wait();