Merge pull request #5 in MM/mpin-sdk-core from feature/slav_backend_users to master

* commit '7815a9734835ccb82df3814b6c30c6378706a438':
  Add ListUsers for specific backend and ListBackends functions.
diff --git a/project/visual_studio_2012/unit_tests.vcxproj b/project/visual_studio_2012/unit_tests.vcxproj
index 65166e2..2160b56 100644
--- a/project/visual_studio_2012/unit_tests.vcxproj
+++ b/project/visual_studio_2012/unit_tests.vcxproj
@@ -55,6 +55,7 @@
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;WinHttp.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <SubSystem>Console</SubSystem>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
diff --git a/src/mpin_sdk.cpp b/src/mpin_sdk.cpp
index 3c76dd3..a441448 100644
--- a/src/mpin_sdk.cpp
+++ b/src/mpin_sdk.cpp
@@ -1327,11 +1327,23 @@
     m_logoutData.erase(user);
 }
 
-void MPinSDK::ListUsers(std::vector<UserPtr>& users)
+void MPinSDK::ListUsers(std::vector<UserPtr>& users) const
+{
+    ListUsers(users, m_users);
+}
+
+void MPinSDK::ListUsers(OUT std::vector<UserPtr>& users, const String& backend) const
+{
+    UsersMap usersMap;
+    LoadUsersFromStorage(backend, usersMap);
+    ListUsers(users, usersMap);
+}
+
+void MPinSDK::ListUsers(OUT std::vector<UserPtr>& users, const UsersMap& usersMap) const
 {
     users.clear();
-    users.reserve(m_users.size());
-    for(UsersMap::iterator i = m_users.begin(); i != m_users.end(); ++i)
+    users.reserve(usersMap.size());
+    for(UsersMap::const_iterator i = usersMap.begin(); i != usersMap.end(); ++i)
     {
         users.push_back(i->second);
     }
@@ -1458,7 +1470,11 @@
 Status MPinSDK::LoadUsersFromStorage()
 {
     ClearUsers();
+    return LoadUsersFromStorage(m_RPAServer, m_users);
+}
 
+Status MPinSDK::LoadUsersFromStorage(const String& backendServer, UsersMap& usersMap) const
+{
 	IStorage* storage = m_context->GetStorage(IStorage::NONSECURE);
 	String data;
 	storage->GetData(data);
@@ -1474,7 +1490,7 @@
         std::istringstream str(data);
         json::Reader::Read(allBackendsObject, str);
 
-        String backend = m_RPAServer;
+        String backend = backendServer;
         backend.ReplaceAll("https://", "");
         backend.ReplaceAll("http://", "");
 
@@ -1523,7 +1539,7 @@
 
             user->CacheTimePermit(timePermit, date);
 
-            m_users[id] = user;
+            usersMap[id] = user;
 		}
     }
     catch(const json::Exception& e)
@@ -1534,6 +1550,31 @@
 	return Status(Status::OK);
 }
 
+void MPinSDK::ListBackends(OUT std::vector<String>& backends) const
+{
+	IStorage* storage = m_context->GetStorage(IStorage::NONSECURE);
+	String data;
+	storage->GetData(data);
+    data.Trim();
+	if(data.empty())
+    {
+		return;
+	}
+
+	try
+    {
+        json::Object allBackendsObject;
+        std::istringstream str(data);
+        json::Reader::Read(allBackendsObject, str);
+
+        for(json::Object::const_iterator i = allBackendsObject.Begin(); i != allBackendsObject.End(); ++i)
+        {
+            backends.push_back(i->name);
+        }
+    }
+    catch(const json::Exception&) {}
+}
+
 const char * MPinSDK::GetVersion()
 {
     return MPIN_SDK_V2_VERSION;
diff --git a/src/mpin_sdk.h b/src/mpin_sdk.h
index 7644c83..902189a 100644
--- a/src/mpin_sdk.h
+++ b/src/mpin_sdk.h
@@ -178,7 +178,6 @@
 
     private:
         friend class MPinSDK;
-        friend class MPinSDKv2;
         User(const String& id, const String& deviceName);
         const String& GetDeviceName() const;
         const String& GetMPinIdHex() const;
@@ -245,7 +244,9 @@
     Status FinishAuthenticationAN(INOUT UserPtr user, const String& pin, const String& accessNumber);
 
     void DeleteUser(INOUT UserPtr user);
-    void ListUsers(OUT std::vector<UserPtr>& users);
+    void ListUsers(OUT std::vector<UserPtr>& users) const;
+    void ListUsers(OUT std::vector<UserPtr>& users, const String& backend) const;
+    void ListBackends(OUT std::vector<String>& backends) const;
     const char * GetVersion();
     bool CanLogout(IN UserPtr user);
     bool Logout(IN UserPtr user);
@@ -330,6 +331,9 @@
 	};
 
 private:
+    typedef std::map<String, UserPtr> UsersMap;
+    typedef std::map<UserPtr, LogoutData> LogoutDataMap;
+    
     bool IsInitilized() const;
     bool IsBackendSet() const;
     Status CheckIfIsInitialized() const;
@@ -347,14 +351,13 @@
     Status CheckUserState(IN UserPtr user, User::State expectedState);
 	Status WriteUsersToStorage();
 	Status LoadUsersFromStorage();
+    Status LoadUsersFromStorage(const String& backendServer, UsersMap& usersMap) const;
+    void ListUsers(OUT std::vector<UserPtr>& users, const UsersMap& usersMap) const;
 
     static const char *DEFAULT_RPS_PREFIX;
     static const int AN_WITH_CHECKSUM_LEN = 7;
 
 private:
-    typedef std::map<String, UserPtr> UsersMap;
-    typedef std::map<UserPtr, LogoutData> LogoutDataMap;
-    
     State m_state;
     IContext *m_context;
     IMPinCrypto *m_crypto;
diff --git a/tests/cmdline_test.cpp b/tests/cmdline_test.cpp
index aae0b13..7ababfa 100644
--- a/tests/cmdline_test.cpp
+++ b/tests/cmdline_test.cpp
@@ -36,6 +36,7 @@
 };
 
 static void TestBackend(const MPinSDK& sdk, const char *backend, const char *rpsPrefix);
+static void TestListBackendAndUsers(const MPinSDK& sdk);
 
 int main(int argc, char *argv[])
 {
@@ -85,6 +86,8 @@
         return 0;
     }
 
+    TestListBackendAndUsers(sdk);
+
     vector<MPinSDK::UserPtr> users;
     sdk.ListUsers(users);
     MPinSDK::UserPtr user;
@@ -194,3 +197,22 @@
         cout << "Backend test OK: " << beckend << endl;
     }
 }
+
+static void TestListBackendAndUsers(const MPinSDK& sdk)
+{
+    vector<MPinSDK::String> backends;
+    sdk.ListBackends(backends);
+
+    cout << endl << "TestListBackendAndUsers: Got " << backends.size() << " backends" << endl;
+
+    for(vector<MPinSDK::String>::const_iterator backend = backends.begin(); backend != backends.end(); ++backend)
+    {
+        cout << "    Listing users for backend '" << *backend << "':" << endl;
+        vector<MPinSDK::UserPtr> users;
+        sdk.ListUsers(users, *backend);
+        for(vector<MPinSDK::UserPtr>::iterator user = users.begin(); user != users.end(); ++user)
+        {
+            cout << "        - " << (*user)->GetId() << endl;
+        }
+    }
+}
diff --git a/tests/unit_tests.cpp b/tests/unit_tests.cpp
index 1950189..6892270 100644
--- a/tests/unit_tests.cpp
+++ b/tests/unit_tests.cpp
@@ -35,7 +35,7 @@
 static AutoContext context;
 static MPinSDK sdk;
 static MPinSDK::StringMap config;
-static const char *backend = "http://192.168.98.89:8005";
+static const char *backend = "http://192.168.98.98:8005";
 
 using namespace boost::unit_test;
 
@@ -76,10 +76,6 @@
     BOOST_CHECK_EQUAL(s, Status::FLOW_ERROR);
     BOOST_CHECK_EQUAL(user->GetState(), User::INVALID);
 
-    s = sdk.VerifyUser(user, "", "");
-    BOOST_CHECK_EQUAL(s, Status::FLOW_ERROR);
-    BOOST_CHECK_EQUAL(user->GetState(), User::INVALID);
-
     s = sdk.ConfirmRegistration(user);
     BOOST_CHECK_EQUAL(s, Status::FLOW_ERROR);
     BOOST_CHECK_EQUAL(user->GetState(), User::INVALID);
@@ -183,6 +179,21 @@
     sdk.ListUsers(users);
     BOOST_CHECK_EQUAL(users.size(), 1);
 
+    std::vector<String> backends;
+    sdk.ListBackends(backends);
+    BOOST_CHECK_EQUAL(backends.size(), 1);
+
+    if(!backends.empty())
+    {
+        users.clear();
+        sdk.ListUsers(users, backends[0]);
+        BOOST_CHECK_EQUAL(users.size(), 1);
+    }
+
+    users.clear();
+    sdk.ListUsers(users, backend);
+    BOOST_CHECK_EQUAL(users.size(), 1);
+
     sdk.DeleteUser(user);
 
     BOOST_MESSAGE("    testUsers2 finished");