Get list of auth modes from AuthManger

BUG=25768507

Change-Id: I6694f961fab045ef9dcd1b6cfbe8a2b2d82861c5
Reviewed-on: https://weave-review.googlesource.com/2064
Reviewed-by: Alex Vakulenko <avakulenko@google.com>
diff --git a/src/privet/auth_manager.cc b/src/privet/auth_manager.cc
index 4d0d2a3..61f5a09 100644
--- a/src/privet/auth_manager.cc
+++ b/src/privet/auth_manager.cc
@@ -276,5 +276,20 @@
   return result;
 }
 
+bool AuthManager::IsAnonymousAuthSupported() const {
+  return !config_ ||
+         config_->GetSettings().local_anonymous_access_role != AuthScope::kNone;
+}
+
+bool AuthManager::IsPairingAuthSupported() const {
+  return !config_ || config_->GetSettings().local_pairing_enabled;
+}
+
+bool AuthManager::IsLocalAuthSupported() const {
+  return !config_ ||
+         config_->GetSettings().root_client_token_owner !=
+             RootClientTokenOwner::kNone;
+}
+
 }  // namespace privet
 }  // namespace weave
diff --git a/src/privet/auth_manager.h b/src/privet/auth_manager.h
index 1e6ad01..00d6e32 100644
--- a/src/privet/auth_manager.h
+++ b/src/privet/auth_manager.h
@@ -62,8 +62,12 @@
 
   std::vector<uint8_t> CreateSessionId();
 
+  bool IsAnonymousAuthSupported() const;
+  bool IsPairingAuthSupported() const;
+  bool IsLocalAuthSupported() const;
+
  private:
-  Config* config_{nullptr};
+  Config* config_{nullptr};  // Can be nullptr for tests.
   base::DefaultClock default_clock_;
   base::Clock* clock_{&default_clock_};
   uint32_t session_counter_{0};
diff --git a/src/privet/mock_delegates.h b/src/privet/mock_delegates.h
index 476bc8d..c75d438 100644
--- a/src/privet/mock_delegates.h
+++ b/src/privet/mock_delegates.h
@@ -74,6 +74,7 @@
                      bool(const std::string&, UserInfo*, ErrorPtr*));
   MOCK_CONST_METHOD0(GetPairingTypes, std::set<PairingType>());
   MOCK_CONST_METHOD0(GetCryptoTypes, std::set<CryptoType>());
+  MOCK_CONST_METHOD0(GetAuthTypes, std::set<AuthType>());
   MOCK_METHOD1(ClaimRootClientAuthToken, std::string(ErrorPtr*));
   MOCK_METHOD2(ConfirmClientAuthToken, bool(const std::string&, ErrorPtr*));
   MOCK_METHOD5(
@@ -115,6 +116,10 @@
         .WillRepeatedly(Return(std::set<CryptoType>{
             CryptoType::kSpake_p224,
         }));
+    EXPECT_CALL(*this, GetAuthTypes())
+        .WillRepeatedly(Return(std::set<AuthType>{
+            AuthType::kAnonymous, AuthType::kPairing, AuthType::kLocal,
+        }));
 
     EXPECT_CALL(*this, StartPairing(_, _, _, _, _))
         .WillRepeatedly(DoAll(SetArgPointee<2>("testSession"),
diff --git a/src/privet/privet_handler.cc b/src/privet/privet_handler.cc
index ef0c54e..db55861 100644
--- a/src/privet/privet_handler.cc
+++ b/src/privet/privet_handler.cc
@@ -253,13 +253,8 @@
   auth->Set(kPairingKey, pairing_types.release());
 
   std::unique_ptr<base::ListValue> auth_types(new base::ListValue());
-  auth_types->AppendString(EnumToString(AuthType::kAnonymous));
-  auth_types->AppendString(EnumToString(AuthType::kPairing));
-
-  // TODO(vitalybuka): Implement cloud auth.
-  // if (cloud.GetConnectionState().IsStatusEqual(ConnectionState::kOnline)) {
-  //   auth_types->AppendString(kAuthTypeCloudValue);
-  // }
+  for (AuthType type : security.GetAuthTypes())
+    auth_types->AppendString(EnumToString(type));
   auth->Set(kAuthModeKey, auth_types.release());
 
   std::unique_ptr<base::ListValue> crypto_types(new base::ListValue());
diff --git a/src/privet/privet_handler_unittest.cc b/src/privet/privet_handler_unittest.cc
index 6fa6f35..6d6a289 100644
--- a/src/privet/privet_handler_unittest.cc
+++ b/src/privet/privet_handler_unittest.cc
@@ -217,6 +217,8 @@
       .WillRepeatedly(Return(std::set<PairingType>{}));
   EXPECT_CALL(security_, GetCryptoTypes())
       .WillRepeatedly(Return(std::set<CryptoType>{}));
+  EXPECT_CALL(security_, GetAuthTypes())
+      .WillRepeatedly(Return(std::set<AuthType>{}));
 
   const char kExpected[] = R"({
     'version': '3.0',
@@ -238,8 +240,6 @@
     'authentication': {
       'anonymousMaxScope': 'user',
       'mode': [
-        'anonymous',
-        'pairing'
       ],
       'pairing': [
       ],
@@ -290,7 +290,8 @@
       'anonymousMaxScope': 'none',
       'mode': [
         'anonymous',
-        'pairing'
+        'pairing',
+        'local'
       ],
       'pairing': [
         'pinCode',
diff --git a/src/privet/security_delegate.h b/src/privet/security_delegate.h
index 42021fd..867ff2a 100644
--- a/src/privet/security_delegate.h
+++ b/src/privet/security_delegate.h
@@ -41,6 +41,9 @@
   // Returns list of crypto methods supported by devices.
   virtual std::set<CryptoType> GetCryptoTypes() const = 0;
 
+  // Returns list of auth methods supported by devices.
+  virtual std::set<AuthType> GetAuthTypes() const = 0;
+
   // Returns Root Client Authorization Token.
   virtual std::string ClaimRootClientAuthToken(ErrorPtr* error) = 0;
 
diff --git a/src/privet/security_manager.cc b/src/privet/security_manager.cc
index 7c44963..bc8dc4f 100644
--- a/src/privet/security_manager.cc
+++ b/src/privet/security_manager.cc
@@ -118,19 +118,33 @@
                                         AuthScope* access_token_scope,
                                         base::TimeDelta* access_token_ttl,
                                         ErrorPtr* error) {
+  auto disabled_mode = [](ErrorPtr* error) {
+    Error::AddTo(error, FROM_HERE, errors::kDomain, errors::kInvalidAuthMode,
+                 "Mode is not available");
+    return false;
+  };
   switch (auth_type) {
     case AuthType::kAnonymous:
+      if (!auth_manager_->IsAnonymousAuthSupported())
+        return disabled_mode(error);
       break;
     case AuthType::kPairing:
+      if (!auth_manager_->IsPairingAuthSupported())
+        return disabled_mode(error);
       if (!IsValidPairingCode(auth_code)) {
         Error::AddTo(error, FROM_HERE, errors::kDomain,
                      errors::kInvalidAuthCode, "Invalid authCode");
         return false;
       }
       break;
+    case AuthType::kLocal:
+      if (!auth_manager_->IsLocalAuthSupported())
+        return disabled_mode(error);
+      NOTIMPLEMENTED();
+      // no break to fall back to default.
     default:
-      Error::AddToPrintf(error, FROM_HERE, errors::kDomain,
-                         errors::kInvalidAuthMode, "Unsupported auth mode");
+      Error::AddTo(error, FROM_HERE, errors::kDomain, errors::kInvalidAuthMode,
+                   "Unsupported auth mode");
       return false;
   }
 
@@ -179,6 +193,20 @@
   return result;
 }
 
+std::set<AuthType> SecurityManager::GetAuthTypes() const {
+  std::set<AuthType> result;
+  if (auth_manager_->IsAnonymousAuthSupported())
+    result.insert(AuthType::kAnonymous);
+
+  if (auth_manager_->IsPairingAuthSupported())
+    result.insert(AuthType::kPairing);
+
+  if (auth_manager_->IsLocalAuthSupported())
+    result.insert(AuthType::kLocal);
+
+  return result;
+}
+
 std::string SecurityManager::ClaimRootClientAuthToken(ErrorPtr* error) {
   return Base64Encode(auth_manager_->ClaimRootClientAuthToken(
       RootClientTokenOwner::kClient, error));
diff --git a/src/privet/security_manager.h b/src/privet/security_manager.h
index b80f6e7..5cb884f 100644
--- a/src/privet/security_manager.h
+++ b/src/privet/security_manager.h
@@ -72,6 +72,7 @@
                         ErrorPtr* error) const override;
   std::set<PairingType> GetPairingTypes() const override;
   std::set<CryptoType> GetCryptoTypes() const override;
+  std::set<AuthType> GetAuthTypes() const override;
   std::string ClaimRootClientAuthToken(ErrorPtr* error) override;
   bool ConfirmClientAuthToken(const std::string& token,
                               ErrorPtr* error) override;
@@ -103,9 +104,9 @@
   AuthManager* auth_manager_{nullptr};
 
   // If true allows unencrypted pairing and accepts any access code.
-  bool is_security_disabled_{false};
-  std::set<PairingType> pairing_modes_;
-  std::string embedded_code_;
+  const bool is_security_disabled_{false};
+  const std::set<PairingType> pairing_modes_;
+  const std::string embedded_code_;
   // TODO(vitalybuka): Session cleanup can be done without posting tasks.
   provider::TaskRunner* task_runner_{nullptr};
   std::map<std::string, std::unique_ptr<KeyExchanger>> pending_sessions_;