add authorization structure to core methods

This commit is contained in:
Evgenii Alekseev 2017-03-01 23:12:17 +03:00
parent dc46039a53
commit de3d7c10c3
11 changed files with 539 additions and 71 deletions

View File

@ -1,10 +1,12 @@
set (SUBPROJECT "queued")
message (STATUS "Subproject ${SUBPROJECT}")
configure_file ("QueuedConfig.h.in" "${CMAKE_BINARY_DIR}/QueuedConfig.h")
add_subdirectory ("src")
# headers
install (DIRECTORY "include/${SUBPROJECT}" DESTINATION "${INCLUDE_INSTALL_DIR}")
install (FILES "${CMAKE_BINARY_DIR}/config.h" DESTINATION "${INCLUDE_INSTALL_DIR}/${SUBPROJECT}")
install (FILES "${CMAKE_BINARY_DIR}/QueuedConfig.h" DESTINATION "${INCLUDE_INSTALL_DIR}/${SUBPROJECT}")
# documentation
if (BUILD_DOCS)
include ("docs.cmake")

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2016 Evgeniy Alekseev
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
*
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
/**
* @file QueuedConfig.h
* Source code of queued library
* @author Evgeniy Alekseev
* @copyright GPLv3
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDCONFIG_H
#define QUEUEDCONFIG_H
/**
* @defgroup QueuedConfig
* @brief Queued configuration constants
*/
namespace QueuedConfig
{
// dbus configuration
/**
* @brief DBus service name for library and application
* @remark required by Qt macro
*/
#define DBUS_SERVICE_NAME "org.quadro.core"
/**
* @ingroup QueuedConfig
* @brief DBus service name for library and application
*/
const char DBUS_SERVICE[] = DBUS_SERVICE_NAME;
/**
* @ingroup QueuedConfig
* @brief DBus object path for library
*/
const char DBUS_OBJECT_PATH[] = "/queued";
// path configuration
// common paths
/**
* @ingroup QueuedConfig
* @brief installation directory for executables
*/
const char BIN_INSTALL_DIR[] = "@BIN_INSTALL_DIR@";
/**
* @ingroup QueuedConfig
* @brief installation directory for data
*/
const char DATA_INSTALL_DIR[] = "@DATA_INSTALL_DIR@";
/**
* @ingroup QueuedConfig
* @brief installation directory for headers
*/
const char INCLUDE_INSTALL_DIR[] = "@INCLUDE_INSTALL_DIR@";
/**
* @ingroup QueuedConfig
* @brief installation directory for libraries
*/
const char LIB_INSTALL_DIR[] = "@LIB_INSTALL_DIR@";
/**
* @ingroup QueuedConfig
* @brief the same as CMAKE_INSTALL_PREFIX
*/
const char ROOT_INSTALL_DIR[] = "@CMAKE_INSTALL_PREFIX@";
// plugin interfaces
/**
* @brief plugin interface name
* @remark required by Qt macro
*/
#define PLUGIN_INTERFACE_NAME \
"queued.plugin/@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@"
/**
* @ingroup QueuedConfig
* @brief plugin interface name
*/
const char PLUGIN_INTERFACE[] = PLUGIN_INTERFACE_NAME;
}
#endif /* QUEUEDCONFIG_H */

View File

@ -28,6 +28,7 @@
#include "QueuedEnums.h"
#include "QueuedLimits.h"
#include "QueuedUserManager.h"
class QueuedAdvancedSettings;
@ -36,7 +37,6 @@ class QueuedProcessManager;
class QueuedReportManager;
class QueuedSettings;
class QueuedTokenManager;
class QueuedUserManager;
/**
* @brief aggregator of queued classes
@ -69,11 +69,14 @@ public:
* task owner user ID
* @param _limits
* task defined limits
* @param _auth
* user auth structure
* @return true on successfully addition
*/
bool addTask(const QString &_command, const QStringList &_arguments,
const QString &_workingDirectory, const unsigned int _nice,
const long long _userId, const QueuedLimits::Limits &_limits);
const long long _userId, const QueuedLimits::Limits &_limits,
const QueuedUserManager::QueuedUserAuthorization &_auth);
/**
* @brief add new user
* @param _name
@ -86,42 +89,65 @@ public:
* user permissions
* @param _limits
* user limits
* @param _auth
* user auth structure
* @return true on successfully addition
*/
bool addUser(const QString &_name, const QString &_email,
const QString &_password, const unsigned int _permissions,
const QueuedLimits::Limits &_limits);
const QueuedLimits::Limits &_limits,
const QueuedUserManager::QueuedUserAuthorization &_auth);
/**
* @brief authorize and create new token for user
* @param _name
* user name
* @param _password
* user password
* @return authorization structure. Token field will be empty in case if no
* authorization occurs
*/
QueuedUserManager::QueuedUserAuthorization
authorization(const QString &_name, const QString &_password);
/**
* @brief edit advanced settings
* @param _key
* advanced settings key
* @param _value
* advanced settings value
* @param _auth
* user auth structure
* @return true on successful option edition
*/
bool editOption(const QString &_key, const QVariant &_value);
bool editOption(const QString &_key, const QVariant &_value,
const QueuedUserManager::QueuedUserAuthorization &_auth);
/**
* @brief edit task
* @param _id
* task ID to edit
* @param _taskData
* task data to edit
* @param _auth
* user auth structure
* @remark _taskData should contain only fields defined in schema, any other
* fields will be ignored. No need to pass all properties here
* @return true on successful task edition
*/
bool editTask(const long long _id, const QVariantHash &_taskData);
bool editTask(const long long _id, const QVariantHash &_taskData,
const QueuedUserManager::QueuedUserAuthorization &_auth);
/**
* @brief edit user
* @param _id
* user ID to edit
* @param _userData
* user data to edit
* @param _auth
* user auth structure
* @remark _userData should contain only fields defined in schema, any other
* fields will be ignored. No need to pass all properties here
* @return true on successful user edition
*/
bool editUser(const long long _id, const QVariantHash &_userData);
bool editUser(const long long _id, const QVariantHash &_userData,
const QueuedUserManager::QueuedUserAuthorization &_auth);
/**
* @brief edit user permissions
* @param _id
@ -130,11 +156,35 @@ public:
* permission to add or remove
* @param _add
* indicates whether it should be added or removed
* @param _auth
* user auth structure
* @return true on successful user permission edition
*/
bool editUserPermission(const long long _id,
const QueuedEnums::Permission &_permission,
const bool _add);
bool
editUserPermission(const long long _id,
const QueuedEnums::Permission &_permission,
const bool _add,
const QueuedUserManager::QueuedUserAuthorization &_auth);
/**
* @brief force start task
* @param _id
* task ID
* @param _auth
* user auth structure
* @return true on successful task start
*/
bool startTask(const long long _id,
const QueuedUserManager::QueuedUserAuthorization &_auth);
/**
* @brief force stop task
* @param _id
* task ID
* @param _auth
* user auth structure
* @return true on successful task stop
*/
bool stopTask(const long long _id,
const QueuedUserManager::QueuedUserAuthorization &_auth);
// control methods
/**
* @brief deinit subclasses
@ -207,6 +257,16 @@ private:
* @brief connection list
*/
QList<QMetaObject::Connection> m_connections;
/**
* @brief drop non-admin fields from database payload
* @param _table
* table name
* @param _payload
* initial database payload
* @return payload with dropped keys
*/
QVariantHash dropAdminFields(const QString &_table,
const QVariantHash &_payload);
/**
* @brief init processes
*/

View File

@ -64,11 +64,14 @@ const char USERS_TABLE[] = "users";
* description to create column
* @var type
* Qt type of column for cast
* @var adminField
* is admin permissions required to edit or not
*/
typedef struct {
QString name;
QString sqlDescription;
QVariant::Type type;
bool adminField;
} QueuedDBField;
/**
* @ingroup QueuedDB
@ -83,39 +86,46 @@ typedef QHash<QString, QHash<QString, QueuedDBField>> QueuedDBSchema;
const QueuedDBSchema DBSchema = {
{SETTINGS_TABLE,
{{"_id",
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong}},
{"key", {"key", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String}},
{"value", {"value", "TEXT", QVariant::String}}}},
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong,
true}},
{"key",
{"key", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String, true}},
{"value", {"value", "TEXT", QVariant::String, true}}}},
{TASKS_TABLE,
{{"_id",
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong}},
{"user", {"user", "INT NOT NULL DEFAULT 0", QVariant::LongLong}},
{"command", {"command", "TEXT", QVariant::String}},
{"commandArguments", {"commandArguments", "TEXT", QVariant::String}},
{"workDirectory", {"workDirectory", "TEXT", QVariant::String}},
{"nice", {"nice", "INT", QVariant::UInt}},
{"uid", {"uid", "INT", QVariant::UInt}},
{"gid", {"gid", "INT", QVariant::UInt}},
{"state", {"state", "INT", QVariant::UInt}},
{"limits", {"limits", "TEXT", QVariant::String}},
{"startTime", {"startTime", "INT", QVariant::LongLong}},
{"endTime", {"endTime", "INT", QVariant::LongLong}}}},
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong,
true}},
{"user", {"user", "INT NOT NULL DEFAULT 0", QVariant::LongLong, false}},
{"command", {"command", "TEXT", QVariant::String, false}},
{"commandArguments",
{"commandArguments", "TEXT", QVariant::String, false}},
{"workDirectory", {"workDirectory", "TEXT", QVariant::String, false}},
{"nice", {"nice", "INT", QVariant::UInt, false}},
{"uid", {"uid", "INT", QVariant::UInt, false}},
{"gid", {"gid", "INT", QVariant::UInt, false}},
{"state", {"state", "INT", QVariant::UInt, true}},
{"limits", {"limits", "TEXT", QVariant::String, false}},
{"startTime", {"startTime", "INT", QVariant::LongLong, true}},
{"endTime", {"endTime", "INT", QVariant::LongLong, true}}}},
{TOKENS_TABLE,
{{"_id",
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong}},
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong,
true}},
{"token",
{"token", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String}},
{"token", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String, true}},
{"validUntil",
{"validUntil", "TEXT NOT NULL DEFAULT '0'", QVariant::String}}}},
{"validUntil", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}}}},
{USERS_TABLE,
{{"_id",
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong}},
{"name", {"name", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String}},
{"password", {"password", "TEXT", QVariant::String}},
{"email", {"email", "TEXT", QVariant::String}},
{"lastLogin", {"lastLogin", "TEXT", QVariant::String}},
{"limits", {"limits", "TEXT", QVariant::String}},
{"permissions", {"permissions", "INT", QVariant::UInt}}}}};
{"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong,
true}},
{"name",
{"name", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String, true}},
{"password", {"password", "TEXT", QVariant::String, false}},
{"email", {"email", "TEXT", QVariant::String, false}},
{"lastLogin", {"lastLogin", "TEXT", QVariant::String, true}},
{"limits", {"limits", "TEXT", QVariant::String, true}},
{"permissions", {"permissions", "INT", QVariant::UInt, true}}}}};
};
#endif /* QUEUEDDATABASESCHEMA_H */

View File

@ -63,8 +63,6 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(LimitTypes)
* administrative permissions
* @var Permissions::JobOwner
* owner job related permissions
* @var Permissions::JobGlobal
* other users job control
* @var Permissions::User
* user related permissions
* @var Permissions::Web
@ -76,10 +74,9 @@ enum class Permission {
SuperAdmin = 1 << 0,
Admin = 1 << 1,
JobOwner = 1 << 2,
JobGlobal = 1 << 3,
User = 1 << 4,
Web = 1 << 5,
Reports = 1 << 6
User = 1 << 3,
Web = 1 << 4,
Reports = 1 << 5
};
Q_DECLARE_FLAGS(Permissions, Permission)
Q_DECLARE_OPERATORS_FOR_FLAGS(Permissions)

View File

@ -98,6 +98,28 @@ struct Limits {
storage = limits.at(4).toLongLong();
valid = true;
};
/**
* @brief structure constructor from fields
* @param _cpuLimit
* limit by CPU cores
* @param _gpuLimit
* limit by GPU cores
* @param _memory
* limit by memory
* @param _gpumemory
* limit by GPU memory
* @param _storage
* limit by storage
*/
Limits(const long long _cpuLimit, const long long _gpuLimit,
const long long _memoryLimit, const long long _gpumemoryLimit,
const long long _storage)
: cpu(_cpuLimit)
, gpu(_gpuLimit)
, memory(_memoryLimit)
, gpumemory(_gpumemoryLimit)
, storage(_storage)
, valid(true){};
};
/**
* @ingroup QueuedLimits
@ -108,7 +130,7 @@ struct Limits {
* conversion status
* @return converted integer
*/
long long convertMemory(QString _value, bool *_status);
long long convertMemory(QString _value, bool *_status = nullptr);
/**
* @ingroup QueuedLimits
* @brief compare two limits

View File

@ -52,7 +52,7 @@ public:
* token ID
* @return true if token is valid otherwise return false
*/
bool isTokenValid(const QString &_token);
bool isTokenValid(const QString &_token) const;
/**
* @brief upload tokens from database
* @param _value
@ -66,6 +66,14 @@ public:
* @return new generated token
*/
QString registerToken(const QDateTime _validUntil);
/**
* @brief token expiration
* @param _token
* token ID
* @return token expiration if token found, otherwise return default
* QDateTime constructor
*/
QDateTime tokenExpiration(const QString &_token) const;
public slots:
/**

View File

@ -55,7 +55,7 @@ public:
typedef struct {
QString token;
QString user;
} UserAuthorization;
} QueuedUserAuthorization;
/**
* @brief QueuedUserManager class constructor
@ -86,6 +86,16 @@ public:
*/
QueuedUser *add(const QueuedUser::QueuedUserDefinitions &_definitions,
const long long _id);
/**
* @brief build user auth structure
* @param _user
* user name
* @param _token
* user token
* @return generated structure
*/
static QueuedUserAuthorization auth(const QString &_user,
const QString &_token);
/**
* @brief authorize user
* @param _user
@ -103,8 +113,17 @@ public:
* service to authorize
* @return true if user allowed to do it otherwise return false
*/
bool authorize(const UserAuthorization &_auth,
bool authorize(const QueuedUserAuthorization &_auth,
const QueuedEnums::Permission _service);
/**
* @brief check token expiration
* @param _token
* token string
* @param _valid
* optional output parameter, will set to true if token is valid
* @return token expiration or default constructor
*/
QDateTime checkToken(const QString &_token, bool *_valid = nullptr) const;
/**
* @brief get UID and GID from user ID
* @param _id

View File

@ -22,6 +22,8 @@
#include "queued/Queued.h"
#include <queued/Queued.h>
#include <queued/QueuedDatabaseSchema.h>
#include "queued/QueuedDatabaseSchema.h"
@ -53,14 +55,38 @@ QueuedCore::~QueuedCore()
/**
* @addTask
*/
bool QueuedCore::addTask(const QString &_command, const QStringList &_arguments,
const QString &_workingDirectory,
const unsigned int _nice, const long long _userId,
const QueuedLimits::Limits &_limits)
bool QueuedCore::addTask(
const QString &_command, const QStringList &_arguments,
const QString &_workingDirectory, const unsigned int _nice,
const long long _userId, const QueuedLimits::Limits &_limits,
const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Add task" << _command << "with arguments" << _arguments
<< "from user" << _userId;
long long userAuthId = m_users->user(_auth.user)->index();
long long actualUserId = (_userId == -1) ? userAuthId : _userId;
// check permissions
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
bool isUser = m_users->authorize(_auth, QueuedEnums::Permission::JobOwner);
if (userAuthId == actualUserId) {
// it means that user places task as own one
if (!isUser) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to add task";
return false;
}
} else {
// user tries to place task as another one
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to add task";
return false;
}
}
// add to database
auto ids = m_users->ids(_userId);
auto taskLimits = QueuedLimits::minimalLimits(
_limits, m_users->user(_userId)->limits(),
@ -80,6 +106,7 @@ bool QueuedCore::addTask(const QString &_command, const QStringList &_arguments,
return false;
}
// add to child object
m_processes->add(properties, id);
return true;
}
@ -88,14 +115,22 @@ bool QueuedCore::addTask(const QString &_command, const QStringList &_arguments,
/**
* @fn addUser
*/
bool QueuedCore::addUser(const QString &_name, const QString &_email,
const QString &_password,
const unsigned int _permissions,
const QueuedLimits::Limits &_limits)
bool QueuedCore::addUser(
const QString &_name, const QString &_email, const QString &_password,
const unsigned int _permissions, const QueuedLimits::Limits &_limits,
const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Add user" << _name << "with email" << _email
<< "and permissions" << _permissions;
// check permissions
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user << "not allowed to add user";
return false;
}
// add to dababase
QVariantHash properties
= {{"name", _name},
{"password", QueuedUser::hashFromPassword(_password)},
@ -108,22 +143,52 @@ bool QueuedCore::addUser(const QString &_name, const QString &_email,
return false;
}
// add to child object
m_users->add(properties, id);
return true;
}
QueuedUserManager::QueuedUserAuthorization
QueuedCore::authorization(const QString &_name, const QString &_password)
{
qCDebug(LOG_LIB) << "Authorize user" << _name;
QString token = m_users->authorize(_name, _password);
QueuedUserManager::QueuedUserAuthorization auth;
auth.user = _name;
if (!token.isEmpty()) {
QVariantHash payload = {
{"token", token},
{"validUntil", m_users->checkToken(token).toString(Qt::ISODate)}};
m_database->add(QueuedDB::TOKENS_TABLE, payload);
}
return auth;
}
/**
* @fn editOption
*/
bool QueuedCore::editOption(const QString &_key, const QVariant &_value)
bool QueuedCore::editOption(
const QString &_key, const QVariant &_value,
const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Set key" << _key << "to" << _value;
// check permissions
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to edit options";
return false;
}
// add to database
long long id = m_advancedSettings->id(_key);
QVariantHash payload = {
{"key", _key}, {"value", _value},
};
QVariantHash payload = {{"key", _key}, {"value", _value}};
bool status = false;
if (id == -1) {
@ -136,6 +201,7 @@ bool QueuedCore::editOption(const QString &_key, const QVariant &_value)
<< "has been modified with status" << status;
}
// add to child objectm
if (status)
m_advancedSettings->set(_key, _value);
return status;
@ -145,7 +211,9 @@ bool QueuedCore::editOption(const QString &_key, const QVariant &_value)
/**
* @fn editTask
*/
bool QueuedCore::editTask(const long long _id, const QVariantHash &_taskData)
bool QueuedCore::editTask(
const long long _id, const QVariantHash &_taskData,
const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Edit task with ID" << _id;
@ -155,8 +223,41 @@ bool QueuedCore::editTask(const long long _id, const QVariantHash &_taskData)
return false;
}
// check permissions
long long userAuthId = m_users->user(_auth.user)->index();
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
bool isUser = m_users->authorize(_auth, QueuedEnums::Permission::JobOwner);
if (userAuthId == task->user()) {
// it means that user edits own task
if (!isUser) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to edit task";
return false;
}
} else {
// user tries to edit random task
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to edit task";
return false;
}
}
// only admin can edit run/stopped task
if (task->pstate() != QueuedEnums::ProcessState::NotRunning) {
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to edit run/exited task";
return false;
}
}
// drop admin fields
QVariantHash payload
= isAdmin ? _taskData
: dropAdminFields(QueuedDB::TASKS_TABLE, _taskData);
// modify record in database first
bool status = m_database->modify(QueuedDB::TASKS_TABLE, _id, _taskData);
bool status = m_database->modify(QueuedDB::TASKS_TABLE, _id, payload);
if (!status) {
qCWarning(LOG_LIB) << "Could not modify task record" << _id
<< "in database, do not edit it in memory";
@ -164,9 +265,9 @@ bool QueuedCore::editTask(const long long _id, const QVariantHash &_taskData)
}
// modify values stored in memory
for (auto &property : _taskData.keys())
for (auto &property : payload.keys())
task->setProperty(property.toLocal8Bit().constData(),
_taskData[property]);
payload[property]);
return true;
}
@ -175,7 +276,9 @@ bool QueuedCore::editTask(const long long _id, const QVariantHash &_taskData)
/**
* @fn editUser
*/
bool QueuedCore::editUser(const long long _id, const QVariantHash &_userData)
bool QueuedCore::editUser(
const long long _id, const QVariantHash &_userData,
const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Edit user with ID" << _id;
@ -185,8 +288,24 @@ bool QueuedCore::editUser(const long long _id, const QVariantHash &_userData)
return false;
}
// check permissions
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
long long userAuthId = m_users->user(_auth.user)->index();
if (userAuthId != _id) {
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to edit user";
return false;
}
}
// drop admin fields
QVariantHash payload
= isAdmin ? _userData
: dropAdminFields(QueuedDB::USERS_TABLE, _userData);
// modify record in database first
bool status = m_database->modify(QueuedDB::USERS_TABLE, _id, _userData);
bool status = m_database->modify(QueuedDB::USERS_TABLE, _id, payload);
if (!status) {
qCWarning(LOG_LIB) << "Could not modify user record" << _id
<< "in database, do not edit it in memory";
@ -194,9 +313,9 @@ bool QueuedCore::editUser(const long long _id, const QVariantHash &_userData)
}
// modify values stored in memory
for (auto &property : _userData.keys())
for (auto &property : payload.keys())
user->setProperty(property.toLocal8Bit().constData(),
_userData[property]);
payload[property]);
return true;
}
@ -205,9 +324,9 @@ bool QueuedCore::editUser(const long long _id, const QVariantHash &_userData)
/**
* @fn editUserPermission
*/
bool QueuedCore::editUserPermission(const long long _id,
const QueuedEnums::Permission &_permission,
const bool _add)
bool QueuedCore::editUserPermission(
const long long _id, const QueuedEnums::Permission &_permission,
const bool _add, const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Edit permissions" << static_cast<int>(_permission)
<< "for user" << _id << "add" << _add;
@ -218,6 +337,18 @@ bool QueuedCore::editUserPermission(const long long _id,
return false;
}
// check permissions
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
long long userAuthId = m_users->user(_auth.user)->index();
if (userAuthId != _id) {
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to edit permissions";
return false;
}
}
// edit runtime permissions to get value
if (_add)
user->addPermissions(_permission);
else
@ -243,6 +374,73 @@ bool QueuedCore::editUserPermission(const long long _id,
}
/**
* @fn startTask
*/
bool QueuedCore::startTask(
const long long _id,
const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Force start task with ID" << _id;
// check permissions
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
long long userAuthId = m_users->user(_auth.user)->index();
if (userAuthId != _id) {
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to start tasks";
return false;
}
}
m_processes->start(_id);
return true;
}
/**
* @fn stopTask
*/
bool QueuedCore::stopTask(
const long long _id,
const QueuedUserManager::QueuedUserAuthorization &_auth)
{
qCDebug(LOG_LIB) << "Force stop task with ID" << _id;
auto task = m_processes->process(_id);
if (!task) {
qCWarning(LOG_LIB) << "Could not find task with ID" << _id;
return false;
}
// check permissions
long long userAuthId = m_users->user(_auth.user)->index();
bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin);
bool isUser = m_users->authorize(_auth, QueuedEnums::Permission::JobOwner);
if (userAuthId == task->user()) {
// it means that user edits own task
if (!isUser) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to stop task";
return false;
}
} else {
// user tries to edit random task
if (!isAdmin) {
qCInfo(LOG_LIB) << "User" << _auth.user
<< "not allowed to stop task";
return false;
}
}
m_processes->stop(_id);
return true;
}
/**
* @fn deinit
*/
@ -351,6 +549,26 @@ void QueuedCore::updateUserLoginTime(const long long _id,
}
/**
* @fn dropAdminFields
*/
QVariantHash QueuedCore::dropAdminFields(const QString &_table,
const QVariantHash &_payload)
{
qCDebug(LOG_LIB) << "Drop admin fields from" << _payload << "in table"
<< _table;
QVariantHash payload;
for (auto &key : _payload.keys()) {
if (QueuedDB::DBSchema[_table][key].adminField)
continue;
payload[key] = _payload[key];
}
return payload;
}
/**
* @fn initProcesses
*/

View File

@ -52,11 +52,12 @@ QueuedTokenManager::~QueuedTokenManager()
/**
* @fn isTokenValid
*/
bool QueuedTokenManager::isTokenValid(const QString &_token)
bool QueuedTokenManager::isTokenValid(const QString &_token) const
{
qCDebug(LOG_LIB) << "Check token on validity" << _token;
return m_tokens.contains(_token);
return m_tokens.contains(_token)
&& (tokenExpiration(_token) > QDateTime::currentDateTimeUtc());
}
@ -101,6 +102,15 @@ QString QueuedTokenManager::registerToken(const QDateTime _validUntil)
}
/**
* @fn tokenExpiration
*/
QDateTime QueuedTokenManager::tokenExpiration(const QString &_token) const
{
return m_tokens[_token];
}
/**
* @fn expireToken
*/

View File

@ -94,6 +94,22 @@ QueuedUserManager::add(const QueuedUser::QueuedUserDefinitions &_definitions,
}
/**
* @fn auth
*/
QueuedUserManager::QueuedUserAuthorization
QueuedUserManager::auth(const QString &_user, const QString &_token)
{
qCDebug(LOG_LIB) << "Generate auth structure for user" << _user;
QueuedUserAuthorization authObj;
authObj.user = _user;
authObj.token = _token;
return authObj;
}
/**
* @fn authorize
*/
@ -124,7 +140,7 @@ QString QueuedUserManager::authorize(const QString &_user,
/**
* @fn authorize
*/
bool QueuedUserManager::authorize(const UserAuthorization &_auth,
bool QueuedUserManager::authorize(const QueuedUserAuthorization &_auth,
const QueuedEnums::Permission _service)
{
qCDebug(LOG_LIB) << "Authorize user" << _auth.user << "for"
@ -146,6 +162,19 @@ bool QueuedUserManager::authorize(const UserAuthorization &_auth,
}
/**
* @fn checkToken
*/
QDateTime QueuedUserManager::checkToken(const QString &_token,
bool *_valid) const
{
if (_valid)
*_valid = m_tokens->isTokenValid(_token);
return m_tokens->tokenExpiration(_token);
}
/**
* @fn ids
*/