diff --git a/appveyor.yml b/appveyor.yml index 868ac32..df57074 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.1.0.{build} +version: 3.0.0.{build} os: Visual Studio 2019 @@ -9,7 +9,7 @@ configuration: Release environment: # Version Suffix - version_suffix: alpha + version_suffix: beta3 install: - ps: .\build\appveyor-semver.ps1 @@ -73,6 +73,16 @@ deploy: on: branch: develop-umbraco-version-8 + # Umbraco MyGet community feed + - provider: NuGet + server: https://www.myget.org/F/umbraco-packages/api/v2/package + symbol_server: https://www.myget.org/F/umbraco-packages/symbols/api/v2/package + api_key: + secure: yvlnQEq6tmxGOdbtTuKyAhcdY1GCD98/sG9+Qo7y7SNb89GAbjLXxueOMspkjvUh + artifact: /.*\.nupkg/ + on: + branch: feature/sdk12 + # GitHub Deployment for releases - provider: GitHub auth_token: @@ -114,3 +124,24 @@ deploy: on: branch: master-umbraco-version-8 appveyor_repo_tag: true + + # GitHub Deployment for releases + - provider: GitHub + auth_token: + secure: Kucu1gQQf8bjRlkR72fyZUiUtmkz7rtZEIgK/RMT1pMnq700m5sSQTiFHOSQUdR5 + artifact: /.*\.zip/ # upload all Zip packages to release assets + draft: false + prerelease: false + on: + branch: main-version-3 + appveyor_repo_tag: true # deploy on tag push only + + # NuGet Deployment for releases + - provider: NuGet + server: + api_key: + secure: TtE4dizVNNLoy4gfrJDGRH1/vfNMTXiAxuMW0va1bcO1ZPXCw0qy12PUfIB+h9O3 + artifact: /.*\.nupkg/ + on: + branch: main-version-3 + appveyor_repo_tag: true diff --git a/build/UmbracoFileSystemProviders.Azure.Forms.proj b/build/UmbracoFileSystemProviders.Azure.Forms.proj index eb6e36c..7a79313 100644 --- a/build/UmbracoFileSystemProviders.Azure.Forms.proj +++ b/build/UmbracoFileSystemProviders.Azure.Forms.proj @@ -105,7 +105,7 @@ Description="$(Description)" Summary="$(Readme)" Version="$(FileVersion)" - MinimumRequiredUmbracoVersion ="$(MinUmbracoVersion)" + MinimumRequiredUmbracoVersion ="[$(MinUmbracoVersion),9.0.0)" Authors="$(AuthorName)" Owners="$(Owners)" Copyright="$(Copyright)" diff --git a/build/UmbracoFileSystemProviders.Azure.Media.proj b/build/UmbracoFileSystemProviders.Azure.Media.proj index b010736..3c58ff4 100644 --- a/build/UmbracoFileSystemProviders.Azure.Media.proj +++ b/build/UmbracoFileSystemProviders.Azure.Media.proj @@ -88,7 +88,7 @@ - + @@ -136,7 +136,7 @@ - - - - + + + \ No newline at end of file diff --git a/build/UmbracoFileSystemProviders.Azure.proj b/build/UmbracoFileSystemProviders.Azure.proj index ab5014c..f6cba33 100644 --- a/build/UmbracoFileSystemProviders.Azure.proj +++ b/build/UmbracoFileSystemProviders.Azure.proj @@ -99,7 +99,7 @@ Description="$(Description)" Summary="$(Readme)" Version="$(FileVersion)" - MinimumRequiredUmbracoVersion ="$(MinUmbracoVersion)" + MinimumRequiredUmbracoVersion ="[$(MinUmbracoVersion),9.0.0)" Authors="$(AuthorName)" Owners="$(Owners)" Copyright="$(Copyright)" diff --git a/build/transforms/umbpak-web.config.install.xdt b/build/transforms/umbpak-web.config.install.xdt index 12627eb..9a3a88e 100644 --- a/build/transforms/umbpak-web.config.install.xdt +++ b/build/transforms/umbpak-web.config.install.xdt @@ -2,8 +2,6 @@ - - @@ -11,10 +9,6 @@ - - - - @@ -23,10 +17,6 @@ - - - - \ No newline at end of file diff --git a/build/transforms/umbpak-web.config.uninstall.xdt b/build/transforms/umbpak-web.config.uninstall.xdt index 4d2396d..cd8725c 100644 --- a/build/transforms/umbpak-web.config.uninstall.xdt +++ b/build/transforms/umbpak-web.config.uninstall.xdt @@ -2,14 +2,10 @@ - - - - diff --git a/src/UmbracoFileSystemProviders.Azure.Installer/InstallerController.cs b/src/UmbracoFileSystemProviders.Azure.Installer/InstallerController.cs index 2266f83..04be900 100644 --- a/src/UmbracoFileSystemProviders.Azure.Installer/InstallerController.cs +++ b/src/UmbracoFileSystemProviders.Azure.Installer/InstallerController.cs @@ -15,9 +15,6 @@ namespace Our.Umbraco.FileSystemProviders.Azure.Installer using System.Web.Http; using System.Xml; - using Microsoft.Azure.Storage; - using Microsoft.Azure.Storage.Blob; - using global::Umbraco.Core; using global::Umbraco.Core.Composing; using global::Umbraco.Core.Logging; @@ -27,6 +24,8 @@ namespace Our.Umbraco.FileSystemProviders.Azure.Installer using Enums; using Models; + using global::Azure.Storage.Blobs; + using global::Azure.Storage.Blobs.Models; /// /// The installer controller for managing installer logic. @@ -84,7 +83,7 @@ public InstallerStatus PostParameters(IEnumerable parameters) bool usePrivateContainer = bool.Parse(newParameters.SingleOrDefault(k => k.Key == "UsePrivateContainer").Value); string rootUrl = newParameters.SingleOrDefault(k => k.Key == "RootUrl").Value; - BlobContainerPublicAccessType blobContainerPublicAccessType = usePrivateContainer ? BlobContainerPublicAccessType.Off : BlobContainerPublicAccessType.Blob; + var blobContainerPublicAccessType = usePrivateContainer ? PublicAccessType.None : PublicAccessType.Blob; if (!TestAzureCredentials(connection, containerName, blobContainerPublicAccessType)) { @@ -445,19 +444,18 @@ private static bool ExecuteImageProcessorSecurityConfigTransform() return true; } - private static bool TestAzureCredentials(string connectionString, string containerName, BlobContainerPublicAccessType accessType) + private static bool TestAzureCredentials(string connectionString, string containerName, PublicAccessType accessType) { bool useEmulator = ConfigurationHelper.GetAppSetting(Azure.Constants.Configuration.UseStorageEmulatorKey) != null && ConfigurationHelper.GetAppSetting(Azure.Constants.Configuration.UseStorageEmulatorKey) .Equals("true", StringComparison.InvariantCultureIgnoreCase); try { - CloudStorageAccount cloudStorageAccount = useEmulator ? CloudStorageAccount.DevelopmentStorageAccount : CloudStorageAccount.Parse(connectionString); - - CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient(); + var cloudStorageAccount = connectionString; // This should fully check that the connection works. - var testContainer = AzureFileSystem.CreateContainer(cloudBlobClient, containerName, accessType); + var azf = AzureFileSystem.GetInstance(containerName, "", connectionString, "", "", ""); + var testContainer = azf.CreateContainer( containerName, accessType); if (testContainer.Exists()) { diff --git a/src/UmbracoFileSystemProviders.Azure.Installer/UmbracoFileSystemProviders.Azure.Installer.csproj b/src/UmbracoFileSystemProviders.Azure.Installer/UmbracoFileSystemProviders.Azure.Installer.csproj index 245a3bd..fbdfc58 100644 --- a/src/UmbracoFileSystemProviders.Azure.Installer/UmbracoFileSystemProviders.Azure.Installer.csproj +++ b/src/UmbracoFileSystemProviders.Azure.Installer/UmbracoFileSystemProviders.Azure.Installer.csproj @@ -54,8 +54,14 @@ MinimumRecommendedRules.ruleset - - ..\packages\AutoMapper.8.0.0\lib\net461\AutoMapper.dll + + ..\packages\Azure.Core.1.18.0\lib\net461\Azure.Core.dll + + + ..\packages\Azure.Storage.Blobs.12.9.1\lib\netstandard2.0\Azure.Storage.Blobs.dll + + + ..\packages\Azure.Storage.Common.12.8.0\lib\netstandard2.0\Azure.Storage.Common.dll ..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll @@ -63,10 +69,6 @@ ..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll - - ..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll - True - ..\packages\CSharpTest.Net.Collections.14.906.1403.1082\lib\net40\CSharpTest.Net.Collections.dll @@ -117,17 +119,8 @@ ..\packages\Microsoft.AspNet.SignalR.Core.2.4.0\lib\net45\Microsoft.AspNet.SignalR.Core.dll - - ..\packages\Microsoft.Azure.ConfigurationManager.4.0.0\lib\net452\Microsoft.Azure.ConfigurationManager.dll - - - ..\packages\Microsoft.Azure.KeyVault.Core.3.0.3\lib\net452\Microsoft.Azure.KeyVault.Core.dll - - - ..\packages\Microsoft.Azure.Storage.Blob.11.1.2\lib\net452\Microsoft.Azure.Storage.Blob.dll - - - ..\packages\Microsoft.Azure.Storage.Common.11.1.2\lib\net452\Microsoft.Azure.Storage.Common.dll + + ..\packages\Microsoft.Bcl.AsyncInterfaces.1.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll ..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll @@ -135,9 +128,6 @@ ..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll - - ..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll - ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll @@ -170,9 +160,6 @@ ..\packages\MiniProfiler.Shared.4.0.138\lib\net461\MiniProfiler.Shared.dll - - ..\packages\MySql.Data.6.10.7\lib\net452\MySql.Data.dll - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll @@ -219,6 +206,9 @@ ..\packages\Superpower.2.0.0\lib\net45\Superpower.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + @@ -231,29 +221,51 @@ ..\packages\Umbraco.SqlServerCE.4.0.0.1\lib\net472\System.Data.SqlServerCe.Entity.dll - - ..\packages\System.Diagnostics.DiagnosticSource.4.4.1\lib\net46\System.Diagnostics.DiagnosticSource.dll + + ..\packages\System.Diagnostics.DiagnosticSource.4.6.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + ..\packages\System.Memory.Data.1.0.2\lib\net461\System.Memory.Data.dll + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + ..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll + + ..\packages\System.Text.Encodings.Web.4.7.2\lib\net461\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.4.6.0\lib\net461\System.Text.Json.dll + ..\packages\System.Threading.Tasks.Dataflow.4.9.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll + + ..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll diff --git a/src/UmbracoFileSystemProviders.Azure.Installer/app.config b/src/UmbracoFileSystemProviders.Azure.Installer/app.config index 4c68c1f..c5806ea 100644 --- a/src/UmbracoFileSystemProviders.Azure.Installer/app.config +++ b/src/UmbracoFileSystemProviders.Azure.Installer/app.config @@ -70,6 +70,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UmbracoFileSystemProviders.Azure.Installer/packages.config b/src/UmbracoFileSystemProviders.Azure.Installer/packages.config index 4d1159e..5b0c333 100644 --- a/src/UmbracoFileSystemProviders.Azure.Installer/packages.config +++ b/src/UmbracoFileSystemProviders.Azure.Installer/packages.config @@ -1,6 +1,8 @@  - + + + @@ -28,13 +30,9 @@ - - - - + - @@ -46,7 +44,6 @@ - @@ -64,16 +61,23 @@ + - + + + + + + + + - \ No newline at end of file diff --git a/src/UmbracoFileSystemProviders.Azure.Tests/UmbracoFileSystemProviders.Azure.Tests.csproj b/src/UmbracoFileSystemProviders.Azure.Tests/UmbracoFileSystemProviders.Azure.Tests.csproj index a249ff2..9ac7ca4 100644 --- a/src/UmbracoFileSystemProviders.Azure.Tests/UmbracoFileSystemProviders.Azure.Tests.csproj +++ b/src/UmbracoFileSystemProviders.Azure.Tests/UmbracoFileSystemProviders.Azure.Tests.csproj @@ -56,8 +56,14 @@ MinimumRecommendedRules.ruleset - - ..\packages\AutoMapper.8.0.0\lib\net461\AutoMapper.dll + + ..\packages\Azure.Core.1.18.0\lib\net461\Azure.Core.dll + + + ..\packages\Azure.Storage.Blobs.12.9.1\lib\netstandard2.0\Azure.Storage.Blobs.dll + + + ..\packages\Azure.Storage.Common.12.8.0\lib\netstandard2.0\Azure.Storage.Common.dll ..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll @@ -65,9 +71,6 @@ ..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll - - ..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll - ..\packages\CSharpTest.Net.Collections.14.906.1403.1082\lib\net40\CSharpTest.Net.Collections.dll @@ -117,17 +120,8 @@ ..\packages\Microsoft.AspNet.SignalR.Core.2.4.0\lib\net45\Microsoft.AspNet.SignalR.Core.dll - - ..\packages\Microsoft.Azure.ConfigurationManager.4.0.0\lib\net452\Microsoft.Azure.ConfigurationManager.dll - - - ..\packages\Microsoft.Azure.KeyVault.Core.3.0.3\lib\net452\Microsoft.Azure.KeyVault.Core.dll - - - ..\packages\Microsoft.Azure.Storage.Blob.11.1.2\lib\net452\Microsoft.Azure.Storage.Blob.dll - - - ..\packages\Microsoft.Azure.Storage.Common.11.1.2\lib\net452\Microsoft.Azure.Storage.Common.dll + + ..\packages\Microsoft.Bcl.AsyncInterfaces.1.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll ..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll @@ -135,9 +129,6 @@ ..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll - - ..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll - ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll @@ -169,9 +160,6 @@ ..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll - - ..\packages\MySql.Data.6.10.7\lib\net452\MySql.Data.dll - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll @@ -221,6 +209,9 @@ ..\packages\Superpower.2.0.0\lib\net45\Superpower.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + @@ -233,30 +224,52 @@ ..\packages\Umbraco.SqlServerCE.4.0.0.1\lib\net472\System.Data.SqlServerCe.Entity.dll - - ..\packages\System.Diagnostics.DiagnosticSource.4.4.1\lib\net46\System.Diagnostics.DiagnosticSource.dll + + ..\packages\System.Diagnostics.DiagnosticSource.4.6.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + ..\packages\System.Memory.Data.1.0.2\lib\net461\System.Memory.Data.dll + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + ..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll + + ..\packages\System.Text.Encodings.Web.4.7.2\lib\net461\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.4.6.0\lib\net461\System.Text.Json.dll + ..\packages\System.Threading.Tasks.Dataflow.4.9.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll + + ..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll diff --git a/src/UmbracoFileSystemProviders.Azure.Tests/app.config b/src/UmbracoFileSystemProviders.Azure.Tests/app.config index a4eb9a8..2ab61d5 100644 --- a/src/UmbracoFileSystemProviders.Azure.Tests/app.config +++ b/src/UmbracoFileSystemProviders.Azure.Tests/app.config @@ -102,6 +102,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UmbracoFileSystemProviders.Azure.Tests/packages.config b/src/UmbracoFileSystemProviders.Azure.Tests/packages.config index 40f1f98..6f66ebf 100644 --- a/src/UmbracoFileSystemProviders.Azure.Tests/packages.config +++ b/src/UmbracoFileSystemProviders.Azure.Tests/packages.config @@ -1,6 +1,8 @@  - + + + @@ -27,13 +29,9 @@ - - - - + - @@ -45,7 +43,6 @@ - @@ -65,16 +62,23 @@ + - + + + + + + + + - \ No newline at end of file diff --git a/src/UmbracoFileSystemProviders.Azure/AzureBlobDirectory.cs b/src/UmbracoFileSystemProviders.Azure/AzureBlobDirectory.cs new file mode 100644 index 0000000..4b86639 --- /dev/null +++ b/src/UmbracoFileSystemProviders.Azure/AzureBlobDirectory.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Azure; +using Azure.Storage.Blobs; +using Azure.Storage.Blobs.Models; + +namespace Our.Umbraco.FileSystemProviders.Azure +{ + internal class AzureBlobDirectory + { + public BlobContainerClient Container { get; } + + public AzureBlobDirectory(BlobContainerClient container, string path) + { + this.Container = container; + this.Prefix = path; + } + + public string Prefix { get; } + + public Pageable ListBlobs() + { + if (string.IsNullOrEmpty(Prefix)) + { + return Container.GetBlobsByHierarchy(); + } + return Container.GetBlobsByHierarchy(prefix: Prefix); + } + + } +} diff --git a/src/UmbracoFileSystemProviders.Azure/AzureFileSystem.cs b/src/UmbracoFileSystemProviders.Azure/AzureFileSystem.cs index c837618..a686a93 100644 --- a/src/UmbracoFileSystemProviders.Azure/AzureFileSystem.cs +++ b/src/UmbracoFileSystemProviders.Azure/AzureFileSystem.cs @@ -16,13 +16,13 @@ namespace Our.Umbraco.FileSystemProviders.Azure using System.Linq; using System.Text.RegularExpressions; using System.Web; + using global::Azure; + using global::Azure.Storage.Blobs; + using global::Azure.Storage.Blobs.Models; using global::Umbraco.Core.Composing; using global::Umbraco.Core.Configuration; using global::Umbraco.Core.IO; using global::Umbraco.Core.Logging; - using Microsoft.Azure.Storage; - using Microsoft.Azure.Storage.Blob; - using Microsoft.Azure.Storage.Blob.Protocol; /// /// A class for communicating with Azure Blob Storage. @@ -72,7 +72,7 @@ public class AzureFileSystem : IFileSystem /// /// The cloud media blob container. /// - private readonly CloudBlobContainer cloudBlobContainer; + private readonly BlobContainerClient cloudBlobContainer; /// /// Initializes a new instance of the class. @@ -89,7 +89,7 @@ public class AzureFileSystem : IFileSystem /// /// Thrown if is invalid. /// - internal AzureFileSystem(string containerName, string rootUrl, string connectionString, int maxDays, bool useDefaultRoute, BlobContainerPublicAccessType accessType) + internal AzureFileSystem(string containerName, string rootUrl, string connectionString, int maxDays, bool useDefaultRoute, PublicAccessType accessType) { if (string.IsNullOrWhiteSpace(containerName)) { @@ -104,64 +104,19 @@ internal AzureFileSystem(string containerName, string rootUrl, string connection && ConfigurationHelper.GetAppSetting(UseStorageEmulatorKey) .Equals("true", StringComparison.InvariantCultureIgnoreCase); - CloudStorageAccount cloudStorageAccount; if (useEmulator) { - cloudStorageAccount = CloudStorageAccount.DevelopmentStorageAccount; - rootUrl = cloudStorageAccount.BlobStorageUri.PrimaryUri.AbsoluteUri; + _connectionString = "UseDevelopmentStorage=true"; + rootUrl = "http://127.0.0.1:10000/devstoreaccount1/"; } else { - cloudStorageAccount = CloudStorageAccount.Parse(connectionString); + _connectionString = connectionString; } - CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient(); - this.cloudBlobContainer = CreateContainer(cloudBlobClient, containerName, accessType); - if (cloudStorageAccount.Credentials.IsSAS) - { - bool isValidSas = true; - var sasTokenParts = cloudStorageAccount.Credentials.SASToken.Split('&'); - var si = sasTokenParts.Where(t => t.StartsWith("si=")).FirstOrDefault(); - if (si != null) - { - var siValue = si.Split('=')[1]; - - // I could not find a way how to get the permissions of a referenced access policy - // var permissions = this.cloudBlobContainer.GetPermissions(AccessCondition.GenerateIfExistsCondition()); - } - else - { - var sr = sasTokenParts.Where(t => t.StartsWith("sr=")).FirstOrDefault(); - var ss = sasTokenParts.Where(t => t.StartsWith("ss=")).FirstOrDefault(); - var srt = sasTokenParts.Where(t => t.StartsWith("srt=")).FirstOrDefault(); - var sp = sasTokenParts.Where(t => t.StartsWith("sp=")).FirstOrDefault(); - if ((ss == null || !ss.Contains("b")) && (sr == null || !sr.Contains("c"))) - { - isValidSas = false; - } - else if (sp != null) - { - var value = sp.Split('=')[1].ToCharArray(); - if (!value.Contains('r') || !value.Contains('w') || !value.Contains('d') || !value.Contains('l')) - { - isValidSas = false; - } - else if (srt != null) - { - value = srt.Split('=')[1].ToCharArray(); - if (!value.Contains('s') || !value.Contains('c') || !value.Contains('o')) - { - isValidSas = false; - } - } - } - } + ValidateSasToken(connectionString); - if (!isValidSas) - { - throw new Exception("SAS token permissions do NOT grant full functionality for UmbracoFileSystemProviders.Azure."); - } - } + this.cloudBlobContainer = CreateContainer(containerName, accessType); // First assign a local copy before editing. We use that to track the type. // TODO: Do we need this? The container should be an identifer. @@ -180,6 +135,54 @@ internal AzureFileSystem(string containerName, string rootUrl, string connection this.MimeTypeResolver = new MimeTypeResolver(); } + private static void ValidateSasToken(string connectionString) + { + //TODO: Validate SAS + + //bool isValidSas = true; + //var sasTokenParts = cloudStorageAccount.Credentials.SASToken.Split('&'); + //var si = sasTokenParts.Where(t => t.StartsWith("si=")).FirstOrDefault(); + //if (si != null) + //{ + // var siValue = si.Split('=')[1]; + + // // I could not find a way how to get the permissions of a referenced access policy + // // var permissions = this.cloudBlobContainer.GetPermissions(AccessCondition.GenerateIfExistsCondition()); + //} + //else + //{ + // var sr = sasTokenParts.Where(t => t.StartsWith("sr=")).FirstOrDefault(); + // var ss = sasTokenParts.Where(t => t.StartsWith("ss=")).FirstOrDefault(); + // var srt = sasTokenParts.Where(t => t.StartsWith("srt=")).FirstOrDefault(); + // var sp = sasTokenParts.Where(t => t.StartsWith("sp=")).FirstOrDefault(); + // if ((ss == null || !ss.Contains("b")) && (sr == null || !sr.Contains("c"))) + // { + // isValidSas = false; + // } + // else if (sp != null) + // { + // var value = sp.Split('=')[1].ToCharArray(); + // if (!value.Contains('r') || !value.Contains('w') || !value.Contains('d') || !value.Contains('l')) + // { + // isValidSas = false; + // } + // else if (srt != null) + // { + // value = srt.Split('=')[1].ToCharArray(); + // if (!value.Contains('s') || !value.Contains('c') || !value.Contains('o')) + // { + // isValidSas = false; + // } + // } + // } + //} + + //if (!isValidSas) + //{ + // throw new Exception("SAS token permissions do NOT grant full functionality for UmbracoFileSystemProviders.Azure."); + //} + } + /// /// Gets or sets the MIME type resolver. /// @@ -246,7 +249,7 @@ public static AzureFileSystem GetInstance(string containerName, string rootUrl, privateContainer = true; } - BlobContainerPublicAccessType blobContainerPublicAccessType = privateContainer ? BlobContainerPublicAccessType.Off : BlobContainerPublicAccessType.Blob; + PublicAccessType blobContainerPublicAccessType = privateContainer ? PublicAccessType.None : PublicAccessType.Blob; fileSystem = new AzureFileSystem(containerName, rootUrl, connectionString, max, defaultRoute, blobContainerPublicAccessType); FileSystems.Add(fileSystem); @@ -266,7 +269,7 @@ public void AddFile(string path, Stream stream, bool overrideIfExists) { Current.Logger.Debug($"AddFile(path, steam, overrideIfExists) method executed with path:{path}"); - CloudBlockBlob blockBlob = this.GetBlockBlobReference(path); + BlobClient blockBlob = this.GetBlockBlobReference(path); if (blockBlob != null) { @@ -282,45 +285,43 @@ public void AddFile(string path, Stream stream, bool overrideIfExists) try { + BlobProperties properties = null; if (exists) { // Ensure original created date is preserved. - blockBlob.FetchAttributes(); - if (blockBlob.Metadata.ContainsKey("CreatedDate")) + properties = blockBlob.GetProperties().Value; + if (properties.Metadata.ContainsKey("CreatedDate")) { // We store the creation date in meta data. - created = DateTime.Parse(blockBlob.Metadata["CreatedDate"], CultureInfo.InvariantCulture).ToUniversalTime(); + created = DateTime.Parse(properties.Metadata["CreatedDate"], CultureInfo.InvariantCulture).ToUniversalTime(); } } - blockBlob.UploadFromStream(stream); + blockBlob.Upload(stream,overrideIfExists); string contentType = this.MimeTypeResolver.Resolve(path); + properties = blockBlob.GetProperties().Value; + var updatedHeaders = new BlobHttpHeaders(); if (!string.IsNullOrWhiteSpace(contentType)) { - blockBlob.Properties.ContentType = contentType; + updatedHeaders.ContentType = contentType; } - blockBlob.Properties.CacheControl = $"public, max-age={this.MaxDays * 86400}"; - blockBlob.SetProperties(); + updatedHeaders.CacheControl = $"public, max-age={this.MaxDays * 86400}"; + + blockBlob.SetHttpHeaders(updatedHeaders); if (created == DateTimeOffset.MinValue) { created = DateTimeOffset.UtcNow; } + var updatedProps = new Dictionary(); // Store the creation date in meta data. - if (blockBlob.Metadata.ContainsKey("CreatedDate")) - { - blockBlob.Metadata["CreatedDate"] = created.ToString(CultureInfo.InvariantCulture); - } - else - { - blockBlob.Metadata.Add("CreatedDate", created.ToString(CultureInfo.InvariantCulture)); - } + updatedProps.Add("CreatedDate",created.ToString(CultureInfo.InvariantCulture)); - blockBlob.SetMetadata(); + blockBlob.SetMetadata(updatedProps); } catch (Exception ex) { @@ -369,21 +370,22 @@ public void DeleteDirectory(string path, bool recursive) return; } - CloudBlobDirectory directory = this.GetDirectoryReference(path); + var directory = this.GetDirectoryReference(path); // WB: This will only delete a folder if it only has files & not sub directories - // IEnumerable blobs = directory.ListBlobs().OfType(); - IEnumerable blobs = directory.ListBlobs(); + // IEnumerable blobs = directory.ListBlobs().OfType(); + var blobs = directory.ListBlobs(); if (recursive) { - foreach (IListBlobItem blobItem in blobs) + foreach (var blobItem in blobs) { try { - if (blobItem is CloudBlobDirectory) + + if (blobItem.IsPrefix) { - CloudBlobDirectory blobFolder = blobItem as CloudBlobDirectory; + var blobFolder = new AzureBlobDirectory(directory.Container, blobItem.Prefix); // Resursively call this method this.DeleteDirectory(blobFolder.Prefix); @@ -391,7 +393,7 @@ public void DeleteDirectory(string path, bool recursive) else { // Can assume its a file aka CloudBlob - CloudBlockBlob blobFile = blobItem as CloudBlockBlob; + var blobFile = GetBlockBlobReference(blobItem.Blob.Name); blobFile?.DeleteIfExists(DeleteSnapshotsOption.IncludeSnapshots); } } @@ -428,7 +430,7 @@ public void DeleteFile(string path) { Current.Logger.Debug($"DeleteFile(path) method executed with path:{path}"); - CloudBlockBlob blockBlob = this.GetBlockBlobReference(path); + var blockBlob = this.GetBlockBlobReference(path); if (blockBlob != null) { @@ -455,7 +457,7 @@ public bool DirectoryExists(string path) Current.Logger.Debug($"DirectoryExists(path) method executed with path:{path}"); string fixedPath = this.FixPath(path); - CloudBlobDirectory directory = this.cloudBlobContainer.GetDirectoryReference(fixedPath); + var directory = new AzureBlobDirectory(cloudBlobContainer,fixedPath); return directory.ListBlobs().Any(); } @@ -471,7 +473,7 @@ public bool FileExists(string path) { Current.Logger.Debug($"FileExists(path) method executed with path:{path}"); - CloudBlockBlob blockBlobReference = this.GetBlockBlobReference(path); + var blockBlobReference = this.GetBlockBlobReference(path); return blockBlobReference?.Exists() ?? false; } @@ -486,16 +488,16 @@ public DateTimeOffset GetCreated(string path) { Current.Logger.Debug($"GetCreated(path) method executed with path:{path}"); - CloudBlockBlob blockBlob = this.GetBlockBlobReference(path); + var blockBlob = this.GetBlockBlobReference(path); if (blockBlob != null) { // Populate the blob's attributes. - blockBlob.FetchAttributes(); - if (blockBlob.Metadata.ContainsKey("CreatedDate")) + var properties = blockBlob.GetProperties().Value; + if (properties.Metadata.ContainsKey("CreatedDate")) { // We store the creation date in meta data. - return DateTimeOffset.Parse(blockBlob.Metadata["CreatedDate"], CultureInfo.InvariantCulture).ToUniversalTime(); + return DateTimeOffset.Parse(properties.Metadata["CreatedDate"], CultureInfo.InvariantCulture).ToUniversalTime(); } } @@ -513,12 +515,16 @@ public IEnumerable GetDirectories(string path) { Current.Logger.Debug($"GetDirectories(path) method executed with path:{path}"); - CloudBlobDirectory directory = this.GetDirectoryReference(path); + var directory = this.GetDirectoryReference(path); + + var listedBlobs = directory.ListBlobs(); + var prefixes = listedBlobs.Where(blob => blob.IsPrefix).Select(x=>x.Prefix).ToList(); + var blobPrefixes = listedBlobs.Where(x => x.IsBlob && x.Blob.Name.LastIndexOf('/') >= 0).Select(x => x.Blob.Name.Substring(0, x.Blob.Name.LastIndexOf('/') + 1)); - IEnumerable blobs = directory.ListBlobs().Where(blob => blob is CloudBlobDirectory).ToList(); // Always get last segment for media sub folder simulation. E.g 1001, 1002 - return blobs.Cast().Select(cd => cd.Prefix.TrimEnd('/')); + var all = prefixes.Union(blobPrefixes); + return all.Select(cd => cd.TrimEnd('/')); } /// @@ -533,9 +539,9 @@ public IEnumerable GetFiles(string path, string filter) { Current.Logger.Debug($"GetFiles(path, filter) method executed with path:{path} & filter {filter}"); - IEnumerable blobs = this.cloudBlobContainer.ListBlobs(this.FixPath(path), true); + IEnumerable blobs = this.cloudBlobContainer.GetBlobsByHierarchy(prefix:this.FixPath(path)); - var blobList = blobs as IList ?? blobs.ToList(); + var blobList = blobs as IList ?? blobs.ToList(); if (!blobList.Any()) { @@ -544,9 +550,9 @@ public IEnumerable GetFiles(string path, string filter) return Enumerable.Empty(); } - return blobList.OfType().Select(cd => + return blobList.Where(x=>x.IsBlob).Select(cd => { - string url = cd.Uri.AbsoluteUri; + string url = cloudBlobContainer.Uri.AbsoluteUri + "/" + cd.Blob.Name; if (filter.Equals("*.*", StringComparison.InvariantCultureIgnoreCase)) { @@ -603,12 +609,12 @@ public DateTimeOffset GetLastModified(string path) { Current.Logger.Debug($"GetLastModified(path) method executed with path:{path}"); - CloudBlockBlob blockBlob = this.GetBlockBlobReference(path); + var blockBlob = this.GetBlockBlobReference(path); if (blockBlob != null) { - blockBlob.FetchAttributes(); - return blockBlob.Properties.LastModified.GetValueOrDefault(); + var properties = blockBlob.GetProperties().Value; + return properties.LastModified; } return DateTimeOffset.MinValue; @@ -653,11 +659,12 @@ public long GetSize(string path) { Current.Logger.Debug($"GetSize(path) method executed with path:{path}"); - CloudBlockBlob blockBlob = this.GetBlockBlobReference(path); + var blockBlob = this.GetBlockBlobReference(path); if (blockBlob != null) { - return blockBlob.Properties.Length; + var properties = blockBlob.GetProperties().Value; + return properties.ContentLength; } return long.MinValue; @@ -674,7 +681,7 @@ public Stream OpenFile(string path) { Current.Logger.Debug($"OpenFile(path) method executed with path:{path}"); - CloudBlockBlob blockBlob = this.GetBlockBlobReference(path); + var blockBlob = this.GetBlockBlobReference(path); if (blockBlob != null) { @@ -685,7 +692,7 @@ public Stream OpenFile(string path) } MemoryStream stream = new MemoryStream(); - blockBlob.DownloadToStream(stream); + blockBlob.DownloadTo(stream); if (stream.CanSeek) { @@ -698,6 +705,24 @@ public Stream OpenFile(string path) return null; } + public string GetETag(string path,string format = "G") + { + Current.Logger.Debug($"GetSize(path) method executed with path:{path}"); + + var blockBlob = this.GetBlockBlobReference(path); + + if (blockBlob != null) + { + var properties = blockBlob.GetProperties().Value; + return properties.ETag.ToString(format); + } + + return null; + } + + private string _connectionString; + + private bool _isSasCredential = false;// cloudBlobClient.Credentials.IsSAS; /// /// Returns the media container, creating a new one if none exists. /// @@ -705,7 +730,7 @@ public Stream OpenFile(string path) /// The name of the container. /// indicating the access permissions. /// The - public static CloudBlobContainer CreateContainer(CloudBlobClient cloudBlobClient, string containerName, BlobContainerPublicAccessType accessType) + public BlobContainerClient CreateContainer(string containerName, PublicAccessType accessType) { Current.Logger.Debug($"CreateContainer(cloudBlobClient, containerName, accessType) method executed with containerName:{containerName}"); @@ -718,45 +743,10 @@ public static CloudBlobContainer CreateContainer(CloudBlobClient cloudBlobClient throw new ArgumentException($"The container name {containerName} is not valid, see https://msdn.microsoft.com/en-us/library/azure/dd135715.aspx for the restrtictions for container names."); } - CloudBlobContainer container = cloudBlobClient.GetContainerReference(containerName.ToLowerInvariant()); - - if (cloudBlobClient.Credentials.IsSAS) + BlobContainerClient container = new BlobContainerClient(_connectionString,containerName.ToLowerInvariant()); + if (_isSasCredential) { - // Shared access signatures (SAS) have some limitations compared to shared access keys - // read more on: https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1 - string[] sasTokenProperties = cloudBlobClient.Credentials.SASToken.Split("&".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); - bool isAccountSas = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("ss=")).FirstOrDefault() != null; - string allowedServices = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("ss=")).FirstOrDefault(); - if (allowedServices != null) - { - allowedServices = allowedServices.Split('=')[1].ToLower(); - } - else - { - allowedServices = string.Empty; - } - - string resourceTypes = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("srt=")).FirstOrDefault(); - if (resourceTypes != null) - { - resourceTypes = resourceTypes.Split('=')[1].ToLower(); - } - else - { - resourceTypes = string.Empty; - } - - string permissions = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("sp=")).FirstOrDefault(); - if (permissions != null) - { - permissions = permissions.Split('=')[1].ToLower(); - } - else - { - permissions = string.Empty; - } - - bool canCreateContainer = allowedServices.Contains('b') && resourceTypes.Contains('c') && permissions.Contains('c'); + bool canCreateContainer = SasCredentialHasContainerCreatePermission(); if (canCreateContainer) { container.CreateIfNotExists(accessType); @@ -765,22 +755,61 @@ public static CloudBlobContainer CreateContainer(CloudBlobClient cloudBlobClient else if (!container.Exists()) { container.CreateIfNotExists(); - BlobContainerPermissions newPermissions = container.GetPermissions(); - newPermissions.PublicAccess = accessType; - container.SetPermissions(newPermissions); + container.SetAccessPolicy(accessType); } return container; } + private static bool SasCredentialHasContainerCreatePermission() + { + throw new NotImplementedException(); + //// Shared access signatures (SAS) have some limitations compared to shared access keys + //// read more on: https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1 + //string[] sasTokenProperties = cloudBlobClient.Credentials.SASToken.Split("&".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + //bool isAccountSas = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("ss=")).FirstOrDefault() != null; + //string allowedServices = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("ss=")).FirstOrDefault(); + //if (allowedServices != null) + //{ + // allowedServices = allowedServices.Split('=')[1].ToLower(); + //} + //else + //{ + // allowedServices = string.Empty; + //} + + //string resourceTypes = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("srt=")).FirstOrDefault(); + //if (resourceTypes != null) + //{ + // resourceTypes = resourceTypes.Split('=')[1].ToLower(); + //} + //else + //{ + // resourceTypes = string.Empty; + //} + + //string permissions = sasTokenProperties.Where(k => k.ToLowerInvariant().StartsWith("sp=")).FirstOrDefault(); + //if (permissions != null) + //{ + // permissions = permissions.Split('=')[1].ToLower(); + //} + //else + //{ + // permissions = string.Empty; + //} + + //bool canCreateContainer = allowedServices.Contains('b') && resourceTypes.Contains('c') && permissions.Contains('c'); + //return canCreateContainer; + } + /// /// Gets a reference to the block blob matching the given path. /// /// The path to the blob. /// - /// The reference. + /// The reference. /// - public CloudBlockBlob GetBlockBlobReference(string path) + public BlobClient GetBlockBlobReference(string path) { Current.Logger.Debug($"GetBlockBlobReference(path) method executed with path:{path}"); @@ -795,26 +824,16 @@ public CloudBlockBlob GetBlockBlobReference(string path) try { - var blobReference = this.cloudBlobContainer.GetBlobReferenceFromServer(blobPath); - if (blobReference.BlobType == BlobType.BlockBlob) - { - return blobReference as CloudBlockBlob; - } - else - { - Current.Logger.Error( - $"A media item '{path}' was requested but it's blob type was {blobReference.BlobType} when it should be BlockBlob"); - return null; - } + return this.cloudBlobContainer.GetBlobClient(blobPath); } - catch (StorageException ex) when (ex.RequestInformation.ErrorCode == BlobErrorCodeStrings.BlobNotFound) + catch (RequestFailedException ex) when (ex.ErrorCode == BlobErrorCode.BlobNotFound) { // blob doesn't exist yet - var blobReference = this.cloudBlobContainer.GetBlockBlobReference(blobPath); + var blobReference = this.cloudBlobContainer.GetBlobClient(blobPath); return blobReference; } - catch (StorageException ex) + catch (RequestFailedException ex) { Current.Logger.Error( $"GetBlockBlobReference exception {ex}"); @@ -827,14 +846,14 @@ public CloudBlockBlob GetBlockBlobReference(string path) /// /// The path to the directory. /// - /// The reference. + /// The reference. /// - private CloudBlobDirectory GetDirectoryReference(string path) + private AzureBlobDirectory GetDirectoryReference(string path) { Current.Logger.Debug($"GetDirectoryReference(path) method executed with path:{path}"); string blobPath = this.FixPath(path); - return this.cloudBlobContainer.GetDirectoryReference(blobPath); + return new AzureBlobDirectory(cloudBlobContainer,blobPath); } /// @@ -885,7 +904,7 @@ private string FixPath(string path) path = path.Replace("\\", Delimiter); string appVirtualPath = this.ApplicationVirtualPath; - if (appVirtualPath != null && path.StartsWith(appVirtualPath)) + if (!string.IsNullOrWhiteSpace(appVirtualPath) && path.StartsWith(appVirtualPath)) { path = path.Substring(appVirtualPath.Length); } diff --git a/src/UmbracoFileSystemProviders.Azure/FileSystemVirtualFile.cs b/src/UmbracoFileSystemProviders.Azure/FileSystemVirtualFile.cs index 351a70e..7dad65a 100644 --- a/src/UmbracoFileSystemProviders.Azure/FileSystemVirtualFile.cs +++ b/src/UmbracoFileSystemProviders.Azure/FileSystemVirtualFile.cs @@ -75,6 +75,12 @@ public override Stream Open() cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(maxDays)); cache.SetMaxAge(new TimeSpan(maxDays, 0, 0, 0)); cache.SetRevalidation(HttpCacheRevalidation.AllCaches); + cache.SetLastModified(azureBlobFileSystem.GetLastModified(VirtualPath).DateTime); + var etag = ((AzureBlobFileSystem)azureBlobFileSystem).FileSystem.GetETag(VirtualPath); + if (!string.IsNullOrWhiteSpace(etag)) + { + cache.SetETag(etag); + } } return this.stream(); diff --git a/src/UmbracoFileSystemProviders.Azure/UmbracoFileSystemProviders.Azure.csproj b/src/UmbracoFileSystemProviders.Azure/UmbracoFileSystemProviders.Azure.csproj index 0cd1b4a..26794f1 100644 --- a/src/UmbracoFileSystemProviders.Azure/UmbracoFileSystemProviders.Azure.csproj +++ b/src/UmbracoFileSystemProviders.Azure/UmbracoFileSystemProviders.Azure.csproj @@ -56,8 +56,14 @@ MinimumRecommendedRules.ruleset - - ..\packages\AutoMapper.8.0.0\lib\net461\AutoMapper.dll + + ..\packages\Azure.Core.1.18.0\lib\net461\Azure.Core.dll + + + ..\packages\Azure.Storage.Blobs.12.9.1\lib\netstandard2.0\Azure.Storage.Blobs.dll + + + ..\packages\Azure.Storage.Common.12.8.0\lib\netstandard2.0\Azure.Storage.Common.dll ..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll @@ -65,10 +71,6 @@ ..\packages\ClientDependency-Mvc5.1.8.0.0\lib\net45\ClientDependency.Core.Mvc.dll - - ..\packages\xmlrpcnet.2.5.0\lib\net20\CookComputing.XmlRpcV2.dll - True - ..\packages\CSharpTest.Net.Collections.14.906.1403.1082\lib\net40\CSharpTest.Net.Collections.dll @@ -118,17 +120,8 @@ ..\packages\Microsoft.AspNet.SignalR.Core.2.4.0\lib\net45\Microsoft.AspNet.SignalR.Core.dll - - ..\packages\Microsoft.Azure.ConfigurationManager.4.0.0\lib\net452\Microsoft.Azure.ConfigurationManager.dll - - - ..\packages\Microsoft.Azure.KeyVault.Core.3.0.3\lib\net452\Microsoft.Azure.KeyVault.Core.dll - - - ..\packages\Microsoft.Azure.Storage.Blob.11.1.2\lib\net452\Microsoft.Azure.Storage.Blob.dll - - - ..\packages\Microsoft.Azure.Storage.Common.11.1.2\lib\net452\Microsoft.Azure.Storage.Common.dll + + ..\packages\Microsoft.Bcl.AsyncInterfaces.1.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll ..\packages\Microsoft.Data.Edm.5.8.4\lib\net40\Microsoft.Data.Edm.dll @@ -136,9 +129,6 @@ ..\packages\Microsoft.Data.OData.5.8.4\lib\net40\Microsoft.Data.OData.dll - - ..\packages\Microsoft.Data.Services.Client.5.8.4\lib\net40\Microsoft.Data.Services.Client.dll - ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.0.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll @@ -167,9 +157,6 @@ ..\packages\MiniProfiler.Shared.4.0.138\lib\net461\MiniProfiler.Shared.dll - - ..\packages\MySql.Data.6.10.7\lib\net452\MySql.Data.dll - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll @@ -216,6 +203,9 @@ ..\packages\Superpower.2.0.0\lib\net45\Superpower.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + @@ -228,30 +218,52 @@ ..\packages\Umbraco.SqlServerCE.4.0.0.1\lib\net472\System.Data.SqlServerCe.Entity.dll - - ..\packages\System.Diagnostics.DiagnosticSource.4.4.1\lib\net46\System.Diagnostics.DiagnosticSource.dll + + ..\packages\System.Diagnostics.DiagnosticSource.4.6.0\lib\net46\System.Diagnostics.DiagnosticSource.dll + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + ..\packages\System.Memory.Data.1.0.2\lib\net461\System.Memory.Data.dll + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + ..\packages\System.Spatial.5.8.4\lib\net40\System.Spatial.dll + + ..\packages\System.Text.Encodings.Web.4.7.2\lib\net461\System.Text.Encodings.Web.dll + + + ..\packages\System.Text.Json.4.6.0\lib\net461\System.Text.Json.dll + ..\packages\System.Threading.Tasks.Dataflow.4.9.0\lib\netstandard2.0\System.Threading.Tasks.Dataflow.dll + + ..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll @@ -301,6 +313,7 @@ + diff --git a/src/UmbracoFileSystemProviders.Azure/app.config b/src/UmbracoFileSystemProviders.Azure/app.config index 7d231fc..9240a30 100644 --- a/src/UmbracoFileSystemProviders.Azure/app.config +++ b/src/UmbracoFileSystemProviders.Azure/app.config @@ -62,6 +62,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UmbracoFileSystemProviders.Azure/packages.config b/src/UmbracoFileSystemProviders.Azure/packages.config index 07c052d..5b6bce7 100644 --- a/src/UmbracoFileSystemProviders.Azure/packages.config +++ b/src/UmbracoFileSystemProviders.Azure/packages.config @@ -1,6 +1,8 @@  - + + + @@ -27,13 +29,9 @@ - - - - + - @@ -44,7 +42,6 @@ - @@ -62,16 +59,23 @@ + - + + + + + + + + - \ No newline at end of file