瀏覽代碼

Allow Functions to be called without Auth. (#2298)

* Allow Functions to be called without Auth.

This was a regression from previous functionality, but is reverted
mostly to the old functionality. Previously `context` would be `nil` in
the completion handler if no Auth was available, but now `context` still
contains `instanceIDToken` but no `authToken`.

Also cover unit tests for the three states: no auth, auth error, and
valid auth.

* Style fixes.

* Cast Auth fake to prevent warning.
Ryan Wilson 7 年之前
父節點
當前提交
fa2aa4f301

+ 6 - 0
Functions/Example/FirebaseFunctions.xcodeproj/project.pbxproj

@@ -30,6 +30,8 @@
 		7CF3BEC21F97EE2F00B16B6E /* FUNFakeInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CF3BEC01F97EE2F00B16B6E /* FUNFakeInstanceID.m */; };
 		873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; };
 		C8AEC40B21B7EE440051C01E /* FIRAuthInteropFake.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AEC40A21B7EE440051C01E /* FIRAuthInteropFake.m */; };
+		EDF5244421F6163100BB24C6 /* FUNContextProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EDF5244321F6163100BB24C6 /* FUNContextProviderTests.m */; };
+		EDF5244521F61AA900BB24C6 /* FIRAuthInteropFake.m in Sources */ = {isa = PBXBuildFile; fileRef = C8AEC40A21B7EE440051C01E /* FIRAuthInteropFake.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -78,6 +80,7 @@
 		C8AEC40921B7EE440051C01E /* FIRAuthInteropFake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FIRAuthInteropFake.h; path = ../../../Example/Shared/FIRAuthInteropFake.h; sourceTree = "<group>"; };
 		C8AEC40A21B7EE440051C01E /* FIRAuthInteropFake.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FIRAuthInteropFake.m; path = ../../../Example/Shared/FIRAuthInteropFake.m; sourceTree = "<group>"; };
 		E0A8D570636E99E7C3396DF8 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
+		EDF5244321F6163100BB24C6 /* FUNContextProviderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUNContextProviderTests.m; sourceTree = "<group>"; };
 		F1F2A7C03C10A3A03F9502B8 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -179,6 +182,7 @@
 			isa = PBXGroup;
 			children = (
 				6003F5BB195388D20070C39A /* FIRFunctionsTests.m */,
+				EDF5244321F6163100BB24C6 /* FUNContextProviderTests.m */,
 				7C58B0391F1441F0005ED954 /* FUNSerializerTests.m */,
 				6003F5B6195388D20070C39A /* Supporting Files */,
 			);
@@ -361,6 +365,8 @@
 			buildActionMask = 2147483647;
 			files = (
 				7C58B03A1F1441F0005ED954 /* FUNSerializerTests.m in Sources */,
+				EDF5244421F6163100BB24C6 /* FUNContextProviderTests.m in Sources */,
+				EDF5244521F61AA900BB24C6 /* FIRAuthInteropFake.m in Sources */,
 				6003F5BC195388D20070C39A /* FIRFunctionsTests.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 73 - 0
Functions/Example/Tests/FUNContextProviderTests.m

@@ -0,0 +1,73 @@
+// Copyright 2019 Google
+//
+// 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.
+
+#import <XCTest/XCTest.h>
+
+#import "FIRAuthInteropFake.h"
+#import "FUNContext.h"
+
+@interface FUNContextProviderTests : XCTestCase
+@end
+
+@implementation FUNContextProviderTests
+
+- (void)testContextWithAuth {
+  FIRAuthInteropFake *auth = [[FIRAuthInteropFake alloc] initWithToken:@"token"
+                                                                userID:@"userID"
+                                                                 error:nil];
+  FUNContextProvider *provider = [[FUNContextProvider alloc] initWithAuth:(id<FIRAuthInterop>)auth];
+  XCTestExpectation *expectation =
+      [self expectationWithDescription:@"Context should have auth keys."];
+  [provider getContext:^(FUNContext *_Nullable context, NSError *_Nullable error) {
+    XCTAssert([context.authToken isEqualToString:@"token"]);
+    XCTAssert([context.instanceIDToken isEqualToString:@"iid"]);
+    XCTAssertNil(error);
+    [expectation fulfill];
+  }];
+
+  [self waitForExpectations:@[ expectation ] timeout:0.1];
+}
+
+- (void)testContextWithAuthError {
+  NSError *authError = [[NSError alloc] initWithDomain:@"com.functions.tests" code:4 userInfo:nil];
+  FIRAuthInteropFake *auth = [[FIRAuthInteropFake alloc] initWithToken:nil
+                                                                userID:nil
+                                                                 error:authError];
+  FUNContextProvider *provider = [[FUNContextProvider alloc] initWithAuth:(id<FIRAuthInterop>)auth];
+  XCTestExpectation *expectation =
+      [self expectationWithDescription:@"Completion handler should fail with Auth error."];
+  [provider getContext:^(FUNContext *_Nullable context, NSError *_Nullable error) {
+    XCTAssertNil(context);
+    XCTAssertEqual(error, auth.error);
+    [expectation fulfill];
+  }];
+
+  [self waitForExpectations:@[ expectation ] timeout:0.1];
+}
+
+- (void)testContextWithoutAuth {
+  FUNContextProvider *provider = [[FUNContextProvider alloc] initWithAuth:nil];
+  XCTestExpectation *expectation =
+      [self expectationWithDescription:@"Completion handler should succeed without Auth."];
+  [provider getContext:^(FUNContext *_Nullable context, NSError *_Nullable error) {
+    XCTAssertNil(error);
+    XCTAssertNil(context.authToken);
+    XCTAssert([context.instanceIDToken isEqualToString:@"iid"]);
+    [expectation fulfill];
+  }];
+
+  [self waitForExpectations:@[ expectation ] timeout:0.1];
+}
+
+@end

+ 1 - 1
Functions/FirebaseFunctions/FUNContext.h

@@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 - (id)init NS_UNAVAILABLE;
 
-- (instancetype)initWithAuth:(id<FIRAuthInterop>)auth NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithAuth:(nullable id<FIRAuthInterop>)auth NS_DESIGNATED_INITIALIZER;
 
 - (void)getContext:(void (^)(FUNContext *_Nullable context, NSError *_Nullable error))completion;
 

+ 12 - 2
Functions/FirebaseFunctions/FUNContext.m

@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 @implementation FUNContextProvider
 
-- (instancetype)initWithAuth:(id<FIRAuthInterop>)auth {
+- (instancetype)initWithAuth:(nullable id<FIRAuthInterop>)auth {
   self = [super init];
   if (self) {
     _auth = auth;
@@ -65,7 +65,17 @@ NS_ASSUME_NONNULL_BEGIN
 }
 
 - (void)getContext:(void (^)(FUNContext *_Nullable context, NSError *_Nullable error))completion {
-  // Get the auth token.
+  // If auth isn't included, call the completion handler and return.
+  if (_auth == nil) {
+    // With no auth, just populate instanceIDToken and call the completion handler.
+    NSString *instanceIDToken = [self instanceIDToken];
+    FUNContext *context = [[FUNContext alloc] initWithAuthToken:nil
+                                                instanceIDToken:instanceIDToken];
+    completion(context, nil);
+    return;
+  }
+
+  // Auth exists, get the auth token.
   [_auth getTokenForcingRefresh:NO
                    withCallback:^(NSString *_Nullable token, NSError *_Nullable error) {
                      if (error) {