Commit 9fbdef75 authored by Tomi Leppänen's avatar Tomi Leppänen

Merge branch 'jb49173_user_model' into 'master'

Add model to access user info

See merge request !134
parents 26cc3aef 6eab714d
......@@ -12,6 +12,7 @@ Requires: connman
Requires: mce >= 1.83.0
Requires: libsailfishkeyprovider >= 0.0.14
Requires: connman-qt5 >= 1.2.21
Requires: user-managerd
Requires(post): coreutils
BuildRequires: pkgconfig(Qt5Qml)
BuildRequires: pkgconfig(Qt5SystemInfo)
......@@ -32,6 +33,8 @@ BuildRequires: pkgconfig(ssu-sysinfo) >= 1.1.0
BuildRequires: pkgconfig(packagekitqt5)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(sailfishaccesscontrol)
BuildRequires: pkgconfig(libsystemd)
BuildRequires: pkgconfig(sailfishusermanager)
%description
%{summary}.
......
......@@ -34,3 +34,4 @@
Q_LOGGING_CATEGORY(lcVpnLog, "org.sailfishos.settings.vpn", QtWarningMsg)
Q_LOGGING_CATEGORY(lcDeveloperModeLog, "org.sailfishos.settings.developermode", QtWarningMsg)
Q_LOGGING_CATEGORY(lcMemoryCardLog, "org.sailfishos.settings.memorycard", QtWarningMsg)
Q_LOGGING_CATEGORY(lcUsersLog, "org.sailfishos.settings.users", QtWarningMsg)
......@@ -37,5 +37,6 @@
Q_DECLARE_LOGGING_CATEGORY(lcVpnLog)
Q_DECLARE_LOGGING_CATEGORY(lcDeveloperModeLog)
Q_DECLARE_LOGGING_CATEGORY(lcMemoryCardLog)
Q_DECLARE_LOGGING_CATEGORY(lcUsersLog)
#endif
......@@ -51,6 +51,8 @@
#include "locationsettings.h"
#include "deviceinfo.h"
#include "nfcsettings.h"
#include "userinfo.h"
#include "usermodel.h"
template<class T>
static QObject *api_factory(QQmlEngine *, QJSEngine *)
......@@ -91,6 +93,8 @@ public:
qmlRegisterType<LocationSettings>(uri, 1, 0, "LocationSettings");
qmlRegisterType<DeviceInfo>(uri, 1, 0, "DeviceInfo");
qmlRegisterType<NfcSettings>(uri, 1, 0, "NfcSettings");
qmlRegisterType<UserInfo>(uri, 1, 0, "UserInfo");
qmlRegisterType<UserModel>(uri, 1, 0, "UserModel");
}
};
......
......@@ -7,7 +7,7 @@ QT -= gui
CONFIG += c++11 hide_symbols link_pkgconfig
PKGCONFIG += profile mlite5 mce timed-qt5 libshadowutils blkid libcrypto nemomodels-qt5 libsailfishkeyprovider connman-qt5 glib-2.0
PKGCONFIG += ssu-sysinfo nemodbus packagekitqt5
PKGCONFIG += ssu-sysinfo nemodbus packagekitqt5 libsystemd sailfishusermanager
system(qdbusxml2cpp -p mceiface.h:mceiface.cpp mce.xml)
......@@ -37,7 +37,9 @@ SOURCES += \
udisks2block.cpp \
udisks2blockdevices.cpp \
udisks2job.cpp \
udisks2monitor.cpp
udisks2monitor.cpp \
userinfo.cpp \
usermodel.cpp
PUBLIC_HEADERS = \
languagemodel.h \
......@@ -60,7 +62,9 @@ PUBLIC_HEADERS = \
systemsettingsglobal.h \
deviceinfo.h \
locationsettings.h \
timezoneinfo.h
timezoneinfo.h \
userinfo.h \
usermodel.h
HEADERS += \
$$PUBLIC_HEADERS \
......@@ -76,7 +80,8 @@ HEADERS += \
partitionmanager_p.h \
udisks2blockdevices_p.h \
udisks2job_p.h \
udisks2monitor_p.h
udisks2monitor_p.h \
userinfo_p.h
DEFINES += \
SYSTEMSETTINGS_BUILD_LIBRARY
......
/*
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#include "userinfo.h"
#include "userinfo_p.h"
#include <pwd.h>
#include <sys/types.h>
#include <systemd/sd-login.h>
namespace {
enum SpecialIds : uid_t {
DeviceOwnerId = 100000,
InvalidId = (uid_t)(-1),
};
QString nameFromGecos(const char *gecos)
{
// typically GECOS has (sub)fields separated by ","
// and the first one of them is full name of the user.
// Sometimes it contains just the full name or it might be empty,
// thus do this on best effort basis.
auto name = QString::fromUtf8(gecos);
int i = name.indexOf(QStringLiteral(","));
if (i != -1)
name.truncate(i);
return name;
}
}
UserInfoPrivate::UserInfoPrivate()
: m_uid(InvalidId)
, m_loggedIn(false)
{
}
UserInfoPrivate::UserInfoPrivate(struct passwd *pwd)
: m_uid(pwd->pw_uid)
, m_username(QString::fromUtf8(pwd->pw_name))
, m_name(nameFromGecos(pwd->pw_gecos))
// require_active == false -> both online and active are logged in.
// 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, 0, "seat0") > 0)
{
}
UserInfoPrivate::~UserInfoPrivate()
{
}
QWeakPointer<UserInfoPrivate> UserInfoPrivate::s_current;
void UserInfoPrivate::set(struct passwd *pwd)
{
QString username;
QString name;
if (pwd) {
Q_ASSERT(pwd->pw_uid == m_uid);
username = QString::fromUtf8(pwd->pw_name);
name = nameFromGecos(pwd->pw_gecos);
} else if (m_uid != InvalidId) {
m_uid = InvalidId;
emit uidChanged();
}
if (m_username != username) {
m_username = username;
emit usernameChanged();
}
if (m_name != name) {
m_name = name;
emit nameChanged();
}
}
/**
* Construct UserInfo for the current user
*
* If it has been constructed before, this reuses the old data.
*/
UserInfo::UserInfo()
{
if (!UserInfoPrivate::s_current.isNull()) {
d_ptr = QSharedPointer<UserInfoPrivate>(UserInfoPrivate::s_current);
}
if (d_ptr.isNull()) {
uid_t uid = InvalidId;
struct passwd *pwd;
if (sd_seat_get_active("seat0", NULL, &uid) < 0 || uid == InvalidId || !(pwd = getpwuid(uid))) {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate);
} else {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate(pwd));
}
// pwd must not be free'd
}
if (current())
UserInfoPrivate::s_current = d_ptr;
connectSignals();
}
UserInfo::UserInfo(const UserInfo &other)
: QObject(other.parent())
, d_ptr(other.d_ptr)
{
connectSignals();
}
/**
* Construct UserInfo by uid
*/
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));
} else {
d_ptr = QSharedPointer<UserInfoPrivate>(new UserInfoPrivate);
}
// pwd must not be free'd
if (current())
UserInfoPrivate::s_current = d_ptr;
connectSignals();
}
/**
* Construct UserInfo by username
*/
UserInfo::UserInfo(QString username)
{
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;
connectSignals();
}
/**
* Construct a placeholder user that doesn't exist
*
* Placeholder users are always invalid.
*/
UserInfo UserInfo::placeholder()
{
return UserInfo(InvalidId);
}
UserInfo::~UserInfo()
{
}
/**
* Returns true if user exists
*/
bool UserInfo::isValid() const
{
Q_D(const UserInfo);
return d->m_uid != InvalidId;
}
QString UserInfo::username() const
{
Q_D(const UserInfo);
return d->m_username;
}
void UserInfo::setUsername(QString username)
{
Q_D(UserInfo);
if (d->m_username != username) {
d->m_username = username;
emit d_ptr->usernameChanged();
}
}
QString UserInfo::name() const
{
Q_D(const UserInfo);
return d->m_name;
}
void UserInfo::setName(QString name)
{
Q_D(UserInfo);
if (d->m_name != name) {
d->m_name = name;
emit d_ptr->nameChanged();
}
}
UserInfo::UserType UserInfo::type() const
{
Q_D(const UserInfo);
// Device lock considers user with id 100000 as device owner.
// Some other places consider the user belonging to sailfish-system
// as device owner. We have to pick one here.
return (d->m_uid == DeviceOwnerId) ? DeviceOwner : User;
}
int UserInfo::uid() const
{
Q_D(const UserInfo);
return (int)d->m_uid;
}
/**
* Returs true if user is logged in on seat0 and is the active user, i.e. the current user
*/
bool UserInfo::current() const
{
Q_D(const UserInfo);
// Any logged in user (on seat0) must be the current one
// since we don't have multisession.
return d->m_loggedIn;
}
void UserInfo::reset()
{
Q_D(UserInfo);
d->set((isValid()) ? getpwuid(d->m_uid) : nullptr);
}
UserInfo &UserInfo::operator=(const UserInfo &other)
{
if (this == &other)
return *this;
d_ptr = other.d_ptr;
return *this;
}
bool UserInfo::operator==(const UserInfo &other) const
{
if (!isValid())
return false;
return d_ptr == other.d_ptr;
}
bool UserInfo::operator!=(const UserInfo &other) const
{
if (!isValid())
return true;
return d_ptr != other.d_ptr;
}
void UserInfo::connectSignals()
{
connect(d_ptr.data(), &UserInfoPrivate::usernameChanged, this, &UserInfo::usernameChanged);
connect(d_ptr.data(), &UserInfoPrivate::nameChanged, this, &UserInfo::nameChanged);
connect(d_ptr.data(), &UserInfoPrivate::uidChanged, this, &UserInfo::uidChanged);
}
/*
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#ifndef USERINFO_H
#define USERINFO_H
#include <QObject>
#include <QList>
#include <QSharedPointer>
#include "systemsettingsglobal.h"
class UserInfoPrivate;
class UserModel;
class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(UserInfo)
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(bool current READ current CONSTANT)
friend class UserModel;
public:
enum UserType {
User = 0,
DeviceOwner = 1,
};
Q_ENUM(UserType)
UserInfo();
UserInfo(const UserInfo &other);
~UserInfo();
static UserInfo placeholder();
bool isValid() const;
QString username() const;
QString name() const;
UserType type() const;
int uid() const;
bool current() const;
Q_INVOKABLE void reset();
UserInfo &operator=(const UserInfo &other);
bool operator==(const UserInfo &other) const;
bool operator!=(const UserInfo &other) const;
signals:
void usernameChanged();
void nameChanged();
void uidChanged();
private:
explicit UserInfo(int uid);
explicit UserInfo(QString username);
void setUsername(QString username);
void setName(QString name);
void connectSignals();
QSharedPointer<UserInfoPrivate> d_ptr;
};
#endif /* USERINFO_H */
/*
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#ifndef USERINFOPRIVATE_H
#define USERINFOPRIVATE_H
#include <QObject>
#include <QString>
#include <QWeakPointer>
class UserInfoPrivate : public QObject
{
Q_OBJECT
public:
UserInfoPrivate();
UserInfoPrivate(struct passwd *pwd);
~UserInfoPrivate();
uid_t m_uid;
QString m_username;
QString m_name;
bool m_loggedIn;
static QWeakPointer<UserInfoPrivate> s_current;
void set(struct passwd *pwd);
signals:
void usernameChanged();
void nameChanged();
void uidChanged();
};
#endif /* USERINFOPRIVATE_H */
This diff is collapsed.
/*
* Copyright (C) 2020 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/
#ifndef USERMODEL_H
#define USERMODEL_H
#include <QAbstractListModel>
#include <QHash>
#include <QVector>
#include "systemsettingsglobal.h"
#include "userinfo.h"
class QDBusInterface;
class QDBusPendingCallWatcher;
class QDBusServiceWatcher;
struct SailfishUserManagerEntry;
class SYSTEMSETTINGS_EXPORT UserModel: public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(bool placeholder READ placeholder WRITE setPlaceholder NOTIFY placeholderChanged)
public:
enum Roles {
UsernameRole = Qt::UserRole,
NameRole,
TypeRole,
UidRole,
CurrentRole,
PlaceholderRole,
};
Q_ENUM(Roles)
enum UserType {
User = 0,
DeviceOwner = 1,
};
Q_ENUM(UserType)
explicit UserModel(QObject *parent = 0);
~UserModel();
bool placeholder();
void setPlaceholder(bool value);
QHash<int, QByteArray> roleNames() const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
Q_INVOKABLE void createUser();
Q_INVOKABLE void removeUser(int row);
Q_INVOKABLE void reset(int row);
Q_INVOKABLE UserInfo * getCurrentUser() const;
signals:
void placeholderChanged();
void userAddFailed();
void userModifyFailed(int row, const QString &name);
void userRemoveFailed(int row, const QString &name);
private slots:
void userAdded(const SailfishUserManagerEntry &entry);
void userModified(uint uid, const QString &newName);
void userRemoved(uint uid);
void userAddFinished(QDBusPendingCallWatcher *call, int row);
void userModifyFinished(QDBusPendingCallWatcher *call, int row);
void userRemoveFinished(QDBusPendingCallWatcher *call, int row);
void createInterface();
void destroyInterface();
private:
QVector<UserInfo> m_users;
QHash<uint, int> m_uidsToRows;
QDBusInterface *m_dBusInterface;
QDBusServiceWatcher *m_dBusWatcher;
};
#endif /* USERMODEL_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment