~charlesk/gnome-control-center/make-new-panel

« back to all changes in this revision

Viewing changes to panels/user-accounts/um-user-manager.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Moya
  • Date: 2011-05-17 10:47:27 UTC
  • mfrom: (0.1.11 experimental) (1.1.45 upstream)
  • Revision ID: james.westby@ubuntu.com-20110517104727-lqel6m8vhfw5jby1
Tags: 1:3.0.1.1-1ubuntu1
* Rebase on Debian, remaining Ubuntu changes:
* debian/control:
  - Build-Depend on hardening-wrapper, dpkg-dev and dh-autoreconf
  - Add dependency on ubuntu-system-service
  - Remove dependency on gnome-icon-theme-symbolic
  - Move dependency on apg, gnome-icon-theme-symbolic and accountsservice to
    be a Recommends: until we get them in main
* debian/rules:
  - Use autoreconf
  - Add binary-post-install rule for gnome-control-center-data
  - Run dh-autoreconf
* debian/gnome-control-center.dirs:
* debian/gnome-control-center.links:
  - Add a link to the control center shell for indicators
* debian/patches/00_disable-nm.patch:
  - Temporary patch to disable building with NetworkManager until we get
    the new one in the archive
* debian/patches/01_git_remove_gettext_calls.patch:
  - Remove calls to AM_GNU_GETTEXT, IT_PROG_INTLTOOL should be enough
* debian/patches/01_git_kill_warning.patch:
  - Kill warning
* debian/patches/50_ubuntu_systemwide_prefs.patch:
  - Ubuntu specific proxy preferences
* debian/patches/51_ubuntu_system_keyboard.patch:
  - Implement the global keyboard spec at https://wiki.ubuntu.com/DefaultKeyboardSettings

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2009-2010 Red Hat, Inc.
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 3 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * Written by: Matthias Clasen <mclasen@redhat.com>
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <stdlib.h>
 
25
#include <stdio.h>
 
26
#include <fcntl.h>
 
27
#include <unistd.h>
 
28
#include <string.h>
 
29
#include <signal.h>
 
30
#include <errno.h>
 
31
#include <sys/stat.h>
 
32
#include <sys/types.h>
 
33
#include <pwd.h>
 
34
 
 
35
#ifdef HAVE_PATHS_H
 
36
#include <paths.h>
 
37
#endif /* HAVE_PATHS_H */
 
38
 
 
39
#include <glib.h>
 
40
#include <glib/gi18n.h>
 
41
#include <glib/gstdio.h>
 
42
#include <glib-object.h>
 
43
#include <gio/gio.h>
 
44
 
 
45
#include "um-user-manager.h"
 
46
 
 
47
enum {
 
48
        USERS_LOADED,
 
49
        USER_ADDED,
 
50
        USER_REMOVED,
 
51
        USER_CHANGED,
 
52
        LAST_SIGNAL
 
53
};
 
54
 
 
55
static guint signals [LAST_SIGNAL] = { 0, };
 
56
 
 
57
static void     um_user_manager_class_init (UmUserManagerClass *klass);
 
58
static void     um_user_manager_init       (UmUserManager      *user_manager);
 
59
static void     um_user_manager_finalize   (GObject            *object);
 
60
 
 
61
static gpointer user_manager_object = NULL;
 
62
 
 
63
G_DEFINE_TYPE (UmUserManager, um_user_manager, G_TYPE_OBJECT)
 
64
 
 
65
static void
 
66
um_user_manager_class_init (UmUserManagerClass *klass)
 
67
{
 
68
        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
 
69
 
 
70
        object_class->finalize = um_user_manager_finalize;
 
71
 
 
72
       signals [USERS_LOADED] =
 
73
                g_signal_new ("users-loaded",
 
74
                              G_TYPE_FROM_CLASS (klass),
 
75
                              G_SIGNAL_RUN_LAST,
 
76
                              G_STRUCT_OFFSET (UmUserManagerClass, users_loaded),
 
77
                              NULL, NULL,
 
78
                              g_cclosure_marshal_VOID__VOID,
 
79
                              G_TYPE_NONE, 0);
 
80
 
 
81
        signals [USER_ADDED] =
 
82
                g_signal_new ("user-added",
 
83
                              G_TYPE_FROM_CLASS (klass),
 
84
                              G_SIGNAL_RUN_LAST,
 
85
                              G_STRUCT_OFFSET (UmUserManagerClass, user_added),
 
86
                              NULL, NULL,
 
87
                              g_cclosure_marshal_VOID__OBJECT,
 
88
                              G_TYPE_NONE, 1, UM_TYPE_USER);
 
89
        signals [USER_REMOVED] =
 
90
                g_signal_new ("user-removed",
 
91
                              G_TYPE_FROM_CLASS (klass),
 
92
                              G_SIGNAL_RUN_LAST,
 
93
                              G_STRUCT_OFFSET (UmUserManagerClass, user_removed),
 
94
                              NULL, NULL,
 
95
                              g_cclosure_marshal_VOID__OBJECT,
 
96
                              G_TYPE_NONE, 1, UM_TYPE_USER);
 
97
        signals [USER_CHANGED] =
 
98
                g_signal_new ("user-changed",
 
99
                              G_TYPE_FROM_CLASS (klass),
 
100
                              G_SIGNAL_RUN_LAST,
 
101
                              G_STRUCT_OFFSET (UmUserManagerClass, user_changed),
 
102
                              NULL, NULL,
 
103
                              g_cclosure_marshal_VOID__OBJECT,
 
104
                              G_TYPE_NONE, 1, UM_TYPE_USER);
 
105
}
 
106
 
 
107
 
 
108
/* We maintain a ring for each group of users with the same real name.
 
109
 * We need this to pick the right display names.
 
110
 */
 
111
static void
 
112
remove_user_from_dupe_ring (UmUserManager *manager,
 
113
                            UmUser        *user)
 
114
{
 
115
        GList *dupes;
 
116
        UmUser *dup;
 
117
 
 
118
        um_user_show_short_display_name (user);
 
119
 
 
120
        dupes = g_object_get_data (G_OBJECT (user), "dupes");
 
121
 
 
122
        if (dupes == NULL) {
 
123
                return;
 
124
        }
 
125
 
 
126
        if (dupes->next == dupes->prev) {
 
127
                dup = dupes->next->data;
 
128
                um_user_show_short_display_name (dup);
 
129
                g_signal_emit (manager, signals[USER_CHANGED], 0, dup);
 
130
 
 
131
                g_list_free_1 (dupes->next);
 
132
                g_object_set_data (G_OBJECT (dup), "dupes", NULL);
 
133
        }
 
134
        else {
 
135
                dupes->next->prev = dupes->prev;
 
136
                dupes->prev->next = dupes->next;
 
137
        }
 
138
 
 
139
        g_list_free_1 (dupes);
 
140
        g_object_set_data (G_OBJECT (user), "dupes", NULL);
 
141
}
 
142
 
 
143
static gboolean
 
144
match_real_name_hrfunc (gpointer key,
 
145
                        gpointer value,
 
146
                        gpointer user)
 
147
{
 
148
        return (value != user && g_strcmp0 (um_user_get_real_name (user), um_user_get_real_name (value)) == 0);
 
149
}
 
150
 
 
151
static void
 
152
add_user_to_dupe_ring (UmUserManager *manager,
 
153
                       UmUser        *user)
 
154
{
 
155
        UmUser *dup;
 
156
        GList *dupes;
 
157
        GList *l;
 
158
 
 
159
        dup = g_hash_table_find (manager->user_by_object_path,
 
160
                                 match_real_name_hrfunc, user);
 
161
 
 
162
        if (!dup) {
 
163
                return;
 
164
        }
 
165
 
 
166
        um_user_show_full_display_name (user);
 
167
 
 
168
        dupes = g_object_get_data (G_OBJECT (dup), "dupes");
 
169
        if (!dupes) {
 
170
                um_user_show_full_display_name (dup);
 
171
                g_signal_emit (manager, signals[USER_CHANGED], 0, dup);
 
172
                dupes = g_list_append (NULL, dup);
 
173
                g_object_set_data (G_OBJECT (dup), "dupes", dupes);
 
174
                dupes->next = dupes->prev = dupes;
 
175
        }
 
176
 
 
177
        l = g_list_append (NULL, user);
 
178
        g_object_set_data (G_OBJECT (user), "dupes", l);
 
179
        l->prev = dupes->prev;
 
180
        dupes->prev->next = l;
 
181
        l->next = dupes;
 
182
        dupes->prev = l;
 
183
}
 
184
 
 
185
static void
 
186
user_changed_handler (UmUser        *user,
 
187
                      UmUserManager *manager)
 
188
{
 
189
        remove_user_from_dupe_ring (manager, user);
 
190
        add_user_to_dupe_ring (manager, user);
 
191
        g_signal_emit (manager, signals[USER_CHANGED], 0, user);
 
192
}
 
193
 
 
194
static void
 
195
user_added_handler (DBusGProxy *proxy,
 
196
                    const char *object_path,
 
197
                    gpointer    user_data)
 
198
{
 
199
        UmUserManager *manager = UM_USER_MANAGER (user_data);
 
200
        UmUser *user;
 
201
 
 
202
        if (g_hash_table_lookup (manager->user_by_object_path, object_path))
 
203
                return;
 
204
 
 
205
        user = um_user_new_from_object_path (object_path);
 
206
        if (!user)
 
207
                return;
 
208
 
 
209
        if (um_user_is_system_account (user)) {
 
210
                g_object_unref (user);
 
211
                return;
 
212
        }
 
213
 
 
214
        add_user_to_dupe_ring (manager, user);
 
215
 
 
216
        g_signal_connect (user, "changed",
 
217
                          G_CALLBACK (user_changed_handler), manager);
 
218
        g_hash_table_insert (manager->user_by_object_path, g_strdup (um_user_get_object_path (user)), g_object_ref (user));
 
219
        g_hash_table_insert (manager->user_by_name, g_strdup (um_user_get_user_name (user)), g_object_ref (user));
 
220
 
 
221
        g_signal_emit (manager, signals[USER_ADDED], 0, user);
 
222
        g_object_unref (user);
 
223
}
 
224
 
 
225
static void
 
226
user_deleted_handler (DBusGProxy *proxy,
 
227
                      const char *object_path,
 
228
                      gpointer    user_data)
 
229
{
 
230
        UmUserManager *manager = UM_USER_MANAGER (user_data);
 
231
        UmUser *user;
 
232
 
 
233
        user = g_hash_table_lookup (manager->user_by_object_path, object_path);
 
234
        if (!user)
 
235
                return;
 
236
        g_object_ref (user);
 
237
        g_signal_handlers_disconnect_by_func (user, user_changed_handler, manager);
 
238
 
 
239
        remove_user_from_dupe_ring (manager, user);
 
240
 
 
241
        g_hash_table_remove (manager->user_by_object_path, um_user_get_object_path (user));
 
242
        g_hash_table_remove (manager->user_by_name, um_user_get_user_name (user));
 
243
        g_signal_emit (manager, signals[USER_REMOVED], 0, user);
 
244
        g_object_unref (user);
 
245
}
 
246
 
 
247
static void
 
248
add_user (const gchar   *object_path,
 
249
          UmUserManager *manager)
 
250
{
 
251
        user_added_handler (NULL, object_path, manager);
 
252
}
 
253
 
 
254
static void
 
255
got_users (DBusGProxy     *proxy,
 
256
           DBusGProxyCall *call_id,
 
257
           gpointer        data)
 
258
{
 
259
        UmUserManager *manager = data;
 
260
        GError *error = NULL;
 
261
        GPtrArray *paths;
 
262
 
 
263
        if (!dbus_g_proxy_end_call (proxy,
 
264
                                    call_id,
 
265
                                    &error,
 
266
                                    dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &paths,
 
267
                                    G_TYPE_INVALID)) {
 
268
                manager->no_service = TRUE;
 
269
                g_error_free (error);
 
270
                goto done;
 
271
        }
 
272
 
 
273
        g_ptr_array_foreach (paths, (GFunc)add_user, manager);
 
274
 
 
275
        g_ptr_array_foreach (paths, (GFunc)g_free, NULL);
 
276
        g_ptr_array_free (paths, TRUE);
 
277
 
 
278
 done:
 
279
        g_signal_emit (G_OBJECT (manager), signals[USERS_LOADED], 0);
 
280
}
 
281
 
 
282
static void
 
283
get_users (UmUserManager *manager)
 
284
{
 
285
        g_debug ("calling 'ListCachedUsers'");
 
286
        dbus_g_proxy_begin_call (manager->proxy,
 
287
                                 "ListCachedUsers",
 
288
                                 got_users,
 
289
                                 manager,
 
290
                                 NULL,
 
291
                                 G_TYPE_INVALID);
 
292
}
 
293
 
 
294
static void
 
295
um_user_manager_init (UmUserManager *manager)
 
296
{
 
297
        GError *error = NULL;
 
298
 
 
299
        manager->user_by_object_path = g_hash_table_new_full (g_str_hash,
 
300
                                                              g_str_equal,
 
301
                                                              g_free,
 
302
                                                              g_object_unref);
 
303
        manager->user_by_name = g_hash_table_new_full (g_str_hash,
 
304
                                                       g_str_equal,
 
305
                                                       g_free,
 
306
                                                       g_object_unref);
 
307
 
 
308
        manager->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 
309
        if (manager->bus == NULL) {
 
310
                g_warning ("Couldn't connect to system bus: %s", error->message);
 
311
                g_error_free (error);
 
312
                goto error;
 
313
        }
 
314
 
 
315
        manager->proxy = dbus_g_proxy_new_for_name (manager->bus,
 
316
                                                    "org.freedesktop.Accounts",
 
317
                                                    "/org/freedesktop/Accounts",
 
318
                                                    "org.freedesktop.Accounts");
 
319
 
 
320
        dbus_g_proxy_add_signal (manager->proxy, "UserAdded", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
 
321
        dbus_g_proxy_add_signal (manager->proxy, "UserDeleted", DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
 
322
 
 
323
        dbus_g_proxy_connect_signal (manager->proxy, "UserAdded",
 
324
                                     G_CALLBACK (user_added_handler), manager, NULL);
 
325
        dbus_g_proxy_connect_signal (manager->proxy, "UserDeleted",
 
326
                                     G_CALLBACK (user_deleted_handler), manager, NULL);
 
327
 
 
328
        get_users (manager);
 
329
 
 
330
 error: ;
 
331
}
 
332
 
 
333
static void
 
334
clear_dup (gpointer key,
 
335
           gpointer value,
 
336
           gpointer data)
 
337
{
 
338
        GList *dupes;
 
339
 
 
340
        /* don't bother maintaining the ring, we're destroying the
 
341
         * entire hash table anyway
 
342
         */
 
343
        dupes = g_object_get_data (G_OBJECT (value), "dupes");
 
344
 
 
345
        if (dupes) {
 
346
                g_list_free_1 (dupes);
 
347
                g_object_set_data (G_OBJECT (value), "dupes", NULL);
 
348
        }
 
349
}
 
350
 
 
351
static void
 
352
um_user_manager_finalize (GObject *object)
 
353
{
 
354
        UmUserManager *manager;
 
355
 
 
356
        manager = UM_USER_MANAGER (object);
 
357
 
 
358
        g_hash_table_foreach (manager->user_by_object_path, clear_dup, NULL);
 
359
        g_hash_table_destroy (manager->user_by_object_path);
 
360
        g_hash_table_destroy (manager->user_by_name);
 
361
 
 
362
        G_OBJECT_CLASS (um_user_manager_parent_class)->finalize (object);
 
363
}
 
364
 
 
365
UmUserManager *
 
366
um_user_manager_ref_default (void)
 
367
{
 
368
        if (user_manager_object != NULL) {
 
369
                g_object_ref (user_manager_object);
 
370
        } else {
 
371
                user_manager_object = g_object_new (UM_TYPE_USER_MANAGER, NULL);
 
372
                g_object_add_weak_pointer (user_manager_object,
 
373
                                           (gpointer *) &user_manager_object);
 
374
        }
 
375
 
 
376
        return UM_USER_MANAGER (user_manager_object);
 
377
}
 
378
 
 
379
typedef struct {
 
380
        UmUserManager       *manager;
 
381
        gchar               *user_name;
 
382
        GAsyncReadyCallback  callback;
 
383
        gpointer             data;
 
384
        GDestroyNotify       destroy;
 
385
}  AsyncUserOpData;
 
386
 
 
387
static void
 
388
async_user_op_data_free (gpointer d)
 
389
{
 
390
        AsyncUserOpData *data = d;
 
391
 
 
392
        g_object_unref (data->manager);
 
393
 
 
394
        g_free (data->user_name);
 
395
 
 
396
        if (data->destroy)
 
397
                data->destroy (data->data);
 
398
 
 
399
        g_free (data);
 
400
}
 
401
 
 
402
static void
 
403
create_user_done (DBusGProxy     *proxy,
 
404
                  DBusGProxyCall *call_id,
 
405
                  gpointer        user_data)
 
406
{
 
407
        AsyncUserOpData *data = user_data;
 
408
        gchar *path;
 
409
        GError *error;
 
410
        GSimpleAsyncResult *res;
 
411
 
 
412
        res = g_simple_async_result_new (G_OBJECT (data->manager),
 
413
                                         data->callback,
 
414
                                         data->data,
 
415
                                         um_user_manager_create_user);
 
416
        error = NULL;
 
417
        if (!dbus_g_proxy_end_call (proxy,
 
418
                                    call_id,
 
419
                                    &error,
 
420
                                    DBUS_TYPE_G_OBJECT_PATH, &path,
 
421
                                    G_TYPE_INVALID)) {
 
422
                /* dbus-glib fail:
 
423
                 * We have to translate the errors manually here, since
 
424
                 * calling dbus_g_error_has_name on the error returned in
 
425
                 * um_user_manager_create_user_finish doesn't work.
 
426
                 */
 
427
                if (dbus_g_error_has_name (error, "org.freedesktop.Accounts.Error.PermissionDenied")) {
 
428
                        g_simple_async_result_set_error (res,
 
429
                                                         UM_USER_MANAGER_ERROR,
 
430
                                                         UM_USER_MANAGER_ERROR_PERMISSION_DENIED,
 
431
                                                         "Not authorized");
 
432
                }
 
433
                else if (dbus_g_error_has_name (error, "org.freedesktop.Accounts.Error.UserExists")) {
 
434
                        g_simple_async_result_set_error (res,
 
435
                                                         UM_USER_MANAGER_ERROR,
 
436
                                                         UM_USER_MANAGER_ERROR_USER_EXISTS,
 
437
                                                         _("A user with name '%s' already exists."),
 
438
                                                         data->user_name);
 
439
                }
 
440
                else {
 
441
                        g_simple_async_result_set_from_error (res, error);
 
442
                }
 
443
                g_error_free (error);
 
444
        }
 
445
        else {
 
446
                g_simple_async_result_set_op_res_gpointer (res, path, g_free);
 
447
        }
 
448
 
 
449
        data->callback (G_OBJECT (data->manager), G_ASYNC_RESULT (res), data->data);
 
450
}
 
451
 
 
452
gboolean
 
453
um_user_manager_create_user_finish (UmUserManager  *manager,
 
454
                                    GAsyncResult   *result,
 
455
                                    UmUser        **user,
 
456
                                    GError        **error)
 
457
{
 
458
        gchar *path;
 
459
        GSimpleAsyncResult *res;
 
460
 
 
461
        res = G_SIMPLE_ASYNC_RESULT (result);
 
462
 
 
463
        *user = NULL;
 
464
 
 
465
        if (g_simple_async_result_propagate_error (res, error)) {
 
466
                return FALSE;
 
467
        }
 
468
 
 
469
        path = g_simple_async_result_get_op_res_gpointer (res);
 
470
        *user = g_hash_table_lookup (manager->user_by_object_path, path);
 
471
 
 
472
        return TRUE;
 
473
}
 
474
 
 
475
void
 
476
um_user_manager_create_user (UmUserManager       *manager,
 
477
                             const char          *user_name,
 
478
                             const char          *real_name,
 
479
                             gint                 account_type,
 
480
                             GAsyncReadyCallback  done,
 
481
                             gpointer             done_data,
 
482
                             GDestroyNotify       destroy)
 
483
{
 
484
        AsyncUserOpData *data;
 
485
 
 
486
        data = g_new0 (AsyncUserOpData, 1);
 
487
        data->manager = g_object_ref (manager);
 
488
        data->user_name = g_strdup (user_name);
 
489
        data->callback = done;
 
490
        data->data = done_data;
 
491
        data->destroy = destroy;
 
492
 
 
493
        dbus_g_proxy_begin_call (manager->proxy,
 
494
                                 "CreateUser",
 
495
                                 create_user_done,
 
496
                                 data,
 
497
                                 async_user_op_data_free,
 
498
                                 G_TYPE_STRING, user_name,
 
499
                                 G_TYPE_STRING, real_name,
 
500
                                 G_TYPE_INT, account_type,
 
501
                                 G_TYPE_INVALID);
 
502
}
 
503
 
 
504
static void
 
505
delete_user_done (DBusGProxy     *proxy,
 
506
                  DBusGProxyCall *call_id,
 
507
                  gpointer        user_data)
 
508
{
 
509
        AsyncUserOpData *data = user_data;
 
510
        GError *error;
 
511
        GSimpleAsyncResult *res;
 
512
 
 
513
        res = g_simple_async_result_new (G_OBJECT (data->manager),
 
514
                                         data->callback,
 
515
                                         data->data,
 
516
                                         um_user_manager_delete_user);
 
517
        error = NULL;
 
518
        if (!dbus_g_proxy_end_call (proxy,
 
519
                                    call_id,
 
520
                                    &error,
 
521
                                    G_TYPE_INVALID)) {
 
522
                if (dbus_g_error_has_name (error, "org.freedesktop.Accounts.Error.PermissionDenied")) {
 
523
                        g_simple_async_result_set_error (res,
 
524
                                                         UM_USER_MANAGER_ERROR,
 
525
                                                         UM_USER_MANAGER_ERROR_PERMISSION_DENIED,
 
526
                                                         "Not authorized");
 
527
                }
 
528
                else if (dbus_g_error_has_name (error, "org.freedesktop.Accounts.Error.UserDoesntExists")) {
 
529
                        g_simple_async_result_set_error (res,
 
530
                                                         UM_USER_MANAGER_ERROR,
 
531
                                                         UM_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST,
 
532
                                                         _("This user does not exist."));
 
533
                }
 
534
                else {
 
535
                        g_simple_async_result_set_from_error (res, error);
 
536
                        g_error_free (error);
 
537
                }
 
538
        }
 
539
 
 
540
        data->callback (G_OBJECT (data->manager), G_ASYNC_RESULT (res), data->data);
 
541
}
 
542
 
 
543
gboolean
 
544
um_user_manager_delete_user_finish (UmUserManager  *manager,
 
545
                                    GAsyncResult   *result,
 
546
                                    GError        **error)
 
547
{
 
548
        GSimpleAsyncResult *res;
 
549
 
 
550
        res = G_SIMPLE_ASYNC_RESULT (result);
 
551
 
 
552
        if (g_simple_async_result_propagate_error (res, error)) {
 
553
                return FALSE;
 
554
        }
 
555
 
 
556
        return TRUE;
 
557
}
 
558
 
 
559
void
 
560
um_user_manager_delete_user (UmUserManager       *manager,
 
561
                             UmUser              *user,
 
562
                             gboolean             remove_files,
 
563
                             GAsyncReadyCallback  done,
 
564
                             gpointer             done_data,
 
565
                             GDestroyNotify       destroy)
 
566
{
 
567
        AsyncUserOpData *data;
 
568
 
 
569
        data = g_new0 (AsyncUserOpData, 1);
 
570
        data->manager = g_object_ref (manager);
 
571
        data->callback = done;
 
572
        data->data = done_data;
 
573
        data->destroy = destroy;
 
574
 
 
575
        dbus_g_proxy_begin_call (manager->proxy,
 
576
                                 "DeleteUser",
 
577
                                 delete_user_done,
 
578
                                 data,
 
579
                                 async_user_op_data_free,
 
580
                                 G_TYPE_INT64, um_user_get_uid (user),
 
581
                                 G_TYPE_BOOLEAN, remove_files,
 
582
                                 G_TYPE_INVALID);
 
583
}
 
584
 
 
585
GSList *
 
586
um_user_manager_list_users (UmUserManager *manager)
 
587
{
 
588
        GSList *list = NULL;
 
589
        GHashTableIter iter;
 
590
        gpointer value;
 
591
 
 
592
        g_hash_table_iter_init (&iter, manager->user_by_name);
 
593
        while (g_hash_table_iter_next (&iter, NULL, &value)) {
 
594
                list = g_slist_prepend (list, value);
 
595
        }
 
596
 
 
597
        return g_slist_sort (list, (GCompareFunc) um_user_collate);
 
598
}
 
599
 
 
600
UmUser *
 
601
um_user_manager_get_user (UmUserManager *manager,
 
602
                          const gchar   *name)
 
603
{
 
604
        return g_hash_table_lookup (manager->user_by_name, name);
 
605
}
 
606
 
 
607
UmUser *
 
608
um_user_manager_get_user_by_id (UmUserManager *manager,
 
609
                                uid_t          uid)
 
610
{
 
611
        struct passwd *pwent;
 
612
 
 
613
        pwent = getpwuid (uid);
 
614
        if (!pwent) {
 
615
                return NULL;
 
616
        }
 
617
 
 
618
        return um_user_manager_get_user (manager, pwent->pw_name);
 
619
}
 
620
 
 
621
gboolean
 
622
um_user_manager_no_service (UmUserManager *manager)
 
623
{
 
624
        return manager->no_service;
 
625
}
 
626
 
 
627
GQuark
 
628
um_user_manager_error_quark (void)
 
629
{
 
630
        return g_quark_from_static_string ("um-user-manager-error-quark");
 
631
}