From d70c23ece0abf7e1c00166e26fa89a670d34a740 Mon Sep 17 00:00:00 2001 From: zxu Date: Fri, 9 Feb 2018 14:28:29 -0500 Subject: port Firestore Auth module in C++ (#733) * Implement firestore/auth/user * add user to project and some fixes * implement firestore/auth/{credentials_provider,empty_credentials_provider} * implement firestore/auth/firebase_credentials_provider * refactoring firebase_credentials_provider and add (disabled but working) unit test * add auth test to project * address changes * small fix to style and project * fix the firebase_credentials_provider_test * fix style * address changes * revert the change to static mutex_ * remove my custom plist path * fix style * address changes * refactoring FirebaseCredentialsProvider to fix the issue w.r.t. auth global dispatch queue * add /*force_refresh=*/ tag to bool literal for style purpose * Use a shared_ptr/weak_ptr handoff on FirebaseCredentialsProvider (#778) * Revert "refactoring FirebaseCredentialsProvider to fix the issue w.r.t. auth global dispatch queue" This reverts commit 87175a4146267d403a774f138b85f8d3b532fa4b. * Use a shared_ptr/weak_ptr handoff on FirebaseCredentialsProvider This avoids any problems with callsbacks retaining pointers to objects destroyed by a C++ destructor --- .../src/firebase/firestore/auth/CMakeLists.txt | 52 ++++++++ .../firestore/auth/credentials_provider.cc | 31 +++++ .../firebase/firestore/auth/credentials_provider.h | 79 ++++++++++++ .../firestore/auth/empty_credentials_provider.cc | 42 +++++++ .../firestore/auth/empty_credentials_provider.h | 37 ++++++ .../auth/firebase_credentials_provider_apple.h | 112 +++++++++++++++++ .../auth/firebase_credentials_provider_apple.mm | 134 +++++++++++++++++++++ .../core/src/firebase/firestore/auth/token.cc | 29 +++++ Firestore/core/src/firebase/firestore/auth/token.h | 68 +++++++++++ Firestore/core/src/firebase/firestore/auth/user.cc | 39 ++++++ Firestore/core/src/firebase/firestore/auth/user.h | 76 ++++++++++++ 11 files changed, 699 insertions(+) create mode 100644 Firestore/core/src/firebase/firestore/auth/CMakeLists.txt create mode 100644 Firestore/core/src/firebase/firestore/auth/credentials_provider.cc create mode 100644 Firestore/core/src/firebase/firestore/auth/credentials_provider.h create mode 100644 Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.cc create mode 100644 Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h create mode 100644 Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h create mode 100644 Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm create mode 100644 Firestore/core/src/firebase/firestore/auth/token.cc create mode 100644 Firestore/core/src/firebase/firestore/auth/token.h create mode 100644 Firestore/core/src/firebase/firestore/auth/user.cc create mode 100644 Firestore/core/src/firebase/firestore/auth/user.h (limited to 'Firestore/core/src/firebase/firestore/auth') diff --git a/Firestore/core/src/firebase/firestore/auth/CMakeLists.txt b/Firestore/core/src/firebase/firestore/auth/CMakeLists.txt new file mode 100644 index 0000000..2241fae --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/CMakeLists.txt @@ -0,0 +1,52 @@ +# Copyright 2018 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. + +cc_library( + firebase_firestore_auth_base + SOURCES + credentials_provider.cc + credentials_provider.h + token.cc + token.h + user.cc + user.h + DEPENDS + absl_strings + firebase_firestore_util +) + +cc_library( + firebase_firestore_auth_apple + SOURCES + firebase_credentials_provider_apple.h + firebase_credentials_provider_apple.mm + DEPENDS + FirebaseCore + firebase_firestore_auth_base + EXCLUDE_FROM_ALL +) + +if(APPLE) + list(APPEND AUTH_DEPENDS firebase_firestore_auth_apple) +endif() + +cc_library( + firebase_firestore_auth + SOURCES + empty_credentials_provider.cc + empty_credentials_provider.h + DEPENDS + ${AUTH_DEPENDS} + firebase_firestore_auth_base +) diff --git a/Firestore/core/src/firebase/firestore/auth/credentials_provider.cc b/Firestore/core/src/firebase/firestore/auth/credentials_provider.cc new file mode 100644 index 0000000..0301944 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/credentials_provider.cc @@ -0,0 +1,31 @@ +/* + * Copyright 2018 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. + */ + +#include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" + +namespace firebase { +namespace firestore { +namespace auth { + +CredentialsProvider::CredentialsProvider() : user_change_listener_(nullptr) { +} + +CredentialsProvider::~CredentialsProvider() { +} + +} // namespace auth +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/auth/credentials_provider.h b/Firestore/core/src/firebase/firestore/auth/credentials_provider.h new file mode 100644 index 0000000..2a52c99 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/credentials_provider.h @@ -0,0 +1,79 @@ +/* + * Copyright 2018 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. + */ + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_CREDENTIALS_PROVIDER_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_CREDENTIALS_PROVIDER_H_ + +#include +#include + +#include "Firestore/core/src/firebase/firestore/auth/token.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" +#include "absl/strings/string_view.h" + +namespace firebase { +namespace firestore { +namespace auth { + +// `TokenErrorListener` is a listener that gets a token or an error. +// token: An auth token as a string, or nullptr if error occurred. +// error: The error if one occurred, or else nullptr. +typedef std::function + TokenListener; + +// Listener notified with a User change. +typedef std::function UserChangeListener; + +/** + * Provides methods for getting the uid and token for the current user and + * listen for changes. + */ +class CredentialsProvider { + public: + CredentialsProvider(); + + virtual ~CredentialsProvider(); + + /** + * Requests token for the current user, optionally forcing a refreshed token + * to be fetched. + */ + virtual void GetToken(bool force_refresh, TokenListener completion) = 0; + + /** + * Sets the listener to be notified of user changes (sign-in / sign-out). It + * is immediately called once with the initial user. + * + * Call with nullptr to remove previous listener. + */ + virtual void SetUserChangeListener(UserChangeListener listener) = 0; + + protected: + /** + * A listener to be notified of user changes (sign-in / sign-out). It is + * immediately called once with the initial user. + * + * Note that this block will be called back on an arbitrary thread that is not + * the normal Firestore worker thread. + */ + UserChangeListener user_change_listener_; +}; + +} // namespace auth +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_CREDENTIALS_PROVIDER_H_ diff --git a/Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.cc b/Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.cc new file mode 100644 index 0000000..6ee7f61 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.cc @@ -0,0 +1,42 @@ +/* + * Copyright 2018 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. + */ + +#define UNUSED(x) (void)(x) + +#include "Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h" + +namespace firebase { +namespace firestore { +namespace auth { + +void EmptyCredentialsProvider::GetToken(bool force_refresh, + TokenListener completion) { + UNUSED(force_refresh); + if (completion) { + completion({"", User::Unauthenticated()}, ""); + } +} + +void EmptyCredentialsProvider::SetUserChangeListener( + UserChangeListener listener) { + if (listener) { + listener(User::Unauthenticated()); + } +} + +} // namespace auth +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h b/Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h new file mode 100644 index 0000000..55b3cc6 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 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. + */ + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_EMPTY_CREDENTIALS_PROVIDER_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_EMPTY_CREDENTIALS_PROVIDER_H_ + +#include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" + +namespace firebase { +namespace firestore { +namespace auth { + +/** `EmptyCredentialsProvider` always yields an empty token. */ +class EmptyCredentialsProvider : public CredentialsProvider { + public: + void GetToken(bool force_refresh, TokenListener completion) override; + void SetUserChangeListener(UserChangeListener listener) override; +}; + +} // namespace auth +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_EMPTY_CREDENTIALS_PROVIDER_H_ diff --git a/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h new file mode 100644 index 0000000..65c4c65 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h @@ -0,0 +1,112 @@ +/* + * Copyright 2018 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. + */ + +// Right now, FirebaseCredentialsProvider only support APPLE build. +#if !defined(__OBJC__) +#error "This header only supports Objective-C++." +#endif // !defined(__OBJC__) + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_FIREBASE_CREDENTIALS_PROVIDER_APPLE_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_FIREBASE_CREDENTIALS_PROVIDER_APPLE_H_ + +#import + +#include +#include // NOLINT(build/c++11) + +#include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h" +#include "Firestore/core/src/firebase/firestore/auth/user.h" +#include "absl/strings/string_view.h" + +@class FIRApp; + +namespace firebase { +namespace firestore { +namespace auth { + +/** + * `FirebaseCredentialsProvider` uses Firebase Auth via `FIRApp` to get an auth + * token. + * + * NOTE: To simplify the implementation, it requires that you set + * `userChangeListener` with a non-`nil` value no more than once and don't call + * `getTokenForcingRefresh:` after setting it to `nil`. + * + * This class must be implemented in a thread-safe manner since it is accessed + * from the thread backing our internal worker queue and the callbacks from + * FIRAuth will be executed on an arbitrary different thread. + * + * For non-Apple desktop build, this is right now just a stub. + */ +class FirebaseCredentialsProvider : public CredentialsProvider { + public: + // TODO(zxu123): Provide a ctor to accept the C++ Firebase Games App, which + // deals all platforms. Right now, only works for FIRApp*. + /** + * Initializes a new FirebaseCredentialsProvider. + * + * @param app The Firebase app from which to get credentials. + */ + explicit FirebaseCredentialsProvider(FIRApp* app); + + ~FirebaseCredentialsProvider() override; + + void GetToken(bool force_refresh, TokenListener completion) override; + + void SetUserChangeListener(UserChangeListener listener) override; + + private: + /** + * Most contents of the FirebaseCredentialProvider are kept in this + * Contents object and pointed to with a shared pointer. Callbacks + * registered with FirebaseAuth use weak pointers to the Contents to + * avoid races between notifications arriving and C++ object destruction. + */ + struct Contents { + Contents(FIRApp* app, const absl::string_view uid) + : app(app), current_user(uid), mutex() { + } + + const FIRApp* app; + + /** + * The current user as reported to us via our AuthStateDidChangeListener. + */ + User current_user; + + /** + * Counter used to detect if the user changed while a + * -getTokenForcingRefresh: request was outstanding. + */ + int user_counter = 0; + + std::mutex mutex; + }; + + /** + * Handle used to stop receiving auth changes once userChangeListener is + * removed. + */ + id auth_listener_handle_; + + std::shared_ptr contents_; +}; + +} // namespace auth +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_FIREBASE_CREDENTIALS_PROVIDER_APPLE_H_ diff --git a/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm new file mode 100644 index 0000000..f463958 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.mm @@ -0,0 +1,134 @@ +/* + * Copyright 2018 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. + */ + +#include "Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h" + +#import +#import +#import + +#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h" +#include "Firestore/core/src/firebase/firestore/util/string_apple.h" + +namespace firebase { +namespace firestore { +namespace auth { + +FirebaseCredentialsProvider::FirebaseCredentialsProvider(FIRApp* app) + : contents_( + std::make_shared(app, util::MakeStringView([app getUID]))) { + std::weak_ptr weak_contents = contents_; + + auth_listener_handle_ = [[NSNotificationCenter defaultCenter] + addObserverForName:FIRAuthStateDidChangeInternalNotification + object:nil + queue:nil + usingBlock:^(NSNotification* notification) { + std::shared_ptr contents = weak_contents.lock(); + if (!contents) { + return; + } + + std::unique_lock lock(contents->mutex); + NSDictionary* user_info = notification.userInfo; + + // ensure we're only notifiying for the current app. + FIRApp* notified_app = + user_info[FIRAuthStateDidChangeInternalNotificationAppKey]; + if (![contents->app isEqual:notified_app]) { + return; + } + + NSString* user_id = + user_info[FIRAuthStateDidChangeInternalNotificationUIDKey]; + User new_user(util::MakeStringView(user_id)); + if (new_user != contents->current_user) { + contents->current_user = new_user; + contents->user_counter++; + UserChangeListener listener = user_change_listener_; + if (listener) { + listener(contents->current_user); + } + } + }]; +} + +FirebaseCredentialsProvider::~FirebaseCredentialsProvider() { + if (auth_listener_handle_) { + // Even though iOS 9 (and later) and macOS 10.11 (and later) keep a weak + // reference to the observer so we could avoid this removeObserver call, we + // still support iOS 8 which requires it. + [[NSNotificationCenter defaultCenter] removeObserver:auth_listener_handle_]; + } +} + +void FirebaseCredentialsProvider::GetToken(bool force_refresh, + TokenListener completion) { + FIREBASE_ASSERT_MESSAGE(auth_listener_handle_, + "GetToken cannot be called after listener removed."); + + // Take note of the current value of the userCounter so that this method can + // fail if there is a user change while the request is outstanding. + int initial_user_counter = contents_->user_counter; + + std::weak_ptr weak_contents = contents_; + void (^get_token_callback)(NSString*, NSError*) = ^( + NSString* _Nullable token, NSError* _Nullable error) { + std::shared_ptr contents = weak_contents.lock(); + if (!contents) { + return; + } + + std::unique_lock lock(contents->mutex); + if (initial_user_counter != contents->user_counter) { + // Cancel the request since the user changed while the request was + // outstanding so the response is likely for a previous user (which + // user, we can't be sure). + completion({"", User::Unauthenticated()}, + "getToken aborted due to user change."); + } else { + completion( + {util::MakeStringView(token), contents->current_user}, + error == nil ? "" : util::MakeStringView(error.localizedDescription)); + } + }; + + [contents_->app getTokenForcingRefresh:force_refresh + withCallback:get_token_callback]; +} + +void FirebaseCredentialsProvider::SetUserChangeListener( + UserChangeListener listener) { + std::unique_lock lock(contents_->mutex); + if (listener) { + FIREBASE_ASSERT_MESSAGE(!user_change_listener_, + "set user_change_listener twice!"); + // Fire initial event. + listener(contents_->current_user); + } else { + FIREBASE_ASSERT_MESSAGE(auth_listener_handle_, + "removed user_change_listener twice!"); + FIREBASE_ASSERT_MESSAGE(user_change_listener_, + "user_change_listener removed without being set!"); + [[NSNotificationCenter defaultCenter] removeObserver:auth_listener_handle_]; + auth_listener_handle_ = nil; + } + user_change_listener_ = listener; +} + +} // namespace auth +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/auth/token.cc b/Firestore/core/src/firebase/firestore/auth/token.cc new file mode 100644 index 0000000..0618ddb --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/token.cc @@ -0,0 +1,29 @@ +/* + * Copyright 2018 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. + */ + +#include "Firestore/core/src/firebase/firestore/auth/token.h" + +namespace firebase { +namespace firestore { +namespace auth { + +Token::Token(const absl::string_view token, const User& user) + : token_(token), user_(user) { +} + +} // namespace auth +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/auth/token.h b/Firestore/core/src/firebase/firestore/auth/token.h new file mode 100644 index 0000000..f3b7363 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/token.h @@ -0,0 +1,68 @@ +/* + * Copyright 2018 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. + */ + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_TOKEN_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_TOKEN_H_ + +#include + +#include "Firestore/core/src/firebase/firestore/auth/user.h" +#include "absl/strings/string_view.h" + +namespace firebase { +namespace firestore { +namespace auth { + +/** + * The current User and the authentication token provided by the underlying + * authentication mechanism. This is the result of calling + * CredentialsProvider::GetToken(). + * + * ## Portability notes: no TokenType on iOS + * + * The TypeScript client supports 1st party Oauth tokens (for the Firebase + * Console to auth as the developer) and OAuth2 tokens for the node.js sdk to + * auth with a service account. We don't have plans to support either case on + * mobile so there's no TokenType here. + */ +// TODO(zxu123): Make this support token-type for desktop workflow. +class Token { + public: + Token(const absl::string_view token, const User& user); + + /** The actual raw token. */ + const std::string& token() const { + return token_; + } + + /** + * The user with which the token is associated (used for persisting user + * state on disk, etc.). + */ + const User& user() const { + return user_; + } + + private: + const std::string token_; + const User user_; +}; + +} // namespace auth +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_TOKEN_H_ diff --git a/Firestore/core/src/firebase/firestore/auth/user.cc b/Firestore/core/src/firebase/firestore/auth/user.cc new file mode 100644 index 0000000..f442d7b --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/user.cc @@ -0,0 +1,39 @@ +/* + * Copyright 2018 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. + */ + +#include "Firestore/core/src/firebase/firestore/auth/user.h" + +#include "Firestore/core/src/firebase/firestore/util/firebase_assert.h" + +namespace firebase { +namespace firestore { +namespace auth { + +User::User() : uid_(), is_authenticated_(false) { +} + +User::User(const absl::string_view uid) : uid_(uid), is_authenticated_(true) { + FIREBASE_ASSERT(!uid.empty()); +} + +const User& User::Unauthenticated() { + static const User kUnauthenticated; + return kUnauthenticated; +} + +} // namespace auth +} // namespace firestore +} // namespace firebase diff --git a/Firestore/core/src/firebase/firestore/auth/user.h b/Firestore/core/src/firebase/firestore/auth/user.h new file mode 100644 index 0000000..58b8b55 --- /dev/null +++ b/Firestore/core/src/firebase/firestore/auth/user.h @@ -0,0 +1,76 @@ +/* + * Copyright 2018 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. + */ + +#ifndef FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_USER_H_ +#define FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_USER_H_ + +#include + +#include "absl/strings/string_view.h" + +namespace firebase { +namespace firestore { +namespace auth { + +/** + * Simple wrapper around a nullable UID. Mostly exists to make code more + * readable and for compatibility with other clients where map keys cannot be + * null. + */ +class User { + public: + /** Construct an unauthenticated user. */ + User(); + + /** Construct an authenticated user with the given UID. */ + explicit User(const absl::string_view uid); + + const std::string& uid() const { + return uid_; + } + + // PORTING NOTE: Here use more clear naming is_authenticated() instead of + // is_unauthenticated(). + bool is_authenticated() const { + return is_authenticated_; + } + + /** Returns an unauthenticated instance. */ + static const User& Unauthenticated(); + + User& operator=(const User& other) = default; + + friend bool operator==(const User& lhs, const User& rhs); + + private: + std::string uid_; + bool is_authenticated_; +}; + +inline bool operator==(const User& lhs, const User& rhs) { + return lhs.is_authenticated_ == rhs.is_authenticated_ && + (!lhs.is_authenticated_ || lhs.uid_ == rhs.uid_); +} + +inline bool operator!=(const User& lhs, const User& rhs) { + return !(lhs == rhs); +} + +} // namespace auth +} // namespace firestore +} // namespace firebase + +#endif // FIRESTORE_CORE_SRC_FIREBASE_FIRESTORE_AUTH_USER_H_ -- cgit v1.2.3