GCC Code Coverage Report


Directory: ./
File: panels/system/users/cc-user-page.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 305 0.0%
Functions: 0 34 0.0%
Branches: 0 125 0.0%

Line Branch Exec Source
1 /*
2 * cc-user-page.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 */
24
25 #undef G_LOG_DOMAIN
26 #define G_LOG_DOMAIN "cc-user-page"
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include "cc-user-page.h"
33 #include "cc-avatar-chooser.h"
34 #include "cc-fingerprint-dialog.h"
35 #include "cc-fingerprint-manager.h"
36 #include "cc-language-chooser.h"
37 #include "cc-list-row.h"
38 #include "cc-password-dialog.h"
39 #include "cc-permission-infobar.h"
40 #include "user-utils.h"
41
42 #include <config.h>
43 #include <errno.h>
44 #include <locale.h>
45 #include <glib/gi18n.h>
46 #include <gio/gio.h>
47 #include <gtk/gtk.h>
48
49 #define GNOME_DESKTOP_USE_UNSTABLE_API
50 #include <libgnome-desktop/gnome-languages.h>
51
52 #ifdef HAVE_MALCONTENT
53 #include <libmalcontent/malcontent.h>
54 #endif
55
56 struct _CcUserPage {
57 AdwNavigationPage parent_instance;
58
59 CcListRow *account_type_row;
60 GtkSwitch *account_type_switch;
61 GtkBox *action_area;
62 AdwAvatar *avatar;
63 CcAvatarChooser *avatar_chooser;
64 GtkMenuButton *avatar_edit_button;
65 GtkButton *avatar_remove_button;
66 AdwSwitchRow *auto_login_row;
67 CcListRow *fingerprint_row;
68 CcListRow *language_row;
69 AdwEntryRow *fullname_row;
70 #ifdef HAVE_MALCONTENT
71 CcListRow *parental_controls_row;
72 #endif
73 CcListRow *password_row;
74 CcPermissionInfobar *permission_infobar;
75 AdwSwitchRow *remove_local_files_choice;
76 GtkWidget *remove_user_button;
77 AdwMessageDialog *remove_local_user_dialog;
78
79 ActUser *user;
80 GSettings *login_screen_settings;
81 GPermission *permission;
82 CcFingerprintManager *fingerprint_manager;
83
84 gboolean locked;
85 gboolean editable;
86 gboolean can_be_demoted;
87 };
88
89 static GtkBuildableIface *parent_buildable_iface;
90 static void cc_user_page_buildable_init (GtkBuildableIface *iface);
91
92 G_DEFINE_TYPE_WITH_CODE (CcUserPage, cc_user_page, ADW_TYPE_NAVIGATION_PAGE,
93 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, cc_user_page_buildable_init))
94
95 enum {
96 PROP_0,
97 PROP_LOCKED,
98 PROP_EDITABLE,
99 PROP_IS_ADMIN,
100 PROP_IS_CURRENT_USER
101 };
102
103 static guint
104 get_num_active_admin (ActUserManager *um)
105 {
106 g_autoptr(GSList) list = NULL;
107 GSList *l;
108 guint num_admin = 0;
109
110 list = act_user_manager_list_users (um);
111 for (l = list; l != NULL; l = l->next) {
112 ActUser *u = l->data;
113 if (act_user_get_account_type (u) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR && !act_user_get_locked (u)) {
114 num_admin++;
115 }
116 }
117
118 return num_admin;
119 }
120
121 static gboolean
122 would_demote_only_admin (ActUser *user)
123 {
124 ActUserManager *um = act_user_manager_get_default ();
125
126 /* Prevent the user from demoting the only admin account.
127 * Returns TRUE when user is an administrator and there is only
128 * one enabled administrator. */
129 if (act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_STANDARD || act_user_get_locked (user)) {
130 return FALSE;
131 }
132
133 if (get_num_active_admin (um) > 1) {
134 return FALSE;
135 }
136
137 return TRUE;
138 }
139
140 static gboolean
141 get_autologin_possible (ActUser *user)
142 {
143 gboolean locked;
144 gboolean set_password_at_login;
145
146 locked = act_user_get_locked (user);
147 set_password_at_login = (act_user_get_password_mode (user) == ACT_USER_PASSWORD_MODE_SET_AT_LOGIN);
148
149 return !(locked || set_password_at_login);
150 }
151
152 static gchar *
153 get_user_language (ActUser *user)
154 {
155 g_autofree gchar *lang = NULL;
156
157 lang = g_strdup (act_user_get_language (user));
158 if (lang && *lang != '\0') {
159 return gnome_get_language_from_locale (lang, NULL);
160 }
161
162 return g_strdup ("—");
163 }
164
165 static const gchar *
166 get_invisible_text (void)
167 {
168 GtkWidget *entry;
169 gunichar invisible_char;
170 static gchar invisible_text[40];
171 gchar *p;
172 gint i;
173
174 entry = gtk_entry_new ();
175 invisible_char = gtk_entry_get_invisible_char (GTK_ENTRY (entry));
176 if (invisible_char == 0) {
177 invisible_char = 0x2022;
178 }
179
180 g_object_ref_sink (entry);
181 g_object_unref (entry);
182
183 /* five bullets */
184 p = invisible_text;
185 for (i = 0; i < 5; i++) {
186 p += g_unichar_to_utf8 (invisible_char, p);
187 }
188 *p = 0;
189
190 return invisible_text;
191 }
192
193 static const gchar *
194 get_password_mode_text (ActUser *user)
195 {
196 const gchar *text;
197
198 if (act_user_get_locked (user)) {
199 text = C_("Password mode", "Account disabled");
200 } else {
201 switch (act_user_get_password_mode (user)) {
202 case ACT_USER_PASSWORD_MODE_REGULAR:
203 text = get_invisible_text ();
204 break;
205 case ACT_USER_PASSWORD_MODE_SET_AT_LOGIN:
206 text = C_("Password mode", "To be set at next login");
207 break;
208 case ACT_USER_PASSWORD_MODE_NONE:
209 text = C_("Password mode", "None");
210 break;
211 default:
212 g_assert_not_reached ();
213 }
214 }
215
216 return text;
217 }
218
219 static void
220 account_type_changed (CcUserPage *self)
221 {
222 ActUserAccountType account_type;
223 gboolean is_admin;
224
225 is_admin = gtk_switch_get_active (self->account_type_switch);
226 account_type = is_admin ? ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR : ACT_USER_ACCOUNT_TYPE_STANDARD;
227
228 if (account_type != act_user_get_account_type (self->user)) {
229 act_user_set_account_type (self->user, account_type);
230 }
231 }
232
233 static void
234 update_generated_avatar (CcUserPage *self)
235 {
236 g_autoptr(GdkTexture) texture = NULL;
237
238 adw_avatar_set_custom_image (self->avatar, NULL);
239
240 texture = draw_avatar_to_texture (self->avatar, AVATAR_PIXEL_SIZE);
241 set_user_icon_data (self->user, texture, IMAGE_SOURCE_VALUE_GENERATED);
242 }
243
244 static void
245 fullname_entry_apply_cb (CcUserPage *self)
246 {
247 const gchar *text;
248
249 text = gtk_editable_get_text (GTK_EDITABLE (self->fullname_row));
250 if (g_strcmp0 (text, act_user_get_real_name (self->user)) != 0 && is_valid_name (text)) {
251 adw_avatar_set_text (self->avatar, text);
252
253 act_user_set_real_name (self->user, text);
254
255 if (adw_avatar_get_custom_image (self->avatar) == NULL) {
256 update_generated_avatar (self);
257 }
258
259 g_debug ("Updating real name to: %s", text);
260 }
261 }
262
263 static void
264 language_chooser_response (CcUserPage *self,
265 guint response_id,
266 CcLanguageChooser *chooser)
267 {
268 g_autofree gchar *language_name = NULL;
269 const gchar *selected_language;
270
271 if (response_id != GTK_RESPONSE_OK) {
272 gtk_window_destroy (GTK_WINDOW (chooser));
273
274 return;
275 }
276
277 selected_language = cc_language_chooser_get_language (chooser);
278 if (!selected_language) {
279 return;
280 }
281
282 if (g_strcmp0 (selected_language, act_user_get_language (self->user)) == 0) {
283 return;
284 }
285
286 act_user_set_language (self->user, selected_language);
287
288 language_name = gnome_get_language_from_locale (selected_language, NULL);
289 cc_list_row_set_secondary_label (self->language_row, language_name);
290
291 gtk_window_close (GTK_WINDOW (chooser));
292 }
293
294 static void
295 change_language (CcUserPage *self)
296 {
297 CcLanguageChooser *language_chooser;
298 const gchar *current_language;
299
300 current_language = act_user_get_language (self->user);
301 language_chooser = cc_language_chooser_new ();
302
303 g_signal_connect_object (language_chooser, "response",
304 G_CALLBACK (language_chooser_response), self,
305 G_CONNECT_SWAPPED);
306
307 if (current_language && *current_language != '\0') {
308 cc_language_chooser_set_language (language_chooser, current_language);
309 }
310
311 gtk_window_set_transient_for (GTK_WINDOW (language_chooser),
312 GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
313 gtk_window_present (GTK_WINDOW (language_chooser));
314 }
315
316 static void
317 change_password (CcUserPage *self)
318 {
319 CcPasswordDialog *dialog = cc_password_dialog_new (self->user);
320
321 adw_dialog_present (ADW_DIALOG (dialog), GTK_WIDGET (self));
322 }
323
324 static void
325 autologin_changed (CcUserPage *self)
326 {
327 ActUserManager *user_manager = act_user_manager_get_default ();
328 gboolean active;
329
330 active = adw_switch_row_get_active (self->auto_login_row);
331 if (active != act_user_get_automatic_login (self->user)) {
332 act_user_set_automatic_login (self->user, active);
333
334 if (act_user_get_automatic_login (self->user)) {
335 g_autoptr(GSList) list = NULL;
336 GSList *l;
337 list = act_user_manager_list_users (user_manager);
338 for (l = list; l != NULL; l = l->next) {
339 ActUser *u = l->data;
340 if (act_user_get_uid (u) != act_user_get_uid (self->user)) {
341 act_user_set_automatic_login (self->user, FALSE);
342 }
343 }
344 }
345 }
346 }
347
348 static void
349 update_fingerprint_row_state (CcUserPage *self,
350 GParamSpec *spec,
351 CcFingerprintManager *manager)
352 {
353 CcFingerprintState state = cc_fingerprint_manager_get_state (manager);
354 gboolean visible = FALSE;
355
356 visible = (act_user_get_uid (self->user) == getuid () &&
357 act_user_is_local_account (self->user) &&
358 (self->login_screen_settings &&
359 g_settings_get_boolean (self->login_screen_settings,
360 "enable-fingerprint-authentication")));
361 gtk_widget_set_visible (GTK_WIDGET (self->fingerprint_row), visible);
362 if (!visible)
363 return;
364
365 if (state != CC_FINGERPRINT_STATE_UPDATING)
366 gtk_widget_set_visible (GTK_WIDGET (self->fingerprint_row),
367 state != CC_FINGERPRINT_STATE_NONE);
368
369 gtk_widget_set_sensitive (GTK_WIDGET (self->fingerprint_row),
370 state != CC_FINGERPRINT_STATE_UPDATING);
371
372 if (state == CC_FINGERPRINT_STATE_ENABLED)
373 cc_list_row_set_secondary_label (self->fingerprint_row, _("Enabled"));
374 else if (state == CC_FINGERPRINT_STATE_DISABLED)
375 cc_list_row_set_secondary_label (self->fingerprint_row, _("Disabled"));
376 }
377
378 static void
379 change_fingerprint (CcUserPage *self)
380 {
381 CcFingerprintDialog *dialog;
382
383 dialog = cc_fingerprint_dialog_new (self->fingerprint_manager);
384 gtk_window_set_transient_for (GTK_WINDOW (dialog),
385 GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self))));
386 gtk_window_present (GTK_WINDOW (dialog));
387 }
388
389 static void
390 delete_user_done (ActUserManager *manager,
391 GAsyncResult *res)
392 {
393 g_autoptr(GError) error = NULL;
394
395 if (!act_user_manager_delete_user_finish (manager, res, &error)) {
396 if (!g_error_matches (error, ACT_USER_MANAGER_ERROR,
397 ACT_USER_MANAGER_ERROR_PERMISSION_DENIED))
398 g_critical ("Failed to delete user: %s", error->message);
399 }
400 }
401
402 static void
403 remove_local_user_response (CcUserPage *self,
404 gchar *response,
405 AdwMessageDialog *dialog)
406 {
407 gboolean remove_files;
408
409 g_assert (ADW_IS_SWITCH_ROW (self->remove_local_files_choice));
410
411 if (g_strcmp0 (response, "cancel") == 0) {
412 return;
413 }
414
415 /* remove autologin */
416 if (act_user_get_automatic_login (self->user)) {
417 act_user_set_automatic_login (self->user, FALSE);
418 }
419
420 /* Prevent user to click again while deleting, issue #2341 */
421 gtk_widget_set_sensitive (GTK_WIDGET (self->remove_user_button), FALSE);
422
423 remove_files = adw_switch_row_get_active (self->remove_local_files_choice);
424 act_user_manager_delete_user_async (act_user_manager_get_default (),
425 self->user,
426 remove_files,
427 NULL,
428 (GAsyncReadyCallback)delete_user_done,
429 NULL);
430 }
431
432 static void
433 remove_user (CcUserPage *self)
434 {
435 GtkWindow *parent;
436
437 // TODO: Handle enterprise accounts
438 parent = GTK_WINDOW (gtk_widget_get_native (GTK_WIDGET (self)));
439 gtk_window_set_transient_for (GTK_WINDOW (self->remove_local_user_dialog), parent);
440 adw_message_dialog_format_heading (self->remove_local_user_dialog, _("Remove %s?"), get_real_or_user_name (self->user));
441 gtk_window_present (GTK_WINDOW (self->remove_local_user_dialog));
442 }
443
444 static void
445 remove_avatar (CcUserPage *self)
446 {
447 gtk_widget_set_visible (GTK_WIDGET (self->avatar_remove_button), FALSE);
448 update_generated_avatar (self);
449 }
450
451 static void
452 cc_user_page_buildable_add_child (GtkBuildable *buildable,
453 GtkBuilder *builder,
454 GObject *child,
455 const gchar *type)
456 {
457 CcUserPage *self = CC_USER_PAGE (buildable);
458
459 gtk_box_append (self->action_area, GTK_WIDGET (child));
460 }
461
462 static void
463 cc_user_page_buildable_init (GtkBuildableIface *iface)
464 {
465 parent_buildable_iface = g_type_interface_peek_parent (iface);
466 iface->add_child = cc_user_page_buildable_add_child;
467 }
468
469 static gboolean
470 is_current_user (ActUser *user)
471 {
472 if (!user)
473 return FALSE;
474
475 return act_user_get_uid (user) == getuid ();
476 }
477
478 static void
479 update_editable_state (CcUserPage *self)
480 {
481 self->editable = (is_current_user (self->user) || !self->locked) && act_user_is_local_account (self->user);
482 g_object_notify (G_OBJECT (self), "editable");
483 }
484
485 #ifdef HAVE_MALCONTENT
486 static void
487 spawn_malcontent_control (CcUserPage *self)
488 {
489 g_autoptr(GError) error = NULL;
490 const gchar *argv[] = { "malcontent-control",
491 #ifdef HAVE_MALCONTENT_0_10
492 "--user", act_user_get_user_name (self->user),
493 #endif /* HAVE_MALCONTENT_0_10 */
494 NULL
495 };
496
497 /* no-op if the user is administrator */
498 if (act_user_get_account_type (self->user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR) {
499 g_debug ("Not launching malcontent because selected user is an admin");
500
501 return;
502 }
503
504 if (!g_spawn_async (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error)) {
505 g_debug ("Couldn't launch malcontent-control: %s", error->message);
506 }
507 }
508
509 static gboolean
510 is_parental_controls_enabled_for_user (ActUser *user)
511 {
512 g_autoptr(MctManager) manager = NULL;
513 g_autoptr(MctAppFilter) app_filter = NULL;
514 g_autoptr(GDBusConnection) system_bus = NULL;
515 g_autoptr(GError) error = NULL;
516
517 /* FIXME: should become asynchronous */
518 system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
519 if (system_bus == NULL) {
520 g_warning ("Error getting system bus while trying to show user details: %s", error->message);
521 return FALSE;
522 }
523
524 manager = mct_manager_new (system_bus);
525 app_filter = mct_manager_get_app_filter (manager,
526 act_user_get_uid (user),
527 MCT_MANAGER_GET_VALUE_FLAGS_NONE,
528 NULL,
529 &error);
530 if (error) {
531 if (!g_error_matches (error, MCT_MANAGER_ERROR, MCT_MANAGER_ERROR_DISABLED))
532 g_warning ("Error retrieving app filter for user %s: %s",
533 act_user_get_user_name (user),
534 error->message);
535
536 return FALSE;
537 }
538
539 return mct_app_filter_is_enabled (app_filter);
540 }
541 #endif
542
543 static void
544 cc_user_page_dispose (GObject *object)
545 {
546 CcUserPage *self = CC_USER_PAGE (object);
547
548 g_clear_object (&self->login_screen_settings);
549
550 G_OBJECT_CLASS (cc_user_page_parent_class)->dispose (object);
551 }
552
553 static void
554 cc_user_page_get_property (GObject *object,
555 guint prop_id,
556 GValue *value,
557 GParamSpec *pspec)
558 {
559 CcUserPage *self = CC_USER_PAGE (object);
560
561 switch (prop_id) {
562 case PROP_EDITABLE:
563 g_value_set_boolean (value, self->editable);
564 break;
565 case PROP_LOCKED:
566 g_value_set_boolean (value, self->locked);
567 break;
568 case PROP_IS_ADMIN:
569 if (!self->user)
570 g_value_set_boolean (value, FALSE);
571 else
572 g_value_set_boolean (value, act_user_get_account_type (self->user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR);
573
574 break;
575 case PROP_IS_CURRENT_USER:
576 g_value_set_boolean (value, is_current_user (self->user));
577 break;
578 default:
579 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
580 }
581 }
582
583 static void
584 cc_user_page_set_property (GObject *object,
585 guint prop_id,
586 const GValue *value,
587 GParamSpec *pspec)
588 {
589 CcUserPage *self = CC_USER_PAGE (object);
590
591 switch (prop_id) {
592 case PROP_EDITABLE:
593 update_editable_state (self);
594 break;
595 case PROP_LOCKED:
596 self->locked = g_value_get_boolean (value);
597 break;
598 default:
599 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
600 }
601 }
602
603 static void
604 cc_user_page_class_init (CcUserPageClass * klass)
605 {
606 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
607 GObjectClass *object_class = G_OBJECT_CLASS (klass);
608
609 object_class->dispose = cc_user_page_dispose;
610 object_class->get_property = cc_user_page_get_property;
611 object_class->set_property = cc_user_page_set_property;
612
613 g_object_class_install_property (object_class,
614 PROP_EDITABLE,
615 g_param_spec_boolean ("editable",
616 "Editable",
617 "Whether the panel is editable",
618 FALSE,
619 G_PARAM_READWRITE));
620 g_object_class_install_property (object_class,
621 PROP_LOCKED,
622 g_param_spec_boolean ("locked",
623 "Locked",
624 "Whether changes require authentication",
625 TRUE,
626 G_PARAM_READWRITE));
627 g_object_class_install_property (object_class,
628 PROP_IS_ADMIN,
629 g_param_spec_boolean ("is-admin",
630 "Is Admin",
631 "Whether the displayed user is administrator",
632 FALSE,
633 G_PARAM_READABLE));
634 g_object_class_install_property (object_class,
635 PROP_IS_CURRENT_USER,
636 g_param_spec_boolean ("is-current-user",
637 "Is Current User",
638 "Whether the displayed user is the current logged user",
639 FALSE,
640 G_PARAM_READABLE));
641 g_type_ensure (CC_TYPE_LIST_ROW);
642
643 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/system/users/cc-user-page.ui");
644
645 gtk_widget_class_bind_template_child (widget_class, CcUserPage, action_area);
646 gtk_widget_class_bind_template_child (widget_class, CcUserPage, avatar);
647 gtk_widget_class_bind_template_child (widget_class, CcUserPage, avatar_edit_button);
648 gtk_widget_class_bind_template_child (widget_class, CcUserPage, avatar_remove_button);
649 gtk_widget_class_bind_template_child (widget_class, CcUserPage, account_type_row);
650 gtk_widget_class_bind_template_child (widget_class, CcUserPage, account_type_switch);
651 gtk_widget_class_bind_template_child (widget_class, CcUserPage, auto_login_row);
652 gtk_widget_class_bind_template_child (widget_class, CcUserPage, fingerprint_row);
653 gtk_widget_class_bind_template_child (widget_class, CcUserPage, fullname_row);
654 gtk_widget_class_bind_template_child (widget_class, CcUserPage, language_row);
655 #ifdef HAVE_MALCONTENT
656 gtk_widget_class_bind_template_child (widget_class, CcUserPage, parental_controls_row);
657 #endif
658 gtk_widget_class_bind_template_child (widget_class, CcUserPage, password_row);
659 gtk_widget_class_bind_template_child (widget_class, CcUserPage, permission_infobar);
660 gtk_widget_class_bind_template_child (widget_class, CcUserPage, remove_local_files_choice);
661 gtk_widget_class_bind_template_child (widget_class, CcUserPage, remove_local_user_dialog);
662 gtk_widget_class_bind_template_child (widget_class, CcUserPage, remove_user_button);
663
664 gtk_widget_class_bind_template_callback (widget_class, account_type_changed);
665 gtk_widget_class_bind_template_callback (widget_class, autologin_changed);
666 gtk_widget_class_bind_template_callback (widget_class, change_fingerprint);
667 gtk_widget_class_bind_template_callback (widget_class, change_language);
668 gtk_widget_class_bind_template_callback (widget_class, change_password);
669 gtk_widget_class_bind_template_callback (widget_class, fullname_entry_apply_cb);
670 gtk_widget_class_bind_template_callback (widget_class, remove_local_user_response);
671 gtk_widget_class_bind_template_callback (widget_class, remove_user);
672 gtk_widget_class_bind_template_callback (widget_class, remove_avatar);
673 }
674
675 static void
676 cc_user_page_init (CcUserPage *self)
677 {
678 g_autofree gchar *malcontent_control_path = NULL;
679
680 gtk_widget_init_template (GTK_WIDGET (self));
681
682 self->avatar_chooser = cc_avatar_chooser_new ();
683 gtk_menu_button_set_popover (self->avatar_edit_button, GTK_WIDGET (self->avatar_chooser));
684
685 #ifdef HAVE_MALCONTENT
686 /* Parental Controls: Unavailable if user is admin or if
687 * malcontent-control is not available (which can happen if
688 * libmalcontent is installed but malcontent-control is not). */
689 malcontent_control_path = g_find_program_in_path ("malcontent-control");
690 if (malcontent_control_path)
691 g_object_bind_property (self,
692 "is-admin",
693 self->parental_controls_row,
694 "visible",
695 G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
696 g_signal_connect_object (self->parental_controls_row,
697 "activated",
698 G_CALLBACK (spawn_malcontent_control),
699 self,
700 G_CONNECT_SWAPPED);
701 #endif
702
703 self->login_screen_settings = settings_or_null ("org.gnome.login-screen");
704 }
705
706 CcUserPage *
707 cc_user_page_new (void)
708 {
709 return CC_USER_PAGE (g_object_new (CC_TYPE_USER_PAGE, NULL));
710 }
711
712 void
713 cc_user_page_set_user (CcUserPage *self,
714 ActUser *user,
715 GPermission *permission)
716 {
717 gboolean is_admin = FALSE;
718 g_autofree gchar *user_language = NULL;
719
720 g_assert (CC_IS_USER_PAGE (self));
721 g_assert (ACT_IS_USER (user));
722
723 g_clear_object (&self->user);
724 self->user = g_object_ref (user);
725 g_object_notify (G_OBJECT (self), "is-current-user");
726 g_object_notify (G_OBJECT (self), "is-admin");
727
728 if (!is_current_user (user))
729 adw_navigation_page_set_title (ADW_NAVIGATION_PAGE (self), get_real_or_user_name (user));
730 adw_navigation_page_set_tag (ADW_NAVIGATION_PAGE (self), act_user_get_user_name (user));
731
732 cc_avatar_chooser_set_user (self->avatar_chooser, self->user);
733 setup_avatar_for_user (self->avatar, self->user);
734 gtk_widget_set_visible (GTK_WIDGET (self->avatar_remove_button),
735 adw_avatar_get_custom_image (self->avatar) != NULL);
736
737
738 gtk_editable_set_text (GTK_EDITABLE (self->fullname_row), act_user_get_real_name (user));
739
740 gtk_widget_set_visible (GTK_WIDGET (self->account_type_row), !would_demote_only_admin (user));
741 is_admin = act_user_get_account_type (user) == ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR;
742 gtk_switch_set_active (self->account_type_switch, is_admin);
743
744 #ifdef HAVE_MALCONTENT
745 cc_list_row_set_secondary_label (self->parental_controls_row,
746 is_parental_controls_enabled_for_user (user) ?
747 /* TRANSLATORS: Status of Parental Controls setup */
748 _("Enabled") : _("Disabled"));
749 #endif
750
751 g_signal_handlers_block_by_func (self->auto_login_row, autologin_changed, self);
752 gtk_widget_set_visible (GTK_WIDGET (self->auto_login_row), get_autologin_possible (user));
753 adw_switch_row_set_active (self->auto_login_row, act_user_get_automatic_login (user));
754 g_signal_handlers_unblock_by_func (self->auto_login_row, autologin_changed, self);
755
756 cc_list_row_set_secondary_label (self->password_row, get_password_mode_text (user));
757 user_language = get_user_language (user);
758 cc_list_row_set_secondary_label (self->language_row, user_language);
759
760 if (!self->fingerprint_manager) {
761 self->fingerprint_manager = cc_fingerprint_manager_new (user);
762 g_signal_connect_object (self->fingerprint_manager,
763 "notify::state",
764 G_CALLBACK (update_fingerprint_row_state),
765 self,
766 G_CONNECT_SWAPPED);
767 update_fingerprint_row_state (self, NULL, self->fingerprint_manager);
768 }
769
770 cc_permission_infobar_set_permission (self->permission_infobar, permission);
771 cc_permission_infobar_set_title (self->permission_infobar, _("Some settings are locked"));
772 g_object_bind_property (permission, "allowed", self, "locked", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
773 g_signal_connect_object (permission, "notify", G_CALLBACK (update_editable_state), self, G_CONNECT_SWAPPED);
774 update_editable_state (self);
775 }
776
777 ActUser *
778 cc_user_page_get_user (CcUserPage *self)
779 {
780 g_assert (CC_IS_USER_PAGE (self));
781 g_assert (ACT_IS_USER (self->user));
782
783 return self->user;
784 }
785