[gnome-initial-setup] account: Do the same for the "enterprise login" section
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-initial-setup] account: Do the same for the "enterprise login" section
- Date: Tue, 19 Nov 2013 16:40:51 +0000 (UTC)
commit 8cc86c5995325ade9e2c8960c342308a98e8a905
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Sat Nov 2 21:00:00 2013 -0400
account: Do the same for the "enterprise login" section
gnome-initial-setup/pages/account/Makefile.am | 15 +-
.../pages/account/account.gresource.xml | 1 +
.../pages/account/gis-account-page-enterprise.c | 816 ++++++++++++++++++++
.../pages/account/gis-account-page-enterprise.h | 64 ++
.../pages/account/gis-account-page-enterprise.ui | 473 ++++++++++++
.../pages/account/gis-account-page.c | 736 +-----------------
.../pages/account/gis-account-page.ui | 467 +-----------
7 files changed, 1387 insertions(+), 1185 deletions(-)
---
diff --git a/gnome-initial-setup/pages/account/Makefile.am b/gnome-initial-setup/pages/account/Makefile.am
index 9a6af50..3965376 100644
--- a/gnome-initial-setup/pages/account/Makefile.am
+++ b/gnome-initial-setup/pages/account/Makefile.am
@@ -22,13 +22,14 @@ account-resources.h: account.gresource.xml $(resource_files)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --generate-header $<
BUILT_SOURCES += account-resources.c account-resources.h
-libgisaccount_la_SOURCES = \
- $(BUILT_SOURCES) \
- gis-account-page.c gis-account-page.h \
- gis-account-page-local.c gis-account-page-local.h \
- um-realm-manager.c um-realm-manager.h \
- um-utils.c um-utils.h \
- pw-utils.c pw-utils.h \
+libgisaccount_la_SOURCES = \
+ $(BUILT_SOURCES) \
+ gis-account-page.c gis-account-page.h \
+ gis-account-page-local.c gis-account-page-local.h \
+ gis-account-page-enterprise.c gis-account-page-enterprise.h \
+ um-realm-manager.c um-realm-manager.h \
+ um-utils.c um-utils.h \
+ pw-utils.c pw-utils.h \
$(NULL)
libgisaccount_la_CFLAGS = $(INITIAL_SETUP_CFLAGS) -I "$(srcdir)/../.."
diff --git a/gnome-initial-setup/pages/account/account.gresource.xml
b/gnome-initial-setup/pages/account/account.gresource.xml
index 7965408..2b3c470 100644
--- a/gnome-initial-setup/pages/account/account.gresource.xml
+++ b/gnome-initial-setup/pages/account/account.gresource.xml
@@ -3,5 +3,6 @@
<gresource prefix="/org/gnome/initial-setup">
<file preprocess="xml-stripblanks" alias="gis-account-page.ui">gis-account-page.ui</file>
<file preprocess="xml-stripblanks" alias="gis-account-page-local.ui">gis-account-page-local.ui</file>
+ <file preprocess="xml-stripblanks"
alias="gis-account-page-enterprise.ui">gis-account-page-enterprise.ui</file>
</gresource>
</gresources>
diff --git a/gnome-initial-setup/pages/account/gis-account-page-enterprise.c
b/gnome-initial-setup/pages/account/gis-account-page-enterprise.c
new file mode 100644
index 0000000..f74a46a
--- /dev/null
+++ b/gnome-initial-setup/pages/account/gis-account-page-enterprise.c
@@ -0,0 +1,816 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "config.h"
+
+#include "gis-account-page-enterprise.h"
+#include "gnome-initial-setup.h"
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <act/act-user-manager.h>
+
+#include "um-realm-manager.h"
+#include "um-utils.h"
+#include "pw-utils.h"
+
+static void join_show_prompt (GisAccountPageEnterprise *page,
+ GError *error);
+
+static void on_join_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data);
+
+static void on_realm_joined (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data);
+
+struct _GisAccountPageEnterprisePrivate
+{
+ GtkWidget *login;
+ GtkWidget *password;
+ GtkWidget *domain;
+ GtkWidget *domain_entry;
+ GtkTreeModel *realms_model;
+
+ GtkWidget *join_dialog;
+ GtkWidget *join_name;
+ GtkWidget *join_password;
+ GtkWidget *join_domain;
+ GtkWidget *join_computer;
+
+ ActUserManager *act_client;
+ ActUser *act_user;
+
+ guint realmd_watch;
+ UmRealmManager *realm_manager;
+ gboolean domain_chosen;
+
+ /* Valid during apply */
+ UmRealmObject *realm;
+ GCancellable *cancellable;
+ gboolean join_prompted;
+
+ GisPageApplyCallback apply_complete_callback;
+ gpointer apply_complete_data;
+};
+typedef struct _GisAccountPageEnterprisePrivate GisAccountPageEnterprisePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GisAccountPageEnterprise, gis_account_page_enterprise, GTK_TYPE_BIN);
+
+enum {
+ VALIDATION_CHANGED,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+validation_changed (GisAccountPageEnterprise *page)
+{
+ g_signal_emit (page, signals[VALIDATION_CHANGED], 0);
+}
+
+static void
+apply_complete (GisAccountPageEnterprise *page,
+ gboolean valid)
+{
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ priv->apply_complete_callback (NULL, valid, priv->apply_complete_data);
+}
+
+static void
+show_error_dialog (GisAccountPageEnterprise *page,
+ const gchar *message,
+ GError *error)
+{
+ GtkWidget *dialog;
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s", message);
+
+ if (error != NULL) {
+ g_dbus_error_strip_remote_error (error);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", error->message);
+ }
+
+ g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+gboolean
+gis_account_page_enterprise_validate (GisAccountPageEnterprise *page)
+{
+ const gchar *name;
+ gboolean valid_name;
+ gboolean valid_domain;
+ GtkTreeIter iter;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+ name = gtk_entry_get_text (GTK_ENTRY (priv->login));
+ valid_name = is_valid_name (name);
+
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->domain), &iter)) {
+ gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->domain)),
+ &iter, 0, &name, -1);
+ } else {
+ name = gtk_entry_get_text (GTK_ENTRY (priv->domain_entry));
+ }
+
+ valid_domain = is_valid_name (name);
+ return valid_name && valid_domain;
+}
+
+static void
+on_permit_user_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ UmRealmCommon *common;
+ GError *error = NULL;
+ gchar *login;
+
+ common = UM_REALM_COMMON (source);
+ um_realm_common_call_change_login_policy_finish (common, result, &error);
+ if (error == NULL) {
+
+ /*
+ * Now tell the account service about this user. The account service
+ * should also lookup information about this via the realm and make
+ * sure all that is functional.
+ */
+ login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->login)));
+ g_return_if_fail (login != NULL);
+
+ g_debug ("Caching remote user: %s", login);
+
+ priv->act_user = act_user_manager_cache_user (priv->act_client, login, NULL);
+ apply_complete (page, TRUE);
+
+ g_free (login);
+ } else {
+ show_error_dialog (page, _("Failed to register account"), error);
+ g_message ("Couldn't permit logins on account: %s", error->message);
+ g_error_free (error);
+ apply_complete (page, FALSE);
+ }
+}
+
+static void
+enterprise_permit_user_login (GisAccountPageEnterprise *page, UmRealmObject *realm)
+{
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ UmRealmCommon *common;
+ gchar *login;
+ const gchar *add[2];
+ const gchar *remove[1];
+ GVariant *options;
+
+ common = um_realm_object_get_common (realm);
+
+ login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->login)));
+ g_return_if_fail (login != NULL);
+
+ add[0] = login;
+ add[1] = NULL;
+ remove[0] = NULL;
+
+ g_debug ("Permitting login for: %s", login);
+ options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
+
+ um_realm_common_call_change_login_policy (common, "",
+ add, remove, options,
+ priv->cancellable,
+ on_permit_user_login,
+ page);
+
+ g_object_unref (common);
+ g_free (login);
+}
+
+static void
+on_set_static_hostname (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GError *error = NULL;
+ GVariant *retval;
+
+ retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
+ if (error != NULL) {
+ join_show_prompt (page, error);
+ g_error_free (error);
+ return;
+ }
+
+ g_variant_unref (retval);
+
+ /* Prompted for some admin credentials, try to use them to log in */
+ um_realm_login (priv->realm,
+ gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
+ gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
+ priv->cancellable, on_join_login, page);
+}
+
+static void
+on_join_response (GtkDialog *dialog,
+ gint response,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GDBusConnection *connection;
+ GError *error = NULL;
+ gchar hostname[128];
+ const gchar *name;
+
+ gtk_widget_hide (GTK_WIDGET (dialog));
+ if (response != GTK_RESPONSE_OK) {
+ apply_complete (page, FALSE);
+ return;
+ }
+
+ name = gtk_entry_get_text (GTK_ENTRY (priv->join_computer));
+ if (gethostname (hostname, sizeof (hostname)) == 0 &&
+ !g_str_equal (name, hostname)) {
+ g_debug ("Setting StaticHostname to '%s'", name);
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, priv->cancellable, &error);
+ if (error != NULL) {
+ apply_complete (page, FALSE);
+ g_warning ("Could not get DBus connection: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_dbus_connection_call (connection, "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
+ "SetStaticHostname",
+ g_variant_new ("(sb)", name, TRUE),
+ G_VARIANT_TYPE ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ G_MAXINT, NULL, on_set_static_hostname, page);
+
+ } else {
+ name = gtk_entry_get_text (GTK_ENTRY (priv->join_name));
+ g_debug ("Logging in as admin user: %s", name);
+
+ /* Prompted for some admin credentials, try to use them to log in */
+ um_realm_login (priv->realm, name,
+ gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
+ NULL, on_join_login, page);
+ }
+}
+
+static void
+join_show_prompt (GisAccountPageEnterprise *page,
+ GError *error)
+{
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ UmRealmKerberosMembership *membership;
+ UmRealmKerberos *kerberos;
+ gchar hostname[128];
+ const gchar *name;
+
+ gtk_entry_set_text (GTK_ENTRY (priv->join_password), "");
+ gtk_widget_grab_focus (GTK_WIDGET (priv->join_password));
+
+ kerberos = um_realm_object_get_kerberos (priv->realm);
+ membership = um_realm_object_get_kerberos_membership (priv->realm);
+
+ gtk_label_set_text (GTK_LABEL (priv->join_domain),
+ um_realm_kerberos_get_domain_name (kerberos));
+
+ if (gethostname (hostname, sizeof (hostname)) == 0)
+ gtk_entry_set_text (GTK_ENTRY (priv->join_computer), hostname);
+
+ clear_entry_validation_error (GTK_ENTRY (priv->join_name));
+ clear_entry_validation_error (GTK_ENTRY (priv->join_password));
+
+ if (!priv->join_prompted) {
+ name = um_realm_kerberos_membership_get_suggested_administrator (membership);
+ if (name && !g_str_equal (name, "")) {
+ g_debug ("Suggesting admin user: %s", name);
+ gtk_entry_set_text (GTK_ENTRY (priv->join_name), name);
+ } else {
+ gtk_widget_grab_focus (GTK_WIDGET (priv->join_name));
+ }
+
+ } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
+ g_debug ("Bad host name: %s", error->message);
+ set_entry_validation_error (GTK_ENTRY (priv->join_computer), error->message);
+
+ } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
+ g_debug ("Bad admin password: %s", error->message);
+ set_entry_validation_error (GTK_ENTRY (priv->join_password), error->message);
+
+ } else {
+ g_debug ("Admin login failure: %s", error->message);
+ g_dbus_error_strip_remote_error (error);
+ set_entry_validation_error (GTK_ENTRY (priv->join_name), error->message);
+ }
+
+ g_debug ("Showing admin password dialog");
+ gtk_window_set_transient_for (GTK_WINDOW (priv->join_dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))));
+ gtk_window_set_modal (GTK_WINDOW (priv->join_dialog), TRUE);
+ gtk_window_present (GTK_WINDOW (priv->join_dialog));
+
+ priv->join_prompted = TRUE;
+ g_object_unref (kerberos);
+ g_object_unref (membership);
+
+ /* And now we wait for on_join_response() */
+}
+
+static void
+on_join_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GError *error = NULL;
+ GBytes *creds;
+
+ um_realm_login_finish (priv->realm, result, &creds, &error);
+
+ /* Logged in as admin successfully, use creds to join domain */
+ if (error == NULL) {
+ if (!um_realm_join_as_admin (priv->realm,
+ gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
+ gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
+ creds, NULL, on_realm_joined, page)) {
+ show_error_dialog (page, _("No supported way to authenticate with this domain"), NULL);
+ g_message ("Authenticating as admin is not supported by the realm");
+ }
+
+ g_bytes_unref (creds);
+
+ /* Couldn't login as admin, show prompt again */
+ } else {
+ join_show_prompt (page, error);
+ g_message ("Couldn't log in as admin to join domain: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+on_realm_joined (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GError *error = NULL;
+
+ um_realm_join_finish (priv->realm, result, &error);
+
+ /* Yay, joined the domain, register the user locally */
+ if (error == NULL) {
+ g_debug ("Joining realm completed successfully");
+ enterprise_permit_user_login (page, priv->realm);
+
+ /* Credential failure while joining domain, prompt for admin creds */
+ } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN) ||
+ g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD) ||
+ g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
+ g_debug ("Joining realm failed due to credentials or host name");
+
+ join_show_prompt (page, error);
+
+ /* Other failure */
+ } else {
+ show_error_dialog (page, _("Failed to join domain"), error);
+ g_message ("Failed to join the domain: %s", error->message);
+ apply_complete (page, FALSE);
+ }
+
+ g_clear_error (&error);
+}
+
+static void
+on_realm_login (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GError *error = NULL;
+ GBytes *creds = NULL;
+
+ um_realm_login_finish (priv->realm, result, &creds, &error);
+
+ /*
+ * User login is valid, but cannot authenticate right now (eg: user needs
+ * to change password at next login etc.)
+ */
+ if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_CANNOT_AUTH)) {
+ g_clear_error (&error);
+ creds = NULL;
+ }
+
+ if (error == NULL) {
+
+ /* Already joined to the domain, just register this user */
+ if (um_realm_is_configured (priv->realm)) {
+ g_debug ("Already joined to this realm");
+ enterprise_permit_user_login (page, priv->realm);
+
+ /* Join the domain, try using the user's creds */
+ } else if (creds == NULL ||
+ !um_realm_join_as_user (priv->realm,
+ gtk_entry_get_text (GTK_ENTRY (priv->login)),
+ gtk_entry_get_text (GTK_ENTRY (priv->password)),
+ creds, priv->cancellable,
+ on_realm_joined,
+ page)) {
+
+ /* If we can't do user auth, try to authenticate as admin */
+ g_debug ("Cannot join with user credentials");
+
+ join_show_prompt (page, error);
+ }
+
+ g_bytes_unref (creds);
+
+ /* A problem with the user's login name or password */
+ } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN)) {
+ g_debug ("Problem with the user's login: %s", error->message);
+ set_entry_validation_error (GTK_ENTRY (priv->login), error->message);
+ gtk_widget_grab_focus (priv->login);
+ apply_complete (page, FALSE);
+
+ } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
+ g_debug ("Problem with the user's password: %s", error->message);
+ set_entry_validation_error (GTK_ENTRY (priv->password), error->message);
+ gtk_widget_grab_focus (priv->password);
+ apply_complete (page, FALSE);
+
+ /* Other login failure */
+ } else {
+ show_error_dialog (page, _("Failed to log into domain"), error);
+ g_message ("Couldn't log in as user: %s", error->message);
+ apply_complete (page, FALSE);
+ }
+
+ g_clear_error (&error);
+}
+
+static void
+enterprise_check_login (GisAccountPageEnterprise *page)
+{
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+ g_assert (priv->realm);
+
+ um_realm_login (priv->realm,
+ gtk_entry_get_text (GTK_ENTRY (priv->login)),
+ gtk_entry_get_text (GTK_ENTRY (priv->password)),
+ priv->cancellable,
+ on_realm_login,
+ page);
+}
+
+static void
+on_realm_discover_input (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GError *error = NULL;
+ GList *realms;
+
+ realms = um_realm_manager_discover_finish (priv->realm_manager,
+ result, &error);
+
+ /* Found a realm, log user into domain */
+ if (error == NULL) {
+ g_assert (realms != NULL);
+ priv->realm = g_object_ref (realms->data);
+ enterprise_check_login (page);
+ g_list_free_full (realms, g_object_unref);
+
+ } else {
+ /* The domain is likely invalid */
+ g_dbus_error_strip_remote_error (error);
+ g_message ("Couldn't discover domain: %s", error->message);
+ gtk_widget_grab_focus (priv->domain_entry);
+ set_entry_validation_error (GTK_ENTRY (priv->domain_entry), error->message);
+ apply_complete (page, FALSE);
+ g_error_free (error);
+ }
+}
+
+static void
+enterprise_add_user (GisAccountPageEnterprise *page)
+{
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GtkTreeIter iter;
+
+ priv->join_prompted = FALSE;
+ g_clear_object (&priv->realm);
+
+ /* Already know about this realm, try to login as user */
+ if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->domain), &iter)) {
+ gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->domain)),
+ &iter, 1, &priv->realm, -1);
+ enterprise_check_login (page);
+
+ /* Something the user typed, we need to discover realm */
+ } else {
+ um_realm_manager_discover (priv->realm_manager,
+ gtk_entry_get_text (GTK_ENTRY (priv->domain_entry)),
+ priv->cancellable,
+ on_realm_discover_input,
+ page);
+ }
+}
+
+gboolean
+gis_account_page_enterprise_apply (GisAccountPageEnterprise *page,
+ GCancellable *cancellable,
+ GisPageApplyCallback callback,
+ gpointer data)
+{
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+ priv->apply_complete_callback = callback;
+ priv->apply_complete_data = data;
+ priv->cancellable = g_object_ref (cancellable);
+ enterprise_add_user (page);
+ return TRUE;
+}
+
+static gchar *
+realm_get_name (UmRealmObject *realm)
+{
+ UmRealmCommon *common;
+ gchar *name;
+
+ common = um_realm_object_get_common (realm);
+ name = g_strdup (um_realm_common_get_name (common));
+ g_object_unref (common);
+
+ return name;
+}
+
+static gboolean
+model_contains_realm (GtkTreeModel *model,
+ const gchar *realm_name)
+{
+ gboolean contains = FALSE;
+ GtkTreeIter iter;
+ gboolean match;
+ gchar *name;
+ gboolean ret;
+
+ ret = gtk_tree_model_get_iter_first (model, &iter);
+ while (ret) {
+ gtk_tree_model_get (model, &iter, 0, &name, -1);
+ match = (g_strcmp0 (name, realm_name) == 0);
+ g_free (name);
+ if (match) {
+ g_debug ("ignoring duplicate realm: %s", realm_name);
+ contains = TRUE;
+ break;
+ }
+ ret = gtk_tree_model_iter_next (model, &iter);
+ }
+
+ return contains;
+}
+
+static void
+enterprise_add_realm (GisAccountPageEnterprise *page,
+ UmRealmObject *realm)
+{
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GtkTreeIter iter;
+ gchar *name;
+
+ name = realm_get_name (realm);
+
+ /*
+ * Don't add a second realm if we already have one with this name.
+ * Sometimes realmd returns two realms for the same name, if it has
+ * different ways to use that realm. The first one that realmd
+ * returns is the one it prefers.
+ */
+
+ if (!model_contains_realm (GTK_TREE_MODEL (priv->realms_model), name)) {
+ gtk_list_store_append (GTK_LIST_STORE (priv->realms_model), &iter);
+ gtk_list_store_set (GTK_LIST_STORE (priv->realms_model), &iter,
+ 0, name,
+ 1, realm,
+ -1);
+
+ if (!priv->domain_chosen && um_realm_is_configured (realm))
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->domain), &iter);
+
+ g_debug ("added realm to drop down: %s %s", name,
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (realm)));
+ }
+
+ g_free (name);
+}
+
+static void
+on_manager_realm_added (UmRealmManager *manager,
+ UmRealmObject *realm,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ enterprise_add_realm (page, realm);
+}
+
+static void
+on_realm_manager_created (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+ GError *error = NULL;
+ GList *realms, *l;
+
+ g_clear_object (&priv->realm_manager);
+ priv->realm_manager = um_realm_manager_new_finish (result, &error);
+
+ if (error != NULL) {
+ g_warning ("Couldn't contact realmd service: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ /* Lookup all the realm objects */
+ realms = um_realm_manager_get_realms (priv->realm_manager);
+ for (l = realms; l != NULL; l = g_list_next (l))
+ enterprise_add_realm (page, l->data);
+
+ g_list_free (realms);
+ g_signal_connect (priv->realm_manager, "realm-added",
+ G_CALLBACK (on_manager_realm_added), page);
+
+ /* When no realms try to discover a sensible default, triggers realm-added signal */
+ um_realm_manager_discover (priv->realm_manager, "", NULL, NULL, NULL);
+ gtk_widget_set_visible (GTK_WIDGET (page), TRUE);
+}
+
+static void
+on_realmd_appeared (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ um_realm_manager_new (NULL, on_realm_manager_created, page);
+}
+
+static void
+on_realmd_disappeared (GDBusConnection *unused1,
+ const gchar *unused2,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+ if (priv->realm_manager != NULL) {
+ g_signal_handlers_disconnect_by_func (priv->realm_manager,
+ on_manager_realm_added,
+ page);
+ g_clear_object (&priv->realm_manager);
+ }
+
+ gtk_widget_set_visible (GTK_WIDGET (page), FALSE);
+}
+
+static void
+on_domain_changed (GtkComboBox *widget,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+ priv->domain_chosen = TRUE;
+ validation_changed (page);
+ clear_entry_validation_error (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget))));
+}
+
+static void
+on_entry_changed (GtkEditable *editable,
+ gpointer user_data)
+{
+ GisAccountPageEnterprise *page = user_data;
+ validation_changed (page);
+ clear_entry_validation_error (GTK_ENTRY (editable));
+}
+
+static void
+gis_account_page_enterprise_constructed (GObject *object)
+{
+ GisAccountPageEnterprise *page = GIS_ACCOUNT_PAGE_ENTERPRISE (object);
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+ G_OBJECT_CLASS (gis_account_page_enterprise_parent_class)->constructed (object);
+
+ priv->act_client = act_user_manager_get_default ();
+
+ priv->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,
+ page, NULL);
+
+ g_signal_connect (priv->join_dialog, "response",
+ G_CALLBACK (on_join_response), page);
+ g_signal_connect (priv->domain, "changed",
+ G_CALLBACK (on_domain_changed), page);
+ g_signal_connect (priv->login, "changed",
+ G_CALLBACK (on_entry_changed), page);
+}
+
+static void
+gis_account_page_enterprise_dispose (GObject *object)
+{
+ GisAccountPageEnterprise *page = GIS_ACCOUNT_PAGE_ENTERPRISE (object);
+ GisAccountPageEnterprisePrivate *priv = gis_account_page_enterprise_get_instance_private (page);
+
+ if (priv->realmd_watch)
+ g_bus_unwatch_name (priv->realmd_watch);
+
+ priv->realmd_watch = 0;
+
+ g_cancellable_cancel (priv->cancellable);
+
+ g_clear_object (&priv->realm_manager);
+ g_clear_object (&priv->realm);
+ g_clear_object (&priv->cancellable);
+
+ G_OBJECT_CLASS (gis_account_page_enterprise_parent_class)->dispose (object);
+}
+
+static void
+gis_account_page_enterprise_class_init (GisAccountPageEnterpriseClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = gis_account_page_enterprise_constructed;
+ object_class->dispose = gis_account_page_enterprise_dispose;
+
+ gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/org/gnome/initial-setup/gis-account-page-enterprise.ui");
+
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, login);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
password);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise, domain);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
domain_entry);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
realms_model);
+
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
join_dialog);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
join_name);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
join_password);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
join_domain);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPageEnterprise,
join_computer);
+
+ signals[VALIDATION_CHANGED] = g_signal_new ("validation-changed", GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE,
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
+gis_account_page_enterprise_init (GisAccountPageEnterprise *page)
+{
+ gtk_widget_init_template (GTK_WIDGET (page));
+}
diff --git a/gnome-initial-setup/pages/account/gis-account-page-enterprise.h
b/gnome-initial-setup/pages/account/gis-account-page-enterprise.h
new file mode 100644
index 0000000..2c7d14f
--- /dev/null
+++ b/gnome-initial-setup/pages/account/gis-account-page-enterprise.h
@@ -0,0 +1,64 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ * Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef __GIS_ACCOUNT_PAGE_ENTERPRISE_H__
+#define __GIS_ACCOUNT_PAGE_ENTERPRISE_H__
+
+#include <gtk/gtk.h>
+
+/* For GisPageApplyCallback */
+#include "gis-page.h"
+
+G_BEGIN_DECLS
+
+#define GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE (gis_account_page_enterprise_get_type ())
+#define GIS_ACCOUNT_PAGE_ENTERPRISE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE, GisAccountPageEnterprise))
+#define GIS_ACCOUNT_PAGE_ENTERPRISE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE, GisAccountPageEnterpriseClass))
+#define GIS_IS_ACCOUNT_PAGE_ENTERPRISE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE))
+#define GIS_IS_ACCOUNT_PAGE_ENTERPRISE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE))
+#define GIS_ACCOUNT_PAGE_ENTERPRISE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE, GisAccountPageEnterpriseClass))
+
+typedef struct _GisAccountPageEnterprise GisAccountPageEnterprise;
+typedef struct _GisAccountPageEnterpriseClass GisAccountPageEnterpriseClass;
+
+struct _GisAccountPageEnterprise
+{
+ GtkBin parent;
+};
+
+struct _GisAccountPageEnterpriseClass
+{
+ GtkBinClass parent_class;
+};
+
+GType gis_account_page_enterprise_get_type (void);
+
+gboolean gis_account_page_enterprise_validate (GisAccountPageEnterprise *enterprise);
+gboolean gis_account_page_enterprise_apply (GisAccountPageEnterprise *enterprise,
+ GCancellable *cancellable,
+ GisPageApplyCallback callback,
+ gpointer data);
+
+G_END_DECLS
+
+#endif /* __GIS_ACCOUNT_PAGE_ENTERPRISE_H__ */
diff --git a/gnome-initial-setup/pages/account/gis-account-page-enterprise.ui
b/gnome-initial-setup/pages/account/gis-account-page-enterprise.ui
new file mode 100644
index 0000000..723a6d8
--- /dev/null
+++ b/gnome-initial-setup/pages/account/gis-account-page-enterprise.ui
@@ -0,0 +1,473 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <template class="GisAccountPageEnterprise" parent="GtkBin">
+ <child>
+ <object class="GtkGrid" id="area">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="sizer3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="margin_bottom">8</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes">Create an Enterprise Account</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </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="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">domain</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Username</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">login</property>
+ </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="label9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">end</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">password</property>
+ </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="login">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ </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">
+ <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>
+ </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>
+ <child>
+ <object class="GtkComboBox" id="domain">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="model">realms_model</property>
+ <property name="has_entry">True</property>
+ <property name="entry_text_column">0</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="domain_entry">
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">12</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Enterprise domain or realm name</property>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="filler">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </template>
+
+ <object class="GtkDialog" id="join_dialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-cancel</property>
+ <property name="use_action_appearance">False</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_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button2">
+ <property name="label" translatable="yes">C_ontinue</property>
+ <property name="use_action_appearance">False</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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="label71">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Domain Administrator Login</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ <attribute name="scale" value="1.2"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">In order to use enterprise logins, this computer
needs to be
+ enrolled in the domain. Please have your network administrator
+ type their domain password here, and choose a unique computer
+ name for your computer.</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">12</property>
+ <property name="hexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Domain</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">join_domain</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="join_domain">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">5</property>
+ <property name="margin_bottom">5</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label18">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">_Computer</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">join_computer</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="join_computer">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Administrator _Name</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">join_name</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="join_name">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="invisible_char">●</property>
+ <property name="invisible_char_set">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Administrator Password</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">join_password</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="GtkEntry" id="join_password">
+ <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>
+ </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>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">button1</action-widget>
+ <action-widget response="-5">button2</action-widget>
+ </action-widgets>
+ </object>
+
+ <object class="GtkListStore" id="realms_model">
+ <columns>
+ <!-- column-name gchararray -->
+ <column type="gchararray"/>
+ <!-- column-name gobject -->
+ <column type="GObject"/>
+ </columns>
+ </object>
+</interface>
diff --git a/gnome-initial-setup/pages/account/gis-account-page.c
b/gnome-initial-setup/pages/account/gis-account-page.c
index 4ee6711..bf4a287 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.c
+++ b/gnome-initial-setup/pages/account/gis-account-page.c
@@ -29,27 +29,11 @@
#include "account-resources.h"
#include "gis-account-page.h"
#include "gis-account-page-local.h"
+#include "gis-account-page-enterprise.h"
#include <glib/gi18n.h>
#include <gio/gio.h>
-#include <act/act-user-manager.h>
-
-#include "um-realm-manager.h"
-#include "um-utils.h"
-#include "pw-utils.h"
-
-static void join_show_prompt (GisAccountPage *page,
- GError *error);
-
-static void on_join_login (GObject *source,
- GAsyncResult *result,
- gpointer user_data);
-
-static void on_realm_joined (GObject *source,
- GAsyncResult *result,
- gpointer user_data);
-
typedef enum {
UM_LOCAL,
UM_ENTERPRISE,
@@ -59,88 +43,26 @@ typedef enum {
struct _GisAccountPagePrivate
{
GtkWidget *page_local;
-
- GtkWidget *enterprise_login;
- GtkWidget *enterprise_password;
- GtkWidget *enterprise_domain;
- GtkWidget *enterprise_domain_entry;
- GtkTreeModel *enterprise_realms_model;
-
- GtkWidget *join_dialog;
- GtkWidget *join_name;
- GtkWidget *join_password;
- GtkWidget *join_domain;
- GtkWidget *join_computer;
+ GtkWidget *page_enterprise;
GtkWidget *page_toggle;
GtkWidget *notebook;
- ActUserManager *act_client;
- ActUser *act_user;
-
UmAccountMode mode;
gboolean has_enterprise;
- guint realmd_watch;
- UmRealmManager *realm_manager;
- gboolean domain_chosen;
-
- /* Valid during apply */
- UmRealmObject *realm;
- GCancellable *cancellable;
- gboolean join_prompted;
};
typedef struct _GisAccountPagePrivate GisAccountPagePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GisAccountPage, gis_account_page, GIS_TYPE_PAGE);
static void
-show_error_dialog (GisAccountPage *page,
- const gchar *message,
- GError *error)
-{
- GtkWidget *dialog;
-
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- return;
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "%s", message);
-
- if (error != NULL) {
- g_dbus_error_strip_remote_error (error);
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- "%s", error->message);
- }
-
- g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
- gtk_window_present (GTK_WINDOW (dialog));
-}
-
-static gboolean
-enterprise_validate (GisAccountPage *page)
+enterprise_apply_complete (GisPage *dummy,
+ gboolean valid,
+ gpointer user_data)
{
- const gchar *name;
- gboolean valid_name;
- gboolean valid_domain;
- GtkTreeIter iter;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
- name = gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login));
- valid_name = is_valid_name (name);
-
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->enterprise_domain), &iter)) {
- gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->enterprise_domain)),
- &iter, 0, &name, -1);
- } else {
- name = gtk_entry_get_text (GTK_ENTRY (priv->enterprise_domain_entry));
- }
-
- valid_domain = is_valid_name (name);
- return valid_name && valid_domain;
+ GisAccountPage *page = GIS_ACCOUNT_PAGE (user_data);
+ gis_page_apply_complete (GIS_PAGE (page), valid);
}
static gboolean
@@ -152,7 +74,7 @@ page_validate (GisAccountPage *page)
case UM_LOCAL:
return gis_account_page_local_validate (GIS_ACCOUNT_PAGE_LOCAL (priv->page_local));
case UM_ENTERPRISE:
- return enterprise_validate (page);
+ return gis_account_page_enterprise_validate (GIS_ACCOUNT_PAGE_ENTERPRISE (priv->page_enterprise));
default:
g_assert_not_reached ();
}
@@ -188,10 +110,15 @@ set_mode (GisAccountPage *page,
}
static void
-set_has_enterprise (GisAccountPage *page,
- gboolean has_enterprise)
+on_enterprise_visible_changed (GObject *object,
+ GParamSpec *param,
+ gpointer user_data)
{
+ GisAccountPage *page = GIS_ACCOUNT_PAGE (user_data);
GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
+ gboolean has_enterprise;
+
+ has_enterprise = gtk_widget_get_visible (priv->page_enterprise);
if (priv->has_enterprise == has_enterprise)
return;
@@ -205,581 +132,6 @@ set_has_enterprise (GisAccountPage *page,
}
static void
-on_permit_user_login (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- UmRealmCommon *common;
- GError *error = NULL;
- gchar *login;
-
- common = UM_REALM_COMMON (source);
- um_realm_common_call_change_login_policy_finish (common, result, &error);
- if (error == NULL) {
-
- /*
- * Now tell the account service about this user. The account service
- * should also lookup information about this via the realm and make
- * sure all that is functional.
- */
- login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)));
- g_return_if_fail (login != NULL);
-
- g_debug ("Caching remote user: %s", login);
-
- priv->act_user = act_user_manager_cache_user (priv->act_client, login, NULL);
- gis_page_apply_complete (GIS_PAGE (page), TRUE);
-
- g_free (login);
- } else {
- show_error_dialog (page, _("Failed to register account"), error);
- g_message ("Couldn't permit logins on account: %s", error->message);
- g_error_free (error);
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
- }
-}
-
-static void
-enterprise_permit_user_login (GisAccountPage *page, UmRealmObject *realm)
-{
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- UmRealmCommon *common;
- gchar *login;
- const gchar *add[2];
- const gchar *remove[1];
- GVariant *options;
-
- common = um_realm_object_get_common (realm);
-
- login = um_realm_calculate_login (common, gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)));
- g_return_if_fail (login != NULL);
-
- add[0] = login;
- add[1] = NULL;
- remove[0] = NULL;
-
- g_debug ("Permitting login for: %s", login);
- options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
-
- um_realm_common_call_change_login_policy (common, "",
- add, remove, options,
- priv->cancellable,
- on_permit_user_login,
- page);
-
- g_object_unref (common);
- g_free (login);
-}
-
-static void
-on_set_static_hostname (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GError *error = NULL;
- GVariant *retval;
-
- retval = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
- if (error != NULL) {
- join_show_prompt (page, error);
- g_error_free (error);
- return;
- }
-
- g_variant_unref (retval);
-
- /* Prompted for some admin credentials, try to use them to log in */
- um_realm_login (priv->realm,
- gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
- gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
- priv->cancellable, on_join_login, page);
-}
-
-static void
-on_join_response (GtkDialog *dialog,
- gint response,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GDBusConnection *connection;
- GError *error = NULL;
- gchar hostname[128];
- const gchar *name;
-
- gtk_widget_hide (GTK_WIDGET (dialog));
- if (response != GTK_RESPONSE_OK) {
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
- return;
- }
-
- name = gtk_entry_get_text (GTK_ENTRY (priv->join_computer));
- if (gethostname (hostname, sizeof (hostname)) == 0 &&
- !g_str_equal (name, hostname)) {
- g_debug ("Setting StaticHostname to '%s'", name);
-
- connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, priv->cancellable, &error);
- if (error != NULL) {
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
- g_warning ("Could not get DBus connection: %s", error->message);
- g_error_free (error);
- return;
- }
-
- g_dbus_connection_call (connection, "org.freedesktop.hostname1",
- "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
- "SetStaticHostname",
- g_variant_new ("(sb)", name, TRUE),
- G_VARIANT_TYPE ("()"),
- G_DBUS_CALL_FLAGS_NONE,
- G_MAXINT, NULL, on_set_static_hostname, page);
-
- } else {
- name = gtk_entry_get_text (GTK_ENTRY (priv->join_name));
- g_debug ("Logging in as admin user: %s", name);
-
- /* Prompted for some admin credentials, try to use them to log in */
- um_realm_login (priv->realm, name,
- gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
- NULL, on_join_login, page);
- }
-}
-
-static void
-join_show_prompt (GisAccountPage *page,
- GError *error)
-{
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- UmRealmKerberosMembership *membership;
- UmRealmKerberos *kerberos;
- gchar hostname[128];
- const gchar *name;
-
- gtk_entry_set_text (GTK_ENTRY (priv->join_password), "");
- gtk_widget_grab_focus (GTK_WIDGET (priv->join_password));
-
- kerberos = um_realm_object_get_kerberos (priv->realm);
- membership = um_realm_object_get_kerberos_membership (priv->realm);
-
- gtk_label_set_text (GTK_LABEL (priv->join_domain),
- um_realm_kerberos_get_domain_name (kerberos));
-
- if (gethostname (hostname, sizeof (hostname)) == 0)
- gtk_entry_set_text (GTK_ENTRY (priv->join_computer), hostname);
-
- clear_entry_validation_error (GTK_ENTRY (priv->join_name));
- clear_entry_validation_error (GTK_ENTRY (priv->join_password));
-
- if (!priv->join_prompted) {
- name = um_realm_kerberos_membership_get_suggested_administrator (membership);
- if (name && !g_str_equal (name, "")) {
- g_debug ("Suggesting admin user: %s", name);
- gtk_entry_set_text (GTK_ENTRY (priv->join_name), name);
- } else {
- gtk_widget_grab_focus (GTK_WIDGET (priv->join_name));
- }
-
- } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
- g_debug ("Bad host name: %s", error->message);
- set_entry_validation_error (GTK_ENTRY (priv->join_computer), error->message);
-
- } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
- g_debug ("Bad admin password: %s", error->message);
- set_entry_validation_error (GTK_ENTRY (priv->join_password), error->message);
-
- } else {
- g_debug ("Admin login failure: %s", error->message);
- g_dbus_error_strip_remote_error (error);
- set_entry_validation_error (GTK_ENTRY (priv->join_name), error->message);
- }
-
- g_debug ("Showing admin password dialog");
- gtk_window_set_transient_for (GTK_WINDOW (priv->join_dialog),
- GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (page))));
- gtk_window_set_modal (GTK_WINDOW (priv->join_dialog), TRUE);
- gtk_window_present (GTK_WINDOW (priv->join_dialog));
-
- priv->join_prompted = TRUE;
- g_object_unref (kerberos);
- g_object_unref (membership);
-
- /* And now we wait for on_join_response() */
-}
-
-static void
-on_join_login (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GError *error = NULL;
- GBytes *creds;
-
- um_realm_login_finish (priv->realm, result, &creds, &error);
-
- /* Logged in as admin successfully, use creds to join domain */
- if (error == NULL) {
- if (!um_realm_join_as_admin (priv->realm,
- gtk_entry_get_text (GTK_ENTRY (priv->join_name)),
- gtk_entry_get_text (GTK_ENTRY (priv->join_password)),
- creds, NULL, on_realm_joined, page)) {
- show_error_dialog (page, _("No supported way to authenticate with this domain"), NULL);
- g_message ("Authenticating as admin is not supported by the realm");
- }
-
- g_bytes_unref (creds);
-
- /* Couldn't login as admin, show prompt again */
- } else {
- join_show_prompt (page, error);
- g_message ("Couldn't log in as admin to join domain: %s", error->message);
- g_error_free (error);
- }
-}
-
-static void
-on_realm_joined (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GError *error = NULL;
-
- um_realm_join_finish (priv->realm, result, &error);
-
- /* Yay, joined the domain, register the user locally */
- if (error == NULL) {
- g_debug ("Joining realm completed successfully");
- enterprise_permit_user_login (page, priv->realm);
-
- /* Credential failure while joining domain, prompt for admin creds */
- } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN) ||
- g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD) ||
- g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_HOSTNAME)) {
- g_debug ("Joining realm failed due to credentials or host name");
-
- join_show_prompt (page, error);
-
- /* Other failure */
- } else {
- show_error_dialog (page, _("Failed to join domain"), error);
- g_message ("Failed to join the domain: %s", error->message);
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
- }
-
- g_clear_error (&error);
-}
-
-static void
-on_realm_login (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GError *error = NULL;
- GBytes *creds = NULL;
-
- um_realm_login_finish (priv->realm, result, &creds, &error);
-
- /*
- * User login is valid, but cannot authenticate right now (eg: user needs
- * to change password at next login etc.)
- */
- if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_CANNOT_AUTH)) {
- g_clear_error (&error);
- creds = NULL;
- }
-
- if (error == NULL) {
-
- /* Already joined to the domain, just register this user */
- if (um_realm_is_configured (priv->realm)) {
- g_debug ("Already joined to this realm");
- enterprise_permit_user_login (page, priv->realm);
-
- /* Join the domain, try using the user's creds */
- } else if (creds == NULL ||
- !um_realm_join_as_user (priv->realm,
- gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)),
- gtk_entry_get_text (GTK_ENTRY (priv->enterprise_password)),
- creds, priv->cancellable,
- on_realm_joined,
- page)) {
-
- /* If we can't do user auth, try to authenticate as admin */
- g_debug ("Cannot join with user credentials");
-
- join_show_prompt (page, error);
- }
-
- g_bytes_unref (creds);
-
- /* A problem with the user's login name or password */
- } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN)) {
- g_debug ("Problem with the user's login: %s", error->message);
- set_entry_validation_error (GTK_ENTRY (priv->enterprise_login), error->message);
- gtk_widget_grab_focus (priv->enterprise_login);
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
-
- } else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
- g_debug ("Problem with the user's password: %s", error->message);
- set_entry_validation_error (GTK_ENTRY (priv->enterprise_password), error->message);
- gtk_widget_grab_focus (priv->enterprise_password);
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
-
- /* Other login failure */
- } else {
- show_error_dialog (page, _("Failed to log into domain"), error);
- g_message ("Couldn't log in as user: %s", error->message);
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
- }
-
- g_clear_error (&error);
-}
-
-static void
-enterprise_check_login (GisAccountPage *page)
-{
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
- g_assert (priv->realm);
-
- um_realm_login (priv->realm,
- gtk_entry_get_text (GTK_ENTRY (priv->enterprise_login)),
- gtk_entry_get_text (GTK_ENTRY (priv->enterprise_password)),
- priv->cancellable,
- on_realm_login,
- page);
-}
-
-static void
-on_realm_discover_input (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GError *error = NULL;
- GList *realms;
-
- realms = um_realm_manager_discover_finish (priv->realm_manager,
- result, &error);
-
- /* Found a realm, log user into domain */
- if (error == NULL) {
- g_assert (realms != NULL);
- priv->realm = g_object_ref (realms->data);
- enterprise_check_login (page);
- g_list_free_full (realms, g_object_unref);
-
- } else {
- /* The domain is likely invalid */
- g_dbus_error_strip_remote_error (error);
- g_message ("Couldn't discover domain: %s", error->message);
- gtk_widget_grab_focus (priv->enterprise_domain_entry);
- set_entry_validation_error (GTK_ENTRY (priv->enterprise_domain_entry), error->message);
- gis_page_apply_complete (GIS_PAGE (page), FALSE);
- g_error_free (error);
- }
-}
-
-static void
-enterprise_add_user (GisAccountPage *page)
-{
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GtkTreeIter iter;
-
- priv->join_prompted = FALSE;
- g_clear_object (&priv->realm);
-
- /* Already know about this realm, try to login as user */
- if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->enterprise_domain), &iter)) {
- gtk_tree_model_get (gtk_combo_box_get_model (GTK_COMBO_BOX (priv->enterprise_domain)),
- &iter, 1, &priv->realm, -1);
- enterprise_check_login (page);
-
- /* Something the user typed, we need to discover realm */
- } else {
- um_realm_manager_discover (priv->realm_manager,
- gtk_entry_get_text (GTK_ENTRY (priv->enterprise_domain_entry)),
- priv->cancellable,
- on_realm_discover_input,
- page);
- }
-}
-
-static gchar *
-realm_get_name (UmRealmObject *realm)
-{
- UmRealmCommon *common;
- gchar *name;
-
- common = um_realm_object_get_common (realm);
- name = g_strdup (um_realm_common_get_name (common));
- g_object_unref (common);
-
- return name;
-}
-
-static gboolean
-model_contains_realm (GtkTreeModel *model,
- const gchar *realm_name)
-{
- gboolean contains = FALSE;
- GtkTreeIter iter;
- gboolean match;
- gchar *name;
- gboolean ret;
-
- ret = gtk_tree_model_get_iter_first (model, &iter);
- while (ret) {
- gtk_tree_model_get (model, &iter, 0, &name, -1);
- match = (g_strcmp0 (name, realm_name) == 0);
- g_free (name);
- if (match) {
- g_debug ("ignoring duplicate realm: %s", realm_name);
- contains = TRUE;
- break;
- }
- ret = gtk_tree_model_iter_next (model, &iter);
- }
-
- return contains;
-}
-
-static void
-enterprise_add_realm (GisAccountPage *page,
- UmRealmObject *realm)
-{
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GtkTreeIter iter;
- gchar *name;
-
- name = realm_get_name (realm);
-
- /*
- * Don't add a second realm if we already have one with this name.
- * Sometimes realmd returns two realms for the same name, if it has
- * different ways to use that realm. The first one that realmd
- * returns is the one it prefers.
- */
-
- if (!model_contains_realm (GTK_TREE_MODEL (priv->enterprise_realms_model), name)) {
- gtk_list_store_append (GTK_LIST_STORE (priv->enterprise_realms_model), &iter);
- gtk_list_store_set (GTK_LIST_STORE (priv->enterprise_realms_model), &iter,
- 0, name,
- 1, realm,
- -1);
-
- if (!priv->domain_chosen && um_realm_is_configured (realm))
- gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->enterprise_domain), &iter);
-
- g_debug ("added realm to drop down: %s %s", name,
- g_dbus_object_get_object_path (G_DBUS_OBJECT (realm)));
- }
-
- g_free (name);
-}
-
-static void
-on_manager_realm_added (UmRealmManager *manager,
- UmRealmObject *realm,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- enterprise_add_realm (page, realm);
-}
-
-static void
-on_realm_manager_created (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
- GError *error = NULL;
- GList *realms, *l;
-
- g_clear_object (&priv->realm_manager);
- priv->realm_manager = um_realm_manager_new_finish (result, &error);
-
- if (error != NULL) {
- g_warning ("Couldn't contact realmd service: %s", error->message);
- g_error_free (error);
- return;
- }
-
- /* Lookup all the realm objects */
- realms = um_realm_manager_get_realms (priv->realm_manager);
- for (l = realms; l != NULL; l = g_list_next (l))
- enterprise_add_realm (page, l->data);
-
- g_list_free (realms);
- g_signal_connect (priv->realm_manager, "realm-added",
- G_CALLBACK (on_manager_realm_added), page);
-
- /* When no realms try to discover a sensible default, triggers realm-added signal */
- um_realm_manager_discover (priv->realm_manager, "", NULL, NULL, NULL);
- set_has_enterprise (page, TRUE);
-}
-
-static void
-on_realmd_appeared (GDBusConnection *connection,
- const gchar *name,
- const gchar *name_owner,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- um_realm_manager_new (NULL, on_realm_manager_created, page);
-}
-
-static void
-on_realmd_disappeared (GDBusConnection *unused1,
- const gchar *unused2,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
- if (priv->realm_manager != NULL) {
- g_signal_handlers_disconnect_by_func (priv->realm_manager,
- on_manager_realm_added,
- page);
- g_clear_object (&priv->realm_manager);
- }
-
- set_has_enterprise (page, FALSE);
-}
-
-static void
-on_domain_changed (GtkComboBox *widget,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
- priv->domain_chosen = TRUE;
- update_page_validation (page);
- clear_entry_validation_error (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget))));
-}
-
-static void
-on_entry_changed (GtkEditable *editable,
- gpointer user_data)
-{
- GisAccountPage *page = user_data;
- update_page_validation (page);
- clear_entry_validation_error (GTK_ENTRY (editable));
-}
-
-static void
toggle_mode (GtkToggleButton *button,
gpointer user_data)
{
@@ -798,8 +150,8 @@ gis_account_page_apply (GisPage *gis_page,
case UM_LOCAL:
return FALSE;
case UM_ENTERPRISE:
- priv->cancellable = g_object_ref (cancellable);
- enterprise_add_user (page);
+ return gis_account_page_enterprise_apply (GIS_ACCOUNT_PAGE_ENTERPRISE (priv->page_enterprise),
cancellable,
+ enterprise_apply_complete, page);
return TRUE;
default:
g_assert_not_reached ();
@@ -846,25 +198,16 @@ gis_account_page_constructed (GObject *object)
G_OBJECT_CLASS (gis_account_page_parent_class)->constructed (object);
- priv->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,
- page, NULL);
-
- g_signal_connect (priv->join_dialog, "response",
- G_CALLBACK (on_join_response), page);
- g_signal_connect (priv->enterprise_domain, "changed",
- G_CALLBACK (on_domain_changed), page);
- g_signal_connect (priv->enterprise_login, "changed",
- G_CALLBACK (on_entry_changed), page);
-
- priv->act_client = act_user_manager_get_default ();
-
g_signal_connect (priv->page_local, "validation-changed",
G_CALLBACK (on_validation_changed), page);
g_signal_connect (priv->page_local, "user-created",
G_CALLBACK (on_local_user_created), page);
+ g_signal_connect (priv->page_enterprise, "validation-changed",
+ G_CALLBACK (on_validation_changed), page);
+ g_signal_connect (priv->page_enterprise, "notify::visible",
+ G_CALLBACK (on_enterprise_visible_changed), page);
+
update_page_validation (page);
priv->has_enterprise = FALSE;
@@ -880,26 +223,6 @@ gis_account_page_constructed (GObject *object)
}
static void
-gis_account_page_dispose (GObject *object)
-{
- GisAccountPage *page = GIS_ACCOUNT_PAGE (object);
- GisAccountPagePrivate *priv = gis_account_page_get_instance_private (page);
-
- if (priv->realmd_watch)
- g_bus_unwatch_name (priv->realmd_watch);
-
- priv->realmd_watch = 0;
-
- g_cancellable_cancel (priv->cancellable);
-
- g_clear_object (&priv->realm_manager);
- g_clear_object (&priv->realm);
- g_clear_object (&priv->cancellable);
-
- G_OBJECT_CLASS (gis_account_page_parent_class)->dispose (object);
-}
-
-static void
gis_account_page_locale_changed (GisPage *page)
{
gis_page_set_title (GIS_PAGE (page), _("Login"));
@@ -914,18 +237,7 @@ gis_account_page_class_init (GisAccountPageClass *klass)
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
"/org/gnome/initial-setup/gis-account-page.ui");
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, page_local);
-
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, enterprise_login);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage,
enterprise_password);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, enterprise_domain);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage,
enterprise_domain_entry);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage,
enterprise_realms_model);
-
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_dialog);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_name);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_password);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_domain);
- gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, join_computer);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, page_enterprise);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, page_toggle);
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisAccountPage, notebook);
@@ -935,7 +247,6 @@ gis_account_page_class_init (GisAccountPageClass *klass)
page_class->apply = gis_account_page_apply;
page_class->save_data = gis_account_page_save_data;
object_class->constructed = gis_account_page_constructed;
- object_class->dispose = gis_account_page_dispose;
}
static void
@@ -943,6 +254,7 @@ gis_account_page_init (GisAccountPage *page)
{
g_resources_register (account_get_resource ());
g_type_ensure (GIS_TYPE_ACCOUNT_PAGE_LOCAL);
+ g_type_ensure (GIS_TYPE_ACCOUNT_PAGE_ENTERPRISE);
gtk_widget_init_template (GTK_WIDGET (page));
}
diff --git a/gnome-initial-setup/pages/account/gis-account-page.ui
b/gnome-initial-setup/pages/account/gis-account-page.ui
index 12dbdd5..d6781bb 100644
--- a/gnome-initial-setup/pages/account/gis-account-page.ui
+++ b/gnome-initial-setup/pages/account/gis-account-page.ui
@@ -24,200 +24,9 @@
</object>
</child>
<child>
- <object class="GtkGrid" id="enterprise_area">
+ <object class="GisAccountPageEnterprise" id="page_enterprise">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="row_spacing">6</property>
- <property name="column_spacing">12</property>
- <child>
- <object class="GtkFrame" id="sizer3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="enterprise_title">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
- <property name="margin_bottom">8</property>
- <property name="hexpand">True</property>
- <property name="label" translatable="yes">Create an Enterprise Account</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- <attribute name="scale" value="1.2"/>
- </attributes>
- </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="label4">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Domain</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">enterprise_domain</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label8">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Username</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">enterprise_login</property>
- </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="label9">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">end</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Password</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">enterprise_password</property>
- </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="enterprise_login">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- <property name="invisible_char">●</property>
- <property name="invisible_char_set">True</property>
- </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="enterprise_password">
- <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>
- </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>
- <child>
- <object class="GtkComboBox" id="enterprise_domain">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="model">enterprise_realms_model</property>
- <property name="has_entry">True</property>
- <property name="entry_text_column">0</property>
- <child internal-child="entry">
- <object class="GtkEntry" id="enterprise_domain_entry">
- <property name="can_focus">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label10">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_bottom">12</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Enterprise domain or realm name</property>
- <attributes>
- <attribute name="scale" value="0.8"/>
- </attributes>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="filler">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">4</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
</object>
- <packing>
- <property name="position">1</property>
- </packing>
</child>
</object>
<packing>
@@ -238,278 +47,4 @@
</object>
</child>
</template>
-
- <object class="GtkDialog" id="join_dialog">
- <property name="can_focus">False</property>
- <property name="border_width">10</property>
- <property name="resizable">False</property>
- <property name="modal">True</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkBox" id="dialog-vbox1">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="dialog-action_area1">
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="button1">
- <property name="label">gtk-cancel</property>
- <property name="use_action_appearance">False</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_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="button2">
- <property name="label" translatable="yes">C_ontinue</property>
- <property name="use_action_appearance">False</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>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="box2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="border_width">5</property>
- <property name="orientation">vertical</property>
- <property name="spacing">10</property>
- <child>
- <object class="GtkLabel" id="label71">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Domain Administrator Login</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- <attribute name="scale" value="1.2"/>
- </attributes>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label12">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="label" translatable="yes">In order to use enterprise logins, this computer
needs to be
- enrolled in the domain. Please have your network administrator
- type their domain password here, and choose a unique computer
- name for your computer.</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="grid1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_left">12</property>
- <property name="hexpand">True</property>
- <property name="row_spacing">6</property>
- <property name="column_spacing">12</property>
- <child>
- <object class="GtkLabel" id="label13">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Domain</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">join_domain</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="join_domain">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_top">5</property>
- <property name="margin_bottom">5</property>
- <property name="xalign">0</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label18">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">_Computer</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">join_computer</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="join_computer">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label14">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Administrator _Name</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">join_name</property>
- <style>
- <class name="dim-label"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="join_name">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- <property name="invisible_char">●</property>
- <property name="invisible_char_set">True</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label15">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">1</property>
- <property name="label" translatable="yes">Administrator Password</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">join_password</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="GtkEntry" id="join_password">
- <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>
- </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>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">button1</action-widget>
- <action-widget response="-5">button2</action-widget>
- </action-widgets>
- </object>
-
- <object class="GtkListStore" id="enterprise_realms_model">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- <!-- column-name gobject -->
- <column type="GObject"/>
- </columns>
- </object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]