Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* cc-enterprise-login-dialog.c |
3 |
|
|
* |
4 |
|
|
* Copyright 2023 Red Hat Inc |
5 |
|
|
* |
6 |
|
|
* This program is free software: you can redistribute it and/or modify |
7 |
|
|
* it under the terms of the GNU General Public License as published by |
8 |
|
|
* the Free Software Foundation, either version 3 of the License, or |
9 |
|
|
* (at your option) any later version. |
10 |
|
|
* |
11 |
|
|
* This program is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 |
|
|
* |
19 |
|
|
* SPDX-License-Identifier: GPL-3.0-or-later |
20 |
|
|
* |
21 |
|
|
* Author(s): |
22 |
|
|
* Felipe Borges <felipeborges@gnome.org> |
23 |
|
|
* Ondrej Holy <oholy@redhat.com> |
24 |
|
|
*/ |
25 |
|
|
|
26 |
|
|
#undef G_LOG_DOMAIN |
27 |
|
|
#define G_LOG_DOMAIN "cc-enterprise-login-dialog" |
28 |
|
|
|
29 |
|
|
#ifdef HAVE_CONFIG_H |
30 |
|
|
#include "config.h" |
31 |
|
|
#endif |
32 |
|
|
|
33 |
|
|
#include "cc-enterprise-login-dialog.h" |
34 |
|
|
#include "cc-entry-feedback.h" |
35 |
|
|
#include "cc-realm-manager.h" |
36 |
|
|
#include "cc-list-row.h" |
37 |
|
|
#include "user-utils.h" |
38 |
|
|
|
39 |
|
|
#include <adwaita.h> |
40 |
|
|
#include <act/act.h> |
41 |
|
|
#include <config.h> |
42 |
|
|
#include <errno.h> |
43 |
|
|
#include <locale.h> |
44 |
|
|
#include <glib/gi18n.h> |
45 |
|
|
#include <gio/gio.h> |
46 |
|
|
#include <gtk/gtk.h> |
47 |
|
|
|
48 |
|
|
#define DOMAIN_CHECK_TIMEOUT 600 |
49 |
|
|
|
50 |
|
|
struct _CcEnterpriseLoginDialog |
51 |
|
|
{ |
52 |
|
|
AdwDialog parent_instance; |
53 |
|
|
|
54 |
|
|
AdwNavigationView *navigation; |
55 |
|
|
AdwNavigationPage *offline_page; |
56 |
|
|
AdwNavigationPage *main_page; |
57 |
|
|
AdwNavigationPage *main_preferences_page; |
58 |
|
|
AdwNavigationPage *enroll_page; |
59 |
|
|
AdwPreferencesPage *enroll_preferences_page; |
60 |
|
|
AdwToastOverlay *toast_overlay; |
61 |
|
|
|
62 |
|
|
GtkButton *add_button; |
63 |
|
|
GtkSpinner *main_page_spinner; |
64 |
|
|
AdwEntryRow *domain_row; |
65 |
|
|
CcEntryFeedback *domain_feedback; |
66 |
|
|
gint domain_timeout_id; |
67 |
|
|
AdwEntryRow *username_row; |
68 |
|
|
AdwPasswordEntryRow *password_row; |
69 |
|
|
|
70 |
|
|
GtkButton *enroll_button; |
71 |
|
|
GtkSpinner *enroll_page_spinner; |
72 |
|
|
AdwEntryRow *admin_name_row; |
73 |
|
|
AdwPasswordEntryRow *admin_password_row; |
74 |
|
|
|
75 |
|
|
CcRealmManager *realm_manager; |
76 |
|
|
CcRealmObject *selected_realm; |
77 |
|
|
GNetworkMonitor *network_monitor; |
78 |
|
|
|
79 |
|
|
GCancellable *cancellable; |
80 |
|
|
}; |
81 |
|
|
|
82 |
|
✗ |
G_DEFINE_TYPE (CcEnterpriseLoginDialog, cc_enterprise_login_dialog, ADW_TYPE_DIALOG) |
83 |
|
|
|
84 |
|
|
static gboolean |
85 |
|
✗ |
add_button_is_valid (CcEnterpriseLoginDialog *self) |
86 |
|
|
{ |
87 |
|
✗ |
return (self->selected_realm != NULL) && |
88 |
|
✗ |
strlen (gtk_editable_get_text (GTK_EDITABLE (self->username_row))) > 0 && |
89 |
|
✗ |
strlen (gtk_editable_get_text (GTK_EDITABLE (self->password_row))) > 0; |
90 |
|
|
} |
91 |
|
|
|
92 |
|
|
static gboolean |
93 |
|
✗ |
enroll_button_is_valid (CcEnterpriseLoginDialog *self) |
94 |
|
|
{ |
95 |
|
✗ |
return strlen (gtk_editable_get_text (GTK_EDITABLE (self->admin_name_row))) > 0 && |
96 |
|
✗ |
strlen (gtk_editable_get_text (GTK_EDITABLE (self->admin_password_row))) > 0; |
97 |
|
|
} |
98 |
|
|
|
99 |
|
|
static void |
100 |
|
✗ |
show_operation_progress (CcEnterpriseLoginDialog *self, |
101 |
|
|
gboolean show) |
102 |
|
|
{ |
103 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->main_page_spinner), show); |
104 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->enroll_page_spinner), show); |
105 |
|
|
|
106 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->main_preferences_page), !show); |
107 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), !show && add_button_is_valid (self)); |
108 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->enroll_preferences_page), !show); |
109 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->enroll_button), !show && enroll_button_is_valid (self)); |
110 |
|
|
|
111 |
|
|
/* Hide passwords during operations. */ |
112 |
|
✗ |
if (show) |
113 |
|
|
{ |
114 |
|
|
GtkEditable *delegate; |
115 |
|
|
|
116 |
|
✗ |
delegate = gtk_editable_get_delegate (GTK_EDITABLE (self->password_row)); |
117 |
|
✗ |
gtk_text_set_visibility (GTK_TEXT (delegate), FALSE); |
118 |
|
|
|
119 |
|
✗ |
delegate = gtk_editable_get_delegate (GTK_EDITABLE (self->admin_password_row)); |
120 |
|
✗ |
gtk_text_set_visibility (GTK_TEXT (delegate), FALSE); |
121 |
|
|
} |
122 |
|
✗ |
} |
123 |
|
|
|
124 |
|
|
static void |
125 |
|
✗ |
cache_user_cb (GObject *source, |
126 |
|
|
GAsyncResult *result, |
127 |
|
|
gpointer user_data) |
128 |
|
|
{ |
129 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
130 |
|
✗ |
g_autoptr (ActUser) user = NULL; |
131 |
|
✗ |
g_autoptr(GError) error = NULL; |
132 |
|
|
|
133 |
|
✗ |
user = act_user_manager_cache_user_finish (ACT_USER_MANAGER (source), result, &error); |
134 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
135 |
|
✗ |
return; |
136 |
|
|
|
137 |
|
|
/* This is where we're finally done */ |
138 |
|
✗ |
if (user != NULL) |
139 |
|
|
{ |
140 |
|
✗ |
g_debug ("Successfully cached remote user: %s", act_user_get_user_name (user)); |
141 |
|
|
|
142 |
|
✗ |
adw_dialog_close (ADW_DIALOG (self)); |
143 |
|
|
} |
144 |
|
|
else |
145 |
|
|
{ |
146 |
|
✗ |
g_message ("Couldn't cache user account: %s", error->message); |
147 |
|
|
|
148 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (_("Failed to register account"))); |
149 |
|
✗ |
show_operation_progress (self, FALSE); |
150 |
|
|
} |
151 |
|
|
} |
152 |
|
|
|
153 |
|
|
static void |
154 |
|
✗ |
change_login_policy_cb (GObject *source, |
155 |
|
|
GAsyncResult *result, |
156 |
|
|
gpointer user_data) |
157 |
|
|
{ |
158 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
159 |
|
✗ |
g_autoptr(GError) error = NULL; |
160 |
|
|
|
161 |
|
✗ |
cc_realm_common_call_change_login_policy_finish (CC_REALM_COMMON (source), result, &error); |
162 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
163 |
|
✗ |
return; |
164 |
|
|
|
165 |
|
✗ |
if (error == NULL) |
166 |
|
|
{ |
167 |
|
|
ActUserManager *manager; |
168 |
|
✗ |
g_autofree gchar *login = NULL; |
169 |
|
|
|
170 |
|
|
/* |
171 |
|
|
* Now tell the account service about this user. The account service |
172 |
|
|
* should also lookup information about this via the realm and make |
173 |
|
|
* sure all that is functional. |
174 |
|
|
*/ |
175 |
|
✗ |
manager = act_user_manager_get_default (); |
176 |
|
✗ |
login = cc_realm_calculate_login (CC_REALM_COMMON (source), gtk_editable_get_text (GTK_EDITABLE (self->username_row))); |
177 |
|
|
|
178 |
|
✗ |
g_debug ("Caching remote user: %s", login); |
179 |
|
|
|
180 |
|
✗ |
act_user_manager_cache_user_async (manager, login, self->cancellable, cache_user_cb, g_object_ref (self)); |
181 |
|
|
} |
182 |
|
|
else |
183 |
|
|
{ |
184 |
|
✗ |
g_message ("Couldn't permit logins on account: %s", error->message); |
185 |
|
|
|
186 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (_("Failed to register account"))); |
187 |
|
✗ |
show_operation_progress (self, FALSE); |
188 |
|
|
} |
189 |
|
|
} |
190 |
|
|
|
191 |
|
|
static void |
192 |
|
✗ |
permit_user_login (CcEnterpriseLoginDialog *self) |
193 |
|
|
{ |
194 |
|
✗ |
g_autoptr(CcRealmCommon) common = NULL; |
195 |
|
|
|
196 |
|
✗ |
common = cc_realm_object_get_common (self->selected_realm); |
197 |
|
✗ |
if (common == NULL) |
198 |
|
|
{ |
199 |
|
✗ |
g_debug ("Failed to register account: failed to get d-bus interface"); |
200 |
|
|
|
201 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (_("Failed to register account"))); |
202 |
|
✗ |
show_operation_progress (self, FALSE); |
203 |
|
|
} |
204 |
|
|
else |
205 |
|
|
{ |
206 |
|
✗ |
g_autofree gchar *login = NULL; |
207 |
|
|
const gchar *add[2]; |
208 |
|
|
const gchar *remove[1]; |
209 |
|
|
GVariant *options; |
210 |
|
|
|
211 |
|
✗ |
login = cc_realm_calculate_login (common, gtk_editable_get_text (GTK_EDITABLE (self->username_row))); |
212 |
|
|
|
213 |
|
✗ |
g_debug ("Permitting login for: %s", login); |
214 |
|
|
|
215 |
|
✗ |
add[0] = login; |
216 |
|
✗ |
add[1] = NULL; |
217 |
|
✗ |
remove[0] = NULL; |
218 |
|
|
|
219 |
|
✗ |
options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0); |
220 |
|
|
|
221 |
|
✗ |
cc_realm_common_call_change_login_policy (common, "", |
222 |
|
|
add, remove, options, |
223 |
|
|
self->cancellable, |
224 |
|
|
change_login_policy_cb, |
225 |
|
|
g_object_ref (self)); |
226 |
|
|
} |
227 |
|
✗ |
} |
228 |
|
|
|
229 |
|
|
static void |
230 |
|
✗ |
realm_join_as_admin_cb (GObject *source, |
231 |
|
|
GAsyncResult *result, |
232 |
|
|
gpointer user_data) |
233 |
|
|
{ |
234 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
235 |
|
✗ |
g_autoptr(GError) error = NULL; |
236 |
|
✗ |
const gchar *message = NULL; |
237 |
|
|
|
238 |
|
✗ |
cc_realm_join_finish (CC_REALM_OBJECT (source), result, &error); |
239 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
240 |
|
✗ |
return; |
241 |
|
|
|
242 |
|
|
/* Yay, joined the domain, register the user locally */ |
243 |
|
✗ |
if (error == NULL) |
244 |
|
|
{ |
245 |
|
✗ |
g_debug ("Joining realm completed successfully"); |
246 |
|
|
|
247 |
|
✗ |
permit_user_login (self); |
248 |
|
✗ |
return; |
249 |
|
|
} |
250 |
|
|
/* Other failure */ |
251 |
|
|
else |
252 |
|
|
{ |
253 |
|
✗ |
g_message ("Failed to join the domain: %s", error->message); |
254 |
|
|
|
255 |
|
✗ |
message = _("Failed to join domain"); |
256 |
|
|
} |
257 |
|
|
|
258 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (message)); |
259 |
|
✗ |
show_operation_progress (self, FALSE); |
260 |
|
|
} |
261 |
|
|
|
262 |
|
|
static void |
263 |
|
✗ |
realm_login_as_admin_cb (GObject *source, |
264 |
|
|
GAsyncResult *result, |
265 |
|
|
gpointer user_data) |
266 |
|
|
{ |
267 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
268 |
|
✗ |
g_autoptr(GError) error = NULL; |
269 |
|
✗ |
g_autoptr(GBytes) creds = NULL; |
270 |
|
✗ |
const gchar *message = NULL; |
271 |
|
|
|
272 |
|
✗ |
creds = cc_realm_login_finish (result, &error); |
273 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
274 |
|
✗ |
return; |
275 |
|
|
|
276 |
|
|
/* Logged in as admin successfully, use creds to join domain */ |
277 |
|
✗ |
if (creds != NULL) |
278 |
|
|
{ |
279 |
|
✗ |
if (cc_realm_join_as_admin (self->selected_realm, |
280 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->admin_name_row)), |
281 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->admin_password_row)), |
282 |
|
✗ |
creds, self->cancellable, |
283 |
|
|
realm_join_as_admin_cb, g_object_ref (self))) |
284 |
|
|
{ |
285 |
|
✗ |
return; |
286 |
|
|
} |
287 |
|
|
|
288 |
|
✗ |
g_message ("Authenticating as admin is not supported by the realm"); |
289 |
|
|
|
290 |
|
✗ |
message = _("No supported way to authenticate with this domain"); |
291 |
|
|
} |
292 |
|
|
|
293 |
|
✗ |
show_operation_progress (self, FALSE); |
294 |
|
|
|
295 |
|
|
/* A problem with the admin's login name or password */ |
296 |
|
✗ |
if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_LOGIN)) |
297 |
|
|
{ |
298 |
|
✗ |
g_debug ("Bad admin login: %s", error->message); |
299 |
|
|
|
300 |
|
✗ |
message = _("That login name didn’t work"); |
301 |
|
✗ |
gtk_widget_grab_focus (GTK_WIDGET (self->admin_name_row)); |
302 |
|
|
} |
303 |
|
✗ |
else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_PASSWORD)) |
304 |
|
|
{ |
305 |
|
✗ |
g_debug ("Bad admin password: %s", error->message); |
306 |
|
|
|
307 |
|
✗ |
message = _("That login password didn’t work"); |
308 |
|
✗ |
gtk_widget_grab_focus (GTK_WIDGET (self->admin_password_row)); |
309 |
|
|
} |
310 |
|
✗ |
else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_HOSTNAME)) |
311 |
|
|
{ |
312 |
|
✗ |
g_debug ("Bad host name: %s", error->message); |
313 |
|
|
|
314 |
|
✗ |
message = _("That hostname didn’t work"); |
315 |
|
|
} |
316 |
|
|
/* Other login failure */ |
317 |
|
|
else |
318 |
|
|
{ |
319 |
|
✗ |
g_message ("Admin login failure: %s", error->message); |
320 |
|
|
|
321 |
|
✗ |
message = _("Failed to log into domain"); |
322 |
|
|
} |
323 |
|
|
|
324 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (message)); |
325 |
|
|
} |
326 |
|
|
|
327 |
|
|
static void |
328 |
|
✗ |
on_enroll_button_clicked_cb (CcEnterpriseLoginDialog *self) |
329 |
|
|
{ |
330 |
|
✗ |
g_debug ("Logging in as admin user: %s", gtk_editable_get_text (GTK_EDITABLE (self->admin_name_row))); |
331 |
|
|
|
332 |
|
✗ |
show_operation_progress (self, TRUE); |
333 |
|
|
|
334 |
|
|
/* Prompted for some admin credentials, try to use them to log in */ |
335 |
|
✗ |
cc_realm_login (self->selected_realm, |
336 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->admin_name_row)), |
337 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->admin_password_row)), |
338 |
|
|
self->cancellable, |
339 |
|
|
realm_login_as_admin_cb, |
340 |
|
|
g_object_ref (self)); |
341 |
|
✗ |
} |
342 |
|
|
|
343 |
|
|
static void |
344 |
|
✗ |
enroll_page_validate (CcEnterpriseLoginDialog *self) |
345 |
|
|
{ |
346 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->enroll_button), enroll_button_is_valid (self)); |
347 |
|
✗ |
} |
348 |
|
|
|
349 |
|
|
static void |
350 |
|
✗ |
clear_enroll_page (CcEnterpriseLoginDialog *self) |
351 |
|
|
{ |
352 |
|
✗ |
gtk_editable_set_text (GTK_EDITABLE (self->admin_name_row), ""); |
353 |
|
✗ |
gtk_editable_set_text (GTK_EDITABLE (self->admin_password_row), ""); |
354 |
|
✗ |
} |
355 |
|
|
|
356 |
|
|
static void |
357 |
|
✗ |
show_enroll_page (CcEnterpriseLoginDialog *self) |
358 |
|
|
{ |
359 |
|
|
const gchar *domain; |
360 |
|
✗ |
g_autofree gchar *description = NULL; |
361 |
|
|
|
362 |
|
✗ |
domain = gtk_editable_get_text (GTK_EDITABLE (self->domain_row)); |
363 |
|
|
|
364 |
|
|
/* Translators: The "%s" is a domain address (e.g. "demo1.freeipa.org"). */ |
365 |
|
✗ |
description = g_strdup_printf (_("To add an enterprise login account, this device needs to be enrolled with <b>%s</b>. " |
366 |
|
|
"To enroll, have your domain administrator enter their name and password."), |
367 |
|
|
domain); |
368 |
|
✗ |
adw_preferences_page_set_description (self->enroll_preferences_page, description); |
369 |
|
|
|
370 |
|
✗ |
if (strlen (gtk_editable_get_text (GTK_EDITABLE (self->admin_name_row))) == 0) |
371 |
|
|
{ |
372 |
|
✗ |
g_autoptr(CcRealmKerberosMembership) membership = NULL; |
373 |
|
✗ |
g_autoptr(CcRealmKerberos) kerberos = NULL; |
374 |
|
|
const gchar *name; |
375 |
|
|
|
376 |
|
✗ |
kerberos = cc_realm_object_get_kerberos (self->selected_realm); |
377 |
|
✗ |
membership = cc_realm_object_get_kerberos_membership (self->selected_realm); |
378 |
|
✗ |
name = cc_realm_kerberos_membership_get_suggested_administrator (membership); |
379 |
|
✗ |
if (name != NULL && !g_str_equal (name, "")) |
380 |
|
|
{ |
381 |
|
✗ |
g_debug ("Suggesting admin user: %s", name); |
382 |
|
|
|
383 |
|
✗ |
gtk_editable_set_text (GTK_EDITABLE (self->admin_name_row), name); |
384 |
|
|
} |
385 |
|
|
} |
386 |
|
|
|
387 |
|
✗ |
adw_navigation_view_push (self->navigation, self->enroll_page); |
388 |
|
✗ |
} |
389 |
|
|
|
390 |
|
|
static void |
391 |
|
✗ |
realm_join_as_user_cb (GObject *source, |
392 |
|
|
GAsyncResult *result, |
393 |
|
|
gpointer user_data) |
394 |
|
|
{ |
395 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
396 |
|
✗ |
g_autoptr(GError) error = NULL; |
397 |
|
|
|
398 |
|
✗ |
cc_realm_join_finish (CC_REALM_OBJECT (source), result, &error); |
399 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
400 |
|
✗ |
return; |
401 |
|
|
|
402 |
|
|
/* Yay, joined the domain, register the user locally */ |
403 |
|
✗ |
if (error == NULL) |
404 |
|
|
{ |
405 |
|
✗ |
g_debug ("Joining realm completed successfully"); |
406 |
|
|
|
407 |
|
✗ |
permit_user_login (self); |
408 |
|
✗ |
return; |
409 |
|
|
} |
410 |
|
|
/* Credential failure while joining domain, prompt for admin creds */ |
411 |
|
✗ |
else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_LOGIN) || |
412 |
|
✗ |
g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_PASSWORD) || |
413 |
|
✗ |
g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_HOSTNAME)) |
414 |
|
|
{ |
415 |
|
✗ |
g_debug ("Joining realm failed due to credentials"); |
416 |
|
|
|
417 |
|
✗ |
show_enroll_page (self); |
418 |
|
|
} |
419 |
|
|
/* Other failure */ |
420 |
|
|
else |
421 |
|
|
{ |
422 |
|
✗ |
g_message ("Failed to join the domain: %s", error->message); |
423 |
|
|
|
424 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (_("Failed to join domain"))); |
425 |
|
|
} |
426 |
|
|
|
427 |
|
✗ |
show_operation_progress (self, FALSE); |
428 |
|
|
} |
429 |
|
|
|
430 |
|
|
static void |
431 |
|
✗ |
realm_login_cb (GObject *source, |
432 |
|
|
GAsyncResult *result, |
433 |
|
|
gpointer user_data) |
434 |
|
|
{ |
435 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
436 |
|
✗ |
g_autoptr(GError) error = NULL; |
437 |
|
✗ |
g_autoptr(GBytes) creds = NULL; |
438 |
|
✗ |
const gchar *message = NULL; |
439 |
|
|
|
440 |
|
✗ |
creds = cc_realm_login_finish (result, &error); |
441 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
442 |
|
✗ |
return; |
443 |
|
|
|
444 |
|
|
/* |
445 |
|
|
* User login is valid, but cannot authenticate right now (eg: user needs |
446 |
|
|
* to change password at next login etc.) |
447 |
|
|
*/ |
448 |
|
✗ |
if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_CANNOT_AUTH)) |
449 |
|
✗ |
g_clear_error (&error); |
450 |
|
|
|
451 |
|
✗ |
if (error == NULL) |
452 |
|
|
{ |
453 |
|
|
/* Already joined to the domain, just register this user */ |
454 |
|
✗ |
if (cc_realm_is_configured (self->selected_realm)) |
455 |
|
|
{ |
456 |
|
✗ |
g_debug ("Already joined to this realm"); |
457 |
|
|
|
458 |
|
✗ |
permit_user_login (self); |
459 |
|
|
} |
460 |
|
|
/* Join the domain, try using the user's creds */ |
461 |
|
✗ |
else if (creds != NULL && |
462 |
|
✗ |
cc_realm_join_as_user (self->selected_realm, |
463 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->username_row)), |
464 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->password_row)), |
465 |
|
✗ |
creds, self->cancellable, |
466 |
|
|
realm_join_as_user_cb, g_object_ref (self))) |
467 |
|
|
{ |
468 |
|
✗ |
return; |
469 |
|
|
} |
470 |
|
|
/* If we can't do user auth, try to authenticate as admin */ |
471 |
|
|
else |
472 |
|
|
{ |
473 |
|
✗ |
g_debug ("Cannot join with user credentials"); |
474 |
|
|
|
475 |
|
✗ |
show_enroll_page (self); |
476 |
|
✗ |
show_operation_progress (self, FALSE); |
477 |
|
|
} |
478 |
|
|
|
479 |
|
✗ |
return; |
480 |
|
|
} |
481 |
|
|
|
482 |
|
✗ |
show_operation_progress (self, FALSE); |
483 |
|
|
|
484 |
|
|
/* A problem with the user's login name or password */ |
485 |
|
✗ |
if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_LOGIN)) |
486 |
|
|
{ |
487 |
|
✗ |
g_debug ("Problem with the user's login: %s", error->message); |
488 |
|
|
|
489 |
|
✗ |
message = _("That login name didn’t work"); |
490 |
|
✗ |
gtk_widget_grab_focus (GTK_WIDGET (self->username_row)); |
491 |
|
|
} |
492 |
|
✗ |
else if (g_error_matches (error, CC_REALM_ERROR, CC_REALM_ERROR_BAD_PASSWORD)) |
493 |
|
|
{ |
494 |
|
✗ |
g_debug ("Problem with the user's password: %s", error->message); |
495 |
|
|
|
496 |
|
✗ |
message = _("That login password didn’t work"); |
497 |
|
✗ |
gtk_widget_grab_focus (GTK_WIDGET (self->password_row)); |
498 |
|
|
} |
499 |
|
|
/* Other login failure */ |
500 |
|
|
else |
501 |
|
|
{ |
502 |
|
✗ |
g_message ("Couldn't log in as user: %s", error->message); |
503 |
|
|
|
504 |
|
✗ |
message = _("Failed to log into domain"); |
505 |
|
✗ |
gtk_widget_grab_focus (GTK_WIDGET (self->domain_row)); |
506 |
|
|
} |
507 |
|
|
|
508 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (message)); |
509 |
|
|
} |
510 |
|
|
|
511 |
|
|
static void |
512 |
|
✗ |
on_add_button_clicked_cb (CcEnterpriseLoginDialog *self) |
513 |
|
|
{ |
514 |
|
✗ |
show_operation_progress (self, TRUE); |
515 |
|
|
|
516 |
|
✗ |
cc_realm_login (self->selected_realm, |
517 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->username_row)), |
518 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->password_row)), |
519 |
|
|
self->cancellable, |
520 |
|
|
realm_login_cb, |
521 |
|
|
g_object_ref (self)); |
522 |
|
✗ |
} |
523 |
|
|
|
524 |
|
|
static void |
525 |
|
✗ |
main_page_validate (CcEnterpriseLoginDialog *self) |
526 |
|
|
{ |
527 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->add_button), add_button_is_valid (self)); |
528 |
|
✗ |
} |
529 |
|
|
|
530 |
|
|
static void |
531 |
|
✗ |
realm_manager_discover_cb (GObject *source, |
532 |
|
|
GAsyncResult *result, |
533 |
|
|
gpointer user_data) |
534 |
|
|
{ |
535 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
536 |
|
✗ |
g_autoptr(GError) error = NULL; |
537 |
|
|
GList *realms; |
538 |
|
|
|
539 |
|
✗ |
realms = cc_realm_manager_discover_finish (self->realm_manager, result, NULL); |
540 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
541 |
|
✗ |
return; |
542 |
|
|
|
543 |
|
|
/* Found a realm, log user into domain */ |
544 |
|
✗ |
if (realms != NULL) |
545 |
|
|
{ |
546 |
|
✗ |
self->selected_realm = g_object_ref (realms->data); |
547 |
|
|
|
548 |
|
✗ |
cc_entry_feedback_update (self->domain_feedback, "emblem-default-symbolic", _("Valid domain")); |
549 |
|
|
} |
550 |
|
|
else |
551 |
|
|
{ |
552 |
|
✗ |
cc_entry_feedback_update (self->domain_feedback, "dialog-warning-symbolic", _("Domain not found")); |
553 |
|
|
} |
554 |
|
|
|
555 |
|
✗ |
main_page_validate (self); |
556 |
|
|
|
557 |
|
✗ |
g_list_free_full (realms, g_object_unref); |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
static void |
561 |
|
✗ |
domain_validate (CcEnterpriseLoginDialog *self) |
562 |
|
|
{ |
563 |
|
✗ |
self->domain_timeout_id = 0; |
564 |
|
|
|
565 |
|
|
/* This is needed to stop previous calls to avoid rewriting feedback. */ |
566 |
|
✗ |
g_cancellable_cancel (self->cancellable); |
567 |
|
✗ |
g_object_unref (self->cancellable); |
568 |
|
✗ |
self->cancellable = g_cancellable_new (); |
569 |
|
|
|
570 |
|
✗ |
cc_realm_manager_discover (self->realm_manager, |
571 |
|
✗ |
gtk_editable_get_text (GTK_EDITABLE (self->domain_row)), |
572 |
|
|
self->cancellable, |
573 |
|
|
realm_manager_discover_cb, |
574 |
|
|
g_object_ref (self)); |
575 |
|
✗ |
} |
576 |
|
|
|
577 |
|
|
static void |
578 |
|
✗ |
on_domain_entry_changed_cb (CcEnterpriseLoginDialog *self) |
579 |
|
|
{ |
580 |
|
|
const gchar *domain; |
581 |
|
|
|
582 |
|
✗ |
if (self->realm_manager == NULL) |
583 |
|
✗ |
return; |
584 |
|
|
|
585 |
|
✗ |
g_clear_handle_id (&self->domain_timeout_id, g_source_remove); |
586 |
|
✗ |
clear_enroll_page (self); |
587 |
|
|
|
588 |
|
✗ |
domain = gtk_editable_get_text (GTK_EDITABLE (self->domain_row)); |
589 |
|
✗ |
if (strlen (domain) == 0) |
590 |
|
|
{ |
591 |
|
✗ |
cc_entry_feedback_reset (self->domain_feedback); |
592 |
|
✗ |
return; |
593 |
|
|
} |
594 |
|
|
|
595 |
|
✗ |
cc_entry_feedback_update (self->domain_feedback, "process-working-symbolic", _("Checking domain…")); |
596 |
|
✗ |
self->domain_timeout_id = g_timeout_add (DOMAIN_CHECK_TIMEOUT, (GSourceFunc)domain_validate, self); |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
static void |
600 |
|
✗ |
check_network_availability (CcEnterpriseLoginDialog *self) |
601 |
|
|
{ |
602 |
|
✗ |
if (!g_network_monitor_get_network_available (self->network_monitor)) |
603 |
|
|
{ |
604 |
|
✗ |
adw_navigation_view_pop_to_page (self->navigation, self->offline_page); |
605 |
|
|
} |
606 |
|
|
else |
607 |
|
|
{ |
608 |
|
✗ |
if (adw_navigation_view_get_visible_page (self->navigation) != self->main_page) |
609 |
|
✗ |
adw_navigation_view_push (self->navigation, self->main_page); |
610 |
|
|
} |
611 |
|
✗ |
} |
612 |
|
|
|
613 |
|
|
static void |
614 |
|
✗ |
on_network_changed_cb (GNetworkMonitor *monitor, |
615 |
|
|
gboolean available, |
616 |
|
|
gpointer user_data) |
617 |
|
|
{ |
618 |
|
✗ |
CcEnterpriseLoginDialog *self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
619 |
|
|
|
620 |
|
✗ |
check_network_availability (self); |
621 |
|
✗ |
} |
622 |
|
|
|
623 |
|
|
static void |
624 |
|
✗ |
realm_manager_new_cb (GObject *source, |
625 |
|
|
GAsyncResult *result, |
626 |
|
|
gpointer user_data) |
627 |
|
|
{ |
628 |
|
✗ |
g_autoptr(CcEnterpriseLoginDialog) self = CC_ENTERPRISE_LOGIN_DIALOG (user_data); |
629 |
|
✗ |
g_autoptr(GError) error = NULL; |
630 |
|
|
|
631 |
|
✗ |
self->realm_manager = cc_realm_manager_new_finish (result, &error); |
632 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
633 |
|
✗ |
return; |
634 |
|
|
|
635 |
|
✗ |
if (error != NULL) |
636 |
|
|
{ |
637 |
|
✗ |
g_warning ("Couldn't contact realmd service: %s", error->message); |
638 |
|
|
|
639 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, adw_toast_new (_("Failed to contact realmd service"))); |
640 |
|
|
} |
641 |
|
|
else |
642 |
|
|
{ |
643 |
|
✗ |
show_operation_progress (self, FALSE); |
644 |
|
|
} |
645 |
|
|
} |
646 |
|
|
|
647 |
|
|
static void |
648 |
|
✗ |
cc_enterprise_login_dialog_dispose (GObject *object) |
649 |
|
|
{ |
650 |
|
✗ |
CcEnterpriseLoginDialog *self = CC_ENTERPRISE_LOGIN_DIALOG (object); |
651 |
|
|
|
652 |
|
✗ |
if (self->cancellable) |
653 |
|
✗ |
g_cancellable_cancel (self->cancellable); |
654 |
|
✗ |
g_clear_object (&self->cancellable); |
655 |
|
|
|
656 |
|
✗ |
g_clear_object (&self->realm_manager); |
657 |
|
|
|
658 |
|
✗ |
g_signal_handlers_disconnect_by_data (self->network_monitor, self); |
659 |
|
|
|
660 |
|
✗ |
g_clear_handle_id (&self->domain_timeout_id, g_source_remove); |
661 |
|
|
|
662 |
|
✗ |
G_OBJECT_CLASS (cc_enterprise_login_dialog_parent_class)->dispose (object); |
663 |
|
✗ |
} |
664 |
|
|
|
665 |
|
|
static void |
666 |
|
✗ |
cc_enterprise_login_dialog_init (CcEnterpriseLoginDialog *self) |
667 |
|
|
{ |
668 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
669 |
|
|
|
670 |
|
✗ |
self->cancellable = g_cancellable_new (); |
671 |
|
|
|
672 |
|
✗ |
self->network_monitor = g_network_monitor_get_default (); |
673 |
|
✗ |
g_signal_connect_object (self->network_monitor, "network-changed", G_CALLBACK (on_network_changed_cb), self, 0); |
674 |
|
✗ |
check_network_availability (self); |
675 |
|
|
|
676 |
|
✗ |
show_operation_progress (self, TRUE); |
677 |
|
✗ |
cc_realm_manager_new (self->cancellable, realm_manager_new_cb, g_object_ref (self)); |
678 |
|
✗ |
} |
679 |
|
|
|
680 |
|
|
static void |
681 |
|
✗ |
cc_enterprise_login_dialog_class_init (CcEnterpriseLoginDialogClass * klass) |
682 |
|
|
{ |
683 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
684 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (klass); |
685 |
|
|
|
686 |
|
✗ |
object_class->dispose = cc_enterprise_login_dialog_dispose; |
687 |
|
|
|
688 |
|
✗ |
g_type_ensure (CC_TYPE_ENTRY_FEEDBACK); |
689 |
|
✗ |
g_type_ensure (CC_TYPE_LIST_ROW); |
690 |
|
|
|
691 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/system/users/cc-enterprise-login-dialog.ui"); |
692 |
|
|
|
693 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, add_button); |
694 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, admin_name_row); |
695 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, admin_password_row); |
696 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, domain_feedback); |
697 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, domain_row); |
698 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, enroll_button); |
699 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, enroll_page); |
700 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, enroll_page_spinner); |
701 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, enroll_preferences_page); |
702 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, main_page); |
703 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, main_page_spinner); |
704 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, main_preferences_page); |
705 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, navigation); |
706 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, offline_page); |
707 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, password_row); |
708 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, toast_overlay); |
709 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, CcEnterpriseLoginDialog, username_row); |
710 |
|
|
|
711 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, enroll_page_validate); |
712 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, main_page_validate); |
713 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_add_button_clicked_cb); |
714 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_domain_entry_changed_cb); |
715 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, on_enroll_button_clicked_cb); |
716 |
|
✗ |
} |
717 |
|
|
|
718 |
|
|
CcEnterpriseLoginDialog * |
719 |
|
✗ |
cc_enterprise_login_dialog_new (void) |
720 |
|
|
{ |
721 |
|
✗ |
return g_object_new (CC_TYPE_ENTERPRISE_LOGIN_DIALOG, NULL); |
722 |
|
|
} |
723 |
|
|
|