Navigation Menu

Skip to content

Commit

Permalink
Merge branch 'jb49640_jb49699' into 'master'
Browse files Browse the repository at this point in the history
Allow setting UserInfo by uid and update UserInfo if changes happen

See merge request mer-core/nemo-qml-plugin-systemsettings!142
  • Loading branch information
Tomin1 committed Apr 23, 2020
2 parents 6a24b44 + fafdffc commit 5ef4c99
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 17 deletions.
89 changes: 73 additions & 16 deletions src/userinfo.cpp
Expand Up @@ -33,6 +33,8 @@
#include "userinfo_p.h"
#include "logging_p.h"

#include <QFile>
#include <QFileSystemWatcher>
#include <QSocketNotifier>
#include <poll.h>
#include <pwd.h>
Expand All @@ -41,6 +43,8 @@

namespace {

const auto UserDatabaseFile = QStringLiteral("/etc/passwd");

enum SpecialIds : uid_t {
DeviceOwnerId = 100000,
UnknownCurrentUserId = (uid_t)(-2),
Expand All @@ -65,6 +69,7 @@ QString nameFromGecos(const char *gecos)
UserInfoPrivate::UserInfoPrivate()
: m_uid(InvalidId)
, m_loggedIn(false)
, m_watcher(nullptr)
{
}

Expand All @@ -76,6 +81,7 @@ UserInfoPrivate::UserInfoPrivate(struct passwd *pwd)
// Specifying seat should make sure that remote users are not
// counted as they don't have seats.
, m_loggedIn(sd_uid_is_on_seat(m_uid, 1, "seat0") > 0)
, m_watcher(nullptr)
{
}

Expand Down Expand Up @@ -143,10 +149,11 @@ UserInfo::UserInfo()
waitForActivation();
}
// pwd must not be free'd
if (current())
UserInfoPrivate::s_current = d_ptr;
}
if (current())
UserInfoPrivate::s_current = d_ptr;
connectSignals();
watchForChanges();
}

UserInfo::UserInfo(const UserInfo &other)
Expand All @@ -161,15 +168,20 @@ UserInfo::UserInfo(const UserInfo &other)
*/
UserInfo::UserInfo(int uid)
{
struct passwd *pwd = (uid_t)uid != InvalidId ? getpwuid((uid_t)uid) : nullptr;
if (pwd) {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate(pwd));
auto current_d = UserInfoPrivate::s_current.toStrongRef();
if (!current_d.isNull() && current_d->m_uid == (uid_t)uid) {
d_ptr = current_d;
} else {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate);
struct passwd *pwd = (uid_t)uid != InvalidId ? getpwuid((uid_t)uid) : nullptr;
if (pwd) {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate(pwd));
} else {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate);
}
// pwd must not be free'd
if (current())
UserInfoPrivate::s_current = d_ptr;
}
// pwd must not be free'd
if (current())
UserInfoPrivate::s_current = d_ptr;
connectSignals();
}

Expand All @@ -178,15 +190,20 @@ UserInfo::UserInfo(int uid)
*/
UserInfo::UserInfo(QString username)
{
struct passwd *pwd = getpwnam(username.toUtf8().constData());
if (pwd) {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate(pwd));
auto current_d = UserInfoPrivate::s_current.toStrongRef();
if (!current_d.isNull() && current_d->m_username == username) {
d_ptr = current_d;
} else {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate);
struct passwd *pwd = getpwnam(username.toUtf8().constData());
if (pwd) {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate(pwd));
} else {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate);
}
// pwd must not be free'd
if (current())
UserInfoPrivate::s_current = d_ptr;
}
// pwd must not be free'd
if (current())
UserInfoPrivate::s_current = d_ptr;
connectSignals();
}

Expand Down Expand Up @@ -275,6 +292,13 @@ int UserInfo::uid() const
return (int)d->m_uid;
}

void UserInfo::setUid(int uid)
{
Q_D(const UserInfo);
if ((uid_t)uid != d->m_uid)
replace(UserInfo(uid).d_ptr);
}

/**
* Returs true if user is logged in on seat0 and is the active user, i.e. the current user
*/
Expand Down Expand Up @@ -312,6 +336,7 @@ void UserInfo::reset()
void UserInfo::replace(QSharedPointer<UserInfoPrivate> other)
{
auto old = d_ptr;
disconnect(old.data(), 0, this, 0);
d_ptr = other;

if (old->m_username != d_ptr->m_username) {
Expand All @@ -331,6 +356,11 @@ void UserInfo::replace(QSharedPointer<UserInfoPrivate> other)

if (old->m_loggedIn != d_ptr->m_loggedIn)
emit currentChanged();

if (old->m_watcher)
watchForChanges();

connectSignals();
}

UserInfo &UserInfo::operator=(const UserInfo &other)
Expand Down Expand Up @@ -366,6 +396,33 @@ void UserInfo::connectSignals()
connect(d_ptr.data(), &UserInfoPrivate::currentChanged, this, &UserInfo::currentChanged);
}

void UserInfo::watchForChanges()
{
Q_D(UserInfo);
d->m_watcher = new QFileSystemWatcher(this);
if (!d->m_watcher->addPath(UserDatabaseFile)) {
qCWarning(lcUsersLog) << "Could not watch for changes in user database";
delete d->m_watcher;
d->m_watcher = nullptr;
} else {
connect(d->m_watcher, &QFileSystemWatcher::fileChanged, this, [this] {
Q_D(UserInfo);
if (QFile::exists(UserDatabaseFile)) {
// Database updated, reset
qCDebug(lcUsersLog) << "Reseting model because user database changed";
reset();
}
if (!d->m_watcher->files().contains(UserDatabaseFile)) {
if (QFile::exists(UserDatabaseFile) && d->m_watcher->addPath(UserDatabaseFile)) {
qCDebug(lcUsersLog) << "Re-watching user database for changes";
} else {
qCWarning(lcUsersLog) << "Stopped watching user database for changes";
}
}
});
}
}

void UserInfo::waitForActivation()
{
// Monitor systemd-logind for changes on seats
Expand Down
4 changes: 3 additions & 1 deletion src/userinfo.h
Expand Up @@ -50,7 +50,7 @@ class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
Q_PROPERTY(QString username READ username NOTIFY usernameChanged)
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(UserType type READ type CONSTANT)
Q_PROPERTY(int uid READ uid NOTIFY uidChanged)
Q_PROPERTY(int uid READ uid WRITE setUid NOTIFY uidChanged)
Q_PROPERTY(bool current READ current NOTIFY currentChanged)

friend class UserModel;
Expand All @@ -75,6 +75,7 @@ class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
QString name() const;
UserType type() const;
int uid() const;
void setUid(int uid);
bool current() const;

Q_INVOKABLE void reset();
Expand All @@ -100,6 +101,7 @@ class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
void replace(QSharedPointer<UserInfoPrivate> other);

void connectSignals();
void watchForChanges();
void waitForActivation();

QSharedPointer<UserInfoPrivate> d_ptr;
Expand Down
3 changes: 3 additions & 0 deletions src/userinfo_p.h
Expand Up @@ -38,6 +38,8 @@
#include <QString>
#include <QWeakPointer>

class QFileSystemWatcher;

class UserInfoPrivate : public QObject
{
Q_OBJECT
Expand All @@ -52,6 +54,7 @@ class UserInfoPrivate : public QObject
QString m_name;
bool m_loggedIn;
static QWeakPointer<UserInfoPrivate> s_current;
QFileSystemWatcher *m_watcher;

void set(struct passwd *pwd);

Expand Down

0 comments on commit 5ef4c99

Please sign in to comment.