From 14bb1237f71e38749558c74963032a0387eecec0 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 15 Aug 2018 16:04:42 -0400 Subject: [PATCH 2/2] user: export new Saved property accountsservice maintains a state file for some users, if those users have selected a specific session or language. There's no good way, at the moment, for an application to check if a specific user has saved state. This commit exports the Saved property on the User object. --- data/org.freedesktop.Accounts.User.xml | 10 ++++++++++ src/daemon.c | 3 +++ src/libaccountsservice/act-user.c | 19 +++++++++++++++++++ src/libaccountsservice/act-user.h | 1 + src/user.c | 10 ++++++++++ src/user.h | 2 ++ 6 files changed, 45 insertions(+) diff --git a/data/org.freedesktop.Accounts.User.xml b/data/org.freedesktop.Accounts.User.xml index 7fc3c61..8d3fe1c 100644 --- a/data/org.freedesktop.Accounts.User.xml +++ b/data/org.freedesktop.Accounts.User.xml @@ -811,60 +811,70 @@ The login history for this user. Each entry in the array represents a login session. The first two members are the login time and logout time, as timestamps (seconds since the epoch). If the session is still running, the logout time is 0. The a{sv} member is a dictionary containing additional information about the session. Possible members include 'type' (with values like ':0', 'tty0', 'pts/0' etc). The filename of a png file containing the users icon. + + + + + Whether the users account has retained state + + + + + Whether the users account is locked. The password mode for the user account, encoded as an integer: 0 Regular password 1 Password must be set at next login 2 No password diff --git a/src/daemon.c b/src/daemon.c index 2851ed6..2587b8a 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -1187,60 +1187,61 @@ daemon_cache_user (AccountsAccounts *accounts, context, g_strdup (user_name), g_free); return TRUE; } static void daemon_uncache_user_authorized_cb (Daemon *daemon, User *dummy, GDBusMethodInvocation *context, gpointer data) { const gchar *user_name = data; User *user; sys_log (context, "uncache user '%s'", user_name); user = daemon_local_find_user_by_name (daemon, user_name); if (user == NULL) { throw_error (context, ERROR_USER_DOES_NOT_EXIST, "No user with the name %s found", user_name); return; } /* Always use the canonical user name looked up */ user_name = user_get_user_name (user); remove_cache_files (user_name); + user_set_saved (user, FALSE); user_set_cached (user, FALSE); accounts_accounts_complete_uncache_user (NULL, context); queue_reload_users (daemon); } static gboolean daemon_uncache_user (AccountsAccounts *accounts, GDBusMethodInvocation *context, const gchar *user_name) { Daemon *daemon = (Daemon*)accounts; daemon_local_check_auth (daemon, NULL, "org.freedesktop.accounts.user-administration", TRUE, daemon_uncache_user_authorized_cb, context, g_strdup (user_name), g_free); return TRUE; } typedef struct { uid_t uid; gboolean remove_files; } DeleteUserData; @@ -1252,60 +1253,62 @@ daemon_delete_user_authorized_cb (Daemon *daemon, gpointer data) { DeleteUserData *ud = data; g_autoptr(GError) error = NULL; struct passwd *pwent; const gchar *argv[6]; User *user; pwent = getpwuid (ud->uid); if (pwent == NULL) { throw_error (context, ERROR_USER_DOES_NOT_EXIST, "No user with uid %d found", ud->uid); return; } sys_log (context, "delete user '%s' (%d)", pwent->pw_name, ud->uid); user = daemon_local_find_user_by_id (daemon, ud->uid); if (user != NULL) { user_set_cached (user, FALSE); if (daemon->priv->autologin == user) { daemon_local_set_automatic_login (daemon, user, FALSE, NULL); } } remove_cache_files (pwent->pw_name); + user_set_saved (user, FALSE); + argv[0] = "/usr/sbin/userdel"; if (ud->remove_files) { argv[1] = "-f"; argv[2] = "-r"; argv[3] = "--"; argv[4] = pwent->pw_name; argv[5] = NULL; } else { argv[1] = "-f"; argv[2] = "--"; argv[3] = pwent->pw_name; argv[4] = NULL; } if (!spawn_with_login_uid (context, argv, &error)) { throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message); return; } accounts_accounts_complete_delete_user (NULL, context); } static gboolean daemon_delete_user (AccountsAccounts *accounts, GDBusMethodInvocation *context, gint64 uid, gboolean remove_files) { diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c index dd8f81b..540ffe7 100644 --- a/src/libaccountsservice/act-user.c +++ b/src/libaccountsservice/act-user.c @@ -849,60 +849,79 @@ act_user_collate (ActUser *user1, * * Returns whether or not #ActUser is currently graphically logged in * on the same seat as the seat of the session of the calling process. * * Returns: %TRUE or %FALSE */ gboolean act_user_is_logged_in (ActUser *user) { return user->our_sessions != NULL; } /** * act_user_is_logged_in_anywhere: * @user: a #ActUser * * Returns whether or not #ActUser is currently logged in in any way * whatsoever. See also act_user_is_logged_in(). * * (Currently, this function is only implemented for systemd-logind. * For ConsoleKit, it is equivalent to act_user_is_logged_in.) * * Returns: %TRUE or %FALSE */ gboolean act_user_is_logged_in_anywhere (ActUser *user) { return user->our_sessions != NULL || user->other_sessions != NULL; } +/** + * act_user_get_saved: + * @user: a #ActUser + * + * Returns whether or not the #ActUser account has retained state in accountsservice. + * + * Returns: %TRUE or %FALSE + */ +gboolean +act_user_get_saved (ActUser *user) +{ + g_return_val_if_fail (ACT_IS_USER (user), TRUE); + + if (user->accounts_proxy == NULL) + return FALSE; + + return accounts_user_get_saved (user->accounts_proxy); +} + /** * act_user_get_locked: * @user: a #ActUser * * Returns whether or not the #ActUser account is locked. * * Returns: %TRUE or %FALSE */ gboolean act_user_get_locked (ActUser *user) { g_return_val_if_fail (ACT_IS_USER (user), TRUE); if (user->accounts_proxy == NULL) return TRUE; return accounts_user_get_locked (user->accounts_proxy); } /** * act_user_get_automatic_login: * @user: a #ActUser * * Returns whether or not #ActUser is automatically logged in at boot time. * * Returns: %TRUE or %FALSE */ gboolean act_user_get_automatic_login (ActUser *user) { diff --git a/src/libaccountsservice/act-user.h b/src/libaccountsservice/act-user.h index 2ef13b1..34d7fe3 100644 --- a/src/libaccountsservice/act-user.h +++ b/src/libaccountsservice/act-user.h @@ -43,60 +43,61 @@ typedef enum { typedef enum { ACT_USER_PASSWORD_MODE_REGULAR, ACT_USER_PASSWORD_MODE_SET_AT_LOGIN, ACT_USER_PASSWORD_MODE_NONE, } ActUserPasswordMode; typedef struct _ActUser ActUser; typedef struct _ActUserClass ActUserClass; GType act_user_get_type (void) G_GNUC_CONST; const char *act_user_get_object_path (ActUser *user); uid_t act_user_get_uid (ActUser *user); const char *act_user_get_user_name (ActUser *user); const char *act_user_get_real_name (ActUser *user); ActUserAccountType act_user_get_account_type (ActUser *user); ActUserPasswordMode act_user_get_password_mode (ActUser *user); const char *act_user_get_password_hint (ActUser *user); const char *act_user_get_home_dir (ActUser *user); const char *act_user_get_shell (ActUser *user); const char *act_user_get_email (ActUser *user); const char *act_user_get_location (ActUser *user); guint act_user_get_num_sessions (ActUser *user); guint act_user_get_num_sessions_anywhere (ActUser *user); gboolean act_user_is_logged_in (ActUser *user); gboolean act_user_is_logged_in_anywhere (ActUser *user); int act_user_get_login_frequency (ActUser *user); gint64 act_user_get_login_time (ActUser *user); const GVariant*act_user_get_login_history (ActUser *user); +gboolean act_user_get_saved (ActUser *user); 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_nonexistent (ActUser *user); const char *act_user_get_icon_file (ActUser *user); const char *act_user_get_language (ActUser *user); const char *act_user_get_x_session (ActUser *user); const char *act_user_get_session (ActUser *user); const char *act_user_get_session_type (ActUser *user); const char *act_user_get_primary_session_id (ActUser *user); gint act_user_collate (ActUser *user1, ActUser *user2); gboolean act_user_is_loaded (ActUser *user); 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); void act_user_set_email (ActUser *user, const char *email); void act_user_set_language (ActUser *user, const char *language); void act_user_set_x_session (ActUser *user, const char *x_session); diff --git a/src/user.c b/src/user.c index 94c0244..93afadc 100644 --- a/src/user.c +++ b/src/user.c @@ -284,60 +284,61 @@ user_update_from_keyfile (User *user, } s = g_key_file_get_string (keyfile, "User", "Location", NULL); if (s != NULL) { accounts_user_set_location (ACCOUNTS_USER (user), s); g_clear_pointer (&s, g_free); } s = g_key_file_get_string (keyfile, "User", "PasswordHint", NULL); if (s != NULL) { accounts_user_set_password_hint (ACCOUNTS_USER (user), s); g_clear_pointer (&s, g_free); } s = g_key_file_get_string (keyfile, "User", "Icon", NULL); if (s != NULL) { accounts_user_set_icon_file (ACCOUNTS_USER (user), s); g_clear_pointer (&s, g_free); } if (g_key_file_has_key (keyfile, "User", "SystemAccount", NULL)) { gboolean system_account; system_account = g_key_file_get_boolean (keyfile, "User", "SystemAccount", NULL); accounts_user_set_system_account (ACCOUNTS_USER (user), system_account); } g_clear_pointer (&user->keyfile, g_key_file_unref); user->keyfile = g_key_file_ref (keyfile); user_set_cached (user, TRUE); + user_set_saved (user, TRUE); g_object_thaw_notify (G_OBJECT (user)); } void user_update_local_account_property (User *user, gboolean local) { accounts_user_set_local_account (ACCOUNTS_USER (user), local); } void user_update_system_account_property (User *user, gboolean system) { accounts_user_set_system_account (ACCOUNTS_USER (user), system); } static void user_save_to_keyfile (User *user, GKeyFile *keyfile) { g_key_file_remove_group (keyfile, "User", NULL); if (accounts_user_get_email (ACCOUNTS_USER (user))) g_key_file_set_string (keyfile, "User", "Email", accounts_user_get_email (ACCOUNTS_USER (user))); if (accounts_user_get_language (ACCOUNTS_USER (user))) g_key_file_set_string (keyfile, "User", "Language", accounts_user_get_language (ACCOUNTS_USER (user))); @@ -357,60 +358,62 @@ user_save_to_keyfile (User *user, g_key_file_set_string (keyfile, "User", "PasswordHint", accounts_user_get_password_hint (ACCOUNTS_USER (user))); if (accounts_user_get_icon_file (ACCOUNTS_USER (user))) g_key_file_set_string (keyfile, "User", "Icon", accounts_user_get_icon_file (ACCOUNTS_USER (user))); g_key_file_set_boolean (keyfile, "User", "SystemAccount", accounts_user_get_system_account (ACCOUNTS_USER (user))); user_set_cached (user, TRUE); } static void save_extra_data (User *user) { g_autofree gchar *data = NULL; g_autofree gchar *filename = NULL; g_autoptr(GError) error = NULL; user_save_to_keyfile (user, user->keyfile); data = g_key_file_to_data (user->keyfile, NULL, &error); if (data == NULL) { g_warning ("Saving data for user %s failed: %s", accounts_user_get_user_name (ACCOUNTS_USER (user)), error->message); return; } filename = g_build_filename (USERDIR, accounts_user_get_user_name (ACCOUNTS_USER (user)), NULL); g_file_set_contents (filename, data, -1, &error); + + user_set_saved (user, TRUE); } static void move_extra_data (const gchar *old_name, const gchar *new_name) { g_autofree gchar *old_filename = NULL; g_autofree gchar *new_filename = NULL; old_filename = g_build_filename (USERDIR, old_name, NULL); new_filename = g_build_filename (USERDIR, new_name, NULL); g_rename (old_filename, new_filename); } static GVariant * user_extension_get_value (User *user, GDBusInterfaceInfo *interface, const GDBusPropertyInfo *property) { const GVariantType *type = G_VARIANT_TYPE (property->signature); GVariant *value; g_autofree gchar *printed = NULL; gint i; /* First, try to get the value from the keyfile */ printed = g_key_file_get_value (user->keyfile, interface->name, property->name, NULL); if (printed) { @@ -773,60 +776,67 @@ const gchar * user_get_object_path (User *user) { return g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (user)); } uid_t user_get_uid (User *user) { return accounts_user_get_uid (ACCOUNTS_USER (user)); } const gchar * user_get_shell(User *user) { return accounts_user_get_shell (ACCOUNTS_USER (user)); } gboolean user_get_cached (User *user) { return user->cached; } void user_set_cached (User *user, gboolean cached) { user->cached = cached; } +void +user_set_saved (User *user, + gboolean saved) +{ + accounts_user_set_saved (ACCOUNTS_USER (user), saved); +} + static void throw_error (GDBusMethodInvocation *context, gint error_code, const gchar *format, ...) { va_list args; g_autofree gchar *message = NULL; va_start (args, format); message = g_strdup_vprintf (format, args); va_end (args); g_dbus_method_invocation_return_error (context, ERROR, error_code, "%s", message); } static void user_change_real_name_authorized_cb (Daemon *daemon, User *user, GDBusMethodInvocation *context, gpointer data) { gchar *name = data; g_autoptr(GError) error = NULL; const gchar *argv[6]; if (g_strcmp0 (accounts_user_get_real_name (ACCOUNTS_USER (user)), name) != 0) { sys_log (context, "change real name of user '%s' (%d) to '%s'", diff --git a/src/user.h b/src/user.h index 39c6f13..b3b3380 100644 --- a/src/user.h +++ b/src/user.h @@ -39,47 +39,49 @@ typedef enum { ACCOUNT_TYPE_STANDARD, ACCOUNT_TYPE_ADMINISTRATOR, #define ACCOUNT_TYPE_LAST ACCOUNT_TYPE_ADMINISTRATOR } AccountType; typedef enum { PASSWORD_MODE_REGULAR, PASSWORD_MODE_SET_AT_LOGIN, PASSWORD_MODE_NONE, #define PASSWORD_MODE_LAST PASSWORD_MODE_NONE } PasswordMode; /* local methods */ GType user_get_type (void) G_GNUC_CONST; User * user_new (Daemon *daemon, uid_t uid); void user_update_from_pwent (User *user, struct passwd *pwent, struct spwd *spent); void user_update_from_keyfile (User *user, GKeyFile *keyfile); void user_update_local_account_property (User *user, gboolean local); void user_update_system_account_property (User *user, gboolean system); gboolean user_get_cached (User *user); void user_set_cached (User *user, gboolean cached); +void user_set_saved (User *user, + gboolean saved); void user_register (User *user); void user_unregister (User *user); void user_changed (User *user); 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); const gchar * user_get_object_path (User *user); uid_t user_get_uid (User *user); const gchar * user_get_shell (User *user); G_END_DECLS #endif -- 2.17.1