mirror of https://github.com/nymea/nymea.git
217 lines
8.9 KiB
C++
217 lines
8.9 KiB
C++
#include "usershandler.h"
|
|
#include "usermanager/usermanager.h"
|
|
#include "usermanager/userinfo.h"
|
|
|
|
#include "loggingcategories.h"
|
|
|
|
namespace nymeaserver {
|
|
|
|
UsersHandler::UsersHandler(UserManager *userManager, QObject *parent):
|
|
JsonHandler(parent),
|
|
m_userManager(userManager)
|
|
{
|
|
registerObject<UserInfo>();
|
|
registerObject<TokenInfo, TokenInfoList>();
|
|
|
|
QVariantMap params, returns;
|
|
QString description;
|
|
|
|
params.clear(); returns.clear();
|
|
description = "Create a new user in the API. Currently this is only allowed to be called once when a new nymea instance is set up. Call Authenticate after this to obtain a device token for this user.";
|
|
params.insert("username", enumValueName(String));
|
|
params.insert("password", enumValueName(String));
|
|
returns.insert("error", enumRef<UserManager::UserError>());
|
|
registerMethod("CreateUser", description, params, returns);
|
|
|
|
params.clear(); returns.clear();
|
|
description = "Change the password for the currently logged in user.";
|
|
params.insert("newPassword", enumValueName(String));
|
|
returns.insert("error", enumRef<UserManager::UserError>());
|
|
registerMethod("ChangePassword", description, params, returns);
|
|
|
|
params.clear(); returns.clear();
|
|
description = "Get info about the current token (the currently logged in user).";
|
|
returns.insert("o:userInfo", objectRef<UserInfo>());
|
|
returns.insert("error", enumRef<UserManager::UserError>());
|
|
registerMethod("GetUserInfo", description, params, returns);
|
|
|
|
params.clear(); returns.clear();
|
|
description = "Get all the tokens for the current user.";
|
|
returns.insert("o:tokenInfoList", objectRef<TokenInfoList>());
|
|
returns.insert("error", enumRef<UserManager::UserError>());
|
|
registerMethod("GetTokens", description, params, returns);
|
|
|
|
params.clear(); returns.clear();
|
|
description = "Revoke access for a given token.";
|
|
params.insert("tokenId", enumValueName(Uuid));
|
|
returns.insert("error", enumRef<UserManager::UserError>());
|
|
registerMethod("RemoveToken", description, params, returns);
|
|
|
|
}
|
|
|
|
QString UsersHandler::name() const
|
|
{
|
|
return "Users";
|
|
}
|
|
|
|
JsonReply *UsersHandler::CreateUser(const QVariantMap ¶ms)
|
|
{
|
|
QString username = params.value("username").toString();
|
|
QString password = params.value("password").toString();
|
|
|
|
UserManager::UserError status = m_userManager->createUser(username, password);
|
|
|
|
QVariantMap returns;
|
|
returns.insert("error", enumValueName<UserManager::UserError>(status));
|
|
return createReply(returns);
|
|
}
|
|
|
|
JsonReply *UsersHandler::ChangePassword(const QVariantMap ¶ms)
|
|
{
|
|
QVariantMap ret;
|
|
|
|
QByteArray currentToken = property("token").toByteArray();
|
|
if (currentToken.isEmpty()) {
|
|
qCWarning(dcJsonRpc()) << "Cannot change password from an unauthenticated connection";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
if (!m_userManager->verifyToken(currentToken)) {
|
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
|
|
QString newPassword = params.value("newPassword").toString();
|
|
QString username = m_userManager->userInfo(currentToken).username();
|
|
|
|
UserManager::UserError status = m_userManager->changePassword(username, newPassword);
|
|
ret.insert("error", enumValueName<UserManager::UserError>(status));
|
|
return createReply(ret);
|
|
}
|
|
|
|
JsonReply *UsersHandler::Authenticate(const QVariantMap ¶ms)
|
|
{
|
|
QString username = params.value("username").toString();
|
|
QString password = params.value("password").toString();
|
|
QString deviceName = params.value("deviceName").toString();
|
|
|
|
QByteArray token = m_userManager->authenticate(username, password, deviceName);
|
|
QVariantMap ret;
|
|
ret.insert("success", !token.isEmpty());
|
|
if (!token.isEmpty()) {
|
|
ret.insert("token", token);
|
|
}
|
|
return createReply(ret);
|
|
}
|
|
|
|
JsonReply *UsersHandler::RequestPushButtonAuth(const QVariantMap ¶ms)
|
|
{
|
|
QString deviceName = params.value("deviceName").toString();
|
|
QUuid clientId = this->property("clientId").toUuid();
|
|
|
|
int transactionId = m_userManager->requestPushButtonAuth(deviceName);
|
|
m_pushButtonTransactions.insert(transactionId, clientId);
|
|
|
|
QVariantMap data;
|
|
data.insert("transactionId", transactionId);
|
|
// TODO: return false if pushbutton auth is disabled in settings
|
|
data.insert("success", true);
|
|
return createReply(data);
|
|
}
|
|
|
|
JsonReply *UsersHandler::GetUserInfo(const QVariantMap ¶ms)
|
|
{
|
|
Q_UNUSED(params)
|
|
QVariantMap ret;
|
|
|
|
QByteArray currentToken = property("token").toByteArray();
|
|
if (currentToken.isEmpty()) {
|
|
qCWarning(dcJsonRpc()) << "Cannot get user info form an unauthenticated connection";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
if (!m_userManager->verifyToken(currentToken)) {
|
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
|
|
UserInfo userInfo = m_userManager->userInfo(currentToken);
|
|
ret.insert("userInfo", pack(userInfo));
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorNoError));
|
|
return createReply(ret);
|
|
}
|
|
|
|
JsonReply *UsersHandler::GetTokens(const QVariantMap ¶ms)
|
|
{
|
|
Q_UNUSED(params)
|
|
QVariantMap ret;
|
|
|
|
QByteArray currentToken = property("token").toByteArray();
|
|
if (currentToken.isEmpty()) {
|
|
qCWarning(dcJsonRpc()) << "Cannot fetch tokens form an unauthenticated connection";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
if (!m_userManager->verifyToken(currentToken)) {
|
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
|
|
TokenInfo tokenInfo = m_userManager->tokenInfo(currentToken);
|
|
qCDebug(dcJsonRpc()) << "Fetching tokens for user" << tokenInfo.username();
|
|
QList<TokenInfo> tokens = m_userManager->tokens(tokenInfo.username());
|
|
QVariantList retList;
|
|
foreach (const TokenInfo &tokenInfo, tokens) {
|
|
retList << pack(tokenInfo);
|
|
}
|
|
ret.insert("tokenInfoList", retList);
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorNoError));
|
|
return createReply(ret);
|
|
}
|
|
|
|
JsonReply *UsersHandler::RemoveToken(const QVariantMap ¶ms)
|
|
{
|
|
QVariantMap ret;
|
|
|
|
QByteArray currentToken = property("token").toByteArray();
|
|
if (currentToken.isEmpty()) {
|
|
qCWarning(dcJsonRpc()) << "Cannot remove a token from an unauthenticated connection.";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
if (!m_userManager->verifyToken(currentToken)) {
|
|
// Might happen if the client is connecting via an unauthenticated connection but tries to sneak in an invalid token
|
|
qCWarning(dcJsonRpc()) << "Invalid token. Is this an unauthenticated connection?";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
QUuid tokenId = params.value("tokenId").toUuid();
|
|
TokenInfo tokenToRemove = m_userManager->tokenInfo(tokenId);
|
|
if (tokenToRemove.id().isNull()) {
|
|
qCWarning(dcJsonRpc()) << "Token with ID" << tokenId << "not found";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorTokenNotFound));
|
|
return createReply(ret);
|
|
}
|
|
|
|
TokenInfo currentTokenInfo = m_userManager->tokenInfo(currentToken);
|
|
if (currentTokenInfo.username() != tokenToRemove.username()) {
|
|
qCWarning(dcJsonRpc()) << "Cannot remove a token from another user!";
|
|
ret.insert("error", enumValueName<UserManager::UserError>(UserManager::UserErrorPermissionDenied));
|
|
return createReply(ret);
|
|
}
|
|
|
|
qCDebug(dcJsonRpc()) << "Removing token" << tokenId << "for user" << currentTokenInfo.username();
|
|
|
|
UserManager::UserError error = m_userManager->removeToken(tokenId);
|
|
ret.insert("error", enumValueName<UserManager::UserError>(error));
|
|
return createReply(ret);
|
|
}
|
|
|
|
}
|