UserManager: Add thing based user permissions
This commit is contained in:
parent
cdabfb54a5
commit
88aa22f3a2
@ -38,6 +38,9 @@
|
||||
#include "integrations/browseritemresult.h"
|
||||
#include "ruleengine/ruleengine.h"
|
||||
|
||||
#include "nymeacore.h"
|
||||
#include "usermanager/usermanager.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonDocument>
|
||||
#include <QCryptographicHash>
|
||||
@ -769,29 +772,65 @@ JsonReply* IntegrationsHandler::GetThings(const QVariantMap ¶ms, const JsonC
|
||||
{
|
||||
QVariantMap returns;
|
||||
QVariantList things;
|
||||
if (params.contains("thingId")) {
|
||||
Thing *thing = m_thingManager->findConfiguredThing(ThingId(params.value("thingId").toString()));
|
||||
if (!thing) {
|
||||
returns.insert("thingError", enumValueName<Thing::ThingError>(Thing::ThingErrorThingNotFound));
|
||||
return createReply(returns);
|
||||
} else {
|
||||
QVariantMap packedThing = pack(thing).toMap();
|
||||
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
||||
if (!translatedSetupStatus.isEmpty()) {
|
||||
packedThing["setupDisplayMessage"] = translatedSetupStatus;
|
||||
|
||||
|
||||
if (NymeaCore::instance()->userManager()->restrictedThingAccess(context.token())) {
|
||||
QList<ThingId> allowedThingIds = NymeaCore::instance()->userManager()->allowedThingIds(context.token());
|
||||
if (params.contains("thingId")) {
|
||||
ThingId thingId(params.value("thingId").toString());
|
||||
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
||||
if (!thing || !allowedThingIds.contains(thingId)) {
|
||||
returns.insert("thingError", enumValueName<Thing::ThingError>(Thing::ThingErrorThingNotFound));
|
||||
return createReply(returns);
|
||||
} else {
|
||||
QVariantMap packedThing = pack(thing).toMap();
|
||||
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
||||
if (!translatedSetupStatus.isEmpty()) {
|
||||
packedThing["setupDisplayMessage"] = translatedSetupStatus;
|
||||
}
|
||||
things.append(packedThing);
|
||||
}
|
||||
} else {
|
||||
foreach (Thing *thing, m_thingManager->configuredThings()) {
|
||||
if (!allowedThingIds.contains(thing->id()))
|
||||
continue;
|
||||
|
||||
|
||||
QVariantMap packedThing = pack(thing).toMap();
|
||||
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
||||
if (!translatedSetupStatus.isEmpty()) {
|
||||
packedThing["setupDisplayMessage"] = translatedSetupStatus;
|
||||
}
|
||||
things.append(packedThing);
|
||||
}
|
||||
things.append(packedThing);
|
||||
}
|
||||
} else {
|
||||
foreach (Thing *thing, m_thingManager->configuredThings()) {
|
||||
QVariantMap packedThing = pack(thing).toMap();
|
||||
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
||||
if (!translatedSetupStatus.isEmpty()) {
|
||||
packedThing["setupDisplayMessage"] = translatedSetupStatus;
|
||||
// Unrestricted things access
|
||||
if (params.contains("thingId")) {
|
||||
Thing *thing = m_thingManager->findConfiguredThing(ThingId(params.value("thingId").toString()));
|
||||
if (!thing) {
|
||||
returns.insert("thingError", enumValueName<Thing::ThingError>(Thing::ThingErrorThingNotFound));
|
||||
return createReply(returns);
|
||||
} else {
|
||||
QVariantMap packedThing = pack(thing).toMap();
|
||||
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
||||
if (!translatedSetupStatus.isEmpty()) {
|
||||
packedThing["setupDisplayMessage"] = translatedSetupStatus;
|
||||
}
|
||||
things.append(packedThing);
|
||||
}
|
||||
} else {
|
||||
foreach (Thing *thing, m_thingManager->configuredThings()) {
|
||||
QVariantMap packedThing = pack(thing).toMap();
|
||||
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
||||
if (!translatedSetupStatus.isEmpty()) {
|
||||
packedThing["setupDisplayMessage"] = translatedSetupStatus;
|
||||
}
|
||||
things.append(packedThing);
|
||||
}
|
||||
things.append(packedThing);
|
||||
}
|
||||
}
|
||||
|
||||
returns.insert("thingError", enumValueName<Thing::ThingError>(Thing::ThingErrorNoError));
|
||||
returns.insert("things", things);
|
||||
return createReply(returns);
|
||||
|
||||
@ -42,12 +42,13 @@ UsersHandler::UsersHandler(UserManager *userManager, QObject *parent):
|
||||
QString description;
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Create a new user in the API with the given username and password. Use scopes to define the permissions for the new user. If no scopes are given, this user will be an admin user. Call Authenticate after this to obtain a device token for this user.";
|
||||
description = "Create a new user in the API with the given username and password. Use scopes to define the permissions for the new user. If the user has not the permission \"PermissionScopeAccessAllThings\", the list of things this user has access to can be defined in the \"allowedThingIds\" property. If no scopes are given, this user will be an admin user. Call Authenticate after this to obtain a device token for this user.";
|
||||
params.insert("username", enumValueName(String));
|
||||
params.insert("password", enumValueName(String));
|
||||
params.insert("o:email", enumValueName(String));
|
||||
params.insert("o:displayName", enumValueName(String));
|
||||
params.insert("o:scopes", flagRef<Types::PermissionScopes>());
|
||||
params.insert("o:allowedThingIds", QVariantList() << enumValueName(Uuid));
|
||||
returns.insert("error", enumRef<UserManager::UserError>());
|
||||
registerMethod("CreateUser", description, params, returns);
|
||||
|
||||
@ -87,9 +88,10 @@ UsersHandler::UsersHandler(UserManager *userManager, QObject *parent):
|
||||
registerMethod("RemoveUser", description, params, returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Set the permissions (scopes) for a given user.";
|
||||
description = "Set the permissions (scopes) for a given user. If the user has not the permission \"PermissionScopeAccessAllThings\" the list of thing IDs this user has access to can be defined in the \"allowedThingIds\" property.";
|
||||
params.insert("username", enumValueName(String));
|
||||
params.insert("scopes", flagRef<Types::PermissionScopes>());
|
||||
params.insert("o:allowedThingIds", QVariantList() << enumValueName(Uuid));
|
||||
returns.insert("error", enumRef<UserManager::UserError>());
|
||||
registerMethod("SetUserScopes", description, params, returns);
|
||||
|
||||
|
||||
@ -79,6 +79,16 @@ void UserInfo::setScopes(Types::PermissionScopes scopes)
|
||||
m_scopes = scopes;
|
||||
}
|
||||
|
||||
void UserInfo::setAllowedThingIds(const QList<ThingId> &allowedThingIds)
|
||||
{
|
||||
m_allowedThingIds = allowedThingIds;
|
||||
}
|
||||
|
||||
QList<ThingId> UserInfo::allowedThingIds() const
|
||||
{
|
||||
return m_allowedThingIds;
|
||||
}
|
||||
|
||||
QVariant UserInfoList::get(int index) const
|
||||
{
|
||||
return QVariant::fromValue(at(index));
|
||||
|
||||
@ -56,11 +56,16 @@ public:
|
||||
Types::PermissionScopes scopes() const;
|
||||
void setScopes(Types::PermissionScopes scopes);
|
||||
|
||||
void setAllowedThingIds(const QList<ThingId> &allowedThingIds);
|
||||
QList<ThingId> allowedThingIds() const;
|
||||
|
||||
private:
|
||||
QString m_username;
|
||||
QString m_email;
|
||||
QString m_displayName;
|
||||
Types::PermissionScopes m_scopes = Types::PermissionScopeNone;
|
||||
QList<ThingId> m_allowedThingIds;
|
||||
|
||||
};
|
||||
|
||||
class UserInfoList: public QList<UserInfo>
|
||||
|
||||
@ -539,6 +539,18 @@ bool UserManager::verifyToken(const QByteArray &token)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UserManager::restrictedThingAccess(const QByteArray &token) const
|
||||
{
|
||||
UserInfo ui = userInfo(tokenInfo(token).username());
|
||||
return !ui.scopes().testFlag(Types::PermissionScopeAccessAllThings);
|
||||
}
|
||||
|
||||
QList<ThingId> UserManager::allowedThingIds(const QByteArray &token) const
|
||||
{
|
||||
UserInfo ui = userInfo(tokenInfo(token).username());
|
||||
return ui.allowedThingIds();
|
||||
}
|
||||
|
||||
bool UserManager::initDB()
|
||||
{
|
||||
m_db.close();
|
||||
|
||||
@ -74,9 +74,11 @@ public:
|
||||
|
||||
UserError removeToken(const QUuid &tokenId);
|
||||
|
||||
|
||||
bool verifyToken(const QByteArray &token);
|
||||
|
||||
bool restrictedThingAccess(const QByteArray &token) const;
|
||||
QList<ThingId> allowedThingIds(const QByteArray &token) const;
|
||||
|
||||
signals:
|
||||
void userAdded(const QString &username);
|
||||
void userRemoved(const QString &username);
|
||||
@ -102,7 +104,9 @@ private:
|
||||
QPair<int, QString> m_pushButtonTransaction;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(nymeaserver::UserManager::UserError)
|
||||
|
||||
#endif // USERMANAGER_H
|
||||
|
||||
@ -87,7 +87,7 @@ public:
|
||||
ThingErrorItemNotFound,
|
||||
ThingErrorItemNotExecutable,
|
||||
ThingErrorUnsupportedFeature,
|
||||
ThingErrorTimeout,
|
||||
ThingErrorTimeout
|
||||
};
|
||||
Q_ENUM(ThingError)
|
||||
|
||||
|
||||
@ -202,6 +202,7 @@ public:
|
||||
PermissionScopeNone = 0x0000,
|
||||
PermissionScopeControlThings = 0x0001,
|
||||
PermissionScopeConfigureThings = 0x0003,
|
||||
PermissionScopeAccessAllThings = 0x0004,
|
||||
PermissionScopeExecuteRules = 0x0010,
|
||||
PermissionScopeConfigureRules = 0x0030,
|
||||
PermissionScopeAdmin = 0xFFFF,
|
||||
|
||||
Reference in New Issue
Block a user