Changeset 405:f056fa7fe8b4 in SMSSender


Ignore:
Timestamp:
May 5, 2014 1:50:05 PM (5 years ago)
Author:
Sämy Zehnder <saemy.zehnder@…>
Branch:
default
Message:
  • Switches to OAuth2 authentication for importing contacts from Google.
Location:
frontend
Files:
5 added
18 edited

Legend:

Unmodified
Added
Removed
  • frontend/business/contactimporter/googlecontactimporter_base.cpp

    r402 r405  
    2626#include "frontend/business/contactimporter/googlecontactimporter.h"
    2727
    28 BaseGoogleContactImporter::BaseGoogleContactImporter(const BaseGoogleContactImporter::AuthData &authData)
    29     : m_authData(authData)
     28BaseGoogleContactImporter::BaseGoogleContactImporter(
     29        const OAuth2::AccessToken &accessToken)
     30    : m_accessToken(accessToken)
    3031{
    3132    m_httpHelper.addTrustedCA(":/certs/Equifax_Secure_Certificate_Authority.crt");
     
    3334
    3435void BaseGoogleContactImporter::importContacts(QSet<SContact *> *contacts) {
    35     // TODO Use OAuth2
    36     requestAuthToken();
     36    m_httpHelper.defaultHeaders().insert(
     37                "Authorization",
     38                QString("%1 %2")
     39                    .arg(m_accessToken.tokenType)
     40                    .arg(m_accessToken.accessToken)
     41                    .toUtf8());
    3742    m_httpHelper.defaultHeaders().insert("GData-Version", "3.0");
    3843
     
    116121
    117122    if ((rx.indexIn(entry) != -1) && !rx.cap(1).isEmpty()) {
    118         //qDebug() << rx.cap(1);
    119123        QStringList aliases;
    120124        aliases.append(rx.cap(1));
     
    122126    }
    123127
    124 }
    125 
    126 void BaseGoogleContactImporter::requestAuthToken() {
    127     QList<IParam*> posts;
    128     posts.append(new SKeyValueParam("accountType", "GOOGLE"));
    129     posts.append(new SKeyValueParam("Email", m_authData.username.toUtf8()));
    130     posts.append(new SKeyValueParam("Passwd", m_authData.password.toUtf8()));
    131     posts.append(new SKeyValueParam("service", "cp"));
    132     posts.append(new SKeyValueParam("source", "gorrion-smssender-3"));
    133 
    134     QString result;
    135     try {
    136         result = m_httpHelper.syncPost(QUrl::fromEncoded("https://www.google.com/accounts/ClientLogin"), posts)->readAll();
    137     } catch (EException &e) {
    138         result = "";
    139     }
    140 
    141     QRegExp rx("Auth=(\\S+)");
    142     if (rx.indexIn(result) != -1) {
    143         m_httpHelper.defaultHeaders().insert("Authorization", QString("GoogleLogin auth=" + rx.cap(1)).toUtf8());
    144     } else {
    145         EException("Login failed. You have probably entered incorrect userdata.")
    146                 .raise();
    147     }
    148128}
    149129
     
    165145
    166146void BaseGoogleContactImporter::Builder::init() {
    167     m_authData.username.clear();
    168     m_authData.password.clear();
     147    m_accessToken = OAuth2::AccessToken();
    169148}
    170149
    171150void BaseGoogleContactImporter::Builder::createImporters(
    172151        QSet<IContactImporter *> *importers) {
    173     importers->insert(new GoogleContactImporter(m_authData));
     152    importers->insert(new GoogleContactImporter(m_accessToken));
    174153}
  • frontend/business/contactimporter/googlecontactimporter_base.h

    r390 r405  
    2323#include "common/business/icontactimporter.h"
    2424#include "common/network/snetworkhelper.h"
     25#include "frontend/business/contactimporter/oauth2.h"
    2526
    2627class BaseGoogleContactImporter : public IContactImporter {
     
    2829
    2930public:
    30     struct AuthData {
    31         QString username;
    32         QString password;
    33     };
    34 
    35     explicit BaseGoogleContactImporter(const AuthData &authData);
     31    explicit BaseGoogleContactImporter(const OAuth2::AccessToken &accessToken);
    3632
    3733public: /* IContactImporter */
     
    4743
    4844    protected:
    49         AuthData m_authData;
     45        OAuth2::AccessToken m_accessToken;
    5046    };
    5147
     
    5955
    6056private:
    61     AuthData m_authData;
     57    OAuth2::AccessToken m_accessToken;
    6258    SNetworkHelper m_httpHelper;
    6359};
  • frontend/frontend-base.pro

    r393 r405  
    1414
    1515LIBS += \
    16     -lcryptopp
     16    -lcryptopp \
     17    -lqjson
    1718
    1819HEADERS += \
     
    2829    business/contactimporter/googlecontactimporter.h \
    2930    business/contactimporter/googlecontactimporter_base.h \
     31    business/contactimporter/oauth2.h \
     32    business/contactimporter/oauth2_p.h \
    3033    business/contactimportermanager.h \
    3134    business/contactmanager.h \
     
    4649    persistence/groupmanager.h \
    4750    persistence/mainstorage_base.h \
     51    persistence/oauth2_credentialstore.h \
    4852    persistence/persistenceintegrationhelper.h \
    4953    persistence/restrictedmainstorage.h \
     
    5761    business/contactimporter/contactimporter.cpp \
    5862    business/contactimporter/googlecontactimporter_base.cpp \
     63    business/contactimporter/oauth2.cpp \
    5964    business/contactimportermanager.cpp \
    6065    business/contactmanager.cpp \
     
    6974    persistence/mainstorage_base.cpp \
    7075    persistence/mainstorage_base_storage.cpp \
     76    persistence/oauth2_credentialstore.cpp \
    7177    persistence/pers_accountmanager.cpp \
    7278    persistence/pers_accountmanager_storage.cpp \
  • frontend/gui/business/googlecontactimporter.cpp

    r390 r405  
    2222#include "frontend/gui/ui/importcontacts/pages/google_page_config.h"
    2323
    24 GoogleContactImporter::GoogleContactImporter(const AuthData &authData)
    25     : BaseGoogleContactImporter(authData)
     24GoogleContactImporter::GoogleContactImporter(const OAuth2::AccessToken &accessToken)
     25    : BaseGoogleContactImporter(accessToken)
    2626{
    27 }
    28 
    29 void GoogleContactImporter::Builder::createPreImportPages(QList<QWizardPage *> *pages) {
    30     pages->append(new UI::GCI::PageConfig(&m_authData));
    3127}
    3228
     
    4440    }
    4541}
     42
     43GoogleContactImporter::Builder::Builder(Persistence::IMainStorage *mainStorage)
     44    : m_mainStorage(mainStorage)
     45{
     46}
     47
     48void GoogleContactImporter::Builder::createPreImportPages(QList<QWizardPage *> *pages) {
     49    pages->append(new UI::GCI::PageConfig(&m_accessToken, m_mainStorage));
     50}
  • frontend/gui/business/googlecontactimporter.h

    r390 r405  
    1919#define FRONTEND_GUI_GOOGLECONTACTIMPORTER_H
    2020
     21#include "common/persistence/imainstorage.h"
    2122#include "frontend/business/contactimporter/googlecontactimporter_base.h"
    2223
    2324class GoogleContactImporter : public BaseGoogleContactImporter {
    2425public:
    25     explicit GoogleContactImporter(const AuthData &authData);
     26    explicit GoogleContactImporter(const OAuth2::AccessToken &accessToken);
    2627
    2728    class Builder : public BaseGoogleContactImporter::Builder {
    2829    public:
     30        explicit Builder(Persistence::IMainStorage *mainStorage);
     31
    2932        void createPreImportPages(QList<QWizardPage *> *pages);
     33
     34    private:
     35        Persistence::IMainStorage * const m_mainStorage;
    3036    };
    3137
  • frontend/gui/business/managerfactory.cpp

    r335 r405  
    5050    , m_guiManager(new UI::GuiManager(m_settingsManager.data()))
    5151{
    52     m_contactImporterManager->registerManagedContactImporter(new ContactFilesImporter::Builder);
    53     m_contactImporterManager->registerManagedContactImporter(new GoogleContactImporter::Builder);
     52    m_contactImporterManager->registerManagedContactImporter(
     53                new ContactFilesImporter::Builder);
     54    m_contactImporterManager->registerManagedContactImporter(
     55                new GoogleContactImporter::Builder(
     56                    persistenceFactory.mainStorage()));
    5457}
    5558ManagerFactory::~ManagerFactory() {
  • frontend/gui/frontend-gui.pro

    r403 r405  
    2828
    2929LIBS += \
     30    -lqjson \
     31\
    3032    -L../../ -lcommon-gui$$LIB_SUFFIX \
    3133
  • frontend/gui/locale/de.ts

    r392 r405  
    246246    </message>
    247247    <message>
    248         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="20"/>
    249         <source>Please enter your username and password to allow smssender to login to google contacts.</source>
    250         <translation>Bitte gib deine Benutzerdaten ein um SMSSender das Login zu Google-Kontakte zu erlauben.</translation>
    251     </message>
    252     <message>
    253         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="30"/>
    254         <source>Username:</source>
    255         <translation>Benutzername:</translation>
    256     </message>
    257     <message>
    258         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="40"/>
    259         <source>Password:</source>
    260         <translation>Passwort:</translation>
     248        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="26"/>
     249        <source>smssender wants access to your Google account. Please choose an already connected one or initiate a new connection.</source>
     250        <translation>SMSSender versucht auf dein Google-Konto zuzugreifen. Bitte wähle ein bereits verbundenes Konto oder verbinde ein Neues.</translation>
     251    </message>
     252    <message>
     253        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="90"/>
     254        <source>Connect a new account</source>
     255        <translation>Verbinde ein neues Konto</translation>
    261256    </message>
    262257</context>
     
    418413<context>
    419414    <name>QObject</name>
    420     <message>
    421         <location filename="../ui/guimanager.cpp" line="63"/>
    422         <source>Error occured</source>
    423         <translation>Fehler aufgetreten</translation>
    424     </message>
    425415    <message>
    426416        <location filename="../business/settings.cpp" line="26"/>
     
    901891</context>
    902892<context>
     893    <name>UI::ExceptionMessageBox</name>
     894    <message>
     895        <location filename="../ui/exceptionmessagebox.cpp" line="28"/>
     896        <source>Error occured</source>
     897        <translation>Fehler aufgetreten</translation>
     898    </message>
     899</context>
     900<context>
     901    <name>UI::GCI::PageConfig</name>
     902    <message>
     903        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="91"/>
     904        <source>Action required</source>
     905        <translation>Aktion erforderlich</translation>
     906    </message>
     907    <message>
     908        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="94"/>
     909        <source>Please see your browser to grant smssender access to your Google account.</source>
     910        <translation>Bitte wechsle in deinen Browser um SMSSender Zugriff auf dein Google-Konto zu gewähren.</translation>
     911    </message>
     912    <message>
     913        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="96"/>
     914        <source>Please open the following link in your browser to grant smssender access to your Google account:
     915&lt;a href=&apos;%1&apos;&gt;%1&lt;/a&gt;</source>
     916        <translation>Bitte öffne den folgenden Link in deinem Browser um SMSSender Zugriff auf dein Google-Konto zu gewähren: &lt;a href=&apos;%1&apos;&gt;%1&lt;/a&gt;</translation>
     917    </message>
     918    <message>
     919        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="191"/>
     920        <source>An error occured while connecting to the Google account.</source>
     921        <translation>Während der Verbindung zu Google ist ein Fehler aufgetreten.</translation>
     922    </message>
     923</context>
     924<context>
    903925    <name>UI::GroupTableModel</name>
    904926    <message>
  • frontend/gui/locale/de_CH.ts

    r392 r405  
    246246    </message>
    247247    <message>
    248         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="20"/>
    249         <source>Please enter your username and password to allow smssender to login to google contacts.</source>
    250         <translation>Bitte gib di Benutzername und di Ghaimwort yh, damit dr SMSSänder sich bi Google-Kontaggt aamälde ka.</translation>
    251     </message>
    252     <message>
    253         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="30"/>
    254         <source>Username:</source>
    255         <translation>Benutzername:</translation>
    256     </message>
    257     <message>
    258         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="40"/>
    259         <source>Password:</source>
    260         <translation>Ghaimwort:</translation>
     248        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="26"/>
     249        <source>smssender wants access to your Google account. Please choose an already connected one or initiate a new connection.</source>
     250        <translation>Dr SMSSänder wött uf di Google-Konto zuegriffe. Bitte wähl e bereits verbundenes Konto oder verbind e Neus.</translation>
     251    </message>
     252    <message>
     253        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="90"/>
     254        <source>Connect a new account</source>
     255        <translation>Verbind e neus Konto</translation>
    261256    </message>
    262257</context>
     
    418413<context>
    419414    <name>QObject</name>
    420     <message>
    421         <location filename="../ui/guimanager.cpp" line="63"/>
    422         <source>Error occured</source>
    423         <translation>Fähler ufträtte</translation>
    424     </message>
    425415    <message>
    426416        <location filename="../business/settings.cpp" line="26"/>
     
    901891</context>
    902892<context>
     893    <name>UI::ExceptionMessageBox</name>
     894    <message>
     895        <location filename="../ui/exceptionmessagebox.cpp" line="28"/>
     896        <source>Error occured</source>
     897        <translation>Fähler ufträtte</translation>
     898    </message>
     899</context>
     900<context>
     901    <name>UI::GCI::PageConfig</name>
     902    <message>
     903        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="91"/>
     904        <source>Action required</source>
     905        <translation>Aktion erforderlich</translation>
     906    </message>
     907    <message>
     908        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="94"/>
     909        <source>Please see your browser to grant smssender access to your Google account.</source>
     910        <translation>Bitte wäggsle in di Browser zum em SMSSänder Zuegriff uf di Google-Konto z gwähre.</translation>
     911    </message>
     912    <message>
     913        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="96"/>
     914        <source>Please open the following link in your browser to grant smssender access to your Google account:
     915&lt;a href=&apos;%1&apos;&gt;%1&lt;/a&gt;</source>
     916        <translation>Bitte öffne dä Link in dim Browser zum em SMSSänder Zuegriff uf di Google-Konto z gwähre: &lt;a href=&apos;%1&apos;&gt;%1&lt;/a&gt;</translation>
     917    </message>
     918    <message>
     919        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="191"/>
     920        <source>An error occured while connecting to the Google account.</source>
     921        <translation>Während dr Vrbinding zu Google isch e Fähler ufträtte.</translation>
     922    </message>
     923</context>
     924<context>
    903925    <name>UI::GroupTableModel</name>
    904926    <message>
  • frontend/gui/locale/fr.ts

    r392 r405  
    248248    </message>
    249249    <message>
    250         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="20"/>
    251         <source>Please enter your username and password to allow smssender to login to google contacts.</source>
    252         <translation>Entrez votre nom d&apos;utilisateur et mot de passe pour permettre smssender de se connecter à google contacts, s&apos;il vous plaît.</translation>
    253     </message>
    254     <message>
    255         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="30"/>
    256         <source>Username:</source>
    257         <translation>Nom d&apos;utilisateur:</translation>
    258     </message>
    259     <message>
    260         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="40"/>
    261         <source>Password:</source>
    262         <translation>Mot de passe:</translation>
     250        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="26"/>
     251        <source>smssender wants access to your Google account. Please choose an already connected one or initiate a new connection.</source>
     252        <translation type="unfinished"></translation>
     253    </message>
     254    <message>
     255        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="90"/>
     256        <source>Connect a new account</source>
     257        <translation type="unfinished"></translation>
    263258    </message>
    264259</context>
     
    420415<context>
    421416    <name>QObject</name>
    422     <message>
    423         <location filename="../ui/guimanager.cpp" line="63"/>
    424         <source>Error occured</source>
    425         <translation>Un erreur s&apos;est produit</translation>
    426     </message>
    427417    <message>
    428418        <location filename="../business/settings.cpp" line="26"/>
     
    903893</context>
    904894<context>
     895    <name>UI::ExceptionMessageBox</name>
     896    <message>
     897        <location filename="../ui/exceptionmessagebox.cpp" line="28"/>
     898        <source>Error occured</source>
     899        <translation type="unfinished">Un erreur s&apos;est produit</translation>
     900    </message>
     901</context>
     902<context>
     903    <name>UI::GCI::PageConfig</name>
     904    <message>
     905        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="91"/>
     906        <source>Action required</source>
     907        <translation type="unfinished"></translation>
     908    </message>
     909    <message>
     910        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="94"/>
     911        <source>Please see your browser to grant smssender access to your Google account.</source>
     912        <translation type="unfinished"></translation>
     913    </message>
     914    <message>
     915        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="96"/>
     916        <source>Please open the following link in your browser to grant smssender access to your Google account:
     917&lt;a href=&apos;%1&apos;&gt;%1&lt;/a&gt;</source>
     918        <translation type="unfinished"></translation>
     919    </message>
     920    <message>
     921        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="191"/>
     922        <source>An error occured while connecting to the Google account.</source>
     923        <translation type="unfinished"></translation>
     924    </message>
     925</context>
     926<context>
    905927    <name>UI::GroupTableModel</name>
    906928    <message>
  • frontend/gui/locale/it.ts

    r392 r405  
    242242    </message>
    243243    <message>
    244         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="20"/>
    245         <source>Please enter your username and password to allow smssender to login to google contacts.</source>
    246         <translation type="unfinished"></translation>
    247     </message>
    248     <message>
    249         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="30"/>
    250         <source>Username:</source>
    251         <translation type="unfinished"></translation>
    252     </message>
    253     <message>
    254         <location filename="../ui/importcontacts/pages/google_page_config.ui" line="40"/>
    255         <source>Password:</source>
     244        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="26"/>
     245        <source>smssender wants access to your Google account. Please choose an already connected one or initiate a new connection.</source>
     246        <translation type="unfinished"></translation>
     247    </message>
     248    <message>
     249        <location filename="../ui/importcontacts/pages/google_page_config.ui" line="90"/>
     250        <source>Connect a new account</source>
    256251        <translation type="unfinished"></translation>
    257252    </message>
     
    414409<context>
    415410    <name>QObject</name>
    416     <message>
    417         <location filename="../ui/guimanager.cpp" line="63"/>
    418         <source>Error occured</source>
    419         <translation type="unfinished"></translation>
    420     </message>
    421411    <message>
    422412        <location filename="../business/settings.cpp" line="26"/>
     
    895885</context>
    896886<context>
     887    <name>UI::ExceptionMessageBox</name>
     888    <message>
     889        <location filename="../ui/exceptionmessagebox.cpp" line="28"/>
     890        <source>Error occured</source>
     891        <translation type="unfinished"></translation>
     892    </message>
     893</context>
     894<context>
     895    <name>UI::GCI::PageConfig</name>
     896    <message>
     897        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="91"/>
     898        <source>Action required</source>
     899        <translation type="unfinished"></translation>
     900    </message>
     901    <message>
     902        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="94"/>
     903        <source>Please see your browser to grant smssender access to your Google account.</source>
     904        <translation type="unfinished"></translation>
     905    </message>
     906    <message>
     907        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="96"/>
     908        <source>Please open the following link in your browser to grant smssender access to your Google account:
     909&lt;a href=&apos;%1&apos;&gt;%1&lt;/a&gt;</source>
     910        <translation type="unfinished"></translation>
     911    </message>
     912    <message>
     913        <location filename="../ui/importcontacts/pages/google_page_config.cpp" line="191"/>
     914        <source>An error occured while connecting to the Google account.</source>
     915        <translation type="unfinished"></translation>
     916    </message>
     917</context>
     918<context>
    897919    <name>UI::GroupTableModel</name>
    898920    <message>
  • frontend/gui/ui/importcontacts/pages/google_page_config.cpp

    r390 r405  
    1818#include "google_page_config.h"
    1919
     20#include <boost/bind.hpp>
     21#include <qjson/parser.h>
     22
     23#include <QDesktopServices>
     24
     25#include "common/network/snetworkhelper.h"
     26#include "common/network/snetworkreply.h"
     27#include "frontend/gui/ui/exceptionmessagebox.h"
     28
    2029namespace UI {
    2130namespace GCI {
    2231
    23 PageConfig::PageConfig(GoogleContactImporter::AuthData *authData)
     32namespace {
     33static const QSet<QString> kRequiredScopes = QStringList(
     34                { OAuth2::Scope::Contacts, OAuth2::Scope::Plus::Me }
     35            ).toSet();
     36} // namespace
     37
     38PageConfig::PageConfig(OAuth2::AccessToken *accessToken,
     39                       Persistence::IMainStorage *mainStorage)
    2440    : QWizardPage()
    25     , m_authData(authData)
     41    , m_accessToken(accessToken)
     42
     43    , m_credentialStore(new Persistence::OAuth2::CredentialStore(mainStorage))
     44    , m_authorizationFlow(new OAuth2::AuthorizationFlow(m_credentialStore.data()))
    2645{
    2746        ui.setupUi(this);
    2847
    29     connect(ui.edtUsername, SIGNAL(textChanged(const QString&)),
     48    connect(m_authorizationFlow.data(), SIGNAL(accessTokenFetched(const OAuth2::AuthorizationFlow::AccessTokenFetchResult &)),
     49            this, SLOT(accessTokenFetched(const OAuth2::AuthorizationFlow::AccessTokenFetchResult &)));
     50
     51    connect(ui.btn_newConnection, SIGNAL(clicked()),
     52            this, SLOT(connectNewAccount()));
     53    connect(ui.sel_existing, SIGNAL(currentIndexChanged(int)),
    3054            this, SLOT(dataChanged()));
    31     connect(ui.edtPassword, SIGNAL(textChanged(const QString&)),
    32             this, SLOT(dataChanged()));
     55
     56    ui.sel_existing->clear();
     57    ui.sel_existing->hide();
     58}
     59
     60void PageConfig::initializePage() {
     61    // Starts fetching access tokens for the already paired accounts.
     62    QStringList pairedAccounts =
     63            m_credentialStore->pairedAccounts(kRequiredScopes);
     64    foreach(const QString &pairedAccount, pairedAccounts) {
     65        m_authorizationFlow->startFetchAccessToken(
     66                    pairedAccount, kRequiredScopes,
     67                    OAuth2::AuthorizationFlow::UrlToUserCallback());
     68    }
    3369}
    3470
    3571void PageConfig::dataChanged() {
    36     m_authData->username = ui.edtUsername->text();
    37     m_authData->password = ui.edtPassword->text();
     72    *m_accessToken =
     73            m_pairedAccounts.value(ui.sel_existing->currentIndex()).accessToken;
    3874
    3975    emit completeChanged();
     
    4177
    4278bool PageConfig::isComplete() const {
    43     return !ui.edtUsername->text().isEmpty() &&
    44            !ui.edtPassword->text().isEmpty();
     79    return ui.sel_existing->currentIndex() >= 0;
     80}
     81
     82void PageConfig::connectNewAccount() {
     83    m_authorizationFlow->startFetchAccessToken(
     84                "", kRequiredScopes,
     85                boost::bind(&PageConfig::showUrlToUser, this, _1));
     86}
     87
     88void PageConfig::showUrlToUser(const QString &url) {
     89    bool ok = QDesktopServices::openUrl(url);
     90
     91    QMessageBox msg(QMessageBox::Question, tr("Action required"), "",
     92                    QMessageBox::Ok, this);
     93    if (ok) {
     94        msg.setText(tr("Please see your browser to grant smssender access to your Google account."));
     95    } else {
     96        msg.setText(tr("Please open the following link in your browser to grant smssender access to your Google account:\n<a href='%1'>%1</a>").arg(url));
     97    }
     98    msg.exec();
     99}
     100
     101// We need access to the https://www.googleapis.com/auth/plus.me scope.
     102bool PageConfig::fetchAccountInfo(const OAuth2::AccessToken &accessToken,
     103                                  QString *name, QIcon *image) {
     104    QScopedPointer<SNetworkHelper> http(new SNetworkHelper);
     105    http->addTrustedCA(":/certs/Equifax_Secure_Certificate_Authority.crt");
     106    http->defaultHeaders().insert("Authorization",
     107                                  QString("%1 %2")
     108                                      .arg(accessToken.tokenType)
     109                                      .arg(accessToken.accessToken)
     110                                      .toUtf8());
     111    SNetworkReply reply;
     112    try {
     113        reply = http->syncGet(QString("https://www.googleapis.com/plus/v1/people/me?"
     114                                      "fields=displayName,image/url"));
     115    } catch (const EException &e) {
     116        qWarning() << "Failed to load Google account information: "
     117                   << e.chainedWhat();
     118        return false;
     119    }
     120
     121    // Parses the reply.
     122    // Can be replaced by QJson in Qt5.
     123    QJson::Parser parser;
     124    bool ok;
     125    QByteArray data = reply->readAll();
     126    QVariantMap result = parser.parse(data, &ok).toMap();
     127    if (!ok) {
     128        return false;
     129    }
     130
     131    // Reads out the account data.
     132    *name = result["displayName"].toString();
     133    QString imageUrl = result["image"].toMap()["url"].toString();
     134    if (name->isEmpty() || imageUrl.isEmpty()) {
     135        return false;
     136    }
     137
     138    QByteArray imageData = http->syncGet(imageUrl)->readAll();
     139    *image = QPixmap::fromImage(QImage::fromData(imageData));
     140
     141    return ok;
     142}
     143
     144/**
     145 * Gets called if either a connection already existed and we got a refreshed
     146 * access token or the user initiated a new connection. In both cases, there
     147 * does not yet exist an item in the selection box -> we fetch the required
     148 * information from the account and create a new entry.
     149 *
     150 * @param account
     151 * @param fetchResult
     152 */
     153void PageConfig::accessTokenFetched(
     154        const OAuth2::AuthorizationFlow::AccessTokenFetchResult &fetchResult) {
     155    try {
     156        if (fetchResult.isError) {
     157            throw QString("Could not fetch the access token: %2")
     158                    .arg(fetchResult.errorMessage);
     159        }
     160
     161        // Checks if the given account is already paired.
     162        for (int i = 0; i < m_pairedAccounts.size(); ++i) {
     163            Account &account = m_pairedAccounts[i];
     164            if (account.id == fetchResult.accountId) {
     165                account.accessToken = fetchResult.accessToken;
     166                return;
     167            }
     168        }
     169
     170        // Creates a new account entry.
     171        m_pairedAccounts.append(Account());
     172        Account &pairedAccount = m_pairedAccounts.last();
     173        pairedAccount.id = fetchResult.accountId;
     174        pairedAccount.accessToken = fetchResult.accessToken;
     175
     176        // Fetches the account email and image.
     177        bool ok = fetchAccountInfo(pairedAccount.accessToken, &pairedAccount.name,
     178                                   &pairedAccount.image);
     179        if (!ok) {
     180            throw QString("Errors in the reply from Google.");
     181        }
     182
     183        // Inserts the account into the paired list.
     184        ui.sel_existing->addItem(pairedAccount.image, pairedAccount.name);
     185        if (ui.sel_existing->currentIndex() < 0) {
     186            ui.sel_existing->setCurrentIndex(0);
     187        }
     188        ui.sel_existing->show();
     189    } catch (QString &error) {
     190        ExceptionMessageBox msg(
     191                    tr("An error occured while connecting to the Google account."),
     192                    EException(error), this);
     193        msg.exec();
     194    }
    45195}
    46196
  • frontend/gui/ui/importcontacts/pages/google_page_config.h

    r320 r405  
    2121#include "ui_google_page_config.h"
    2222
     23#include <QIcon>
     24#include <QScopedPointer>
    2325#include <QWizardPage>
    2426
     27#include "common/persistence/imainstorage.h"
    2528#include "frontend/business/contactimporter/googlecontactimporter.h"
     29#include "frontend/business/contactimporter/oauth2.h"
     30#include "frontend/persistence/oauth2_credentialstore.h"
    2631
    2732namespace UI {
     
    3237
    3338public:
    34     explicit PageConfig(GoogleContactImporter::AuthData *authData);
     39    PageConfig(OAuth2::AccessToken *accessToken,
     40               Persistence::IMainStorage *mainStorage);
    3541
    3642public: /* QWizardPage */
     43    void initializePage();
    3744    bool isComplete() const;
    3845
    3946private slots:
     47    void accessTokenFetched(
     48            const OAuth2::AuthorizationFlow::AccessTokenFetchResult &fetchResult);
     49    void connectNewAccount();
    4050    void dataChanged();
    4151
    4252private:
     53    struct Account {
     54        QString id;
     55        QString name;
     56        QIcon image;
     57        OAuth2::AccessToken accessToken;
     58    };
     59
     60    bool fetchAccountInfo(const OAuth2::AccessToken &accessToken,
     61                          QString *name, QIcon *image);
     62    void showUrlToUser(const QString &url);
     63
    4364    ::GCI::Ui::PageConfigClass ui;
    4465
    45     GoogleContactImporter::AuthData * const m_authData;
     66    OAuth2::AccessToken * const m_accessToken;
     67
     68    QScopedPointer<Persistence::OAuth2::CredentialStore> m_credentialStore;
     69    QScopedPointer<OAuth2::AuthorizationFlow> m_authorizationFlow;
     70    QList<Account> m_pairedAccounts;
    4671};
    4772
  • frontend/gui/ui/importcontacts/pages/google_page_config.ui

    r320 r405  
    88    <y>0</y>
    99    <width>400</width>
    10     <height>168</height>
     10    <height>223</height>
    1111   </rect>
    1212  </property>
     
    1414   <string>PageConfig</string>
    1515  </property>
    16   <layout class="QFormLayout" name="formLayout">
    17    <item row="0" column="0" colspan="2">
     16  <layout class="QVBoxLayout" name="verticalLayout">
     17   <item>
    1818    <widget class="QLabel" name="label">
     19     <property name="sizePolicy">
     20      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
     21       <horstretch>0</horstretch>
     22       <verstretch>0</verstretch>
     23      </sizepolicy>
     24     </property>
    1925     <property name="text">
    20       <string>Please enter your username and password to allow smssender to login to google contacts.</string>
     26      <string>smssender wants access to your Google account. Please choose an already connected one or initiate a new connection.</string>
    2127     </property>
    2228     <property name="wordWrap">
     
    2531    </widget>
    2632   </item>
    27    <item row="2" column="0">
    28     <widget class="QLabel" name="label_2">
    29      <property name="text">
    30       <string>Username:</string>
    31      </property>
    32     </widget>
    33    </item>
    34    <item row="2" column="1">
    35     <widget class="QLineEdit" name="edtUsername"/>
    36    </item>
    37    <item row="3" column="0">
    38     <widget class="QLabel" name="label_3">
    39      <property name="text">
    40       <string>Password:</string>
    41      </property>
    42     </widget>
    43    </item>
    44    <item row="3" column="1">
    45     <widget class="QLineEdit" name="edtPassword">
    46      <property name="echoMode">
    47       <enum>QLineEdit::Password</enum>
    48      </property>
    49     </widget>
    50    </item>
    51    <item row="1" column="0" colspan="2">
     33   <item>
    5234    <spacer name="verticalSpacer">
    5335     <property name="orientation">
     
    6547    </spacer>
    6648   </item>
     49   <item>
     50    <widget class="QComboBox" name="sel_existing">
     51     <property name="minimumSize">
     52      <size>
     53       <width>0</width>
     54       <height>50</height>
     55      </size>
     56     </property>
     57     <property name="iconSize">
     58      <size>
     59       <width>42</width>
     60       <height>42</height>
     61      </size>
     62     </property>
     63    </widget>
     64   </item>
     65   <item>
     66    <spacer name="verticalSpacer_3">
     67     <property name="orientation">
     68      <enum>Qt::Vertical</enum>
     69     </property>
     70     <property name="sizeType">
     71      <enum>QSizePolicy::Fixed</enum>
     72     </property>
     73     <property name="sizeHint" stdset="0">
     74      <size>
     75       <width>20</width>
     76       <height>2</height>
     77      </size>
     78     </property>
     79    </spacer>
     80   </item>
     81   <item>
     82    <widget class="QPushButton" name="btn_newConnection">
     83     <property name="minimumSize">
     84      <size>
     85       <width>0</width>
     86       <height>40</height>
     87      </size>
     88     </property>
     89     <property name="text">
     90      <string>Connect a new account</string>
     91     </property>
     92    </widget>
     93   </item>
     94   <item>
     95    <spacer name="verticalSpacer_2">
     96     <property name="orientation">
     97      <enum>Qt::Vertical</enum>
     98     </property>
     99     <property name="sizeHint" stdset="0">
     100      <size>
     101       <width>20</width>
     102       <height>0</height>
     103      </size>
     104     </property>
     105    </spacer>
     106   </item>
    67107  </layout>
    68108 </widget>
  • frontend/locale/de.ts

    r392 r405  
    88        <source>Importing contacts</source>
    99        <translation>Importiere Kontakte</translation>
     10    </message>
     11</context>
     12<context>
     13    <name>OAuth2::RequestAccessTokenHandler</name>
     14    <message>
     15        <location filename="../business/contactimporter/oauth2.cpp" line="248"/>
     16        <source>smssender wont be able to connect to your account! :(</source>
     17        <translation>SMSSender wird nicht auf dein Konto zugreifen können! :(</translation>
     18    </message>
     19    <message>
     20        <location filename="../business/contactimporter/oauth2.cpp" line="254"/>
     21        <source>Thank you! :)
     22You can close this window now.</source>
     23        <translation>Danke!
     24Du kannst dieses Fenster nun schliessen.</translation>
    1025    </message>
    1126</context>
     
    102117    </message>
    103118    <message>
    104         <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="155"/>
     119        <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="139"/>
    105120        <source>Import contacts from Google contacts.</source>
    106121        <translation>Importiere Kontakte von Google-Kontakte.</translation>
  • frontend/locale/de_CH.ts

    r392 r405  
    88        <source>Importing contacts</source>
    99        <translation>Am Kontäggt importiere</translation>
     10    </message>
     11</context>
     12<context>
     13    <name>OAuth2::RequestAccessTokenHandler</name>
     14    <message>
     15        <location filename="../business/contactimporter/oauth2.cpp" line="248"/>
     16        <source>smssender wont be able to connect to your account! :(</source>
     17        <translation>Dr SMSSänder wird nid chönne uf di Konto zuegrife! :(</translation>
     18    </message>
     19    <message>
     20        <location filename="../business/contactimporter/oauth2.cpp" line="254"/>
     21        <source>Thank you! :)
     22You can close this window now.</source>
     23        <translation>Dangge!
     24Du chasch das Fänschter jez schliesse.</translation>
    1025    </message>
    1126</context>
     
    102117    </message>
    103118    <message>
    104         <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="155"/>
     119        <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="139"/>
    105120        <source>Import contacts from Google contacts.</source>
    106121        <translation>Importier Kontäggt vo Google-Kontäggt.</translation>
  • frontend/locale/fr.ts

    r392 r405  
    88        <source>Importing contacts</source>
    99        <translation>Importer les contacts</translation>
     10    </message>
     11</context>
     12<context>
     13    <name>OAuth2::RequestAccessTokenHandler</name>
     14    <message>
     15        <location filename="../business/contactimporter/oauth2.cpp" line="248"/>
     16        <source>smssender wont be able to connect to your account! :(</source>
     17        <translation type="unfinished"></translation>
     18    </message>
     19    <message>
     20        <location filename="../business/contactimporter/oauth2.cpp" line="254"/>
     21        <source>Thank you! :)
     22You can close this window now.</source>
     23        <translation type="unfinished"></translation>
    1024    </message>
    1125</context>
     
    102116    </message>
    103117    <message>
    104         <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="155"/>
     118        <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="139"/>
    105119        <source>Import contacts from Google contacts.</source>
    106120        <translation>Importation de Google contacts.</translation>
  • frontend/locale/it.ts

    r392 r405  
    77        <location filename="../business/contactimporter/contactimporter.cpp" line="264"/>
    88        <source>Importing contacts</source>
     9        <translation type="unfinished"></translation>
     10    </message>
     11</context>
     12<context>
     13    <name>OAuth2::RequestAccessTokenHandler</name>
     14    <message>
     15        <location filename="../business/contactimporter/oauth2.cpp" line="248"/>
     16        <source>smssender wont be able to connect to your account! :(</source>
     17        <translation type="unfinished"></translation>
     18    </message>
     19    <message>
     20        <location filename="../business/contactimporter/oauth2.cpp" line="254"/>
     21        <source>Thank you! :)
     22You can close this window now.</source>
    923        <translation type="unfinished"></translation>
    1024    </message>
     
    102116    </message>
    103117    <message>
    104         <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="155"/>
     118        <location filename="../business/contactimporter/googlecontactimporter_base.cpp" line="139"/>
    105119        <source>Import contacts from Google contacts.</source>
    106120        <translation type="unfinished"></translation>
Note: See TracChangeset for help on using the changeset viewer.