[gnome-control-center/wip/add-account: 4/7] Populate the domain drop down with enterprise domains



commit f0b44a9a8d9181dd67521d38a7613c63148a5a10
Author: Stef Walter <stefw gnome org>
Date:   Thu May 31 17:06:42 2012 +0200

    Populate the domain drop down with enterprise domains
    
     * Initial interaction with realmd

 panels/user-accounts/Makefile.am                   |   15 ++-
 panels/user-accounts/data/Makefile.am              |    1 +
 panels/user-accounts/data/account-dialog.ui        |    5 +-
 .../user-accounts/data/org.freedesktop.realmd.xml  |  126 ++++++++++++++
 panels/user-accounts/um-account-dialog.c           |  181 +++++++++++++++++++-
 5 files changed, 316 insertions(+), 12 deletions(-)
---
diff --git a/panels/user-accounts/Makefile.am b/panels/user-accounts/Makefile.am
index f23d8d8..d98b5fb 100644
--- a/panels/user-accounts/Makefile.am
+++ b/panels/user-accounts/Makefile.am
@@ -25,6 +25,10 @@ if BUILD_CHEESE
 AM_CPPFLAGS += $(CHEESE_CFLAGS)
 endif
 
+BUILT_SOURCES = \
+	um-realm-generated.c \
+	um-realm-generated.h
+
 libuser_accounts_la_SOURCES =		\
 	um-account-type.h		\
 	um-account-type.c 		\
@@ -55,7 +59,8 @@ libuser_accounts_la_SOURCES =		\
 	um-editable-combo.c		\
 	um-user-panel.h 		\
 	um-user-panel.c			\
-	um-user-module.c
+	um-user-module.c		\
+	$(BUILT_SOURCES)
 
 libuser_accounts_la_LIBADD = 		\
 	$(PANEL_LIBS)			\
@@ -71,6 +76,11 @@ endif
 
 libuser_accounts_la_LDFLAGS = $(PANEL_LDFLAGS)
 
+um-realm-generated.c: $(srcdir)/data/org.freedesktop.realmd.xml
+	$(AM_V_GEN) gdbus-codegen --interface-prefix org.freedesktop.realmd. \
+		--generate-c-code um-realm-generated --c-namespace UmRealm $<
+um-realm-generated.h: um-realm-generated.c
+
 frob_account_dialog_SOURCES = \
 	frob-account-dialog.c \
 	um-account-dialog.h \
@@ -80,7 +90,8 @@ frob_account_dialog_SOURCES = \
 	um-user-manager.h \
 	um-user-manager.c \
 	um-utils.h \
-	um-utils.c
+	um-utils.c \
+	$(BUILT_SOURCES)
 
 frob_account_dialog_LDADD = \
 	$(libuser_accounts_la_LIBADD)
diff --git a/panels/user-accounts/data/Makefile.am b/panels/user-accounts/data/Makefile.am
index dbc17c6..d03d14b 100644
--- a/panels/user-accounts/data/Makefile.am
+++ b/panels/user-accounts/data/Makefile.am
@@ -16,6 +16,7 @@ desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
 
 EXTRA_DIST = 					\
 	gnome-user-accounts-panel.desktop.in.in	\
+	org.freedesktop.realmd.xml		\
 	$(ui_DATA)
 
 CLEANFILES =					\
diff --git a/panels/user-accounts/data/account-dialog.ui b/panels/user-accounts/data/account-dialog.ui
index 217ad81..78ab9eb 100644
--- a/panels/user-accounts/data/account-dialog.ui
+++ b/panels/user-accounts/data/account-dialog.ui
@@ -271,15 +271,14 @@
                 <property name="orientation">vertical</property>
                 <property name="spacing">3</property>
                 <child>
-                  <object class="GtkComboBoxText" id="enterprise-domain">
+                  <object class="GtkComboBox" id="enterprise-domain">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="hexpand">True</property>
                     <property name="has_entry">True</property>
                     <property name="entry_text_column">0</property>
-                    <property name="id_column">1</property>
                     <child internal-child="entry">
-                      <object class="GtkEntry" id="enterprise-domain-entry">
+                      <object class="GtkEntry" id="combobox-entry">
                         <property name="can_focus">True</property>
                       </object>
                     </child>
diff --git a/panels/user-accounts/data/org.freedesktop.realmd.xml b/panels/user-accounts/data/org.freedesktop.realmd.xml
new file mode 100644
index 0000000..d929d2c
--- /dev/null
+++ b/panels/user-accounts/data/org.freedesktop.realmd.xml
@@ -0,0 +1,126 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+
+<node name="/">
+	<!--
+	 * Global interface implemented by realmd. Allows listing of providers
+	 * and discovering which one is relevant for a given domain.
+	 *
+	 * This is implemented by individual providers, but is aggregated
+	 * globally at the system bus name 'org.freedesktop.realmd' with the
+	 * object path '/org/freedesktop/realmd'
+	-->
+	<interface name="org.freedesktop.realmd.Provider">
+
+		<!--
+		 * A list of known, enrolled or discovered realms.
+		 * Each realm is a DBus object and is represeted by a:
+		 *   s: DBus bus name of the realm
+		 *   o: DBus object path of the realm
+		 *   s: DBus interface name, like 'ofr.KerberosRealm' (below)
+		-->
+		<property name="Realms" type="a(sos)" access="read"/>
+
+		<!--
+		 * Discover whether a string represents a realm that a provider
+		 * can enroll or otherwise use.
+		-->
+		<method name="Discover">
+			<!-- The input string -->
+			<arg name="string" type="s" direction="in"/>
+
+			<!-- Returned match relevance -->
+			<arg name="relevance" type="i" direction="out"/>
+
+			<!-- The realm objects: bus name, object path, interface -->
+			<arg name="realm" type="a(sos)" direction="out"/>
+		</method>
+	</interface>
+
+	<!--
+	 * This interface is implemented by Providers and Realms to provide
+	 * additional information when an long running operation is happening
+	 *
+	 * In particular you can connect to the "Diagnostics" signal when
+	 * during an enroll or unenroll to get details.
+	-->
+	<interface name="org.freedesktop.realmd.Diagnostics">
+		<signal name="Diagnostics">
+			<arg name="data" type="s"/>
+		</signal>
+	</interface>
+
+	<!--
+	 * This interface is implemented by Kerberos realms.
+	-->
+	<interface name="org.freedesktop.realmd.KerberosRealm">
+
+		<!--
+		 * The kerberos realm name. Usually capitalized.
+		-->
+		<property name="Name" type="s" access="read"/>
+
+		<!--
+		 * The DNS domain name for this realm.
+		-->
+		<property name="Domain" type="s" access="read"/>
+
+		<!--
+		 * The format for user logins when this realm is enrolled.
+		 * This property may not be valid unless machine is enrolled
+		 * in this realm. The format contains a %s where the user name
+		 * goes eg: "DOMAIN\%s"
+		-->
+		<property name="UserFormat" type="s" access="read"/>
+
+		<!--
+		 * Whether the machine is enrolled in this realm or not.
+		-->
+		<property name="Enrolled" type="b" access="read"/>
+
+		<!--
+		 * Enroll the machine in this realm using an administrative
+		 * account and a password.
+		-->
+		<method name="EnrollWithPassword">
+			<arg name="principal" type="s" direction="in"/>
+			<arg name="password" type="s" direction="in"/>
+			<arg name="options" type="a{sv}" direction="in"/>
+		</method>
+
+		<!--
+		 * Enroll the machine in this realm using kerberos cached
+		 * administrative credentials.
+		-->
+		<method name="EnrollWithCredentialCache">
+			<!-- The contents of a kerberos cache file containing administrative credentials -->
+			<arg name="kerberos_cache" type="ay" direction="in">
+				<annotation name="org.gtk.GDBus.C.ForceGVariant" value="yup"/>
+			</arg>
+			<arg name="options" type="a{sv}" direction="in"/>
+		</method>
+
+		<!--
+		 * Unenroll the machine from this realm using an administrative
+		 * account and a password.
+		-->
+		<method name="UnenrollWithPassword">
+			<arg name="principal" type="s" direction="in"/>
+			<arg name="password" type="s" direction="in"/>
+			<arg name="options" type="a{sv}" direction="in"/>
+		</method>
+
+		<!--
+		 * Unenroll the machine from this realm using a kerberos cached
+		 * administrative credentials.
+		-->
+		<method name="UnenrollWithCredentialCache">
+			<!-- The contents of a kerberos cache file containing administrative credentials -->
+			<arg name="kerberos_cache" type="ay" direction="in">
+				<annotation name="org.gtk.GDBus.C.ForceGVariant" value="yup"/>
+			</arg>
+			<arg name="options" type="a{sv}" direction="in"/>
+		</method>
+
+	</interface>
+</node>
diff --git a/panels/user-accounts/um-account-dialog.c b/panels/user-accounts/um-account-dialog.c
index 518b8cb..7574c10 100644
--- a/panels/user-accounts/um-account-dialog.c
+++ b/panels/user-accounts/um-account-dialog.c
@@ -27,6 +27,7 @@
 #include <gtk/gtk.h>
 
 #include "um-account-dialog.h"
+#include "um-realm-generated.h"
 #include "um-user-manager.h"
 #include "um-utils.h"
 
@@ -45,6 +46,8 @@ struct _UmAccountDialog {
 	GtkDialog parent;
 	GtkNotebook *notebook;
 	GSimpleAsyncResult *async;
+	GCancellable *cancellable;
+
 	GtkWidget *bar;
 	gboolean bar_updating;
 
@@ -54,9 +57,13 @@ struct _UmAccountDialog {
 	GtkWidget *local_account_type;
 
 	/* Enterprise users */
-	GtkWidget *enterprise_domain;
+	guint realmd_watch;
+	GtkWidget *enterprise_button;
+	GtkListStore *enterprise_realms;
+	GtkComboBox *enterprise_domain;
 	GtkWidget *enterprise_login;
 	GtkWidget *enterprise_password;
+	UmRealmProvider *realm_provider;
 };
 
 typedef struct {
@@ -392,14 +399,158 @@ enterprise_add (UmAccountDialog *self)
 }
 
 static void
+on_realm_proxy_created (GObject *source,
+                        GAsyncResult *result,
+                        gpointer user_data)
+{
+	UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
+	UmRealmKerberosRealm *realm;
+	GError *error = NULL;
+	GtkTreeIter iter;
+
+	realm = um_realm_kerberos_realm_proxy_new_finish (result, &error);
+
+	if (error != NULL) {
+		g_warning ("Couldn't create realm proxy: %s", error->message);
+		g_error_free (error);
+		return;
+	}
+
+	gtk_list_store_append (self->enterprise_realms, &iter);
+	gtk_list_store_set (self->enterprise_realms, &iter,
+	                    0, um_realm_kerberos_realm_get_domain (realm),
+	                    1, realm,
+	                    -1);
+
+	if (um_realm_kerberos_realm_get_enrolled (realm))
+		gtk_combo_box_set_active_iter (self->enterprise_domain, &iter);
+
+	g_object_unref (realm);
+}
+
+static void
+enterprise_populate_realms (UmAccountDialog *self,
+                            GDBusConnection *connection,
+                            GVariant *realms)
+{
+	GVariantIter iter;
+	const gchar *path;
+	const gchar *name;
+	const gchar *iface;
+
+	if (realms == NULL)
+		return;
+
+	/* We only support kerberos realms */
+
+	g_variant_iter_init (&iter, realms);
+	while (g_variant_iter_loop (&iter, "(&s&o&s)", &name, &path, &iface)) {
+		if (g_str_equal (iface, "org.freedesktop.realmd.KerberosRealm")) {
+			um_realm_kerberos_realm_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE,
+			                                   name, path, self->cancellable,
+			                                   on_realm_proxy_created, self);
+		}
+	}
+}
+
+static void
+on_provider_discover_default (GObject *source,
+                              GAsyncResult *result,
+                              gpointer user_data)
+{
+	UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
+	GDBusConnection *connection;
+	GError *error = NULL;
+	GVariant *realms;
+	gint relevance;
+
+	um_realm_provider_call_discover_finish (self->realm_provider, &relevance,
+	                                        &realms, result, &error);
+	if (error == NULL) {
+		connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (self->realm_provider));
+		enterprise_populate_realms (self, connection, realms);
+		g_variant_unref (realms);
+	} else {
+		g_warning ("Couldn't discover default realm: %s", error->message);
+		g_error_free (error);
+	}
+}
+
+static void
+on_provider_proxy_created (GObject *source,
+                           GAsyncResult *result,
+                           gpointer user_data)
+{
+	UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
+	GDBusConnection *connection;
+	GError *error = NULL;
+	GVariant *realms;
+
+	g_clear_object (&self->realm_provider);
+
+	self->realm_provider = um_realm_provider_proxy_new_for_bus_finish (result, &error);
+	if (error != NULL) {
+		if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
+			g_warning ("Couldn't contact realmd service: %s", error->message);
+		g_error_free (error);
+	}
+
+	if (!self->realm_provider)
+		return;
+
+	connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (self->realm_provider));
+
+	/* Lookup all the realm objects */
+	realms = um_realm_provider_get_realms (self->realm_provider);
+	enterprise_populate_realms (self, connection, realms);
+
+	/* When no realms try to discover a sensible default */
+	um_realm_provider_call_discover (self->realm_provider, "", self->cancellable,
+	                                 on_provider_discover_default, self);
+
+	/* Show the 'Enterprise Login' stuff, and update bar */
+	gtk_widget_show (self->enterprise_button);
+	bar_update (self, NULL);
+}
+
+static void
+on_realmd_appeared (GDBusConnection *connection,
+                    const gchar *name,
+                    const gchar *name_owner,
+                    gpointer user_data)
+{
+	UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
+	um_realm_provider_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE,
+	                             name, "/org/freedesktop/realmd",
+	                             self->cancellable, on_provider_proxy_created, self);
+}
+
+static void
+on_realmd_disappeared (GDBusConnection *connection,
+                       const gchar *name,
+                       gpointer user_data)
+{
+	UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
+	gtk_list_store_clear (self->enterprise_realms);
+	g_clear_object (&self->realm_provider);
+	gtk_widget_hide (self->enterprise_button);
+	bar_update (self, NULL);
+}
+
+static void
 enterprise_construct (UmAccountDialog *self,
                       GtkBuilder *builder)
 {
 	GtkWidget *widget;
 
+	self->enterprise_realms = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT);
+
 	widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-domain");
 	g_signal_connect (widget, "notify::text", G_CALLBACK (on_text_changed), self);
-	self->enterprise_domain = widget;
+	self->enterprise_domain = GTK_COMBO_BOX (widget);
+	gtk_combo_box_set_model (self->enterprise_domain,
+	                         GTK_TREE_MODEL (self->enterprise_realms));
+	gtk_combo_box_set_entry_text_column (self->enterprise_domain, 0);
 
 	widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-login");
 	g_signal_connect (widget, "notify::text", G_CALLBACK (on_text_changed), self);
@@ -408,15 +559,20 @@ enterprise_construct (UmAccountDialog *self,
 	widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-password");
 	self->enterprise_password = widget;
 
-	/* TODO: Populate the drop down for enrolled domains */
-	/* TODO: Choose first domain if so */
-	/* TODO: If another domain not selected, then validate and enter current domain name */
+	/* Initially we hide the 'Enterprise Login' stuff */
+	widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-button");
+	self->enterprise_button = widget;
+	gtk_widget_hide (widget);
+
+	self->realmd_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "org.freedesktop.realmd",
+	                                       G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+	                                       on_realmd_appeared, on_realmd_disappeared,
+	                                       self, NULL);
 }
 
 static void
 enterprise_clear (UmAccountDialog *self)
 {
-	gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (self->enterprise_domain))), "");
 	gtk_entry_set_text (GTK_ENTRY (self->enterprise_login), "");
 	gtk_entry_set_text (GTK_ENTRY (self->enterprise_password), "");
 }
@@ -424,7 +580,7 @@ enterprise_clear (UmAccountDialog *self)
 static void
 um_account_dialog_init (UmAccountDialog *self)
 {
-
+	self->cancellable = g_cancellable_new ();
 }
 
 static void
@@ -503,12 +659,23 @@ um_account_dialog_response (GtkDialog *dialog,
 		break;
 	}
 
+	g_cancellable_cancel (self->cancellable);
 	gtk_widget_hide (GTK_WIDGET (self));
 }
 
 static void
 um_account_dialog_finalize (GObject *obj)
 {
+	UmAccountDialog *self = UM_ACCOUNT_DIALOG (obj);
+
+	g_cancellable_cancel (self->cancellable);
+	g_object_unref (self->cancellable);
+	g_object_unref (self->enterprise_realms);
+	g_clear_object (&self->realm_provider);
+
+	if (self->realmd_watch)
+		g_bus_unwatch_name (self->realmd_watch);
+
 	G_OBJECT_CLASS (um_account_dialog_parent_class)->finalize (obj);
 }
 



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