Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
[![NuGet Version](http://img.shields.io/nuget/v/GeekLearning.Storage.svg?style=flat-square&label=NuGet:%20Abstractions)](https://www.nuget.org/packages/GeekLearning.Storage/)
[![NuGet Version](http://img.shields.io/nuget/v/GeekLearning.Storage.FileSystem.svg?style=flat-square&label=NuGet:%20FileSystem)](https://www.nuget.org/packages/GeekLearning.Storage.FileSystem/)
[![NuGet Version](http://img.shields.io/nuget/v/GeekLearning.Storage.Azure.svg?style=flat-square&label=NuGet:%20Azure%20Storage)](https://www.nuget.org/packages/GeekLearning.Storage.Azure/)
[![NuGet Version](http://img.shields.io/nuget/v/GeekLearning.Storage.svg?style=flat-square&label=NuGet)](https://www.nuget.org/packages/GeekLearning.Storage/)
[![Build Status](https://geeklearning.visualstudio.com/_apis/public/build/definitions/f841b266-7595-4d01-9ee1-4864cf65aa73/27/badge)](#)

# Geek Learning Cloud Storage Abstraction
Expand Down
49 changes: 49 additions & 0 deletions src/GeekLearning.Storage.Azure/AzureStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,55 @@ public async Task<IFileReference> SaveAsync(Stream data, IPrivateFileReference f
return reference;
}

public Task<string> GetSharedAccessSignatureAsync(ISharedAccessPolicy policy)
{
var adHocPolicy = new SharedAccessBlobPolicy()
{
SharedAccessStartTime = policy.StartTime,
SharedAccessExpiryTime = policy.ExpiryTime,
Permissions = FromGenericToAzure(policy.Permissions),
};

return Task.FromResult(this.container.Value.GetSharedAccessSignature(adHocPolicy));
}

internal static SharedAccessBlobPermissions FromGenericToAzure(SharedAccessPermissions permissions)
{
var result = SharedAccessBlobPermissions.None;

if (permissions.HasFlag(SharedAccessPermissions.Add))
{
result |= SharedAccessBlobPermissions.Add;
}

if (permissions.HasFlag(SharedAccessPermissions.Create))
{
result |= SharedAccessBlobPermissions.Create;
}

if (permissions.HasFlag(SharedAccessPermissions.Delete))
{
result |= SharedAccessBlobPermissions.Delete;
}

if (permissions.HasFlag(SharedAccessPermissions.List))
{
result |= SharedAccessBlobPermissions.List;
}

if (permissions.HasFlag(SharedAccessPermissions.Read))
{
result |= SharedAccessBlobPermissions.Read;
}

if (permissions.HasFlag(SharedAccessPermissions.Write))
{
result |= SharedAccessBlobPermissions.Write;
}

return result;
}

private async Task<Internal.AzureFileReference> InternalGetAsync(IPrivateFileReference file, bool withMetadata = false)
{
var azureFile = file as Internal.AzureFileReference;
Expand Down
17 changes: 12 additions & 5 deletions src/GeekLearning.Storage.Azure/Internal/AzureFileReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ public Task UpdateAsync(Stream stream)
return this.CloudBlob.UploadFromStreamAsync(stream);
}

public Task<string> GetExpirableUriAsync()
{
throw new NotImplementedException();
}

public async Task ReadToStreamAsync(Stream targetStream)
{
await this.CloudBlob.DownloadRangeToStreamAsync(targetStream, null, null);
Expand All @@ -88,5 +83,17 @@ public Task SavePropertiesAsync()
{
return this.propertiesLazy.Value.SaveAsync();
}

public Task<string> GetSharedAccessSignature(ISharedAccessPolicy policy)
{
var adHocPolicy = new SharedAccessBlobPolicy()
{
SharedAccessStartTime = policy.StartTime,
SharedAccessExpiryTime = policy.ExpiryTime,
Permissions = AzureStore.FromGenericToAzure(policy.Permissions),
};

return Task.FromResult(this.CloudBlob.GetSharedAccessSignature(adHocPolicy));
}
}
}
5 changes: 5 additions & 0 deletions src/GeekLearning.Storage.FileSystem/FileSystemStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ public async Task<IFileReference> SaveAsync(Stream data, IPrivateFileReference f
return fileReference;
}

public Task<string> GetSharedAccessSignatureAsync(ISharedAccessPolicy policy)
{
throw new NotSupportedException();
}

private async Task<Internal.FileSystemFileReference> InternalGetAsync(IPrivateFileReference file, bool withMetadata = false, bool checkIfExists = true)
{
var fileSystemFile = file as Internal.FileSystemFileReference;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ public Task DeleteAsync()
return Task.FromResult(true);
}

public Task<string> GetExpirableUriAsync()
{
throw new NotImplementedException();
}

public Task<byte[]> ReadAllBytesAsync()
{
return Task.FromResult(File.ReadAllBytes(this.FileSystemPath));
Expand Down Expand Up @@ -109,5 +104,10 @@ public Task SavePropertiesAsync()
this,
(this.Properties as FileSystemFileProperties).ExtendedProperties);
}

public Task<string> GetSharedAccessSignature(ISharedAccessPolicy policy)
{
throw new NotSupportedException();
}
}
}
4 changes: 4 additions & 0 deletions src/GeekLearning.Storage/GeekLearning.Storage.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@
<Folder Include="Properties\" />
</ItemGroup>

<ItemGroup>
<None Include="ISharedAccessPolicy.cs" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions src/GeekLearning.Storage/IFileReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public interface IFileReference : IPrivateFileReference

Task UpdateAsync(Stream stream);

Task<string> GetExpirableUriAsync();

Task SavePropertiesAsync();

Task<string> GetSharedAccessSignature(ISharedAccessPolicy policy);
}
}
13 changes: 13 additions & 0 deletions src/GeekLearning.Storage/ISharedAccessPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace GeekLearning.Storage
{
using System;

public interface ISharedAccessPolicy
{
DateTimeOffset? StartTime { get; }

DateTimeOffset? ExpiryTime { get; }

SharedAccessPermissions Permissions { get; }
}
}
2 changes: 2 additions & 0 deletions src/GeekLearning.Storage/IStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,7 @@ public interface IStore
Task<IFileReference> SaveAsync(byte[] data, IPrivateFileReference file, string contentType);

Task<IFileReference> SaveAsync(Stream data, IPrivateFileReference file, string contentType);

Task<string> GetSharedAccessSignatureAsync(ISharedAccessPolicy policy);
}
}
2 changes: 2 additions & 0 deletions src/GeekLearning.Storage/Internal/GenericStoreProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,7 @@ public GenericStoreProxy(IStorageFactory factory, IOptions<TOptions> options)
public Task<IFileReference> SaveAsync(Stream data, IPrivateFileReference file, string contentType) => this.innerStore.SaveAsync(data, file, contentType);

public Task<IFileReference> SaveAsync(byte[] data, IPrivateFileReference file, string contentType) => this.innerStore.SaveAsync(data, file, contentType);

public Task<string> GetSharedAccessSignatureAsync(ISharedAccessPolicy policy) => this.innerStore.GetSharedAccessSignatureAsync(policy);
}
}
16 changes: 16 additions & 0 deletions src/GeekLearning.Storage/SharedAccessPermissions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace GeekLearning.Storage
{
using System;

[Flags]
public enum SharedAccessPermissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4,
List = 8,
Add = 16,
Create = 32
}
}
13 changes: 13 additions & 0 deletions src/GeekLearning.Storage/SharedAccessPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace GeekLearning.Storage
{
using System;

public class SharedAccessPolicy : ISharedAccessPolicy
{
public DateTimeOffset? StartTime { get; set; }

public DateTimeOffset? ExpiryTime { get; set; }

public SharedAccessPermissions Permissions { get; set; }
}
}
68 changes: 68 additions & 0 deletions tests/GeekLearning.Storage.Integration.Test/SharedAccessTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
namespace GeekLearning.Storage.Integration.Test
{
using Storage;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.Extensions.Options;
using GeekLearning.Storage.Azure.Configuration;
using System.Linq;

[Collection(nameof(IntegrationCollection))]
[Trait("Operation", "SharedAccess"), Trait("Kind", "Integration")]
public class SharedAccessTests
{
private readonly StoresFixture storeFixture;

public SharedAccessTests(StoresFixture fixture)
{
this.storeFixture = fixture;
}

[Theory(DisplayName = nameof(StoreSharedAccess)), InlineData("Store3"), InlineData("Store4"), InlineData("Store5"), InlineData("Store6")]
public async Task StoreSharedAccess(string storeName)
{
var storageFactory = this.storeFixture.Services.GetRequiredService<IStorageFactory>();
var options = this.storeFixture.Services.GetRequiredService<IOptions<AzureParsedOptions>>();

var store = storageFactory.GetStore(storeName);

options.Value.ParsedStores.TryGetValue(storeName, out var storeOptions);

var sharedAccessSignature = await store.GetSharedAccessSignatureAsync(new SharedAccessPolicy
{
ExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessPermissions.List,
});

var account = CloudStorageAccount.Parse(storeOptions.ConnectionString);

var accountSAS = new StorageCredentials(sharedAccessSignature);
var accountWithSAS = new CloudStorageAccount(accountSAS, account.Credentials.AccountName, endpointSuffix: null, useHttps: true);
var blobClientWithSAS = accountWithSAS.CreateCloudBlobClient();
var containerWithSAS = blobClientWithSAS.GetContainerReference(storeOptions.FolderName);

BlobContinuationToken continuationToken = null;
List<IListBlobItem> results = new List<IListBlobItem>();

do
{
var response = await containerWithSAS.ListBlobsSegmentedAsync(continuationToken);
continuationToken = response.ContinuationToken;
results.AddRange(response.Results);
}
while (continuationToken != null);

var filesFromStore = await store.ListAsync(null, false, false);

Assert.Equal(filesFromStore.Length, results.OfType<ICloudBlob>().Count());
}
}
}