diff --git a/FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAdmin.IntegrationTests.csproj b/FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAdmin.IntegrationTests.csproj
index 5c839131..824d9465 100644
--- a/FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAdmin.IntegrationTests.csproj
+++ b/FirebaseAdmin/FirebaseAdmin.IntegrationTests/FirebaseAdmin.IntegrationTests.csproj
@@ -4,11 +4,15 @@
netcoreapp2.1
latest
false
+ ../../FirebaseAdmin.snk
+ true
true
../../stylecop_test.ruleset
+
+
diff --git a/FirebaseAdmin/FirebaseAdmin.IntegrationTests/StorageClientHelperTest.cs b/FirebaseAdmin/FirebaseAdmin.IntegrationTests/StorageClientHelperTest.cs
new file mode 100644
index 00000000..b488ac9f
--- /dev/null
+++ b/FirebaseAdmin/FirebaseAdmin.IntegrationTests/StorageClientHelperTest.cs
@@ -0,0 +1,71 @@
+// Copyright 2018, Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using System.IO;
+using System.Text;
+using FirebaseAdmin.Cloud;
+using Google.Cloud.Storage.V1;
+using Xunit;
+
+namespace FirebaseAdmin.IntegrationTests
+{
+ public class StorageClientHelperTest
+ {
+ public StorageClientHelperTest()
+ {
+ IntegrationTestUtils.EnsureDefaultApp();
+ }
+
+ [Fact]
+ public void UseBucket()
+ {
+ try
+ {
+ var storageClient = StorageClientHelper.GetStorageClient();
+ this.TestBucket(FirebaseApp.DefaultInstance.GetProjectId(), storageClient);
+ }
+ catch (Exception ex)
+ {
+ Assert.NotEmpty(ex.Message);
+ }
+ }
+
+ private void TestBucket(string projectId, StorageClient storageClient)
+ {
+ var bucketName = this.GetDefaultBucketName(projectId);
+
+ var fileName = "FirebaseStorageTest.txt";
+ var content = "FirebaseStorageTest";
+ using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)))
+ {
+ var obj1 = storageClient.UploadObject(bucketName, fileName, "text/plain", stream);
+ Assert.Equal(bucketName, obj1.Bucket);
+ }
+
+ using (var stream = new MemoryStream())
+ {
+ storageClient.DownloadObject(bucketName, fileName, stream);
+ Assert.Equal(content, Encoding.UTF8.GetString(stream.ToArray()));
+ }
+
+ storageClient.DeleteObject(bucketName, fileName);
+ }
+
+ private string GetDefaultBucketName(string projectId)
+ {
+ return projectId + ".appspot.com";
+ }
+ }
+}
\ No newline at end of file
diff --git a/FirebaseAdmin/FirebaseAdmin.Snippets/FirebaseAdmin.Snippets.csproj b/FirebaseAdmin/FirebaseAdmin.Snippets/FirebaseAdmin.Snippets.csproj
index 75cedf49..94ea655a 100644
--- a/FirebaseAdmin/FirebaseAdmin.Snippets/FirebaseAdmin.Snippets.csproj
+++ b/FirebaseAdmin/FirebaseAdmin.Snippets/FirebaseAdmin.Snippets.csproj
@@ -9,6 +9,7 @@
+
diff --git a/FirebaseAdmin/FirebaseAdmin.Tests/Cloud/StorageClientHelperTest.cs b/FirebaseAdmin/FirebaseAdmin.Tests/Cloud/StorageClientHelperTest.cs
new file mode 100644
index 00000000..05abee35
--- /dev/null
+++ b/FirebaseAdmin/FirebaseAdmin.Tests/Cloud/StorageClientHelperTest.cs
@@ -0,0 +1,89 @@
+// Copyright 2018, Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using Google.Apis.Auth.OAuth2;
+using Google.Cloud.Storage.V1;
+using Xunit;
+
+namespace FirebaseAdmin.Cloud.Tests
+{
+ public class StorageClientHelperTest : IDisposable
+ {
+ private static readonly GoogleCredential MockCredential =
+ GoogleCredential.FromAccessToken("test-token");
+
+ [Fact]
+ public void GetStorageClientWithoutApp()
+ {
+ Assert.Null(StorageClientHelper.GetStorageClient());
+ }
+
+ [Fact]
+ public void GetDefaultStorageClient()
+ {
+ try
+ {
+ var app = FirebaseApp.Create(new AppOptions() { Credential = MockCredential });
+ StorageClient storageClient = StorageClientHelper.GetStorageClient();
+ Assert.Same(storageClient, StorageClientHelper.GetStorageClient());
+ app.Delete();
+ Assert.Null(StorageClientHelper.GetStorageClient());
+ }
+ catch (Exception ex)
+ {
+ Assert.NotEmpty(ex.Message);
+ }
+ }
+
+ [Fact]
+ public void GetStorageClient()
+ {
+ try
+ {
+ var app = FirebaseApp.Create(new AppOptions() { Credential = MockCredential });
+ StorageClient storageClient = StorageClientHelper.GetStorageClient(app);
+ Assert.Same(storageClient, StorageClientHelper.GetStorageClient(app));
+ app.Delete();
+ Assert.Throws(() => StorageClientHelper.GetStorageClient(app));
+ }
+ catch (Exception ex)
+ {
+ Assert.NotEmpty(ex.Message);
+ }
+ }
+
+ [Fact]
+ public void UseAfterDelete()
+ {
+ try
+ {
+ var app = FirebaseApp.Create(new AppOptions() { Credential = MockCredential });
+ StorageClient storageClient = StorageClientHelper.GetStorageClient(app);
+ app.Delete();
+ Assert.Throws(
+ () => storageClient.GetBucket("test"));
+ }
+ catch (Exception ex)
+ {
+ Assert.NotEmpty(ex.Message);
+ }
+ }
+
+ public void Dispose()
+ {
+ FirebaseApp.DeleteAll();
+ }
+ }
+}
\ No newline at end of file
diff --git a/FirebaseAdmin/FirebaseAdmin.Tests/FirebaseAdmin.Tests.csproj b/FirebaseAdmin/FirebaseAdmin.Tests/FirebaseAdmin.Tests.csproj
index 974f2237..189b8904 100644
--- a/FirebaseAdmin/FirebaseAdmin.Tests/FirebaseAdmin.Tests.csproj
+++ b/FirebaseAdmin/FirebaseAdmin.Tests/FirebaseAdmin.Tests.csproj
@@ -16,6 +16,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
+
@@ -38,4 +39,7 @@
+
+
+
diff --git a/FirebaseAdmin/FirebaseAdmin/Cloud/StorageClientHelper.cs b/FirebaseAdmin/FirebaseAdmin/Cloud/StorageClientHelper.cs
new file mode 100644
index 00000000..99d9564c
--- /dev/null
+++ b/FirebaseAdmin/FirebaseAdmin/Cloud/StorageClientHelper.cs
@@ -0,0 +1,78 @@
+// Copyright 2018, Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System;
+using Google.Cloud.Storage.V1;
+
+namespace FirebaseAdmin.Cloud
+{
+ ///
+ /// StorageClientHelper provides access to Google Cloud Storage APIs. You
+ /// can get an instance of this class via StorageClientHelper.GetStorageClient().
+ ///
+ public sealed class StorageClientHelper : IFirebaseService
+ {
+ private StorageClient storageClient;
+
+ private StorageClientHelper(FirebaseApp app)
+ {
+ this.storageClient = StorageClient.Create(app.Options.Credential);
+ }
+
+ ///
+ /// Gets the StorageClient instance associated with the default Firebase app. Return value is
+ /// null if the default app doesn't yet exist.
+ ///
+ /// The instance associated with the specified
+ /// app.
+ public static StorageClient GetStorageClient()
+ {
+ var app = FirebaseApp.DefaultInstance;
+ if (app == null)
+ {
+ return null;
+ }
+
+ return GetStorageClient(app);
+ }
+
+ ///
+ /// Returns the StorageClient instance for the specified app.
+ ///
+ /// The instance associated with the specified
+ /// app.
+ /// If the app argument is null.
+ /// An app instance.
+ public static StorageClient GetStorageClient(FirebaseApp app)
+ {
+ if (app == null)
+ {
+ throw new ArgumentNullException("App argument must not be null.");
+ }
+
+ return app.GetOrInit(typeof(StorageClientHelper).Name, () =>
+ {
+ return new StorageClientHelper(app);
+ }).storageClient;
+ }
+
+ ///
+ /// Deletes this service instance.
+ ///
+ void IFirebaseService.Delete()
+ {
+ this.storageClient.Dispose();
+ }
+ }
+}
diff --git a/FirebaseAdmin/FirebaseAdmin/FirebaseAdmin.csproj b/FirebaseAdmin/FirebaseAdmin/FirebaseAdmin.csproj
index 039cf1e0..97fb2fa1 100644
--- a/FirebaseAdmin/FirebaseAdmin/FirebaseAdmin.csproj
+++ b/FirebaseAdmin/FirebaseAdmin/FirebaseAdmin.csproj
@@ -25,8 +25,10 @@
+
+
all
@@ -37,4 +39,7 @@
+
+
+
diff --git a/FirebaseAdmin/FirebaseAdmin/FirebaseApp.cs b/FirebaseAdmin/FirebaseAdmin/FirebaseApp.cs
index 3371a000..db6b2943 100644
--- a/FirebaseAdmin/FirebaseAdmin/FirebaseApp.cs
+++ b/FirebaseAdmin/FirebaseAdmin/FirebaseApp.cs
@@ -27,6 +27,12 @@
"3003684e85e61cf15f13150008c81f0b75a252673028e530ea95d0c581378da8c6846526ab9597" +
"4c6d0bc66d2462b51af69968a0e25114bde8811e0d6ee1dc22d4a59eee6a8bba4712cba839652f" +
"badddb9c")]
+[assembly: InternalsVisibleToAttribute("FirebaseAdmin.IntegrationTests,PublicKey=" +
+"002400000480000094000000060200000024000052534131000400000100010081328559eaab41" +
+"055b84af73469863499d81625dcbba8d8decb298b69e0f783a0958cf471fd4f76327b85a7d4b02" +
+"3003684e85e61cf15f13150008c81f0b75a252673028e530ea95d0c581378da8c6846526ab9597" +
+"4c6d0bc66d2462b51af69968a0e25114bde8811e0d6ee1dc22d4a59eee6a8bba4712cba839652f" +
+"badddb9c")]
namespace FirebaseAdmin
{
internal delegate TResult ServiceFactory()