Merge lp:~dobey/ubuntuone-credentials/update-13-10 into lp:ubuntuone-credentials/stable-13-10

Proposed by dobey on 2013-08-27
Status: Merged
Approved by: dobey on 2013-08-28
Approved revision: no longer in the source branch.
Merged at revision: 29
Proposed branch: lp:~dobey/ubuntuone-credentials/update-13-10
Merge into: lp:ubuntuone-credentials/stable-13-10
Diff against target: 2484 lines (+1661/-146)
46 files modified
.bzrignore (+1/-0)
CMakeLists.txt (+19/-0)
data/CMakeLists.txt (+7/-0)
data/ubuntuone.provider (+14/-0)
data/ubuntuone.service (+8/-0)
data/ubuntuone.service-type (+7/-0)
libubuntuoneauth/CMakeLists.txt (+2/-4)
libubuntuoneauth/identityprovider.cpp (+11/-4)
libubuntuoneauth/identityprovider.h (+1/-0)
libubuntuoneauth/keyring.cpp (+147/-87)
libubuntuoneauth/keyring.h (+12/-0)
libubuntuoneauth/libubuntuoneauth.symbols (+9/-0)
libubuntuoneauth/logging.cpp (+17/-1)
libubuntuoneauth/network.cpp (+20/-12)
libubuntuoneauth/network.h (+0/-2)
libubuntuoneauth/requests.cpp (+24/-1)
libubuntuoneauth/requests.h (+16/-4)
libubuntuoneauth/ssoservice.cpp (+21/-10)
libubuntuoneauth/ssoservice.h (+5/-3)
libubuntuoneauth/token.h (+1/-1)
music-login/CMakeLists.txt (+2/-2)
music-login/loginform.cpp (+15/-4)
music-login/registerform.cpp (+2/-1)
music-login/ssowizard.cpp (+12/-3)
music-login/ssowizard.h (+2/-1)
music-login/tests/CMakeLists.txt (+2/-2)
music-login/tests/testloginform.cpp (+26/-2)
music-login/tests/testloginform.h (+4/-2)
online-accounts-provider/CMakeLists.txt (+6/-0)
online-accounts-provider/ExistingAccount.qml (+95/-0)
online-accounts-provider/LoginForm.qml (+100/-0)
online-accounts-provider/Main.qml (+50/-0)
online-accounts-provider/NewAccount.qml (+257/-0)
online-accounts-provider/RegisterForm.qml (+97/-0)
qml-credentials-service/CMakeLists.txt (+25/-0)
qml-credentials-service/README (+31/-0)
qml-credentials-service/examples/embeddingMain.qml (+129/-0)
qml-credentials-service/qmldir.template (+3/-0)
qml-credentials-service/ubuntuone_credentials_plugin.cpp (+11/-0)
qml-credentials-service/ubuntuone_credentials_plugin.h (+16/-0)
qml-credentials-service/ubuntuone_credentials_service.cpp (+157/-0)
qml-credentials-service/ubuntuone_credentials_service.h (+62/-0)
signon-plugin/CMakeLists.txt (+37/-0)
signon-plugin/ubuntuone-plugin.cpp (+80/-0)
signon-plugin/ubuntuone-plugin.h (+56/-0)
signon-plugin/ubuntuonedata.h (+42/-0)
To merge this branch: bzr merge lp:~dobey/ubuntuone-credentials/update-13-10
Reviewer Review Type Date Requested Status
Roberto Alsina (community) 2013-08-27 Approve on 2013-08-28
Review via email: mp+182490@code.launchpad.net

Commit Message

Rodney Dawes <email address hidden>

    Switch from using using the keyring, to storing tokens in online-accounts.
    Add necessary data files for online-accounts storage.
    Add the beginnings of a signon plugin for u1.
    Always print critical/fatal messages to stderr.
    When debug is enabled, also print debug messages to stderr.
    Add ctors for network requests to use the SSO_AUTH_BASE_URL value.
    Change usage of SSO_*_BASE_URL values to not require ending /.
    Restructure API URL constants to separate path from base URL.
    Only export the UbuntuOne namespace symbols in the shared library.

Michael McCracken <email address hidden>

    Add UOA provider plug-in to house login/register UI.
    Ensure initial value of _state variable is IDLE.
    Set signon plugin name to 'ubuntuoneplugin' as required by the signond plugin loader.
    Add cmake rule to generate qmltypes file for qtcreator integration.
    Validate input and show error messages for invalid email, short password, etc…
    Fix credential deletion and expose it via QML plugin.
    Improve UI, better support embedding into external QML, and add embedding example code.
    Add error signal for failure cases in Network class - covers connection failures.
    Add support for two-factor auth to the ssoservice and QML plugin (LP: #1197081)
    Add QML plugin that wraps login/register and signUrl functionality of libubuntuoneauth.

Diego Sarmentero <email address hidden>

    Fix UI flow requested by design for Returning Customers.

To post a comment you must log in.
Roberto Alsina (ralsina) wrote :

+1 exhausted

review: Approve
Ubuntu One Auto Pilot (otto-pilot) wrote :

The attempt to merge lp:~dobey/ubuntuone-credentials/update-13-10 into lp:ubuntuone-credentials/stable-13-10 failed. Below is the output from the failed tests.

-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26")
-- checking for modules 'libsignon-qt5;accounts-qt5'
-- package 'libsignon-qt5' not found
-- package 'accounts-qt5' not found
-- Configuring incomplete, errors occurred!

CMake Error at /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake:279 (message):
  A required package was not found
Call Stack (most recent call first):
  /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake:333 (_pkg_check_modules_internal)
  CMakeLists.txt:28 (pkg_check_modules)

CMake Error at libubuntuoneauth/CMakeLists.txt:4 (find_package):
  By not providing "FindQt5Core.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "Qt5Core", but
  CMake did not find one.

  Could not find a package configuration file provided by "Qt5Core" with any
  of the following names:

    Qt5CoreConfig.cmake
    qt5core-config.cmake

  Add the installation prefix of "Qt5Core" to CMAKE_PREFIX_PATH or set
  "Qt5Core_DIR" to a directory containing one of the above files. If
  "Qt5Core" provides a separate development package or SDK, be sure it has
  been installed.

29. By Mike McCracken on 2013-08-28

Rodney Dawes <email address hidden>

    Switch from using using the keyring, to storing tokens in online-accounts.
    Add necessary data files for online-accounts storage.
    Add the beginnings of a signon plugin for u1.
    Always print critical/fatal messages to stderr.
    When debug is enabled, also print debug messages to stderr.
    Add ctors for network requests to use the SSO_AUTH_BASE_URL value.
    Change usage of SSO_*_BASE_URL values to not require ending /.
    Restructure API URL constants to separate path from base URL.
    Only export the UbuntuOne namespace symbols in the shared library.

Michael McCracken <email address hidden>

    Add UOA provider plug-in to house login/register UI.
    Ensure initial value of _state variable is IDLE.
    Set signon plugin name to 'ubuntuoneplugin' as required by the signond plugin loader.
    Add cmake rule to generate qmltypes file for qtcreator integration.
    Validate input and show error messages for invalid email, short password, etc…
    Fix credential deletion and expose it via QML plugin.
    Improve UI, better support embedding into external QML, and add embedding example code.
    Add error signal for failure cases in Network class - covers connection failures.
    Add support for two-factor auth to the ssoservice and QML plugin (LP: #1197081)
    Add QML plugin that wraps login/register and signUrl functionality of libubuntuoneauth.

Diego Sarmentero <email address hidden>

    Fix UI flow requested by design for Returning Customers.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2013-05-01 15:39:22 +0000
3+++ .bzrignore 2013-08-27 20:30:52 +0000
4@@ -10,6 +10,7 @@
5 test-ubuntuoneauthui
6 ubuntuone-music-login
7 moc_*.cpp
8+qmldir
9 ui_*.h
10 *_automoc.cpp
11 *_resources.cpp
12
13=== modified file 'CMakeLists.txt'
14--- CMakeLists.txt 2013-07-08 14:34:25 +0000
15+++ CMakeLists.txt 2013-08-27 20:30:52 +0000
16@@ -15,6 +15,19 @@
17 SET (AUTHUI_LIB_API_VERSION 2.0)
18 SET (AUTHUI_LIB_NAME ubuntuoneauthui-${AUTHUI_LIB_API_VERSION})
19
20+# these names are also used in qml-credentials-service/qmldir, be sure to change them in both places
21+SET (QML_MODULE_NAME UbuntuOne)
22+SET (QML_PLUGIN_API_VERSION 1.0)
23+SET (QML_PLUGIN_NAME UbuntuOneCredentialsPlugin-${QML_PLUGIN_API_VERSION})
24+
25+# For the signon plug-in module
26+SET (SIGNON_PLUGIN_NAME ubuntuoneplugin)
27+
28+# Need to get libsignon/accounts here, as they get exposed in headers
29+find_package (PkgConfig REQUIRED)
30+pkg_check_modules(LIBSIGNON REQUIRED libsignon-qt5 accounts-qt5)
31+add_definitions(${LIBSIGNON_CFLAGS} ${LIBSIGNON_CFLAGS_OTHER})
32+
33 # Some default CFLAGS
34 SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -Wall -Werror -fPIC")
35 SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -O2 -g -Wall -Werror -fPIC")
36@@ -23,6 +36,8 @@
37 SET (LIB_SUFFIX "" CACHE STRING "Define suffix of library directory name.")
38 SET (LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
39
40+set (QML_MODULE_INSTALL_DIR ${LIB_INSTALL_DIR}/qt5/qml )
41+
42 include_directories(${CMAKE_SOURCE_DIR}/libubuntuoneauth
43 ${CMAKE_SOURCE_DIR}/libubuntuoneauthui)
44
45@@ -35,9 +50,13 @@
46 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
47
48
49+add_subdirectory(data)
50 add_subdirectory(libubuntuoneauth)
51 add_subdirectory(libubuntuoneauthui)
52 add_subdirectory(music-login)
53+add_subdirectory(signon-plugin)
54+add_subdirectory(qml-credentials-service)
55+add_subdirectory(online-accounts-provider)
56
57 # We need to add these here which simply depend on other test rules, as
58 # CMake doesn't allow defining a "check" rule in multiple places.
59
60=== added directory 'data'
61=== added file 'data/CMakeLists.txt'
62--- data/CMakeLists.txt 1970-01-01 00:00:00 +0000
63+++ data/CMakeLists.txt 2013-08-27 20:30:52 +0000
64@@ -0,0 +1,7 @@
65+file (GLOB PROVIDER_FILES *.provider)
66+file (GLOB SERVICE_FILES *.service)
67+file (GLOB SERVICE_TYPE_FILES *.service-type)
68+
69+install (FILES ${PROVIDER_FILES} DESTINATION share/accounts/providers/)
70+install (FILES ${SERVICE_FILES} DESTINATION share/accounts/services/)
71+install (FILES ${SERVICE_TYPE_FILES} DESTINATION share/accounts/service_types/)
72
73=== added file 'data/ubuntuone.provider'
74--- data/ubuntuone.provider 1970-01-01 00:00:00 +0000
75+++ data/ubuntuone.provider 2013-08-27 20:30:52 +0000
76@@ -0,0 +1,14 @@
77+<?xml version="1.0" encoding="UTF-8"?>
78+<provider id="ubuntuone">
79+ <name>Ubuntu One</name>
80+ <icon>ubuntuone</icon>
81+ <plugin>ubuntuone</plugin>
82+ <translations>ubuntuone-credentials</translations>
83+
84+ <template>
85+ <group name="auth">
86+ <setting name="method">password</setting>
87+ <setting name="mechanism">password</setting>
88+ </group>
89+ </template>
90+</provider>
91
92=== added file 'data/ubuntuone.service'
93--- data/ubuntuone.service 1970-01-01 00:00:00 +0000
94+++ data/ubuntuone.service 2013-08-27 20:30:52 +0000
95@@ -0,0 +1,8 @@
96+<?xml version="1.0" encoding="UTF-8"?>
97+<service id="ubuntuone">
98+ <type>ubuntuone</type>
99+ <name>Ubuntu One</name>
100+ <icon>ubuntuone</icon>
101+ <provider>ubuntuone</provider>
102+
103+</service>
104
105=== added file 'data/ubuntuone.service-type'
106--- data/ubuntuone.service-type 1970-01-01 00:00:00 +0000
107+++ data/ubuntuone.service-type 2013-08-27 20:30:52 +0000
108@@ -0,0 +1,7 @@
109+<?xml version="1.0" encoding="UTF-8"?>
110+<service-type id="ubuntuone">
111+ <name>Ubuntu One</name>
112+ <description>Integrate with Ubuntu One</description>
113+ <icon>ubuntuone</icon>
114+ <translations>ubuntuone-credentials</translations>
115+</service-type>
116
117=== modified file 'libubuntuoneauth/CMakeLists.txt'
118--- libubuntuoneauth/CMakeLists.txt 2013-06-14 22:30:19 +0000
119+++ libubuntuoneauth/CMakeLists.txt 2013-08-27 20:30:52 +0000
120@@ -18,10 +18,7 @@
121 # HEADERS only includes the public headers for installation.
122 FILE (GLOB HEADERS *.h)
123
124-find_package (PkgConfig REQUIRED)
125-pkg_check_modules(LIBSECRET REQUIRED libsecret-1)
126 pkg_check_modules(OAUTH REQUIRED oauth)
127-add_definitions(${LIBSECRET_CFLAGS} ${LIBSECRET_CFLAGS_OTHER})
128 add_definitions(${OAUTH_CFLAGS} ${OAUTH_CFLAGS_OTHER})
129
130 # Need the project version here
131@@ -30,8 +27,9 @@
132 add_library (${AUTH_LIB_NAME} ${LIB_TYPE} ${SOURCES})
133 qt5_use_modules (${AUTH_LIB_NAME} Core DBus Xml Network)
134 target_link_libraries (${AUTH_LIB_NAME}
135- ${LIBSECRET_LDFLAGS}
136+ ${LIBSIGNON_LDFLAGS}
137 ${OAUTH_LDFLAGS}
138+ -Wl,--version-script -Wl,${CMAKE_CURRENT_SOURCE_DIR}/libubuntuoneauth.symbols
139 )
140
141 SET_TARGET_PROPERTIES(${AUTH_LIB_NAME} PROPERTIES
142
143=== modified file 'libubuntuoneauth/identityprovider.cpp'
144--- libubuntuoneauth/identityprovider.cpp 2013-06-20 19:17:09 +0000
145+++ libubuntuoneauth/identityprovider.cpp 2013-08-27 20:30:52 +0000
146@@ -19,6 +19,7 @@
147
148 #include "identityprovider.h"
149 #include "responses.h"
150+#include "errormessages.h"
151
152
153 namespace UbuntuOne {
154@@ -81,10 +82,16 @@
155
156 void IdentityProvider::OnErrorOccurred(const ErrorResponse& error)
157 {
158- qWarning("Error occurred creating account: %d (%s)",
159- error.code(), error.message().toUtf8().data());
160-
161- emit ErrorOccurred(error);
162+ if (error.code() == CODE_TWOFACTOR_REQUIRED){
163+ emit TwoFactorAuthRequired();
164+
165+ }else{
166+
167+ qWarning("Error occurred creating token: %d (%s)",
168+ error.code(), error.message().toUtf8().data());
169+
170+ emit ErrorOccurred(error);
171+ }
172
173 }
174
175
176=== modified file 'libubuntuoneauth/identityprovider.h'
177--- libubuntuoneauth/identityprovider.h 2013-06-14 22:39:59 +0000
178+++ libubuntuoneauth/identityprovider.h 2013-08-27 20:30:52 +0000
179@@ -42,6 +42,7 @@
180 void PasswordTokenGranted(const PasswordTokenResponse& token);
181 void AccountGranted(const AccountResponse& account);
182 void ErrorOccurred(const ErrorResponse& error);
183+ void TwoFactorAuthRequired();
184
185 public slots:
186 void OnOAuthTokenGranted(const OAuthTokenResponse& token);
187
188=== modified file 'libubuntuoneauth/keyring.cpp'
189--- libubuntuoneauth/keyring.cpp 2013-06-20 19:17:09 +0000
190+++ libubuntuoneauth/keyring.cpp 2013-08-27 20:30:52 +0000
191@@ -15,122 +15,182 @@
192 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
193 * Boston, MA 02110-1301, USA.
194 */
195-#include <libsecret/secret.h>
196+#include <Accounts/Account>
197+#include <Accounts/AccountService>
198+#include <Accounts/Service>
199+#include <Accounts/ServiceType>
200+#include <SignOn/Identity>
201
202 #include <QDebug>
203
204 #include "keyring.h"
205
206-#define TOKEN_KEY_TYPE "Ubuntu SSO credentials"
207-#define TOKEN_ATTR_TYPE_KEY "key-type"
208-#define TOKEN_ATTR_NAME_KEY "token-name"
209+using namespace Accounts;
210+using namespace SignOn;
211+
212
213 namespace UbuntuOne {
214
215 Keyring::Keyring(QObject *parent)
216- : QObject(parent)
217- {
218- }
219-
220- static const SecretSchema *_getTokenSchema()
221- {
222- static const SecretSchema schema = {
223- "com.ubuntu.one.Token", SECRET_SCHEMA_DONT_MATCH_NAME,
224- {
225- { TOKEN_ATTR_TYPE_KEY, SECRET_SCHEMA_ATTRIBUTE_STRING },
226- { TOKEN_ATTR_NAME_KEY, SECRET_SCHEMA_ATTRIBUTE_STRING },
227- }
228- };
229-
230- return &schema;
231- }
232-
233- static void _onPasswordLookup(GObject *source, GAsyncResult *result,
234- Keyring *keyring)
235- {
236- GError *error = NULL;
237-
238- gchar *password = secret_password_lookup_finish(result, &error);
239-
240- if (error != NULL) {
241- QString message(error->message);
242- qCritical() << "Error in secret_password_lookup: " << message;
243- emit keyring->keyringError(message);
244- g_error_free(error);
245- } else if (password == NULL) {
246- emit keyring->tokenNotFound();
247+ : QObject(parent),
248+ _manager()
249+ {
250+ }
251+
252+ void Keyring::handleError(const SignOn::Error &error)
253+ {
254+ qCritical() << "Error:" << error.message();
255+ emit keyringError(error.message());
256+ }
257+
258+ void Keyring::handleSessionData(const SignOn::SessionData &data)
259+ {
260+ QString secret = data.Secret();
261+
262+ if (secret.length() == 0) {
263+ QString msg("Could not read credentials secret value.");
264+ qCritical() << msg;
265+ emit keyringError(msg);
266+ return;
267+ }
268+
269+ Token *token = Token::fromQuery(secret);
270+ if (token->isValid()) {
271+ emit tokenFound(*token);
272 } else {
273- QString query(password);
274- Token *token = Token::fromQuery(query);
275- if (token->isValid()) {
276- emit keyring->tokenFound(*token);
277- } else {
278- QString message("Faild to convert result to Token object.");
279- qCritical() << message;
280- emit keyring->keyringError(message);
281- }
282- delete token;
283- secret_password_free(password);
284+ QString message("Failed to convert result to Token object.");
285+ qCritical() << message;
286+ emit keyringError(message);
287 }
288+ delete token;
289 }
290
291 void Keyring::findToken()
292 {
293- secret_password_lookup(_getTokenSchema(), NULL,
294- (GAsyncReadyCallback)_onPasswordLookup, this,
295- TOKEN_ATTR_TYPE_KEY, TOKEN_KEY_TYPE,
296- TOKEN_ATTR_NAME_KEY, Token::buildTokenName().toUtf8().data(),
297- NULL);
298+ QString _acctName("ubuntuone");
299+ AccountIdList _ids = _manager.accountList(_acctName);
300+ Identity *identity;
301+ Account *account;
302+
303+ if (_ids.length() > 0) {
304+ if (_ids.length() > 1) {
305+ qDebug() << "findToken(): Found '" << _ids.length() << "' accounts. Using first.";
306+ }
307+ account = _manager.account(_ids[0]);
308+ qDebug() << "findToken(): Using Ubuntu One account '" << _ids[0] << "'.";
309+ identity = Identity::existingIdentity(account->credentialsId());
310+ AuthSession *session = identity->createSession(QStringLiteral("password"));
311+ if (session != NULL) {
312+ connect(session, SIGNAL(response(const SignOn::SessionData&)),
313+ this, SLOT(handleSessionData(const SignOn::SessionData&)));
314+ connect(session, SIGNAL(error(const SignOn::Error&)),
315+ this, SLOT(handleError(const SignOn::Error&)));
316+ session->process(SessionData(), QStringLiteral("password"));
317+ return;
318+ }
319+ qCritical() << "Unable to create AuthSession.";
320+ }
321+ emit tokenNotFound();
322 }
323
324- static void _onPasswordStored(GObject *source, GAsyncResult *result,
325- Keyring *keyring)
326+ void Keyring::handleCredentialsStored(const quint32 id)
327 {
328- GError *error = NULL;
329-
330- secret_password_store_finish (result, &error);
331- if (error != NULL) {
332- QString message(error->message);
333- qCritical() << "Error storing token: " << message;
334- emit keyring->keyringError(message);
335- g_error_free(error);
336+ QString _acctName("ubuntuone");
337+ AccountIdList _ids = _manager.accountList(_acctName);
338+ Account *account;
339+
340+ if (_ids.length() > 0) {
341+ if (_ids.length() > 1) {
342+ qDebug() << "handleCredentialsStored(): Found '" << _ids.length() << "' accounts. Using first.";
343+ }
344+ account = _manager.account(_ids[0]);
345+ qDebug() << "handleCredentialsStored(): Using Ubuntu One account '" << _ids[0] << "'.";
346+ account->selectService();
347+ account->setCredentialsId(id);
348+
349+ ServiceList services = account->services(_acctName);
350+ if (services.length() > 0) {
351+ account->selectService(services[0]);
352+ } else {
353+ QString errMsg("Unable to enable 'ubuntuone' service.");
354+ emit keyringError(errMsg);
355+ }
356+ account->setEnabled(true);
357+ account->sync();
358+ emit tokenStored();
359 return;
360 }
361- emit keyring->tokenStored();
362+ emit keyringError(QStringLiteral("Could not sync credentials ID."));
363 }
364
365 void Keyring::storeToken(Token token)
366 {
367- secret_password_store(_getTokenSchema(), SECRET_COLLECTION_DEFAULT,
368- TOKEN_ID, token.toQuery().toUtf8().data(), NULL,
369- (GAsyncReadyCallback)_onPasswordStored, this,
370- TOKEN_ATTR_TYPE_KEY, TOKEN_KEY_TYPE,
371- TOKEN_ATTR_NAME_KEY, Token::buildTokenName().toUtf8().data(),
372- NULL);
373- }
374-
375- static void _onPasswordCleared(GObject *source, GAsyncResult *result,
376- Keyring *keyring)
377- {
378- GError *error = NULL;
379-
380- secret_password_store_finish (result, &error);
381- if (error != NULL) {
382- QString message(error->message);
383- qDebug() << message;
384- emit keyring->keyringError(message);
385- g_error_free(error);
386+ QString _acctName("ubuntuone");
387+ AccountIdList _ids = _manager.accountList(_acctName);
388+ Identity *identity;
389+ Account *account;
390+
391+ if (_ids.length() > 0) {
392+ if (_ids.length() > 1) {
393+ qDebug() << "storeToken(): Found '" << _ids.length() << "' accounts. Using first.";
394+ }
395+ account = _manager.account(_ids[0]);
396+ qDebug() << "storeToken(): Using Ubuntu One account '" << _ids[0] << "'.";
397+ identity = Identity::existingIdentity(account->credentialsId());
398+ } else {
399+ account = _manager.createAccount(_acctName);
400+
401+ ServiceList services = account->services(_acctName);
402+ if (services.length() > 0) {
403+ account->selectService(services[0]);
404+ } else {
405+ QString errMsg("Unable to enable 'ubuntuone' service.");
406+ emit keyringError(errMsg);
407+ }
408+
409+ identity = Identity::newIdentity();
410+ account->setEnabled(true);
411+ account->sync();
412 }
413- emit keyring->tokenDeleted();
414+
415+ connect(identity, SIGNAL(error(const SignOn::Error&)),
416+ this, SLOT(handleError(const SignOn::Error&)));
417+ connect(identity, SIGNAL(credentialsStored(const quint32)),
418+ this, SLOT(handleCredentialsStored(const quint32)));
419+
420+ IdentityInfo info = IdentityInfo();
421+
422+ info.setSecret(token.toQuery(), true);
423+ identity->storeCredentials(info);
424+ }
425+
426+ void Keyring::handleAccountRemoved()
427+ {
428+ emit tokenDeleted();
429 }
430
431 void Keyring::deleteToken()
432 {
433- secret_password_clear(_getTokenSchema(), NULL,
434- (GAsyncReadyCallback)_onPasswordCleared, this,
435- TOKEN_ATTR_TYPE_KEY, TOKEN_KEY_TYPE,
436- TOKEN_ATTR_NAME_KEY, Token::buildTokenName().toUtf8().data(),
437- NULL);
438+ QString _acctName("ubuntuone");
439+ AccountIdList _ids = _manager.accountList(_acctName);
440+ if (_ids.length() > 0) {
441+ if (_ids.length() > 1) {
442+ qDebug() << "deleteToken(): Found '" << _ids.length() << "' accounts. Using first.";
443+ }
444+ Account *account = _manager.account(_ids[0]);
445+ qDebug() << "deleteToken(): Using Ubuntu One account '" << _ids[0] << "'.";
446+ Identity *identity = Identity::existingIdentity(account->credentialsId());
447+ connect(account, SIGNAL(removed()),
448+ this, SLOT(handleAccountRemoved()));
449+ connect(identity, SIGNAL(error(const SignOn::Error&)),
450+ this, SLOT(handleError(const SignOn::Error&)));
451+
452+ identity->remove();
453+ account->remove();
454+ account->sync();
455+ return;
456+ }
457+ emit tokenNotFound();
458 }
459
460 } // namespace UbuntuOne
461
462=== modified file 'libubuntuoneauth/keyring.h'
463--- libubuntuoneauth/keyring.h 2013-05-24 19:10:54 +0000
464+++ libubuntuoneauth/keyring.h 2013-08-27 20:30:52 +0000
465@@ -18,6 +18,9 @@
466 #ifndef _U1_KEYRING_H_
467 #define _U1_KEYRING_H_
468
469+#include <Accounts/Manager>
470+#include <SignOn/Identity>
471+
472 #include <QObject>
473
474 #include "token.h"
475@@ -42,6 +45,15 @@
476 void tokenDeleted();
477
478 void keyringError(QString message);
479+
480+ private Q_SLOTS:
481+ void handleError(const SignOn::Error &error);
482+ void handleSessionData(const SignOn::SessionData &data);
483+ void handleCredentialsStored(const quint32 id);
484+ void handleAccountRemoved();
485+
486+ private:
487+ Accounts::Manager _manager;
488 };
489
490 } /* namespace UbuntuOne */
491
492=== added file 'libubuntuoneauth/libubuntuoneauth.symbols'
493--- libubuntuoneauth/libubuntuoneauth.symbols 1970-01-01 00:00:00 +0000
494+++ libubuntuoneauth/libubuntuoneauth.symbols 2013-08-27 20:30:52 +0000
495@@ -0,0 +1,9 @@
496+{
497+ global:
498+ extern "C++" {
499+ *UbuntuOne::*;
500+ };
501+ qt_*;
502+ local:
503+ *;
504+};
505
506=== modified file 'libubuntuoneauth/logging.cpp'
507--- libubuntuoneauth/logging.cpp 2013-05-01 15:39:22 +0000
508+++ libubuntuoneauth/logging.cpp 2013-08-27 20:30:52 +0000
509@@ -114,7 +114,23 @@
510 if (type < _logLevel)
511 return;
512
513- _logStream << QDateTime::currentDateTime().toString(_datetimeFormat).toUtf8().data() << " - " << getMessageTypeString(type).toUtf8().data() << " - " << message.toUtf8().data() << "\n";
514+ QString logMessage;
515+ QTextStream _logMessage(&logMessage);
516+ _logMessage << QDateTime::currentDateTime().toString(_datetimeFormat).toUtf8().data() << " - " << getMessageTypeString(type).toUtf8().data() << " - " << message.toUtf8().data() << "\n";
517+
518+ QTextStream _stdErr(stderr, QIODevice::WriteOnly);
519+ switch (type) {
520+ case QtDebugMsg:
521+ case QtCriticalMsg:
522+ case QtFatalMsg:
523+ _stdErr << logMessage;
524+ break;
525+ default:
526+ break;
527+ }
528+ _stdErr.device()->close();
529+
530+ _logStream << logMessage;
531 _logStream.flush();
532
533 if (type == QtFatalMsg)
534
535=== modified file 'libubuntuoneauth/network.cpp'
536--- libubuntuoneauth/network.cpp 2013-06-14 22:39:59 +0000
537+++ libubuntuoneauth/network.cpp 2013-08-27 20:30:52 +0000
538@@ -23,10 +23,12 @@
539
540 #include <QStringList>
541
542+#include "errormessages.h"
543 #include "network.h"
544 #include "responses.h"
545 #include "requests.h"
546
547+#define NO_HTTP_REASON QString("No HTTP error reason")
548
549 namespace UbuntuOne {
550
551@@ -51,30 +53,35 @@
552 /* TODO: see if we really need to do this check, we could just operate
553 on a bad value as being an error rather than the extra check? */
554 if (!statusAttr.isValid()) {
555- qDebug() << "Invalid status received!";
556+ QString errmsg = QString("Invalid status attribute in Network::OnReply");
557+ // Use login failed code, which results in generic error message:
558+ emit ErrorOccurred(ErrorResponse(0, NO_HTTP_REASON, LOGIN_FAILED, errmsg));
559 return;
560 }
561
562 int httpStatus = statusAttr.toInt();
563
564- qDebug() << "Network::OnReply from " << reply->url();
565- qDebug() << "Network::OnReply status: " << httpStatus;
566+ qDebug() << "Network::OnReply from " << reply->url()
567+ << " status: " << httpStatus;
568
569 QByteArray payload = reply->readAll();
570 if (payload.isEmpty()) {
571- qDebug() << "empty payload";
572- return; /* TODO: Do something to signal we're having a bad time. */
573+ QString errmsg = QString("Network::OnReply: empty payload, giving up.");
574+ emit ErrorOccurred(ErrorResponse(0, NO_HTTP_REASON, LOGIN_FAILED, errmsg));
575+ return;
576 }
577
578 QJsonDocument document = QJsonDocument::fromJson(payload);
579- /* TODO: add logging or raise some type of error signal? */
580+
581 if (document.isEmpty()) {
582- qDebug() << "oops, received empty document";
583+ QString errmsg = QString("Network::OnReply received empty document");
584+ emit ErrorOccurred(ErrorResponse(0, NO_HTTP_REASON, LOGIN_FAILED, errmsg));
585 return;
586 }
587
588 if (!document.isObject()) {
589- qDebug() << "uh oh, this isn't good.";
590+ QString errmsg = QString("Network::OnReply received invalid QJsonDocument");
591+ emit ErrorOccurred(ErrorResponse(0, NO_HTTP_REASON, LOGIN_FAILED, errmsg));
592 return;
593 }
594
595@@ -82,17 +89,18 @@
596
597 /* TODO: map out urls to reply parsers */
598 if (httpStatus == 200 || httpStatus == 201) {
599- if (reply->url() == OAUTH_API)
600+ if (reply->url().path() == OAUTH_PATH)
601 ProcessOAuthTokenReply(object);
602- else if (reply->url() == PASSWORD_API)
603+ else if (reply->url().path() == PASSWORD_PATH)
604 ProcessPasswordTokenReply(object);
605- else if (reply->url() == ACCOUNTS_API)
606+ else if (reply->url().path() == ACCOUNTS_PATH)
607 ProcessAccountsReply(object);
608 } else /* Statuses outside 200, 201 are fails */ {
609 QVariant phraseAttr = reply->attribute(
610 QNetworkRequest::HttpReasonPhraseAttribute);
611 if (!phraseAttr.isValid()) {
612- qDebug() << "got a bad HTTP reason";
613+ QString errmsg = QString("HTTP reason phrase is invalid");
614+ emit ErrorOccurred(ErrorResponse(httpStatus, NO_HTTP_REASON, LOGIN_FAILED, errmsg));
615 return;
616 }
617 QString httpReason = phraseAttr.toString();
618
619=== modified file 'libubuntuoneauth/network.h'
620--- libubuntuoneauth/network.h 2013-06-14 22:39:59 +0000
621+++ libubuntuoneauth/network.h 2013-08-27 20:30:52 +0000
622@@ -28,8 +28,6 @@
623
624 namespace UbuntuOne {
625
626-//static QString API_BASE = "https://login.ubuntu.com/api/v2/";
627-
628 class Network : public QObject
629 {
630 Q_OBJECT
631
632=== modified file 'libubuntuoneauth/requests.cpp'
633--- libubuntuoneauth/requests.cpp 2013-06-14 22:39:59 +0000
634+++ libubuntuoneauth/requests.cpp 2013-08-27 20:30:52 +0000
635@@ -40,13 +40,20 @@
636 {
637 }
638
639+OAuthTokenRequest::OAuthTokenRequest(QString base_url,
640+ QString email, QString password,
641+ QString name, QString otp)
642+ : RequestInterface(base_url + OAUTH_PATH),
643+ _email(email), _password(password), _name(name), _otp(otp)
644+{
645+}
646+
647 QByteArray OAuthTokenRequest::serialize() const
648 {
649 QJsonObject serializer;
650 serializer.insert("email", this->email());
651 serializer.insert("password", this->password());
652 serializer.insert("token_name", this->name());
653- /* TODO: check for null */
654 if (!this->otp().isEmpty())
655 serializer.insert("otp", this->otp());
656
657@@ -73,6 +80,17 @@
658 {
659 }
660
661+AccountRequest::AccountRequest(QString base_url,
662+ QString email, QString password, QString name,
663+ QString captchaId, QString captchaSolution,
664+ bool createCaptcha)
665+ : RequestInterface(base_url + ACCOUNTS_PATH),
666+ _email(email), _password(password), _name(name),
667+ _captchaId(captchaId), _captchaSolution(captchaSolution),
668+ _createCaptcha(createCaptcha)
669+{
670+}
671+
672 QByteArray AccountRequest::serialize() const
673 {
674 QJsonObject data;
675@@ -97,6 +115,11 @@
676 {
677 }
678
679+PasswordTokenRequest::PasswordTokenRequest(QString base_url, QString email)
680+ : RequestInterface(base_url + PASSWORD_PATH), _email(email)
681+{
682+}
683+
684 QByteArray PasswordTokenRequest::serialize() const
685 {
686 QJsonObject data;
687
688=== modified file 'libubuntuoneauth/requests.h'
689--- libubuntuoneauth/requests.h 2013-06-14 22:39:59 +0000
690+++ libubuntuoneauth/requests.h 2013-08-27 20:30:52 +0000
691@@ -24,10 +24,14 @@
692
693 namespace UbuntuOne {
694
695-static QString API_BASE = "https://login.ubuntu.com/api/v2/";
696-static QString OAUTH_API = API_BASE + "tokens/oauth";
697-static QString PASSWORD_API = API_BASE + "tokens/password";
698-static QString ACCOUNTS_API = API_BASE + "accounts";
699+static QString API_VERSION = "/api/v2";
700+static QString API_BASE = "https://login.ubuntu.com/";
701+static QString OAUTH_PATH = API_VERSION + "/tokens/oauth";
702+static QString OAUTH_API = API_BASE + OAUTH_PATH;
703+static QString PASSWORD_PATH = API_VERSION + "/tokens/password";
704+static QString PASSWORD_API = API_BASE + PASSWORD_PATH;
705+static QString ACCOUNTS_PATH = API_VERSION + "/accounts";
706+static QString ACCOUNTS_API = API_BASE + ACCOUNTS_PATH;
707
708 class RequestInterface
709 {
710@@ -47,6 +51,9 @@
711 OAuthTokenRequest();
712 OAuthTokenRequest(QString email, QString password,
713 QString token, QString otp);
714+ OAuthTokenRequest(QString base_url,
715+ QString email, QString password,
716+ QString token, QString otp);
717
718 QByteArray serialize() const;
719
720@@ -71,6 +78,10 @@
721 AccountRequest(QString email, QString password, QString name,
722 QString captchaId, QString captchaSolution,
723 bool createCaptcha = true);
724+ AccountRequest(QString base_url,
725+ QString email, QString password, QString name,
726+ QString captchaId, QString captchaSolution,
727+ bool createCaptcha);
728
729 QByteArray serialize() const;
730
731@@ -98,6 +109,7 @@
732 public:
733 PasswordTokenRequest();
734 PasswordTokenRequest(QString email);
735+ PasswordTokenRequest(QString base_url, QString email);
736
737 QByteArray serialize() const;
738
739
740=== modified file 'libubuntuoneauth/ssoservice.cpp'
741--- libubuntuoneauth/ssoservice.cpp 2013-06-28 23:44:14 +0000
742+++ libubuntuoneauth/ssoservice.cpp 2013-08-27 20:30:52 +0000
743@@ -67,8 +67,11 @@
744 SIGNAL(AccountGranted(const AccountResponse&)),
745 this, SLOT(accountRegistered(const AccountResponse&)));
746 connect(&(_provider),
747+ SIGNAL(TwoFactorAuthRequired()),
748+ this, SLOT(handleTwoFactorAuthRequired()));
749+ connect(&(_provider),
750 SIGNAL(ErrorOccurred(const ErrorResponse&)),
751- this, SLOT(errorOcurred(const ErrorResponse&)));
752+ this, SLOT(errorOccurred(const ErrorResponse&)));
753 }
754
755 void SSOService::getCredentials()
756@@ -88,14 +91,15 @@
757
758 void SSOService::handleTokenStored()
759 {
760- emit credentialsStored(_pendingPing);
761+ emit credentialsStored();
762 _pendingPing = Token();
763 }
764
765 void SSOService::registerUser(QString email, QString password,
766 QString display_name)
767 {
768- AccountRequest request(email, password, display_name, NULL, NULL);
769+ AccountRequest request(getAuthBaseUrl(),
770+ email, password, display_name, NULL, NULL);
771
772 _tempPassword = password;
773 _tempEmail = email;
774@@ -108,14 +112,21 @@
775 _tempPassword = "";
776 }
777
778- void SSOService::login(QString email, QString password)
779+ void SSOService::login(QString email, QString password, QString twoFactorCode)
780 {
781- OAuthTokenRequest request(email, password, Token::buildTokenName(), NULL);
782+ OAuthTokenRequest request(getAuthBaseUrl(),
783+ email, password,
784+ Token::buildTokenName(), twoFactorCode);
785 _tempEmail = email;
786
787 _provider.GetOAuthToken(request);
788 }
789
790+ void SSOService::handleTwoFactorAuthRequired()
791+ {
792+ emit twoFactorAuthRequired();
793+ }
794+
795 static QString _getPlatformDataParams()
796 {
797 struct utsname _platData;
798@@ -128,7 +139,7 @@
799 params->addQueryItem("client_version", PROJECT_VERSION);
800
801 QString result = params->toString();
802- qDebug() << "Ping parameters:" << result;
803+
804 return result;
805 }
806
807@@ -136,7 +147,7 @@
808 {
809 QString baseUrl = qgetenv("SSO_AUTH_BASE_URL");
810 if (baseUrl.isEmpty())
811- baseUrl = QStringLiteral("https://login.ubuntu.com/");
812+ baseUrl = QStringLiteral("https://login.ubuntu.com");
813 return baseUrl;
814 }
815
816@@ -144,7 +155,7 @@
817 {
818 QString baseUrl = qgetenv("SSO_UONE_BASE_URL");
819 if (baseUrl.isEmpty())
820- baseUrl = QStringLiteral("https://one.ubuntu.com/");
821+ baseUrl = QStringLiteral("https://one.ubuntu.com");
822 return baseUrl;
823 }
824
825@@ -152,7 +163,7 @@
826 {
827 Token realToken = Token(token.token_key(), token.token_secret(),
828 token.consumer_key(), token.consumer_secret());
829- QString urlToSign = getUOneBaseUrl() + "oauth/sso-finished-so-get-tokens/" + _tempEmail + "?" + _getPlatformDataParams();
830+ QString urlToSign = getUOneBaseUrl() + "/oauth/sso-finished-so-get-tokens/" + _tempEmail + "?" + _getPlatformDataParams();
831 QString authHeader = realToken.signUrl(urlToSign,
832 QStringLiteral("GET"));
833 QNetworkRequest *_request = new QNetworkRequest();
834@@ -189,7 +200,7 @@
835 _keyring->deleteToken();
836 }
837
838- void SSOService::errorOcurred(const ErrorResponse& error)
839+ void SSOService::errorOccurred(const ErrorResponse& error)
840 {
841 _tempPassword = "";
842 emit requestFailed(error);
843
844=== modified file 'libubuntuoneauth/ssoservice.h'
845--- libubuntuoneauth/ssoservice.h 2013-06-20 19:21:02 +0000
846+++ libubuntuoneauth/ssoservice.h 2013-08-27 20:30:52 +0000
847@@ -40,7 +40,7 @@
848
849 void invalidateCredentials();
850 void getCredentials();
851- void login(QString email, QString password);
852+ void login(QString email, QString password, QString twoFactorCode = QString());
853 void registerUser(QString email, QString password,
854 QString display_name);
855
856@@ -49,10 +49,11 @@
857
858 signals:
859 void credentialsDeleted();
860- void credentialsStored(const Token& token);
861+ void credentialsStored();
862 void credentialsFound(const Token& token);
863 void credentialsNotFound();
864 void requestFailed(const ErrorResponse& error);
865+ void twoFactorAuthRequired();
866
867 private slots:
868 void accountPinged(QNetworkReply*);
869@@ -62,7 +63,8 @@
870 void handleCredentialsNotFound();
871 void tokenReceived(const OAuthTokenResponse& token);
872 void accountRegistered(const AccountResponse& account);
873- void errorOcurred(const ErrorResponse&);
874+ void errorOccurred(const ErrorResponse&);
875+ void handleTwoFactorAuthRequired();
876
877 private:
878 Keyring *_keyring;
879
880=== modified file 'libubuntuoneauth/token.h'
881--- libubuntuoneauth/token.h 2013-06-25 15:52:14 +0000
882+++ libubuntuoneauth/token.h 2013-08-27 20:30:52 +0000
883@@ -49,4 +49,4 @@
884
885 } /* namespace UbuntuOne */
886
887-#endif /* _U1_KEYRING_H_ */
888+#endif /* _U1_TOKEN_H_ */
889
890=== modified file 'music-login/CMakeLists.txt'
891--- music-login/CMakeLists.txt 2013-05-09 12:19:06 +0000
892+++ music-login/CMakeLists.txt 2013-08-27 20:30:52 +0000
893@@ -46,8 +46,8 @@
894 qt5_use_modules (${MUSIC_LOGIN_LIB} Core DBus Gui Widgets Network)
895 qt5_use_modules (${MUSIC_LOGIN_EXE} DBus Widgets Network)
896 target_link_libraries (${MUSIC_LOGIN_EXE}
897- -Wl,-rpath,${CMAKE_BINARY_DIR}/lib
898- -L${CMAKE_BINARY_DIR}/lib
899+ -Wl,-rpath,${CMAKE_BINARY_DIR}/libubuntuoneauth
900+ -L${CMAKE_BINARY_DIR}/libubuntuoneauth
901 ${AUTH_LIB_NAME}
902 ${MUSIC_LIB_NAME}
903 )
904
905=== modified file 'music-login/loginform.cpp'
906--- music-login/loginform.cpp 2013-06-14 22:30:19 +0000
907+++ music-login/loginform.cpp 2013-08-27 20:30:52 +0000
908@@ -71,13 +71,15 @@
909
910 void LoginForm::validateForm()
911 {
912- bool value = this->checkEmail() && this->checkPassword() && this->_sessionActive;
913+ bool passwordCheck = this->ui->radioNewCustomer->isChecked() || this->checkPassword();
914+ bool value = this->checkEmail() && passwordCheck && this->_sessionActive;
915 this->ui->btnProceed->setEnabled(value);
916 }
917
918 bool LoginForm::checkEmail()
919 {
920- bool value = !this->ui->lineEmail->text().isEmpty() && this->ui->lineEmail->text().contains("@");
921+ QRegExp mailRE(".+@.+");
922+ bool value = mailRE.exactMatch(this->ui->lineEmail->text());
923 this->ui->lineEmail->setProperty("error", !value);
924 this->style()->unpolish(this->ui->lineEmail);
925 this->style()->polish(this->ui->lineEmail);
926@@ -86,7 +88,10 @@
927
928 bool LoginForm::checkPassword()
929 {
930- bool value = this->ui->linePassword->text().length() > 7;
931+ bool value = true;
932+ if(this->ui->radioReturningCustomer->isChecked()){
933+ value = this->ui->linePassword->text().length() > 7;
934+ }
935 this->ui->linePassword->setProperty("error", !value);
936 this->style()->unpolish(this->ui->linePassword);
937 this->style()->polish(this->ui->linePassword);
938@@ -121,11 +126,15 @@
939 void LoginForm::on_radioNewCustomer_clicked()
940 {
941 this->ui->btnProceed->setText(tr("Continue"));
942+ this->validateForm();
943+ this->checkPassword();
944+ this->ui->lblPasswordError->setVisible(false);
945 }
946
947 void LoginForm::on_radioReturningCustomer_clicked()
948 {
949 this->ui->btnProceed->setText(tr("Proceed to Checkout"));
950+ this->validateForm();
951 }
952
953 void LoginForm::showEmailWarning()
954@@ -135,5 +144,7 @@
955
956 void LoginForm::showPasswordWarning()
957 {
958- this->ui->lblPasswordError->setVisible(!this->checkPassword());
959+ if(this->ui->radioReturningCustomer->isChecked()){
960+ this->ui->lblPasswordError->setVisible(!this->checkPassword());
961+ }
962 }
963
964=== modified file 'music-login/registerform.cpp'
965--- music-login/registerform.cpp 2013-06-14 22:30:19 +0000
966+++ music-login/registerform.cpp 2013-08-27 20:30:52 +0000
967@@ -104,7 +104,8 @@
968
969 bool RegisterForm::checkEmail()
970 {
971- bool value = !this->ui->lineEmail->text().isEmpty() && this->ui->lineEmail->text().contains("@");
972+ QRegExp mailRE(".+@.+");
973+ bool value = mailRE.exactMatch(this->ui->lineEmail->text());
974 this->ui->lineEmail->setProperty("error", !value);
975 this->style()->unpolish(this->ui->lineEmail);
976 this->style()->polish(this->ui->lineEmail);
977
978=== modified file 'music-login/ssowizard.cpp'
979--- music-login/ssowizard.cpp 2013-07-02 18:59:41 +0000
980+++ music-login/ssowizard.cpp 2013-08-27 20:30:52 +0000
981@@ -81,11 +81,14 @@
982 QObject::connect(&(this->downloader), SIGNAL(fileDownloaded(QString&)),
983 this, SLOT(imageDownloaded(QString&)));
984
985- QObject::connect(&(this->_service), SIGNAL(credentialsStored(const Token&)),
986- this, SLOT(accountAuthenticated(Token)));
987+ QObject::connect(&(this->_service), SIGNAL(credentialsStored()),
988+ this, SLOT(accountAuthenticated()));
989 QObject::connect(&(this->_service), SIGNAL(credentialsFound(const Token&)),
990 this, SLOT(openUrlAndFinish(Token)));
991
992+ QObject::connect(&(this->_service), SIGNAL(twoFactorAuthRequired()),
993+ this, SLOT(handleTwoFactorAuthRequired()));
994+
995 QObject::connect(&(this->_service), SIGNAL(requestFailed(const ErrorResponse&)),
996 this, SLOT(serviceFailed(const ErrorResponse&)));
997 QObject::connect(this->ui->pageLogin, SIGNAL(newCustomerSelected(QString,QString)),
998@@ -142,7 +145,7 @@
999 this->_service.login(email, password);
1000 }
1001
1002-void SSOWizard::accountAuthenticated(Token token)
1003+void SSOWizard::accountAuthenticated()
1004 {
1005 this->_service.getCredentials();
1006 }
1007@@ -172,6 +175,12 @@
1008 this->ui->stackedWidget->setCurrentIndex(0);
1009 }
1010
1011+void SSOWizard::handleTwoFactorAuthRequired()
1012+{
1013+ this->_overlay->hide();
1014+ this->showError(ErrorResponse(401, QString(), TWOFACTOR_REQUIRED, QString()));
1015+}
1016+
1017 void SSOWizard::serviceFailed(const ErrorResponse& error)
1018 {
1019 this->_overlay->hide();
1020
1021=== modified file 'music-login/ssowizard.h'
1022--- music-login/ssowizard.h 2013-07-02 18:59:41 +0000
1023+++ music-login/ssowizard.h 2013-08-27 20:30:52 +0000
1024@@ -67,8 +67,9 @@
1025 void registerAndBuy(QString email, QString password, QString name);
1026 void showPageLogin();
1027
1028- void accountAuthenticated(Token);
1029+ void accountAuthenticated();
1030 void openUrlAndFinish(Token);
1031+ void handleTwoFactorAuthRequired();
1032 void serviceFailed(const ErrorResponse&);
1033
1034 private:
1035
1036=== modified file 'music-login/tests/CMakeLists.txt'
1037--- music-login/tests/CMakeLists.txt 2013-05-27 02:26:03 +0000
1038+++ music-login/tests/CMakeLists.txt 2013-08-27 20:30:52 +0000
1039@@ -20,8 +20,8 @@
1040 qt5_use_modules (${UI_TESTS_TARGET} Test DBus Network Widgets)
1041 add_dependencies (${UI_TESTS_TARGET} ${MUSIC_LOGIN_LIB})
1042 target_link_libraries (${UI_TESTS_TARGET}
1043- -Wl,-rpath,${CMAKE_BINARY_DIR}/lib
1044- -L${CMAKE_BINARY_DIR}/lib
1045+ -Wl,-rpath,${CMAKE_BINARY_DIR}/libubuntuoneauth
1046+ -L${CMAKE_BINARY_DIR}/libubuntuoneauth
1047 ${AUTH_LIB_NAME}
1048 ${MUSIC_LOGIN_LIB}
1049 )
1050
1051=== modified file 'music-login/tests/testloginform.cpp'
1052--- music-login/tests/testloginform.cpp 2013-06-14 22:30:19 +0000
1053+++ music-login/tests/testloginform.cpp 2013-08-27 20:30:52 +0000
1054@@ -51,6 +51,7 @@
1055 this->loginForm.ui->btnProceed->setEnabled(false);
1056 this->loginForm.ui->lblEmailError->setVisible(false);
1057 this->loginForm.ui->lblPasswordError->setVisible(false);
1058+ this->loginForm.ui->btnProceed->setText(QString("Proceed to Checkout"));
1059 }
1060
1061 void TestLoginForm::cleanup()
1062@@ -83,7 +84,7 @@
1063 QVERIFY(this->loginForm.checkPassword());
1064 }
1065
1066-void TestLoginForm::testValidateForm()
1067+void TestLoginForm::testValidateFormWithPassword()
1068 {
1069 QVERIFY(!this->loginForm.ui->btnProceed->isEnabled());
1070 this->loginForm.ui->lineEmail->setText("mail@ubuntu.com");
1071@@ -92,6 +93,15 @@
1072 QVERIFY(this->loginForm.ui->btnProceed->isEnabled());
1073 }
1074
1075+void TestLoginForm::testValidateFormWithoutPassword()
1076+{
1077+ QVERIFY(!this->loginForm.ui->btnProceed->isEnabled());
1078+ this->loginForm.ui->lineEmail->setText("mail@ubuntu.com");
1079+ QVERIFY(!this->loginForm.ui->btnProceed->isEnabled());
1080+ this->loginForm.ui->radioNewCustomer->click();
1081+ QVERIFY(this->loginForm.ui->btnProceed->isEnabled());
1082+}
1083+
1084 void TestLoginForm::testCheckEmailWarnings()
1085 {
1086 this->loginForm.show();
1087@@ -104,9 +114,10 @@
1088 QVERIFY(!this->loginForm.ui->lblEmailError->isVisible());
1089 }
1090
1091-void TestLoginForm::testCheckPasswordWarnings()
1092+void TestLoginForm::testCheckPasswordWarningsReturningCustomer()
1093 {
1094 this->loginForm.show();
1095+ this->loginForm.ui->radioReturningCustomer->setChecked(true);
1096 QVERIFY(!this->loginForm.ui->lblPasswordError->isVisible());
1097 this->loginForm.ui->linePassword->setText("pass");
1098 this->loginForm.ui->linePassword->editingFinished();
1099@@ -116,6 +127,19 @@
1100 QVERIFY(!this->loginForm.ui->lblPasswordError->isVisible());
1101 }
1102
1103+void TestLoginForm::testCheckPasswordWarningsNewCustomer()
1104+{
1105+ this->loginForm.show();
1106+ this->loginForm.ui->radioNewCustomer->setChecked(true);
1107+ QVERIFY(!this->loginForm.ui->lblPasswordError->isVisible());
1108+ this->loginForm.ui->linePassword->setText("pass");
1109+ this->loginForm.ui->linePassword->editingFinished();
1110+ QVERIFY(!this->loginForm.ui->lblPasswordError->isVisible());
1111+ this->loginForm.ui->linePassword->setText("password");
1112+ this->loginForm.ui->linePassword->editingFinished();
1113+ QVERIFY(!this->loginForm.ui->lblPasswordError->isVisible());
1114+}
1115+
1116 void TestLoginForm::testButtonProceed()
1117 {
1118 QVERIFY(!this->_newCustomerEmitted);
1119
1120=== modified file 'music-login/tests/testloginform.h'
1121--- music-login/tests/testloginform.h 2013-05-08 14:36:08 +0000
1122+++ music-login/tests/testloginform.h 2013-08-27 20:30:52 +0000
1123@@ -47,9 +47,11 @@
1124 void init();
1125 void testCheckEmail();
1126 void testCheckPassword();
1127- void testValidateForm();
1128+ void testValidateFormWithPassword();
1129+ void testValidateFormWithoutPassword();
1130 void testCheckEmailWarnings();
1131- void testCheckPasswordWarnings();
1132+ void testCheckPasswordWarningsReturningCustomer();
1133+ void testCheckPasswordWarningsNewCustomer();
1134 void testButtonProceed();
1135 void testButtonText();
1136 void testShowErrorTipsAlreadyRegistered();
1137
1138=== added directory 'online-accounts-provider'
1139=== added file 'online-accounts-provider/CMakeLists.txt'
1140--- online-accounts-provider/CMakeLists.txt 1970-01-01 00:00:00 +0000
1141+++ online-accounts-provider/CMakeLists.txt 2013-08-27 20:30:52 +0000
1142@@ -0,0 +1,6 @@
1143+file (GLOB QML_PLUGIN_FILES *.qml)
1144+
1145+# The path (including plug-in name) where the QML files are installed
1146+set (QML_PLUGIN_INSTALL_DIR share/accounts/qml-plugins/ubuntuone/)
1147+
1148+install (FILES ${QML_PLUGIN_FILES} DESTINATION ${QML_PLUGIN_INSTALL_DIR})
1149
1150=== added file 'online-accounts-provider/ExistingAccount.qml'
1151--- online-accounts-provider/ExistingAccount.qml 1970-01-01 00:00:00 +0000
1152+++ online-accounts-provider/ExistingAccount.qml 2013-08-27 20:30:52 +0000
1153@@ -0,0 +1,95 @@
1154+/*
1155+ * Copyright (C) 2013 Canonical Ltd.
1156+ *
1157+ *
1158+ * This program is free software: you can redistribute it and/or modify it
1159+ * under the terms of the GNU General Public License version 3, as published
1160+ * by the Free Software Foundation.
1161+ *
1162+ * This program is distributed in the hope that it will be useful, but
1163+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1164+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1165+ * PURPOSE. See the GNU General Public License for more details.
1166+ *
1167+ * You should have received a copy of the GNU General Public License along
1168+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1169+ */
1170+
1171+import QtQuick 2.0
1172+import Ubuntu.Components 0.1
1173+import Ubuntu.Components.ListItems 0.1 as ListItem
1174+import Ubuntu.Components.Popups 0.1
1175+import Ubuntu.OnlineAccounts 0.1
1176+import Ubuntu.OnlineAccounts.Plugin 1.0
1177+
1178+Column {
1179+ id: root
1180+
1181+ property variant __account: account
1182+
1183+ signal finished
1184+
1185+ anchors.left: parent.left
1186+ anchors.right: parent.right
1187+
1188+ ListItem.SingleValue {
1189+ text: "User Name"
1190+ value: account.displayName
1191+ }
1192+
1193+ ListItem.SingleValue {
1194+ text: "Token Name"
1195+ value: account.displayName
1196+ }
1197+
1198+ ServiceSwitches {
1199+ account: __account
1200+ enabled: __account.enabled
1201+ opacity: enabled ? 1 : 0.5
1202+ }
1203+
1204+ // TOFIX: use ListItem.SingleControl when lp #1194844 is fixed
1205+ ListItem.Base {
1206+ Button {
1207+ anchors {
1208+ verticalCenter: parent.verticalCenter
1209+ right: parent.right
1210+ left: parent.left
1211+ }
1212+ text: "Remove account…"
1213+ onClicked: PopupUtils.open(removalConfirmationComponent); // huh? , removeBtn)
1214+ }
1215+ showDivider: false
1216+ }
1217+
1218+ Component {
1219+ id: removalConfirmationComponent
1220+ Dialog {
1221+ id: dialog
1222+
1223+ property bool confirmed: false
1224+
1225+ title: "Remove Credentials"
1226+ text: "Removing the Ubuntu One credentials will prevent any applications on this device from accessing your account. You can authorize the device again by providing your username and password."
1227+
1228+ Button {
1229+ text: "Remove"
1230+ onClicked: {
1231+ PopupUtils.close(dialog);
1232+ console.log("Removing account: " + __account);
1233+ account.removed.connect(root.finished);
1234+ account.remove(Account.RemoveCredentials);
1235+ }
1236+
1237+ }
1238+
1239+ Button {
1240+ text: "Cancel"
1241+ onClicked: {
1242+ console.log("User cancelled account removal");
1243+ PopupUtils.close(dialog);
1244+ }
1245+ }
1246+ } // Dialog
1247+ } //Component
1248+}
1249
1250=== added file 'online-accounts-provider/LoginForm.qml'
1251--- online-accounts-provider/LoginForm.qml 1970-01-01 00:00:00 +0000
1252+++ online-accounts-provider/LoginForm.qml 2013-08-27 20:30:52 +0000
1253@@ -0,0 +1,100 @@
1254+import QtQuick 2.0
1255+import Ubuntu.Components 0.1
1256+
1257+Rectangle {
1258+ // Set a non-zero height and width so that the parent Column in
1259+ // CredentialsUI lays out correctly. Set matching color so we
1260+ // don't see a line.
1261+ height: 0.001
1262+ width: main.width
1263+ color: main.parent.color
1264+
1265+ property alias password: passwordTextField.text
1266+ property alias twoFactorVisible: twoFactorUI.visible
1267+ property alias twoFactorCode: twoFactorTextField.text
1268+
1269+ Column {
1270+ spacing: units.gu(2)
1271+
1272+ Label {
1273+ text: "I am a returning user and my password is:"
1274+ fontSize: "small"
1275+ }
1276+ TextField {
1277+ id: passwordTextField
1278+
1279+ placeholderText: "Your password"
1280+ echoMode: TextInput.Password
1281+ width: main.width - (2 * main.anchors.margins)
1282+
1283+ Keys.onReturnPressed: main.processForm();
1284+ }
1285+
1286+ Label {
1287+ text: '<a href="https://login.ubuntu.com/+forgot_password"><span style="color: #dd4814;">Forgotten your password?</span></a>'
1288+ textFormat: Text.RichText
1289+ fontSize: "small"
1290+ onLinkActivated: { Qt.openUrlExternally(link); }
1291+ }
1292+
1293+
1294+ Column {
1295+ id: twoFactorUI
1296+ spacing: units.gu(2)
1297+ height: 1
1298+ width: parent.width
1299+ visible: false
1300+
1301+ Label {
1302+ text: "Type your verification code:"
1303+ fontSize: "small"
1304+ }
1305+
1306+ TextField {
1307+ id: twoFactorTextField
1308+ placeholderText: "2-factor device code"
1309+ echoMode: TextInput.Password
1310+ focus: true
1311+ width: main.width - (2 * main.anchors.margins)
1312+ Keys.onReturnPressed: {
1313+ main.processForm();
1314+ }
1315+ }
1316+
1317+ Label {
1318+ text: '<a href="https://login.ubuntu.com/+device-help"><span style="color: #dd4814;">Authentication Device Help</span></a>'
1319+ textFormat: Text.RichText
1320+ fontSize: "small"
1321+ onLinkActivated: { Qt.openUrlExternally(link); }
1322+ }
1323+
1324+ } // Rectangle : twoFactorUI
1325+
1326+
1327+ }// Column
1328+
1329+ function resetUI() {
1330+ twoFactorUI.visible = false;
1331+ twoFactorTextField.text = "";
1332+ passwordTextField.text = "";
1333+ }
1334+
1335+ function validateInput() {
1336+ var passwordLongEnough = passwordTextField.text.length > 7;
1337+ passwordTextField.errorHighlight = !passwordLongEnough;
1338+ if (!passwordLongEnough) {
1339+ main.showError("Password must be at least 8 characters long.");
1340+ }
1341+
1342+ if (!twoFactorUI.visible) {
1343+ return passwordLongEnough;
1344+ }
1345+
1346+ var twoFactorLongEnough = twoFactorTextField.text.length > 0;
1347+ twoFactorTextField.errorHighlight = !twoFactorLongEnough;
1348+ if(!twoFactorLongEnough){
1349+ main.showError("Please enter your two-factor device code.");
1350+ }
1351+ return passwordLongEnough && twoFactorLongEnough;
1352+ }
1353+}
1354
1355=== added file 'online-accounts-provider/Main.qml'
1356--- online-accounts-provider/Main.qml 1970-01-01 00:00:00 +0000
1357+++ online-accounts-provider/Main.qml 2013-08-27 20:30:52 +0000
1358@@ -0,0 +1,50 @@
1359+/*
1360+ * Copyright (C) 2013 Canonical Ltd.
1361+ *
1362+ *
1363+ * This program is free software: you can redistribute it and/or modify it
1364+ * under the terms of the GNU General Public License version 3, as published
1365+ * by the Free Software Foundation.
1366+ *
1367+ * This program is distributed in the hope that it will be useful, but
1368+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1369+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1370+ * PURPOSE. See the GNU General Public License for more details.
1371+ *
1372+ * You should have received a copy of the GNU General Public License along
1373+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1374+ */
1375+
1376+import QtQuick 2.0
1377+import Ubuntu.Components 0.1
1378+import Ubuntu.OnlineAccounts 0.1
1379+
1380+Flickable {
1381+ id: root
1382+
1383+ property url newAccountUrl: "NewAccount.qml"
1384+ property url existingAccountUrl: "ExistingAccount.qml"
1385+ property Component newAccountComponent: null
1386+ property Component existingAccountComponent: null
1387+
1388+ property alias source: loader.source
1389+
1390+ signal finished
1391+
1392+ anchors.left: parent.left
1393+ anchors.right: parent.right
1394+ contentHeight: contentItem.childrenRect.height
1395+
1396+ Loader {
1397+ id: loader
1398+ anchors.left: parent.left
1399+ anchors.right: parent.right
1400+ source: sourceComponent === null ? (account.accountId != 0 ? existingAccountUrl : newAccountUrl) : ""
1401+ sourceComponent: account.accountId != 0 ? existingAccountComponent : newAccountComponent
1402+
1403+ Connections {
1404+ target: loader.item
1405+ onFinished: root.finished()
1406+ }
1407+ }
1408+}
1409
1410=== added file 'online-accounts-provider/NewAccount.qml'
1411--- online-accounts-provider/NewAccount.qml 1970-01-01 00:00:00 +0000
1412+++ online-accounts-provider/NewAccount.qml 2013-08-27 20:30:52 +0000
1413@@ -0,0 +1,257 @@
1414+/*
1415+ * Copyright (C) 2013 Canonical Ltd.
1416+ *
1417+ *
1418+ * This program is free software: you can redistribute it and/or modify it
1419+ * under the terms of the GNU General Public License version 3, as published
1420+ * by the Free Software Foundation.
1421+ *
1422+ * This program is distributed in the hope that it will be useful, but
1423+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1424+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1425+ * PURPOSE. See the GNU General Public License for more details.
1426+ *
1427+ * You should have received a copy of the GNU General Public License along
1428+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1429+ */
1430+
1431+import QtQuick 2.0
1432+import Ubuntu.Components 0.1
1433+import UbuntuOne 1.0
1434+import Ubuntu.OnlineAccounts 0.1
1435+
1436+
1437+Column {
1438+ id: main
1439+
1440+ //property variant authenticationParameters: null
1441+
1442+ property bool isNewAccount: false
1443+ property variant __account: account
1444+// unneeded:? property alias globalAccountService: globalAccountSettings
1445+
1446+
1447+ state: "login" // or "register" or "twofactor"
1448+ property var currentVisible: loginForm
1449+ property var formValid: false
1450+
1451+ signal finished
1452+
1453+ anchors.left: parent.left
1454+ anchors.right: parent.right
1455+
1456+ Component.onCompleted: {
1457+ isNewAccount = (account.accountId === 0);
1458+ resetUI();
1459+ }
1460+
1461+ Label {
1462+ id: title
1463+ text: "One account to log in to everything on Ubuntu"
1464+ fontSize: "medium"
1465+ color: UbuntuColors.coolGrey
1466+ anchors.left: parent.left
1467+ anchors.right: parent.right
1468+ anchors.margins: parent.anchors.margins
1469+ }
1470+
1471+ Label {
1472+ id: errorLabel
1473+ text: ""
1474+ font.bold: true
1475+ color: "red"
1476+ visible: false
1477+
1478+ anchors.left: parent.left
1479+ anchors.right: parent.right
1480+ anchors.margins: parent.anchors.margins
1481+
1482+ }
1483+
1484+ Label {
1485+ text: "Please type your email:"
1486+ fontSize: "large"
1487+
1488+ anchors.left: parent.left
1489+ anchors.right: parent.right
1490+ anchors.margins: parent.anchors.margins
1491+ }
1492+
1493+ TextField {
1494+ id: emailTextField
1495+ placeholderText: "Your email"
1496+ focus: true;
1497+
1498+ width: main.width - (2 * main.anchors.margins)
1499+ anchors.left: parent.left
1500+ anchors.margins: parent.anchors.margins
1501+ }
1502+
1503+ Row {
1504+ spacing: units.gu(2)
1505+ Switch {
1506+ id: newUserToggleSwitch
1507+ checked: false
1508+
1509+ onCheckedChanged: {
1510+ toggleNewUser();
1511+ }
1512+ }
1513+ Label {
1514+ anchors.verticalCenter: newUserToggleSwitch.verticalCenter
1515+ text: "I am a new Ubuntu One user"
1516+ fontSize: "large"
1517+ }
1518+ anchors.left: parent.left
1519+ anchors.right: parent.right
1520+ anchors.margins: parent.anchors.margins
1521+
1522+ } // Row
1523+
1524+ LoginForm {
1525+ id: loginForm
1526+ visible: true
1527+
1528+ anchors.left: parent.left
1529+ anchors.right: parent.right
1530+ anchors.margins: parent.anchors.margins
1531+ }
1532+
1533+ RegisterForm {
1534+ id: registerForm
1535+ visible: false
1536+
1537+ anchors.left: parent.left
1538+ anchors.right: parent.right
1539+ anchors.margins: parent.anchors.margins
1540+ }
1541+
1542+ Rectangle {
1543+ id: loadingOverlay
1544+ opacity: 0.6
1545+ color: "white"
1546+ visible: false
1547+ width: main.width
1548+ height: main.height
1549+ //TODO: anchors.centerIn: main.parent
1550+
1551+ ActivityIndicator {
1552+ id: activity
1553+ //TODO: anchors.centerIn: parent
1554+ running: true
1555+ }
1556+ }
1557+
1558+ // -------------------------------------------------
1559+
1560+ UbuntuOneCredentialsService {
1561+ id: u1credservice
1562+
1563+ onLoginOrRegisterSuccess: {
1564+ handleSuccess();
1565+ }
1566+
1567+ onTwoFactorAuthRequired: {
1568+ showTwoFactorUI();
1569+ }
1570+
1571+ onLoginOrRegisterError: {
1572+ if (errorMessage == "Invalid request data") {
1573+ errorMessage = "Please enter a valid email address.";
1574+ }
1575+ showError(errorMessage);
1576+ }
1577+ }
1578+
1579+ function resetUI() {
1580+ errorLabel.visible = false;
1581+ emailTextField.text = "";
1582+ loginForm.resetUI()
1583+ registerForm.resetUI();
1584+ newUserToggleSwitch.checked = false;
1585+ state = "login";
1586+ switchTo(loginForm);
1587+ formValid = false;
1588+ }
1589+
1590+ function showError(message) {
1591+ errorLabel.text = message;
1592+ errorLabel.visible = true;
1593+ loadingOverlay.visible = false;
1594+ }
1595+
1596+ function switchTo(newVisible) {
1597+ currentVisible.visible = false;
1598+ newVisible.visible = true;
1599+ currentVisible = newVisible;
1600+ }
1601+
1602+ function toggleNewUser() {
1603+ if(state == "login") {
1604+ switchTo(registerForm)
1605+ state = "register";
1606+ } else if(state == "register") {
1607+ switchTo(loginForm)
1608+ state = "login";
1609+ } else {
1610+ console.debug("unexpected state" + state + "in toggleNewUser");
1611+ }
1612+ }
1613+
1614+ function processForm() {
1615+ validateInput();
1616+ if (!formValid) {
1617+ return;
1618+ }
1619+ loadingOverlay.visible = true;
1620+ if(state == "login") {
1621+ var password = loginForm.password;
1622+ u1credservice.login(emailTextField.text, password);
1623+ } else if(state == "register") {
1624+ var password = registerForm.password;
1625+ var display_name = registerForm.display_name;
1626+ u1credservice.registerUser(emailTextField.text, password, display_name);
1627+ } else if(state == "twofactor") {
1628+ u1credservice.login(emailTextField.text, loginForm.password, loginForm.twoFactorCode);
1629+ }
1630+ }
1631+
1632+ function handleSuccess() {
1633+ loadingOverlay.visible = false;
1634+ errorLabel.visible = false;
1635+ resetUI();
1636+ finished();
1637+ }
1638+
1639+ function showTwoFactorUI() {
1640+ loadingOverlay.visible = false;
1641+ if(state != "login") {
1642+ console.log("Error: did not expect two factor request from register");
1643+ showError("An internal error occurred. Please try again later.");
1644+ return;
1645+ }
1646+ errorLabel.visible = false;
1647+ state = "twofactor";
1648+ loginForm.twoFactorVisible = true;
1649+ formValid = false;
1650+ }
1651+
1652+ function validateInput() {
1653+ formValid = emailTextField.acceptableInput;
1654+ if(!formValid) {
1655+ showError("Please enter a valid email address.");
1656+ return;
1657+ }
1658+
1659+ if(state == "login" || state == "twofactor") {
1660+ formValid &= loginForm.validateInput();
1661+ } else {
1662+ formValid &= registerForm.validateInput();
1663+ }
1664+
1665+ if(formValid) {
1666+ errorLabel.visible = false;
1667+ }
1668+ }
1669+
1670+}
1671
1672=== added file 'online-accounts-provider/RegisterForm.qml'
1673--- online-accounts-provider/RegisterForm.qml 1970-01-01 00:00:00 +0000
1674+++ online-accounts-provider/RegisterForm.qml 2013-08-27 20:30:52 +0000
1675@@ -0,0 +1,97 @@
1676+import QtQuick 2.0
1677+import Ubuntu.Components 0.1
1678+
1679+Rectangle {
1680+ // Set a non-zero height and width so that the parent Column in
1681+ // CredentialsUI lays out correctly. Set matching color so we
1682+ // don't see a 1px line.
1683+ height: 0.001
1684+ width: main.width
1685+ color: main.parent.color
1686+
1687+ property alias password: passwordTextField.text
1688+ property alias display_name: nameTextField.text
1689+
1690+
1691+ Column {
1692+ spacing: units.gu(2)
1693+
1694+ Label {
1695+ id: subtitle
1696+ fontSize: "small"
1697+ text: "Please tell us your name and choose a password."
1698+ }
1699+
1700+ TextField {
1701+ id: nameTextField
1702+ placeholderText: "Your name"
1703+ width: main.width - (2 * main.anchors.margins)
1704+ }
1705+
1706+ TextField {
1707+ id: passwordTextField
1708+ placeholderText: "Password with at least 8 characters"
1709+ echoMode: TextInput.Password
1710+ width: main.width - (2 * main.anchors.margins)
1711+ }
1712+
1713+ TextField {
1714+ id: confirmPasswordTextField
1715+ placeholderText: "Re-type password"
1716+ echoMode: TextInput.Password
1717+ width: main.width - (2 * main.anchors.margins)
1718+ }
1719+ Row {
1720+ spacing: units.gu(2)
1721+ CheckBox {
1722+ id: termsAndConditionsCheckBox
1723+ checked: false
1724+ }
1725+
1726+ Label {
1727+ anchors.verticalCenter: termsAndConditionsCheckBox.verticalCenter
1728+ text: "I agree to the <a href='http://one.ubuntu.com/terms/'>Ubuntu One Terms and Conditions</a>"
1729+ fontSize: "small"
1730+ onLinkActivated: { Qt.openUrlExternally(link); }
1731+ }
1732+ }
1733+ }
1734+
1735+ function resetUI() {
1736+ termsAndConditionsCheckBox.checked = false;
1737+ nameTextField.text = "";
1738+ passwordTextField.text = "";
1739+ confirmPasswordTextField.text = "";
1740+ }
1741+
1742+ function validateInput() {
1743+ var valid = termsAndConditionsCheckBox.checked;
1744+ if (!valid) {
1745+ main.showError("Please accept the terms and conditions by checking the box.");
1746+ return false;
1747+ }
1748+
1749+ var nameOK = (nameTextField.text != "");
1750+ nameTextField.errorHighlight = !nameOK;
1751+ if (!nameOK) {
1752+ main.showError("Please enter a name.");
1753+ return false;
1754+ }
1755+
1756+ var passwordLongEnough = passwordTextField.length > 7;
1757+ passwordTextField.errorHighlight = !passwordLongEnough;
1758+ if (!passwordLongEnough) {
1759+ main.showError("Your password must be at least 8 characters long.");
1760+ return false;
1761+ }
1762+
1763+ var passwordsMatch = (passwordTextField.text == confirmPasswordTextField.text);
1764+ confirmPasswordTextField.errorHighlight = !passwordsMatch;
1765+ if (!passwordsMatch) {
1766+ main.showError("The passwords do not match.");
1767+ return false;
1768+ }
1769+
1770+ return true;
1771+ }
1772+}
1773
1774=== added directory 'qml-credentials-service'
1775=== added file 'qml-credentials-service/CMakeLists.txt'
1776--- qml-credentials-service/CMakeLists.txt 1970-01-01 00:00:00 +0000
1777+++ qml-credentials-service/CMakeLists.txt 2013-08-27 20:30:52 +0000
1778@@ -0,0 +1,25 @@
1779+# Qt5 bits
1780+set (CMAKE_INCLUDE_CURRENT_DIR ON)
1781+set (CMAKE_AUTOMOC ON)
1782+find_package(Qt5Core REQUIRED)
1783+
1784+file (GLOB CPP_SOURCES *.cpp)
1785+
1786+configure_file (qmldir.template qmldir)
1787+
1788+add_library (${QML_PLUGIN_NAME} MODULE ${CPP_SOURCES})
1789+qt5_use_modules (${QML_PLUGIN_NAME} Core Widgets Quick Qml )
1790+target_link_libraries (${QML_PLUGIN_NAME}
1791+ -Wl,-rpath,${CMAKE_BINARY_DIR}/libubuntuoneauth
1792+ -L${CMAKE_BINARY_DIR}/libubuntuoneauth
1793+ ${AUTH_LIB_NAME}
1794+)
1795+
1796+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/qmldir DESTINATION ${QML_MODULE_INSTALL_DIR}/${QML_MODULE_NAME} )
1797+
1798+install (TARGETS ${QML_PLUGIN_NAME}
1799+ LIBRARY DESTINATION ${QML_MODULE_INSTALL_DIR}/${QML_MODULE_NAME}
1800+ NAMELINK_SKIP
1801+)
1802+
1803+install (CODE "execute_process(COMMAND qmlplugindump ${QML_MODULE_NAME} ${QML_PLUGIN_API_VERSION} ${CMAKE_INSTALL_PREFIX}/${QML_MODULE_INSTALL_DIR} OUTPUT_FILE ${CMAKE_INSTALL_PREFIX}/${QML_MODULE_INSTALL_DIR}/${QML_MODULE_NAME}/${QML_MODULE_NAME}.qmltypes)")
1804
1805=== added file 'qml-credentials-service/README'
1806--- qml-credentials-service/README 1970-01-01 00:00:00 +0000
1807+++ qml-credentials-service/README 2013-08-27 20:30:52 +0000
1808@@ -0,0 +1,31 @@
1809+
1810+Ubuntu One Credentials QML Plugin
1811+
1812+This plugin provides the UbuntuOne QML Component, which exposes the
1813+CredentialsService plugin, allowing you to display login/register UI
1814+and check for credentials and sign URLs.
1815+
1816+
1817+HACKING
1818+
1819+An example for embedding the UI provided by the plugin is in examples/embedding.qml
1820+
1821+The CMake setup only builds the complete QML component at install, and
1822+the qmltypes file required by qtcreator is also only built at install,
1823+so to test without installing to a system location, you will need to
1824+do something like the following:
1825+
1826+mkdir -p build
1827+cd build
1828+cmake -D .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp/installtemp ..
1829+make all install
1830+
1831+Then, when running, point LD_LIBRARY_PATH to the install lib dir so
1832+that libubuntuonecredentials is discoverable. Here's an example of running qmlscene to try the example code:
1833+
1834+LD_LIBRARY_PATH=/tmp/installtemp/lib/ qmlscene -I /tmp/installtemp/lib/qt5/qml/ qml-credentials-service/examples/embeddingMain.qml
1835+
1836+
1837+
1838+
1839+
1840
1841=== added directory 'qml-credentials-service/examples'
1842=== added file 'qml-credentials-service/examples/embeddingMain.qml'
1843--- qml-credentials-service/examples/embeddingMain.qml 1970-01-01 00:00:00 +0000
1844+++ qml-credentials-service/examples/embeddingMain.qml 2013-08-27 20:30:52 +0000
1845@@ -0,0 +1,129 @@
1846+import QtQuick 2.0
1847+import Ubuntu.Components 0.1
1848+import UbuntuOne 1.0
1849+
1850+Rectangle {
1851+ id: exampleMain
1852+ width: units.gu(100)
1853+ height: units.gu(120)
1854+ color: UbuntuColors.coolGrey
1855+
1856+ Column {
1857+ spacing: units.gu(2)
1858+ anchors.fill: parent
1859+
1860+ add: Transition {
1861+ NumberAnimation { properties: "opacity"; easing.type: Easing.OutQuad; duration: 1000}
1862+ }
1863+
1864+ Row {
1865+ anchors.left: parent.left
1866+ anchors.margins: units.gu(2)
1867+ spacing: units.gu(2)
1868+
1869+ Switch {
1870+ id: showCredsUISwitch
1871+ checked: true
1872+ }
1873+
1874+ Label {
1875+ id: label
1876+ color: "white"
1877+ text: "Show Creds UI"
1878+ anchors.verticalCenter: showCredsUISwitch.verticalCenter
1879+ }
1880+
1881+ Label {
1882+ id: statusLabel
1883+ color: "white"
1884+ text: ""
1885+ anchors.verticalCenter: showCredsUISwitch.verticalCenter
1886+ }
1887+ }
1888+
1889+ // Here is where we've embedded the UI for UbuntuOne login and register.
1890+ // Note that you must declare some width and height for the layout to work.
1891+
1892+ CredentialsUI {
1893+ id: credsUI
1894+
1895+ width: parent.width * 0.80
1896+ height: (parent.height - showCredsUISwitch.height) * 0.80
1897+ anchors.horizontalCenter: parent.horizontalCenter
1898+ visible: showCredsUISwitch.checked
1899+
1900+ onUserCancelled: {
1901+ showCredsUISwitch.checked = false;
1902+ statusLabel.text = "Login/Register cancelled by user";
1903+ credsUI.resetUI();
1904+ }
1905+
1906+ onSucceeded: {
1907+ showCredsUISwitch.checked = false;
1908+ statusLabel.text = "Login/Register succeeded";
1909+ credsUI.resetUI();
1910+ }
1911+ }
1912+
1913+ Label {
1914+ id: infoLabel
1915+ text: "Press this button to check for credentials in local keyring:"
1916+ color: "white"
1917+ }
1918+
1919+ Button {
1920+ id: btnCancel
1921+ text: "Check existing creds"
1922+ color: "#1c091a"
1923+ onClicked: {
1924+ u1credservice.checkCredentials();
1925+ }
1926+ }
1927+
1928+ Label {
1929+ id: revokeLabel
1930+ text: "Press this button to delete the credentials in local keyring:"
1931+ color: "white"
1932+ }
1933+
1934+ Button {
1935+ id: btnRevoke
1936+ text: "Invalidate existing creds"
1937+ color: "#1c091a"
1938+ onClicked: {
1939+ u1credservice.invalidateCredentials();
1940+ }
1941+ }
1942+
1943+ } // Column
1944+
1945+ /* Below, an example of how to use the service without showing UI,
1946+ just to test if there is a local credential already, and sign a
1947+ url with it, if it does exist.*/
1948+
1949+ UbuntuOneCredentialsService {
1950+ id: u1credservice
1951+
1952+ onCredentialsFound: {
1953+ infoLabel.text = "Credentials Found. signing a url.";
1954+ signUrl("http://server", "GET");
1955+ }
1956+
1957+ onUrlSigned: {
1958+ infoLabel.text = "signed url is "+ signedUrl;
1959+ }
1960+
1961+ onUrlSigningError: {
1962+ infoLabel.text = "signing error:" + errorMessage;
1963+ }
1964+
1965+ onCredentialsNotFound: {
1966+ infoLabel.text = "No Credentials Found.";
1967+ signUrl("http://server", "GET"); // xfail
1968+ }
1969+
1970+ onCredentialsDeleted: {
1971+ revokeLabel.text = "Deleted Credentials successfully";
1972+ }
1973+ }
1974+} // UbuntuShape
1975
1976=== added file 'qml-credentials-service/qmldir.template'
1977--- qml-credentials-service/qmldir.template 1970-01-01 00:00:00 +0000
1978+++ qml-credentials-service/qmldir.template 2013-08-27 20:30:52 +0000
1979@@ -0,0 +1,3 @@
1980+module @QML_MODULE_NAME@
1981+plugin @QML_PLUGIN_NAME@
1982+typeinfo @QML_MODULE_NAME@.qmltypes
1983
1984=== added file 'qml-credentials-service/ubuntuone_credentials_plugin.cpp'
1985--- qml-credentials-service/ubuntuone_credentials_plugin.cpp 1970-01-01 00:00:00 +0000
1986+++ qml-credentials-service/ubuntuone_credentials_plugin.cpp 2013-08-27 20:30:52 +0000
1987@@ -0,0 +1,11 @@
1988+#include "ubuntuone_credentials_plugin.h"
1989+#include "ubuntuone_credentials_service.h"
1990+
1991+#include <qqml.h>
1992+
1993+void UbuntuOneCredentialsPlugin::registerTypes(const char *uri)
1994+{
1995+ qmlRegisterType<UbuntuOneCredentialsService>(uri, 1, 0, "UbuntuOneCredentialsService");
1996+}
1997+
1998+
1999
2000=== added file 'qml-credentials-service/ubuntuone_credentials_plugin.h'
2001--- qml-credentials-service/ubuntuone_credentials_plugin.h 1970-01-01 00:00:00 +0000
2002+++ qml-credentials-service/ubuntuone_credentials_plugin.h 2013-08-27 20:30:52 +0000
2003@@ -0,0 +1,16 @@
2004+#ifndef UBUNTUONECREDENTIALS_PLUGIN_H
2005+#define UBUNTUONECREDENTIALS_PLUGIN_H
2006+
2007+#include <QQmlExtensionPlugin>
2008+
2009+class UbuntuOneCredentialsPlugin : public QQmlExtensionPlugin
2010+{
2011+ Q_OBJECT
2012+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2013+
2014+public:
2015+ void registerTypes(const char *uri);
2016+};
2017+
2018+#endif // UBUNTUONECREDENTIALS_PLUGIN_H
2019+
2020
2021=== added file 'qml-credentials-service/ubuntuone_credentials_service.cpp'
2022--- qml-credentials-service/ubuntuone_credentials_service.cpp 1970-01-01 00:00:00 +0000
2023+++ qml-credentials-service/ubuntuone_credentials_service.cpp 2013-08-27 20:30:52 +0000
2024@@ -0,0 +1,157 @@
2025+#include "ubuntuone_credentials_service.h"
2026+#include <QDebug>
2027+
2028+UbuntuOneCredentialsService::UbuntuOneCredentialsService(QQuickItem *parent):
2029+ QQuickItem(parent)
2030+{
2031+ _state = IDLE;
2032+ QObject::connect(&(this->_service), SIGNAL(credentialsFound(Token)),
2033+ this, SLOT(handleCredentialsFound(Token)));
2034+ QObject::connect(&(this->_service), SIGNAL(credentialsNotFound()),
2035+ this, SLOT(handleCredentialsNotFound()));
2036+ QObject::connect(&(this->_service), SIGNAL(credentialsStored()),
2037+ this, SLOT(handleCredentialsStored()));
2038+ QObject::connect(&(this->_service), SIGNAL(credentialsDeleted()),
2039+ this, SLOT(handleCredentialsDeleted()));
2040+
2041+ QObject::connect(&(this->_service), SIGNAL(twoFactorAuthRequired()),
2042+ this, SLOT(handleTwoFactorAuthRequired()));
2043+
2044+ QObject::connect(&(this->_service), SIGNAL(requestFailed(ErrorResponse)),
2045+ this, SLOT(handleError(ErrorResponse)));
2046+}
2047+
2048+UbuntuOneCredentialsService::~UbuntuOneCredentialsService()
2049+{
2050+}
2051+
2052+
2053+// public API (Q_INVOKABLE)
2054+
2055+void UbuntuOneCredentialsService::checkCredentials()
2056+{
2057+ Q_ASSERT(_state == IDLE);
2058+ _state = CHECK;
2059+ _service.getCredentials();
2060+}
2061+
2062+void UbuntuOneCredentialsService::invalidateCredentials()
2063+{
2064+ Q_ASSERT(_state == IDLE);
2065+ _state = DELETE;
2066+ _service.invalidateCredentials();
2067+}
2068+
2069+void UbuntuOneCredentialsService::login(QString email, QString password, QString twoFactorCode)
2070+{
2071+ Q_ASSERT(_state == IDLE);
2072+ _state = LOGIN;
2073+ _service.login(email, password, twoFactorCode);
2074+}
2075+
2076+void UbuntuOneCredentialsService::registerUser(QString email, QString password, QString name)
2077+{
2078+ Q_ASSERT(_state == IDLE);
2079+ _state = REGISTER;
2080+ _service.registerUser(email, password, name);
2081+}
2082+
2083+// calling signUrl with no credentials stored will emit an error
2084+void UbuntuOneCredentialsService::signUrl(const QString url, const QString method, bool asQuery)
2085+{
2086+ Q_ASSERT(_state == IDLE);
2087+ _state = SIGN;
2088+ _sign_url = url;
2089+ _sign_method = method;
2090+ _sign_asQuery = asQuery;
2091+ _service.getCredentials();
2092+}
2093+
2094+// signal handlers
2095+
2096+// credentials found is only sent by _service.getCredentials(), not login or register
2097+void UbuntuOneCredentialsService::handleCredentialsFound(const Token& token)
2098+{
2099+ QString signedUrl;
2100+
2101+ qDebug() << "in UbuntuOneCredentialsService::handleCredentialsFound";
2102+
2103+ // set state before emitting any signals, as signals happen 'after' transition
2104+ CredentialsServiceState calledState = _state;
2105+ _state = IDLE;
2106+
2107+ switch(calledState){
2108+ case CHECK:
2109+ emit credentialsFound();
2110+ break;
2111+ case SIGN:
2112+ signedUrl = token.signUrl(_sign_url, _sign_method, _sign_asQuery);
2113+ emit urlSigned(signedUrl);
2114+ break;
2115+ default:
2116+ qDebug() << "UbuntuOneCredentialsService did not expect credentialsFound in state " << calledState;
2117+ }
2118+
2119+}
2120+
2121+void UbuntuOneCredentialsService::handleCredentialsNotFound()
2122+{
2123+ qDebug() << "in UbuntuOneCredentialsService::handleCredentialsNotFound";
2124+
2125+ // set state before emitting any signals, as signals happen 'after' transition
2126+ CredentialsServiceState calledState = _state;
2127+ _state = IDLE;
2128+
2129+ switch(calledState){
2130+ case CHECK:
2131+ emit credentialsNotFound();
2132+ break;
2133+ case SIGN:
2134+ emit urlSigningError(QString("Attempt to sign without credentials in keyring"));
2135+ break;
2136+ default:
2137+ qDebug() << "UbuntuOneCredentialsService did not expect credentialsNotFound in state " << calledState;
2138+ }
2139+}
2140+
2141+// Credentials stored is signaled when the u1 ping is done after login/register
2142+void UbuntuOneCredentialsService::handleCredentialsStored()
2143+{
2144+ qDebug() << "in UbuntuOneCredentialsService::handleCredentialsStored";
2145+
2146+ // set state before emitting any signals, as signals happen 'after' transition
2147+ CredentialsServiceState calledState = _state;
2148+ _state = IDLE;
2149+
2150+ if (calledState == LOGIN || calledState == REGISTER){
2151+ emit loginOrRegisterSuccess();
2152+ }else{
2153+ qDebug() << "UbuntuOneCredentialsService did not expect credentialsStored in state " << calledState;
2154+ }
2155+}
2156+
2157+void UbuntuOneCredentialsService::handleCredentialsDeleted()
2158+{
2159+ qDebug() << "in UbuntuOneCredentialsService::handleCredentialsDeleted";
2160+
2161+ // set state before emitting any signals, as signals happen 'after' transition
2162+ CredentialsServiceState calledState = _state;
2163+ _state = IDLE;
2164+
2165+ if (calledState == DELETE){
2166+ emit credentialsDeleted();
2167+ }else{
2168+ qDebug() << "UbuntuOneCredentialsService did not expect credentialsDeleted in state " << calledState;
2169+ }
2170+}
2171+
2172+void UbuntuOneCredentialsService::handleTwoFactorAuthRequired(){
2173+ _state = IDLE;
2174+ emit twoFactorAuthRequired();
2175+}
2176+
2177+void UbuntuOneCredentialsService::handleError(const ErrorResponse& error)
2178+{
2179+ _state = IDLE;
2180+ emit loginOrRegisterError(error.message());
2181+}
2182
2183=== added file 'qml-credentials-service/ubuntuone_credentials_service.h'
2184--- qml-credentials-service/ubuntuone_credentials_service.h 1970-01-01 00:00:00 +0000
2185+++ qml-credentials-service/ubuntuone_credentials_service.h 2013-08-27 20:30:52 +0000
2186@@ -0,0 +1,62 @@
2187+#ifndef UBUNTUONE_CREDENTIALS_SERVICE_H
2188+#define UBUNTUONE_CREDENTIALS_SERVICE_H
2189+
2190+#include <QQuickItem>
2191+#include "ssoservice.h"
2192+
2193+using namespace UbuntuOne;
2194+
2195+enum CredentialsServiceState{
2196+ IDLE = 0,
2197+ CHECK,
2198+ LOGIN,
2199+ REGISTER,
2200+ SIGN,
2201+ DELETE
2202+};
2203+
2204+class UbuntuOneCredentialsService : public QQuickItem
2205+{
2206+ Q_OBJECT
2207+ Q_DISABLE_COPY(UbuntuOneCredentialsService)
2208+
2209+public:
2210+ UbuntuOneCredentialsService(QQuickItem *parent = 0);
2211+ ~UbuntuOneCredentialsService();
2212+
2213+ Q_INVOKABLE void checkCredentials();
2214+ Q_INVOKABLE void invalidateCredentials();
2215+ Q_INVOKABLE void login(QString email, QString password, QString twoFactorCode = QString());
2216+ Q_INVOKABLE void registerUser(QString email, QString password, QString name);
2217+ Q_INVOKABLE void signUrl(QString url, QString method, bool asQuery = false);
2218+
2219+signals:
2220+ void credentialsFound();
2221+ void credentialsNotFound();
2222+ void credentialsDeleted();
2223+ void loginOrRegisterSuccess();
2224+ void loginOrRegisterError(QString errorMessage);
2225+ void twoFactorAuthRequired();
2226+ void urlSigned(QString signedUrl);
2227+ void urlSigningError(QString errorMessage);
2228+
2229+private slots:
2230+ void handleCredentialsFound(const Token&);
2231+ void handleCredentialsNotFound();
2232+ void handleCredentialsStored();
2233+ void handleCredentialsDeleted();
2234+ void handleTwoFactorAuthRequired();
2235+ void handleError(const ErrorResponse&);
2236+
2237+private:
2238+ SSOService _service;
2239+ CredentialsServiceState _state;
2240+ QString _sign_url;
2241+ QString _sign_method;
2242+ bool _sign_asQuery;
2243+};
2244+
2245+QML_DECLARE_TYPE(UbuntuOneCredentialsService)
2246+
2247+#endif // UBUNTUONE_CREDENTIALS_SERVICE_H
2248+
2249
2250=== added directory 'signon-plugin'
2251=== added file 'signon-plugin/CMakeLists.txt'
2252--- signon-plugin/CMakeLists.txt 1970-01-01 00:00:00 +0000
2253+++ signon-plugin/CMakeLists.txt 2013-08-27 20:30:52 +0000
2254@@ -0,0 +1,37 @@
2255+# Qt5 bits
2256+SET (CMAKE_INCLUDE_CURRENT_DIR ON)
2257+SET (CMAKE_AUTOMOC ON)
2258+find_package(Qt5Core REQUIRED)
2259+
2260+# The sources for building the library
2261+FILE (GLOB SOURCES *.cpp)
2262+# HEADERS only includes the public headers for installation.
2263+FILE (GLOB HEADERS *.h)
2264+
2265+find_package (PkgConfig REQUIRED)
2266+pkg_check_modules(SIGNON REQUIRED signon-plugins)
2267+add_definitions(${SIGNON_CFLAGS} ${SIGNON_CFLAGS_OTHER})
2268+
2269+# Workaround for cmake not adding these to automoc properly
2270+SET (CMAKE_AUTOMOC_MOC_OPTIONS "${SIGNON_CFLAGS} ${CMAKE_AUTOMOC_MOC_OPTIONS}")
2271+
2272+# Need the project version here
2273+add_definitions("-DPROJECT_VERSION=\"${PROJECT_VERSION}\"")
2274+
2275+add_library (${SIGNON_PLUGIN_NAME} MODULE ${SOURCES})
2276+qt5_use_modules (${SIGNON_PLUGIN_NAME} Core Xml Network)
2277+target_link_libraries (${SIGNON_PLUGIN_NAME}
2278+ -Wl,-rpath,${CMAKE_BINARY_DIR}/libubuntuoneauth
2279+ -L${CMAKE_BINARY_DIR}/libubuntuoneauth
2280+ ${AUTH_LIB_NAME}
2281+ ${SIGNON_PLUGIN_LDFLAGS}
2282+)
2283+
2284+SET (SIGNON_PLUGIN_INSTALL_DIR lib/signon)
2285+
2286+INSTALL (
2287+ TARGETS ${SIGNON_PLUGIN_NAME}
2288+ LIBRARY DESTINATION ${SIGNON_PLUGIN_INSTALL_DIR}
2289+)
2290+
2291+#add_subdirectory(tests)
2292
2293=== added file 'signon-plugin/ubuntuone-plugin.cpp'
2294--- signon-plugin/ubuntuone-plugin.cpp 1970-01-01 00:00:00 +0000
2295+++ signon-plugin/ubuntuone-plugin.cpp 2013-08-27 20:30:52 +0000
2296@@ -0,0 +1,80 @@
2297+/*
2298+ * Copyright 2013 Canonical Ltd.
2299+ *
2300+ * This library is free software; you can redistribute it and/or
2301+ * modify it under the terms of version 3 of the GNU Lesser General Public
2302+ * License as published by the Free Software Foundation.
2303+ *
2304+ * This program is distributed in the hope that it will be useful,
2305+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2306+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2307+ * General Public License for more details.
2308+ *
2309+ * You should have received a copy of the GNU Lesser General Public
2310+ * License along with this library; if not, write to the
2311+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2312+ * Boston, MA 02110-1301, USA.
2313+ */
2314+#include <token.h>
2315+
2316+#include "ubuntuone-plugin.h"
2317+
2318+
2319+namespace UbuntuOne {
2320+
2321+ SignOnPlugin::SignOnPlugin(QObject *parent)
2322+ : AuthPluginInterface(parent)
2323+ {
2324+ }
2325+
2326+ SignOnPlugin::~SignOnPlugin()
2327+ {
2328+ }
2329+
2330+ QString SignOnPlugin::type() const
2331+ {
2332+ return QLatin1String("ubuntuone");
2333+ }
2334+
2335+ QStringList SignOnPlugin::mechanisms() const
2336+ {
2337+ QStringList res = QStringList(QLatin1String("ubuntuone"));
2338+
2339+ return res;
2340+ }
2341+
2342+ void SignOnPlugin::cancel()
2343+ {
2344+ }
2345+
2346+ void SignOnPlugin::process(const SignOn::SessionData &inData,
2347+ const QString &mechanism)
2348+ {
2349+ Q_UNUSED(mechanism);
2350+ PluginData response;
2351+ m_data = inData.data<PluginData>();
2352+
2353+ if (!inData.Secret().isEmpty()) {
2354+ response.setConsumer(m_data.Consumer());
2355+ response.setConsumerSecret(m_data.ConsumerSecret());
2356+ response.setToken(m_data.Token());
2357+ response.setTokenSecret(m_data.TokenSecret());
2358+
2359+ response.setName(Token::buildTokenName());
2360+
2361+ emit result(response);
2362+ return;
2363+ }
2364+
2365+ SignOn::UiSessionData data;
2366+ data.setRealm(inData.Realm());
2367+ data.setShowRealm(!data.Realm().isEmpty());
2368+ emit userActionRequired(data);
2369+ }
2370+
2371+ void SignOnPlugin::userActionFinished(const SignOn::UiSessionData &data)
2372+ {
2373+ }
2374+
2375+ SIGNON_DECL_AUTH_PLUGIN(SignOnPlugin)
2376+} // namespace UbuntuOne
2377
2378=== added file 'signon-plugin/ubuntuone-plugin.h'
2379--- signon-plugin/ubuntuone-plugin.h 1970-01-01 00:00:00 +0000
2380+++ signon-plugin/ubuntuone-plugin.h 2013-08-27 20:30:52 +0000
2381@@ -0,0 +1,56 @@
2382+/*
2383+ * Copyright 2013 Canonical Ltd.
2384+ *
2385+ * This library is free software; you can redistribute it and/or
2386+ * modify it under the terms of version 3 of the GNU Lesser General Public
2387+ * License as published by the Free Software Foundation.
2388+ *
2389+ * This program is distributed in the hope that it will be useful,
2390+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2391+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2392+ * General Public License for more details.
2393+ *
2394+ * You should have received a copy of the GNU Lesser General Public
2395+ * License along with this library; if not, write to the
2396+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2397+ * Boston, MA 02110-1301, USA.
2398+ */
2399+#ifndef _UBUNTUONE_PLUGIN_H_
2400+#define _UBUNTUONE_PLUGIN_H_
2401+
2402+#include <QtCore>
2403+
2404+#include <SignOn/AuthPluginInterface>
2405+#include <SignOn/Error>
2406+#include <SignOn/SessionData>
2407+#include <SignOn/UiSessionData>
2408+
2409+#include "ubuntuonedata.h"
2410+
2411+
2412+namespace UbuntuOne {
2413+
2414+ class SignOnPlugin : public AuthPluginInterface
2415+ {
2416+ Q_OBJECT
2417+ Q_INTERFACES(AuthPluginInterface)
2418+
2419+ public:
2420+ SignOnPlugin(QObject *parent = 0);
2421+ virtual ~SignOnPlugin();
2422+
2423+ public Q_SLOTS:
2424+ QString type() const;
2425+ QStringList mechanisms() const;
2426+ void cancel();
2427+ void process(const SignOn::SessionData &inData,
2428+ const QString &mechanism = 0);
2429+ void userActionFinished(const SignOn::UiSessionData &data);
2430+
2431+ private:
2432+ PluginData m_data;
2433+ };
2434+
2435+} // namespace UbuntuOne
2436+
2437+#endif
2438
2439=== added file 'signon-plugin/ubuntuonedata.h'
2440--- signon-plugin/ubuntuonedata.h 1970-01-01 00:00:00 +0000
2441+++ signon-plugin/ubuntuonedata.h 2013-08-27 20:30:52 +0000
2442@@ -0,0 +1,42 @@
2443+/*
2444+ * Copyright 2013 Canonical Ltd.
2445+ *
2446+ * This library is free software; you can redistribute it and/or
2447+ * modify it under the terms of version 3 of the GNU Lesser General Public
2448+ * License as published by the Free Software Foundation.
2449+ *
2450+ * This program is distributed in the hope that it will be useful,
2451+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2452+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2453+ * General Public License for more details.
2454+ *
2455+ * You should have received a copy of the GNU Lesser General Public
2456+ * License along with this library; if not, write to the
2457+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
2458+ * Boston, MA 02110-1301, USA.
2459+ */
2460+#ifndef _UBUNTUONE_DATA_H_
2461+#define _UBUNTUONE_DATA_H_
2462+
2463+#include <sessiondata.h>
2464+
2465+namespace UbuntuOne {
2466+
2467+ class PluginData : public SignOn::SessionData
2468+ {
2469+ public:
2470+ // The name of the token
2471+ SIGNON_SESSION_DECLARE_PROPERTY(QString, Name);
2472+
2473+ // The consumer key and secret for signing
2474+ SIGNON_SESSION_DECLARE_PROPERTY(QString, Consumer);
2475+ SIGNON_SESSION_DECLARE_PROPERTY(QString, ConsumerSecret);
2476+
2477+ // The access token and secret for signing
2478+ SIGNON_SESSION_DECLARE_PROPERTY(QString, Token);
2479+ SIGNON_SESSION_DECLARE_PROPERTY(QString, TokenSecret);
2480+ };
2481+
2482+} // namespace UbuntuOne
2483+
2484+#endif

Subscribers

People subscribed via source and target branches

to all changes: