summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2017-11-30 10:44:25 +1300
committerRobert Ancell <robert.ancell@canonical.com>2018-01-18 16:45:17 +1300
commit555799ae183f94b1154bcdab3240124f205c28e4 (patch)
treea6afbca27efe0dec82a7dd5d93ee3d48a085781a
parent1760d7290cd3c1af44d0e92258f8a7045d20cdab (diff)
downloadaccountsservice-wip/rancell/guest-accounts.tar.gz
Add guest account supportwip/rancell/guest-accounts
-rw-r--r--data/org.freedesktop.Accounts.User.xml10
-rw-r--r--data/org.freedesktop.Accounts.xml46
-rw-r--r--doc/libaccountsservice/libaccountsservice-sections.txt7
-rw-r--r--src/daemon.c125
-rw-r--r--src/daemon.h1
-rw-r--r--src/libaccountsservice/act-user-manager.c245
-rw-r--r--src/libaccountsservice/act-user-manager.h13
-rw-r--r--src/libaccountsservice/act-user.c30
-rw-r--r--src/libaccountsservice/act-user.h1
-rw-r--r--src/user.c43
-rw-r--r--src/user.h3
11 files changed, 521 insertions, 3 deletions
diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml
index 4ab989a..c6063b2 100644
--- a/data/org.freedesktop.Accounts.User.xml
+++ b/data/org.freedesktop.Accounts.User.xml
@@ -811,6 +811,16 @@
</doc:doc>
</property>
+ <property name="GuestAccount" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether this is a guest account or not.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
<signal name="Changed">
<doc:doc>
<doc:description>
diff --git a/data/org.freedesktop.Accounts.xml b/data/org.freedesktop.Accounts.xml
index 4612c5d..ae5dfe7 100644
--- a/data/org.freedesktop.Accounts.xml
+++ b/data/org.freedesktop.Accounts.xml
@@ -111,6 +111,27 @@
</doc:doc>
</method>
+ <method name="CreateGuest">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="user" direction="out" type="o">
+ <doc:doc><doc:summary>Object path of the new user</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Creates a new guest account.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
<method name="CacheUser">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="name" direction="in" type="s">
@@ -182,6 +203,31 @@
</doc:permission>
<doc:errors>
<doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.UserDoesNotExist">if the user id cannot be resolved</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
+ </doc:errors>
+ </doc:doc>
+ </method>
+
+ <method name="DeleteGuest">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="id" direction="in" type="x">
+ <doc:doc><doc:summary>The uid to delete</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Deletes a guest account. Has the same behaviour as DeleteUser but ensures only guest accounts are deleted.
+ </doc:para>
+ </doc:description>
+ <doc:permission>
+ The caller needs the org.freedesktop.accounts.user-administration PolicyKit authorization.
+ </doc:permission>
+ <doc:errors>
+ <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.UserDoesNotExist">if the user id cannot be resolved</doc:error>
+ <doc:error name="org.freedesktop.Accounts.Error.UserNotGuest">if the user is not a guest account</doc:error>
<doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error>
</doc:errors>
</doc:doc>
diff --git a/doc/libaccountsservice/libaccountsservice-sections.txt b/doc/libaccountsservice/libaccountsservice-sections.txt
index 26c0bc7..a90c3f3 100644
--- a/doc/libaccountsservice/libaccountsservice-sections.txt
+++ b/doc/libaccountsservice/libaccountsservice-sections.txt
@@ -27,6 +27,7 @@ act_user_get_shell
act_user_get_uid
act_user_get_user_name
act_user_get_x_session
+act_user_is_guest_account
act_user_is_loaded
act_user_is_local_account
act_user_is_logged_in
@@ -67,9 +68,15 @@ act_user_manager_can_switch
act_user_manager_create_user
act_user_manager_create_user_async
act_user_manager_create_user_finish
+act_user_manager_create_guest
+act_user_manager_create_guest_async
+act_user_manager_create_guest_finish
act_user_manager_delete_user
act_user_manager_delete_user_async
act_user_manager_delete_user_finish
+act_user_manager_delete_guest
+act_user_manager_delete_guest_async
+act_user_manager_delete_guest_finish
act_user_manager_get_default
act_user_manager_get_user
act_user_manager_get_user_by_id
diff --git a/src/daemon.c b/src/daemon.c
index 9ec153a..05c4b89 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -95,7 +95,8 @@ static const GDBusErrorEntry accounts_error_entries[] =
{ ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" },
{ ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
{ ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" },
- { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }
+ { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" },
+ { ERROR_USER_NOT_GUEST, "org.freedesktop.Accounts.Error.UserNotGuest" }
};
GQuark
@@ -126,6 +127,7 @@ error_get_type (void)
ENUM_ENTRY (ERROR_USER_DOES_NOT_EXIST, "UserDoesntExist"),
ENUM_ENTRY (ERROR_PERMISSION_DENIED, "PermissionDenied"),
ENUM_ENTRY (ERROR_NOT_SUPPORTED, "NotSupported"),
+ ENUM_ENTRY (ERROR_USER_NOT_GUEST, "UserNotGuest"),
{ 0, 0, 0 }
};
g_assert (NUM_ERRORS == G_N_ELEMENTS (values) - 1);
@@ -1139,6 +1141,88 @@ daemon_create_user (AccountsAccounts *accounts,
return TRUE;
}
+static gchar *
+make_guest_username (void)
+{
+ const gchar *random_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ GString *user_name;
+ int i;
+
+ user_name = g_string_new ("guest-");
+ for (i = 0; i < 6; i++) {
+ gint32 j = g_random_int_range (0, strlen (random_chars));
+ g_string_append_c (user_name, random_chars[j]);
+ }
+
+ return g_string_free (user_name, FALSE);
+}
+
+static void
+daemon_create_guest_authorized_cb (Daemon *daemon,
+ User *dummy,
+ GDBusMethodInvocation *context,
+ gpointer data)
+
+{
+ User *user;
+ GError *error;
+ gchar *user_name;
+ const gchar *argv[7];
+
+ sys_log (context, "create guest");
+
+ while (TRUE) {
+ user_name = make_guest_username ();
+ if (getpwnam (user_name) == NULL)
+ break;
+ g_free (user_name);
+ }
+
+ argv[0] = "/usr/sbin/useradd";
+ argv[1] = "-m";
+ argv[2] = "-c";
+ argv[3] = "Guest";
+ argv[4] = "--";
+ argv[5] = user_name;
+ argv[6] = NULL;
+
+ error = NULL;
+ if (!spawn_with_login_uid (context, argv, &error)) {
+ throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
+ g_error_free (error);
+ g_free (user_name);
+ return;
+ }
+
+ user = daemon_local_find_user_by_name (daemon, user_name);
+ user_update_local_account_property (user, TRUE);
+ user_update_system_account_property (user, FALSE);
+ user_update_guest_account_property (user, TRUE);
+
+ cache_user (daemon, user);
+
+ accounts_accounts_complete_create_guest (NULL, context, user_get_object_path (user));
+
+ g_free (user_name);
+}
+
+static gboolean
+daemon_create_guest (AccountsAccounts *accounts,
+ GDBusMethodInvocation *context)
+{
+ Daemon *daemon = (Daemon*)accounts;
+
+ daemon_local_check_auth (daemon,
+ NULL,
+ "org.freedesktop.accounts.user-administration",
+ TRUE,
+ daemon_create_guest_authorized_cb,
+ context,
+ NULL, NULL);
+
+ return TRUE;
+}
+
static void
daemon_cache_user_authorized_cb (Daemon *daemon,
User *dummy,
@@ -1243,6 +1327,7 @@ daemon_uncache_user (AccountsAccounts *accounts,
typedef struct {
uid_t uid;
gboolean remove_files;
+ gboolean only_guest;
} DeleteUserData;
static void
@@ -1269,6 +1354,11 @@ daemon_delete_user_authorized_cb (Daemon *daemon,
user = daemon_local_find_user_by_id (daemon, ud->uid);
+ if (ud->only_guest && ((user == NULL || !user_get_guest_account (user)))) {
+ throw_error (context, ERROR_USER_NOT_GUEST, "User is not a guest account");
+ return;
+ }
+
if (user != NULL) {
user_set_cached (user, FALSE);
@@ -1333,6 +1423,37 @@ daemon_delete_user (AccountsAccounts *accounts,
return TRUE;
}
+static gboolean
+daemon_delete_guest (AccountsAccounts *accounts,
+ GDBusMethodInvocation *context,
+ gint64 uid,
+ gboolean remove_files)
+{
+ Daemon *daemon = (Daemon*)accounts;
+ DeleteUserData *data;
+
+ if ((uid_t)uid == 0) {
+ throw_error (context, ERROR_FAILED, "Refuse to delete root user");
+ return TRUE;
+ }
+
+ data = g_new0 (DeleteUserData, 1);
+ data->uid = (uid_t)uid;
+ data->only_guest = TRUE;
+ data->remove_files = TRUE;
+
+ daemon_local_check_auth (daemon,
+ NULL,
+ "org.freedesktop.accounts.user-administration",
+ TRUE,
+ daemon_delete_user_authorized_cb,
+ context,
+ data,
+ (GDestroyNotify)g_free);
+
+ return TRUE;
+}
+
typedef struct {
Daemon *daemon;
User *user;
@@ -1594,7 +1715,9 @@ static void
daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface)
{
iface->handle_create_user = daemon_create_user;
+ iface->handle_create_guest = daemon_create_guest;
iface->handle_delete_user = daemon_delete_user;
+ iface->handle_delete_guest = daemon_delete_guest;
iface->handle_find_user_by_id = daemon_find_user_by_id;
iface->handle_find_user_by_name = daemon_find_user_by_name;
iface->handle_list_cached_users = daemon_list_cached_users;
diff --git a/src/daemon.h b/src/daemon.h
index b7e072e..d78a5fb 100644
--- a/src/daemon.h
+++ b/src/daemon.h
@@ -57,6 +57,7 @@ typedef enum {
ERROR_USER_DOES_NOT_EXIST,
ERROR_PERMISSION_DENIED,
ERROR_NOT_SUPPORTED,
+ ERROR_USER_NOT_GUEST,
NUM_ERRORS
} Error;
diff --git a/src/libaccountsservice/act-user-manager.c b/src/libaccountsservice/act-user-manager.c
index 3c9ccac..68adc67 100644
--- a/src/libaccountsservice/act-user-manager.c
+++ b/src/libaccountsservice/act-user-manager.c
@@ -86,6 +86,7 @@
* @ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST: The user does not exist
* @ACT_USER_MANAGER_ERROR_PERMISSION_DENIED: Permission denied
* @ACT_USER_MANAGER_ERROR_NOT_SUPPORTED: Operation not supported
+ * @ACT_USER_MANAGER_ERROR_USER_NOT_GUEST: The user is not a guest account
*
* Various error codes returned by the accounts service.
*/
@@ -255,7 +256,8 @@ static const GDBusErrorEntry error_entries[] = {
{ ACT_USER_MANAGER_ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" },
{ ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
{ ACT_USER_MANAGER_ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" },
- { ACT_USER_MANAGER_ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }
+ { ACT_USER_MANAGER_ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" },
+ { ACT_USER_MANAGER_ERROR_USER_NOT_GUEST, "org.freedesktop.Accounts.Error.UserNotGuest" }
};
GQuark
@@ -3121,6 +3123,130 @@ act_user_manager_create_user_finish (ActUserManager *manager,
}
/**
+ * act_user_manager_create_guest:
+ * @manager: a #ActUserManager
+ * @error: a #GError
+ *
+ * Creates a guest account on the system.
+ *
+ * Returns: (transfer full): user object
+ *
+ * Since: 0.6.46
+ */
+ActUser *
+act_user_manager_create_guest (ActUserManager *manager,
+ GError **error)
+{
+ GError *local_error = NULL;
+ gboolean res;
+ gchar *path;
+ ActUser *user;
+
+ g_debug ("ActUserManager: Creating guest");
+
+ g_assert (manager->priv->accounts_proxy != NULL);
+
+ local_error = NULL;
+ res = accounts_accounts_call_create_guest_sync (manager->priv->accounts_proxy,
+ &path,
+ NULL,
+ &local_error);
+ if (! res) {
+ g_propagate_error (error, local_error);
+ return NULL;
+ }
+
+ user = add_new_user_for_object_path (path, manager);
+
+ g_free (path);
+
+ return user;
+}
+
+/**
+ * act_user_manager_create_guest_async:
+ * @manager: a #ActUserManager
+ * @cancellable: (allow-none): optional #GCancellable object,
+ * %NULL to ignore
+ * @callback: (scope async): a #GAsyncReadyCallback to call
+ * when the request is satisfied
+ * @user_data: (closure): the data to pass to @callback
+ *
+ * Asynchronously creates a guest account on the system.
+ *
+ * For more details, see act_user_manager_create_guest(), which
+ * is the synchronous version of this call.
+ *
+ * Since: 0.6.46
+ */
+void
+act_user_manager_create_guest_async (ActUserManager *manager,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ g_return_if_fail (ACT_IS_USER_MANAGER (manager));
+ g_return_if_fail (manager->priv->accounts_proxy != NULL);
+
+ g_debug ("ActUserManager: Creating guest (async)");
+
+ g_assert (manager->priv->accounts_proxy != NULL);
+
+ task = g_task_new (G_OBJECT (manager),
+ cancellable,
+ callback, user_data);
+
+ accounts_accounts_call_create_guest (manager->priv->accounts_proxy,
+ cancellable,
+ act_user_manager_async_complete_handler, task);
+}
+
+/**
+ * act_user_manager_create_guest_finish:
+ * @manager: a #ActUserManager
+ * @result: a #GAsyncResult
+ * @error: a #GError
+ *
+ * Finishes an asynchronous guest creation.
+ *
+ * See act_user_manager_create_guest_async().
+ *
+ * Returns: (transfer full): user object
+ *
+ * Since: 0.6.46
+ */
+ActUser *
+act_user_manager_create_guest_finish (ActUserManager *manager,
+ GAsyncResult *result,
+ GError **error)
+{
+ GAsyncResult *inner_result;
+ ActUser *user = NULL;
+ gchar *path;
+ GError *remote_error = NULL;
+
+ inner_result = g_task_propagate_pointer (G_TASK (result), error);
+ if (inner_result == NULL) {
+ return FALSE;
+ }
+
+ if (accounts_accounts_call_create_guest_finish (manager->priv->accounts_proxy,
+ &path, inner_result, &remote_error)) {
+ user = add_new_user_for_object_path (path, manager);
+ g_free (path);
+ }
+
+ if (remote_error) {
+ g_dbus_error_strip_remote_error (remote_error);
+ g_propagate_error (error, remote_error);
+ }
+
+ return user;
+}
+
+/**
* act_user_manager_cache_user:
* @manager: a #ActUserManager
* @username: a user name
@@ -3479,3 +3605,120 @@ act_user_manager_delete_user_finish (ActUserManager *manager,
return success;
}
+
+/**
+ * act_user_manager_delete_guest:
+ * @manager: a #ActUserManager
+ * @user: an #ActUser object
+ * @error: a #GError
+ *
+ * Deletes a guest account on the system.
+ *
+ * Returns: %TRUE if the user account was successfully deleted
+ *
+ * Since: 0.6.46
+ */
+gboolean
+act_user_manager_delete_guest (ActUserManager *manager,
+ ActUser *user,
+ GError **error)
+{
+ GError *local_error = NULL;
+
+ g_debug ("ActUserManager: Deleting guest '%s' (uid %ld)", act_user_get_user_name (user), (long) act_user_get_uid (user));
+
+ g_return_val_if_fail (ACT_IS_USER_MANAGER (manager), FALSE);
+ g_return_val_if_fail (ACT_IS_USER (user), FALSE);
+ g_return_val_if_fail (manager->priv->accounts_proxy != NULL, FALSE);
+
+ if (!accounts_accounts_call_delete_guest_sync (manager->priv->accounts_proxy,
+ act_user_get_uid (user),
+ NULL,
+ &local_error)) {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * act_user_manager_delete_guest_async:
+ * @manager: a #ActUserManager
+ * @user: a #ActUser object
+ * @remove_files: %TRUE to delete the users home directory
+ * @cancellable: (allow-none): optional #GCancellable object,
+ * %NULL to ignore
+ * @callback: (scope async): a #GAsyncReadyCallback to call
+ * when the request is satisfied
+ * @user_data: (closure): the data to pass to @callback
+ *
+ * Asynchronously deletes a user account from the system.
+ *
+ * For more details, see act_user_manager_delete_guest(), which
+ * is the synchronous version of this call.
+ *
+ * Since: 0.6.46
+ */
+void
+act_user_manager_delete_guest_async (ActUserManager *manager,
+ ActUser *user,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ g_return_if_fail (ACT_IS_USER_MANAGER (manager));
+ g_return_if_fail (ACT_IS_USER (user));
+ g_return_if_fail (manager->priv->accounts_proxy != NULL);
+
+ task = g_task_new (G_OBJECT (manager),
+ cancellable,
+ callback, user_data);
+
+ g_debug ("ActUserManager: Deleting (async) guest '%s' (uid %ld)", act_user_get_user_name (user), (long) act_user_get_uid (user));
+
+ accounts_accounts_call_delete_guest (manager->priv->accounts_proxy,
+ act_user_get_uid (user),
+ cancellable,
+ act_user_manager_async_complete_handler, task);
+}
+
+/**
+ * act_user_manager_delete_guest_finish:
+ * @manager: a #ActUserManager
+ * @result: a #GAsyncResult
+ * @error: a #GError
+ *
+ * Finishes an asynchronous guest account deletion.
+ *
+ * See act_user_manager_delete_guest_async().
+ *
+ * Returns: %TRUE if the guest account was successfully deleted
+ *
+ * Since: 0.6.46
+ */
+gboolean
+act_user_manager_delete_guest_finish (ActUserManager *manager,
+ GAsyncResult *result,
+ GError **error)
+{
+ GAsyncResult *inner_result;
+ gboolean success;
+ GError *remote_error = NULL;
+
+ inner_result = g_task_propagate_pointer (G_TASK (result), error);
+ if (inner_result == NULL) {
+ return FALSE;
+ }
+
+ success = accounts_accounts_call_delete_guest_finish (manager->priv->accounts_proxy,
+ inner_result, &remote_error);
+ if (remote_error) {
+ g_dbus_error_strip_remote_error (remote_error);
+ g_propagate_error (error, remote_error);
+ }
+
+ return success;
+}
diff --git a/src/libaccountsservice/act-user-manager.h b/src/libaccountsservice/act-user-manager.h
index f337ad2..bdcf5b4 100644
--- a/src/libaccountsservice/act-user-manager.h
+++ b/src/libaccountsservice/act-user-manager.h
@@ -67,7 +67,8 @@ typedef enum ActUserManagerError
ACT_USER_MANAGER_ERROR_USER_EXISTS,
ACT_USER_MANAGER_ERROR_USER_DOES_NOT_EXIST,
ACT_USER_MANAGER_ERROR_PERMISSION_DENIED,
- ACT_USER_MANAGER_ERROR_NOT_SUPPORTED
+ ACT_USER_MANAGER_ERROR_NOT_SUPPORTED,
+ ACT_USER_MANAGER_ERROR_USER_NOT_GUEST
} ActUserManagerError;
#define ACT_USER_MANAGER_ERROR act_user_manager_error_quark ()
@@ -107,6 +108,16 @@ ActUser * act_user_manager_create_user_finish (ActUserManager *
GAsyncResult *result,
GError **error);
+ActUser * act_user_manager_create_guest (ActUserManager *manager,
+ GError **error);
+void act_user_manager_create_guest_async (ActUserManager *manager,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ActUser * act_user_manager_create_guest_finish (ActUserManager *manager,
+ GAsyncResult *result,
+ GError **error);
+
ActUser * act_user_manager_cache_user (ActUserManager *manager,
const char *username,
GError **error);
diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c
index 70691a0..cb2ed62 100644
--- a/src/libaccountsservice/act-user.c
+++ b/src/libaccountsservice/act-user.c
@@ -86,6 +86,7 @@ enum {
PROP_LOCKED,
PROP_AUTOMATIC_LOGIN,
PROP_SYSTEM_ACCOUNT,
+ PROP_GUEST_ACCOUNT,
PROP_NONEXISTENT,
PROP_LOCAL_ACCOUNT,
PROP_LOGIN_FREQUENCY,
@@ -437,6 +438,14 @@ act_user_class_init (ActUserClass *class)
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class,
+ PROP_GUEST_ACCOUNT,
+ g_param_spec_boolean ("guest-account",
+ "Guest Account",
+ "Guest Account",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
/**
* ActUser::changed:
@@ -947,6 +956,27 @@ act_user_is_local_account (ActUser *user)
}
/**
+ * act_user_is_guest_account:
+ * @user: a #ActUser
+ *
+ * Retrieves whether the user is a guest account or not.
+ *
+ * Returns: %TRUE if the user is a guest
+ *
+ * Since: 0.6.46
+ */
+gboolean
+act_user_is_guest_account (ActUser *user)
+{
+ g_return_val_if_fail (ACT_IS_USER (user), TRUE);
+
+ if (user->accounts_proxy == NULL)
+ return TRUE;
+
+ return accounts_user_get_guest_account (user->accounts_proxy);
+}
+
+/**
* act_user_is_nonexistent:
* @user: the user object to examine.
*
diff --git a/src/libaccountsservice/act-user.h b/src/libaccountsservice/act-user.h
index c685fcc..414f641 100644
--- a/src/libaccountsservice/act-user.h
+++ b/src/libaccountsservice/act-user.h
@@ -74,6 +74,7 @@ gboolean act_user_get_locked (ActUser *user);
gboolean act_user_get_automatic_login (ActUser *user);
gboolean act_user_is_system_account (ActUser *user);
gboolean act_user_is_local_account (ActUser *user);
+gboolean act_user_is_guest_account (ActUser *user);
gboolean act_user_is_nonexistent (ActUser *user);
const char *act_user_get_icon_file (ActUser *user);
const char *act_user_get_language (ActUser *user);
diff --git a/src/user.c b/src/user.c
index 0dee26c..c960b95 100644
--- a/src/user.c
+++ b/src/user.c
@@ -70,6 +70,7 @@ enum {
PROP_AUTOMATIC_LOGIN,
PROP_SYSTEM_ACCOUNT,
PROP_LOCAL_ACCOUNT,
+ PROP_GUEST_ACCOUNT,
};
struct User {
@@ -110,6 +111,7 @@ struct User {
gboolean automatic_login;
gboolean system_account;
gboolean local_account;
+ gboolean guest_account;
gboolean cached;
guint *extension_ids;
@@ -361,6 +363,16 @@ user_update_from_keyfile (User *user,
}
}
+ if (g_key_file_has_key (keyfile, "User", "GuestAccount", NULL)) {
+ gboolean guest_account;
+
+ guest_account = g_key_file_get_boolean (keyfile, "User", "GuestAccount", NULL);
+ if (guest_account != user->guest_account) {
+ user->guest_account = guest_account;
+ g_object_notify (G_OBJECT (user), "guest-account");
+ }
+ }
+
g_clear_pointer (&user->keyfile, g_key_file_unref);
user->keyfile = g_key_file_ref (keyfile);
user_set_cached (user, TRUE);
@@ -388,6 +400,16 @@ user_update_system_account_property (User *user,
g_object_notify (G_OBJECT (user), "system-account");
}
+void
+user_update_guest_account_property (User *user,
+ gboolean guest)
+{
+ if (guest == user->guest_account)
+ return;
+ user->guest_account = guest;
+ g_object_notify (G_OBJECT (user), "guest-account");
+}
+
static void
user_save_to_keyfile (User *user,
GKeyFile *keyfile)
@@ -413,6 +435,7 @@ user_save_to_keyfile (User *user,
g_key_file_set_string (keyfile, "User", "Icon", user->icon_file);
g_key_file_set_boolean (keyfile, "User", "SystemAccount", user->system_account);
+ g_key_file_set_boolean (keyfile, "User", "GuestAccount", user->guest_account);
user_set_cached (user, TRUE);
}
@@ -799,6 +822,12 @@ user_get_local_account (User *user)
return user->local_account;
}
+gboolean
+user_get_guest_account (User *user)
+{
+ return user->guest_account;
+}
+
const gchar *
user_get_object_path (User *user)
{
@@ -2156,6 +2185,12 @@ user_real_get_system_account (AccountsUser *user)
return USER (user)->system_account;
}
+static gboolean
+user_real_get_guest_account (AccountsUser *user)
+{
+ return USER (user)->guest_account;
+}
+
static void
user_finalize (GObject *object)
{
@@ -2222,6 +2257,9 @@ user_set_property (GObject *object,
case PROP_SYSTEM_ACCOUNT:
user->system_account = g_value_get_boolean (value);
break;
+ case PROP_GUEST_ACCOUNT:
+ user->guest_account = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -2304,6 +2342,9 @@ user_get_property (GObject *object,
case PROP_LOCAL_ACCOUNT:
g_value_set_boolean (value, user->local_account);
break;
+ case PROP_GUEST_ACCOUNT:
+ g_value_set_boolean (value, user->guest_account);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
@@ -2362,6 +2403,7 @@ user_accounts_user_iface_init (AccountsUserIface *iface)
iface->get_password_hint = user_real_get_password_hint;
iface->get_automatic_login = user_real_get_automatic_login;
iface->get_system_account = user_real_get_system_account;
+ iface->get_guest_account = user_real_get_guest_account;
}
static void
@@ -2385,6 +2427,7 @@ user_init (User *user)
user->locked = FALSE;
user->automatic_login = FALSE;
user->system_account = FALSE;
+ user->guest_account = FALSE;
user->login_history = NULL;
user->keyfile = g_key_file_new ();
}
diff --git a/src/user.h b/src/user.h
index 39c6f13..573d5e8 100644
--- a/src/user.h
+++ b/src/user.h
@@ -63,6 +63,8 @@ void user_update_local_account_property (User *user,
gboolean local);
void user_update_system_account_property (User *user,
gboolean system);
+void user_update_guest_account_property (User *user,
+ gboolean guest);
gboolean user_get_cached (User *user);
void user_set_cached (User *user,
gboolean cached);
@@ -76,6 +78,7 @@ void user_save (User *user);
const gchar * user_get_user_name (User *user);
gboolean user_get_system_account (User *user);
gboolean user_get_local_account (User *user);
+gboolean user_get_guest_account (User *user);
const gchar * user_get_object_path (User *user);
uid_t user_get_uid (User *user);
const gchar * user_get_shell (User *user);