[epiphany/wip/ephy-sync] Implement login logic
- From: Gabriel - Cristian Ivascu <gabrielivascu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/ephy-sync] Implement login logic
- Date: Sat, 25 Jun 2016 11:10:56 +0000 (UTC)
commit 7002e2b7a44dd1a45125c4b32eae6c8ed8714038
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date: Sat Jun 25 14:10:22 2016 +0300
Implement login logic
src/ephy-sync-service.c | 151 +++++++++++++++++++++++++++++++++++------------
src/ephy-sync-service.h | 4 +-
src/ephy-sync-utils.c | 4 +
src/ephy-sync-utils.h | 2 +
src/prefs-dialog.c | 29 +++++++--
5 files changed, 143 insertions(+), 47 deletions(-)
---
diff --git a/src/ephy-sync-service.c b/src/ephy-sync-service.c
index 6f100ef..a074281 100644
--- a/src/ephy-sync-service.c
+++ b/src/ephy-sync-service.c
@@ -28,9 +28,13 @@
#include <libsoup/soup.h>
#include <string.h>
+#define BASEURL "https://api.accounts.firefox.com/v1"
+
struct _EphySyncService {
GObject parent_instance;
+ SoupSession *soup_session;
+
gchar *user_email;
GHashTable *tokens;
};
@@ -44,7 +48,8 @@ ephy_sync_service_finalize (GObject *object)
EphySyncService *self = EPHY_SYNC_SERVICE (object);
g_free (self->user_email);
- g_hash_table_destroy (self->tokens);
+ g_clear_object (&self->tokens);
+ g_clear_object (&self->soup_session);
G_OBJECT_CLASS (ephy_sync_service_parent_class)->finalize (object);
}
@@ -64,6 +69,7 @@ ephy_sync_service_init (EphySyncService *self)
self->tokens = g_hash_table_new_full (NULL, g_str_equal,
NULL, g_free);
+ self->soup_session = soup_session_new ();
sync_user = g_settings_get_string (EPHY_SETTINGS_MAIN,
EPHY_PREFS_SYNC_USER);
@@ -76,17 +82,24 @@ ephy_sync_service_init (EphySyncService *self)
LOG ("[%d] sync service inited", __LINE__);
}
-static void
-server_response_cb (SoupSession *session,
- SoupMessage *message,
- gpointer user_data)
+static SoupMessage *
+synchronous_post_request (EphySyncService *self,
+ const gchar *endpoint,
+ gchar *request_body)
{
- if (message->status_code == 200) {
-LOG ("[%d] response body: %s", __LINE__, message->response_body->data);
- // TODO: parse response data using JsonParser
- } else {
-LOG ("[%d] Error response from server: [%u] %s", __LINE__, message->status_code, message->reason_phrase);
- }
+ SoupMessage *message;
+
+ message = soup_message_new (SOUP_METHOD_POST,
+ g_strdup_printf ("%s/%s", BASEURL, endpoint));
+ soup_message_set_request (message,
+ "application/json",
+ SOUP_MEMORY_TAKE,
+ request_body,
+ strlen (request_body));
+LOG ("[%d] Sending synchronous POST request to %s endpoint", __LINE__, endpoint);
+ soup_session_send_message (self->soup_session, message);
+
+ return message;
}
EphySyncService *
@@ -161,44 +174,92 @@ ephy_sync_service_delete_all_tokens (EphySyncService *self)
LOG ("[%d] Deleted all tokens", __LINE__);
}
-void
-ephy_sync_service_login (EphySyncService *self)
+gboolean
+ephy_sync_service_login (EphySyncService *self,
+ guint *error_code,
+ gchar **error_message)
{
- SoupSession *session;
SoupMessage *message;
+ JsonParser *parser;
+ JsonNode *root;
+ JsonObject *object;
gchar *request_body;
+ gchar *quickStretchedPW;
gchar *authPW;
+ gchar *unwrapBKey;
+ gchar *uid;
+ gchar *sessionToken;
+ gchar *keyFetchToken;
+ authPW = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_AUTHPW);
+ g_return_val_if_fail (authPW, FALSE);
-LOG ("[%d] Preparing soup message", __LINE__);
+ request_body = g_strconcat ("{\"authPW\": \"", authPW,
+ "\", \"email\": \"", self->user_email,
+ "\"}", NULL);
- session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT,
- "test-json",
- NULL);
- message = soup_message_new (SOUP_METHOD_POST,
- "https://api.accounts.firefox.com/v1/account/login");
+ message = synchronous_post_request (self,
+ "account/login?keys=true",
+ request_body);
+LOG ("[%d] status code: %u", __LINE__, message->status_code);
- authPW = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_AUTHPW);
- g_assert (authPW != NULL);
+ parser = json_parser_new ();
+ json_parser_load_from_data (parser, message->response_body->data, -1, NULL);
+ root = json_parser_get_root (parser);
+ g_assert (JSON_NODE_HOLDS_OBJECT (root));
+ object = json_node_get_object (root);
- request_body = g_strconcat ("{\"authPW\": \"",
- authPW,
- "\", \"email\": \"",
- self->user_email,
- "\"}",
- NULL);
+ if (message->status_code != 200) {
+ *error_message = g_strdup (json_object_get_string_member (object, "message"));
+ *error_code = json_object_get_int_member (object, "errno");
- soup_message_set_request (message,
- "application/json",
- SOUP_MEMORY_COPY,
- request_body,
- strlen (request_body));
+LOG ("[%d] errno: %u, errmsg: %s", __LINE__, *error_code, *error_message);
+
+ ephy_sync_service_delete_all_tokens (self);
+ ephy_sync_service_set_user_email (self, NULL);
- soup_session_queue_message (session, message, server_response_cb, NULL);
-LOG ("[%d] Queued the soup message", __LINE__);
+ return FALSE;
+ }
- // TODO: find a way to safely free request_body
- // TODO: find a way to safely destroy session, message
+ /* Extract uid, sesionToken, keyFetchToken */
+ uid = g_strdup (json_object_get_string_member (object, "uid"));
+ sessionToken = g_strdup (json_object_get_string_member (object, "sessionToken"));
+ keyFetchToken = g_strdup (json_object_get_string_member (object, "keyFetchToken"));
+
+ /* Save tokens in memory */
+ ephy_sync_service_save_token (self,
+ EPHY_SYNC_TOKEN_UID,
+ uid);
+ ephy_sync_service_save_token (self,
+ EPHY_SYNC_TOKEN_SESSIONTOKEN,
+ sessionToken);
+ ephy_sync_service_save_token (self,
+ EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
+ keyFetchToken);
+
+ /* Store tokens on disk */
+ quickStretchedPW = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW);
+ unwrapBKey = ephy_sync_service_get_token (self, EPHY_SYNC_TOKEN_UNWRAPBKEY);
+ ephy_sync_secret_store_token (self->user_email,
+ EPHY_SYNC_TOKEN_AUTHPW,
+ authPW);
+ ephy_sync_secret_store_token (self->user_email,
+ EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
+ keyFetchToken);
+ ephy_sync_secret_store_token (self->user_email,
+ EPHY_SYNC_TOKEN_SESSIONTOKEN,
+ sessionToken);
+ ephy_sync_secret_store_token (self->user_email,
+ EPHY_SYNC_TOKEN_UID,
+ uid);
+ ephy_sync_secret_store_token (self->user_email,
+ EPHY_SYNC_TOKEN_UNWRAPBKEY,
+ unwrapBKey);
+ ephy_sync_secret_store_token (self->user_email,
+ EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW,
+ quickStretchedPW);
+
+ return TRUE;
}
void
@@ -213,8 +274,6 @@ ephy_sync_service_stretch (EphySyncService *self,
guint8 *authPW;
guint8 *unwrapBKey;
- g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
-
salt_stretch = ephy_sync_utils_kwe ("quickStretch", emailUTF8);
quickStretchedPW = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
ephy_sync_crypto_pbkdf2_1k ((guint8 *) passwordUTF8,
@@ -248,6 +307,20 @@ ephy_sync_utils_display_hex ("quickStretchedPW", quickStretchedPW, EPHY_SYNC_TOK
LOG ("[%d] Stretching done", __LINE__);
+ ephy_sync_service_set_user_email (self, emailUTF8);
+ ephy_sync_service_save_token (self,
+ EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW,
+ ephy_sync_utils_encode_hex (quickStretchedPW,
+ EPHY_SYNC_TOKEN_LENGTH));
+ ephy_sync_service_save_token (self,
+ EPHY_SYNC_TOKEN_AUTHPW,
+ ephy_sync_utils_encode_hex (authPW,
+ EPHY_SYNC_TOKEN_LENGTH));
+ ephy_sync_service_save_token (self,
+ EPHY_SYNC_TOKEN_UNWRAPBKEY,
+ ephy_sync_utils_encode_hex (unwrapBKey,
+ EPHY_SYNC_TOKEN_LENGTH));
+
g_free (salt_stretch);
g_free (info_unwrap);
g_free (info_auth);
diff --git a/src/ephy-sync-service.h b/src/ephy-sync-service.h
index e467c83..2631971 100644
--- a/src/ephy-sync-service.h
+++ b/src/ephy-sync-service.h
@@ -52,7 +52,9 @@ void ephy_sync_service_stretch (EphySyncService *self,
const gchar *emailUTF8,
const gchar *passwordUTF8);
-void ephy_sync_service_login (EphySyncService *self);
+gboolean ephy_sync_service_login (EphySyncService *self,
+ guint *error_code,
+ gchar **error_message);
G_END_DECLS
diff --git a/src/ephy-sync-utils.c b/src/ephy-sync-utils.c
index 152dddb..68d2f36 100644
--- a/src/ephy-sync-utils.c
+++ b/src/ephy-sync-utils.c
@@ -78,8 +78,12 @@ ephy_sync_utils_token_name_from_type (EphySyncTokenType token_type)
switch (token_type) {
case EPHY_SYNC_TOKEN_AUTHPW:
return "authPw";
+ case EPHY_SYNC_TOKEN_KEYFETCHTOKEN:
+ return "keyFetchToken";
case EPHY_SYNC_TOKEN_SESSIONTOKEN:
return "sessionToken";
+ case EPHY_SYNC_TOKEN_UID:
+ return "uid";
case EPHY_SYNC_TOKEN_UNWRAPBKEY:
return "unwrapBKey";
case EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW:
diff --git a/src/ephy-sync-utils.h b/src/ephy-sync-utils.h
index ea0b6f5..d3eeae6 100644
--- a/src/ephy-sync-utils.h
+++ b/src/ephy-sync-utils.h
@@ -27,7 +27,9 @@ G_BEGIN_DECLS
typedef enum {
EPHY_SYNC_TOKEN_AUTHPW,
+ EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
EPHY_SYNC_TOKEN_SESSIONTOKEN,
+ EPHY_SYNC_TOKEN_UID,
EPHY_SYNC_TOKEN_UNWRAPBKEY,
EPHY_SYNC_TOKEN_QUICKSTRETCHEDPW
} EphySyncTokenType;
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index c25455a..452d8ee 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -35,6 +35,7 @@
#include "ephy-session.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
+#include "ephy-sync-service.h"
#include "clear-data-dialog.h"
#include "cookies-dialog.h"
#include "languages.h"
@@ -169,12 +170,16 @@ static void
on_sync_login_button_clicked (GtkWidget *button,
PrefsDialog *dialog)
{
+ EphySyncService *sync_service;
const gchar *emailUTF8;
const gchar *passwordUTF8;
+ gboolean login_ok;
+ guint error_code = 0;
+ gchar *error_message = NULL;
- gtk_label_set_markup (GTK_LABEL (dialog->sync_email_details_label), NULL);
- gtk_label_set_markup (GTK_LABEL (dialog->sync_password_details_label), NULL);
- gtk_label_set_markup (GTK_LABEL (dialog->sync_extra_details_label), NULL);
+ gtk_label_set_markup (GTK_LABEL (dialog->sync_email_details_label), "");
+ gtk_label_set_markup (GTK_LABEL (dialog->sync_password_details_label), "");
+ gtk_label_set_markup (GTK_LABEL (dialog->sync_extra_details_label), "");
emailUTF8 = gtk_entry_get_text (GTK_ENTRY (dialog->sync_email_entry));
passwordUTF8 = gtk_entry_get_text (GTK_ENTRY (dialog->sync_password_entry));
@@ -182,28 +187,38 @@ on_sync_login_button_clicked (GtkWidget *button,
if (emailUTF8 && !emailUTF8[0]) {
gtk_label_set_markup (GTK_LABEL (dialog->sync_email_details_label),
_("<span fgcolor='#e6780b'>Please insert your email</span>"));
-LOG ("[%d] empty email field", __LINE__);
return;
}
if (passwordUTF8 && !passwordUTF8[0]) {
gtk_label_set_markup (GTK_LABEL (dialog->sync_password_details_label),
_("<span fgcolor='#e6780b'>Please insert your password</span>"));
-LOG ("[%d] empty password field", __LINE__);
return;
}
LOG ("[%d] email: %s", __LINE__, emailUTF8);
LOG ("[%d] password: %s", __LINE__, passwordUTF8);
- /* TODO: Call /account/login endpoint and handle server response */
+ sync_service = ephy_shell_get_global_sync_service ();
+ ephy_sync_service_stretch (sync_service, emailUTF8, passwordUTF8);
+ login_ok = ephy_sync_service_login (sync_service, &error_code, &error_message);
+
+ if (login_ok == FALSE) {
+ /* Translators: the %s refers to the error message. */
+ gtk_label_set_markup (GTK_LABEL (dialog->sync_extra_details_label),
+ g_strdup_printf (_("<span fgcolor='#e6780b'>Error: %s</span>"),
+ error_message));
+ g_free (error_message);
+ return;
+ }
g_settings_set_string (EPHY_SETTINGS_MAIN,
EPHY_PREFS_SYNC_USER,
emailUTF8);
/* Translators: the %s refers to the email of the currently logged in user. */
gtk_label_set_markup (GTK_LABEL (dialog->sync_logout_details_label),
- g_strdup_printf (_("Currently logged in as <b>%s</b>"), emailUTF8));
+ g_strdup_printf (_("Currently logged in as <b>%s</b>"),
+ emailUTF8));
gtk_container_remove (GTK_CONTAINER (dialog->sync_authenticate_box),
dialog->sync_login_grid);
gtk_box_pack_start (GTK_BOX (dialog->sync_authenticate_box),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]