[gnome-software/wip/rancell/ubuntuone: 2/2] Add UbuntuOne plugin to authorize Ubuntu reviews



commit 083367c42d7e03ccb2e33367b893a02d1f18094b
Author: Robert Ancell <robert ancell canonical com>
Date:   Wed Jun 29 16:37:38 2016 +1200

    Add UbuntuOne plugin to authorize Ubuntu reviews

 src/gs-plugin.h                        |   22 ++--
 src/plugins/Makefile.am                |   12 ++-
 src/plugins/gs-plugin-ubuntu-reviews.c |   24 ++++
 src/plugins/gs-plugin-ubuntuone.c      |  202 ++++++++++++++++++++++++++++++++
 4 files changed, 250 insertions(+), 10 deletions(-)
---
diff --git a/src/gs-plugin.h b/src/gs-plugin.h
index 646157f..28347b9 100644
--- a/src/gs-plugin.h
+++ b/src/gs-plugin.h
@@ -100,15 +100,17 @@ typedef enum {
 
 /**
  * GsPluginError:
- * @GS_PLUGIN_ERROR_FAILED:            Generic failure
- * @GS_PLUGIN_ERROR_NOT_SUPPORTED:     Action not supported
- * @GS_PLUGIN_ERROR_CANCELLED:         Action was cancelled
- * @GS_PLUGIN_ERROR_NO_NETWORK:                No network connection available
- * @GS_PLUGIN_ERROR_NO_SECURITY:       Security policy forbid action
- * @GS_PLUGIN_ERROR_NO_SPACE:          No disk space to allow action
- * @GS_PLUGIN_ERROR_AUTH_REQUIRED:     Authentication was required
- * @GS_PLUGIN_ERROR_AUTH_INVALID:      Provided authentication was invalid
- * @GS_PLUGIN_ERROR_PIN_REQUIRED:      PIN required for authentication
+ * @GS_PLUGIN_ERROR_FAILED:                    Generic failure
+ * @GS_PLUGIN_ERROR_NOT_SUPPORTED:             Action not supported
+ * @GS_PLUGIN_ERROR_CANCELLED:                 Action was cancelled
+ * @GS_PLUGIN_ERROR_NO_NETWORK:                        No network connection available
+ * @GS_PLUGIN_ERROR_NO_SECURITY:               Security policy forbid action
+ * @GS_PLUGIN_ERROR_NO_SPACE:                  No disk space to allow action
+ * @GS_PLUGIN_ERROR_AUTH_REQUIRED:             Authentication was required
+ * @GS_PLUGIN_ERROR_AUTH_INVALID:              Provided authentication was invalid
+ * @GS_PLUGIN_ERROR_PIN_REQUIRED:              PIN required for authentication
+ * @GS_PLUGIN_ERROR_ACCOUNT_SUSPENDED:         User account has been suspended
+ * @GS_PLUGIN_ERROR_ACCOUNT_DEACTIVATED:       User account has been deactivated
  *
  * The failure error types.
  **/
@@ -122,6 +124,8 @@ typedef enum {
        GS_PLUGIN_ERROR_AUTH_REQUIRED,
        GS_PLUGIN_ERROR_AUTH_INVALID,
        GS_PLUGIN_ERROR_PIN_REQUIRED,
+       GS_PLUGIN_ERROR_ACCOUNT_SUSPENDED,
+       GS_PLUGIN_ERROR_ACCOUNT_DEACTIVATED,
        /*< private >*/
        GS_PLUGIN_ERROR_LAST
 } GsPluginError;
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index c57b7d4..09abc13 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -43,7 +43,8 @@ plugin_LTLIBRARIES =                                  \
        libgs_plugin_fedora-tagger-usage.la             \
        libgs_plugin_epiphany.la                        \
        libgs_plugin_icons.la                           \
-       libgs_plugin_snap.la
+       libgs_plugin_snap.la                            \
+       libgs_plugin_ubuntuone.la
 
 if HAVE_PACKAGEKIT
 plugin_LTLIBRARIES +=                                  \
@@ -344,6 +345,15 @@ libgs_plugin_snap_la_LIBADD =                              \
 libgs_plugin_snap_la_LDFLAGS = -module -avoid-version
 libgs_plugin_snap_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
+libgs_plugin_ubuntuone_la_SOURCES =                    \
+       gs-plugin-ubuntuone.c
+libgs_plugin_ubuntuone_la_LIBADD =                     \
+       $(GS_PLUGIN_LIBS)                               \
+       $(SOUP_LIBS)                                    \
+       $(JSON_GLIB_LIBS)
+libgs_plugin_ubuntuone_la_LDFLAGS = -module -avoid-version
+libgs_plugin_ubuntuone_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
+
 if ENABLE_TESTS
 check_PROGRAMS =                                               \
        gs-self-test
diff --git a/src/plugins/gs-plugin-ubuntu-reviews.c b/src/plugins/gs-plugin-ubuntu-reviews.c
index b60b994..2c5cc81 100644
--- a/src/plugins/gs-plugin-ubuntu-reviews.c
+++ b/src/plugins/gs-plugin-ubuntu-reviews.c
@@ -715,3 +715,27 @@ gs_plugin_refine_app (GsPlugin *plugin,
        return TRUE;
 }
 
+static gboolean
+get_auth (GsPlugin *plugin)
+{
+       return FALSE;
+}
+
+gboolean
+gs_plugin_review_submit (GsPlugin *plugin,
+                        GsApp *app,
+                        GsReview *review,
+                        GCancellable *cancellable,
+                        GError **error)
+{
+       if (!get_auth (plugin))
+       {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_AUTH_REQUIRED,
+                                    "Requires authentication with @ubuntuone");
+               return FALSE;
+       }
+
+       return TRUE;
+}
diff --git a/src/plugins/gs-plugin-ubuntuone.c b/src/plugins/gs-plugin-ubuntuone.c
new file mode 100644
index 0000000..e618fcb
--- /dev/null
+++ b/src/plugins/gs-plugin-ubuntuone.c
@@ -0,0 +1,202 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <gnome-software.h>
+#include <libsoup/soup.h>
+#include <json-glib/json-glib.h>
+
+// Documented in http://canonical-identity-provider.readthedocs.io
+#define UBUNTU_LOGIN_HOST "https://login.ubuntu.com";
+
+struct GsPluginData {
+       GsAuth                  *auth;
+};
+
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+       GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
+
+       /* set up a dummy authentication provider */
+       priv->auth = gs_auth_new (gs_plugin_get_name (plugin));
+       gs_auth_set_provider_name (priv->auth, "Ubuntu One");
+        //gs_auth_set_provider_logo (priv->auth, "...");
+       gs_plugin_add_auth (plugin, priv->auth);
+}
+
+gboolean
+gs_plugin_auth_login (GsPlugin *plugin, GsAuth *auth,
+                     GCancellable *cancellable, GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       g_autoptr(JsonBuilder) builder = NULL;
+       g_autoptr(JsonNode) json_root = NULL;
+       g_autoptr(JsonGenerator) json_generator = NULL;
+       g_autofree gchar *data = NULL;
+       g_autofree gchar *uri = NULL;
+       g_autoptr(SoupMessage) msg = NULL;
+       guint status_code;
+       g_autoptr(JsonParser) parser = NULL;
+       JsonNode *response_root;
+       const gchar *consumer_key, *consumer_secret, *token_key, *token_secret;
+
+       if (auth != priv->auth)
+               return TRUE;
+
+       builder = json_builder_new ();
+       json_builder_begin_object (builder);
+       json_builder_set_member_name (builder, "token_name");
+       json_builder_add_string_value (builder, "GNOME Software");
+       json_builder_set_member_name (builder, "email");
+       json_builder_add_string_value (builder, gs_auth_get_username (auth));
+       json_builder_set_member_name (builder, "password");
+       json_builder_add_string_value (builder, gs_auth_get_password (auth));
+       if (gs_auth_get_pin (auth)) {
+               json_builder_set_member_name (builder, "otp");
+               json_builder_add_string_value (builder, gs_auth_get_pin (auth));
+       }
+       json_builder_end_object (builder);
+
+       json_root = json_builder_get_root (builder);
+       json_generator = json_generator_new ();
+       json_generator_set_pretty (json_generator, TRUE);
+       json_generator_set_root (json_generator, json_root);
+       data = json_generator_to_data (json_generator, NULL);
+       if (data == NULL) {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "Failed to generate JSON request");
+               return FALSE;
+       }
+
+       uri = g_strdup_printf ("%s/api/v2/tokens/oauth", UBUNTU_LOGIN_HOST);
+       msg = soup_message_new (SOUP_METHOD_POST, uri);
+       soup_message_set_request (msg, "application/json", SOUP_MEMORY_COPY, data, strlen (data));
+       status_code = soup_session_send_message (gs_plugin_get_soup_session (plugin), msg);
+
+       parser = json_parser_new ();
+       if (!json_parser_load_from_data (parser, msg->response_body->data, -1, error))
+               return FALSE;
+       response_root = json_parser_get_root (parser);
+
+       if (status_code != SOUP_STATUS_OK) {
+               const gchar *message, *code;
+
+               message = json_object_get_string_member (json_node_get_object (response_root), "message");
+               code = json_object_get_string_member (json_node_get_object (response_root), "code");
+
+               if (g_strcmp0 (code, "INVALID_CREDENTIALS") == 0 || g_strcmp0 (code, "EMAIL_INVALIDATED") == 
0 || g_strcmp0 (code, "TWOFACTOR_FAILURE") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_AUTH_INVALID,
+                                            message);
+               }
+               else if (g_strcmp0 (code, "ACCOUNT_SUSPENDED") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_ACCOUNT_SUSPENDED,
+                                            message);
+               }
+               else if (g_strcmp0 (code, "ACCOUNT_DEACTIVATED") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_ACCOUNT_DEACTIVATED,
+                                            message);
+               }
+               else if (g_strcmp0 (code, "TWOFACTOR_REQUIRED") == 0) {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_PIN_REQUIRED,
+                                            message);
+               }
+               else {
+                       g_set_error_literal (error,
+                                            GS_PLUGIN_ERROR,
+                                            GS_PLUGIN_ERROR_FAILED,
+                                            message);
+               }
+               return FALSE;
+       }
+
+       consumer_key = json_object_get_string_member (json_node_get_object (response_root), "consumer_key");
+       consumer_secret = json_object_get_string_member (json_node_get_object (response_root), 
"consumer_secret");
+       token_key = json_object_get_string_member (json_node_get_object (response_root), "token_key");
+       token_secret = json_object_get_string_member (json_node_get_object (response_root), "token_secret");
+       if (consumer_key == NULL || consumer_secret == NULL || token_key == NULL || token_secret == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "%s missing required fields", UBUNTU_LOGIN_HOST);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean
+gs_plugin_auth_logout (GsPlugin *plugin, GsAuth *auth,
+                      GCancellable *cancellable, GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+
+       if (auth != priv->auth)
+               return TRUE;
+
+       return TRUE;
+}
+
+gboolean
+gs_plugin_auth_lost_password (GsPlugin *plugin, GsAuth *auth,
+                             GCancellable *cancellable, GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+
+       if (auth != priv->auth)
+               return TRUE;
+
+       /* return with data */
+       g_set_error (error,
+                    GS_PLUGIN_ERROR,
+                    GS_PLUGIN_ERROR_AUTH_INVALID,
+                    "do online using @%s/+forgot_password", UBUNTU_LOGIN_HOST);
+       return FALSE;
+}
+
+gboolean
+gs_plugin_auth_register (GsPlugin *plugin, GsAuth *auth,
+                        GCancellable *cancellable, GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+
+       if (auth != priv->auth)
+               return TRUE;
+
+       /* return with data */
+       g_set_error (error,
+                    GS_PLUGIN_ERROR,
+                    GS_PLUGIN_ERROR_AUTH_INVALID,
+                    "do online using @%s/+login", UBUNTU_LOGIN_HOST);
+       return FALSE;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]