1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
4  * Copyright (C) 2007-2008 William Jon McCann <mccann@jhu.edu>
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 2 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #include <config.h>
22 
23 #include <float.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <gio/gio.h>
32 
33 #include "act-user-private.h"
34 #include "accounts-user-generated.h"
35 
36 /**
37  * SECTION:act-user
38  * @title: ActUser
39  * @short_description: information about a user account
40  *
41  * An ActUser object represents a user account on the system.
42  */
43 
44 /**
45  * ActUser:
46  *
47  * Represents a user account on the system.
48  */
49 
50 /**
51  * ActUserAccountType:
52  * @ACT_USER_ACCOUNT_TYPE_STANDARD: Normal non-administrative user
53  * @ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR: Administrative user
54  *
55  * Type of user account
56  */
57 
58 /**
59  * ActUserPasswordMode:
60  * @ACT_USER_PASSWORD_MODE_REGULAR: Password set normally
61  * @ACT_USER_PASSWORD_MODE_SET_AT_LOGIN: Password will be chosen at next login
62  * @ACT_USER_PASSWORD_MODE_NONE: No password set
63  *
64  * Mode for setting the user's password.
65  */
66 
67 #define ACT_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ACT_TYPE_USER, ActUserClass))
68 #define ACT_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ACT_TYPE_USER))
69 #define ACT_USER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), ACT_TYPE_USER, ActUserClass))
70 
71 #define ACCOUNTS_NAME           "org.freedesktop.Accounts"
72 #define ACCOUNTS_USER_INTERFACE "org.freedesktop.Accounts.User"
73 
74 enum {
75         PROP_0,
76         PROP_UID,
77         PROP_USER_NAME,
78         PROP_REAL_NAME,
79         PROP_ACCOUNT_TYPE,
80         PROP_PASSWORD_MODE,
81         PROP_PASSWORD_HINT,
82         PROP_HOME_DIR,
83         PROP_SHELL,
84         PROP_EMAIL,
85         PROP_LOCATION,
86         PROP_LOCKED,
87         PROP_AUTOMATIC_LOGIN,
88         PROP_SYSTEM_ACCOUNT,
89         PROP_NONEXISTENT,
90         PROP_LOCAL_ACCOUNT,
91         PROP_LOGIN_FREQUENCY,
92         PROP_LOGIN_TIME,
93         PROP_LOGIN_HISTORY,
94         PROP_ICON_FILE,
95         PROP_LANGUAGE,
96         PROP_X_SESSION,
97         PROP_IS_LOADED
98 };
99 
100 enum {
101         CHANGED,
102         SESSIONS_CHANGED,
103         LAST_SIGNAL
104 };
105 
106 struct _ActUser {
107         GObject         parent;
108 
109         GDBusConnection *connection;
110         AccountsUser    *accounts_proxy;
111 
112         GList          *our_sessions;
113         GList          *other_sessions;
114 
115         guint           is_loaded : 1;
116         guint           nonexistent : 1;
117 };
118 
119 struct _ActUserClass
120 {
121         GObjectClass parent_class;
122 };
123 
124 static void act_user_finalize     (GObject      *object);
125 
126 static guint signals[LAST_SIGNAL] = { 0 };
127 
G_DEFINE_TYPE(ActUser,act_user,G_TYPE_OBJECT)128 G_DEFINE_TYPE (ActUser, act_user, G_TYPE_OBJECT)
129 
130 static int
131 session_compare (const char *a,
132                  const char *b)
133 {
134         if (a == NULL) {
135                 return 1;
136         } else if (b == NULL) {
137                 return -1;
138         }
139 
140         return strcmp (a, b);
141 }
142 
143 void
_act_user_add_session(ActUser * user,const char * ssid,gboolean is_ours)144 _act_user_add_session (ActUser    *user,
145                        const char *ssid,
146                        gboolean    is_ours)
147 {
148         GList *li;
149 
150         g_return_if_fail (ACT_IS_USER (user));
151         g_return_if_fail (ssid != NULL);
152 
153         li = g_list_find_custom (user->our_sessions, ssid, (GCompareFunc)session_compare);
154         if (li == NULL)
155                 li = g_list_find_custom (user->other_sessions, ssid, (GCompareFunc)session_compare);
156 
157         if (li == NULL) {
158                 g_debug ("ActUser: adding session %s", ssid);
159                 if (is_ours)
160                         user->our_sessions = g_list_prepend (user->our_sessions, g_strdup (ssid));
161                 else
162                         user->other_sessions = g_list_prepend (user->other_sessions, g_strdup (ssid));
163                 g_signal_emit (user, signals[SESSIONS_CHANGED], 0);
164         } else {
165                 g_debug ("ActUser: session already present: %s", ssid);
166         }
167 }
168 
169 void
_act_user_remove_session(ActUser * user,const char * ssid)170 _act_user_remove_session (ActUser    *user,
171                           const char *ssid)
172 {
173         GList *li, **headp;
174 
175         g_return_if_fail (ACT_IS_USER (user));
176         g_return_if_fail (ssid != NULL);
177 
178         headp = &(user->our_sessions);
179         li = g_list_find_custom (user->our_sessions, ssid, (GCompareFunc)session_compare);
180         if (li == NULL) {
181                 headp = &(user->other_sessions);
182                 li = g_list_find_custom (user->other_sessions, ssid, (GCompareFunc)session_compare);
183         }
184 
185         if (li != NULL) {
186                 g_debug ("ActUser: removing session %s", ssid);
187                 g_free (li->data);
188                 *headp = g_list_delete_link (*headp, li);
189                 g_signal_emit (user, signals[SESSIONS_CHANGED], 0);
190         } else {
191                 g_debug ("ActUser: session not found: %s", ssid);
192         }
193 }
194 
195 /**
196  * act_user_get_num_sessions:
197  * @user: a user
198  *
199  * Get the number of sessions for a user that are graphical and on the
200  * same seat as the session of the calling process.
201  *
202  * Returns: the number of sessions
203  */
204 guint
act_user_get_num_sessions(ActUser * user)205 act_user_get_num_sessions (ActUser    *user)
206 {
207         return g_list_length (user->our_sessions);
208 }
209 
210 /**
211  * act_user_get_num_sessions_anywhere:
212  * @user: a user
213  *
214  * Get the number of sessions for a user on any seat of any type.
215  * See also act_user_get_num_sessions().
216  *
217  * (Currently, this function is only implemented for systemd-logind.
218  * For ConsoleKit, it is equivalent to act_user_get_num_sessions.)
219  *
220  * Returns: the number of sessions
221  */
222 guint
act_user_get_num_sessions_anywhere(ActUser * user)223 act_user_get_num_sessions_anywhere (ActUser    *user)
224 {
225         return (g_list_length (user->our_sessions)
226                 + g_list_length (user->other_sessions));
227 }
228 
229 static void
act_user_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)230 act_user_get_property (GObject    *object,
231                        guint       param_id,
232                        GValue     *value,
233                        GParamSpec *pspec)
234 {
235         ActUser *user;
236 
237         user = ACT_USER (object);
238 
239         switch (param_id) {
240         case PROP_NONEXISTENT:
241                 g_value_set_boolean (value, user->nonexistent);
242                 break;
243         case PROP_IS_LOADED:
244                 g_value_set_boolean (value, user->is_loaded);
245                 break;
246         default:
247                 if (user->accounts_proxy != NULL) {
248                         const char *property_name;
249 
250                         property_name = g_param_spec_get_name (pspec);
251 
252                         g_object_get_property (G_OBJECT (user->accounts_proxy), property_name, value);
253 
254                 }
255                 break;
256         }
257 }
258 
259 
260 static void
act_user_class_init(ActUserClass * class)261 act_user_class_init (ActUserClass *class)
262 {
263         GObjectClass *gobject_class;
264 
265         gobject_class = G_OBJECT_CLASS (class);
266 
267         gobject_class->finalize = act_user_finalize;
268         gobject_class->get_property = act_user_get_property;
269 
270         g_object_class_install_property (gobject_class,
271                                          PROP_REAL_NAME,
272                                          g_param_spec_string ("real-name",
273                                                               "Real Name",
274                                                               "The real name to display for this user.",
275                                                               NULL,
276                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
277 
278         g_object_class_install_property (gobject_class,
279                                          PROP_ACCOUNT_TYPE,
280                                          g_param_spec_int ("account-type",
281                                                            "Account Type",
282                                                            "The account type for this user.",
283                                                            ACT_USER_ACCOUNT_TYPE_STANDARD,
284                                                            ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR,
285                                                            ACT_USER_ACCOUNT_TYPE_STANDARD,
286                                                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
287         g_object_class_install_property (gobject_class,
288                                          PROP_PASSWORD_MODE,
289                                          g_param_spec_int ("password-mode",
290                                                            "Password Mode",
291                                                            "The password mode for this user.",
292                                                            ACT_USER_PASSWORD_MODE_REGULAR,
293                                                            ACT_USER_PASSWORD_MODE_NONE,
294                                                            ACT_USER_PASSWORD_MODE_REGULAR,
295                                                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
296 
297         g_object_class_install_property (gobject_class,
298                                          PROP_PASSWORD_HINT,
299                                          g_param_spec_string ("password-hint",
300                                                               "Password Hint",
301                                                               "Hint to help this user remember his password",
302                                                               NULL,
303                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
304 
305         g_object_class_install_property (gobject_class,
306                                          PROP_UID,
307                                          g_param_spec_int ("uid",
308                                                            "User ID",
309                                                            "The UID for this user.",
310                                                            0, G_MAXINT, 0,
311                                                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
312         g_object_class_install_property (gobject_class,
313                                          PROP_USER_NAME,
314                                          g_param_spec_string ("user-name",
315                                                               "User Name",
316                                                               "The login name for this user.",
317                                                               NULL,
318                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
319         g_object_class_install_property (gobject_class,
320                                          PROP_HOME_DIR,
321                                          g_param_spec_string ("home-directory",
322                                                               "Home Directory",
323                                                               "The home directory for this user.",
324                                                               NULL,
325                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
326         g_object_class_install_property (gobject_class,
327                                          PROP_SHELL,
328                                          g_param_spec_string ("shell",
329                                                               "Shell",
330                                                               "The shell for this user.",
331                                                               NULL,
332                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
333         g_object_class_install_property (gobject_class,
334                                          PROP_EMAIL,
335                                          g_param_spec_string ("email",
336                                                               "Email",
337                                                               "The email address for this user.",
338                                                               NULL,
339                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
340         g_object_class_install_property (gobject_class,
341                                          PROP_LOCATION,
342                                          g_param_spec_string ("location",
343                                                               "Location",
344                                                               "The location of this user.",
345                                                               NULL,
346                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
347         g_object_class_install_property (gobject_class,
348                                          PROP_LOGIN_FREQUENCY,
349                                          g_param_spec_int ("login-frequency",
350                                                            "login frequency",
351                                                            "login frequency",
352                                                            0,
353                                                            G_MAXINT,
354                                                            0,
355                                                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
356         g_object_class_install_property (gobject_class,
357                                          PROP_LOGIN_TIME,
358                                          g_param_spec_int64 ("login-time",
359                                                              "Login time",
360                                                              "The last login time for this user.",
361                                                              0,
362                                                              G_MAXINT64,
363                                                              0,
364                                                              G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
365         g_object_class_install_property (gobject_class,
366                                          PROP_LOGIN_HISTORY,
367                                          g_param_spec_variant ("login-history",
368                                                                "Login history",
369                                                                "The login history for this user.",
370                                                                G_VARIANT_TYPE ("a(xxa{sv})"),
371                                                                NULL,
372                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
373         g_object_class_install_property (gobject_class,
374                                          PROP_ICON_FILE,
375                                          g_param_spec_string ("icon-file",
376                                                               "Icon File",
377                                                               "The path to an icon for this user.",
378                                                               NULL,
379                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
380         g_object_class_install_property (gobject_class,
381                                          PROP_LANGUAGE,
382                                          g_param_spec_string ("language",
383                                                               "Language",
384                                                               "User's locale.",
385                                                               NULL,
386                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
387         g_object_class_install_property (gobject_class,
388                                          PROP_X_SESSION,
389                                          g_param_spec_string ("x-session",
390                                                               "X session",
391                                                               "User's X session.",
392                                                               NULL,
393                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
394         g_object_class_install_property (gobject_class,
395                                          PROP_IS_LOADED,
396                                          g_param_spec_boolean ("is-loaded",
397                                                                "Is loaded",
398                                                                "Determines whether or not the user object is loaded and ready to read from.",
399                                                                FALSE,
400                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
401         g_object_class_install_property (gobject_class,
402                                          PROP_NONEXISTENT,
403                                          g_param_spec_boolean ("nonexistent",
404                                                                "Doesn't exist",
405                                                                "Determines whether or not the user object represents a valid user account.",
406                                                                FALSE,
407                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
408         g_object_class_install_property (gobject_class,
409                                          PROP_LOCKED,
410                                          g_param_spec_boolean ("locked",
411                                                                "Locked",
412                                                                "Locked",
413                                                                FALSE,
414                                                               G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
415 
416         g_object_class_install_property (gobject_class,
417                                          PROP_AUTOMATIC_LOGIN,
418                                          g_param_spec_boolean ("automatic-login",
419                                                                "Automatic Login",
420                                                                "Automatic Login",
421                                                                FALSE,
422                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
423 
424         g_object_class_install_property (gobject_class,
425                                          PROP_LOCAL_ACCOUNT,
426                                          g_param_spec_boolean ("local-account",
427                                                                "Local Account",
428                                                                "Local Account",
429                                                                FALSE,
430                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
431 
432         g_object_class_install_property (gobject_class,
433                                          PROP_SYSTEM_ACCOUNT,
434                                          g_param_spec_boolean ("system-account",
435                                                                "System Account",
436                                                                "System Account",
437                                                                FALSE,
438                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
439 
440 
441         /**
442          * ActUser::changed:
443          *
444          * Emitted when the user accounts changes in some way.
445          */
446         signals [CHANGED] =
447                 g_signal_new ("changed",
448                               G_TYPE_FROM_CLASS (class),
449                               G_SIGNAL_RUN_LAST,
450                               0,
451                               NULL, NULL,
452                               g_cclosure_marshal_VOID__VOID,
453                               G_TYPE_NONE, 0);
454         /**
455          * ActUser::sessions-changed:
456          *
457          * Emitted when the list of sessions for this user changes.
458          */
459         signals [SESSIONS_CHANGED] =
460                 g_signal_new ("sessions-changed",
461                               G_TYPE_FROM_CLASS (class),
462                               G_SIGNAL_RUN_LAST,
463                               0,
464                               NULL, NULL,
465                               g_cclosure_marshal_VOID__VOID,
466                               G_TYPE_NONE, 0);
467 }
468 
469 static void
act_user_init(ActUser * user)470 act_user_init (ActUser *user)
471 {
472         g_autoptr(GError) error = NULL;
473 
474         user->our_sessions = NULL;
475         user->other_sessions = NULL;
476 
477         user->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
478         if (user->connection == NULL) {
479                 g_warning ("Couldn't connect to system bus: %s", error->message);
480         }
481 }
482 
483 static void
act_user_finalize(GObject * object)484 act_user_finalize (GObject *object)
485 {
486         ActUser *user;
487 
488         user = ACT_USER (object);
489 
490         if (user->accounts_proxy != NULL) {
491                 g_object_unref (user->accounts_proxy);
492         }
493 
494         if (user->connection != NULL) {
495                 g_object_unref (user->connection);
496         }
497 
498         if (G_OBJECT_CLASS (act_user_parent_class)->finalize)
499                 (*G_OBJECT_CLASS (act_user_parent_class)->finalize) (object);
500 }
501 
502 static void
set_is_loaded(ActUser * user,gboolean is_loaded)503 set_is_loaded (ActUser  *user,
504                gboolean  is_loaded)
505 {
506         if (user->is_loaded != is_loaded) {
507                 user->is_loaded = is_loaded;
508                 g_object_notify (G_OBJECT (user), "is-loaded");
509         }
510 }
511 
512 /**
513  * act_user_get_uid:
514  * @user: the user object to examine.
515  *
516  * Retrieves the ID of @user.
517  *
518  * Returns: a pointer to an array of characters which must not be modified or
519  *  freed, or %NULL.
520  **/
521 
522 uid_t
act_user_get_uid(ActUser * user)523 act_user_get_uid (ActUser *user)
524 {
525         g_return_val_if_fail (ACT_IS_USER (user), -1);
526 
527         if (user->accounts_proxy == NULL)
528                 return -1;
529 
530         return accounts_user_get_uid (user->accounts_proxy);
531 }
532 
533 /**
534  * act_user_get_real_name:
535  * @user: the user object to examine.
536  *
537  * Retrieves the display name of @user.
538  *
539  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
540  *  freed, or %NULL.
541  **/
542 const char *
act_user_get_real_name(ActUser * user)543 act_user_get_real_name (ActUser *user)
544 {
545         const char *real_name = NULL;
546 
547         g_return_val_if_fail (ACT_IS_USER (user), NULL);
548 
549         if (user->accounts_proxy == NULL)
550                 return NULL;
551 
552         real_name = accounts_user_get_real_name (user->accounts_proxy);
553 
554         if (real_name == NULL || real_name[0] == '\0') {
555                 real_name = accounts_user_get_user_name (user->accounts_proxy);
556         }
557 
558         return real_name;
559 }
560 
561 /**
562  * act_user_get_account_type:
563  * @user: the user object to examine.
564  *
565  * Retrieves the account type of @user.
566  *
567  * Returns: a #ActUserAccountType
568  **/
569 ActUserAccountType
act_user_get_account_type(ActUser * user)570 act_user_get_account_type (ActUser *user)
571 {
572         g_return_val_if_fail (ACT_IS_USER (user), ACT_USER_ACCOUNT_TYPE_STANDARD);
573 
574         if (user->accounts_proxy == NULL)
575                 return ACT_USER_ACCOUNT_TYPE_STANDARD;
576 
577         return accounts_user_get_account_type (user->accounts_proxy);
578 }
579 
580 /**
581  * act_user_get_password_mode:
582  * @user: the user object to examine.
583  *
584  * Retrieves the password mode of @user.
585  *
586  * Returns: a #ActUserPasswordMode
587  **/
588 ActUserPasswordMode
act_user_get_password_mode(ActUser * user)589 act_user_get_password_mode (ActUser *user)
590 {
591         g_return_val_if_fail (ACT_IS_USER (user), ACT_USER_PASSWORD_MODE_REGULAR);
592 
593         if (user->accounts_proxy == NULL)
594                 return ACT_USER_PASSWORD_MODE_REGULAR;
595 
596         return accounts_user_get_password_mode (user->accounts_proxy);
597 }
598 
599 /**
600  * act_user_get_password_hint:
601  * @user: the user object to examine.
602  *
603  * Retrieves the password hint set by @user.
604  *
605  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
606  *  freed, or %NULL.
607  **/
608 const char *
act_user_get_password_hint(ActUser * user)609 act_user_get_password_hint (ActUser *user)
610 {
611         g_return_val_if_fail (ACT_IS_USER (user), NULL);
612 
613         if (user->accounts_proxy == NULL)
614                 return NULL;
615 
616         return accounts_user_get_password_hint (user->accounts_proxy);
617 }
618 
619 /**
620  * act_user_get_home_dir:
621  * @user: the user object to examine.
622  *
623  * Retrieves the home directory for @user.
624  *
625  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
626  *  freed, or %NULL.
627  **/
628 const char *
act_user_get_home_dir(ActUser * user)629 act_user_get_home_dir (ActUser *user)
630 {
631         g_return_val_if_fail (ACT_IS_USER (user), NULL);
632 
633         if (user->accounts_proxy == NULL)
634                 return NULL;
635 
636         return accounts_user_get_home_directory (user->accounts_proxy);
637 }
638 
639 /**
640  * act_user_get_shell:
641  * @user: the user object to examine.
642  *
643  * Retrieves the shell assigned to @user.
644  *
645  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
646  *  freed, or %NULL.
647  **/
648 const char *
act_user_get_shell(ActUser * user)649 act_user_get_shell (ActUser *user)
650 {
651         g_return_val_if_fail (ACT_IS_USER (user), NULL);
652 
653         if (user->accounts_proxy == NULL)
654                 return NULL;
655 
656         return accounts_user_get_shell (user->accounts_proxy);
657 }
658 
659 /**
660  * act_user_get_email:
661  * @user: the user object to examine.
662  *
663  * Retrieves the email address set by @user.
664  *
665  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
666  *  freed, or %NULL.
667  **/
668 const char *
act_user_get_email(ActUser * user)669 act_user_get_email (ActUser *user)
670 {
671         g_return_val_if_fail (ACT_IS_USER (user), NULL);
672 
673         if (user->accounts_proxy == NULL)
674                 return NULL;
675 
676         return accounts_user_get_email (user->accounts_proxy);
677 }
678 
679 /**
680  * act_user_get_location:
681  * @user: the user object to examine.
682  *
683  * Retrieves the location set by @user.
684  *
685  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
686  *  freed, or %NULL.
687  **/
688 const char *
act_user_get_location(ActUser * user)689 act_user_get_location (ActUser *user)
690 {
691         g_return_val_if_fail (ACT_IS_USER (user), NULL);
692 
693         if (user->accounts_proxy == NULL)
694                 return NULL;
695 
696         return accounts_user_get_location (user->accounts_proxy);
697 }
698 
699 /**
700  * act_user_get_user_name:
701  * @user: the user object to examine.
702  *
703  * Retrieves the login name of @user.
704  *
705  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
706  *  freed, or %NULL.
707  **/
708 
709 const char *
act_user_get_user_name(ActUser * user)710 act_user_get_user_name (ActUser *user)
711 {
712         g_return_val_if_fail (ACT_IS_USER (user), NULL);
713 
714         if (user->accounts_proxy == NULL)
715                 return NULL;
716 
717         return accounts_user_get_user_name (user->accounts_proxy);
718 }
719 
720 /**
721  * act_user_get_login_frequency:
722  * @user: a #ActUser
723  *
724  * Returns the number of times @user has logged in.
725  *
726  * Returns: the login frequency
727  */
728 int
act_user_get_login_frequency(ActUser * user)729 act_user_get_login_frequency (ActUser *user)
730 {
731         g_return_val_if_fail (ACT_IS_USER (user), 0);
732 
733         if (user->accounts_proxy == NULL)
734                 return 1;
735 
736         return accounts_user_get_login_frequency (user->accounts_proxy);
737 }
738 
739 /**
740  * act_user_get_login_time:
741  * @user: a #ActUser
742  *
743  * Returns the last login time for @user.
744  *
745  * Returns: the login time
746  */
747 gint64
act_user_get_login_time(ActUser * user)748 act_user_get_login_time (ActUser *user)
749 {
750         g_return_val_if_fail (ACT_IS_USER (user), 0);
751 
752         if (user->accounts_proxy == NULL)
753                 return 0;
754 
755         return accounts_user_get_login_time (user->accounts_proxy);
756 }
757 
758 /**
759  * act_user_get_login_history:
760  * @user: a #ActUser
761  *
762  * Returns the login history for @user.
763  *
764  * Returns: (transfer none): a pointer to GVariant of type "a(xxa{sv})"
765  * which must not be modified or freed, or %NULL.
766  */
767 const GVariant *
act_user_get_login_history(ActUser * user)768 act_user_get_login_history (ActUser *user)
769 {
770         g_return_val_if_fail (ACT_IS_USER (user), NULL);
771 
772         if (user->accounts_proxy == NULL)
773                 return NULL;
774 
775         return accounts_user_get_login_history (user->accounts_proxy);
776 }
777 
778 /**
779  * act_user_collate:
780  * @user1: a user
781  * @user2: a user
782  *
783  * Organize the user by login frequency and names.
784  *
785  * Returns: negative if @user1 is before @user2, zero if equal
786  *    or positive if @user1 is after @user2
787  */
788 int
act_user_collate(ActUser * user1,ActUser * user2)789 act_user_collate (ActUser *user1,
790                   ActUser *user2)
791 {
792         const char *str1;
793         const char *str2;
794         int         num1;
795         int         num2;
796         guint       len1;
797         guint       len2;
798 
799         g_return_val_if_fail (ACT_IS_USER (user1), 0);
800         g_return_val_if_fail (ACT_IS_USER (user2), 0);
801 
802         num1 = act_user_get_login_frequency (user1);
803         num2 = act_user_get_login_frequency (user2);
804 
805         if (num1 > num2) {
806                 return -1;
807         }
808 
809         if (num1 < num2) {
810                 return 1;
811         }
812 
813 
814         len1 = g_list_length (user1->our_sessions);
815         len2 = g_list_length (user2->our_sessions);
816 
817         if (len1 > len2) {
818                 return -1;
819         }
820 
821         if (len1 < len2) {
822                 return 1;
823         }
824 
825         /* if login frequency is equal try names */
826         str1 = act_user_get_real_name (user1);
827         str2 = act_user_get_real_name (user2);
828 
829         if (str1 == NULL && str2 != NULL) {
830                 return -1;
831         }
832 
833         if (str1 != NULL && str2 == NULL) {
834                 return 1;
835         }
836 
837         if (str1 == NULL && str2 == NULL) {
838                 return 0;
839         }
840 
841         return g_utf8_collate (str1, str2);
842 }
843 
844 /**
845  * act_user_is_logged_in:
846  * @user: a #ActUser
847  *
848  * Returns whether or not #ActUser is currently graphically logged in
849  * on the same seat as the seat of the session of the calling process.
850  *
851  * Returns: %TRUE or %FALSE
852  */
853 gboolean
act_user_is_logged_in(ActUser * user)854 act_user_is_logged_in (ActUser *user)
855 {
856         return user->our_sessions != NULL;
857 }
858 
859 /**
860  * act_user_is_logged_in_anywhere:
861  * @user: a #ActUser
862  *
863  * Returns whether or not #ActUser is currently logged in in any way
864  * whatsoever.  See also act_user_is_logged_in().
865  *
866  * (Currently, this function is only implemented for systemd-logind.
867  * For ConsoleKit, it is equivalent to act_user_is_logged_in.)
868  *
869  * Returns: %TRUE or %FALSE
870  */
871 gboolean
act_user_is_logged_in_anywhere(ActUser * user)872 act_user_is_logged_in_anywhere (ActUser *user)
873 {
874         return user->our_sessions != NULL || user->other_sessions != NULL;
875 }
876 
877 /**
878  * act_user_get_saved:
879  * @user: a #ActUser
880  *
881  * Returns whether or not the #ActUser account has retained state in accountsservice.
882  *
883  * Returns: %TRUE or %FALSE
884  */
885 gboolean
act_user_get_saved(ActUser * user)886 act_user_get_saved (ActUser *user)
887 {
888         g_return_val_if_fail (ACT_IS_USER (user), TRUE);
889 
890         if (user->accounts_proxy == NULL)
891                 return FALSE;
892 
893         return accounts_user_get_saved (user->accounts_proxy);
894 }
895 
896 /**
897  * act_user_get_locked:
898  * @user: a #ActUser
899  *
900  * Returns whether or not the #ActUser account is locked.
901  *
902  * Returns: %TRUE or %FALSE
903  */
904 gboolean
act_user_get_locked(ActUser * user)905 act_user_get_locked (ActUser *user)
906 {
907         g_return_val_if_fail (ACT_IS_USER (user), TRUE);
908 
909         if (user->accounts_proxy == NULL)
910                 return TRUE;
911 
912         return accounts_user_get_locked (user->accounts_proxy);
913 }
914 
915 /**
916  * act_user_get_automatic_login:
917  * @user: a #ActUser
918  *
919  * Returns whether or not #ActUser is automatically logged in at boot time.
920  *
921  * Returns: %TRUE or %FALSE
922  */
923 gboolean
act_user_get_automatic_login(ActUser * user)924 act_user_get_automatic_login (ActUser *user)
925 {
926         g_return_val_if_fail (ACT_IS_USER (user), FALSE);
927 
928         if (user->accounts_proxy == NULL)
929                 return FALSE;
930 
931        return accounts_user_get_automatic_login (user->accounts_proxy);
932 }
933 
934 /**
935  * act_user_is_system_account:
936  * @user: a #ActUser
937  *
938  * Returns whether or not #ActUser represents a 'system account' like
939  * 'root' or 'nobody'.
940  *
941  * Returns: %TRUE or %FALSE
942  */
943 gboolean
act_user_is_system_account(ActUser * user)944 act_user_is_system_account (ActUser *user)
945 {
946         g_return_val_if_fail (ACT_IS_USER (user), TRUE);
947 
948         if (user->accounts_proxy == NULL)
949                 return TRUE;
950 
951         return accounts_user_get_system_account (user->accounts_proxy);
952 }
953 
954 /**
955  * act_user_is_local_account:
956  * @user: the user object to examine.
957  *
958  * Retrieves whether the user is a local account or not.
959  *
960  * Returns: %TRUE if the user is local
961  **/
962 gboolean
act_user_is_local_account(ActUser * user)963 act_user_is_local_account (ActUser   *user)
964 {
965         g_return_val_if_fail (ACT_IS_USER (user), FALSE);
966 
967         if (user->accounts_proxy == NULL)
968                 return FALSE;
969 
970         return accounts_user_get_local_account (user->accounts_proxy);
971 }
972 
973 /**
974  * act_user_is_nonexistent:
975  * @user: the user object to examine.
976  *
977  * Retrieves whether the user is nonexistent or not.
978  *
979  * Returns: %TRUE if the user is nonexistent
980  **/
981 gboolean
act_user_is_nonexistent(ActUser * user)982 act_user_is_nonexistent (ActUser   *user)
983 {
984         g_return_val_if_fail (ACT_IS_USER (user), FALSE);
985 
986         return user->nonexistent;
987 }
988 
989 /**
990  * act_user_get_icon_file:
991  * @user: a #ActUser
992  *
993  * Returns the path to the account icon belonging to @user.
994  *
995  * Returns: (transfer none): a path to an icon
996  */
997 const char *
act_user_get_icon_file(ActUser * user)998 act_user_get_icon_file (ActUser *user)
999 {
1000         g_return_val_if_fail (ACT_IS_USER (user), NULL);
1001 
1002         if (user->accounts_proxy == NULL)
1003                 return NULL;
1004 
1005         return accounts_user_get_icon_file (user->accounts_proxy);
1006 }
1007 
1008 /**
1009  * act_user_get_language:
1010  * @user: a #ActUser
1011  *
1012  * Returns the path to the configured locale of @user.
1013  *
1014  * Returns: (transfer none): a path to an icon
1015  */
1016 const char *
act_user_get_language(ActUser * user)1017 act_user_get_language (ActUser *user)
1018 {
1019         g_return_val_if_fail (ACT_IS_USER (user), NULL);
1020 
1021         if (user->accounts_proxy == NULL)
1022                 return NULL;
1023 
1024         return accounts_user_get_language (user->accounts_proxy);
1025 }
1026 
1027 /**
1028  * act_user_get_x_session:
1029  * @user: a #ActUser
1030  *
1031  * Returns the path to the configured X session for @user.
1032  *
1033  * Returns: (transfer none): a path to an icon
1034  */
1035 const char *
act_user_get_x_session(ActUser * user)1036 act_user_get_x_session (ActUser *user)
1037 {
1038         g_return_val_if_fail (ACT_IS_USER (user), NULL);
1039 
1040         if (user->accounts_proxy == NULL)
1041                 return NULL;
1042 
1043         return accounts_user_get_xsession (user->accounts_proxy);
1044 }
1045 
1046 /**
1047  * act_user_get_session:
1048  * @user: a #ActUser
1049  *
1050  * Returns the path to the configured session for @user.
1051  *
1052  * Returns: (transfer none): a path to an icon
1053  */
1054 const char *
act_user_get_session(ActUser * user)1055 act_user_get_session (ActUser *user)
1056 {
1057         g_return_val_if_fail (ACT_IS_USER (user), NULL);
1058 
1059         if (user->accounts_proxy == NULL)
1060                 return NULL;
1061 
1062         return accounts_user_get_session (user->accounts_proxy);
1063 }
1064 
1065 /**
1066  * act_user_get_session_type:
1067  * @user: a #ActUser
1068  *
1069  * Returns the type of the configured session for @user.
1070  *
1071  * Returns: (transfer none): a path to an icon
1072  */
1073 const char *
act_user_get_session_type(ActUser * user)1074 act_user_get_session_type (ActUser *user)
1075 {
1076         g_return_val_if_fail (ACT_IS_USER (user), NULL);
1077 
1078         if (user->accounts_proxy == NULL)
1079                 return NULL;
1080 
1081         return accounts_user_get_session_type (user->accounts_proxy);
1082 }
1083 
1084 /**
1085  * act_user_get_object_path:
1086  * @user: a #ActUser
1087  *
1088  * Returns the user accounts service object path of @user,
1089  * or %NULL if @user doesn't have an object path associated
1090  * with it.
1091  *
1092  * Returns: (transfer none): the object path of the user
1093  */
1094 const char *
act_user_get_object_path(ActUser * user)1095 act_user_get_object_path (ActUser *user)
1096 {
1097         g_return_val_if_fail (ACT_IS_USER (user), NULL);
1098 
1099         if (user->accounts_proxy == NULL)
1100                 return NULL;
1101 
1102         return g_dbus_proxy_get_object_path (G_DBUS_PROXY (user->accounts_proxy));
1103 }
1104 
1105 /**
1106  * act_user_get_primary_session_id:
1107  * @user: a #ActUser
1108  *
1109  * Returns the id of the primary session of @user, or %NULL if @user
1110  * has no primary session.  The primary session will always be
1111  * graphical and will be chosen from the sessions on the same seat as
1112  * the seat of the session of the calling process.
1113  *
1114  * Returns: (transfer none): the id of the primary session of the user
1115  */
1116 const char *
act_user_get_primary_session_id(ActUser * user)1117 act_user_get_primary_session_id (ActUser *user)
1118 {
1119         if (user->our_sessions == NULL) {
1120                 g_debug ("User %s is not logged in here, so has no primary session",
1121                          act_user_get_user_name (user));
1122                 return NULL;
1123         }
1124 
1125         /* FIXME: better way to choose? */
1126         return user->our_sessions->data;
1127 }
1128 
1129 /**
1130  * _act_user_update_as_nonexistent:
1131  * @user: the user object to update.
1132  *
1133  * Set's the 'non-existent' property of @user to #TRUE
1134  * Can only be called before the user is loaded.
1135  **/
1136 void
_act_user_update_as_nonexistent(ActUser * user)1137 _act_user_update_as_nonexistent (ActUser *user)
1138 {
1139         g_return_if_fail (ACT_IS_USER (user));
1140         g_return_if_fail (!act_user_is_loaded (user));
1141         g_return_if_fail (act_user_get_object_path (user) == NULL);
1142 
1143         user->nonexistent = TRUE;
1144         g_object_notify (G_OBJECT (user), "nonexistent");
1145 
1146         set_is_loaded (user, TRUE);
1147 }
1148 
1149 static void
on_accounts_proxy_changed(ActUser * user)1150 on_accounts_proxy_changed (ActUser *user)
1151 {
1152         g_signal_emit (user, signals[CHANGED], 0);
1153 }
1154 
1155 /**
1156  * _act_user_update_from_object_path:
1157  * @user: the user object to update.
1158  * @object_path: the object path of the user to use.
1159  *
1160  * Updates the properties of @user from the accounts service via
1161  * the object path in @object_path.
1162  **/
1163 void
_act_user_update_from_object_path(ActUser * user,const char * object_path)1164 _act_user_update_from_object_path (ActUser    *user,
1165                                    const char *object_path)
1166 {
1167         AccountsUser    *accounts_proxy;
1168         g_autoptr(GError) error = NULL;
1169 
1170         g_return_if_fail (ACT_IS_USER (user));
1171         g_return_if_fail (object_path != NULL);
1172         g_return_if_fail (act_user_get_object_path (user) == NULL);
1173 
1174         accounts_proxy = accounts_user_proxy_new_sync (user->connection,
1175                                                        G_DBUS_PROXY_FLAGS_NONE,
1176                                                        ACCOUNTS_NAME,
1177                                                        object_path,
1178                                                        NULL,
1179                                                        &error);
1180         if (!accounts_proxy) {
1181                 g_warning ("Couldn't create accounts proxy: %s", error->message);
1182                 return;
1183         }
1184 
1185         user->accounts_proxy = accounts_proxy;
1186 
1187         g_signal_connect_object (user->accounts_proxy,
1188                                  "changed",
1189                                  G_CALLBACK (on_accounts_proxy_changed),
1190                                  user,
1191                                  G_CONNECT_SWAPPED);
1192 
1193         g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (user->accounts_proxy), INT_MAX);
1194 
1195         set_is_loaded (user, TRUE);
1196 }
1197 
1198 void
_act_user_update_login_frequency(ActUser * user,int login_frequency)1199 _act_user_update_login_frequency (ActUser    *user,
1200                                   int         login_frequency)
1201 {
1202         if (act_user_get_login_frequency (user) == login_frequency) {
1203                 return;
1204         }
1205 
1206         accounts_user_set_login_frequency (user->accounts_proxy,
1207                                            login_frequency);
1208 }
1209 
1210 static void
copy_sessions_lists(ActUser * user,ActUser * user_to_copy)1211 copy_sessions_lists (ActUser *user,
1212                      ActUser *user_to_copy)
1213 {
1214         GList *node;
1215 
1216         for (node = g_list_last (user_to_copy->our_sessions);
1217              node != NULL;
1218              node = node->prev) {
1219                 user->our_sessions = g_list_prepend (user->our_sessions, g_strdup (node->data));
1220         }
1221 
1222         for (node = g_list_last (user_to_copy->other_sessions);
1223              node != NULL;
1224              node = node->prev) {
1225                 user->other_sessions = g_list_prepend (user->other_sessions, g_strdup (node->data));
1226         }
1227 }
1228 
1229 void
_act_user_load_from_user(ActUser * user,ActUser * user_to_copy)1230 _act_user_load_from_user (ActUser    *user,
1231                           ActUser    *user_to_copy)
1232 {
1233         if (!user_to_copy->is_loaded) {
1234                 return;
1235         }
1236 
1237         user->accounts_proxy = g_object_ref (user_to_copy->accounts_proxy);
1238 
1239         g_signal_connect_object (user->accounts_proxy,
1240                                  "changed",
1241                                  G_CALLBACK (on_accounts_proxy_changed),
1242                                  user,
1243                                  G_CONNECT_SWAPPED);
1244 
1245         if (user->our_sessions == NULL && user->other_sessions == NULL) {
1246                 copy_sessions_lists (user, user_to_copy);
1247                 g_signal_emit (user, signals[SESSIONS_CHANGED], 0);
1248         }
1249 
1250         set_is_loaded (user, TRUE);
1251 }
1252 
1253 /**
1254  * act_user_is_loaded:
1255  * @user: a #ActUser
1256  *
1257  * Determines whether or not the user object is loaded and ready to read from.
1258  * #ActUserManager:is-loaded property must be %TRUE before calling
1259  * act_user_manager_list_users()
1260  *
1261  * Returns: %TRUE or %FALSE
1262  */
1263 gboolean
act_user_is_loaded(ActUser * user)1264 act_user_is_loaded (ActUser *user)
1265 {
1266         return user->is_loaded;
1267 }
1268 
1269 /**
1270  * act_user_get_password_expiration_policy:
1271  * @user: the user object to query.
1272  * @expiration_time: location to write time users password expires
1273  * @last_change_time: location to write time users password was last changed.
1274  * @min_days_between_changes: location to write minimum number of days needed between password changes.
1275  * @max_days_between_changes: location to write maximum number of days password can stay unchanged.
1276  * @days_to_warn: location to write number of days to warn user password is about to expire.
1277  * @days_after_expiration_until_lock: location to write number of days account will be locked after password expires.
1278  *
1279  * Get the password expiration policy for a user.
1280  *
1281  * Note this function is synchronous and ignores errors.
1282  **/
1283 void
act_user_get_password_expiration_policy(ActUser * user,gint64 * expiration_time,gint64 * last_change_time,gint64 * min_days_between_changes,gint64 * max_days_between_changes,gint64 * days_to_warn,gint64 * days_after_expiration_until_lock)1284 act_user_get_password_expiration_policy (ActUser *user,
1285                                          gint64  *expiration_time,
1286                                          gint64  *last_change_time,
1287                                          gint64  *min_days_between_changes,
1288                                          gint64  *max_days_between_changes,
1289                                          gint64  *days_to_warn,
1290                                          gint64  *days_after_expiration_until_lock)
1291 {
1292         g_autoptr(GError) error = NULL;
1293 
1294         g_return_if_fail (ACT_IS_USER (user));
1295         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1296 
1297         if (!accounts_user_call_get_password_expiration_policy_sync (user->accounts_proxy,
1298                                                                      expiration_time,
1299                                                                      last_change_time,
1300                                                                      min_days_between_changes,
1301                                                                      max_days_between_changes,
1302                                                                      days_to_warn,
1303                                                                      days_after_expiration_until_lock,
1304                                                                      NULL,
1305                                                                      &error)) {
1306                 g_warning ("GetPasswordExpirationPolicy call failed: %s", error->message);
1307                 return;
1308         }
1309 }
1310 
1311 /**
1312  * act_user_set_email:
1313  * @user: the user object to alter.
1314  * @email: an email address
1315  *
1316  * Assigns a new email to @user.
1317  *
1318  * Note this function is synchronous and ignores errors.
1319  **/
1320 void
act_user_set_email(ActUser * user,const char * email)1321 act_user_set_email (ActUser    *user,
1322                     const char *email)
1323 {
1324         g_autoptr(GError) error = NULL;
1325 
1326         g_return_if_fail (ACT_IS_USER (user));
1327         g_return_if_fail (email != NULL);
1328         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1329 
1330         if (!accounts_user_call_set_email_sync (user->accounts_proxy,
1331                                                 email,
1332                                                 NULL,
1333                                                 &error)) {
1334                 g_warning ("SetEmail call failed: %s", error->message);
1335                 return;
1336         }
1337 }
1338 
1339 /**
1340  * act_user_set_language:
1341  * @user: the user object to alter.
1342  * @language: a locale (e.g. en_US.utf8)
1343  *
1344  * Assigns a new locale for @user.
1345  *
1346  * Note this function is synchronous and ignores errors.
1347  **/
1348 void
act_user_set_language(ActUser * user,const char * language)1349 act_user_set_language (ActUser    *user,
1350                        const char *language)
1351 {
1352         g_autoptr(GError) error = NULL;
1353 
1354         g_return_if_fail (ACT_IS_USER (user));
1355         g_return_if_fail (language != NULL);
1356         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1357 
1358         if (!accounts_user_call_set_language_sync (user->accounts_proxy,
1359                                                    language,
1360                                                    NULL,
1361                                                    &error)) {
1362                 g_warning ("SetLanguage for language %s failed: %s", language, error->message);
1363                 return;
1364         }
1365 }
1366 
1367 /**
1368  * act_user_set_x_session:
1369  * @user: the user object to alter.
1370  * @x_session: an x session (e.g. gnome)
1371  *
1372  * Assigns a new x session for @user.
1373  *
1374  * Note this function is synchronous and ignores errors.
1375  **/
1376 void
act_user_set_x_session(ActUser * user,const char * x_session)1377 act_user_set_x_session (ActUser    *user,
1378                         const char *x_session)
1379 {
1380         g_autoptr(GError) error = NULL;
1381 
1382         g_return_if_fail (ACT_IS_USER (user));
1383         g_return_if_fail (x_session != NULL);
1384         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1385 
1386         if (!accounts_user_call_set_xsession_sync (user->accounts_proxy,
1387                                                    x_session,
1388                                                    NULL,
1389                                                    &error)) {
1390                 g_warning ("SetXSession call failed: %s", error->message);
1391                 return;
1392         }
1393 }
1394 
1395 /**
1396  * act_user_set_session:
1397  * @user: the user object to alter.
1398  * @session: a session (e.g. gnome)
1399  *
1400  * Assigns a new session for @user.
1401  *
1402  * Note this function is synchronous and ignores errors.
1403  **/
1404 void
act_user_set_session(ActUser * user,const char * session)1405 act_user_set_session (ActUser    *user,
1406                       const char *session)
1407 {
1408         g_autoptr(GError) error = NULL;
1409 
1410         g_return_if_fail (ACT_IS_USER (user));
1411         g_return_if_fail (session != NULL);
1412         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1413 
1414         if (!accounts_user_call_set_session_sync (user->accounts_proxy,
1415                                                   session,
1416                                                   NULL,
1417                                                   &error)) {
1418                 g_warning ("SetSession call failed: %s", error->message);
1419                 return;
1420         }
1421 }
1422 
1423 /**
1424  * act_user_set_session_type:
1425  * @user: the user object to alter.
1426  * @session_type: a type of session (e.g. "wayland" or "x11")
1427  *
1428  * Assigns a type to the session for @user.
1429  *
1430  * Note this function is synchronous and ignores errors.
1431  **/
1432 void
act_user_set_session_type(ActUser * user,const char * session_type)1433 act_user_set_session_type (ActUser    *user,
1434                            const char *session_type)
1435 {
1436         g_autoptr(GError) error = NULL;
1437 
1438         g_return_if_fail (ACT_IS_USER (user));
1439         g_return_if_fail (session_type != NULL);
1440         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1441 
1442         if (!accounts_user_call_set_session_type_sync (user->accounts_proxy,
1443                                                        session_type,
1444                                                        NULL,
1445                                                        &error)) {
1446                 g_warning ("SetSessionType call failed: %s", error->message);
1447                 return;
1448         }
1449 }
1450 
1451 /**
1452  * act_user_set_location:
1453  * @user: the user object to alter.
1454  * @location: a location
1455  *
1456  * Assigns a new location for @user.
1457  *
1458  * Note this function is synchronous and ignores errors.
1459  **/
1460 void
act_user_set_location(ActUser * user,const char * location)1461 act_user_set_location (ActUser    *user,
1462                        const char *location)
1463 {
1464         g_autoptr(GError) error = NULL;
1465 
1466         g_return_if_fail (ACT_IS_USER (user));
1467         g_return_if_fail (location != NULL);
1468         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1469 
1470         if (!accounts_user_call_set_location_sync (user->accounts_proxy,
1471                                                    location,
1472                                                    NULL,
1473                                                    &error)) {
1474                 g_warning ("SetLocation call failed: %s", error->message);
1475                 return;
1476         }
1477 }
1478 
1479 /**
1480  * act_user_set_user_name:
1481  * @user: the user object to alter.
1482  * @user_name: a new user name
1483  *
1484  * Assigns a new username for @user.
1485  *
1486  * Note this function is synchronous and ignores errors.
1487  **/
1488 void
act_user_set_user_name(ActUser * user,const char * user_name)1489 act_user_set_user_name (ActUser    *user,
1490                         const char *user_name)
1491 {
1492         g_autoptr(GError) error = NULL;
1493 
1494         g_return_if_fail (ACT_IS_USER (user));
1495         g_return_if_fail (user_name != NULL);
1496         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1497 
1498         if (!accounts_user_call_set_user_name_sync (user->accounts_proxy,
1499                                                     user_name,
1500                                                     NULL,
1501                                                     &error)) {
1502                 g_warning ("SetUserName call failed: %s", error->message);
1503                 return;
1504         }
1505 }
1506 
1507 /**
1508  * act_user_set_real_name:
1509  * @user: the user object to alter.
1510  * @real_name: a new name
1511  *
1512  * Assigns a new name for @user.
1513  *
1514  * Note this function is synchronous and ignores errors.
1515  **/
1516 void
act_user_set_real_name(ActUser * user,const char * real_name)1517 act_user_set_real_name (ActUser    *user,
1518                         const char *real_name)
1519 {
1520         g_autoptr(GError) error = NULL;
1521 
1522         g_return_if_fail (ACT_IS_USER (user));
1523         g_return_if_fail (real_name != NULL);
1524         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1525 
1526         if (!accounts_user_call_set_real_name_sync (user->accounts_proxy,
1527                                                     real_name,
1528                                                     NULL,
1529                                                     &error)) {
1530                 g_warning ("SetRealName call failed: %s", error->message);
1531                 return;
1532         }
1533 }
1534 
1535 /**
1536  * act_user_set_icon_file:
1537  * @user: the user object to alter.
1538  * @icon_file: path to an icon
1539  *
1540  * Assigns a new icon for @user.
1541  *
1542  * Note this function is synchronous and ignores errors.
1543  **/
1544 void
act_user_set_icon_file(ActUser * user,const char * icon_file)1545 act_user_set_icon_file (ActUser    *user,
1546                         const char *icon_file)
1547 {
1548         g_autoptr(GError) error = NULL;
1549 
1550         g_return_if_fail (ACT_IS_USER (user));
1551         g_return_if_fail (icon_file != NULL);
1552         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1553 
1554         if (!accounts_user_call_set_icon_file_sync (user->accounts_proxy,
1555                                                     icon_file,
1556                                                     NULL,
1557                                                     &error)) {
1558                 g_warning ("SetIconFile call failed: %s", error->message);
1559                 return;
1560         }
1561 }
1562 
1563 /**
1564  * act_user_set_account_type:
1565  * @user: the user object to alter.
1566  * @account_type: a #ActUserAccountType
1567  *
1568  * Changes the account type of @user.
1569  *
1570  * Note this function is synchronous and ignores errors.
1571  **/
1572 void
act_user_set_account_type(ActUser * user,ActUserAccountType account_type)1573 act_user_set_account_type (ActUser            *user,
1574                            ActUserAccountType  account_type)
1575 {
1576         g_autoptr(GError) error = NULL;
1577 
1578         g_return_if_fail (ACT_IS_USER (user));
1579         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1580 
1581         if (!accounts_user_call_set_account_type_sync (user->accounts_proxy,
1582                                                     account_type,
1583                                                     NULL,
1584                                                     &error)) {
1585                 g_warning ("SetAccountType call failed: %s", error->message);
1586                 return;
1587         }
1588 }
1589 
1590 static gchar
salt_char(GRand * rand)1591 salt_char (GRand *rand)
1592 {
1593         gchar salt[] = "ABCDEFGHIJKLMNOPQRSTUVXYZ"
1594                        "abcdefghijklmnopqrstuvxyz"
1595                        "./0123456789";
1596 
1597         return salt[g_rand_int_range (rand, 0, G_N_ELEMENTS (salt))];
1598 }
1599 
1600 static gchar *
make_crypted(const gchar * plain)1601 make_crypted (const gchar *plain)
1602 {
1603         g_autoptr(GString) salt = NULL;
1604         g_autoptr(GRand) rand = NULL;
1605         gint i;
1606 
1607         rand = g_rand_new ();
1608         salt = g_string_sized_new (21);
1609 
1610         /* SHA 256 */
1611         g_string_append (salt, "$6$");
1612         for (i = 0; i < 16; i++) {
1613                 g_string_append_c (salt, salt_char (rand));
1614         }
1615         g_string_append_c (salt, '$');
1616 
1617         return g_strdup (crypt (plain, salt->str));
1618 }
1619 
1620 /**
1621  * act_user_set_password:
1622  * @user: the user object to alter.
1623  * @password: a password
1624  * @hint: a hint to help user recall password
1625  *
1626  * Changes the password of @user to @password.
1627  * @hint is displayed to the user if they forget the password.
1628  *
1629  * Note this function is synchronous and ignores errors.
1630  **/
1631 void
act_user_set_password(ActUser * user,const gchar * password,const gchar * hint)1632 act_user_set_password (ActUser             *user,
1633                        const gchar         *password,
1634                        const gchar         *hint)
1635 {
1636         g_autoptr(GError) error = NULL;
1637         g_autofree gchar *crypted = NULL;
1638 
1639         g_return_if_fail (ACT_IS_USER (user));
1640         g_return_if_fail (password != NULL);
1641         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1642 
1643         crypted = make_crypted (password);
1644         if (!accounts_user_call_set_password_sync (user->accounts_proxy,
1645                                                    crypted,
1646                                                    hint,
1647                                                    NULL,
1648                                                    &error)) {
1649                 g_warning ("SetPassword call failed: %s", error->message);
1650         }
1651         memset (crypted, 0, strlen (crypted));
1652 }
1653 
1654 /**
1655  * act_uset_set_password_hint:
1656  * @user: the user object to alter.
1657  * @hint: a hint to help user recall password
1658  *
1659  * Sets the password hint of @user.
1660  * @hint is displayed to the user if they forget the password.
1661  *
1662  * Note this function is synchronous and ignores errors.
1663  **/
1664 void
act_user_set_password_hint(ActUser * user,const gchar * hint)1665 act_user_set_password_hint (ActUser     *user,
1666                             const gchar *hint)
1667 {
1668         g_autoptr(GError) error = NULL;
1669 
1670         g_return_if_fail (ACT_IS_USER (user));
1671         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1672 
1673         if (!accounts_user_call_set_password_hint_sync (user->accounts_proxy,
1674                                                         hint,
1675                                                         NULL,
1676                                                         &error)) {
1677                 g_warning ("SetPasswordHint call failed: %s", error->message);
1678         }
1679 }
1680 
1681 /**
1682  * act_user_set_password_mode:
1683  * @user: the user object to alter.
1684  * @password_mode: a #ActUserPasswordMode
1685  *
1686  * Changes the password of @user.  If @password_mode is
1687  * ACT_USER_PASSWORD_MODE_SET_AT_LOGIN then the user will
1688  * be asked for a new password at the next login.  If @password_mode
1689  * is ACT_USER_PASSWORD_MODE_NONE then the user will not require
1690  * a password to log in.
1691  *
1692  * Note this function is synchronous and ignores errors.
1693  **/
1694 void
act_user_set_password_mode(ActUser * user,ActUserPasswordMode password_mode)1695 act_user_set_password_mode (ActUser             *user,
1696                             ActUserPasswordMode  password_mode)
1697 {
1698         g_autoptr(GError) error = NULL;
1699 
1700         g_return_if_fail (ACT_IS_USER (user));
1701         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1702 
1703         if (!accounts_user_call_set_password_mode_sync (user->accounts_proxy,
1704                                                         (gint) password_mode,
1705                                                         NULL,
1706                                                         &error)) {
1707                 g_warning ("SetPasswordMode call failed: %s", error->message);
1708         }
1709 }
1710 
1711 /**
1712  * act_user_set_locked:
1713  * @user: the user object to alter.
1714  * @locked: whether or not the account is locked
1715  *
1716  * Note this function is synchronous and ignores errors.
1717  **/
1718 void
act_user_set_locked(ActUser * user,gboolean locked)1719 act_user_set_locked (ActUser  *user,
1720                      gboolean  locked)
1721 {
1722         g_autoptr(GError) error = NULL;
1723 
1724         g_return_if_fail (ACT_IS_USER (user));
1725         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1726 
1727         if (!accounts_user_call_set_locked_sync (user->accounts_proxy,
1728                                                  locked,
1729                                                  NULL,
1730                                                  &error)) {
1731                 g_warning ("SetLocked call failed: %s", error->message);
1732         }
1733 }
1734 
1735 /**
1736  * act_user_set_automatic_login:
1737  * @user: the user object to alter
1738  * @enabled: whether or not to autologin for user.
1739  *
1740  * If enabled is set to %TRUE then this user will automatically be logged in
1741  * at boot up time.  Only one user can be configured to auto login at any given
1742  * time, so subsequent calls to act_user_set_automatic_login() override previous
1743  * calls.
1744  *
1745  * Note this function is synchronous and ignores errors.
1746  **/
1747 void
act_user_set_automatic_login(ActUser * user,gboolean enabled)1748 act_user_set_automatic_login (ActUser   *user,
1749                               gboolean  enabled)
1750 {
1751         g_autoptr(GError) error = NULL;
1752 
1753         g_return_if_fail (ACT_IS_USER (user));
1754         g_return_if_fail (ACCOUNTS_IS_USER (user->accounts_proxy));
1755 
1756         if (!accounts_user_call_set_automatic_login_sync (user->accounts_proxy,
1757                                                           enabled,
1758                                                           NULL,
1759                                                           &error)) {
1760                 g_warning ("SetAutomaticLogin call failed: %s", error->message);
1761         }
1762 }
1763