mirror of
https://github.com/arcan1s/queued.git
synced 2025-04-24 15:37:19 +00:00
add authorization structure to core methods
This commit is contained in:
parent
dc46039a53
commit
de3d7c10c3
@ -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")
|
||||
|
93
sources/queued/QueuedConfig.h.in
Normal file
93
sources/queued/QueuedConfig.h.in
Normal 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 */
|
@ -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
|
||||
*/
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user