test-system-xauthority \
test-user-renamed \
test-user-renamed-invalid \
+ test-users-gobject \
+ test-users-python \
test-keyboard-layout \
test-no-keyboard-layout \
test-language \
test-login-qt4-guest-fail-setup-script \
test-login-qt4-guest-logout \
test-login-qt4-remote-session \
+ test-users-qt4 \
test-qt4-power \
test-qt4-power-no-console-kit \
test-qt4-power-no-login1 \
test-login-qt5-guest-fail-setup-script \
test-login-qt5-guest-logout \
test-login-qt5-remote-session \
+ test-users-qt5 \
test-qt5-power \
test-qt5-power-no-console-kit \
test-qt5-power-no-login1 \
scripts/switch-to-user-logout.conf \
scripts/switch-to-user-no-password.conf \
scripts/system-xauthority.conf \
+ scripts/users.conf \
scripts/util-path.conf \
scripts/user-renamed.conf \
scripts/user-renamed-invalid.conf \
}
g_free (r);
+ r = g_strdup_printf ("%s LOG-USER-LIST-LENGTH", greeter_id);
+ if (strcmp (request, r) == 0)
+ status_notify ("%s LOG-USER-LIST-LENGTH N=%d", greeter_id, lightdm_user_list_get_length (lightdm_user_list_get_instance ()));
+ g_free (r);
+
+ r = g_strdup_printf ("%s LOG-USER USERNAME=", greeter_id);
+ if (g_str_has_prefix (request, r))
+ {
+ LightDMUser *user;
+ const gchar *username;
+
+ username = request + strlen (r);
+ user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username);
+ status_notify ("%s LOG-USER USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+ }
+ g_free (r);
+
+ r = g_strdup_printf ("%s LOG-USER-LIST", greeter_id);
+ if (strcmp (request, r) == 0)
+ {
+ GList *users, *link;
+
+ users = lightdm_user_list_get_users (lightdm_user_list_get_instance ());
+ for (link = users; link; link = link->next)
+ {
+ LightDMUser *user = link->data;
+ status_notify ("%s LOG-USER USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+ }
+ }
+ g_free (r);
+
r = g_strdup_printf ("%s LOG-LAYOUT USERNAME=", greeter_id);
if (g_str_has_prefix (request, r))
{
g_free (r);
}
+static void
+user_added_cb (LightDMUserList *user_list, LightDMUser *user)
+{
+ status_notify ("%s USER-ADDED USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+}
+
+static void
+user_removed_cb (LightDMUserList *user_list, LightDMUser *user)
+{
+ status_notify ("%s USER-REMOVED USERNAME=%s", greeter_id, lightdm_user_get_name (user));
+}
+
int
main (int argc, char **argv)
{
g_signal_connect (greeter, "authentication-complete", G_CALLBACK (authentication_complete_cb), NULL);
g_signal_connect (greeter, "autologin-timer-expired", G_CALLBACK (autologin_timer_expired_cb), NULL);
+ if (g_key_file_get_boolean (config, "test-greeter-config", "log-user-changes", NULL))
+ {
+ g_signal_connect (lightdm_user_list_get_instance (), "user-added", G_CALLBACK (user_added_cb), NULL);
+ g_signal_connect (lightdm_user_list_get_instance (), "user-removed", G_CALLBACK (user_removed_cb), NULL);
+ }
+
status_notify ("%s CONNECT-TO-DAEMON", greeter_id);
if (!lightdm_greeter_connect_sync (greeter, NULL))
{
if not greeter.start_session_sync (request[len(r):]):
status_notify ('%s SESSION-FAILED' % greeter_id)
+ r = '%s LOG-USER-LIST-LENGTH' % greeter_id
+ if request == r:
+ status_notify ('%s LOG-USER-LIST-LENGTH N=%d' % (greeter_id, LightDM.UserList.get_instance ().get_length ()))
+
+ r = '%s LOG-USER USERNAME=' % greeter_id
+ if request.startswith (r):
+ username = request[len(r):]
+ user = LightDM.UserList.get_instance ().get_user_by_name (username)
+ status_notify ('%s LOG-USER USERNAME=%s' % (greeter_id, user.get_name ()))
+
+ r = '%s LOG-USER-LIST' % greeter_id
+ if request == r:
+ users = LightDM.UserList.get_instance ().get_users ();
+ for user in users:
+ status_notify ('%s LOG-USER USERNAME=%s' % (greeter_id, user.get_name ()))
+
r = '%s LOG-LAYOUT' % greeter_id
if request == r:
layout = LightDM.get_layout ().get_name ()
r = '%s LOG-LANGUAGE USERNAME=' % greeter_id
if request.startswith (r):
username = request[len(r):]
- user = lightdm_user_list_get_user_by_name (lightdm_user_list_get_instance (), username)
- language = lightdm_user_get_language (user)
+ user = LightDM.UserList.get_instance ().get_user_by_name (username)
+ language = user.get_language ()
if language is None:
language = ''
status_notify ('%s LOG-LANGUAGE USERNAME=%s LANGUAGE=%s' % (greeter_id, username, language))
status_notify ('%s START' % greeter_id)
+config = GLib.KeyFile ()
+config.load_from_file (os.getenv ('LIGHTDM_TEST_ROOT') + '/script', GLib.KeyFileFlags.NONE)
+
# NOTE: There don't seem to be any good X bindings so we have to mock up our own...
(host, display_number) = display.split (':')
if host == '':
greeter.connect ('authentication-complete', authentication_complete_cb)
greeter.connect ('autologin-timer-expired', autologin_timer_expired_cb)
+def user_added_cb (user_list, user):
+ status_notify ('%s USER-ADDED USERNAME=%s' % (greeter_id, user.get_name ()))
+def user_removed_cb (user_list, user):
+ status_notify ('%s USER-REMOVED USERNAME=%s' % (greeter_id, user.get_name ()))
+log_user_changes = False
+try:
+ log_user_changes = config.get_boolean ('test-greeter-config', 'log-user-changes')
+except:
+ pass
+if log_user_changes:
+ LightDM.UserList.get_instance ().connect ('user-added', user_added_cb)
+ LightDM.UserList.get_instance ().connect ('user-removed', user_removed_cb)
+
status_notify ('%s CONNECT-TO-DAEMON' % greeter_id)
if not greeter.connect_sync ():
status_notify ('%s FAIL-CONNECT-DAEMON' % greeter_id)
#include <xcb/xcb.h>
#include <QLightDM/Greeter>
#include <QLightDM/Power>
+#include <QLightDM/UsersModel>
#include <QtCore/QSettings>
#include <QtCore/QDebug>
#include <QtCore/QCoreApplication>
static QSettings *config = NULL;
static QLightDM::PowerInterface *power = NULL;
static TestGreeter *greeter = NULL;
+static QLightDM::UsersModel *users_model = NULL;
TestGreeter::TestGreeter ()
{
status_notify ("%s AUTOLOGIN-TIMER-EXPIRED", greeter_id);
}
+void TestGreeter::userRowsInserted (const QModelIndex & parent, int start, int end)
+{
+ for (int i = start; i <= end; i++)
+ {
+ QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+ status_notify ("%s USER-ADDED USERNAME=%s", greeter_id, qPrintable (name));
+ }
+}
+
+void TestGreeter::userRowsRemoved (const QModelIndex & parent, int start, int end)
+{
+ for (int i = start; i <= end; i++)
+ {
+ QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+ status_notify ("%s USER-REMOVED USERNAME=%s", greeter_id, qPrintable (name));
+ }
+}
+
static void
signal_cb (int signum)
{
}
g_free (r);
+ r = g_strdup_printf ("%s LOG-USER-LIST-LENGTH", greeter_id);
+ if (strcmp (request, r) == 0)
+ status_notify ("%s LOG-USER-LIST-LENGTH N=%d", greeter_id, users_model->rowCount (QModelIndex ()));
+ g_free (r);
+
+ r = g_strdup_printf ("%s LOG-USER USERNAME=", greeter_id);
+ if (g_str_has_prefix (request, r))
+ {
+ const gchar *username = request + strlen (r);
+ for (int i = 0; i < users_model->rowCount (QModelIndex ()); i++)
+ {
+ QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+ if (name == username)
+ status_notify ("%s LOG-USER USERNAME=%s", greeter_id, qPrintable (name));
+ }
+ }
+ g_free (r);
+
+ r = g_strdup_printf ("%s LOG-USER-LIST", greeter_id);
+ if (strcmp (request, r) == 0)
+ {
+ for (int i = 0; i < users_model->rowCount (QModelIndex ()); i++)
+ {
+ QString name = users_model->data (users_model->index (i, 0), QLightDM::UsersModel::NameRole).toString ();
+ status_notify ("%s LOG-USER USERNAME=%s", greeter_id, qPrintable (name));
+ }
+ }
+ g_free (r);
+
r = g_strdup_printf ("%s GET-CAN-SUSPEND", greeter_id);
if (strcmp (request, r) == 0)
{
power = new QLightDM::PowerInterface();
greeter = new TestGreeter();
-
+
+ users_model = new QLightDM::UsersModel();
+ if (config->value ("test-greeter-config/log-user-changes", "false") == "true")
+ {
+ QObject::connect (users_model, SIGNAL(rowsInserted(const QModelIndex&, int, int)), greeter, SLOT(userRowsInserted(const QModelIndex&, int, int)));
+ QObject::connect (users_model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)), greeter, SLOT(userRowsRemoved(const QModelIndex&, int, int)));
+ }
+
status_notify ("%s CONNECT-TO-DAEMON", greeter_id);
if (!greeter->connectSync())
{
#include <QLightDM/Greeter>
+#include <QLightDM/UsersModel>
class TestGreeter : public QLightDM::Greeter
{
void showPrompt(QString text, QLightDM::Greeter::PromptType type);
void authenticationComplete();
void autologinTimerExpired();
+ void userRowsInserted(const QModelIndex & parent, int start, int end);
+ void userRowsRemoved(const QModelIndex & parent, int start, int end);
};
gchar *language;
gchar *xsession;
gchar **layouts;
+ gboolean hidden;
} AccountsUser;
static GList *accounts_users = NULL;
static void handle_user_call (GDBusConnection *connection,
static void run_lightdm (void);
static void quit (int status);
static void check_status (const gchar *status);
+static AccountsUser *get_accounts_user_by_uid (guint uid);
+static AccountsUser *get_accounts_user_by_name (const gchar *username);
+static void accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal);
static gboolean
kill_timeout_cb (gpointer data)
g_hash_table_insert (children, GINT_TO_POINTER (process->pid), process);
}
}
+ else if (strcmp (name, "ADD-USER") == 0)
+ {
+ gchar *status_text, *username;
+ AccountsUser *user;
+
+ username = g_hash_table_lookup (params, "USERNAME");
+ user = get_accounts_user_by_name (username);
+ if (user)
+ accounts_user_set_hidden (user, FALSE, TRUE);
+ else
+ g_warning ("Unknown user %s", username);
+
+ status_text = g_strdup_printf ("RUNNER ADD-USER USERNAME=%s", username);
+ check_status (status_text);
+ g_free (status_text);
+ }
+ else if (strcmp (name, "DELETE-USER") == 0)
+ {
+ gchar *status_text, *username;
+ AccountsUser *user;
+
+ username = g_hash_table_lookup (params, "USERNAME");
+ user = get_accounts_user_by_name (username);
+ if (user)
+ accounts_user_set_hidden (user, TRUE, TRUE);
+ else
+ g_warning ("Unknown user %s", username);
+
+ status_text = g_strdup_printf ("RUNNER DELETE-USER USERNAME=%s", username);
+ check_status (status_text);
+ g_free (status_text);
+ }
/* Forward to external processes */
else if (g_str_has_prefix (name, "SESSION-") ||
g_str_has_prefix (name, "GREETER-") ||
NULL);
}
+static AccountsUser *
+get_accounts_user_by_uid (guint uid)
+{
+ GList *link;
+
+ for (link = accounts_users; link; link = link->next)
+ {
+ AccountsUser *u = link->data;
+ if (u->uid == uid)
+ return u;
+ }
+
+ return NULL;
+}
+
+static AccountsUser *
+get_accounts_user_by_name (const gchar *username)
+{
+ GList *link;
+
+ for (link = accounts_users; link; link = link->next)
+ {
+ AccountsUser *u = link->data;
+ if (strcmp (u->user_name, username) == 0)
+ return u;
+ }
+
+ return NULL;
+}
+
+static void
+accounts_user_set_hidden (AccountsUser *user, gboolean hidden, gboolean emit_signal)
+{
+ GError *error = NULL;
+
+ user->hidden = hidden;
+
+ if (user->hidden && user->id != 0)
+ {
+ g_dbus_connection_unregister_object (accounts_connection, user->id);
+ g_dbus_connection_emit_signal (accounts_connection,
+ NULL,
+ "/org/freedesktop/Accounts",
+ "org.freedesktop.Accounts",
+ "UserDeleted",
+ g_variant_new ("(o)", user->path),
+ &error);
+ if (error)
+ g_warning ("Failed to emit UserDeleted: %s", error->message);
+ g_clear_error (&error);
+
+ user->id = 0;
+ }
+ if (!user->hidden && user->id == 0)
+ {
+ user->id = g_dbus_connection_register_object (accounts_connection,
+ user->path,
+ user_info->interfaces[0],
+ &user_vtable,
+ user,
+ NULL,
+ &error);
+ if (error)
+ g_warning ("Failed to register user: %s", error->message);
+ g_clear_error (&error);
+
+ g_dbus_connection_emit_signal (accounts_connection,
+ NULL,
+ "/org/freedesktop/Accounts",
+ "org.freedesktop.Accounts",
+ "UserAdded",
+ g_variant_new ("(o)", user->path),
+ &error);
+ if (error)
+ g_warning ("Failed to emit UserAdded: %s", error->message);
+ g_clear_error (&error);
+ }
+}
+
static void
load_passwd_file ()
{
gchar *path, *data, **lines;
+ gchar **user_filter = NULL;
int i;
+ if (g_key_file_has_key (config, "test-runner-config", "accounts-service-user-filter", NULL))
+ {
+ gchar *filter;
+
+ filter = g_key_file_get_string (config, "test-runner-config", "accounts-service-user-filter", NULL);
+ user_filter = g_strsplit (filter, " ", -1);
+ g_free (filter);
+ }
+
path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "passwd", NULL);
g_file_get_contents (path, &data, NULL, NULL);
g_free (path);
fields = g_strsplit (lines[i], ":", -1);
if (fields == NULL || g_strv_length (fields) < 7)
+ {
+ g_strfreev (fields);
continue;
+ }
user_name = fields[0];
uid = atoi (fields[2]);
real_name = fields[4];
- for (link = accounts_users; link; link = link->next)
- {
- AccountsUser *u = link->data;
- if (u->uid == uid)
- {
- user = u;
- break;
- }
- }
+ user = get_accounts_user_by_uid (uid);
if (!user)
{
gchar *path;
user = g_malloc0 (sizeof (AccountsUser));
accounts_users = g_list_append (accounts_users, user);
+ /* Only allow users in whitelist */
+ user->hidden = FALSE;
+ if (user_filter)
+ {
+ int j;
+
+ user->hidden = TRUE;
+ for (j = 0; user_filter[j] != NULL; j++)
+ if (strcmp (user_name, user_filter[j]) == 0)
+ user->hidden = FALSE;
+ }
+
dmrc_file = g_key_file_new ();
path = g_build_filename (temp_dir, "home", user_name, ".dmrc", NULL);
g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
user->xsession = g_key_file_get_string (dmrc_file, "Desktop", "Session", NULL);
user->layouts = g_key_file_get_string_list (dmrc_file, "X-Accounts", "Layouts", NULL, NULL);
user->path = g_strdup_printf ("/org/freedesktop/Accounts/User%d", uid);
- user->id = g_dbus_connection_register_object (accounts_connection,
- user->path,
- user_info->interfaces[0],
- &user_vtable,
- user,
- NULL,
- &error);
- if (error)
- g_warning ("Failed to register user: %s", error->message);
- g_clear_error (&error);
+ accounts_user_set_hidden (user, user->hidden, FALSE);
g_key_file_free (dmrc_file);
}
for (link = accounts_users; link; link = link->next)
{
AccountsUser *user = link->data;
- g_variant_builder_add_value (&builder, g_variant_new_object_path (user->path));
+ if (!user->hidden)
+ g_variant_builder_add_value (&builder, g_variant_new_object_path (user->path));
}
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ao)", &builder));
g_variant_get (parameters, "(&s)", &user_name);
load_passwd_file ();
- for (link = accounts_users; link; link = link->next)
- {
- AccountsUser *u = link->data;
- if (strcmp (u->user_name, user_name) == 0)
- {
- user = u;
- break;
- }
- }
- if (user)
+ user = get_accounts_user_by_name (user_name);
+ if (user && !user->hidden)
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", user->path));
else
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No such user: %s", user_name);
" <arg name='name' direction='in' type='s'/>"
" <arg name='user' direction='out' type='o'/>"
" </method>"
+ " <signal name='UserAdded'>"
+ " <arg name='user' type='o'/>"
+ " </signal>"
+ " <signal name='UserDeleted'>"
+ " <arg name='user' type='o'/>"
+ " </signal>"
" </interface>"
"</node>";
static const GDBusInterfaceVTable accounts_vtable =
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-gobject-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-python-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-qt4-greeter
--- /dev/null
+#!/bin/sh
+./src/dbus-env ./src/test-runner users test-qt5-greeter