814 lines
28 KiB
Diff
814 lines
28 KiB
Diff
|
From b6a41a1b9e9020a23dbc418183ebe4746b6ec027 Mon Sep 17 00:00:00 2001
|
||
|
From: Kalev Lember <klember@redhat.com>
|
||
|
Date: Mon, 18 May 2020 14:45:35 +0200
|
||
|
Subject: [PATCH 1/2] Add basic auth support to flatpak plugin
|
||
|
|
||
|
This is useful for e.g. OCI remotes that can use basic auth.
|
||
|
|
||
|
All user visible strings in the basic auth dialog are taken from the
|
||
|
flatpak CLI client.
|
||
|
---
|
||
|
lib/gs-plugin-loader.c | 29 +++-
|
||
|
lib/gs-plugin-loader.h | 7 +-
|
||
|
lib/gs-plugin.c | 68 +++++++++-
|
||
|
lib/gs-plugin.h | 13 +-
|
||
|
plugins/flatpak/gs-plugin-flatpak.c | 55 +++++++-
|
||
|
po/POTFILES.in | 2 +
|
||
|
src/gnome-software.gresource.xml | 1 +
|
||
|
src/gs-basic-auth-dialog.c | 130 ++++++++++++++++++
|
||
|
src/gs-basic-auth-dialog.h | 28 ++++
|
||
|
src/gs-basic-auth-dialog.ui | 203 ++++++++++++++++++++++++++++
|
||
|
src/gs-shell.c | 25 +++-
|
||
|
src/meson.build | 1 +
|
||
|
12 files changed, 556 insertions(+), 6 deletions(-)
|
||
|
create mode 100644 src/gs-basic-auth-dialog.c
|
||
|
create mode 100644 src/gs-basic-auth-dialog.h
|
||
|
create mode 100644 src/gs-basic-auth-dialog.ui
|
||
|
|
||
|
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
|
||
|
index 979f3d5d..35382e3f 100644
|
||
|
--- a/lib/gs-plugin-loader.c
|
||
|
+++ b/lib/gs-plugin-loader.c
|
||
|
@@ -1,7 +1,7 @@
|
||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||
|
*
|
||
|
* Copyright (C) 2007-2018 Richard Hughes <richard@hughsie.com>
|
||
|
- * Copyright (C) 2014-2018 Kalev Lember <klember@redhat.com>
|
||
|
+ * Copyright (C) 2014-2020 Kalev Lember <klember@redhat.com>
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
@@ -74,6 +74,7 @@ enum {
|
||
|
SIGNAL_PENDING_APPS_CHANGED,
|
||
|
SIGNAL_UPDATES_CHANGED,
|
||
|
SIGNAL_RELOAD,
|
||
|
+ SIGNAL_BASIC_AUTH_START,
|
||
|
SIGNAL_LAST
|
||
|
};
|
||
|
|
||
|
@@ -2016,6 +2017,23 @@ gs_plugin_loader_status_changed_cb (GsPlugin *plugin,
|
||
|
0, app, status);
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+gs_plugin_loader_basic_auth_start_cb (GsPlugin *plugin,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GCallback callback,
|
||
|
+ gpointer user_data,
|
||
|
+ GsPluginLoader *plugin_loader)
|
||
|
+{
|
||
|
+ g_debug ("emitting basic-auth-start %s", realm);
|
||
|
+ g_signal_emit (plugin_loader,
|
||
|
+ signals[SIGNAL_BASIC_AUTH_START], 0,
|
||
|
+ remote,
|
||
|
+ realm,
|
||
|
+ callback,
|
||
|
+ user_data);
|
||
|
+}
|
||
|
+
|
||
|
static gboolean
|
||
|
gs_plugin_loader_job_actions_changed_delay_cb (gpointer user_data)
|
||
|
{
|
||
|
@@ -2102,6 +2120,9 @@ gs_plugin_loader_open_plugin (GsPluginLoader *plugin_loader,
|
||
|
g_signal_connect (plugin, "status-changed",
|
||
|
G_CALLBACK (gs_plugin_loader_status_changed_cb),
|
||
|
plugin_loader);
|
||
|
+ g_signal_connect (plugin, "basic-auth-start",
|
||
|
+ G_CALLBACK (gs_plugin_loader_basic_auth_start_cb),
|
||
|
+ plugin_loader);
|
||
|
g_signal_connect (plugin, "report-event",
|
||
|
G_CALLBACK (gs_plugin_loader_report_event_cb),
|
||
|
plugin_loader);
|
||
|
@@ -2712,6 +2733,12 @@ gs_plugin_loader_class_init (GsPluginLoaderClass *klass)
|
||
|
G_STRUCT_OFFSET (GsPluginLoaderClass, reload),
|
||
|
NULL, NULL, g_cclosure_marshal_VOID__VOID,
|
||
|
G_TYPE_NONE, 0);
|
||
|
+ signals [SIGNAL_BASIC_AUTH_START] =
|
||
|
+ g_signal_new ("basic-auth-start",
|
||
|
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
||
|
+ G_STRUCT_OFFSET (GsPluginLoaderClass, basic_auth_start),
|
||
|
+ NULL, NULL, g_cclosure_marshal_generic,
|
||
|
+ G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
diff --git a/lib/gs-plugin-loader.h b/lib/gs-plugin-loader.h
|
||
|
index 74cbfa53..e88ea2d1 100644
|
||
|
--- a/lib/gs-plugin-loader.h
|
||
|
+++ b/lib/gs-plugin-loader.h
|
||
|
@@ -1,7 +1,7 @@
|
||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||
|
*
|
||
|
* Copyright (C) 2007-2017 Richard Hughes <richard@hughsie.com>
|
||
|
- * Copyright (C) 2015 Kalev Lember <klember@redhat.com>
|
||
|
+ * Copyright (C) 2015-2020 Kalev Lember <klember@redhat.com>
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
@@ -31,6 +31,11 @@ struct _GsPluginLoaderClass
|
||
|
void (*pending_apps_changed) (GsPluginLoader *plugin_loader);
|
||
|
void (*updates_changed) (GsPluginLoader *plugin_loader);
|
||
|
void (*reload) (GsPluginLoader *plugin_loader);
|
||
|
+ void (*basic_auth_start) (GsPluginLoader *plugin_loader,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GCallback callback,
|
||
|
+ gpointer user_data);
|
||
|
};
|
||
|
|
||
|
GsPluginLoader *gs_plugin_loader_new (void);
|
||
|
diff --git a/lib/gs-plugin.c b/lib/gs-plugin.c
|
||
|
index 5aed1058..3f63fa97 100644
|
||
|
--- a/lib/gs-plugin.c
|
||
|
+++ b/lib/gs-plugin.c
|
||
|
@@ -1,7 +1,7 @@
|
||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||
|
*
|
||
|
* Copyright (C) 2013-2016 Richard Hughes <richard@hughsie.com>
|
||
|
- * Copyright (C) 2014-2018 Kalev Lember <klember@redhat.com>
|
||
|
+ * Copyright (C) 2014-2020 Kalev Lember <klember@redhat.com>
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
@@ -87,6 +87,7 @@ enum {
|
||
|
SIGNAL_RELOAD,
|
||
|
SIGNAL_REPORT_EVENT,
|
||
|
SIGNAL_ALLOW_UPDATES,
|
||
|
+ SIGNAL_BASIC_AUTH_START,
|
||
|
SIGNAL_LAST
|
||
|
};
|
||
|
|
||
|
@@ -851,6 +852,64 @@ gs_plugin_status_update (GsPlugin *plugin, GsApp *app, GsPluginStatus status)
|
||
|
g_source_attach (idle_source, NULL);
|
||
|
}
|
||
|
|
||
|
+typedef struct {
|
||
|
+ GsPlugin *plugin;
|
||
|
+ gchar *remote;
|
||
|
+ gchar *realm;
|
||
|
+ GCallback callback;
|
||
|
+ gpointer user_data;
|
||
|
+} GsPluginBasicAuthHelper;
|
||
|
+
|
||
|
+static gboolean
|
||
|
+gs_plugin_basic_auth_start_cb (gpointer user_data)
|
||
|
+{
|
||
|
+ GsPluginBasicAuthHelper *helper = user_data;
|
||
|
+ g_signal_emit (helper->plugin,
|
||
|
+ signals[SIGNAL_BASIC_AUTH_START], 0,
|
||
|
+ helper->remote,
|
||
|
+ helper->realm,
|
||
|
+ helper->callback,
|
||
|
+ helper->user_data);
|
||
|
+ g_free (helper->remote);
|
||
|
+ g_free (helper->realm);
|
||
|
+ g_slice_free (GsPluginBasicAuthHelper, helper);
|
||
|
+ return FALSE;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * gs_plugin_basic_auth_start:
|
||
|
+ * @plugin: a #GsPlugin
|
||
|
+ * @remote: a string
|
||
|
+ * @realm: a string
|
||
|
+ * @callback: callback to invoke to submit the user/password
|
||
|
+ * @user_data: callback data to pass to the callback
|
||
|
+ *
|
||
|
+ * Emit the basic-auth-start signal in the main thread.
|
||
|
+ *
|
||
|
+ * Since: 3.38
|
||
|
+ **/
|
||
|
+void
|
||
|
+gs_plugin_basic_auth_start (GsPlugin *plugin,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GCallback callback,
|
||
|
+ gpointer user_data)
|
||
|
+{
|
||
|
+ GsPluginBasicAuthHelper *helper;
|
||
|
+ g_autoptr(GSource) idle_source = NULL;
|
||
|
+
|
||
|
+ helper = g_slice_new0 (GsPluginBasicAuthHelper);
|
||
|
+ helper->plugin = plugin;
|
||
|
+ helper->remote = g_strdup (remote);
|
||
|
+ helper->realm = g_strdup (realm);
|
||
|
+ helper->callback = callback;
|
||
|
+ helper->user_data = user_data;
|
||
|
+
|
||
|
+ idle_source = g_idle_source_new ();
|
||
|
+ g_source_set_callback (idle_source, gs_plugin_basic_auth_start_cb, helper, NULL);
|
||
|
+ g_source_attach (idle_source, NULL);
|
||
|
+}
|
||
|
+
|
||
|
static gboolean
|
||
|
gs_plugin_app_launch_cb (gpointer user_data)
|
||
|
{
|
||
|
@@ -1959,6 +2018,13 @@ gs_plugin_class_init (GsPluginClass *klass)
|
||
|
G_STRUCT_OFFSET (GsPluginClass, allow_updates),
|
||
|
NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
|
||
|
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
||
|
+
|
||
|
+ signals [SIGNAL_BASIC_AUTH_START] =
|
||
|
+ g_signal_new ("basic-auth-start",
|
||
|
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
|
||
|
+ G_STRUCT_OFFSET (GsPluginClass, basic_auth_start),
|
||
|
+ NULL, NULL, g_cclosure_marshal_generic,
|
||
|
+ G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
diff --git a/lib/gs-plugin.h b/lib/gs-plugin.h
|
||
|
index 7dd2d864..d07afd3b 100644
|
||
|
--- a/lib/gs-plugin.h
|
||
|
+++ b/lib/gs-plugin.h
|
||
|
@@ -1,6 +1,7 @@
|
||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||
|
*
|
||
|
* Copyright (C) 2012-2016 Richard Hughes <richard@hughsie.com>
|
||
|
+ * Copyright (C) 2020 Kalev Lember <klember@redhat.com>
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
@@ -37,7 +38,12 @@ struct _GsPluginClass
|
||
|
GsPluginEvent *event);
|
||
|
void (*allow_updates) (GsPlugin *plugin,
|
||
|
gboolean allow_updates);
|
||
|
- gpointer padding[26];
|
||
|
+ void (*basic_auth_start) (GsPlugin *plugin,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GCallback callback,
|
||
|
+ gpointer user_data);
|
||
|
+ gpointer padding[25];
|
||
|
};
|
||
|
|
||
|
typedef struct GsPluginData GsPluginData;
|
||
|
@@ -116,5 +122,10 @@ void gs_plugin_report_event (GsPlugin *plugin,
|
||
|
void gs_plugin_set_allow_updates (GsPlugin *plugin,
|
||
|
gboolean allow_updates);
|
||
|
gboolean gs_plugin_get_network_available (GsPlugin *plugin);
|
||
|
+void gs_plugin_basic_auth_start (GsPlugin *plugin,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GCallback callback,
|
||
|
+ gpointer user_data);
|
||
|
|
||
|
G_END_DECLS
|
||
|
diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c
|
||
|
index 4d6a81ba..2518025d 100644
|
||
|
--- a/plugins/flatpak/gs-plugin-flatpak.c
|
||
|
+++ b/plugins/flatpak/gs-plugin-flatpak.c
|
||
|
@@ -2,7 +2,7 @@
|
||
|
*
|
||
|
* Copyright (C) 2016 Joaquim Rocha <jrocha@endlessm.com>
|
||
|
* Copyright (C) 2016-2018 Richard Hughes <richard@hughsie.com>
|
||
|
- * Copyright (C) 2017-2018 Kalev Lember <klember@redhat.com>
|
||
|
+ * Copyright (C) 2017-2020 Kalev Lember <klember@redhat.com>
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
@@ -456,6 +456,55 @@ _group_apps_by_installation (GsPlugin *plugin,
|
||
|
return g_steal_pointer (&applist_by_flatpaks);
|
||
|
}
|
||
|
|
||
|
+#if FLATPAK_CHECK_VERSION(1,6,0)
|
||
|
+typedef struct {
|
||
|
+ FlatpakTransaction *transaction;
|
||
|
+ guint id;
|
||
|
+} BasicAuthData;
|
||
|
+
|
||
|
+static void
|
||
|
+basic_auth_data_free (BasicAuthData *data)
|
||
|
+{
|
||
|
+ g_object_unref (data->transaction);
|
||
|
+ g_slice_free (BasicAuthData, data);
|
||
|
+}
|
||
|
+
|
||
|
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(BasicAuthData, basic_auth_data_free)
|
||
|
+
|
||
|
+static void
|
||
|
+_basic_auth_cb (const gchar *user, const gchar *password, gpointer user_data)
|
||
|
+{
|
||
|
+ g_autoptr(BasicAuthData) data = user_data;
|
||
|
+
|
||
|
+ g_debug ("Submitting basic auth data");
|
||
|
+
|
||
|
+ /* NULL user aborts the basic auth request */
|
||
|
+ flatpak_transaction_complete_basic_auth (data->transaction, data->id, user, password, NULL /* options */);
|
||
|
+}
|
||
|
+
|
||
|
+static gboolean
|
||
|
+_basic_auth_start (FlatpakTransaction *transaction,
|
||
|
+ const char *remote,
|
||
|
+ const char *realm,
|
||
|
+ GVariant *options,
|
||
|
+ guint id,
|
||
|
+ GsPlugin *plugin)
|
||
|
+{
|
||
|
+ BasicAuthData *data;
|
||
|
+
|
||
|
+ if (!gs_plugin_has_flags (plugin, GS_PLUGIN_FLAGS_INTERACTIVE))
|
||
|
+ return FALSE;
|
||
|
+
|
||
|
+ data = g_slice_new0 (BasicAuthData);
|
||
|
+ data->transaction = g_object_ref (transaction);
|
||
|
+ data->id = id;
|
||
|
+
|
||
|
+ g_debug ("Login required remote %s (realm %s)\n", remote, realm);
|
||
|
+ gs_plugin_basic_auth_start (plugin, remote, realm, G_CALLBACK (_basic_auth_cb), data);
|
||
|
+ return TRUE;
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
static FlatpakTransaction *
|
||
|
_build_transaction (GsPlugin *plugin, GsFlatpak *flatpak,
|
||
|
GCancellable *cancellable, GError **error)
|
||
|
@@ -491,6 +540,10 @@ _build_transaction (GsPlugin *plugin, GsFlatpak *flatpak,
|
||
|
/* connect up signals */
|
||
|
g_signal_connect (transaction, "ref-to-app",
|
||
|
G_CALLBACK (_ref_to_app), plugin);
|
||
|
+#if FLATPAK_CHECK_VERSION(1,6,0)
|
||
|
+ g_signal_connect (transaction, "basic-auth-start",
|
||
|
+ G_CALLBACK (_basic_auth_start), plugin);
|
||
|
+#endif
|
||
|
|
||
|
/* use system installations as dependency sources for user installations */
|
||
|
flatpak_transaction_add_default_dependency_sources (transaction);
|
||
|
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
||
|
index 20721c4a..a44a6ad3 100644
|
||
|
--- a/po/POTFILES.in
|
||
|
+++ b/po/POTFILES.in
|
||
|
@@ -10,6 +10,8 @@ src/gs-app-row.c
|
||
|
src/gs-app-row.ui
|
||
|
src/gs-app-tile.c
|
||
|
src/gs-app-tile.ui
|
||
|
+src/gs-basic-auth-dialog.c
|
||
|
+src/gs-basic-auth-dialog.ui
|
||
|
lib/gs-category.c
|
||
|
src/gs-category-page.c
|
||
|
src/gs-category-page.ui
|
||
|
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
|
||
|
index 3eaabca2..459ecf82 100644
|
||
|
--- a/src/gnome-software.gresource.xml
|
||
|
+++ b/src/gnome-software.gresource.xml
|
||
|
@@ -4,6 +4,7 @@
|
||
|
<file preprocess="xml-stripblanks">gnome-software.ui</file>
|
||
|
<file preprocess="xml-stripblanks">gs-app-addon-row.ui</file>
|
||
|
<file preprocess="xml-stripblanks">gs-app-row.ui</file>
|
||
|
+ <file preprocess="xml-stripblanks">gs-basic-auth-dialog.ui</file>
|
||
|
<file preprocess="xml-stripblanks">gs-category-page.ui</file>
|
||
|
<file preprocess="xml-stripblanks">gs-category-tile.ui</file>
|
||
|
<file preprocess="xml-stripblanks">gs-details-page.ui</file>
|
||
|
diff --git a/src/gs-basic-auth-dialog.c b/src/gs-basic-auth-dialog.c
|
||
|
new file mode 100644
|
||
|
index 00000000..c690a327
|
||
|
--- /dev/null
|
||
|
+++ b/src/gs-basic-auth-dialog.c
|
||
|
@@ -0,0 +1,130 @@
|
||
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||
|
+ *
|
||
|
+ * Copyright (C) 2020 Kalev Lember <klember@redhat.com>
|
||
|
+ *
|
||
|
+ * SPDX-License-Identifier: GPL-2.0+
|
||
|
+ */
|
||
|
+
|
||
|
+#include "config.h"
|
||
|
+
|
||
|
+#include "gs-basic-auth-dialog.h"
|
||
|
+
|
||
|
+#include <glib.h>
|
||
|
+#include <glib/gi18n.h>
|
||
|
+#include <gtk/gtk.h>
|
||
|
+
|
||
|
+struct _GsBasicAuthDialog
|
||
|
+{
|
||
|
+ GtkDialog parent_instance;
|
||
|
+
|
||
|
+ GsBasicAuthCallback callback;
|
||
|
+ gpointer callback_data;
|
||
|
+
|
||
|
+ /* template widgets */
|
||
|
+ GtkButton *login_button;
|
||
|
+ GtkLabel *description_label;
|
||
|
+ GtkEntry *user_entry;
|
||
|
+ GtkEntry *password_entry;
|
||
|
+};
|
||
|
+
|
||
|
+G_DEFINE_TYPE (GsBasicAuthDialog, gs_basic_auth_dialog, GTK_TYPE_DIALOG)
|
||
|
+
|
||
|
+static void
|
||
|
+cancel_button_clicked_cb (GsBasicAuthDialog *dialog)
|
||
|
+{
|
||
|
+ /* abort the basic auth request */
|
||
|
+ dialog->callback (NULL, NULL, dialog->callback_data);
|
||
|
+
|
||
|
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+login_button_clicked_cb (GsBasicAuthDialog *dialog)
|
||
|
+{
|
||
|
+ const gchar *user;
|
||
|
+ const gchar *password;
|
||
|
+
|
||
|
+ user = gtk_entry_get_text (dialog->user_entry);
|
||
|
+ password = gtk_entry_get_text (dialog->password_entry);
|
||
|
+
|
||
|
+ /* submit the user/password to basic auth */
|
||
|
+ dialog->callback (user, password, dialog->callback_data);
|
||
|
+
|
||
|
+ gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+dialog_validate (GsBasicAuthDialog *dialog)
|
||
|
+{
|
||
|
+ const gchar *user;
|
||
|
+ const gchar *password;
|
||
|
+ gboolean valid_user;
|
||
|
+ gboolean valid_password;
|
||
|
+
|
||
|
+ /* require user */
|
||
|
+ user = gtk_entry_get_text (dialog->user_entry);
|
||
|
+ valid_user = user != NULL && strlen (user) != 0;
|
||
|
+
|
||
|
+ /* require password */
|
||
|
+ password = gtk_entry_get_text (dialog->password_entry);
|
||
|
+ valid_password = password != NULL && strlen (password) != 0;
|
||
|
+
|
||
|
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->login_button), valid_user && valid_password);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+update_description (GsBasicAuthDialog *dialog, const gchar *remote, const gchar *realm)
|
||
|
+{
|
||
|
+ g_autofree gchar *description = NULL;
|
||
|
+
|
||
|
+ /* TRANSLATORS: This is a description for entering user/password */
|
||
|
+ description = g_strdup_printf (_("Login required remote %s (realm %s)"),
|
||
|
+ remote, realm);
|
||
|
+ gtk_label_set_text (dialog->description_label, description);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+gs_basic_auth_dialog_init (GsBasicAuthDialog *dialog)
|
||
|
+{
|
||
|
+ gtk_widget_init_template (GTK_WIDGET (dialog));
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+gs_basic_auth_dialog_class_init (GsBasicAuthDialogClass *klass)
|
||
|
+{
|
||
|
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||
|
+
|
||
|
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-basic-auth-dialog.ui");
|
||
|
+
|
||
|
+ gtk_widget_class_bind_template_child (widget_class, GsBasicAuthDialog, login_button);
|
||
|
+ gtk_widget_class_bind_template_child (widget_class, GsBasicAuthDialog, description_label);
|
||
|
+ gtk_widget_class_bind_template_child (widget_class, GsBasicAuthDialog, user_entry);
|
||
|
+ gtk_widget_class_bind_template_child (widget_class, GsBasicAuthDialog, password_entry);
|
||
|
+
|
||
|
+ gtk_widget_class_bind_template_callback (widget_class, dialog_validate);
|
||
|
+ gtk_widget_class_bind_template_callback (widget_class, cancel_button_clicked_cb);
|
||
|
+ gtk_widget_class_bind_template_callback (widget_class, login_button_clicked_cb);
|
||
|
+}
|
||
|
+
|
||
|
+GtkWidget *
|
||
|
+gs_basic_auth_dialog_new (GtkWindow *parent,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GsBasicAuthCallback callback,
|
||
|
+ gpointer callback_data)
|
||
|
+{
|
||
|
+ GsBasicAuthDialog *dialog;
|
||
|
+
|
||
|
+ dialog = g_object_new (GS_TYPE_BASIC_AUTH_DIALOG,
|
||
|
+ "use-header-bar", TRUE,
|
||
|
+ "transient-for", parent,
|
||
|
+ "modal", TRUE,
|
||
|
+ NULL);
|
||
|
+ dialog->callback = callback;
|
||
|
+ dialog->callback_data = callback_data;
|
||
|
+
|
||
|
+ update_description (dialog, remote, realm);
|
||
|
+ dialog_validate (dialog);
|
||
|
+
|
||
|
+ return GTK_WIDGET (dialog);
|
||
|
+}
|
||
|
diff --git a/src/gs-basic-auth-dialog.h b/src/gs-basic-auth-dialog.h
|
||
|
new file mode 100644
|
||
|
index 00000000..ec5f1d03
|
||
|
--- /dev/null
|
||
|
+++ b/src/gs-basic-auth-dialog.h
|
||
|
@@ -0,0 +1,28 @@
|
||
|
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||
|
+ *
|
||
|
+ * Copyright (C) 2020 Kalev Lember <klember@redhat.com>
|
||
|
+ *
|
||
|
+ * SPDX-License-Identifier: GPL-2.0+
|
||
|
+ */
|
||
|
+
|
||
|
+#pragma once
|
||
|
+
|
||
|
+#include <gtk/gtk.h>
|
||
|
+
|
||
|
+#include "gnome-software-private.h"
|
||
|
+
|
||
|
+G_BEGIN_DECLS
|
||
|
+
|
||
|
+typedef void (*GsBasicAuthCallback) (const gchar *user, const gchar *password, gpointer callback_data);
|
||
|
+
|
||
|
+#define GS_TYPE_BASIC_AUTH_DIALOG (gs_basic_auth_dialog_get_type ())
|
||
|
+
|
||
|
+G_DECLARE_FINAL_TYPE (GsBasicAuthDialog, gs_basic_auth_dialog, GS, BASIC_AUTH_DIALOG, GtkDialog)
|
||
|
+
|
||
|
+GtkWidget *gs_basic_auth_dialog_new (GtkWindow *parent,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GsBasicAuthCallback callback,
|
||
|
+ gpointer callback_data);
|
||
|
+
|
||
|
+G_END_DECLS
|
||
|
diff --git a/src/gs-basic-auth-dialog.ui b/src/gs-basic-auth-dialog.ui
|
||
|
new file mode 100644
|
||
|
index 00000000..339e831d
|
||
|
--- /dev/null
|
||
|
+++ b/src/gs-basic-auth-dialog.ui
|
||
|
@@ -0,0 +1,203 @@
|
||
|
+<?xml version="1.0" encoding="UTF-8"?>
|
||
|
+<interface>
|
||
|
+ <template class="GsBasicAuthDialog" parent="GtkDialog">
|
||
|
+ <property name="can_focus">False</property>
|
||
|
+ <property name="border_width">5</property>
|
||
|
+ <property name="resizable">False</property>
|
||
|
+ <property name="modal">True</property>
|
||
|
+ <property name="destroy_with_parent">True</property>
|
||
|
+ <property name="type_hint">dialog</property>
|
||
|
+ <property name="title" translatable="yes">Login Required</property>
|
||
|
+ <property name="use_header_bar">1</property>
|
||
|
+ <child internal-child="headerbar">
|
||
|
+ <object class="GtkHeaderBar">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">False</property>
|
||
|
+ <property name="show_close_button">False</property>
|
||
|
+ <child>
|
||
|
+ <object class="GtkButton" id="cancel_button">
|
||
|
+ <property name="label" translatable="yes">_Cancel</property>
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">True</property>
|
||
|
+ <property name="can_default">True</property>
|
||
|
+ <property name="receives_default">True</property>
|
||
|
+ <property name="use_action_appearance">False</property>
|
||
|
+ <property name="use_underline">True</property>
|
||
|
+ <property name="valign">center</property>
|
||
|
+ <signal name="clicked" handler="cancel_button_clicked_cb" object="GsBasicAuthDialog" swapped="yes"/>
|
||
|
+ <style>
|
||
|
+ <class name="text-button"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="pack_type">start</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ <child>
|
||
|
+ <object class="GtkButton" id="login_button">
|
||
|
+ <property name="label" translatable="yes">_Login</property>
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">True</property>
|
||
|
+ <property name="can_default">True</property>
|
||
|
+ <property name="has_default">True</property>
|
||
|
+ <property name="receives_default">True</property>
|
||
|
+ <property name="use_action_appearance">False</property>
|
||
|
+ <property name="use_underline">True</property>
|
||
|
+ <property name="valign">center</property>
|
||
|
+ <signal name="clicked" handler="login_button_clicked_cb" object="GsBasicAuthDialog" swapped="yes"/>
|
||
|
+ <style>
|
||
|
+ <class name="text-button"/>
|
||
|
+ <class name="suggested-action"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="pack_type">end</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ </object>
|
||
|
+ </child>
|
||
|
+ <child internal-child="vbox">
|
||
|
+ <object class="GtkBox">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">False</property>
|
||
|
+ <property name="orientation">vertical</property>
|
||
|
+ <child>
|
||
|
+ <object class="GtkGrid">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">False</property>
|
||
|
+ <property name="hexpand">True</property>
|
||
|
+ <property name="row_spacing">8</property>
|
||
|
+ <property name="column_spacing">6</property>
|
||
|
+ <property name="border_width">20</property>
|
||
|
+ <property name="margin_end">20</property>
|
||
|
+ <child>
|
||
|
+ <object class="GtkLabel" id="description_label">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">False</property>
|
||
|
+ <property name="wrap">True</property>
|
||
|
+ <property name="wrap_mode">word-char</property>
|
||
|
+ <property name="margin_bottom">20</property>
|
||
|
+ <property name="max_width_chars">55</property>
|
||
|
+ <property name="xalign">0</property>
|
||
|
+ <style>
|
||
|
+ <class name="dim-label"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="left_attach">0</property>
|
||
|
+ <property name="top_attach">0</property>
|
||
|
+ <property name="width">2</property>
|
||
|
+ <property name="height">1</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ <child>
|
||
|
+ <object class="GtkLabel" id="user_label">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">False</property>
|
||
|
+ <property name="xalign">1</property>
|
||
|
+ <property name="label" translatable="yes">_User</property>
|
||
|
+ <property name="use_underline">True</property>
|
||
|
+ <property name="mnemonic_widget">user_entry</property>
|
||
|
+ <property name="margin_start">20</property>
|
||
|
+ <style>
|
||
|
+ <class name="dim-label"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="left_attach">0</property>
|
||
|
+ <property name="top_attach">3</property>
|
||
|
+ <property name="width">1</property>
|
||
|
+ <property name="height">1</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ <child>
|
||
|
+ <object class="GtkLabel" id="password_label">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">False</property>
|
||
|
+ <property name="xalign">1</property>
|
||
|
+ <property name="label" translatable="yes">_Password</property>
|
||
|
+ <property name="use_underline">True</property>
|
||
|
+ <property name="mnemonic_widget">password_entry</property>
|
||
|
+ <property name="margin_start">20</property>
|
||
|
+ <style>
|
||
|
+ <class name="dim-label"/>
|
||
|
+ </style>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="left_attach">0</property>
|
||
|
+ <property name="top_attach">4</property>
|
||
|
+ <property name="width">1</property>
|
||
|
+ <property name="height">1</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ <child>
|
||
|
+ <object class="GtkEntry" id="user_entry">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">True</property>
|
||
|
+ <property name="has_focus">True</property>
|
||
|
+ <property name="hexpand">True</property>
|
||
|
+ <property name="invisible_char">●</property>
|
||
|
+ <property name="activates_default">True</property>
|
||
|
+ <property name="invisible_char_set">True</property>
|
||
|
+ <property name="input_purpose">password</property>
|
||
|
+ <signal name="changed" handler="dialog_validate" object="GsBasicAuthDialog" swapped="yes"/>
|
||
|
+ <signal name="activate" handler="dialog_validate" object="GsBasicAuthDialog" swapped="yes"/>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="left_attach">1</property>
|
||
|
+ <property name="top_attach">3</property>
|
||
|
+ <property name="width">1</property>
|
||
|
+ <property name="height">1</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ <child>
|
||
|
+ <object class="GtkEntry" id="password_entry">
|
||
|
+ <property name="visible">True</property>
|
||
|
+ <property name="can_focus">True</property>
|
||
|
+ <property name="hexpand">True</property>
|
||
|
+ <property name="visibility">False</property>
|
||
|
+ <property name="invisible_char">●</property>
|
||
|
+ <property name="activates_default">True</property>
|
||
|
+ <property name="invisible_char_set">True</property>
|
||
|
+ <property name="input_purpose">password</property>
|
||
|
+ <signal name="changed" handler="dialog_validate" object="GsBasicAuthDialog" swapped="yes"/>
|
||
|
+ <signal name="activate" handler="dialog_validate" object="GsBasicAuthDialog" swapped="yes"/>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="left_attach">1</property>
|
||
|
+ <property name="top_attach">4</property>
|
||
|
+ <property name="width">1</property>
|
||
|
+ <property name="height">1</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ </object>
|
||
|
+ <packing>
|
||
|
+ <property name="expand">False</property>
|
||
|
+ <property name="fill">True</property>
|
||
|
+ <property name="position">0</property>
|
||
|
+ </packing>
|
||
|
+ </child>
|
||
|
+ </object>
|
||
|
+ </child>
|
||
|
+ </template>
|
||
|
+ <object class="GtkSizeGroup">
|
||
|
+ <widgets>
|
||
|
+ <widget name="user_label"/>
|
||
|
+ <widget name="password_label"/>
|
||
|
+ </widgets>
|
||
|
+ </object>
|
||
|
+ <object class="GtkSizeGroup">
|
||
|
+ <widgets>
|
||
|
+ <widget name="user_entry"/>
|
||
|
+ <widget name="password_entry"/>
|
||
|
+ </widgets>
|
||
|
+ </object>
|
||
|
+ <object class="GtkSizeGroup">
|
||
|
+ <property name="mode">horizontal</property>
|
||
|
+ <widgets>
|
||
|
+ <widget name="login_button"/>
|
||
|
+ <widget name="cancel_button"/>
|
||
|
+ </widgets>
|
||
|
+ </object>
|
||
|
+</interface>
|
||
|
diff --git a/src/gs-shell.c b/src/gs-shell.c
|
||
|
index 009776ad..41503cf8 100644
|
||
|
--- a/src/gs-shell.c
|
||
|
+++ b/src/gs-shell.c
|
||
|
@@ -2,7 +2,7 @@
|
||
|
*
|
||
|
* Copyright (C) 2013-2017 Richard Hughes <richard@hughsie.com>
|
||
|
* Copyright (C) 2013 Matthias Clasen <mclasen@redhat.com>
|
||
|
- * Copyright (C) 2014-2018 Kalev Lember <klember@redhat.com>
|
||
|
+ * Copyright (C) 2014-2020 Kalev Lember <klember@redhat.com>
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0+
|
||
|
*/
|
||
|
@@ -18,6 +18,7 @@
|
||
|
|
||
|
#include "gs-common.h"
|
||
|
#include "gs-shell.h"
|
||
|
+#include "gs-basic-auth-dialog.h"
|
||
|
#include "gs-details-page.h"
|
||
|
#include "gs-installed-page.h"
|
||
|
#include "gs-metered-data-dialog.h"
|
||
|
@@ -362,6 +363,25 @@ scheduler_ready_cb (GObject *source_object,
|
||
|
}
|
||
|
#endif /* HAVE_MOGWAI */
|
||
|
|
||
|
+static void
|
||
|
+gs_shell_basic_auth_start_cb (GsPluginLoader *plugin_loader,
|
||
|
+ const gchar *remote,
|
||
|
+ const gchar *realm,
|
||
|
+ GsBasicAuthCallback callback,
|
||
|
+ gpointer callback_data,
|
||
|
+ GsShell *shell)
|
||
|
+{
|
||
|
+ GsShellPrivate *priv = gs_shell_get_instance_private (shell);
|
||
|
+ GtkWidget *dialog;
|
||
|
+
|
||
|
+ dialog = gs_basic_auth_dialog_new (priv->main_window, remote, realm, callback, callback_data);
|
||
|
+ gs_shell_modal_dialog_present (shell, GTK_DIALOG (dialog));
|
||
|
+
|
||
|
+ /* just destroy */
|
||
|
+ g_signal_connect_swapped (dialog, "response",
|
||
|
+ G_CALLBACK (gtk_widget_destroy), dialog);
|
||
|
+}
|
||
|
+
|
||
|
static void
|
||
|
free_back_entry (BackEntry *entry)
|
||
|
{
|
||
|
@@ -2126,6 +2146,9 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
|
||
|
g_signal_connect_object (priv->plugin_loader, "notify::network-metered",
|
||
|
G_CALLBACK (gs_shell_network_metered_notify_cb),
|
||
|
shell, 0);
|
||
|
+ g_signal_connect_object (priv->plugin_loader, "basic-auth-start",
|
||
|
+ G_CALLBACK (gs_shell_basic_auth_start_cb),
|
||
|
+ shell, 0);
|
||
|
priv->cancellable = g_object_ref (cancellable);
|
||
|
|
||
|
priv->settings = g_settings_new ("org.gnome.software");
|
||
|
diff --git a/src/meson.build b/src/meson.build
|
||
|
index cbd0a511..6581e77c 100644
|
||
|
--- a/src/meson.build
|
||
|
+++ b/src/meson.build
|
||
|
@@ -20,6 +20,7 @@ gnome_software_sources = [
|
||
|
'gs-application.c',
|
||
|
'gs-app-row.c',
|
||
|
'gs-app-tile.c',
|
||
|
+ 'gs-basic-auth-dialog.c',
|
||
|
'gs-category-page.c',
|
||
|
'gs-category-tile.c',
|
||
|
'gs-common.c',
|
||
|
--
|
||
|
2.26.2
|
||
|
|