diff --git a/sources/3rdparty/result b/sources/3rdparty/result index e03dc8e..fafc011 160000 --- a/sources/3rdparty/result +++ b/sources/3rdparty/result @@ -1 +1 @@ -Subproject commit e03dc8efb056f468b108c5034e19fec96e5b976b +Subproject commit fafc01123d53370f7744596fadd4e77212bc55fa diff --git a/sources/queued-daemon/src/QueuedApplication.cpp b/sources/queued-daemon/src/QueuedApplication.cpp index 978f212..a2ade85 100644 --- a/sources/queued-daemon/src/QueuedApplication.cpp +++ b/sources/queued-daemon/src/QueuedApplication.cpp @@ -49,6 +49,7 @@ QueuedApplication::~QueuedApplication() void QueuedApplication::init() { + m_core->deinit(); m_core->init(m_configuration["config"].toString()); } diff --git a/sources/queued-server/src/QueuedTcpServerResponseHelperAuth.cpp b/sources/queued-server/src/QueuedTcpServerResponseHelperAuth.cpp index 523e284..ca4d24a 100644 --- a/sources/queued-server/src/QueuedTcpServerResponseHelperAuth.cpp +++ b/sources/queued-server/src/QueuedTcpServerResponseHelperAuth.cpp @@ -28,8 +28,7 @@ QVariantHash QueuedTcpServerResponseHelperAuth::auth(const QVariantHash &_data) auto res = QueuedCoreAdaptor::auth(_data["user"].toString(), _data["password"].toString()); - Result::match( - res, + res.match( [&output](const QString &val) { output = {{"code", 200}, {"token", val}}; }, @@ -51,8 +50,8 @@ bool QueuedTcpServerResponseHelperAuth::tryAuth(const QString &_token) auto res = QueuedCoreAdaptor::auth(_token); bool ret = true; - Result::match(res, [&ret](const bool val) { ret = val; }, - [&ret](const QueuedError &err) { ret = false; }); + res.match([&ret](const bool val) { ret = val; }, + [&ret](const QueuedError &err) { ret = false; }); return ret; } diff --git a/sources/queued-server/src/QueuedTcpServerResponseHelperOption.cpp b/sources/queued-server/src/QueuedTcpServerResponseHelperOption.cpp index 90649a3..c333917 100644 --- a/sources/queued-server/src/QueuedTcpServerResponseHelperOption.cpp +++ b/sources/queued-server/src/QueuedTcpServerResponseHelperOption.cpp @@ -27,13 +27,13 @@ QueuedTcpServerResponseHelperOption::getOption(const QString &_option) auto res = QueuedCoreAdaptor::getOption(_option); QVariantHash output; - Result::match(res, - [&output](const QVariant &val) { - output = {{"code", 200}, {"token", val}}; - }, - [&output](const QueuedError &) { - output = {{"code", 404}, {"message", "Option not found"}}; - }); + res.match( + [&output](const QVariant &val) { + output = {{"code", 200}, {"token", val}}; + }, + [&output](const QueuedError &) { + output = {{"code", 404}, {"message", "Option not found"}}; + }); return output; } @@ -51,8 +51,7 @@ QVariantHash QueuedTcpServerResponseHelperOption::setOption( = QueuedCoreAdaptor::sendOptionEdit(_option, _value["value"], _token); QVariantHash output; - Result::match( - res, + res.match( [&output](const QVariant &) { output = {{"code", 200}}; }, diff --git a/sources/queued-server/src/QueuedTcpServerResponseHelperPermissions.cpp b/sources/queued-server/src/QueuedTcpServerResponseHelperPermissions.cpp index 8cb4c4f..c381e48 100644 --- a/sources/queued-server/src/QueuedTcpServerResponseHelperPermissions.cpp +++ b/sources/queued-server/src/QueuedTcpServerResponseHelperPermissions.cpp @@ -36,8 +36,7 @@ QVariantHash QueuedTcpServerResponseHelperPermissions::addPermission( = QueuedCoreAdaptor::sendUserPermissionAdd(_id, permission, _token); QVariantHash output; - Result::match( - res, + res.match( [&output](const QVariant &) { output = {{"code", 200}}; }, @@ -66,8 +65,7 @@ QVariantHash QueuedTcpServerResponseHelperPermissions::removePermission( = QueuedCoreAdaptor::sendUserPermissionRemove(_id, permission, _token); QVariantHash output; - Result::match( - res, + res.match( [&output](const QVariant &) { output = {{"code", 200}}; }, diff --git a/sources/queued-server/src/QueuedTcpServerResponseHelperPlugins.cpp b/sources/queued-server/src/QueuedTcpServerResponseHelperPlugins.cpp index 97f8315..84cfe50 100644 --- a/sources/queued-server/src/QueuedTcpServerResponseHelperPlugins.cpp +++ b/sources/queued-server/src/QueuedTcpServerResponseHelperPlugins.cpp @@ -28,8 +28,7 @@ QueuedTcpServerResponseHelperPlugins::addPlugin(const QString &_name, auto res = QueuedCoreAdaptor::sendPluginAdd(_name, _token); QVariantHash output; - Result::match( - res, + res.match( [&output](const bool) { output = {{"code", 200}}; }, @@ -47,8 +46,7 @@ QVariantHash QueuedTcpServerResponseHelperPlugins::listPlugins() = QueuedCoreAdaptor::getOption(QueuedConfig::QueuedSettings::Plugins); QVariantHash output; - Result::match( - res, + res.match( [&output](const QVariant &val) { output = {{"code", 200}, {"plugins", val.toStringList()}}; }, @@ -69,8 +67,7 @@ QueuedTcpServerResponseHelperPlugins::removePlugin(const QString &_name, auto res = QueuedCoreAdaptor::sendPluginRemove(_name, _token); QVariantHash output; - Result::match( - res, + res.match( [&output](const bool) { output = {{"code", 200}}; }, diff --git a/sources/queued-server/src/QueuedTcpServerResponseHelperTask.cpp b/sources/queued-server/src/QueuedTcpServerResponseHelperTask.cpp index 114deca..135960c 100644 --- a/sources/queued-server/src/QueuedTcpServerResponseHelperTask.cpp +++ b/sources/queued-server/src/QueuedTcpServerResponseHelperTask.cpp @@ -30,8 +30,7 @@ QVariantHash QueuedTcpServerResponseHelperTask::addOrEditTask( if (_id > 0) { // edit existing task auto res = QueuedCoreAdaptor::sendTaskEdit(_id, defs, _token); - Result::match( - res, + res.match( [&output](const bool val) { output = {{"code", val ? 200 : 500}}; }, @@ -41,8 +40,7 @@ QVariantHash QueuedTcpServerResponseHelperTask::addOrEditTask( } else { // add new task auto res = QueuedCoreAdaptor::sendTaskAdd(defs, _token); - Result::match( - res, + res.match( [&output](const long long val) { output = {{"code", val ? 200 : 500}, {"id", val}}; }, @@ -98,16 +96,14 @@ QueuedTcpServerResponseHelperTask::getTask(const long long _id, QVariantHash output = {{"code", 200}}; if (property.isEmpty()) { auto res = QueuedCoreAdaptor::getTask(_id); - Result::match( - res, + res.match( [&output](const QVariantHash &val) { output["properties"] = val; }, [&output](const QueuedError &err) { output = {{"code", 500}, {"message", err.message().c_str()}}; }); } else { auto res = QueuedCoreAdaptor::getTask(_id, property); - Result::match( - res, + res.match( [&output, &property](const QVariant &val) { output["properties"] = {{property, val}}; }, @@ -136,8 +132,7 @@ QueuedTcpServerResponseHelperTask::getTasks(const QVariantHash &_data, // some conversion magic QVariantList outputReport; auto res = QueuedCoreAdaptor::getTasks(userId, start, stop, _token); - Result::match( - res, + res.match( [&output, &outputReport](const QList &val) { for (auto &user : val) outputReport += user; @@ -160,8 +155,7 @@ QueuedTcpServerResponseHelperTask::startOrStopTask(const long long _id, auto res = QueuedCoreAdaptor::getTask(_id); QVariantHash output; - Result::match( - res, + res.match( [&output, &_id, &_token](const QVariantHash &val) { if (val["startTime"].toString().isEmpty() || !val["endTime"].toString().isEmpty()) @@ -185,8 +179,7 @@ QVariantHash QueuedTcpServerResponseHelperTask::startTask(const long long _id, auto res = QueuedCoreAdaptor::sendTaskStart(_id, _token); QVariantHash output; - Result::match( - res, + res.match( [&output](const bool val) { output = {{"code", val ? 200 : 500}}; }, @@ -206,8 +199,7 @@ QVariantHash QueuedTcpServerResponseHelperTask::stopTask(const long long _id, auto res = QueuedCoreAdaptor::sendTaskStop(_id, _token); QVariantHash output; - Result::match( - res, + res.match( [&output](const bool val) { output = {{"code", val ? 200 : 500}}; }, diff --git a/sources/queued-server/src/QueuedTcpServerResponseHelperUser.cpp b/sources/queued-server/src/QueuedTcpServerResponseHelperUser.cpp index 8583927..7ebdfb2 100644 --- a/sources/queued-server/src/QueuedTcpServerResponseHelperUser.cpp +++ b/sources/queued-server/src/QueuedTcpServerResponseHelperUser.cpp @@ -27,8 +27,8 @@ QVariantHash QueuedTcpServerResponseHelperUser::addOrEditUser( // try define if user exists first auto userIdRes = QueuedCoreAdaptor::getUserId(_user); long long userId = -1; - Result::match(userIdRes, [&userId](const long long val) { userId = val; }, - [&userId](const QueuedError &) {}); + userIdRes.match([&userId](const long long val) { userId = val; }, + [&userId](const QueuedError &) {}); auto defs = getDefinitions(_data); defs.name = _user; @@ -37,8 +37,7 @@ QVariantHash QueuedTcpServerResponseHelperUser::addOrEditUser( if (userId > 0) { // edit existing user auto res = QueuedCoreAdaptor::sendUserEdit(userId, defs, _token); - Result::match( - res, + res.match( [&output](const bool val) { output = {{"code", val ? 200 : 500}}; }, @@ -48,8 +47,7 @@ QVariantHash QueuedTcpServerResponseHelperUser::addOrEditUser( } else { // add new user auto res = QueuedCoreAdaptor::sendUserAdd(defs, _token); - Result::match( - res, + res.match( [&output](const long long val) { output = {{"code", val ? 200 : 500}, {"id", val}}; }, @@ -69,10 +67,10 @@ QueuedTcpServerResponseHelperUser::getDefinitions(const QVariantHash &_data) QueuedUser::QueuedUserDefinitions defs; defs.email = _data["email"].toString(); - auto res = QueuedCoreAdaptor::sendPasswordHash(_data["password"].toString()); - Result::match( - res, [&defs](const QString &val) { defs.password = val; }, - [](const QueuedError &) {}); + auto res + = QueuedCoreAdaptor::sendPasswordHash(_data["password"].toString()); + res.match([&defs](const QString &val) { defs.password = val; }, + [](const QueuedError &) {}); defs.permissions = _data["permissions"].toUInt(); // limits QueuedLimits::Limits limits; @@ -102,8 +100,7 @@ QueuedTcpServerResponseHelperUser::getReport(const QVariantHash &_data, // some conversion magic QVariantList outputReport; auto res = QueuedCoreAdaptor::getPerformance(start, stop, _token); - Result::match( - res, + res.match( [&output, &outputReport](const QList &val) { for (auto &user : val) outputReport += user; @@ -125,8 +122,8 @@ QueuedTcpServerResponseHelperUser::getUser(const QString &_user, auto userIdRes = QueuedCoreAdaptor::getUserId(_user); long long userId = -1; - Result::match(userIdRes, [&userId](const long long val) { userId = val; }, - [](const QueuedError &) {}); + userIdRes.match([&userId](const long long val) { userId = val; }, + [](const QueuedError &) {}); if (userId == -1) return {{"code", 500}}; @@ -135,16 +132,14 @@ QueuedTcpServerResponseHelperUser::getUser(const QString &_user, QVariantHash output = {{"code", 200}}; if (property.isEmpty()) { auto res = QueuedCoreAdaptor::getUser(userId); - Result::match( - res, + res.match( [&output](const QVariantHash &val) { output["properties"] = val; }, [&output](const QueuedError &err) { output = {{"code", 500}, {"message", err.message().c_str()}}; }); } else { auto res = QueuedCoreAdaptor::getUser(userId, property); - Result::match( - res, + res.match( [&output, &property](const QVariant &val) { output["properties"] = {{property, val}}; }, @@ -172,8 +167,7 @@ QueuedTcpServerResponseHelperUser::getUsers(const QVariantHash &_data, // some conversion magic QVariantList outputReport; auto res = QueuedCoreAdaptor::getUsers(lastLogin, permission, _token); - Result::match( - res, + res.match( [&output, &outputReport](const QList &val) { for (auto &user : val) outputReport += user; diff --git a/sources/queued/include/queued/QueuedCore.h b/sources/queued/include/queued/QueuedCore.h index 1a63cdf..ffc0eee 100644 --- a/sources/queued/include/queued/QueuedCore.h +++ b/sources/queued/include/queued/QueuedCore.h @@ -29,20 +29,11 @@ #include "QueuedEnums.h" #include "QueuedLimits.h" #include "QueuedResult.h" -#include "QueuedStaticConfig.h" -class QueuedAdvancedSettings; -class QueuedDatabase; -class QueuedDatabaseManager; -class QueuedPluginManager; +class QueuedCorePrivate; class QueuedProcess; -class QueuedProcessManager; -class QueuedReportManager; -class QueuedSettings; -class QueuedTokenManager; class QueuedUser; -class QueuedUserManager; /** * @brief aggregator of queued classes @@ -314,222 +305,16 @@ public: */ void init(const QString &_configuration); -private slots: - /** - * @brief notify clients about settings update - * @param _id - * updated key id - * @param _key - * updated key - * @param _value - * new value - */ - void updateSettings(const QueuedConfig::QueuedSettings _id, - const QString &_key, const QVariant &_value); - /** - * @brief update process time - * @param _id - * task id - * @param _startTime - * task start time or empty - * @param _endTime - * task end time or empty - */ - void updateTaskTime(const long long _id, const QDateTime &_startTime, - const QDateTime &_endTime); - /** - * @brief update user login time - * @param _id - * user ID - * @param _time - * user login time - */ - void updateUserLoginTime(const long long _id, const QDateTime &_time); - private: /** - * @brief pointer to advanced settings object + * @brief pointer to private implementation */ - QueuedAdvancedSettings *m_advancedSettings = nullptr; - /** - * @brief pointer to database object - */ - QueuedDatabase *m_database = nullptr; - /** - * @brief pointer to database manager object - */ - QueuedDatabaseManager *m_databaseManager = nullptr; - /** - * @brief pointer to plugin manager - */ - QueuedPluginManager *m_plugins = nullptr; - /** - * @brief pointer to process manager - */ - QueuedProcessManager *m_processes = nullptr; - /** - * @brief pointer to report manager - */ - QueuedReportManager *m_reports = nullptr; - /** - * @brief pointer to settings object - */ - QueuedSettings *m_settings = nullptr; - /** - * @brief pointer to user manager - */ - QueuedUserManager *m_users = nullptr; - // additional properties - /** - * @brief connection list - */ - QList 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); + QueuedCorePrivate *m_impl = nullptr; /** * @brief init DBus interface * @throw QueuedDBusException */ void initDBus(); - /** - * @brief method allows to init class if it was not created - * @tparam T - * class name - * @tparam Args - * class constructor arguments - * @param _dest - * pointer to destination - * @param _args - * class constructor arguments - */ - template T *initObject(T *_dest, Args... _args) - { - return _dest ? _dest : new T(this, _args...); - }; - /** - * @brief init plugins - */ - void initPlugins(); - /** - * @brief init processes - */ - void initProcesses(); - /** - * @brief init settings and database - * @param _configuration - * path to configuration file - * @throw QueuedDatabaseException - */ - void initSettings(const QString &_configuration); - /** - * @brief init users - */ - void initUsers(); - // private interfaces - /** - * @brief add new task - * @param _command - * command line - * @param _arguments - * command arguments - * @param _workingDirectory - * working directory - * @param _userId - * task owner user ID - * @param _limits - * task defined limits - * @return task ID or -1 if no task added - */ - QueuedResult addTaskPrivate(const QString &_command, - const QStringList &_arguments, - const QString &_workingDirectory, - const long long _userId, - const QueuedLimits::Limits &_limits); - /** - * @brief add new user - * @param _name - * user name - * @param _email - * user email - * @param _password - * user password - * @param _permissions - * user permissions - * @param _limits - * user limits - * @return user ID or -1 if no user found - */ - QueuedResult addUserPrivate(const QString &_name, - const QString &_email, - const QString &_password, - const uint _permissions, - const QueuedLimits::Limits &_limits); - /** - * @brief edit advanced settings - * @param _key - * advanced settings key - * @param _value - * advanced settings value - * @return true on successful option edition - */ - QueuedResult editOptionPrivate(const QString &_key, - const QVariant &_value); - /** - * @brief edit plugin list - * @param _plugin - * plugin name - * @param add - * true if it requires add plugin - * @return true on successful action - */ - QueuedResult editPluginPrivate(const QString &_plugin, - const bool _add); - /** - * @brief edit task - * @param _id - * task ID to edit - * @param _taskData - * task data to edit - * @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 - */ - QueuedResult editTaskPrivate(const long long _id, - const QVariantHash &_taskData); - /** - * @brief edit user - * @param _id - * user ID to edit - * @param _userData - * user data to edit - * @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 - */ - QueuedResult editUserPrivate(const long long _id, - const QVariantHash &_userData); - /** - * @brief edit user permissions - * @param _id - * user ID to edit - * @param _permission - * permission to add or remove - * @param _add - * indicates whether it should be added or removed - * @return true on successful user permission edition - */ - QueuedResult - editUserPermissionPrivate(const long long _id, - const QueuedEnums::Permission &_permission, - const bool _add); }; diff --git a/sources/queued/include/queued/QueuedProcess.h b/sources/queued/include/queued/QueuedProcess.h index e821e82..b955d78 100644 --- a/sources/queued/include/queued/QueuedProcess.h +++ b/sources/queued/include/queued/QueuedProcess.h @@ -94,14 +94,14 @@ public: /** * @brief QueuedProcess class constructor - * @param parent + * @param _parent * pointer to parent item * @param definitions * definitions of process * @param index * index of process */ - explicit QueuedProcess(QObject *parent, + explicit QueuedProcess(QObject *_parent, const QueuedProcessDefinitions &definitions, const long long index); /** diff --git a/sources/queued/include/queued/QueuedReportManager.h b/sources/queued/include/queued/QueuedReportManager.h index adb036d..6fde6c0 100644 --- a/sources/queued/include/queued/QueuedReportManager.h +++ b/sources/queued/include/queued/QueuedReportManager.h @@ -43,12 +43,12 @@ class QueuedReportManager : public QObject public: /** * @brief QueuedReportManager class constructor - * @param parent + * @param _parent * pointer to parent item - * @param database + * @param _database * pointer to database object */ - explicit QueuedReportManager(QObject *parent, QueuedDatabase *database); + explicit QueuedReportManager(QObject *_parent, QueuedDatabase *_database); /** * @brief QueuedReportManager class destructor */ diff --git a/sources/queued/include/queued/QueuedTokenManager.h b/sources/queued/include/queued/QueuedTokenManager.h index afc5004..f40b551 100644 --- a/sources/queued/include/queued/QueuedTokenManager.h +++ b/sources/queued/include/queued/QueuedTokenManager.h @@ -54,10 +54,10 @@ public: /** * @brief QueuedTokenManager class constructor - * @param parent + * @param _parent * pointer to parent item */ - explicit QueuedTokenManager(QObject *parent); + explicit QueuedTokenManager(QObject *_parent); /** * @brief QueuedTokenManager class destructor */ diff --git a/sources/queued/include/queued/QueuedUser.h b/sources/queued/include/queued/QueuedUser.h index 2e8c337..dd5b9ad 100644 --- a/sources/queued/include/queued/QueuedUser.h +++ b/sources/queued/include/queued/QueuedUser.h @@ -71,14 +71,14 @@ public: /** * @brief QueuedUser class constructor - * @param parent + * @param _parent * pointer to parent item * @param definitions * definitions of user * @param index * index of process */ - explicit QueuedUser(QObject *parent, + explicit QueuedUser(QObject *_parent, const QueuedUserDefinitions &definitions, const long long index); /** diff --git a/sources/queued/include/queued/private/QueuedCorePrivate.h b/sources/queued/include/queued/private/QueuedCorePrivate.h new file mode 100644 index 0000000..8bfea14 --- /dev/null +++ b/sources/queued/include/queued/private/QueuedCorePrivate.h @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2017 Queued team + * + * 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 QueuedCorePrivate.h + * Header of Queued library + * @author Queued team + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#ifndef QUEUEDCOREPRIVATE_H +#define QUEUEDCOREPRIVATE_H + +#include + +#include "queued/QueuedEnums.h" +#include "queued/QueuedLimits.h" +#include "queued/QueuedResult.h" +#include "queued/QueuedStaticConfig.h" + + +class QueuedAdvancedSettings; +class QueuedCorePrivateHelper; +class QueuedDatabase; +class QueuedDatabaseManager; +class QueuedPluginManager; +class QueuedProcess; +class QueuedProcessManager; +class QueuedReportManager; +class QueuedSettings; +class QueuedUser; +class QueuedUserManager; + +/** + * @brief private aggregator of queued classes + */ +class QueuedCorePrivate : public QObject +{ + Q_OBJECT + +public: + /** + * @brief QueuedCorePrivate class constructor + * @param _parent + * pointer to parent item + */ + explicit QueuedCorePrivate(QObject *_parent); + /** + * @brief QueuedCorePrivate class destructor + */ + virtual ~QueuedCorePrivate(); + /** + * @brief add plugin to autoload and load it now + * @param _plugin + * plugin name + * @param _token + * user auth token + * @return true on successfully addition + */ + QueuedResult addPlugin(const QString &_plugin, const QString &_token); + /** + * @brief add new task + * @param _command + * command line + * @param _arguments + * command arguments + * @param _workingDirectory + * working directory + * @param _userId + * task owner user ID + * @param _limits + * task defined limits + * @param _token + * user auth token + * @return task ID or -1 if no task added + */ + QueuedResult + addTask(const QString &_command, const QStringList &_arguments, + const QString &_workingDirectory, const long long _userId, + const QueuedLimits::Limits &_limits, const QString &_token); + /** + * @brief add new user + * @param _name + * user name + * @param _email + * user email + * @param _password + * user password + * @param _permissions + * user permissions + * @param _limits + * user limits + * @param _token + * user auth token + * @return user ID or -1 if no user created + */ + QueuedResult addUser(const QString &_name, const QString &_email, + const QString &_password, + const uint _permissions, + const QueuedLimits::Limits &_limits, + const QString &_token); + /** + * @brief try to authorize by given token + * @param _token + * token ID + * @return true if token is valid + */ + QueuedResult authorization(const QString &_token); + /** + * @brief authorize and create new token for user + * @param _name + * user name + * @param _password + * user password + * @return token. It will be empty if authorization error occurs + */ + QueuedResult authorization(const QString &_name, + const QString &_password); + /** + * @brief edit advanced settings + * @param _key + * advanced settings key + * @param _value + * advanced settings value + * @param _token + * user auth token + * @return true on successful option edition + */ + QueuedResult editOption(const QString &_key, const QVariant &_value, + const QString &_token); + /** + * @brief edit task + * @param _id + * task ID to edit + * @param _taskData + * task data to edit + * @param _token + * user auth token + * @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 + */ + QueuedResult editTask(const long long _id, + const QVariantHash &_taskData, + const QString &_token); + /** + * @brief edit user + * @param _id + * user ID to edit + * @param _userData + * user data to edit + * @param _token + * user auth token + * @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 + */ + QueuedResult editUser(const long long _id, + const QVariantHash &_userData, + const QString &_token); + /** + * @brief edit user permissions + * @param _id + * user ID to edit + * @param _permission + * permission to add or remove + * @param _add + * indicates whether it should be added or removed + * @param _token + * user auth token + * @return true on successful user permission edition + */ + QueuedResult + editUserPermission(const long long _id, + const QueuedEnums::Permission &_permission, + const bool _add, const QString &_token); + /** + * @brief hash password + * @param _password + * user password as plain text + * @return hashed password with applied salt + */ + QueuedResult hashFromPassword(const QString &_password); + /** + * @brief get value from advanced settings + * @param _key + * key string + * @return option value or empty QVariant + */ + QueuedResult option(const QString &_key); + /** + * @brief usage report + * @param _from + * start report date + * @param _to + * stop report date + * @param _token + * user auth token + * @return performance table + */ + QueuedResult> + performanceReport(const QDateTime &_from, const QDateTime &_to, + const QString &_token) const; + /** + * @brief get plugin settings + * @param _plugin + * plugin name + * @return hash of plugin settings + */ + QVariantHash pluginSettings(const QString &_plugin); + /** + * @brief remove plugin from autoload and unload it now + * @param _plugin + * plugin name + * @param _token + * user auth token + * @return true on successful plugin removal + */ + QueuedResult removePlugin(const QString &_plugin, + const QString &_token); + /** + * @brief force start task + * @param _id + * task ID + * @param _token + * user auth token + * @return true on successful task start + */ + QueuedResult startTask(const long long _id, const QString &_token); + /** + * @brief force stop task + * @param _id + * task ID + * @param _token + * user auth token + * @return true on successful task stop + */ + QueuedResult stopTask(const long long _id, const QString &_token); + /** + * @brief get task by ID + * @param _id + * task ID + * @return task object or nullptr if no task found + */ + const QueuedProcess *task(const long long _id) const; + /** + * list of tasks which match criteria + * @param _user + * task user ID filter + * @param _from + * minimal start time + * @param _to + * maximal end time + * @param _token + * user auth token + * @return list of tasks in database format + */ + QueuedResult> taskReport(const long long _user, + const QDateTime &_from, + const QDateTime &_to, + const QString &_token) const; + /** + * @brief get user by ID + * @param _id + * user ID + * @return user object or nullptr if no user found + */ + const QueuedUser *user(const long long _id) const; + /** + * @brief get user by name + * @param _name + * user name + * @return user object or nullptr if no user found + */ + const QueuedUser *user(const QString &_name) const; + /** + * list of users which match criteria + * @param _lastLogged + * last logged minimal date + * @param _permission + * user permission filter + * @param _token + * user auth token + * @return list of users in database format + */ + QueuedResult> + userReport(const QDateTime &_lastLogged, + const QueuedEnums::Permission _permission, + const QString &_token) const; + // control methods + /** + * @brief deinit subclasses + */ + void deinit(); + /** + * @brief init subclasses + * @param _configuration + * path to configuration file + * @throw QueuedDatabaseException + * @throw QueuedDBusException + */ + void init(const QString &_configuration); + +private slots: + /** + * @brief notify clients about settings update + * @param _id + * updated key id + * @param _key + * updated key + * @param _value + * new value + */ + void updateSettings(const QueuedConfig::QueuedSettings _id, + const QString &_key, const QVariant &_value); + /** + * @brief update process time + * @param _id + * task id + * @param _startTime + * task start time or empty + * @param _endTime + * task end time or empty + */ + void updateTaskTime(const long long _id, const QDateTime &_startTime, + const QDateTime &_endTime); + /** + * @brief update user login time + * @param _id + * user ID + * @param _time + * user login time + */ + void updateUserLoginTime(const long long _id, const QDateTime &_time); + +private: + /** + * @brief private helper pointer + */ + friend class QueuedCorePrivateHelper; + QueuedCorePrivateHelper *m_helper = nullptr; + /** + * @brief pointer to advanced settings object + */ + QueuedAdvancedSettings *m_advancedSettings = nullptr; + /** + * @brief pointer to database object + */ + QueuedDatabase *m_database = nullptr; + /** + * @brief pointer to database manager object + */ + QueuedDatabaseManager *m_databaseManager = nullptr; + /** + * @brief pointer to plugin manager + */ + QueuedPluginManager *m_plugins = nullptr; + /** + * @brief pointer to process manager + */ + QueuedProcessManager *m_processes = nullptr; + /** + * @brief pointer to report manager + */ + QueuedReportManager *m_reports = nullptr; + /** + * @brief pointer to settings object + */ + QueuedSettings *m_settings = nullptr; + /** + * @brief pointer to user manager + */ + QueuedUserManager *m_users = nullptr; + // additional properties + /** + * @brief connection list + */ + QList m_connections; + /** + * @brief init plugins + */ + void initPlugins(); + /** + * @brief init processes + */ + void initProcesses(); + /** + * @brief init settings and database + * @param _configuration + * path to configuration file + * @throw QueuedDatabaseException + */ + void initSettings(const QString &_configuration); + /** + * @brief init users + */ + void initUsers(); +}; + + +#endif /* QUEUEDCOREPRIVATE_H */ diff --git a/sources/queued/include/queued/private/QueuedCorePrivateHelper.h b/sources/queued/include/queued/private/QueuedCorePrivateHelper.h new file mode 100644 index 0000000..55d480b --- /dev/null +++ b/sources/queued/include/queued/private/QueuedCorePrivateHelper.h @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2017 Queued team + * + * 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 QueuedCorePrivateHelper.h + * Header of Queued library + * @author Queued team + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#ifndef QUEUEDCOREPRIVATEHELPER_H +#define QUEUEDCOREPRIVATEHELPER_H + +#include + +#include "queued/QueuedEnums.h" +#include "queued/QueuedLimits.h" +#include "queued/QueuedResult.h" + + +class QueuedAdvancedSettings; +class QueuedCorePrivate; +class QueuedDatabase; +class QueuedPluginManager; +class QueuedProcessManager; +class QueuedUserManager; + +/** + * @brief helper for private core class + */ +class QueuedCorePrivateHelper : public QObject +{ + Q_OBJECT + +public: + /** + * @brief QueuedCorePrivateHelper class constructor + * @param _parent + * pointer to parent item + */ + explicit QueuedCorePrivateHelper(QObject *_parent); + /** + * @brief QueuedCorePrivateHelper class destructor + */ + virtual ~QueuedCorePrivateHelper(); + +private: + // interfaces + friend class QueuedCorePrivate; + QueuedCorePrivate *m_core = nullptr; + /** + * @brief pointer to advanced settings object + * @return pointer to advanced settings object + */ + QueuedAdvancedSettings *advancedSettings(); + /** + * @brief pointer to database object + * @return pointer to database object + */ + QueuedDatabase *database(); + /** + * @brief pointer to plugin manager + * @return pointer to plugin manager + */ + QueuedPluginManager *plugins(); + /** + * @brief pointer to process manager + * @return pointer to process manager + */ + QueuedProcessManager *processes(); + /** + * @brief pointer to user manager + * @return pointer to user manager + */ + QueuedUserManager *users(); + + /** + * @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 method allows to init class if it was not created + * @tparam T + * class name + * @tparam Args + * class constructor arguments + * @param _parent + * pointer to parent object of destination object + * @param _dest + * pointer to destination + * @param _args + * class constructor arguments + */ + template T *initObject(T *_dest, Args... _args) + { + return _dest ? _dest : new T(m_core, _args...); + }; + // private interfaces + /** + * @brief add new task + * @param _command + * command line + * @param _arguments + * command arguments + * @param _workingDirectory + * working directory + * @param _userId + * task owner user ID + * @param _limits + * task defined limits + * @return task ID or -1 if no task added + */ + QueuedResult addTaskPrivate(const QString &_command, + const QStringList &_arguments, + const QString &_workingDirectory, + const long long _userId, + const QueuedLimits::Limits &_limits); + /** + * @brief add new user + * @param _name + * user name + * @param _email + * user email + * @param _password + * user password + * @param _permissions + * user permissions + * @param _limits + * user limits + * @return user ID or -1 if no user found + */ + QueuedResult addUserPrivate(const QString &_name, + const QString &_email, + const QString &_password, + const uint _permissions, + const QueuedLimits::Limits &_limits); + /** + * @brief edit advanced settings + * @param _key + * advanced settings key + * @param _value + * advanced settings value + * @return true on successful option edition + */ + QueuedResult editOptionPrivate(const QString &_key, + const QVariant &_value); + /** + * @brief edit plugin list + * @param _plugin + * plugin name + * @param add + * true if it requires add plugin + * @return true on successful action + */ + QueuedResult editPluginPrivate(const QString &_plugin, + const bool _add); + /** + * @brief edit task + * @param _id + * task ID to edit + * @param _taskData + * task data to edit + * @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 + */ + QueuedResult editTaskPrivate(const long long _id, + const QVariantHash &_taskData); + /** + * @brief edit user + * @param _id + * user ID to edit + * @param _userData + * user data to edit + * @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 + */ + QueuedResult editUserPrivate(const long long _id, + const QVariantHash &_userData); + /** + * @brief edit user permissions + * @param _id + * user ID to edit + * @param _permission + * permission to add or remove + * @param _add + * indicates whether it should be added or removed + * @return true on successful user permission edition + */ + QueuedResult + editUserPermissionPrivate(const long long _id, + const QueuedEnums::Permission &_permission, + const bool _add); +}; + + +#endif /* QUEUEDCOREPRIVATEHELPER_H */ diff --git a/sources/queued/src/QueuedCore.cpp b/sources/queued/src/QueuedCore.cpp index 2a51165..44b0e28 100644 --- a/sources/queued/src/QueuedCore.cpp +++ b/sources/queued/src/QueuedCore.cpp @@ -23,13 +23,7 @@ #include -#include -#include -#include - -#include "../../3rdparty/result/result.hpp" -#include -#include +#include /** @@ -42,6 +36,8 @@ QueuedCore::QueuedCore(QObject *_parent) : QObject(_parent) { qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; + + m_impl = new QueuedCorePrivate(this); } @@ -53,6 +49,7 @@ QueuedCore::~QueuedCore() qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; deinit(); + m_impl->deleteLater(); } @@ -64,14 +61,7 @@ QueuedResult QueuedCore::addPlugin(const QString &_plugin, { qCDebug(LOG_LIB) << "Add plugin" << _plugin; - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to add plugin"; - return QueuedError("Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - - return editPluginPrivate(_plugin, true); + return m_impl->addPlugin(_plugin, _token); } @@ -86,38 +76,8 @@ QueuedCore::addTask(const QString &_command, const QStringList &_arguments, qCDebug(LOG_LIB) << "Add task" << _command << "with arguments" << _arguments << "from user" << _userId; - auto authUser = m_users->user(_token, true); - if (!authUser) { - qCWarning(LOG_LIB) << "Could not find auth user" << _token; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - long long userAuthId = authUser->index(); - long long actualUserId = (_userId == -1) ? userAuthId : _userId; - - // check permissions - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - bool isUser = m_users->authorize(_token, QueuedEnums::Permission::Job); - if (userAuthId == actualUserId) { - // it means that user places task as own one - if (!isUser) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to add task"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } else { - // user tries to place task as another one - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to add task"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } - - return addTaskPrivate(_command, _arguments, _workingDirectory, _userId, - _limits); + return m_impl->addTask(_command, _arguments, _workingDirectory, _userId, + _limits, _token); } @@ -132,23 +92,8 @@ QueuedCore::addUser(const QString &_name, const QString &_email, qCDebug(LOG_LIB) << "Add user" << _name << "with email" << _email << "and permissions" << _permissions; - // check permissions - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to add user"; - return QueuedError("Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - - // check if already exists - auto userObj = user(_name); - if (userObj) { - qCWarning(LOG_LIB) << "User" << _name << "already exists"; - return QueuedError("User already exists", - QueuedEnums::ReturnStatus::InvalidArgument); - } - - return addUserPrivate(_name, _email, _password, _permissions, _limits); + return m_impl->addUser(_name, _email, _password, _permissions, _limits, + _token); } @@ -157,10 +102,7 @@ QueuedCore::addUser(const QString &_name, const QString &_email, */ QueuedResult QueuedCore::authorization(const QString &_token) { - bool status = false; - m_users->checkToken(_token, &status); - - return status; + return m_impl->authorization(_token); } @@ -172,19 +114,7 @@ QueuedResult QueuedCore::authorization(const QString &_name, { qCDebug(LOG_LIB) << "Authorize user" << _name; - QString token = m_users->authorize(_name, _password); - if (token.isEmpty()) { - return QueuedError("Invalid username or password", - QueuedEnums::ReturnStatus::InvalidPassword); - } else { - QVariantHash payload - = {{"token", token}, - {"user", _name}, - {"validUntil", - m_users->checkToken(token).toString(Qt::ISODateWithMs)}}; - m_database->add(QueuedDB::TOKENS_TABLE, payload); - return token; - } + return m_impl->authorization(_name, _password); } @@ -197,15 +127,7 @@ QueuedResult QueuedCore::editOption(const QString &_key, { qCDebug(LOG_LIB) << "Set key" << _key << "to" << _value; - // check permissions - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit options"; - return QueuedError("Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - - return editOptionPrivate(_key, _value); + return m_impl->editOption(_key, _value, _token); } @@ -218,57 +140,7 @@ QueuedResult QueuedCore::editTask(const long long _id, { qCDebug(LOG_LIB) << "Edit task with ID" << _id; - auto task = m_processes->process(_id); - if (!task) { - qCWarning(LOG_LIB) << "Could not find task with ID" << _id; - return QueuedError("Task does not exist", - QueuedEnums::ReturnStatus::InvalidArgument); - } - - // check permissions - auto authUser = m_users->user(_token, true); - if (!authUser) { - qCWarning(LOG_LIB) << "Could not find auth user" << _token; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - long long userAuthId = authUser->index(); - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - bool isUser = m_users->authorize(_token, QueuedEnums::Permission::Job); - if (userAuthId == task->user()) { - // it means that user edits own task - if (!isUser) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit task"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } else { - // user tries to edit random task - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit task"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } - // only admin can edit run/stopped task - if (!task->startTime().isNull()) { - if (!isAdmin) { - qCInfo(LOG_LIB) - << "User" << _token << "not allowed to edit run/exited task"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } - - // drop admin fields - QVariantHash payload - = isAdmin ? _taskData - : dropAdminFields(QueuedDB::TASKS_TABLE, _taskData); - - return editTaskPrivate(_id, payload); + return m_impl->editTask(_id, _taskData, _token); } @@ -281,37 +153,7 @@ QueuedResult QueuedCore::editUser(const long long _id, { qCDebug(LOG_LIB) << "Edit user with ID" << _id; - auto userObj = user(_id); - if (!userObj) { - qCWarning(LOG_LIB) << "Could not find user with ID" << _id; - return QueuedError("User does not exist", - QueuedEnums::ReturnStatus::InvalidArgument); - } - - // check permissions - auto authUser = m_users->user(_token, true); - if (!authUser) { - qCWarning(LOG_LIB) << "Could not find auth user" << _token; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - long long userAuthId = authUser->index(); - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - if (userAuthId != _id) { - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit user"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } - - // drop admin fields - QVariantHash payload - = isAdmin ? _userData - : dropAdminFields(QueuedDB::USERS_TABLE, _userData); - - return editUserPrivate(_id, payload); + return m_impl->editUser(_id, _userData, _token); } @@ -326,16 +168,7 @@ QueuedCore::editUserPermission(const long long _id, qCDebug(LOG_LIB) << "Edit permissions" << static_cast(_permission) << "for user" << _id << "add" << _add; - // check permissions - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token - << "not allowed to edit permissions"; - return QueuedError("Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - - return editUserPermissionPrivate(_id, _permission, _add); + return m_impl->editUserPermission(_id, _permission, _add, _token); } @@ -344,9 +177,7 @@ QueuedCore::editUserPermission(const long long _id, */ QueuedResult QueuedCore::hashFromPassword(const QString &_password) { - return _password.isEmpty() ? "" - : QueuedUser::hashFromPassword( - _password, m_settings->admin().salt); + return m_impl->hashFromPassword(_password); } @@ -357,7 +188,7 @@ QueuedResult QueuedCore::option(const QString &_key) { qCDebug(LOG_LIB) << "Look for option" << _key; - return m_advancedSettings->get(_key); + return m_impl->option(_key); } @@ -370,28 +201,7 @@ QueuedCore::performanceReport(const QDateTime &_from, const QDateTime &_to, { qCDebug(LOG_LIB) << "Get performance report for" << _from << _to; - // check permissions - auto authUser = m_users->user(_token, true); - if (!authUser) { - qCWarning(LOG_LIB) << "Could not find auth user" << _token; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - long long userAuthId = authUser->index(); - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); - - if (isAdmin) { - return m_reports->performance(this, _from, _to); - } else { - auto data = m_reports->performance(this, _from, _to); - QList output; - for (auto &userData : data) { - if (userData["_id"].toLongLong() != userAuthId) - continue; - output.append(userData); - } - return output; - } + return m_impl->performanceReport(_from, _to, _token); } @@ -402,16 +212,7 @@ QVariantHash QueuedCore::pluginSettings(const QString &_plugin) { qCDebug(LOG_LIB) << "Get plugin settings for" << _plugin; - auto dbSettings - = m_database->get(QueuedDB::SETTINGS_TABLE, - QString("WHERE key LIKE 'Plugin.%1.%'").arg(_plugin)); - QVariantHash settings; - std::for_each(dbSettings.cbegin(), dbSettings.cend(), - [&settings](const QVariantHash &value) { - settings[value["key"].toString()] = value["value"]; - }); - - return settings; + return m_impl->pluginSettings(_plugin); } @@ -423,14 +224,7 @@ QueuedResult QueuedCore::removePlugin(const QString &_plugin, { qCDebug(LOG_LIB) << "Remove plugin" << _plugin; - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to remove plugin"; - return QueuedError("Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - - return editPluginPrivate(_plugin, false); + return m_impl->removePlugin(_plugin, _token); } @@ -442,27 +236,7 @@ QueuedResult QueuedCore::startTask(const long long _id, { qCDebug(LOG_LIB) << "Force start task with ID" << _id; - // check permissions - auto authUser = m_users->user(_token, true); - if (!authUser) { - qCWarning(LOG_LIB) << "Could not find auth user" << _token; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - long long userAuthId = authUser->index(); - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - if (userAuthId != _id) { - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to start tasks"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } - - m_processes->start(_id); - - return true; + return m_impl->startTask(_id, _token); } @@ -474,44 +248,7 @@ QueuedResult QueuedCore::stopTask(const long long _id, { 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 QueuedError("Task does not exist", - QueuedEnums::ReturnStatus::InvalidArgument); - } - - // check permissions - auto authUser = m_users->user(_token, true); - if (!authUser) { - qCWarning(LOG_LIB) << "Could not find auth user" << _token; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - long long userAuthId = authUser->index(); - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); - bool isUser = m_users->authorize(_token, QueuedEnums::Permission::Job); - if (userAuthId == task->user()) { - // it means that user edits own task - if (!isUser) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to stop task"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } else { - // user tries to edit random task - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to stop task"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } - - m_processes->stop(_id); - - return true; + return m_impl->stopTask(_id, _token); } @@ -522,7 +259,7 @@ const QueuedProcess *QueuedCore::task(const long long _id) const { qCDebug(LOG_LIB) << "Get task by ID" << _id; - return m_processes->process(_id); + return m_impl->task(_id); } @@ -535,29 +272,7 @@ QueuedCore::taskReport(const long long _user, const QDateTime &_from, { qCDebug(LOG_LIB) << "Get tasks table by" << _user << _from << _to; - // check permissions - auto authUser = m_users->user(_token, true); - if (!authUser) { - qCWarning(LOG_LIB) << "Could not find auth user" << _token; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - long long userAuthId = authUser->index(); - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); - long long effectiveUserId = _user; - if (_user == -1) { - effectiveUserId = userAuthId; - } else if (userAuthId != _user) { - if (!isAdmin) { - qCInfo(LOG_LIB) - << "User" << _token << "not allowed to get task report"; - return QueuedError( - "Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - } - - return m_reports->tasks(effectiveUserId, _from, _to); + return m_impl->taskReport(_user, _from, _to, _token); } @@ -568,7 +283,7 @@ const QueuedUser *QueuedCore::user(const long long _id) const { qCDebug(LOG_LIB) << "Get user by ID" << _id; - return m_users->user(_id); + return m_impl->user(_id); } @@ -579,7 +294,7 @@ const QueuedUser *QueuedCore::user(const QString &_name) const { qCDebug(LOG_LIB) << "Get user by name" << _name; - return m_users->user(_name, false); + return m_impl->user(_name); } @@ -594,15 +309,7 @@ QueuedCore::userReport(const QDateTime &_lastLogged, qCDebug(LOG_LIB) << "Get users table by" << _lastLogged << static_cast(_permission); - // check permissions - bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); - if (!isAdmin) { - qCInfo(LOG_LIB) << "User" << _token << "not allowed to get user report"; - return QueuedError("Not allowed", - QueuedEnums::ReturnStatus::InsufficientPermissions); - } - - return m_reports->users(_lastLogged, _permission); + return m_impl->userReport(_lastLogged, _permission, _token); } @@ -611,10 +318,7 @@ QueuedCore::userReport(const QDateTime &_lastLogged, */ void QueuedCore::deinit() { - // clear connections first - for (auto &connection : m_connections) - disconnect(connection); - m_connections.clear(); + m_impl->deinit(); // dbus cleanup QDBusConnection::systemBus().unregisterObject( @@ -634,146 +338,10 @@ void QueuedCore::init(const QString &_configuration) { qCDebug(LOG_LIB) << "Load configuration from" << _configuration; - // deinit objects if any - deinit(); - - // init parts - initSettings(_configuration); - initUsers(); - initPlugins(); - initProcesses(); - - // settings update notifier - m_connections - += connect(m_advancedSettings, - SIGNAL(valueUpdated(const QueuedConfig::QueuedSettings, - const QString &, const QVariant &)), - this, - SLOT(updateSettings(const QueuedConfig::QueuedSettings, - const QString &, const QVariant &))); + m_impl->init(_configuration); // dbus session initDBus(); - - // run! - m_processes->start(); -} - - -/** - * @fn updateSettings - */ -void QueuedCore::updateSettings(const QueuedConfig::QueuedSettings _id, - const QString &_key, const QVariant &_value) -{ - qCDebug(LOG_LIB) << "Received update for" << static_cast(_id) << _key - << "with value" << _value; - - // FIXME probably there is a better way to change settings - switch (_id) { - case QueuedConfig::QueuedSettings::Invalid: - // check if it is plugin settings - if (_key.startsWith("Plugin.")) - m_plugins->optionChanged(_key, _value); - // do nothing otherwise - break; - case QueuedConfig::QueuedSettings::DatabaseInterval: - m_databaseManager->setInterval(_value.toLongLong()); - break; - case QueuedConfig::QueuedSettings::DatabaseVersion: - break; - case QueuedConfig::QueuedSettings::DefaultLimits: - break; - case QueuedConfig::QueuedSettings::KeepTasks: - m_databaseManager->setKeepTasks(_value.toLongLong()); - break; - case QueuedConfig::QueuedSettings::KeepUsers: - m_databaseManager->setKeepUsers(_value.toLongLong()); - break; - case QueuedConfig::QueuedSettings::OnExitAction: - m_processes->setExitAction( - static_cast(_value.toInt())); - break; - case QueuedConfig::QueuedSettings::Plugins: - // do nothing here - break; - case QueuedConfig::QueuedSettings::ProcessCommandLine: - m_processes->setProcessLine(_value.toString()); - break; - case QueuedConfig::QueuedSettings::ServerAddress: - case QueuedConfig::QueuedSettings::ServerMaxConnections: - case QueuedConfig::QueuedSettings::ServerPort: - case QueuedConfig::QueuedSettings::ServerTimeout: - // do nothing here - break; - case QueuedConfig::QueuedSettings::TokenExpiration: - m_users->setTokenExpiration(_value.toLongLong()); - break; - } -} - - -/** - * @fn updateTaskTime - */ -void QueuedCore::updateTaskTime(const long long _id, - const QDateTime &_startTime, - const QDateTime &_endTime) -{ - qCDebug(LOG_LIB) << "Update task" << _id << "time to" << _startTime - << _endTime; - - QVariantHash record; - if (_startTime.isValid()) { - record["startTime"] = _startTime.toString(Qt::ISODateWithMs); - if (m_plugins) - emit(m_plugins->interface()->onStartTask(_id)); - } - if (_endTime.isValid()) { - record["endTime"] = _endTime.toString(Qt::ISODateWithMs); - if (m_plugins) - emit(m_plugins->interface()->onStopTask(_id)); - } - - bool status = m_database->modify(QueuedDB::TASKS_TABLE, _id, record); - if (!status) - qCWarning(LOG_LIB) << "Could not modify task record" << _id; -} - - -/** - * @fn updateUserLoginTime - */ -void QueuedCore::updateUserLoginTime(const long long _id, - const QDateTime &_time) -{ - qCDebug(LOG_LIB) << "Update user" << _id << "with login time" << _time; - - QVariantHash record = {{"lastLogin", _time.toString(Qt::ISODateWithMs)}}; - - bool status = m_database->modify(QueuedDB::USERS_TABLE, _id, record); - if (!status) - qCWarning(LOG_LIB) << "Could not modify user record" << _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; } @@ -816,401 +384,3 @@ void QueuedCore::initDBus() throw QueuedDBusException(message); } } - - -/** - * @fn initPlugins - */ -void QueuedCore::initPlugins() -{ - QStringList pluginList - = m_advancedSettings->get(QueuedConfig::QueuedSettings::Plugins) - .toString() - .split('\n'); - QString token = m_users->authorize(m_settings->admin().name); - - m_plugins = initObject(m_plugins, token); - for (auto &plugin : pluginList) - m_plugins->loadPlugin(plugin, pluginSettings(plugin)); -} - - -/** - * @fn initProcesses - */ -void QueuedCore::initProcesses() -{ - // init processes - auto onExitAction = static_cast( - m_advancedSettings->get(QueuedConfig::QueuedSettings::OnExitAction) - .toInt()); - auto processLine - = m_advancedSettings - ->get(QueuedConfig::QueuedSettings::ProcessCommandLine) - .toString(); - - m_processes = initObject(m_processes); - m_processes->setProcessLine(processLine); - m_processes->setExitAction(onExitAction); - auto dbProcesses - = m_database->get(QueuedDB::TASKS_TABLE, "WHERE endTime IS NULL"); - m_processes->loadProcesses(dbProcesses); - - m_connections - += connect(m_processes, &QueuedProcessManager::taskStartTimeReceived, - [this](const long long _index, const QDateTime &_time) { - return updateTaskTime(_index, _time, QDateTime()); - }); - m_connections - += connect(m_processes, &QueuedProcessManager::taskStopTimeReceived, - [this](const long long _index, const QDateTime &_time) { - return updateTaskTime(_index, QDateTime(), _time); - }); -} - - -/** - * @fn initSettings - */ -void QueuedCore::initSettings(const QString &_configuration) -{ - // read configuration first - m_settings = initObject(m_settings, _configuration); - m_settings->readConfiguration(); - // init database now - auto dbSetup = m_settings->db(); - m_database = initObject(m_database, dbSetup.path, dbSetup.driver); - m_database->close(); - bool status = m_database->open(dbSetup.hostname, dbSetup.port, - dbSetup.username, dbSetup.password); - if (!status) { - QString message = "Could not open database"; - qCCritical(LOG_LIB) << message; - throw QueuedDatabaseException(message); - } - - // create administrator if required - auto dbAdmin = m_settings->admin(); - m_database->createAdministrator(dbAdmin.name, dbAdmin.password); - - // and load advanced settings - m_advancedSettings = initObject(m_advancedSettings); - m_advancedSettings->set(m_database->get(QueuedDB::SETTINGS_TABLE)); - if (!m_advancedSettings->checkDatabaseVersion()) { - qCInfo(LOG_LIB) << "Bump database version to" - << QueuedConfig::DATABASE_VERSION; - editOptionPrivate(m_advancedSettings->internalId( - QueuedConfig::QueuedSettings::DatabaseVersion), - QueuedConfig::DATABASE_VERSION); - } - - // report manager - m_reports = initObject(m_reports, m_database); - // database manager - m_databaseManager = initObject(m_databaseManager, m_database); -} - - -/** - * @fn initUsers - */ -void QueuedCore::initUsers() -{ - // load users and tokens - auto expiry - = m_advancedSettings->get(QueuedConfig::QueuedSettings::TokenExpiration) - .toLongLong(); - - m_users = initObject(m_users); - m_users->setSalt(m_settings->admin().salt); - m_users->setTokenExpiration(expiry); - QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs); - auto dbTokens = m_database->get( - QueuedDB::TOKENS_TABLE, - QString("WHERE datetime(validUntil) > datetime('%1')").arg(now)); - m_users->loadTokens(dbTokens); - auto dbUsers = m_database->get(QueuedDB::USERS_TABLE); - m_users->loadUsers(dbUsers); - - m_connections += connect( - m_users, SIGNAL(userLoggedIn(const long long, const QDateTime &)), this, - SLOT(updateUserLoginTime(const long long, const QDateTime &))); -} - - -/** - * @addTaskPrivate - */ -QueuedResult QueuedCore::addTaskPrivate( - const QString &_command, const QStringList &_arguments, - const QString &_workingDirectory, const long long _userId, - const QueuedLimits::Limits &_limits) -{ - qCDebug(LOG_LIB) << "Add task" << _command << "with arguments" << _arguments - << "from user" << _userId; - - // add to database - auto ids = m_users->ids(_userId); - auto userObj = user(_userId); - if (!userObj) { - qCWarning(LOG_LIB) << "Could not find task user" << _userId; - return QueuedError("Invalid token", - QueuedEnums::ReturnStatus::InvalidToken); - } - auto taskLimits = QueuedLimits::minimalLimits( - _limits, userObj->nativeLimits(), - QueuedLimits::Limits( - m_advancedSettings->get(QueuedConfig::QueuedSettings::DefaultLimits) - .toString())); - QVariantHash properties = {{"user", _userId}, - {"command", _command}, - {"commandArguments", _arguments}, - {"workDirectory", _workingDirectory}, - {"nice", 0}, - {"uid", ids.first}, - {"gid", ids.second}, - {"limits", taskLimits.toString()}}; - auto id = m_database->add(QueuedDB::TASKS_TABLE, properties); - if (id == -1) { - qCWarning(LOG_LIB) << "Could not add task" << _command; - return QueuedError("", QueuedEnums::ReturnStatus::Error); - } - - // add to child object - m_processes->add(properties, id); - // notify plugins - if (m_plugins) - emit(m_plugins->interface()->onAddTask(id)); - - return id; -} - - -/** - * @fn addUserPrivate - */ -QueuedResult -QueuedCore::addUserPrivate(const QString &_name, const QString &_email, - const QString &_password, const uint _permissions, - const QueuedLimits::Limits &_limits) -{ - qCDebug(LOG_LIB) << "Add user" << _name << "with email" << _email - << "and permissions" << _permissions; - // add to database - QVariantHash properties = {{"name", _name}, - {"password", _password}, - {"email", _email}, - {"permissions", _permissions}, - {"limits", _limits.toString()}}; - auto id = m_database->add(QueuedDB::USERS_TABLE, properties); - if (id == -1) { - qCWarning(LOG_LIB) << "Could not add user" << _name; - return QueuedError("", QueuedEnums::ReturnStatus::Error); - } - - // add to child object - m_users->add(properties, id); - // notify plugins - if (m_plugins) - emit(m_plugins->interface()->onAddUser(id)); - - return id; -} - - -/** - * @fn editOptionPrivate - */ -QueuedResult QueuedCore::editOptionPrivate(const QString &_key, - const QVariant &_value) -{ - qCDebug(LOG_LIB) << "Set key" << _key << "to" << _value; - - // add to database - long long id = m_advancedSettings->id(_key); - QVariantHash payload = {{"key", _key}, {"value", _value}}; - - bool status; - if (id == -1) { - id = m_database->add(QueuedDB::SETTINGS_TABLE, payload); - qCInfo(LOG_LIB) << "Added new key with ID" << id; - status = (id != -1); - } else { - status = m_database->modify(QueuedDB::SETTINGS_TABLE, id, payload); - qCInfo(LOG_LIB) << "Value for" << _key - << "has been modified with status" << status; - } - - // add to child object - if (status) { - m_advancedSettings->set(_key, _value); - // notify plugins if required - if (m_plugins) { - auto tryPluginOption = m_plugins->convertOptionName(_key); - if ((!tryPluginOption.first.isEmpty()) - && (!tryPluginOption.second.isEmpty())) - m_plugins->optionChanged(_key, _value); - // notify plugins - emit(m_plugins->interface()->onEditOption(_key, _value)); - } - } - - return status; -} - - -/** - * @fn editPluginPrivate - */ -QueuedResult QueuedCore::editPluginPrivate(const QString &_plugin, - const bool _add) -{ - qCDebug(LOG_LIB) << "Edit plugin" << _plugin << "add" << _add; - - QStringList pluginList - = m_advancedSettings->get(QueuedConfig::QueuedSettings::Plugins) - .toString() - .split('\n'); - - QueuedResult r; - if (_add && !pluginList.contains(_plugin)) { - if (m_plugins->loadPlugin(_plugin, pluginSettings(_plugin))) { - pluginList.append(_plugin); - r = true; - } - } else if (!_add && pluginList.contains(_plugin)) { - if (m_plugins->unloadPlugin(_plugin)) { - pluginList.removeAll(_plugin); - r = true; - } - } else { - qCDebug(LOG_LIB) << "Plugin" << _plugin - << "not loaded or already loaded"; - r = QueuedError("Plugin is not loaded or already loaded", - QueuedEnums::ReturnStatus::Error); - } - - if (r.type() == Result::Content::Value) { - editOptionPrivate(m_advancedSettings->internalId( - QueuedConfig::QueuedSettings::Plugins), - pluginList.join('\n')); - // notify plugins - if (m_plugins) { - if (_add) - emit(m_plugins->interface()->onAddPlugin(_plugin)); - else - emit(m_plugins->interface()->onRemovePlugin(_plugin)); - } - } - - return r; -} - - -/** - * @fn editTaskPrivate - */ -QueuedResult QueuedCore::editTaskPrivate(const long long _id, - const QVariantHash &_taskData) -{ - qCDebug(LOG_LIB) << "Edit task with ID" << _id; - - auto task = m_processes->process(_id); - if (!task) { - qCWarning(LOG_LIB) << "Could not find task with ID" << _id; - return QueuedError("Task does not exist", - QueuedEnums::ReturnStatus::InvalidArgument); - } - - // modify record in database first - bool status = m_database->modify(QueuedDB::TASKS_TABLE, _id, _taskData); - if (!status) { - qCWarning(LOG_LIB) << "Could not modify task record" << _id - << "in database, do not edit it in memory"; - return QueuedError("", QueuedEnums::ReturnStatus::Error); - } - - // modify values stored in memory - for (auto &property : _taskData.keys()) - task->setProperty(qPrintable(property), _taskData[property]); - // notify plugins - if (m_plugins) - emit(m_plugins->interface()->onEditTask(_id, _taskData)); - - return true; -} - - -/** - * @fn editUserPrivate - */ -QueuedResult QueuedCore::editUserPrivate(const long long _id, - const QVariantHash &_userData) -{ - qCDebug(LOG_LIB) << "Edit user with ID" << _id; - - auto userObj = m_users->user(_id); - if (!userObj) { - qCWarning(LOG_LIB) << "Could not find user with ID" << _id; - return QueuedError("User does not exist", - QueuedEnums::ReturnStatus::InvalidArgument); - }; - - // modify record in database first - bool status = m_database->modify(QueuedDB::USERS_TABLE, _id, _userData); - if (!status) { - qCWarning(LOG_LIB) << "Could not modify user record" << _id - << "in database, do not edit it in memory"; - return QueuedError("", QueuedEnums::ReturnStatus::Error); - } - - // modify values stored in memory - for (auto &property : _userData.keys()) - userObj->setProperty(qPrintable(property), _userData[property]); - // notify plugins - if (m_plugins) - emit(m_plugins->interface()->onEditUser(_id, _userData)); - - return true; -} - - -/** - * @fn editUserPermissionPrivate - */ -QueuedResult QueuedCore::editUserPermissionPrivate( - const long long _id, const QueuedEnums::Permission &_permission, - const bool _add) -{ - qCDebug(LOG_LIB) << "Edit permissions" << static_cast(_permission) - << "for user" << _id << "add" << _add; - - auto userObj = m_users->user(_id); - if (!userObj) { - qCWarning(LOG_LIB) << "Could not find user with ID" << _id; - return QueuedError("User does not exist", - QueuedEnums::ReturnStatus::InvalidArgument); - } - - // edit runtime permissions to get value - auto perms = _add ? userObj->addPermission(_permission) - : userObj->removePermission(_permission); - auto permissions = static_cast(perms); - qCInfo(LOG_LIB) << "New user permissions" << perms; - - // modify in database now - QVariantHash payload = {{"permissions", permissions}}; - 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"; - // rollback in-memory values - if (_add) - userObj->removePermission(_permission); - else - userObj->addPermission(_permission); - return QueuedError("", QueuedEnums::ReturnStatus::Error); - } - - return true; -} diff --git a/sources/queued/src/QueuedCoreAdaptor.cpp b/sources/queued/src/QueuedCoreAdaptor.cpp index 6a473cd..42dba3b 100644 --- a/sources/queued/src/QueuedCoreAdaptor.cpp +++ b/sources/queued/src/QueuedCoreAdaptor.cpp @@ -75,9 +75,9 @@ QueuedResult QueuedCoreAdaptor::sendPasswordHash(const QString &_password) { QVariantList args = {_password}; - return sendRequest(QueuedConfig::DBUS_SERVICE, - QueuedConfig::DBUS_OBJECT_PATH, - QueuedConfig::DBUS_SERVICE, "Auth", args); + return sendRequest( + QueuedConfig::DBUS_SERVICE, QueuedConfig::DBUS_OBJECT_PATH, + QueuedConfig::DBUS_SERVICE, "PasswordHash", args); } @@ -348,11 +348,11 @@ QueuedResult QueuedCoreAdaptor::getTask(const long long _id) auto res = getTask(_id, ""); QueuedResult output; - Result::match(res, - [&output](const QVariant &val) { - output = toResult(val); - }, - [&output](const QueuedError &err) { output = err; }); + res.match( + [&output](const QVariant &val) { + output = toResult(val); + }, + [&output](const QueuedError &err) { output = err; }); return output; } @@ -400,11 +400,11 @@ QueuedResult QueuedCoreAdaptor::getUser(const long long _id) auto res = getUser(_id, ""); QueuedResult output; - Result::match(res, - [&output](const QVariant &val) { - output = toResult(val); - }, - [&output](const QueuedError &err) { output = err; }); + res.match( + [&output](const QVariant &val) { + output = toResult(val); + }, + [&output](const QueuedError &err) { output = err; }); return output; } diff --git a/sources/queued/src/QueuedCorePrivate.cpp b/sources/queued/src/QueuedCorePrivate.cpp new file mode 100644 index 0000000..1700ad5 --- /dev/null +++ b/sources/queued/src/QueuedCorePrivate.cpp @@ -0,0 +1,585 @@ +/* + * Copyright (c) 2017 Queued team + * + * 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 QueuedCorePrivate.cpp + * Source code of queued library + * @author Queued team + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#include +#include + +#include "queued/QueuedDatabaseSchema.h" + +#include + + +/** + * @class QueuedCorePrivate + */ +/** + * @fn addPlugin + */ +QueuedResult QueuedCorePrivate::addPlugin(const QString &_plugin, + const QString &_token) +{ + qCDebug(LOG_LIB) << "Add plugin" << _plugin; + + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to add plugin"; + return QueuedError("Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + + return m_helper->editPluginPrivate(_plugin, true); +} + + +/** + * @addTask + */ +QueuedResult QueuedCorePrivate::addTask( + const QString &_command, const QStringList &_arguments, + const QString &_workingDirectory, const long long _userId, + const QueuedLimits::Limits &_limits, const QString &_token) +{ + qCDebug(LOG_LIB) << "Add task" << _command << "with arguments" << _arguments + << "from user" << _userId; + + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + long long userAuthId = authUser->index(); + long long actualUserId = (_userId == -1) ? userAuthId : _userId; + + // check permissions + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + bool isUser = m_users->authorize(_token, QueuedEnums::Permission::Job); + if (userAuthId == actualUserId) { + // it means that user places task as own one + if (!isUser) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to add task"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } else { + // user tries to place task as another one + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to add task"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } + + return m_helper->addTaskPrivate(_command, _arguments, _workingDirectory, + _userId, _limits); +} + + +/** + * @fn addUser + */ +QueuedResult +QueuedCorePrivate::addUser(const QString &_name, const QString &_email, + const QString &_password, const uint _permissions, + const QueuedLimits::Limits &_limits, + const QString &_token) +{ + qCDebug(LOG_LIB) << "Add user" << _name << "with email" << _email + << "and permissions" << _permissions; + + // check permissions + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to add user"; + return QueuedError("Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + + // check if already exists + auto userObj = user(_name); + if (userObj) { + qCWarning(LOG_LIB) << "User" << _name << "already exists"; + return QueuedError("User already exists", + QueuedEnums::ReturnStatus::InvalidArgument); + } + + return m_helper->addUserPrivate(_name, _email, _password, _permissions, + _limits); +} + + +/** + * @fn authorization + */ +QueuedResult QueuedCorePrivate::authorization(const QString &_token) +{ + bool status = false; + m_users->checkToken(_token, &status); + + return status; +} + + +/** + * @fn authorization + */ +QueuedResult QueuedCorePrivate::authorization(const QString &_name, + const QString &_password) +{ + qCDebug(LOG_LIB) << "Authorize user" << _name; + + QString token = m_users->authorize(_name, _password); + if (token.isEmpty()) { + return QueuedError("Invalid username or password", + QueuedEnums::ReturnStatus::InvalidPassword); + } else { + QVariantHash payload + = {{"token", token}, + {"user", _name}, + {"validUntil", + m_users->checkToken(token).toString(Qt::ISODateWithMs)}}; + m_database->add(QueuedDB::TOKENS_TABLE, payload); + return token; + } +} + + +/** + * @fn editOption + */ +QueuedResult QueuedCorePrivate::editOption(const QString &_key, + const QVariant &_value, + const QString &_token) +{ + qCDebug(LOG_LIB) << "Set key" << _key << "to" << _value; + + // check permissions + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit options"; + return QueuedError("Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + + return m_helper->editOptionPrivate(_key, _value); +} + + +/** + * @fn editTask + */ +QueuedResult QueuedCorePrivate::editTask(const long long _id, + const QVariantHash &_taskData, + const QString &_token) +{ + qCDebug(LOG_LIB) << "Edit task with ID" << _id; + + auto task = m_processes->process(_id); + if (!task) { + qCWarning(LOG_LIB) << "Could not find task with ID" << _id; + return QueuedError("Task does not exist", + QueuedEnums::ReturnStatus::InvalidArgument); + } + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + bool isUser = m_users->authorize(_token, QueuedEnums::Permission::Job); + if (userAuthId == task->user()) { + // it means that user edits own task + if (!isUser) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit task"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } else { + // user tries to edit random task + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit task"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } + // only admin can edit run/stopped task + if (!task->startTime().isNull()) { + if (!isAdmin) { + qCInfo(LOG_LIB) + << "User" << _token << "not allowed to edit run/exited task"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } + + // drop admin fields + QVariantHash payload + = isAdmin ? _taskData + : m_helper->dropAdminFields(QueuedDB::TASKS_TABLE, _taskData); + + return m_helper->editTaskPrivate(_id, payload); +} + + +/** + * @fn editUser + */ +QueuedResult QueuedCorePrivate::editUser(const long long _id, + const QVariantHash &_userData, + const QString &_token) +{ + qCDebug(LOG_LIB) << "Edit user with ID" << _id; + + auto userObj = user(_id); + if (!userObj) { + qCWarning(LOG_LIB) << "Could not find user with ID" << _id; + return QueuedError("User does not exist", + QueuedEnums::ReturnStatus::InvalidArgument); + } + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + if (userAuthId != _id) { + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to edit user"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } + + // drop admin fields + QVariantHash payload + = isAdmin ? _userData + : m_helper->dropAdminFields(QueuedDB::USERS_TABLE, _userData); + + return m_helper->editUserPrivate(_id, payload); +} + + +/** + * @fn editUserPermission + */ +QueuedResult QueuedCorePrivate::editUserPermission( + const long long _id, const QueuedEnums::Permission &_permission, + const bool _add, const QString &_token) +{ + qCDebug(LOG_LIB) << "Edit permissions" << static_cast(_permission) + << "for user" << _id << "add" << _add; + + // check permissions + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token + << "not allowed to edit permissions"; + return QueuedError("Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + + return m_helper->editUserPermissionPrivate(_id, _permission, _add); +} + + +/** + * @fn hashFromPassword + */ +QueuedResult +QueuedCorePrivate::hashFromPassword(const QString &_password) +{ + return _password.isEmpty() ? "" + : QueuedUser::hashFromPassword( + _password, m_settings->admin().salt); +} + + +/** + * @fn option + */ +QueuedResult QueuedCorePrivate::option(const QString &_key) +{ + qCDebug(LOG_LIB) << "Look for option" << _key; + + return m_advancedSettings->get(_key); +} + + +/** + * @fn performanceReport + */ +QueuedResult> QueuedCorePrivate::performanceReport( + const QDateTime &_from, const QDateTime &_to, const QString &_token) const +{ + qCDebug(LOG_LIB) << "Get performance report for" << _from << _to; + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); + + if (isAdmin) { + return m_reports->performance(static_cast(parent()), + _from, _to); + } else { + auto data = m_reports->performance(static_cast(parent()), + _from, _to); + QList output; + for (auto &userData : data) { + if (userData["_id"].toLongLong() != userAuthId) + continue; + output.append(userData); + } + return output; + } +} + + +/** + * @fn pluginSettings + */ +QVariantHash QueuedCorePrivate::pluginSettings(const QString &_plugin) +{ + qCDebug(LOG_LIB) << "Get plugin settings for" << _plugin; + + auto dbSettings + = m_database->get(QueuedDB::SETTINGS_TABLE, + QString("WHERE key LIKE 'Plugin.%1.%'").arg(_plugin)); + QVariantHash settings; + std::for_each(dbSettings.cbegin(), dbSettings.cend(), + [&settings](const QVariantHash &value) { + settings[value["key"].toString()] = value["value"]; + }); + + return settings; +} + + +/** + * @fn removePlugin + */ +QueuedResult QueuedCorePrivate::removePlugin(const QString &_plugin, + const QString &_token) +{ + qCDebug(LOG_LIB) << "Remove plugin" << _plugin; + + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to remove plugin"; + return QueuedError("Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + + return m_helper->editPluginPrivate(_plugin, false); +} + + +/** + * @fn startTask + */ +QueuedResult QueuedCorePrivate::startTask(const long long _id, + const QString &_token) +{ + qCDebug(LOG_LIB) << "Force start task with ID" << _id; + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + if (userAuthId != _id) { + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to start tasks"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } + + m_processes->start(_id); + + return true; +} + + +/** + * @fn stopTask + */ +QueuedResult QueuedCorePrivate::stopTask(const long long _id, + const QString &_token) +{ + 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 QueuedError("Task does not exist", + QueuedEnums::ReturnStatus::InvalidArgument); + } + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Admin); + bool isUser = m_users->authorize(_token, QueuedEnums::Permission::Job); + if (userAuthId == task->user()) { + // it means that user edits own task + if (!isUser) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to stop task"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } else { + // user tries to edit random task + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to stop task"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } + + m_processes->stop(_id); + + return true; +} + + +/** + * @fn task + */ +const QueuedProcess *QueuedCorePrivate::task(const long long _id) const +{ + qCDebug(LOG_LIB) << "Get task by ID" << _id; + + return m_processes->process(_id); +} + + +/** + * @fn taskReport + */ +QueuedResult> +QueuedCorePrivate::taskReport(const long long _user, const QDateTime &_from, + const QDateTime &_to, const QString &_token) const +{ + qCDebug(LOG_LIB) << "Get tasks table by" << _user << _from << _to; + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); + long long effectiveUserId = _user; + if (_user == -1) { + effectiveUserId = userAuthId; + } else if (userAuthId != _user) { + if (!isAdmin) { + qCInfo(LOG_LIB) + << "User" << _token << "not allowed to get task report"; + return QueuedError( + "Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + } + + return m_reports->tasks(effectiveUserId, _from, _to); +} + + +/** + * @fn user + */ +const QueuedUser *QueuedCorePrivate::user(const long long _id) const +{ + qCDebug(LOG_LIB) << "Get user by ID" << _id; + + return m_users->user(_id); +} + + +/** + * @fn user + */ +const QueuedUser *QueuedCorePrivate::user(const QString &_name) const +{ + qCDebug(LOG_LIB) << "Get user by name" << _name; + + return m_users->user(_name, false); +} + + +/** + * @fn userReport + */ +QueuedResult> +QueuedCorePrivate::userReport(const QDateTime &_lastLogged, + const QueuedEnums::Permission _permission, + const QString &_token) const +{ + qCDebug(LOG_LIB) << "Get users table by" << _lastLogged + << static_cast(_permission); + + // check permissions + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to get user report"; + return QueuedError("Not allowed", + QueuedEnums::ReturnStatus::InsufficientPermissions); + } + + return m_reports->users(_lastLogged, _permission); +} diff --git a/sources/queued/src/QueuedCorePrivateHelper.cpp b/sources/queued/src/QueuedCorePrivateHelper.cpp new file mode 100644 index 0000000..9c57c93 --- /dev/null +++ b/sources/queued/src/QueuedCorePrivateHelper.cpp @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2017 Queued team + * + * 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 QueuedCorePrivateHelper.cpp + * Source code of queued library + * @author Queued team + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#include +#include + +#include "queued/QueuedDatabaseSchema.h" + +#include + + +/** + * @class QueuedCorePrivateHelper + */ +/** + * @fn QueuedCorePrivateHelper + */ +QueuedCorePrivateHelper::QueuedCorePrivateHelper(QObject *_parent) + : QObject(_parent) +{ + qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; + + m_core = static_cast(parent()); +} + + +/** + * @fn ~QueuedCorePrivateHelper + */ +QueuedCorePrivateHelper::~QueuedCorePrivateHelper() +{ + qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; +} + + +/** + * @fn advancedSettings + */ +QueuedAdvancedSettings *QueuedCorePrivateHelper::advancedSettings() +{ + return m_core->m_advancedSettings; +} + + +/** + * @fn database + */ +QueuedDatabase *QueuedCorePrivateHelper::database() +{ + return m_core->m_database; +} + + +/** + * @fn plugins + */ +QueuedPluginManager *QueuedCorePrivateHelper::plugins() +{ + return m_core->m_plugins; +} + + +/** + * @fn processes + */ +QueuedProcessManager *QueuedCorePrivateHelper::processes() +{ + return m_core->m_processes; +} + + +/** + * @fn users + */ +QueuedUserManager *QueuedCorePrivateHelper::users() +{ + return m_core->m_users; +} + + +/** + * @fn dropAdminFields + */ +QVariantHash +QueuedCorePrivateHelper::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; +} + + +/** + * @addTaskPrivate + */ +QueuedResult QueuedCorePrivateHelper::addTaskPrivate( + const QString &_command, const QStringList &_arguments, + const QString &_workingDirectory, const long long _userId, + const QueuedLimits::Limits &_limits) +{ + qCDebug(LOG_LIB) << "Add task" << _command << "with arguments" << _arguments + << "from user" << _userId; + + // add to database + auto ids = users()->ids(_userId); + auto userObj = m_core->user(_userId); + if (!userObj) { + qCWarning(LOG_LIB) << "Could not find task user" << _userId; + return QueuedError("Invalid token", + QueuedEnums::ReturnStatus::InvalidToken); + } + auto taskLimits = QueuedLimits::minimalLimits( + _limits, userObj->nativeLimits(), + QueuedLimits::Limits( + advancedSettings() + ->get(QueuedConfig::QueuedSettings::DefaultLimits) + .toString())); + QVariantHash properties = {{"user", _userId}, + {"command", _command}, + {"commandArguments", _arguments}, + {"workDirectory", _workingDirectory}, + {"nice", 0}, + {"uid", ids.first}, + {"gid", ids.second}, + {"limits", taskLimits.toString()}}; + auto id = database()->add(QueuedDB::TASKS_TABLE, properties); + if (id == -1) { + qCWarning(LOG_LIB) << "Could not add task" << _command; + return QueuedError("", QueuedEnums::ReturnStatus::Error); + } + + // add to child object + processes()->add(properties, id); + // notify plugins + if (plugins()) + emit(plugins()->interface()->onAddTask(id)); + + return id; +} + + +/** + * @fn addUserPrivate + */ +QueuedResult QueuedCorePrivateHelper::addUserPrivate( + const QString &_name, const QString &_email, const QString &_password, + const uint _permissions, const QueuedLimits::Limits &_limits) +{ + qCDebug(LOG_LIB) << "Add user" << _name << "with email" << _email + << "and permissions" << _permissions; + // add to database + QVariantHash properties = {{"name", _name}, + {"password", _password}, + {"email", _email}, + {"permissions", _permissions}, + {"limits", _limits.toString()}}; + auto id = database()->add(QueuedDB::USERS_TABLE, properties); + if (id == -1) { + qCWarning(LOG_LIB) << "Could not add user" << _name; + return QueuedError("", QueuedEnums::ReturnStatus::Error); + } + + // add to child object + users()->add(properties, id); + // notify plugins + if (plugins()) + emit(plugins()->interface()->onAddUser(id)); + + return id; +} + + +/** + * @fn editOptionPrivate + */ +QueuedResult +QueuedCorePrivateHelper::editOptionPrivate(const QString &_key, + const QVariant &_value) +{ + qCDebug(LOG_LIB) << "Set key" << _key << "to" << _value; + + // add to database + long long id = advancedSettings()->id(_key); + QVariantHash payload = {{"key", _key}, {"value", _value}}; + + bool status; + if (id == -1) { + id = database()->add(QueuedDB::SETTINGS_TABLE, payload); + qCInfo(LOG_LIB) << "Added new key with ID" << id; + status = (id != -1); + } else { + status = database()->modify(QueuedDB::SETTINGS_TABLE, id, payload); + qCInfo(LOG_LIB) << "Value for" << _key + << "has been modified with status" << status; + } + + // add to child object + if (status) { + advancedSettings()->set(_key, _value); + // notify plugins if required + if (plugins()) { + auto tryPluginOption = plugins()->convertOptionName(_key); + if ((!tryPluginOption.first.isEmpty()) + && (!tryPluginOption.second.isEmpty())) + plugins()->optionChanged(_key, _value); + // notify plugins + emit(plugins()->interface()->onEditOption(_key, _value)); + } + } + + return status; +} + + +/** + * @fn editPluginPrivate + */ +QueuedResult +QueuedCorePrivateHelper::editPluginPrivate(const QString &_plugin, + const bool _add) +{ + qCDebug(LOG_LIB) << "Edit plugin" << _plugin << "add" << _add; + + QStringList pluginList = advancedSettings() + ->get(QueuedConfig::QueuedSettings::Plugins) + .toString() + .split('\n'); + + QueuedResult r; + if (_add && !pluginList.contains(_plugin)) { + if (plugins()->loadPlugin(_plugin, m_core->pluginSettings(_plugin))) { + pluginList.append(_plugin); + r = true; + } + } else if (!_add && pluginList.contains(_plugin)) { + if (plugins()->unloadPlugin(_plugin)) { + pluginList.removeAll(_plugin); + r = true; + } + } else { + qCDebug(LOG_LIB) << "Plugin" << _plugin + << "not loaded or already loaded"; + r = QueuedError("Plugin is not loaded or already loaded", + QueuedEnums::ReturnStatus::Error); + } + + if (r.type() == Result::Content::Value) { + editOptionPrivate(advancedSettings()->internalId( + QueuedConfig::QueuedSettings::Plugins), + pluginList.join('\n')); + // notify plugins + if (plugins()) { + if (_add) + emit(plugins()->interface()->onAddPlugin(_plugin)); + else + emit(plugins()->interface()->onRemovePlugin(_plugin)); + } + } + + return r; +} + + +/** + * @fn editTaskPrivate + */ +QueuedResult +QueuedCorePrivateHelper::editTaskPrivate(const long long _id, + const QVariantHash &_taskData) +{ + qCDebug(LOG_LIB) << "Edit task with ID" << _id; + + auto task = processes()->process(_id); + if (!task) { + qCWarning(LOG_LIB) << "Could not find task with ID" << _id; + return QueuedError("Task does not exist", + QueuedEnums::ReturnStatus::InvalidArgument); + } + + // modify record in database first + bool status = database()->modify(QueuedDB::TASKS_TABLE, _id, _taskData); + if (!status) { + qCWarning(LOG_LIB) << "Could not modify task record" << _id + << "in database, do not edit it in memory"; + return QueuedError("", QueuedEnums::ReturnStatus::Error); + } + + // modify values stored in memory + for (auto &property : _taskData.keys()) + task->setProperty(qPrintable(property), _taskData[property]); + // notify plugins + if (plugins()) + emit(plugins()->interface()->onEditTask(_id, _taskData)); + + return true; +} + + +/** + * @fn editUserPrivate + */ +QueuedResult +QueuedCorePrivateHelper::editUserPrivate(const long long _id, + const QVariantHash &_userData) +{ + qCDebug(LOG_LIB) << "Edit user with ID" << _id; + + auto userObj = users()->user(_id); + if (!userObj) { + qCWarning(LOG_LIB) << "Could not find user with ID" << _id; + return QueuedError("User does not exist", + QueuedEnums::ReturnStatus::InvalidArgument); + }; + + // modify record in database first + bool status = database()->modify(QueuedDB::USERS_TABLE, _id, _userData); + if (!status) { + qCWarning(LOG_LIB) << "Could not modify user record" << _id + << "in database, do not edit it in memory"; + return QueuedError("", QueuedEnums::ReturnStatus::Error); + } + + // modify values stored in memory + for (auto &property : _userData.keys()) + userObj->setProperty(qPrintable(property), _userData[property]); + // notify plugins + if (plugins()) + emit(plugins()->interface()->onEditUser(_id, _userData)); + + return true; +} + + +/** + * @fn editUserPermissionPrivate + */ +QueuedResult QueuedCorePrivateHelper::editUserPermissionPrivate( + const long long _id, const QueuedEnums::Permission &_permission, + const bool _add) +{ + qCDebug(LOG_LIB) << "Edit permissions" << static_cast(_permission) + << "for user" << _id << "add" << _add; + + auto userObj = users()->user(_id); + if (!userObj) { + qCWarning(LOG_LIB) << "Could not find user with ID" << _id; + return QueuedError("User does not exist", + QueuedEnums::ReturnStatus::InvalidArgument); + } + + // edit runtime permissions to get value + auto perms = _add ? userObj->addPermission(_permission) + : userObj->removePermission(_permission); + auto permissions = static_cast(perms); + qCInfo(LOG_LIB) << "New user permissions" << perms; + + // modify in database now + QVariantHash payload = {{"permissions", permissions}}; + bool status = 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"; + // rollback in-memory values + if (_add) + userObj->removePermission(_permission); + else + userObj->addPermission(_permission); + return QueuedError("", QueuedEnums::ReturnStatus::Error); + } + + return true; +} diff --git a/sources/queued/src/QueuedCorePrivateInitializator.cpp b/sources/queued/src/QueuedCorePrivateInitializator.cpp new file mode 100644 index 0000000..ee56694 --- /dev/null +++ b/sources/queued/src/QueuedCorePrivateInitializator.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2017 Queued team + * + * 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 QueuedCorePrivateInitializator.cpp + * Source code of queued library + * @author Queued team + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#include +#include + +#include "queued/QueuedDatabaseSchema.h" + +#include + + +/** + * @class QueuedCorePrivate + */ +/** + * @fn QueuedCorePrivate + */ +QueuedCorePrivate::QueuedCorePrivate(QObject *_parent) + : QObject(_parent) +{ + qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; + + m_helper = new QueuedCorePrivateHelper(this); +} + + +/** + * @fn ~QueuedCorePrivate + */ +QueuedCorePrivate::~QueuedCorePrivate() +{ + qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; + + deinit(); +} + + +/** + * @fn deinit + */ +void QueuedCorePrivate::deinit() +{ + // clear connections first + for (auto &connection : m_connections) + disconnect(connection); + m_connections.clear(); +} + + +/** + * @fn init + */ +void QueuedCorePrivate::init(const QString &_configuration) +{ + qCDebug(LOG_LIB) << "Load configuration from" << _configuration; + + // deinit objects if any + deinit(); + + // init parts + initSettings(_configuration); + initUsers(); + initPlugins(); + initProcesses(); + + // settings update notifier + m_connections + += connect(m_advancedSettings, + SIGNAL(valueUpdated(const QueuedConfig::QueuedSettings, + const QString &, const QVariant &)), + this, + SLOT(updateSettings(const QueuedConfig::QueuedSettings, + const QString &, const QVariant &))); + + // run! + m_processes->start(); +} + + +/** + * @fn initPlugins + */ +void QueuedCorePrivate::initPlugins() +{ + QStringList pluginList + = m_advancedSettings->get(QueuedConfig::QueuedSettings::Plugins) + .toString() + .split('\n'); + QString token = m_users->authorize(m_settings->admin().name); + + m_plugins = m_helper->initObject(m_plugins, token); + for (auto &plugin : pluginList) + m_plugins->loadPlugin(plugin, pluginSettings(plugin)); +} + + +/** + * @fn initProcesses + */ +void QueuedCorePrivate::initProcesses() +{ + // init processes + auto onExitAction = static_cast( + m_advancedSettings->get(QueuedConfig::QueuedSettings::OnExitAction) + .toInt()); + auto processLine + = m_advancedSettings + ->get(QueuedConfig::QueuedSettings::ProcessCommandLine) + .toString(); + + m_processes = m_helper->initObject(m_processes); + m_processes->setProcessLine(processLine); + m_processes->setExitAction(onExitAction); + auto dbProcesses + = m_database->get(QueuedDB::TASKS_TABLE, "WHERE endTime IS NULL"); + m_processes->loadProcesses(dbProcesses); + + m_connections + += connect(m_processes, &QueuedProcessManager::taskStartTimeReceived, + [this](const long long _index, const QDateTime &_time) { + return updateTaskTime(_index, _time, QDateTime()); + }); + m_connections + += connect(m_processes, &QueuedProcessManager::taskStopTimeReceived, + [this](const long long _index, const QDateTime &_time) { + return updateTaskTime(_index, QDateTime(), _time); + }); +} + + +/** + * @fn initSettings + */ +void QueuedCorePrivate::initSettings(const QString &_configuration) +{ + // read configuration first + m_settings = m_helper->initObject(m_settings, _configuration); + m_settings->readConfiguration(); + // init database now + auto dbSetup = m_settings->db(); + m_database = m_helper->initObject(m_database, dbSetup.path, dbSetup.driver); + m_database->close(); + bool status = m_database->open(dbSetup.hostname, dbSetup.port, + dbSetup.username, dbSetup.password); + if (!status) { + QString message = "Could not open database"; + qCCritical(LOG_LIB) << message; + throw QueuedDatabaseException(message); + } + + // create administrator if required + auto dbAdmin = m_settings->admin(); + m_database->createAdministrator(dbAdmin.name, dbAdmin.password); + + // and load advanced settings + m_advancedSettings = m_helper->initObject(m_advancedSettings); + m_advancedSettings->set(m_database->get(QueuedDB::SETTINGS_TABLE)); + if (!m_advancedSettings->checkDatabaseVersion()) { + qCInfo(LOG_LIB) << "Bump database version to" + << QueuedConfig::DATABASE_VERSION; + m_helper->editOptionPrivate( + m_advancedSettings->internalId( + QueuedConfig::QueuedSettings::DatabaseVersion), + QueuedConfig::DATABASE_VERSION); + } + + // report manager + m_reports = m_helper->initObject(m_reports, m_database); + // database manager + m_databaseManager = m_helper->initObject(m_databaseManager, m_database); +} + + +/** + * @fn initUsers + */ +void QueuedCorePrivate::initUsers() +{ + // load users and tokens + auto expiry + = m_advancedSettings->get(QueuedConfig::QueuedSettings::TokenExpiration) + .toLongLong(); + + m_users = m_helper->initObject(m_users); + m_users->setSalt(m_settings->admin().salt); + m_users->setTokenExpiration(expiry); + QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs); + auto dbTokens = m_database->get( + QueuedDB::TOKENS_TABLE, + QString("WHERE datetime(validUntil) > datetime('%1')").arg(now)); + m_users->loadTokens(dbTokens); + auto dbUsers = m_database->get(QueuedDB::USERS_TABLE); + m_users->loadUsers(dbUsers); + + m_connections += connect( + m_users, SIGNAL(userLoggedIn(const long long, const QDateTime &)), this, + SLOT(updateUserLoginTime(const long long, const QDateTime &))); +} diff --git a/sources/queued/src/QueuedCorePrivateSlots.cpp b/sources/queued/src/QueuedCorePrivateSlots.cpp new file mode 100644 index 0000000..c4af59f --- /dev/null +++ b/sources/queued/src/QueuedCorePrivateSlots.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2017 Queued team + * + * 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 QueuedCorePrivate.cpp + * Source code of queued library + * @author Queued team + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#include +#include + +#include "queued/QueuedDatabaseSchema.h" + +#include + + +/** + * @class QueuedCorePrivate + */ +/** + * @fn updateSettings + */ +void QueuedCorePrivate::updateSettings(const QueuedConfig::QueuedSettings _id, + const QString &_key, + const QVariant &_value) +{ + qCDebug(LOG_LIB) << "Received update for" << static_cast(_id) << _key + << "with value" << _value; + + // FIXME probably there is a better way to change settings + switch (_id) { + case QueuedConfig::QueuedSettings::Invalid: + // check if it is plugin settings + if (_key.startsWith("Plugin.")) + m_plugins->optionChanged(_key, _value); + // do nothing otherwise + break; + case QueuedConfig::QueuedSettings::DatabaseInterval: + m_databaseManager->setInterval(_value.toLongLong()); + break; + case QueuedConfig::QueuedSettings::DatabaseVersion: + break; + case QueuedConfig::QueuedSettings::DefaultLimits: + break; + case QueuedConfig::QueuedSettings::KeepTasks: + m_databaseManager->setKeepTasks(_value.toLongLong()); + break; + case QueuedConfig::QueuedSettings::KeepUsers: + m_databaseManager->setKeepUsers(_value.toLongLong()); + break; + case QueuedConfig::QueuedSettings::OnExitAction: + m_processes->setExitAction( + static_cast(_value.toInt())); + break; + case QueuedConfig::QueuedSettings::Plugins: + // do nothing here + break; + case QueuedConfig::QueuedSettings::ProcessCommandLine: + m_processes->setProcessLine(_value.toString()); + break; + case QueuedConfig::QueuedSettings::ServerAddress: + case QueuedConfig::QueuedSettings::ServerMaxConnections: + case QueuedConfig::QueuedSettings::ServerPort: + case QueuedConfig::QueuedSettings::ServerTimeout: + // do nothing here + break; + case QueuedConfig::QueuedSettings::TokenExpiration: + m_users->setTokenExpiration(_value.toLongLong()); + break; + } +} + + +/** + * @fn updateTaskTime + */ +void QueuedCorePrivate::updateTaskTime(const long long _id, + const QDateTime &_startTime, + const QDateTime &_endTime) +{ + qCDebug(LOG_LIB) << "Update task" << _id << "time to" << _startTime + << _endTime; + + QVariantHash record; + if (_startTime.isValid()) { + record["startTime"] = _startTime.toString(Qt::ISODateWithMs); + if (m_plugins) + emit(m_plugins->interface()->onStartTask(_id)); + } + if (_endTime.isValid()) { + record["endTime"] = _endTime.toString(Qt::ISODateWithMs); + if (m_plugins) + emit(m_plugins->interface()->onStopTask(_id)); + } + + bool status = m_database->modify(QueuedDB::TASKS_TABLE, _id, record); + if (!status) + qCWarning(LOG_LIB) << "Could not modify task record" << _id; +} + + +/** + * @fn updateUserLoginTime + */ +void QueuedCorePrivate::updateUserLoginTime(const long long _id, + const QDateTime &_time) +{ + qCDebug(LOG_LIB) << "Update user" << _id << "with login time" << _time; + + QVariantHash record = {{"lastLogin", _time.toString(Qt::ISODateWithMs)}}; + + bool status = m_database->modify(QueuedDB::USERS_TABLE, _id, record); + if (!status) + qCWarning(LOG_LIB) << "Could not modify user record" << _id; +} diff --git a/sources/queued/src/QueuedDatabaseManager.cpp b/sources/queued/src/QueuedDatabaseManager.cpp index c715377..799fab9 100644 --- a/sources/queued/src/QueuedDatabaseManager.cpp +++ b/sources/queued/src/QueuedDatabaseManager.cpp @@ -30,10 +30,10 @@ /** * @fn QueuedDatabaseManager */ -QueuedDatabaseManager::QueuedDatabaseManager(QObject *parent, - QueuedDatabase *database) - : QObject(parent) - , m_database(database) +QueuedDatabaseManager::QueuedDatabaseManager(QObject *_parent, + QueuedDatabase *_database) + : QObject(_parent) + , m_database(_database) { qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; diff --git a/sources/queued/src/QueuedProcess.cpp b/sources/queued/src/QueuedProcess.cpp index e672f16..8897812 100644 --- a/sources/queued/src/QueuedProcess.cpp +++ b/sources/queued/src/QueuedProcess.cpp @@ -33,10 +33,10 @@ /** * @fn QueuedProcess */ -QueuedProcess::QueuedProcess(QObject *parent, +QueuedProcess::QueuedProcess(QObject *_parent, const QueuedProcessDefinitions &definitions, const long long index) - : QProcess(parent) + : QProcess(_parent) , m_definitions(definitions) , m_index(index) { diff --git a/sources/queued/src/QueuedReportManager.cpp b/sources/queued/src/QueuedReportManager.cpp index 1ff70e6..973d2db 100644 --- a/sources/queued/src/QueuedReportManager.cpp +++ b/sources/queued/src/QueuedReportManager.cpp @@ -32,10 +32,10 @@ /** * @fn QueuedReportManager */ -QueuedReportManager::QueuedReportManager(QObject *parent, - QueuedDatabase *database) - : QObject(parent) - , m_database(database) +QueuedReportManager::QueuedReportManager(QObject *_parent, + QueuedDatabase *_database) + : QObject(_parent) + , m_database(_database) { qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; } diff --git a/sources/queued/src/QueuedTokenManager.cpp b/sources/queued/src/QueuedTokenManager.cpp index ffde7f8..f0fdbd6 100644 --- a/sources/queued/src/QueuedTokenManager.cpp +++ b/sources/queued/src/QueuedTokenManager.cpp @@ -32,8 +32,8 @@ /** * @fn QueuedTokenManager */ -QueuedTokenManager::QueuedTokenManager(QObject *parent) - : QObject(parent) +QueuedTokenManager::QueuedTokenManager(QObject *_parent) + : QObject(_parent) { qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; } diff --git a/sources/queued/src/QueuedUser.cpp b/sources/queued/src/QueuedUser.cpp index fcc2320..009d21c 100644 --- a/sources/queued/src/QueuedUser.cpp +++ b/sources/queued/src/QueuedUser.cpp @@ -36,10 +36,10 @@ extern "C" { /** * @fn QueuedUser */ -QueuedUser::QueuedUser(QObject *parent, +QueuedUser::QueuedUser(QObject *_parent, const QueuedUserDefinitions &definitions, const long long index) - : QObject(parent) + : QObject(_parent) , m_definitions(definitions) , m_index(index) { diff --git a/sources/queuedctl/src/QueuedctlAuth.cpp b/sources/queuedctl/src/QueuedctlAuth.cpp index 4f098cf..f63193a 100644 --- a/sources/queuedctl/src/QueuedctlAuth.cpp +++ b/sources/queuedctl/src/QueuedctlAuth.cpp @@ -31,15 +31,15 @@ QueuedctlCommon::QueuedctlResult QueuedctlAuth::auth(const QString &_user, QueuedctlCommon::QueuedctlResult output; auto res = QueuedCoreAdaptor::auth(_user, QueuedctlUser::getPassword()); - Result::match(res, - [&output, &_user, &_cache](const QString &val) { - setToken(val, _user, _cache); - output.status = true; - }, - [&output](const QueuedError &err) { - output.status = false; - output.output = err.message().c_str(); - }); + res.match( + [&output, &_user, &_cache](const QString &val) { + setToken(val, _user, _cache); + output.status = true; + }, + [&output](const QueuedError &err) { + output.status = false; + output.output = err.message().c_str(); + }); return output; } diff --git a/sources/queuedctl/src/QueuedctlCommon.cpp b/sources/queuedctl/src/QueuedctlCommon.cpp index 621bc8e..dd41060 100644 --- a/sources/queuedctl/src/QueuedctlCommon.cpp +++ b/sources/queuedctl/src/QueuedctlCommon.cpp @@ -236,11 +236,10 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, case QueuedctlArgument::PermissionAdd: { auto userIdRes = QueuedCoreAdaptor::getUserId(args.at(1)); long long userId = -1; - Result::match(userIdRes, - [&userId](const long long val) { userId = val; }, - [&result](const QueuedError &err) { - result.output = err.message().c_str(); - }); + userIdRes.match([&userId](const long long val) { userId = val; }, + [&result](const QueuedError &err) { + result.output = err.message().c_str(); + }); if (userId == -1) break; QString token = QueuedctlAuth::getToken(_cache, _user); @@ -250,11 +249,10 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, case QueuedctlArgument::PermissionRemove: { auto userIdRes = QueuedCoreAdaptor::getUserId(args.at(1)); long long userId = -1; - Result::match(userIdRes, - [&userId](const long long val) { userId = val; }, - [&result](const QueuedError &err) { - result.output = err.message().c_str(); - }); + userIdRes.match([&userId](const long long val) { userId = val; }, + [&result](const QueuedError &err) { + result.output = err.message().c_str(); + }); if (userId == -1) break; QString token = QueuedctlAuth::getToken(_cache, _user); @@ -283,14 +281,14 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, } case QueuedctlArgument::Status: { auto res = QueuedCoreAdaptor::getStatus(); - Result::match(res, - [&result](const QueuedStatusMap &val) { - result.status = true; - result.output = hashHashToString(val); - }, - [&result](const QueuedError &err) { - result.output = err.message().c_str(); - }); + res.match( + [&result](const QueuedStatusMap &val) { + result.status = true; + result.output = hashHashToString(val); + }, + [&result](const QueuedError &err) { + result.output = err.message().c_str(); + }); break; } case QueuedctlArgument::TaskAdd: { @@ -334,11 +332,10 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, case QueuedctlArgument::UserGet: { auto userIdRes = QueuedCoreAdaptor::getUserId(args.at(1)); long long userId = -1; - Result::match(userIdRes, - [&userId](const long long val) { userId = val; }, - [&result](const QueuedError &err) { - result.output = err.message().c_str(); - }); + userIdRes.match([&userId](const long long val) { userId = val; }, + [&result](const QueuedError &err) { + result.output = err.message().c_str(); + }); if (userId == -1) break; result = QueuedctlUser::getUser(userId, args.at(2)); @@ -352,11 +349,10 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, case QueuedctlArgument::UserSet: { auto userIdRes = QueuedCoreAdaptor::getUserId(args.at(1)); long long userId = -1; - Result::match(userIdRes, - [&userId](const long long val) { userId = val; }, - [&result](const QueuedError &err) { - result.output = err.message().c_str(); - }); + userIdRes.match([&userId](const long long val) { userId = val; }, + [&result](const QueuedError &err) { + result.output = err.message().c_str(); + }); if (userId == -1) break; QString token = QueuedctlAuth::getToken(_cache, _user); diff --git a/sources/queuedctl/src/QueuedctlOption.cpp b/sources/queuedctl/src/QueuedctlOption.cpp index f776102..0886ba2 100644 --- a/sources/queuedctl/src/QueuedctlOption.cpp +++ b/sources/queuedctl/src/QueuedctlOption.cpp @@ -28,10 +28,10 @@ QueuedctlOption::editOption(const QString &_option, const QVariant &_value, QueuedctlCommon::QueuedctlResult output; auto res = QueuedCoreAdaptor::sendOptionEdit(_option, _value, _token); - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -44,14 +44,14 @@ QueuedctlOption::getOption(const QString &_option) QueuedctlCommon::QueuedctlResult output; auto res = QueuedCoreAdaptor::getOption(_option); - Result::match(res, - [&output](const QVariant &val) { - output.status = val.isValid(); - output.output = val.toString(); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QVariant &val) { + output.status = val.isValid(); + output.output = val.toString(); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } diff --git a/sources/queuedctl/src/QueuedctlPermissions.cpp b/sources/queuedctl/src/QueuedctlPermissions.cpp index 9afc946..3a1b1d3 100644 --- a/sources/queuedctl/src/QueuedctlPermissions.cpp +++ b/sources/queuedctl/src/QueuedctlPermissions.cpp @@ -33,10 +33,10 @@ QueuedctlCommon::QueuedctlResult QueuedctlPermissions::addPermission( } else { auto res = QueuedCoreAdaptor::sendUserPermissionAdd(_id, permission, _token); - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); } return output; @@ -56,10 +56,10 @@ QueuedctlCommon::QueuedctlResult QueuedctlPermissions::removePermission( } else { auto res = QueuedCoreAdaptor::sendUserPermissionRemove(_id, permission, _token); - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); } return output; diff --git a/sources/queuedctl/src/QueuedctlPlugins.cpp b/sources/queuedctl/src/QueuedctlPlugins.cpp index 0598a40..544063b 100644 --- a/sources/queuedctl/src/QueuedctlPlugins.cpp +++ b/sources/queuedctl/src/QueuedctlPlugins.cpp @@ -28,10 +28,10 @@ QueuedctlPlugins::addPlugin(const QString &_plugin, const QString &_token) auto res = QueuedCoreAdaptor::sendPluginAdd(_plugin, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -43,14 +43,14 @@ QueuedctlCommon::QueuedctlResult QueuedctlPlugins::listPlugins() = QueuedCoreAdaptor::getOption(QueuedConfig::QueuedSettings::Plugins); QueuedctlCommon::QueuedctlResult output; - Result::match(res, - [&output](const QVariant &val) { - output.status = val.isValid(); - output.output = val.toString(); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QVariant &val) { + output.status = val.isValid(); + output.output = val.toString(); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -64,10 +64,10 @@ QueuedctlPlugins::removePlugin(const QString &_plugin, const QString &_token) auto res = QueuedCoreAdaptor::sendPluginRemove(_plugin, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } diff --git a/sources/queuedctl/src/QueuedctlTask.cpp b/sources/queuedctl/src/QueuedctlTask.cpp index 2c79f6e..638c31d 100644 --- a/sources/queuedctl/src/QueuedctlTask.cpp +++ b/sources/queuedctl/src/QueuedctlTask.cpp @@ -35,14 +35,14 @@ QueuedctlCommon::QueuedctlResult QueuedctlTask::addTask( auto res = QueuedCoreAdaptor::sendTaskAdd(_definitions, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, - [&output](const long long val) { - output.status = (val > 0); - output.output = QString::number(val); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const long long val) { + output.status = (val > 0); + output.output = QString::number(val); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -69,8 +69,7 @@ QueuedctlTask::getDefinitions(const QCommandLineParser &_parser, definitions.user = 0; } else { auto res = QueuedCoreAdaptor::getUserId(_parser.value("task-user")); - Result::match( - res, + res.match( [&definitions](const long long val) { definitions.user = val; }, [&definitions](const QueuedError &) { definitions.user = 0; }); } @@ -114,24 +113,24 @@ QueuedctlTask::getTask(const long long _id, const QString &_property) if (_property.isEmpty()) { auto res = QueuedCoreAdaptor::getTask(_id); - Result::match(res, - [&output](const QVariantHash &val) { - output.status = true; - output.output = QueuedctlCommon::hashToString(val); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QVariantHash &val) { + output.status = true; + output.output = QueuedctlCommon::hashToString(val); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); } else { auto res = QueuedCoreAdaptor::getTask(_id, _property); - Result::match(res, - [&output](const QVariant &val) { - output.status = val.isValid(); - output.output = val.toString(); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QVariant &val) { + output.status = val.isValid(); + output.output = val.toString(); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); } return output; @@ -145,8 +144,8 @@ QueuedctlTask::getTasks(const QCommandLineParser &_parser, long long userId = -1; if (!_parser.value("task-user").isEmpty()) { auto res = QueuedCoreAdaptor::getUserId(_parser.value("task-user")); - Result::match(res, [&userId](const long long val) { userId = val; }, - [&userId](const QueuedError &) {}); + res.match([&userId](const long long val) { userId = val; }, + [&userId](const QueuedError &) {}); } QDateTime stop = QDateTime::fromString(_parser.value("stop"), Qt::ISODateWithMs); @@ -156,14 +155,14 @@ QueuedctlTask::getTasks(const QCommandLineParser &_parser, QueuedctlCommon::QueuedctlResult output; auto res = QueuedCoreAdaptor::getTasks(userId, start, stop, _token); - Result::match(res, - [&output](const QList &val) { - output.status = true; - output.output = QueuedctlCommon::hashListToString(val); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QList &val) { + output.status = true; + output.output = QueuedctlCommon::hashListToString(val); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -310,10 +309,10 @@ QueuedctlCommon::QueuedctlResult QueuedctlTask::setTask( auto res = QueuedCoreAdaptor::sendTaskEdit(_id, _definitions, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -327,10 +326,10 @@ QueuedctlCommon::QueuedctlResult QueuedctlTask::startTask(const long long _id, auto res = QueuedCoreAdaptor::sendTaskStart(_id, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -344,10 +343,10 @@ QueuedctlCommon::QueuedctlResult QueuedctlTask::stopTask(const long long _id, auto res = QueuedCoreAdaptor::sendTaskStart(_id, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } diff --git a/sources/queuedctl/src/QueuedctlUser.cpp b/sources/queuedctl/src/QueuedctlUser.cpp index c570499..ebf76f0 100644 --- a/sources/queuedctl/src/QueuedctlUser.cpp +++ b/sources/queuedctl/src/QueuedctlUser.cpp @@ -37,14 +37,14 @@ QueuedctlUser::addUser(const QueuedUser::QueuedUserDefinitions &_definitions, auto res = QueuedCoreAdaptor::sendUserAdd(_definitions, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, - [&output](const long long val) { - output.status = (val > 0); - output.output = QString::number(val); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const long long val) { + output.status = (val > 0); + output.output = QString::number(val); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -64,14 +64,14 @@ QueuedctlUser::getReport(const QCommandLineParser &_parser, auto res = QueuedCoreAdaptor::getPerformance(start, stop, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, - [&output](const QList &val) { - output.status = true; - output.output = QueuedctlCommon::hashListToString(val); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QList &val) { + output.status = true; + output.output = QueuedctlCommon::hashListToString(val); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -88,12 +88,12 @@ QueuedctlUser::getDefinitions(const QCommandLineParser &_parser, // define password first definitions.password = _parser.isSet("stdin-password") - ? getPassword() - : _parser.value("password"); + ? getPassword() + : _parser.value("password"); auto res = QueuedCoreAdaptor::sendPasswordHash(definitions.password); - Result::match( - res, [&definitions](const QString &val) { definitions.password = val; }, - [](const QueuedError &) {}); + res.match( + [&definitions](const QString &val) { definitions.password = val; }, + [&definitions](const QueuedError &) { definitions.password = ""; }); definitions.email = _parser.value("email"); // limits now @@ -144,24 +144,24 @@ QueuedctlUser::getUser(const long long _id, const QString &_property) if (_property.isEmpty()) { auto res = QueuedCoreAdaptor::getUser(_id); - Result::match(res, - [&output](const QVariantHash &val) { - output.status = true; - output.output = QueuedctlCommon::hashToString(val); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QVariantHash &val) { + output.status = true; + output.output = QueuedctlCommon::hashToString(val); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); } else { auto res = QueuedCoreAdaptor::getUser(_id, _property); - Result::match(res, - [&output](const QVariant &val) { - output.status = val.isValid(); - output.output = val.toString(); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QVariant &val) { + output.status = val.isValid(); + output.output = val.toString(); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); } return output; @@ -182,14 +182,14 @@ QueuedctlUser::getUsers(const QCommandLineParser &_parser, auto res = QueuedCoreAdaptor::getUsers(lastLogin, permission, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, - [&output](const QList &val) { - output.status = true; - output.output = QueuedctlCommon::hashListToString(val); - }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match( + [&output](const QList &val) { + output.status = true; + output.output = QueuedctlCommon::hashListToString(val); + }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; } @@ -326,10 +326,10 @@ QueuedctlUser::setUser(const long long _id, auto res = QueuedCoreAdaptor::sendUserEdit(_id, _definitions, _token); QueuedctlCommon::QueuedctlResult output; - Result::match(res, [&output](const bool val) { output.status = val; }, - [&output](const QueuedError &err) { - output.output = err.message().c_str(); - }); + res.match([&output](const bool val) { output.status = val; }, + [&output](const QueuedError &err) { + output.output = err.message().c_str(); + }); return output; }