Add initial test for thing based authentication
This commit is contained in:
parent
71cd3561b6
commit
f77d94ef7b
@ -131,12 +131,12 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
description = "Add a new thing to the system. "
|
description = "Add a new thing to the system. "
|
||||||
"Only things with a setupMethod of SetupMethodJustAdd can be added this way. "
|
"Only things with a setupMethod of SetupMethodJustAdd can be added this way. "
|
||||||
"For things with a setupMethod different than SetupMethodJustAdd, use PairThing. "
|
"For things with a setupMethod different than SetupMethodJustAdd, use PairThing. "
|
||||||
"Things with CreateMethodJustAdd require all parameters to be supplied here. "
|
"Things with CreateMethodJustAdd require all parameters to be supplied here. "
|
||||||
"Things with CreateMethodDiscovery require the use of a thingDescriptorId. For discovered "
|
"Things with CreateMethodDiscovery require the use of a thingDescriptorId. For discovered "
|
||||||
"things, params are not required and will be taken from the ThingDescriptor, however, they "
|
"things, params are not required and will be taken from the ThingDescriptor, however, they "
|
||||||
"may be overridden by supplying thingParams.";
|
"may be overridden by supplying thingParams.";
|
||||||
params.insert("o:thingClassId", enumValueName(Uuid));
|
params.insert("o:thingClassId", enumValueName(Uuid));
|
||||||
params.insert("name", enumValueName(String));
|
params.insert("name", enumValueName(String));
|
||||||
params.insert("o:thingDescriptorId", enumValueName(Uuid));
|
params.insert("o:thingDescriptorId", enumValueName(Uuid));
|
||||||
@ -148,23 +148,23 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
description = "Pair a new thing. "
|
description = "Pair a new thing. "
|
||||||
"Use this to set up or reconfigure things for ThingClasses with a setupMethod different than SetupMethodJustAdd. "
|
"Use this to set up or reconfigure things for ThingClasses with a setupMethod different than SetupMethodJustAdd. "
|
||||||
"Depending on the CreateMethod and whether a new thing is set up or an existing one is reconfigured, different parameters "
|
"Depending on the CreateMethod and whether a new thing is set up or an existing one is reconfigured, different parameters "
|
||||||
"are required:\n"
|
"are required:\n"
|
||||||
"CreateMethodJustAdd takes the thingClassId and the parameters you want to have with that thing. "
|
"CreateMethodJustAdd takes the thingClassId and the parameters you want to have with that thing. "
|
||||||
"If an existing thing should be reconfigured, the thingId of said thing should be given additionally.\n"
|
"If an existing thing should be reconfigured, the thingId of said thing should be given additionally.\n"
|
||||||
"CreateMethodDiscovery requires the use of a thingDescriptorId, previously obtained with DiscoverThings. Optionally, "
|
"CreateMethodDiscovery requires the use of a thingDescriptorId, previously obtained with DiscoverThings. Optionally, "
|
||||||
"parameters can be overridden with the give thingParams. ThingDescriptors containing a thingId will reconfigure an "
|
"parameters can be overridden with the give thingParams. ThingDescriptors containing a thingId will reconfigure an "
|
||||||
"existing thing, descriptors without a thingId will add a new thing to the system.\n"
|
"existing thing, descriptors without a thingId will add a new thing to the system.\n"
|
||||||
"If success is true, the return values will contain a pairingTransactionId, a displayMessage and "
|
"If success is true, the return values will contain a pairingTransactionId, a displayMessage and "
|
||||||
"the setupMethod. Depending on the setupMethod, the application should present the use an appropriate login mask, "
|
"the setupMethod. Depending on the setupMethod, the application should present the use an appropriate login mask, "
|
||||||
"that is, For SetupMethodDisplayPin the user should enter a pin that is displayed on the device or online service, for SetupMethodEnterPin the "
|
"that is, For SetupMethodDisplayPin the user should enter a pin that is displayed on the device or online service, for SetupMethodEnterPin the "
|
||||||
"application should present the given PIN so the user can enter it on the device or online service. For SetupMethodPushButton, the displayMessage "
|
"application should present the given PIN so the user can enter it on the device or online service. For SetupMethodPushButton, the displayMessage "
|
||||||
"shall be presented to the user as informational hints to press a button on the device. For SetupMethodUserAndPassword a login "
|
"shall be presented to the user as informational hints to press a button on the device. For SetupMethodUserAndPassword a login "
|
||||||
"mask for a user and password login should be presented to the user. In case of SetupMethodOAuth, an OAuth URL will be returned "
|
"mask for a user and password login should be presented to the user. In case of SetupMethodOAuth, an OAuth URL will be returned "
|
||||||
"which shall be opened in a web view to allow the user logging in.\n"
|
"which shall be opened in a web view to allow the user logging in.\n"
|
||||||
"Once the login procedure has completed, the application shall proceed with ConfirmPairing, providing the results of the pairing "
|
"Once the login procedure has completed, the application shall proceed with ConfirmPairing, providing the results of the pairing "
|
||||||
"procedure.";
|
"procedure.";
|
||||||
params.insert("o:thingClassId", enumValueName(Uuid));
|
params.insert("o:thingClassId", enumValueName(Uuid));
|
||||||
params.insert("o:name", enumValueName(String));
|
params.insert("o:name", enumValueName(String));
|
||||||
params.insert("o:thingDescriptorId", enumValueName(Uuid));
|
params.insert("o:thingDescriptorId", enumValueName(Uuid));
|
||||||
@ -180,9 +180,9 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
description = "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field "
|
description = "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field "
|
||||||
"and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" "
|
"and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" "
|
||||||
"field. In case of SetupMethodOAuth, the previously opened web view will eventually be redirected to http://128.0.0.1:8888 "
|
"field. In case of SetupMethodOAuth, the previously opened web view will eventually be redirected to http://128.0.0.1:8888 "
|
||||||
"and the OAuth code as query parameters to this url. Provide the entire unmodified URL in the secret field.";
|
"and the OAuth code as query parameters to this url. Provide the entire unmodified URL in the secret field.";
|
||||||
params.insert("pairingTransactionId", enumValueName(Uuid));
|
params.insert("pairingTransactionId", enumValueName(Uuid));
|
||||||
params.insert("o:username", enumValueName(String));
|
params.insert("o:username", enumValueName(String));
|
||||||
params.insert("o:secret", enumValueName(String));
|
params.insert("o:secret", enumValueName(String));
|
||||||
@ -200,10 +200,10 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
description = "Performs a thing discovery for things of the given thingClassId and returns the results. "
|
description = "Performs a thing discovery for things of the given thingClassId and returns the results. "
|
||||||
"This function may take a while to return. Note that this method will include all the found "
|
"This function may take a while to return. Note that this method will include all the found "
|
||||||
"things, that is, including things that may already have been added. Those things will have "
|
"things, that is, including things that may already have been added. Those things will have "
|
||||||
"thingId set to the id of the already added thing. Such results may be used to reconfigure "
|
"thingId set to the id of the already added thing. Such results may be used to reconfigure "
|
||||||
"existing things and might be filtered in cases where only unknown things are of interest.";
|
"existing things and might be filtered in cases where only unknown things are of interest.";
|
||||||
params.insert("thingClassId", enumValueName(Uuid));
|
params.insert("thingClassId", enumValueName(Uuid));
|
||||||
params.insert("o:discoveryParams", objectRef<ParamList>());
|
params.insert("o:discoveryParams", objectRef<ParamList>());
|
||||||
returns.insert("thingError", enumRef<Thing::ThingError>());
|
returns.insert("thingError", enumRef<Thing::ThingError>());
|
||||||
@ -314,26 +314,26 @@ IntegrationsHandler::IntegrationsHandler(ThingManager *thingManager, QObject *pa
|
|||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
description = "Browse a thing. "
|
description = "Browse a thing. "
|
||||||
"If a ThingClass indicates a thing is browsable, this method will return the BrowserItems. If no "
|
"If a ThingClass indicates a thing is browsable, this method will return the BrowserItems. If no "
|
||||||
"parameter besides the thingId is used, the root node of this thingwill be returned. Any "
|
"parameter besides the thingId is used, the root node of this thingwill be returned. Any "
|
||||||
"returned item which is browsable can be passed as node. Results will be children of the given node.\n"
|
"returned item which is browsable can be passed as node. Results will be children of the given node.\n"
|
||||||
"In case of an error during browsing, the error will be indicated and the displayMessage may contain "
|
"In case of an error during browsing, the error will be indicated and the displayMessage may contain "
|
||||||
"additional information for the user. The displayMessage will be translated. A client UI showing this "
|
"additional information for the user. The displayMessage will be translated. A client UI showing this "
|
||||||
"message to the user should be prepared for empty, but also longer strings.";
|
"message to the user should be prepared for empty, but also longer strings.";
|
||||||
params.insert("thingId", enumValueName(Uuid));
|
params.insert("thingId", enumValueName(Uuid));
|
||||||
params.insert("o:itemId", enumValueName(String));
|
params.insert("o:itemId", enumValueName(String));
|
||||||
returns.insert("thingError", enumRef<Thing::ThingError>());
|
returns.insert("thingError", enumRef<Thing::ThingError>());
|
||||||
returns.insert("o:displayMessage", enumValueName(String));
|
returns.insert("o:displayMessage", enumValueName(String));
|
||||||
returns.insert("items", QVariantList() << objectRef("BrowserItem"));
|
returns.insert("o:items", QVariantList() << objectRef("BrowserItem"));
|
||||||
registerMethod("BrowseThing", description, params, returns, Types::PermissionScopeNone);
|
registerMethod("BrowseThing", description, params, returns, Types::PermissionScopeNone);
|
||||||
|
|
||||||
params.clear(); returns.clear();
|
params.clear(); returns.clear();
|
||||||
description = "Get a single item from the browser. "
|
description = "Get a single item from the browser. "
|
||||||
"This won't give any more info on an item than a regular BrowseThing call, but it allows to fetch "
|
"This won't give any more info on an item than a regular BrowseThing call, but it allows to fetch "
|
||||||
"details of an item if only the ID is known.\n"
|
"details of an item if only the ID is known.\n"
|
||||||
"In case of an error during browsing, the error will be indicated and the displayMessage may contain "
|
"In case of an error during browsing, the error will be indicated and the displayMessage may contain "
|
||||||
"additional information for the user. The displayMessage will be translated. A client UI showing this "
|
"additional information for the user. The displayMessage will be translated. A client UI showing this "
|
||||||
"message to the user should be prepared for empty, but also longer strings.";
|
"message to the user should be prepared for empty, but also longer strings.";
|
||||||
params.insert("thingId", enumValueName(Uuid));
|
params.insert("thingId", enumValueName(Uuid));
|
||||||
params.insert("o:itemId", enumValueName(String));
|
params.insert("o:itemId", enumValueName(String));
|
||||||
returns.insert("thingError", enumRef<Thing::ThingError>());
|
returns.insert("thingError", enumRef<Thing::ThingError>());
|
||||||
@ -530,7 +530,7 @@ QHash<QString, QString> IntegrationsHandler::cacheHashes() const
|
|||||||
return m_cacheHashes;
|
return m_cacheHashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetVendors(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetVendors(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(params)
|
Q_UNUSED(params)
|
||||||
QVariantList vendors;
|
QVariantList vendors;
|
||||||
@ -544,7 +544,7 @@ JsonReply* IntegrationsHandler::GetVendors(const QVariantMap ¶ms, const Json
|
|||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetThingClasses(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetThingClasses(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
QVariantList thingClasses;
|
QVariantList thingClasses;
|
||||||
@ -603,13 +603,13 @@ JsonReply *IntegrationsHandler::DiscoverThings(const QVariantMap ¶ms, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
reply->setData(returns);
|
reply->setData(returns);
|
||||||
reply->finished();
|
emit reply->finished();
|
||||||
|
|
||||||
});
|
});
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetPlugins(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetPlugins(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(params)
|
Q_UNUSED(params)
|
||||||
QVariantList plugins;
|
QVariantList plugins;
|
||||||
@ -643,7 +643,7 @@ JsonReply *IntegrationsHandler::GetPluginConfiguration(const QVariantMap ¶ms
|
|||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::SetPluginConfiguration(const QVariantMap ¶ms)
|
JsonReply *IntegrationsHandler::SetPluginConfiguration(const QVariantMap ¶ms)
|
||||||
{
|
{
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
PluginId pluginId = PluginId(params.value("pluginId").toString());
|
PluginId pluginId = PluginId(params.value("pluginId").toString());
|
||||||
@ -653,7 +653,7 @@ JsonReply* IntegrationsHandler::SetPluginConfiguration(const QVariantMap ¶ms
|
|||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::AddThing(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::AddThing(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingClassId thingClassId(params.value("thingClassId").toString());
|
ThingClassId thingClassId(params.value("thingClassId").toString());
|
||||||
QString thingName = params.value("name").toString();
|
QString thingName = params.value("name").toString();
|
||||||
@ -670,7 +670,7 @@ JsonReply* IntegrationsHandler::AddThing(const QVariantMap ¶ms, const JsonCo
|
|||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
returns.insert("thingError", enumValueName<Thing::ThingError>(Thing::ThingErrorMissingParameter));
|
returns.insert("thingError", enumValueName<Thing::ThingError>(Thing::ThingErrorMissingParameter));
|
||||||
jsonReply->setData(returns);
|
jsonReply->setData(returns);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
}
|
}
|
||||||
info = m_thingManager->addConfiguredThing(thingClassId, thingParams, thingName);
|
info = m_thingManager->addConfiguredThing(thingClassId, thingParams, thingName);
|
||||||
@ -690,7 +690,7 @@ JsonReply* IntegrationsHandler::AddThing(const QVariantMap ¶ms, const JsonCo
|
|||||||
returns.insert("thingId", info->thing()->id());
|
returns.insert("thingId", info->thing()->id());
|
||||||
}
|
}
|
||||||
jsonReply->setData(returns);
|
jsonReply->setData(returns);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
|
|
||||||
});
|
});
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
@ -735,7 +735,7 @@ JsonReply *IntegrationsHandler::PairThing(const QVariantMap ¶ms, const JsonC
|
|||||||
}
|
}
|
||||||
|
|
||||||
jsonReply->setData(returns);
|
jsonReply->setData(returns);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
@ -762,20 +762,20 @@ JsonReply *IntegrationsHandler::ConfirmPairing(const QVariantMap ¶ms)
|
|||||||
returns.insert("thingId", info->thingId().toString());
|
returns.insert("thingId", info->thingId().toString());
|
||||||
}
|
}
|
||||||
jsonReply->setData(returns);
|
jsonReply->setData(returns);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetThings(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetThings(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
QVariantList things;
|
QVariantList things;
|
||||||
|
|
||||||
|
if (NymeaCore::instance()->userManager()->hasRestrictedThingAccess(context.token())) {
|
||||||
if (NymeaCore::instance()->userManager()->restrictedThingAccess(context.token())) {
|
// Restricted things access
|
||||||
QList<ThingId> allowedThingIds = NymeaCore::instance()->userManager()->allowedThingIds(context.token());
|
QList<ThingId> allowedThingIds = NymeaCore::instance()->userManager()->getAllowedThingIdsForToken(context.token());
|
||||||
if (params.contains("thingId")) {
|
if (params.contains("thingId")) {
|
||||||
ThingId thingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
||||||
@ -795,7 +795,6 @@ JsonReply* IntegrationsHandler::GetThings(const QVariantMap ¶ms, const JsonC
|
|||||||
if (!allowedThingIds.contains(thing->id()))
|
if (!allowedThingIds.contains(thing->id()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
QVariantMap packedThing = pack(thing).toMap();
|
QVariantMap packedThing = pack(thing).toMap();
|
||||||
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
QString translatedSetupStatus = m_thingManager->translate(thing->pluginId(), thing->setupDisplayMessage(), context.locale());
|
||||||
if (!translatedSetupStatus.isEmpty()) {
|
if (!translatedSetupStatus.isEmpty()) {
|
||||||
@ -858,13 +857,11 @@ JsonReply *IntegrationsHandler::ReconfigureThing(const QVariantMap ¶ms, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect(info, &ThingSetupInfo::finished, jsonReply, [info, jsonReply, locale](){
|
connect(info, &ThingSetupInfo::finished, jsonReply, [info, jsonReply, locale](){
|
||||||
|
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
returns.insert("thingError", enumValueName<Thing::ThingError>(info->status()));
|
returns.insert("thingError", enumValueName<Thing::ThingError>(info->status()));
|
||||||
returns.insert("displayMessage", info->translatedDisplayMessage(locale));
|
returns.insert("displayMessage", info->translatedDisplayMessage(locale));
|
||||||
jsonReply->setData(returns);
|
jsonReply->setData(returns);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
@ -882,7 +879,7 @@ JsonReply *IntegrationsHandler::EditThing(const QVariantMap ¶ms)
|
|||||||
return createReply(statusToReply(status));
|
return createReply(statusToReply(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::RemoveThing(const QVariantMap ¶ms)
|
JsonReply *IntegrationsHandler::RemoveThing(const QVariantMap ¶ms)
|
||||||
{
|
{
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
ThingId thingId = ThingId(params.value("thingId").toString());
|
||||||
@ -937,7 +934,7 @@ JsonReply *IntegrationsHandler::SetStateFilter(const QVariantMap ¶ms)
|
|||||||
return createReply(statusToReply(status));
|
return createReply(statusToReply(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingClass thingClass = m_thingManager->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
ThingClass thingClass = m_thingManager->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
||||||
ThingClass translatedThingClass = m_thingManager->translateThingClass(thingClass, context.locale());
|
ThingClass translatedThingClass = m_thingManager->translateThingClass(thingClass, context.locale());
|
||||||
@ -947,7 +944,7 @@ JsonReply* IntegrationsHandler::GetEventTypes(const QVariantMap ¶ms, const J
|
|||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetActionTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetActionTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingClass thingClass = m_thingManager->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
ThingClass thingClass = m_thingManager->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
||||||
ThingClass translatedThingClass = m_thingManager->translateThingClass(thingClass, context.locale());
|
ThingClass translatedThingClass = m_thingManager->translateThingClass(thingClass, context.locale());
|
||||||
@ -957,7 +954,7 @@ JsonReply* IntegrationsHandler::GetActionTypes(const QVariantMap ¶ms, const
|
|||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetStateTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetStateTypes(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingClass thingClass = m_thingManager->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
ThingClass thingClass = m_thingManager->findThingClass(ThingClassId(params.value("thingClassId").toString()));
|
||||||
ThingClass translatedThingClass = m_thingManager->translateThingClass(thingClass, context.locale());
|
ThingClass translatedThingClass = m_thingManager->translateThingClass(thingClass, context.locale());
|
||||||
@ -967,28 +964,34 @@ JsonReply* IntegrationsHandler::GetStateTypes(const QVariantMap ¶ms, const J
|
|||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply* IntegrationsHandler::GetStateValue(const QVariantMap ¶ms) const
|
JsonReply *IntegrationsHandler::GetStateValue(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
Thing *thing = m_thingManager->findConfiguredThing(ThingId(params.value("thingId").toString()));
|
ThingId thingId(params.value("thingId").toString());
|
||||||
if (!thing) {
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
}
|
|
||||||
|
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
||||||
|
if (!thing)
|
||||||
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
StateTypeId stateTypeId = StateTypeId(params.value("stateTypeId").toString());
|
StateTypeId stateTypeId = StateTypeId(params.value("stateTypeId").toString());
|
||||||
if (!thing->hasState(stateTypeId)) {
|
if (!thing->hasState(stateTypeId))
|
||||||
return createReply(statusToReply(Thing::ThingErrorStateTypeNotFound));
|
return createReply(statusToReply(Thing::ThingErrorStateTypeNotFound));
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap returns = statusToReply(Thing::ThingErrorNoError);
|
QVariantMap returns = statusToReply(Thing::ThingErrorNoError);
|
||||||
returns.insert("value", thing->state(stateTypeId).value());
|
returns.insert("value", thing->state(stateTypeId).value());
|
||||||
return createReply(returns);
|
return createReply(returns);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply *IntegrationsHandler::GetStateValues(const QVariantMap ¶ms) const
|
JsonReply *IntegrationsHandler::GetStateValues(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
Thing *thing = m_thingManager->findConfiguredThing(ThingId(params.value("thingId").toString()));
|
ThingId thingId(params.value("thingId").toString());
|
||||||
if (!thing) {
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
|
Thing *thing = m_thingManager->findConfiguredThing(thingId);
|
||||||
|
if (!thing)
|
||||||
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap returns = statusToReply(Thing::ThingErrorNoError);
|
QVariantMap returns = statusToReply(Thing::ThingErrorNoError);
|
||||||
returns.insert("values", pack(thing->states()));
|
returns.insert("values", pack(thing->states()));
|
||||||
@ -997,7 +1000,10 @@ JsonReply *IntegrationsHandler::GetStateValues(const QVariantMap ¶ms) const
|
|||||||
|
|
||||||
JsonReply *IntegrationsHandler::BrowseThing(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::BrowseThing(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
QString itemId = params.value("itemId").toString();
|
QString itemId = params.value("itemId").toString();
|
||||||
|
|
||||||
JsonReply *jsonReply = createAsyncReply("BrowseThing");
|
JsonReply *jsonReply = createAsyncReply("BrowseThing");
|
||||||
@ -1007,15 +1013,16 @@ JsonReply *IntegrationsHandler::BrowseThing(const QVariantMap ¶ms, const Jso
|
|||||||
|
|
||||||
QVariantMap returns = statusToReply(result->status());
|
QVariantMap returns = statusToReply(result->status());
|
||||||
QVariantList list;
|
QVariantList list;
|
||||||
foreach (const BrowserItem &item, result->items()) {
|
foreach (const BrowserItem &item, result->items())
|
||||||
list.append(packBrowserItem(item));
|
list.append(packBrowserItem(item));
|
||||||
}
|
|
||||||
returns.insert("items", list);
|
returns.insert("items", list);
|
||||||
if (!result->displayMessage().isEmpty()) {
|
|
||||||
|
if (!result->displayMessage().isEmpty())
|
||||||
returns.insert("displayMessage", result->translatedDisplayMessage(context.locale()));
|
returns.insert("displayMessage", result->translatedDisplayMessage(context.locale()));
|
||||||
}
|
|
||||||
jsonReply->setData(returns);
|
jsonReply->setData(returns);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
@ -1023,10 +1030,11 @@ JsonReply *IntegrationsHandler::BrowseThing(const QVariantMap ¶ms, const Jso
|
|||||||
|
|
||||||
JsonReply *IntegrationsHandler::GetBrowserItem(const QVariantMap ¶ms, const JsonContext &context) const
|
JsonReply *IntegrationsHandler::GetBrowserItem(const QVariantMap ¶ms, const JsonContext &context) const
|
||||||
{
|
{
|
||||||
QVariantMap returns;
|
ThingId thingId(params.value("thingId").toString());
|
||||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
QString itemId = params.value("itemId").toString();
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
|
QString itemId = params.value("itemId").toString();
|
||||||
JsonReply *jsonReply = createAsyncReply("GetBrowserItem");
|
JsonReply *jsonReply = createAsyncReply("GetBrowserItem");
|
||||||
|
|
||||||
BrowserItemResult *result = m_thingManager->browserItemDetails(thingId, itemId, context.locale());
|
BrowserItemResult *result = m_thingManager->browserItemDetails(thingId, itemId, context.locale());
|
||||||
@ -1039,7 +1047,7 @@ JsonReply *IntegrationsHandler::GetBrowserItem(const QVariantMap ¶ms, const
|
|||||||
params.insert("displayMessage", result->translatedDisplayMessage(context.locale()));
|
params.insert("displayMessage", result->translatedDisplayMessage(context.locale()));
|
||||||
}
|
}
|
||||||
jsonReply->setData(params);
|
jsonReply->setData(params);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
@ -1048,6 +1056,9 @@ JsonReply *IntegrationsHandler::GetBrowserItem(const QVariantMap ¶ms, const
|
|||||||
JsonReply *IntegrationsHandler::ExecuteAction(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::ExecuteAction(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId(params.value("thingId").toString());
|
ThingId thingId(params.value("thingId").toString());
|
||||||
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
ActionTypeId actionTypeId(params.value("actionTypeId").toString());
|
ActionTypeId actionTypeId(params.value("actionTypeId").toString());
|
||||||
ParamList actionParams = unpack<ParamList>(params.value("params"));
|
ParamList actionParams = unpack<ParamList>(params.value("params"));
|
||||||
QLocale locale = context.locale();
|
QLocale locale = context.locale();
|
||||||
@ -1065,7 +1076,7 @@ JsonReply *IntegrationsHandler::ExecuteAction(const QVariantMap ¶ms, const J
|
|||||||
data.insert("displayMessage", info->translatedDisplayMessage(locale));
|
data.insert("displayMessage", info->translatedDisplayMessage(locale));
|
||||||
}
|
}
|
||||||
jsonReply->setData(data);
|
jsonReply->setData(data);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
@ -1074,6 +1085,9 @@ JsonReply *IntegrationsHandler::ExecuteAction(const QVariantMap ¶ms, const J
|
|||||||
JsonReply *IntegrationsHandler::ExecuteBrowserItem(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::ExecuteBrowserItem(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
ThingId thingId = ThingId(params.value("thingId").toString());
|
||||||
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
QString itemId = params.value("itemId").toString();
|
QString itemId = params.value("itemId").toString();
|
||||||
BrowserAction action(thingId, itemId);
|
BrowserAction action(thingId, itemId);
|
||||||
|
|
||||||
@ -1087,7 +1101,7 @@ JsonReply *IntegrationsHandler::ExecuteBrowserItem(const QVariantMap ¶ms, co
|
|||||||
data.insert("displayMessage", info->translatedDisplayMessage(context.locale()));
|
data.insert("displayMessage", info->translatedDisplayMessage(context.locale()));
|
||||||
}
|
}
|
||||||
jsonReply->setData(data);
|
jsonReply->setData(data);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
@ -1096,6 +1110,9 @@ JsonReply *IntegrationsHandler::ExecuteBrowserItem(const QVariantMap ¶ms, co
|
|||||||
JsonReply *IntegrationsHandler::ExecuteBrowserItemAction(const QVariantMap ¶ms, const JsonContext &context)
|
JsonReply *IntegrationsHandler::ExecuteBrowserItemAction(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId = ThingId(params.value("thingId").toString());
|
ThingId thingId = ThingId(params.value("thingId").toString());
|
||||||
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
QString itemId = params.value("itemId").toString();
|
QString itemId = params.value("itemId").toString();
|
||||||
ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString());
|
ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString());
|
||||||
ParamList paramList = unpack<ParamList>(params.value("params"));
|
ParamList paramList = unpack<ParamList>(params.value("params"));
|
||||||
@ -1111,15 +1128,18 @@ JsonReply *IntegrationsHandler::ExecuteBrowserItemAction(const QVariantMap ¶
|
|||||||
data.insert("displayMessage", info->translatedDisplayMessage(context.locale()));
|
data.insert("displayMessage", info->translatedDisplayMessage(context.locale()));
|
||||||
}
|
}
|
||||||
jsonReply->setData(data);
|
jsonReply->setData(data);
|
||||||
jsonReply->finished();
|
emit jsonReply->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
return jsonReply;
|
return jsonReply;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonReply *IntegrationsHandler::GetIOConnections(const QVariantMap ¶ms)
|
JsonReply *IntegrationsHandler::GetIOConnections(const QVariantMap ¶ms, const JsonContext &context)
|
||||||
{
|
{
|
||||||
ThingId thingId = params.value("thingId").toUuid();
|
ThingId thingId = params.value("thingId").toUuid();
|
||||||
|
if (!NymeaCore::instance()->userManager()->accessToThingGranted(thingId, context.token()))
|
||||||
|
return createReply(statusToReply(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
IOConnections ioConnections = m_thingManager->ioConnections(thingId);
|
IOConnections ioConnections = m_thingManager->ioConnections(thingId);
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
QVariant bla = pack(ioConnections);
|
QVariant bla = pack(ioConnections);
|
||||||
|
|||||||
@ -61,8 +61,9 @@ public:
|
|||||||
Q_INVOKABLE JsonReply *GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
Q_INVOKABLE JsonReply *GetEventTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
Q_INVOKABLE JsonReply *GetActionTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
Q_INVOKABLE JsonReply *GetActionTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
Q_INVOKABLE JsonReply *GetStateTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
Q_INVOKABLE JsonReply *GetStateTypes(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
Q_INVOKABLE JsonReply *GetStateValue(const QVariantMap ¶ms) const;
|
|
||||||
Q_INVOKABLE JsonReply *GetStateValues(const QVariantMap ¶ms) const;
|
Q_INVOKABLE JsonReply *GetStateValue(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
|
Q_INVOKABLE JsonReply *GetStateValues(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
|
|
||||||
Q_INVOKABLE JsonReply *BrowseThing(const QVariantMap ¶ms, const JsonContext &context) const;
|
Q_INVOKABLE JsonReply *BrowseThing(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap ¶ms, const JsonContext &context) const;
|
Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||||
@ -71,7 +72,7 @@ public:
|
|||||||
Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap ¶ms, const JsonContext &context);
|
Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap ¶ms, const JsonContext &context);
|
||||||
Q_INVOKABLE JsonReply *ExecuteBrowserItemAction(const QVariantMap ¶ms, const JsonContext &context);
|
Q_INVOKABLE JsonReply *ExecuteBrowserItemAction(const QVariantMap ¶ms, const JsonContext &context);
|
||||||
|
|
||||||
Q_INVOKABLE JsonReply *GetIOConnections(const QVariantMap ¶ms);
|
Q_INVOKABLE JsonReply *GetIOConnections(const QVariantMap ¶ms, const JsonContext &context);
|
||||||
Q_INVOKABLE JsonReply *ConnectIO(const QVariantMap ¶ms);
|
Q_INVOKABLE JsonReply *ConnectIO(const QVariantMap ¶ms);
|
||||||
Q_INVOKABLE JsonReply *DisconnectIO(const QVariantMap ¶ms);
|
Q_INVOKABLE JsonReply *DisconnectIO(const QVariantMap ¶ms);
|
||||||
|
|
||||||
|
|||||||
@ -656,7 +656,7 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!handler->jsonMethods().contains(method)) {
|
if (!handler->jsonMethods().contains(method)) {
|
||||||
qCWarning(dcJsonRpc()) << QString("JSON RPC method called for invalid method: %1.%2").arg(targetNamespace).arg(method);
|
qCWarning(dcJsonRpc()) << QString("JSON RPC method called for invalid method: %1.%2").arg(targetNamespace, method);
|
||||||
sendErrorResponse(interface, clientId, commandId, "No such method");
|
sendErrorResponse(interface, clientId, commandId, "No such method");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -195,14 +195,16 @@ UserManager::UserError UserManager::createUser(const QString &username, const QS
|
|||||||
QByteArray salt = QUuid::createUuid().toString().remove(QRegularExpression("[{}]")).toUtf8();
|
QByteArray salt = QUuid::createUuid().toString().remove(QRegularExpression("[{}]")).toUtf8();
|
||||||
QByteArray hashedPassword = QCryptographicHash::hash(QString(password + salt).toUtf8(), QCryptographicHash::Sha512).toBase64();
|
QByteArray hashedPassword = QCryptographicHash::hash(QString(password + salt).toUtf8(), QCryptographicHash::Sha512).toBase64();
|
||||||
QSqlQuery query(m_db);
|
QSqlQuery query(m_db);
|
||||||
query.prepare("INSERT INTO users(username, email, displayName, password, salt, scopes, allowedThingIds) VALUES(?, ?, ?, ?, ?, ?, ?);");
|
query.prepare("INSERT INTO users(username, email, displayName, password, salt, scopes, allowedThingIds)"
|
||||||
query.addBindValue(username.toLower());
|
"VALUES(:username, :email, :displayName, :password, :salt, :scopes, :allowedThingIds);");
|
||||||
query.addBindValue(email);
|
|
||||||
query.addBindValue(displayName);
|
query.bindValue(":username", username.toLower());
|
||||||
query.addBindValue(QString::fromUtf8(hashedPassword));
|
query.bindValue(":email", email);
|
||||||
query.addBindValue(QString::fromUtf8(salt));
|
query.bindValue(":displayName", displayName);
|
||||||
query.addBindValue(Types::scopesToStringList(scopes).join(','));
|
query.bindValue(":password", QString::fromUtf8(hashedPassword));
|
||||||
query.addBindValue(Types::thingIdsToStringList(thingIds).join(','));
|
query.bindValue(":salt", QString::fromUtf8(salt));
|
||||||
|
query.bindValue(":scopes", Types::scopesToStringList(scopes).join(','));
|
||||||
|
query.bindValue(":allowedThingIds", Types::thingIdsToStringList(thingIds).join(','));
|
||||||
query.exec();
|
query.exec();
|
||||||
if (query.lastError().type() != QSqlError::NoError) {
|
if (query.lastError().type() != QSqlError::NoError) {
|
||||||
qCWarning(dcUserManager) << "Error creating user:" << query.lastError().databaseText() << query.lastError().driverText();
|
qCWarning(dcUserManager) << "Error creating user:" << query.lastError().databaseText() << query.lastError().driverText();
|
||||||
@ -241,14 +243,15 @@ UserManager::UserError UserManager::changePassword(const QString &username, cons
|
|||||||
// Update the password
|
// Update the password
|
||||||
QByteArray salt = QUuid::createUuid().toString().remove(QRegularExpression("[{}]")).toUtf8();
|
QByteArray salt = QUuid::createUuid().toString().remove(QRegularExpression("[{}]")).toUtf8();
|
||||||
QByteArray hashedPassword = QCryptographicHash::hash(QString(newPassword + salt).toUtf8(), QCryptographicHash::Sha512).toBase64();
|
QByteArray hashedPassword = QCryptographicHash::hash(QString(newPassword + salt).toUtf8(), QCryptographicHash::Sha512).toBase64();
|
||||||
QString updatePasswordQueryString = QString("UPDATE users SET password = \"%1\", salt = \"%2\" WHERE lower(username) = \"%3\";")
|
|
||||||
.arg(QString::fromUtf8(hashedPassword))
|
|
||||||
.arg(QString::fromUtf8(salt))
|
|
||||||
.arg(username.toLower());
|
|
||||||
|
|
||||||
QSqlQuery updatePasswordQuery(m_db);
|
QSqlQuery updatePasswordQuery(m_db);
|
||||||
if (!updatePasswordQuery.exec(updatePasswordQueryString)) {
|
updatePasswordQuery.prepare("UPDATE users SET password = :password, salt = :salt WHERE lower(username) = :username;");
|
||||||
qCWarning(dcUserManager()) << "Unable to execute SQL query" << updatePasswordQueryString << m_db.lastError().databaseText() << m_db.lastError().driverText();
|
updatePasswordQuery.bindValue(":password", QString::fromUtf8(hashedPassword));
|
||||||
|
updatePasswordQuery.bindValue(":salt", QString::fromUtf8(salt));
|
||||||
|
updatePasswordQuery.bindValue(":username", username.toLower());
|
||||||
|
|
||||||
|
if (!updatePasswordQuery.exec()) {
|
||||||
|
qCWarning(dcUserManager()) << "Unable to execute SQL query" << updatePasswordQuery.executedQuery() << m_db.lastError().databaseText() << m_db.lastError().driverText();
|
||||||
return UserErrorBackendError;
|
return UserErrorBackendError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +266,7 @@ UserManager::UserError UserManager::changePassword(const QString &username, cons
|
|||||||
|
|
||||||
UserManager::UserError UserManager::removeUser(const QString &username)
|
UserManager::UserError UserManager::removeUser(const QString &username)
|
||||||
{
|
{
|
||||||
QString dropUserQueryString = QString("DELETE FROM users WHERE lower(username) =\"%1\";").arg(username.toLower());
|
QString dropUserQueryString = QString("DELETE FROM users WHERE lower(username) = \"%1\";").arg(username.toLower());
|
||||||
QSqlQuery dropUserQuery(m_db);
|
QSqlQuery dropUserQuery(m_db);
|
||||||
if (!dropUserQuery.exec(dropUserQueryString)) {
|
if (!dropUserQuery.exec(dropUserQueryString)) {
|
||||||
qCWarning(dcUserManager()) << "Unable to execute SQL query" << dropUserQueryString << m_db.lastError().databaseText() << m_db.lastError().driverText();
|
qCWarning(dcUserManager()) << "Unable to execute SQL query" << dropUserQueryString << m_db.lastError().databaseText() << m_db.lastError().driverText();
|
||||||
@ -291,25 +294,27 @@ UserManager::UserError UserManager::setUserScopes(const QString &username, Types
|
|||||||
return UserErrorInconsistantScopes;
|
return UserErrorInconsistantScopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Verify thing IDs, if there is no thing with this id, we don't save it and it will not be verified.
|
// Verify thing IDs, if there is no thing with this id, we don't save it and it will not be verified.
|
||||||
// We don't return an error, the thing might have dissapeared
|
// We don't return an error, the thing might have dissapeared
|
||||||
QList<ThingId> thingIds;
|
QList<ThingId> thingIds;
|
||||||
foreach (const ThingId &thingId, allowedThingIds) {
|
foreach (const ThingId &thingId, allowedThingIds) {
|
||||||
if (NymeaCore::instance()->thingManager()->configuredThings().findById(thingId) == nullptr) {
|
if (NymeaCore::instance()->thingManager()->configuredThings().findById(thingId) == nullptr) {
|
||||||
qCWarning(dcUserManager()) << "Cannot set user scope for" << username << "because there is no thing with ID ";
|
qCWarning(dcUserManager()) << "The user" << username << "should have access to thing with ID" << thingId.toString() << "but there is no such thing. Ignoring value.";
|
||||||
} else {
|
} else {
|
||||||
thingIds.append(thingId);
|
thingIds.append(thingId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString scopesString = Types::scopesToStringList(scopes).join(',');
|
QString scopesString = Types::scopesToStringList(scopes).join(',');
|
||||||
QString allowedThingIdsString = Types::thingIdsToStringList(thingIds).join(',');
|
QString allowedThingIdsString = Types::thingIdsToStringList(thingIds).join(',');
|
||||||
|
|
||||||
|
qCDebug(dcUserManager()) << "Updating scopes of user" << username << "Scopes:" << scopes << "Allowed things:" << allowedThingIds;
|
||||||
QSqlQuery setScopesQuery(m_db);
|
QSqlQuery setScopesQuery(m_db);
|
||||||
setScopesQuery.prepare("UPDATE users SET scopes = :scopes, allowedThingIds = :allowedThingIds WHERE username = :username");
|
setScopesQuery.prepare("UPDATE users SET scopes = :scopes, allowedThingIds = :allowedThingIds WHERE username = :username");
|
||||||
|
setScopesQuery.bindValue(":username", username);
|
||||||
setScopesQuery.bindValue(":scopes", scopesString);
|
setScopesQuery.bindValue(":scopes", scopesString);
|
||||||
setScopesQuery.bindValue(":allowedThingIds", allowedThingIdsString);
|
setScopesQuery.bindValue(":allowedThingIds", allowedThingIdsString);
|
||||||
setScopesQuery.bindValue(":username", username);
|
|
||||||
if (!setScopesQuery.exec()) {
|
if (!setScopesQuery.exec()) {
|
||||||
qCWarning(dcUserManager()) << "Error updating scopes for user" << username << setScopesQuery.lastError().databaseText() << setScopesQuery.lastError().driverText();
|
qCWarning(dcUserManager()) << "Error updating scopes for user" << username << setScopesQuery.lastError().databaseText() << setScopesQuery.lastError().driverText();
|
||||||
return UserErrorBackendError;
|
return UserErrorBackendError;
|
||||||
@ -575,16 +580,23 @@ bool UserManager::verifyToken(const QByteArray &token)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserManager::restrictedThingAccess(const QByteArray &token) const
|
bool UserManager::hasRestrictedThingAccess(const QByteArray &token) const
|
||||||
{
|
{
|
||||||
UserInfo ui = userInfo(tokenInfo(token).username());
|
UserInfo ui = userInfo(tokenInfo(token).username());
|
||||||
return !ui.scopes().testFlag(Types::PermissionScopeAccessAllThings);
|
return !ui.scopes().testFlag(Types::PermissionScopeAccessAllThings);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<ThingId> UserManager::allowedThingIds(const QByteArray &token) const
|
bool UserManager::accessToThingGranted(const ThingId &thingId, const QByteArray &token)
|
||||||
{
|
{
|
||||||
UserInfo ui = userInfo(tokenInfo(token).username());
|
if (!hasRestrictedThingAccess(token))
|
||||||
return ui.allowedThingIds();
|
return true;
|
||||||
|
|
||||||
|
return getAllowedThingIdsForToken(token).contains(thingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ThingId> UserManager::getAllowedThingIdsForToken(const QByteArray &token) const
|
||||||
|
{
|
||||||
|
return userInfo(tokenInfo(token).username()).allowedThingIds();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UserManager::initDB()
|
bool UserManager::initDB()
|
||||||
|
|||||||
@ -77,8 +77,9 @@ public:
|
|||||||
|
|
||||||
bool verifyToken(const QByteArray &token);
|
bool verifyToken(const QByteArray &token);
|
||||||
|
|
||||||
bool restrictedThingAccess(const QByteArray &token) const;
|
bool hasRestrictedThingAccess(const QByteArray &token) const;
|
||||||
QList<ThingId> allowedThingIds(const QByteArray &token) const;
|
bool accessToThingGranted(const ThingId &thingId, const QByteArray &token);
|
||||||
|
QList<ThingId> getAllowedThingIdsForToken(const QByteArray &token) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void userAdded(const QString &username);
|
void userAdded(const QString &username);
|
||||||
|
|||||||
@ -69,7 +69,6 @@ public:
|
|||||||
QVariantMap jsonMethods() const;
|
QVariantMap jsonMethods() const;
|
||||||
QVariantMap jsonNotifications() const;
|
QVariantMap jsonNotifications() const;
|
||||||
|
|
||||||
|
|
||||||
template<typename T> static QString enumRef();
|
template<typename T> static QString enumRef();
|
||||||
template<typename T> static QString flagRef();
|
template<typename T> static QString flagRef();
|
||||||
template<typename T> static QString objectRef();
|
template<typename T> static QString objectRef();
|
||||||
|
|||||||
@ -22,9 +22,7 @@
|
|||||||
*
|
*
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include <QtTest>
|
#include "testusermanager.h"
|
||||||
|
|
||||||
#include "logging/logengine.h"
|
|
||||||
#include "nymeacore.h"
|
#include "nymeacore.h"
|
||||||
#include "nymeatestbase.h"
|
#include "nymeatestbase.h"
|
||||||
#include "usermanager/usermanager.h"
|
#include "usermanager/usermanager.h"
|
||||||
@ -33,83 +31,10 @@
|
|||||||
|
|
||||||
#include "../../utils/pushbuttonagent.h"
|
#include "../../utils/pushbuttonagent.h"
|
||||||
|
|
||||||
|
#include "../plugins/mock/extern-plugininfo.h"
|
||||||
|
|
||||||
using namespace nymeaserver;
|
using namespace nymeaserver;
|
||||||
|
|
||||||
class TestUsermanager: public NymeaTestBase
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
TestUsermanager(QObject* parent = nullptr);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void initTestCase();
|
|
||||||
|
|
||||||
void init();
|
|
||||||
|
|
||||||
void loginValidation_data();
|
|
||||||
void loginValidation();
|
|
||||||
|
|
||||||
void createUser();
|
|
||||||
|
|
||||||
void authenticate();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Cases for push button auth:
|
|
||||||
|
|
||||||
Case 1: regular pushbutton
|
|
||||||
- alice sends Users.RequestPushButtonAuth, gets "OK" back (if push button hardware is available)
|
|
||||||
- alice pushes the hardware button and gets a notification on jsonrpc containing the token for local auth
|
|
||||||
*/
|
|
||||||
void authenticatePushButton();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Case 2: if we have an attacker in the network, he could try to call requestPushButtonAuth and
|
|
||||||
hope someone would eventually press the button and give him a token. In order to prevent this,
|
|
||||||
any previous attempt for a push button auth needs to be cancelled when a new request comes in:
|
|
||||||
|
|
||||||
* Mallory does RequestPushButtonAuth, gets OK back
|
|
||||||
* Alice does RequestPushButtonAuth,
|
|
||||||
* Mallory receives a "PushButtonFailed" notification
|
|
||||||
* Alice receives OK
|
|
||||||
* Alice presses the hardware button
|
|
||||||
* Alice reveices a notification with token, mallory receives nothing
|
|
||||||
|
|
||||||
Case 3: Mallory tries to hijack it back again
|
|
||||||
|
|
||||||
* Mallory does RequestPushButtonAuth, gets OK back
|
|
||||||
* Alice does RequestPusButtonAuth,
|
|
||||||
* Alice gets ok reply, Mallory gets failed notification
|
|
||||||
* Mallory quickly does RequestPushButtonAuth again to win the fight
|
|
||||||
* Alice gets failed notification and can instruct the user to _not_ press the button now until procedure is restarted
|
|
||||||
*/
|
|
||||||
void authenticatePushButtonAuthInterrupt();
|
|
||||||
|
|
||||||
void authenticatePushButtonAuthConnectionDrop();
|
|
||||||
|
|
||||||
void createDuplicateUser();
|
|
||||||
|
|
||||||
void getTokens();
|
|
||||||
|
|
||||||
void removeToken();
|
|
||||||
|
|
||||||
void unauthenticatedCallAfterTokenRemove();
|
|
||||||
|
|
||||||
void changePassword();
|
|
||||||
|
|
||||||
void authenticateAfterPasswordChangeOK();
|
|
||||||
|
|
||||||
void authenticateAfterPasswordChangeFail();
|
|
||||||
|
|
||||||
void getUserInfo();
|
|
||||||
|
|
||||||
void testScopeConsitancy_data();
|
|
||||||
void testScopeConsitancy();
|
|
||||||
|
|
||||||
private:
|
|
||||||
// m_apiToken is in testBase
|
|
||||||
QUuid m_tokenId;
|
|
||||||
};
|
|
||||||
|
|
||||||
TestUsermanager::TestUsermanager(QObject *parent): NymeaTestBase(parent)
|
TestUsermanager::TestUsermanager(QObject *parent): NymeaTestBase(parent)
|
||||||
{
|
{
|
||||||
QCoreApplication::instance()->setOrganizationName("nymea-test");
|
QCoreApplication::instance()->setOrganizationName("nymea-test");
|
||||||
@ -639,5 +564,159 @@ void TestUsermanager::testScopeConsitancy()
|
|||||||
QCOMPARE(response.toMap().value("params").toMap().value("error").toString(), error);
|
QCOMPARE(response.toMap().value("params").toMap().value("error").toString(), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "testusermanager.moc"
|
void TestUsermanager::testRestrictedThingAccess()
|
||||||
|
{
|
||||||
|
// Add 2 mock things
|
||||||
|
ThingId thingIdOne;
|
||||||
|
ThingId thingIdTwo;
|
||||||
|
|
||||||
|
QString usernameAdmin = "admin";
|
||||||
|
QString passwordAdmin = "Bla1234*";
|
||||||
|
|
||||||
|
QString usernameGuest = "guest";
|
||||||
|
QString passwordGuest = "Bla1234+";
|
||||||
|
|
||||||
|
QVariant response;
|
||||||
|
QVariantList thingParams;
|
||||||
|
QVariantMap params;
|
||||||
|
|
||||||
|
injectAndWait("JSONRPC.Hello");
|
||||||
|
|
||||||
|
// Create admin user
|
||||||
|
params.clear();
|
||||||
|
params.insert("username", usernameAdmin);
|
||||||
|
params.insert("password", passwordAdmin);
|
||||||
|
response = injectAndWait("JSONRPC.CreateUser", params);
|
||||||
|
QVERIFY2(response.toMap().value("status").toString() == "success", "Error creating user");
|
||||||
|
QVERIFY2(response.toMap().value("params").toMap().value("error").toString() == "UserErrorNoError", "Error creating user");
|
||||||
|
|
||||||
|
// Authenticate admin user
|
||||||
|
params.clear();
|
||||||
|
params.insert("username", usernameAdmin);
|
||||||
|
params.insert("password", passwordAdmin);
|
||||||
|
params.insert("deviceName", "autotests");
|
||||||
|
response = injectAndWait("JSONRPC.Authenticate", params);
|
||||||
|
QVERIFY2(response.toMap().value("status").toString() == "success", "Error authenticating");
|
||||||
|
QVERIFY2(response.toMap().value("params").toMap().value("success").toString() == "true", "Error authenticating");
|
||||||
|
|
||||||
|
m_adminToken = response.toMap().value("params").toMap().value("token").toByteArray();
|
||||||
|
|
||||||
|
// Use the admin token for now
|
||||||
|
m_apiToken = m_adminToken;
|
||||||
|
|
||||||
|
// Add thing one
|
||||||
|
QVariantMap httpportParamOne;
|
||||||
|
httpportParamOne.insert("paramTypeId", mockThingHttpportParamTypeId.toString());
|
||||||
|
httpportParamOne.insert("value", m_mockThing1Port - 1);
|
||||||
|
thingParams << httpportParamOne;
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.insert("thingClassId", mockThingClassId);
|
||||||
|
params.insert("name", "Test thing available for all users");
|
||||||
|
params.insert("thingParams", thingParams);
|
||||||
|
response = injectAndWait("Integrations.AddThing", params);
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorNoError));
|
||||||
|
thingIdOne = ThingId(response.toMap().value("params").toMap().value("thingId").toString());
|
||||||
|
|
||||||
|
// Add thing two
|
||||||
|
QVariantMap httpportParamTwo;
|
||||||
|
httpportParamOne.insert("paramTypeId", mockThingHttpportParamTypeId.toString());
|
||||||
|
httpportParamOne.insert("value", m_mockThing1Port - 2);
|
||||||
|
thingParams.clear();
|
||||||
|
thingParams << httpportParamOne;
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.insert("thingClassId", mockThingClassId);
|
||||||
|
params.insert("name", "Test thing available for all users");
|
||||||
|
params.insert("thingParams", thingParams);
|
||||||
|
response = injectAndWait("Integrations.AddThing", params);
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorNoError));
|
||||||
|
thingIdTwo = ThingId(response.toMap().value("params").toMap().value("thingId").toString());
|
||||||
|
|
||||||
|
|
||||||
|
// Create guest user
|
||||||
|
QStringList scopes;
|
||||||
|
scopes << "PermissionScopeControlThings";
|
||||||
|
QVariantList allowedThingIds;
|
||||||
|
allowedThingIds << thingIdTwo;
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.insert("username", usernameGuest);
|
||||||
|
params.insert("password", passwordGuest);
|
||||||
|
params.insert("scopes", scopes);
|
||||||
|
params.insert("allowedThingIds", allowedThingIds);
|
||||||
|
response = injectAndWait("Users.CreateUser", params);
|
||||||
|
QVERIFY2(response.toMap().value("status").toString() == "success", "Error creating user");
|
||||||
|
QVERIFY2(response.toMap().value("params").toMap().value("error").toString() == "UserErrorNoError", "Error creating user");
|
||||||
|
|
||||||
|
response = injectAndWait("Integrations.GetThings");
|
||||||
|
QVariantList things = response.toMap().value("params").toMap().value("things").toList();
|
||||||
|
//qCDebug(dcTests()) << qUtf8Printable(QJsonDocument::fromVariant(things).toJson(QJsonDocument::Indented));
|
||||||
|
QVERIFY2(things.count() >= 2, "Expected to get 2 or more things as admin");
|
||||||
|
|
||||||
|
// Everything set up, now authenticate as guest
|
||||||
|
|
||||||
|
// Authenticate guest user
|
||||||
|
params.clear();
|
||||||
|
params.insert("username", usernameGuest);
|
||||||
|
params.insert("password", passwordGuest);
|
||||||
|
params.insert("deviceName", "autotests");
|
||||||
|
response = injectAndWait("JSONRPC.Authenticate", params);
|
||||||
|
QVERIFY2(response.toMap().value("status").toString() == "success", "Error authenticating");
|
||||||
|
QVERIFY2(response.toMap().value("params").toMap().value("success").toString() == "true", "Error authenticating");
|
||||||
|
|
||||||
|
m_guestToken = response.toMap().value("params").toMap().value("token").toByteArray();
|
||||||
|
|
||||||
|
// Use the admin token for now
|
||||||
|
m_apiToken = m_guestToken;
|
||||||
|
|
||||||
|
// Try to access restricted thing
|
||||||
|
|
||||||
|
response = injectAndWait("Integrations.GetThings");
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorNoError));
|
||||||
|
things = response.toMap().value("params").toMap().value("things").toList();
|
||||||
|
QVERIFY2(things.count() == 1, "Expected to get exactly 1 things as guest");
|
||||||
|
|
||||||
|
// GetThings (access)
|
||||||
|
params.clear();
|
||||||
|
params.insert("thingId", thingIdTwo);
|
||||||
|
response = injectAndWait("Integrations.GetThings", params);
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorNoError));
|
||||||
|
|
||||||
|
// GetThings (no access)
|
||||||
|
params.clear();
|
||||||
|
params.insert("thingId", thingIdOne);
|
||||||
|
response = injectAndWait("Integrations.GetThings", params);
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
|
// GetStateValue
|
||||||
|
params.clear();
|
||||||
|
params.insert("thingId", thingIdOne);
|
||||||
|
params.insert("stateTypeId", mockConnectedStateTypeId);
|
||||||
|
response = injectAndWait("Integrations.GetStateValue", params);
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
|
// BrowseThing
|
||||||
|
params.clear();
|
||||||
|
params.insert("thingId", thingIdOne);
|
||||||
|
response = injectAndWait("Integrations.BrowseThing", params);
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
|
// GetBrowserItem
|
||||||
|
params.clear();
|
||||||
|
params.insert("thingId", thingIdOne);
|
||||||
|
response = injectAndWait("Integrations.GetBrowserItem", params);
|
||||||
|
verifyError(response, "thingError", enumValueName(Thing::ThingErrorThingNotFound));
|
||||||
|
|
||||||
|
// Make sure notification get received from allowed thing
|
||||||
|
|
||||||
|
// Make sure no notification will be recived from restricted thing
|
||||||
|
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(TestUsermanager)
|
QTEST_MAIN(TestUsermanager)
|
||||||
|
|
||||||
|
|||||||
125
tests/auto/usermanager/testusermanager.h
Normal file
125
tests/auto/usermanager/testusermanager.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
*
|
||||||
|
* Copyright 2013 - 2025, nymea GmbH
|
||||||
|
* Contact: contact@nymea.io
|
||||||
|
*
|
||||||
|
* This file is part of nymea.
|
||||||
|
* This project including source code and documentation is protected by
|
||||||
|
* copyright law, and remains the property of nymea GmbH. All rights, including
|
||||||
|
* reproduction, publication, editing and translation, are reserved. The use of
|
||||||
|
* this project is subject to the terms of a license agreement to be concluded
|
||||||
|
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
|
||||||
|
* under https://nymea.io/license
|
||||||
|
*
|
||||||
|
* GNU General Public License Usage
|
||||||
|
* Alternatively, this project may be redistributed and/or modified under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, GNU version 3. This project is distributed in the hope that it
|
||||||
|
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||||
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this project. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* For any further details and any questions please contact us under
|
||||||
|
* contact@nymea.io or see our FAQ/Licensing Information on
|
||||||
|
* https://nymea.io/license/faq
|
||||||
|
*
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef TESTUSERMANAGER_H
|
||||||
|
#define TESTUSERMANAGER_H
|
||||||
|
|
||||||
|
#include <QtTest>
|
||||||
|
#include "nymeatestbase.h"
|
||||||
|
|
||||||
|
using namespace nymeaserver;
|
||||||
|
|
||||||
|
class TestUsermanager: public NymeaTestBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TestUsermanager(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initTestCase();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void loginValidation_data();
|
||||||
|
void loginValidation();
|
||||||
|
|
||||||
|
void createUser();
|
||||||
|
|
||||||
|
void authenticate();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Cases for push button auth:
|
||||||
|
|
||||||
|
Case 1: regular pushbutton
|
||||||
|
- alice sends Users.RequestPushButtonAuth, gets "OK" back (if push button hardware is available)
|
||||||
|
- alice pushes the hardware button and gets a notification on jsonrpc containing the token for local auth
|
||||||
|
*/
|
||||||
|
void authenticatePushButton();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Case 2: if we have an attacker in the network, he could try to call requestPushButtonAuth and
|
||||||
|
hope someone would eventually press the button and give him a token. In order to prevent this,
|
||||||
|
any previous attempt for a push button auth needs to be cancelled when a new request comes in:
|
||||||
|
|
||||||
|
* Mallory does RequestPushButtonAuth, gets OK back
|
||||||
|
* Alice does RequestPushButtonAuth,
|
||||||
|
* Mallory receives a "PushButtonFailed" notification
|
||||||
|
* Alice receives OK
|
||||||
|
* Alice presses the hardware button
|
||||||
|
* Alice reveices a notification with token, mallory receives nothing
|
||||||
|
|
||||||
|
Case 3: Mallory tries to hijack it back again
|
||||||
|
|
||||||
|
* Mallory does RequestPushButtonAuth, gets OK back
|
||||||
|
* Alice does RequestPusButtonAuth,
|
||||||
|
* Alice gets ok reply, Mallory gets failed notification
|
||||||
|
* Mallory quickly does RequestPushButtonAuth again to win the fight
|
||||||
|
* Alice gets failed notification and can instruct the user to _not_ press the button now until procedure is restarted
|
||||||
|
*/
|
||||||
|
void authenticatePushButtonAuthInterrupt();
|
||||||
|
|
||||||
|
void authenticatePushButtonAuthConnectionDrop();
|
||||||
|
|
||||||
|
void createDuplicateUser();
|
||||||
|
|
||||||
|
void getTokens();
|
||||||
|
|
||||||
|
void removeToken();
|
||||||
|
|
||||||
|
void unauthenticatedCallAfterTokenRemove();
|
||||||
|
|
||||||
|
void changePassword();
|
||||||
|
|
||||||
|
void authenticateAfterPasswordChangeOK();
|
||||||
|
|
||||||
|
void authenticateAfterPasswordChangeFail();
|
||||||
|
|
||||||
|
void getUserInfo();
|
||||||
|
|
||||||
|
void testScopeConsitancy_data();
|
||||||
|
void testScopeConsitancy();
|
||||||
|
|
||||||
|
void testRestrictedThingAccess();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// m_apiToken is in testBase
|
||||||
|
QUuid m_tokenId;
|
||||||
|
|
||||||
|
void authenticateTestuser(const QString &username);
|
||||||
|
|
||||||
|
QString m_usernameAdmin = "admin";
|
||||||
|
QString m_usernameGuest = "guest";
|
||||||
|
|
||||||
|
QByteArray m_adminToken;
|
||||||
|
QByteArray m_guestToken;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TESTUSERMANAGER_H
|
||||||
@ -3,7 +3,8 @@ include(../autotests.pri)
|
|||||||
|
|
||||||
TARGET = nymeatestusermanager
|
TARGET = nymeatestusermanager
|
||||||
|
|
||||||
HEADERS += ../../utils/pushbuttonagent.h
|
HEADERS += ../../utils/pushbuttonagent.h \
|
||||||
|
testusermanager.h
|
||||||
|
|
||||||
SOURCES += testusermanager.cpp \
|
SOURCES += testusermanager.cpp \
|
||||||
../../utils/pushbuttonagent.cpp
|
../../utils/pushbuttonagent.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user