[haiku-commits] haiku: hrev47891 - src/apps/haikudepot

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 21 Sep 2014 00:22:55 +0200 (CEST)

hrev47891 adds 2 changesets to branch 'master'
old head: f511367b330b856bc63995205f053e990fc16c74
new head: 36171a48e74618c56ec3bf2dd64543eeb433e448
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=36171a4+%5Ef511367

----------------------------------------------------------------------------

28075ee: HaikuDepot: Implemented logging into haiku-depot-server
  
  UserLoginWindow:
   * Focus nickname text field on tab switches
   * Implement testing the login info, the web-app replies with a token, if
     valid. It could be used for Token Bearer authorization of requests, but
     this is not used yet. Instead the username and password are set on the
     Model. Also after creating a new account successfully.
  Model:
   * Use a member instance of WebAppInterface. Set the preferred language
     and the login-info only once.

36171a4: HaikuDepot: Only authorize requests where needed.
  
  No requests are implemented yet which need to identify a user (such as rating
  a package).

                                      [ Stephan Aßmus <superstippi@xxxxxx> ]

----------------------------------------------------------------------------

6 files changed, 176 insertions(+), 34 deletions(-)
src/apps/haikudepot/Model.cpp           | 33 +++++-----
src/apps/haikudepot/Model.h             |  7 +++
src/apps/haikudepot/UserLoginWindow.cpp | 95 ++++++++++++++++++++++++++---
src/apps/haikudepot/UserLoginWindow.h   |  3 +
src/apps/haikudepot/WebAppInterface.cpp | 61 +++++++++++++++---
src/apps/haikudepot/WebAppInterface.h   | 11 +++-

############################################################################

Commit:      28075ee4274d1bd1c4dc57ffc85ecfdfd2afaaa5
URL:         http://cgit.haiku-os.org/haiku/commit/?id=28075ee
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sat Sep 20 22:09:17 2014 UTC

HaikuDepot: Implemented logging into haiku-depot-server

UserLoginWindow:
 * Focus nickname text field on tab switches
 * Implement testing the login info, the web-app replies with a token, if
   valid. It could be used for Token Bearer authorization of requests, but
   this is not used yet. Instead the username and password are set on the
   Model. Also after creating a new account successfully.
Model:
 * Use a member instance of WebAppInterface. Set the preferred language
   and the login-info only once.

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp
index 2b5b86a..d832456 100644
--- a/src/apps/haikudepot/Model.cpp
+++ b/src/apps/haikudepot/Model.cpp
@@ -21,8 +21,6 @@
 #include <Message.h>
 #include <Path.h>
 
-#include "WebAppInterface.h"
-
 
 #undef B_TRANSLATION_CONTEXT
 #define B_TRANSLATION_CONTEXT "Model"
@@ -338,6 +336,7 @@ Model::Model()
                                language.CopyInto(fPreferredLanguage, 0, 2);
                }
        }
+       fWebAppInterface.SetPreferredLanguage(fPreferredLanguage);
 }
 
 
@@ -516,8 +515,6 @@ Model::PopulatePackage(const PackageInfoRef& package, 
uint32 flags)
 
        if ((flags & POPULATE_USER_RATINGS) != 0) {
                // Retrieve info from web-app
-               WebAppInterface interface;
-               interface.SetPreferredLanguage(fPreferredLanguage);
                BMessage info;
 
                BString packageName;
@@ -528,7 +525,7 @@ Model::PopulatePackage(const PackageInfoRef& package, 
uint32 flags)
                        architecture = package->Architecture();
                }
        
-               status_t status = interface.RetrieveUserRatings(packageName,
+               status_t status = 
fWebAppInterface.RetrieveUserRatings(packageName,
                        architecture, 0, 50, info);
                if (status == B_OK) {
                        // Parse message
@@ -641,6 +638,17 @@ Model::StopPopulatingAllPackages()
 }
 
 
+void
+Model::SetAuthorization(const BString& username, const BString& password)
+{
+       BAutolock locker(&fLock);
+       fWebAppInterface.SetAuthorization(username, password);
+}
+
+
+// #pragma mark - private
+
+
 int32
 Model::_PopulateAllPackagesEntry(void* cookie)
 {
@@ -727,8 +735,6 @@ Model::_PopulatePackageInfos(PackageList& packages, bool 
fromCacheOnly,
                return;
        
        // Retrieve info from web-app
-       WebAppInterface interface;
-       interface.SetPreferredLanguage(fPreferredLanguage);
        BMessage info;
 
        StringList packageNames;
@@ -739,7 +745,7 @@ Model::_PopulatePackageInfos(PackageList& packages, bool 
fromCacheOnly,
                packageArchitectures.Add(package->Architecture());
        }
 
-       status_t status = interface.RetrieveBulkPackageInfo(packageNames,
+       status_t status = fWebAppInterface.RetrieveBulkPackageInfo(packageNames,
                packageArchitectures, info);
        if (status == B_OK) {
                // Parse message
@@ -818,11 +824,9 @@ Model::_PopulatePackageInfo(const PackageInfoRef& package, 
bool fromCacheOnly)
                return;
        
        // Retrieve info from web-app
-       WebAppInterface interface;
-       interface.SetPreferredLanguage(fPreferredLanguage);
        BMessage info;
 
-       status_t status = interface.RetrievePackageInfo(package->Title(),
+       status_t status = fWebAppInterface.RetrievePackageInfo(package->Title(),
                package->Architecture(), info);
        if (status == B_OK) {
                // Parse message
@@ -995,10 +999,10 @@ Model::_PopulatePackageIcon(const PackageInfoRef& 
package, bool fromCacheOnly)
                return;
 
        // Retrieve icon from web-app
-       WebAppInterface interface;
        BMallocIO buffer;
 
-       status_t status = interface.RetrievePackageIcon(package->Title(), 
&buffer);
+       status_t status = fWebAppInterface.RetrievePackageIcon(package->Title(),
+               &buffer);
        if (status == B_OK) {
                BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), 
true);
                BAutolock locker(&fLock);
@@ -1053,12 +1057,11 @@ Model::_PopulatePackageScreenshot(const PackageInfoRef& 
package,
                return;
 
        // Retrieve screenshot from web-app
-       WebAppInterface interface;
        BMallocIO buffer;
 
        int32 scaledHeight = scaledWidth * info.Height() / info.Width();
 
-       status_t status = interface.RetrieveScreenshot(info.Code(),
+       status_t status = fWebAppInterface.RetrieveScreenshot(info.Code(),
                scaledWidth, scaledHeight, &buffer);
        if (status == B_OK) {
                BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), 
true);
diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h
index ca8c67a..c968c1c 100644
--- a/src/apps/haikudepot/Model.h
+++ b/src/apps/haikudepot/Model.h
@@ -8,6 +8,8 @@
 #include <Locker.h>
 
 #include "PackageInfo.h"
+#include "WebAppInterface.h"
+
 
 class BMessage;
 
@@ -105,6 +107,9 @@ public:
                        const BString&          PreferredLanguage() const
                                                                        { 
return fPreferredLanguage; }
 
+                       void                            SetAuthorization(const 
BString& username,
+                                                                       const 
BString& password);
+
 private:
        static  int32                           _PopulateAllPackagesEntry(void* 
cookie);
                        void                            
_PopulateAllPackagesThread(bool fromCacheOnly);
@@ -168,6 +173,8 @@ private:
                        thread_id                       
fPopulateAllPackagesThread;
        volatile bool                           fStopPopulatingAllPackages;
                        BString                         fPreferredLanguage;
+
+                       WebAppInterface         fWebAppInterface;
 };
 
 
diff --git a/src/apps/haikudepot/UserLoginWindow.cpp 
b/src/apps/haikudepot/UserLoginWindow.cpp
index 09bbff3..0a525ca 100644
--- a/src/apps/haikudepot/UserLoginWindow.cpp
+++ b/src/apps/haikudepot/UserLoginWindow.cpp
@@ -209,12 +209,14 @@ UserLoginWindow::_SetMode(Mode mode)
                case LOGIN:
                        fTabView->Select((int32)0);
                        fSendButton->SetLabel(B_TRANSLATE("Log in"));
+                       fUsernameField->MakeFocus();
                        break;
                case CREATE_ACCOUNT:
                        fTabView->Select(1);
                        fSendButton->SetLabel(B_TRANSLATE("Create account"));
                        if (fCaptchaToken.IsEmpty())
                                _RequestCaptcha();
+                       fNewUsernameField->MakeFocus();
                        break;
                default:
                        break;
@@ -225,15 +227,15 @@ UserLoginWindow::_SetMode(Mode mode)
 void
 UserLoginWindow::_Login()
 {
-       // TODO: Implement...
-       BAlert* alert = new BAlert(B_TRANSLATE("Not implemented"),
-               B_TRANSLATE("Sorry, while the web application would already 
support "
-               "logging in, HaikuDepot was not yet updated to use "
-               "this functionality."),
-               B_TRANSLATE("Bummer"));
-       alert->Go(NULL);
-
-       PostMessage(B_QUIT_REQUESTED);
+       BAutolock locker(&fLock);
+       
+       if (fWorkerThread >= 0)
+               return;
+
+       thread_id thread = spawn_thread(&_AuthenticateThreadEntry,
+               "Authenticator", B_NORMAL_PRIORITY, this);
+       if (thread >= 0)
+               _SetWorkerThread(thread);
 }
 
 
@@ -304,6 +306,79 @@ UserLoginWindow::_SetWorkerThread(thread_id thread)
 
 
 int32
+UserLoginWindow::_AuthenticateThreadEntry(void* data)
+{
+       UserLoginWindow* window = reinterpret_cast<UserLoginWindow*>(data);
+       window->_AuthenticateThread();
+       return 0;
+}
+
+
+void
+UserLoginWindow::_AuthenticateThread()
+{
+       if (!Lock())
+               return;
+
+       BString nickName(fUsernameField->Text());
+       BString passwordClear(fPasswordField->Text());
+
+       Unlock();
+
+       WebAppInterface interface;
+       BMessage info;
+
+       status_t status = interface.AuthenticateUser(
+               nickName, passwordClear, info);
+
+       BString error = B_TRANSLATE("Authentication failed. "
+               "Connection to the service failed.");
+
+       BMessage result;
+       if (status == B_OK && info.FindMessage("result", &result) == B_OK) {
+               BString token;
+               if (result.FindString("token", &token) == B_OK && 
!token.IsEmpty()) {
+                       // We don't care for or store the token for now. The 
web-service
+                       // supports two methods of authorizing requests. One is 
via
+                       // Basic Authentication in the HTTP header, the other 
is via
+                       // Token Bearer. Since the connection is encrypted, it 
is hopefully
+                       // ok to send the password with each request instead of 
implementing
+                       // the Token Bearer. See section 5.1.2 in the 
haiku-depot-web
+                       // documentation.
+                       error = "";
+                       fModel.SetAuthorization(nickName, passwordClear);
+               } else {
+                       error = B_TRANSLATE("Authentication failed. The user 
does "
+                               "not exist or the wrong password was 
supplied.");
+               }
+       }
+
+       if (!error.IsEmpty()) {
+               BAlert* alert = new(std::nothrow) BAlert(
+                       B_TRANSLATE("Authentication failed"),
+                       error,
+                       B_TRANSLATE("Close"));
+
+               if (alert != NULL)
+                       alert->Go();
+
+               _SetWorkerThread(-1);
+       } else {
+               _SetWorkerThread(-1);
+               BMessenger(this).SendMessage(B_QUIT_REQUESTED);
+
+               BAlert* alert = new(std::nothrow) BAlert(
+                       B_TRANSLATE("Success"),
+                       B_TRANSLATE("The authentication was successful."),
+                       B_TRANSLATE("Close"));
+
+               if (alert != NULL)
+                       alert->Go();
+       }
+}
+
+
+int32
 UserLoginWindow::_RequestCaptchaThreadEntry(void* data)
 {
        UserLoginWindow* window = reinterpret_cast<UserLoginWindow*>(data);
@@ -433,6 +508,8 @@ UserLoginWindow::_CreateAccountThread()
                fCaptchaToken = "";
                _RequestCaptcha();
        } else {
+               fModel.SetAuthorization(nickName, passwordClear);
+
                _SetWorkerThread(-1);
                BMessenger(this).SendMessage(B_QUIT_REQUESTED);
 
diff --git a/src/apps/haikudepot/UserLoginWindow.h 
b/src/apps/haikudepot/UserLoginWindow.h
index cdcd813..a178881 100644
--- a/src/apps/haikudepot/UserLoginWindow.h
+++ b/src/apps/haikudepot/UserLoginWindow.h
@@ -40,6 +40,9 @@ private:
 
                        void                            
_SetWorkerThread(thread_id thread);
 
+       static  int32                           _AuthenticateThreadEntry(void* 
data);
+                       void                            _AuthenticateThread();
+
        static  int32                           
_RequestCaptchaThreadEntry(void* data);
                        void                            _RequestCaptchaThread();
 
diff --git a/src/apps/haikudepot/WebAppInterface.cpp 
b/src/apps/haikudepot/WebAppInterface.cpp
index 3eb44f1..9e1189d 100644
--- a/src/apps/haikudepot/WebAppInterface.cpp
+++ b/src/apps/haikudepot/WebAppInterface.cpp
@@ -238,11 +238,34 @@ WebAppInterface::WebAppInterface()
 }
 
 
+WebAppInterface::WebAppInterface(const WebAppInterface& other)
+       :
+       fUsername(other.fUsername),
+       fPassword(other.fPassword),
+       fLanguage(other.fLanguage)
+{
+}
+
+
 WebAppInterface::~WebAppInterface()
 {
 }
 
 
+WebAppInterface&
+WebAppInterface::operator=(const WebAppInterface& other)
+{
+       if (this == &other)
+               return *this;
+       
+       fUsername = other.fUsername;
+       fPassword = other.fPassword;
+       fLanguage = other.fLanguage;
+       
+       return *this;
+}
+
+
 void
 WebAppInterface::SetAuthorization(const BString& username,
        const BString& password)
@@ -452,6 +475,26 @@ WebAppInterface::CreateUser(const BString& nickName,
 }
 
 
+status_t
+WebAppInterface::AuthenticateUser(const BString& nickName,
+       const BString& passwordClear, BMessage& message)
+{
+       BString jsonString = JsonBuilder()
+               .AddValue("jsonrpc", "2.0")
+               .AddValue("id", ++fRequestIndex)
+               .AddValue("method", "authenticateUser")
+               .AddArray("params")
+                       .AddObject()
+                               .AddValue("nickname", nickName)
+                               .AddValue("passwordClear", passwordClear)
+                       .EndObject()
+               .EndArray()
+       .End();
+
+       return _SendJsonRequest("user", jsonString, message);
+}
+
+
 // #pragma mark - private
 
 
diff --git a/src/apps/haikudepot/WebAppInterface.h 
b/src/apps/haikudepot/WebAppInterface.h
index 181bc9f..1fe1b7c 100644
--- a/src/apps/haikudepot/WebAppInterface.h
+++ b/src/apps/haikudepot/WebAppInterface.h
@@ -21,8 +21,11 @@ typedef List<BString, false> StringList;
 class WebAppInterface {
 public:
                                                                
WebAppInterface();
+                                                               
WebAppInterface(const WebAppInterface& other);
        virtual                                         ~WebAppInterface();
 
+                       WebAppInterface&        operator=(const 
WebAppInterface& other);
+
                        void                            SetAuthorization(const 
BString& username,
                                                                        const 
BString& password);
                        void                            
SetPreferredLanguage(const BString& language);
@@ -63,6 +66,10 @@ public:
                                                                        const 
BString& languageCode,
                                                                        
BMessage& message);
 
+                       status_t                        AuthenticateUser(const 
BString& nickName,
+                                                                       const 
BString& passwordClear,
+                                                                       
BMessage& message);
+
 private:
                        status_t                        _SendJsonRequest(const 
char* domain,
                                                                        BString 
jsonString, BMessage& reply) const;
@@ -71,7 +78,6 @@ private:
                        BString                         fUsername;
                        BString                         fPassword;
                        BString                         fLanguage;
-                       BString                         fArchitecture;
        static  int                                     fRequestIndex;
 };
 

############################################################################

Revision:    hrev47891
Commit:      36171a48e74618c56ec3bf2dd64543eeb433e448
URL:         http://cgit.haiku-os.org/haiku/commit/?id=36171a4
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sat Sep 20 22:17:25 2014 UTC

HaikuDepot: Only authorize requests where needed.

No requests are implemented yet which need to identify a user (such as rating
a package).

----------------------------------------------------------------------------

diff --git a/src/apps/haikudepot/WebAppInterface.cpp 
b/src/apps/haikudepot/WebAppInterface.cpp
index 9e1189d..d8cc173 100644
--- a/src/apps/haikudepot/WebAppInterface.cpp
+++ b/src/apps/haikudepot/WebAppInterface.cpp
@@ -300,7 +300,7 @@ WebAppInterface::RetrievePackageInfo(const BString& 
packageName,
                .EndArray()
        .End();
 
-       return _SendJsonRequest("pkg", jsonString, message);
+       return _SendJsonRequest("pkg", jsonString, false, message);
 }
 
 
@@ -332,7 +332,7 @@ WebAppInterface::RetrieveBulkPackageInfo(const StringList& 
packageNames,
                .EndArray()
        .End();
 
-       return _SendJsonRequest("pkg", jsonString, message);
+       return _SendJsonRequest("pkg", jsonString, false, message);
 }
 
 
@@ -385,7 +385,7 @@ WebAppInterface::RetrieveUserRatings(const BString& 
packageName,
                .EndArray()
        .End();
 
-       return _SendJsonRequest("userrating", jsonString, message);
+       return _SendJsonRequest("userrating", jsonString, false, message);
 }
 
 
@@ -439,7 +439,7 @@ WebAppInterface::RequestCaptcha(BMessage& message)
                .EndArray()
        .End();
 
-       return _SendJsonRequest("captcha", jsonString, message);
+       return _SendJsonRequest("captcha", jsonString, false, message);
 }
 
 
@@ -471,7 +471,7 @@ WebAppInterface::CreateUser(const BString& nickName,
 
        BString jsonString = builder.End();
 
-       return _SendJsonRequest("user", jsonString, message);
+       return _SendJsonRequest("user", jsonString, false, message);
 }
 
 
@@ -491,7 +491,7 @@ WebAppInterface::AuthenticateUser(const BString& nickName,
                .EndArray()
        .End();
 
-       return _SendJsonRequest("user", jsonString, message);
+       return _SendJsonRequest("user", jsonString, false, message);
 }
 
 
@@ -500,7 +500,7 @@ WebAppInterface::AuthenticateUser(const BString& nickName,
 
 status_t
 WebAppInterface::_SendJsonRequest(const char* domain, BString jsonString,
-       BMessage& reply) const
+       bool needsAuthorization, BMessage& reply) const
 {
        BString urlString("https://depot.haiku-os.org/api/v1/";);
        urlString << domain;
@@ -515,8 +515,10 @@ WebAppInterface::_SendJsonRequest(const char* domain, 
BString jsonString,
 
        BHttpRequest request(url, true, "HTTP", &listener, &context);
 
-       // Authentication
-       if (!fUsername.IsEmpty() && !fPassword.IsEmpty()) {
+       // Authentication via Basic Authentication
+       // The other way would be to obtain a token and then use the Token 
Bearer
+       // header.
+       if (needsAuthorization && !fUsername.IsEmpty() && !fPassword.IsEmpty()) 
{
                request.SetUserName(fUsername);
                request.SetPassword(fPassword);
        }
diff --git a/src/apps/haikudepot/WebAppInterface.h 
b/src/apps/haikudepot/WebAppInterface.h
index 1fe1b7c..3407b25 100644
--- a/src/apps/haikudepot/WebAppInterface.h
+++ b/src/apps/haikudepot/WebAppInterface.h
@@ -72,7 +72,8 @@ public:
 
 private:
                        status_t                        _SendJsonRequest(const 
char* domain,
-                                                                       BString 
jsonString, BMessage& reply) const;
+                                                                       BString 
jsonString, bool needsAuthorization,
+                                                                       
BMessage& reply) const;
 
 private:
                        BString                         fUsername;


Other related posts:

  • » [haiku-commits] haiku: hrev47891 - src/apps/haikudepot - superstippi