diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt index 770d40b..7fd6adc 100644 --- a/sources/CMakeLists.txt +++ b/sources/CMakeLists.txt @@ -72,9 +72,10 @@ include(cppcheck.cmake) include(paths.cmake) get_directory_property(CMAKE_DEFINITIONS COMPILE_DEFINITIONS) -configure_file(${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h) -add_subdirectory(queued) +configure_file("${CMAKE_SOURCE_DIR}/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/version.h") +add_subdirectory("queued") +add_subdirectory("queued-daemon") if (BUILD_TESTING) enable_testing() - add_subdirectory(test) + add_subdirectory("test") endif () diff --git a/sources/queued-daemon/CMakeLists.txt b/sources/queued-daemon/CMakeLists.txt new file mode 100644 index 0000000..b683ae8 --- /dev/null +++ b/sources/queued-daemon/CMakeLists.txt @@ -0,0 +1,13 @@ +# set project name +set (SUBPROJECT "queued-daemon") +message (STATUS "Subproject ${SUBPROJECT}") + +add_subdirectory ("src") +# build man +file (GLOB SUBPROJECT_MAN_IN "*.1") +file (RELATIVE_PATH SUBPROJECT_MAN "${CMAKE_SOURCE_DIR}" "${SUBPROJECT_MAN_IN}") +configure_file ("${SUBPROJECT_MAN_IN}" "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_MAN}") + +install (FILES "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_MAN}" DESTINATION "${DATA_INSTALL_DIR}/man/man1") +install (FILES "bash-completions" DESTINATION "${DATA_INSTALL_DIR}/bash-completion/completions" RENAME "${SUBPROJECT}") +install (FILES "zsh-completions" DESTINATION "${DATA_INSTALL_DIR}/zsh/site-functions" RENAME "_${SUBPROJECT}") diff --git a/sources/queued-daemon/bash-completions b/sources/queued-daemon/bash-completions new file mode 100644 index 0000000..e69de29 diff --git a/sources/queued-daemon/queued-daemon.1 b/sources/queued-daemon/queued-daemon.1 new file mode 100644 index 0000000..e69de29 diff --git a/sources/queued-daemon/queued.ini.example b/sources/queued-daemon/queued.ini.example new file mode 100644 index 0000000..a0cb798 --- /dev/null +++ b/sources/queued-daemon/queued.ini.example @@ -0,0 +1,11 @@ +[Administrator] +Username = root +Password = 0dd3e512642c97ca3f747f9a76e374fbda73f9292823c0313be9d78add7cdd8f72235af0c553dd26797e78e1854edee0ae002f8aba074b066dfce1af114e32f8 + +[Database] +Driver = QSQLITE +Hostname = +Password = +Path = /tmp/queued.db +Port = +Username = diff --git a/sources/queued-daemon/src/CMakeLists.txt b/sources/queued-daemon/src/CMakeLists.txt new file mode 100644 index 0000000..0c22400 --- /dev/null +++ b/sources/queued-daemon/src/CMakeLists.txt @@ -0,0 +1,18 @@ +# set files +file (GLOB_RECURSE SUBPROJECT_SOURCES "*.cpp") +file (GLOB_RECURSE SUBPROJECT_HEADERS "*.h") + +# include_path +include_directories ("${PROJECT_LIBRARY_DIR}/include" + "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_BINARY_DIR}" + "${PROJECT_TRDPARTY_DIR}" + "${Qt_INCLUDE}") + +qt5_wrap_cpp (SUBPROJECT_MOC_SOURCES "${SUBPROJECT_HEADERS}") + +add_executable ("${SUBPROJECT}" "${SUBPROJECT_HEADERS}" "${SUBPROJECT_SOURCES}" + "${SUBPROJECT_MOC_SOURCES}") +target_link_libraries ("${SUBPROJECT}" "${PROJECT_LIBRARY}" "${Qt_LIBRARIES}") +# install properties +install (TARGETS "${SUBPROJECT}" DESTINATION "${BIN_INSTALL_DIR}") diff --git a/sources/queued-daemon/src/QueuedApplication.cpp b/sources/queued-daemon/src/QueuedApplication.cpp new file mode 100644 index 0000000..b01c27c --- /dev/null +++ b/sources/queued-daemon/src/QueuedApplication.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + + +#include "QueuedApplication.h" + +#include +#include + +#include "queued/Queued.h" + +#include "QueuedApplicationInterface.h" + + +QueuedApplication::QueuedApplication(QObject *parent, const QVariantHash &args) + : QObject(parent) + , m_configuration(args) +{ + qSetMessagePattern(QueuedDebug::LOG_FORMAT); + qCDebug(LOG_APP) << __PRETTY_FUNCTION__; + for (auto &metadata : QueuedDebug::getBuildData()) + qCDebug(LOG_APP) << metadata; + + init(); +} + + +QueuedApplication::~QueuedApplication() +{ + qCDebug(LOG_APP) << __PRETTY_FUNCTION__; + + deinit(); +} + + +void QueuedApplication::deinit() +{ + QDBusConnection::sessionBus().unregisterObject( + QueuedConfig::DBUS_APPLICATION_PATH); + + if (m_core) + delete m_core; +} + + +void QueuedApplication::init() +{ + deinit(); + + initCore(); + initDBus(); +} + + +void QueuedApplication::initCore() +{ + m_core = new QueuedCore(this); + // init objects + m_core->init(m_configuration[QString("config")].toString()); +} + + +void QueuedApplication::initDBus() +{ + QDBusConnection bus = QDBusConnection::systemBus(); + + if (!bus.registerObject(QueuedConfig::DBUS_APPLICATION_PATH, + new QueuedApplicationInterface(this), + QDBusConnection::ExportAllContents)) { + QString message = QString("Could not register application object %1") + .arg(bus.lastError().message()); + qCCritical(LOG_DBUS) << message; + throw QueuedDBusException(message); + } +} diff --git a/sources/queued-daemon/src/QueuedApplication.h b/sources/queued-daemon/src/QueuedApplication.h new file mode 100644 index 0000000..cd3267e --- /dev/null +++ b/sources/queued-daemon/src/QueuedApplication.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + + +#ifndef QUEUEDAPPLICATION_H +#define QUEUEDAPPLICATION_H + +#include +#include + + +class QueuedCore; + +class QueuedApplication : public QObject +{ + Q_OBJECT + +public: + explicit QueuedApplication(QObject *parent, const QVariantHash &args); + virtual ~QueuedApplication(); + void deinit(); + void init(); + +private: + // backend + void initDBus(); + void initCore(); + // library + QueuedCore *m_core = nullptr; + // configuration + QVariantHash m_configuration; +}; + + +#endif /* QUEUEDAPPLICATION_H */ diff --git a/sources/queued-daemon/src/QueuedApplicationInterface.cpp b/sources/queued-daemon/src/QueuedApplicationInterface.cpp new file mode 100644 index 0000000..c786fa6 --- /dev/null +++ b/sources/queued-daemon/src/QueuedApplicationInterface.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + + +#include "QueuedApplicationInterface.h" + +#include +#include + +#include "queued/Queued.h" + +#include "QueuedApplication.h" + + +QueuedApplicationInterface::QueuedApplicationInterface( + QueuedApplication *parent) + : QDBusAbstractAdaptor(parent) + , m_application(parent) +{ + qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__; +} + + +QueuedApplicationInterface::~QueuedApplicationInterface() +{ + qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__; +} + + +bool QueuedApplicationInterface::Active() const +{ + return true; +} + + +void QueuedApplicationInterface::Close() const +{ + return QCoreApplication::exit(0); +} + + +QStringList QueuedApplicationInterface::UIDs() const +{ + QStringList uids; + uids.append(QString::number(getuid())); + uids.append(QString::number(geteuid())); + + return uids; +} diff --git a/sources/queued-daemon/src/QueuedApplicationInterface.h b/sources/queued-daemon/src/QueuedApplicationInterface.h new file mode 100644 index 0000000..48765db --- /dev/null +++ b/sources/queued-daemon/src/QueuedApplicationInterface.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + + +#ifndef QUEUEDAPPLICATIONINTERFACE_H +#define QUEUEDAPPLICATIONINTERFACE_H + +#include + +#include "QueuedConfig.h" + + +class QueuedApplication; + +class QueuedApplicationInterface : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME) + +public: + explicit QueuedApplicationInterface(QueuedApplication *parent); + virtual ~QueuedApplicationInterface(); + +public slots: + bool Active() const; + Q_NOREPLY void Close() const; + QStringList UIDs() const; + +private: + QueuedApplication *m_application = nullptr; +}; + + +#endif /* QUEUEDAPPLICATIONINTERFACE_H */ diff --git a/sources/queued-daemon/src/main.cpp b/sources/queued-daemon/src/main.cpp new file mode 100644 index 0000000..91badfd --- /dev/null +++ b/sources/queued-daemon/src/main.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + + +#include +#include +#include +#include + +#include + +#include "QueuedApplication.h" +#include "version.h" + + +bool existingSessionOperation(const QString &operation) +{ + QVariantList arguments = QueuedCoreAdaptor::sendRequest( + QueuedConfig::DBUS_SERVICE, QueuedConfig::DBUS_APPLICATION_PATH, + QueuedConfig::DBUS_SERVICE, operation, QVariantList()); + + return (!arguments.isEmpty() && arguments.at(0).type() == QVariant::Bool + && arguments[0].toBool()); +} + + +int main(int argc, char *argv[]) +{ + // daemon(0, 0); + + QCoreApplication app(argc, argv); + app.setApplicationName(NAME); + app.setApplicationVersion(VERSION); + + // parser + QCommandLineParser parser; + parser.setApplicationDescription( + "Daemon for starting jobs to queue of calculations"); + parser.addHelpOption(); + parser.addVersionOption(); + + // configuration option + QCommandLineOption configOption(QStringList() << "c" + << "config", + "Read initial configuration from file", + "config", QueuedSettings::defaultPath()); + parser.addOption(configOption); + + // debug mode + QCommandLineOption debugOption(QStringList() << "d" + << "debug", + "Print debug information"); + parser.addOption(debugOption); + + parser.process(app); + + // check if exists + if (existingSessionOperation(QString("Active"))) { + qCWarning(LOG_APP) << "Another session is active"; + return 1; + } + + // enable debug + if (parser.isSet(debugOption)) + QueuedDebug::enableDebug(); + + // build initial options hash + QVariantHash arguments = {{"config", parser.value(configOption)}}; + + // start application + QueuedApplication instance(nullptr, arguments); + return app.exec(); +} diff --git a/sources/queued-daemon/zsh-completions b/sources/queued-daemon/zsh-completions new file mode 100644 index 0000000..e69de29 diff --git a/sources/queued/QueuedConfig.h.in b/sources/queued/QueuedConfig.h.in index 00c123d..9c11ce4 100644 --- a/sources/queued/QueuedConfig.h.in +++ b/sources/queued/QueuedConfig.h.in @@ -35,17 +35,27 @@ namespace QueuedConfig * @brief DBus service name for library and application * @remark required by Qt macro */ -#define DBUS_SERVICE_NAME "org.quadro.core" +#define DBUS_SERVICE_NAME "org.queued.core" /** * @ingroup QueuedConfig * @brief DBus service name for library and application */ const char DBUS_SERVICE[] = DBUS_SERVICE_NAME; +/** + * @ingroup QueuedConfig + * @brief DBus object path for applicaiton + */ +const char DBUS_APPLICATION_PATH[] = "/application"; /** * @ingroup QueuedConfig * @brief DBus object path for library */ const char DBUS_OBJECT_PATH[] = "/queued"; +/** + * @ingroup QueuedConfig + * @brief DBus properties path for library + */ +const char DBUS_PROPERTY_PATH[] = "/property"; // path configuration // common paths diff --git a/sources/queued/include/queued/Queued.h b/sources/queued/include/queued/Queued.h index 7375576..f00408c 100644 --- a/sources/queued/include/queued/Queued.h +++ b/sources/queued/include/queued/Queued.h @@ -29,6 +29,7 @@ #include "QueuedCore.h" #include "QueuedCoreAdaptor.h" #include "QueuedCoreInterface.h" +#include "QueuedCorePropertiesInterface.h" #include "QueuedDatabase.h" #include "QueuedDebug.h" #include "QueuedEnums.h" diff --git a/sources/queued/include/queued/QueuedCore.h b/sources/queued/include/queued/QueuedCore.h index bf9329f..b893220 100644 --- a/sources/queued/include/queued/QueuedCore.h +++ b/sources/queued/include/queued/QueuedCore.h @@ -33,6 +33,7 @@ class QueuedAdvancedSettings; class QueuedDatabase; +class QueuedProcess; class QueuedProcessManager; class QueuedReportManager; class QueuedSettings; @@ -185,6 +186,20 @@ public: */ bool stopTask(const long long _id, const QueuedUserManager::QueuedUserAuthorization &_auth); + /** + * @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); + /** + * @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); // control methods /** * @brief deinit subclasses diff --git a/sources/queued/include/queued/QueuedCoreAdaptor.h b/sources/queued/include/queued/QueuedCoreAdaptor.h index 2c6ea77..9394236 100644 --- a/sources/queued/include/queued/QueuedCoreAdaptor.h +++ b/sources/queued/include/queued/QueuedCoreAdaptor.h @@ -24,30 +24,49 @@ #ifndef QUEUEDCOREADAPTOR_H #define QUEUEDCOREADAPTOR_H -#include +#include +#include /** - * @brief DBus adaptor for core interface + * @defgroup QueuedCoreAdaptor + * @brief adaptor to DBus methods */ -class QueuedCoreAdaptor : public QObject +namespace QueuedCoreAdaptor { - Q_OBJECT - -public: - /** - * @brief QueuedCoreAdaptor class constructor - * @param parent - * pointer to parent item - */ - explicit QueuedCoreAdaptor(QObject *parent); - /** - * @brief QueuedCoreAdaptor class destructor - */ - virtual ~QueuedCoreAdaptor(); - -private: +/** + * @ingroup QueuedCoreAdaptor + * @brief common DBus request + * @param _service + * DBus service name + * @param _path + * DBus object path + * @param _interface + * DBus interface name + * @param _cmd + * command which will be sent to DBus + * @param _args + * command arguments + * @return reply object from DBus request + */ +QVariantList sendRequest(const QString &_service, const QString &_path, + const QString &_interface, const QString &_cmd, + const QVariantList &_args); +/** + * @ingroup QueuedCoreAdaptor + * @brief additional method to avoid conversion from DBus type to native ones + * @tparam T + * type to which DBus data should be converted + * @param _data + * source data + * @return converted value + */ +template T toNativeType(const QVariant &_data) +{ + return qdbus_cast( + _data.value().variant().value()); }; +} #endif /* QUEUEDCOREADAPTOR_H */ diff --git a/sources/queued/include/queued/QueuedCoreInterface.h b/sources/queued/include/queued/QueuedCoreInterface.h index c5fe73a..74f03c1 100644 --- a/sources/queued/include/queued/QueuedCoreInterface.h +++ b/sources/queued/include/queued/QueuedCoreInterface.h @@ -114,16 +114,45 @@ public slots: * @brief edit task * @param id * task ID - * @param data - * new task data + * @param command + * new command or empty + * @param arguments + * command line arguments or empty + * @param directory + * working directory or empty + * @param nice + * nice level or 0 + * @param uid + * new uid or 0 + * @param state + * new state or 0 + * @param cpu + * new limit by CPU cores or -1 + * @param gpu + * limit by GPU cores or -1 + * @param memory + * new limit by memory or -1 + * @param gpumemory + * new limit by GPU memory or -1 + * @param storage + * new limit by storage or -1 + * @param start + * new start time in ISO format or empty + * @param end + * new end time in ISO format or empty * @param whoAmI * auth user name * @param token * auth user token * @return true on successful task edition */ - bool TaskEdit(const qlonglong id, const QDBusVariant &data, - const QString &whoAmI, const QString &token); + bool TaskEdit(const qlonglong id, const QString &command, + const QStringList &arguments, const QString &directory, + const uint nice, const uint uid, const uint gid, + const uint state, const long long cpu, const long long gpu, + const QString &memory, const QString &gpumemory, + const QString &storage, const QString &whoAmI, + const QString &token); /** * @brief force start task * @param id @@ -184,16 +213,34 @@ public slots: * @brief edit user * @param id * user ID - * @param data - * new user data + * @param name + * new user name or empty + * @param password + * new user password or empty + * @param email + * new user email or empty + * @param cpu + * new limit by CPU cores or -1 + * @param gpu + * limit by GPU cores or -1 + * @param memory + * new limit by memory or -1 + * @param gpumemory + * new limit by GPU memory or -1 + * @param storage + * new limit by storage or -1 * @param whoAmI * auth user name * @param token * auth user token * @return true on successful user edition */ - bool UserEdit(const qlonglong id, const QDBusVariant &data, - const QString &whoAmI, const QString &token); + bool UserEdit(const qlonglong id, const QString &name, + const QString &password, const QString &email, + const long long cpu, const long long gpu, + const QString &memory, const QString &gpumemory, + const QString &storage, const QString &whoAmI, + const QString &token); /** * @brief add permission to user * @param id diff --git a/sources/queued/include/queued/QueuedCorePropertiesInterface.h b/sources/queued/include/queued/QueuedCorePropertiesInterface.h new file mode 100644 index 0000000..7424e3d --- /dev/null +++ b/sources/queued/include/queued/QueuedCorePropertiesInterface.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +/** + * @file QueuedCorePropertiesInterface.h + * Header of Queued library + * @author Evgeniy Alekseev + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#ifndef QUEUEDCOREPROPERTIESINTERFACE_H +#define QUEUEDCOREPROPERTIESINTERFACE_H + +#include +#include + +#include "QueuedConfig.h" + + +class QueuedCore; + +/** + * @brief DBus interface for QueuedCore class + */ +class QueuedCorePropertiesInterface : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME) + +public: + /** + * @brief QueuedCorePropertiesInterface class constructor + * @param parent + * pointer to QueuedCore object + */ + explicit QueuedCorePropertiesInterface(QueuedCore *parent); + /** + * @brief QueuedCorePropertiesInterface class destructor + */ + virtual ~QueuedCorePropertiesInterface(); + +public slots: + /** + * @brief get task property + * @param id + * task ID + * @param property + * property name + * @return property value or empty if task or property not found + */ + QDBusVariant TaskProperty(const long long id, const QString &property); + /** + * @brief get user property + * @param id + * user ID + * @param property + * property name + * @return property value or empty if user or property not found + */ + QDBusVariant UserProperty(const long long id, const QString &property); + +private: + /** + * @brief pointer to database object + */ + QueuedCore *m_core = nullptr; +}; + + +#endif /* QUEUEDCOREPROPERTIESINTERFACE_H */ diff --git a/sources/queued/include/queued/QueuedDatabaseSchema.h b/sources/queued/include/queued/QueuedDatabaseSchema.h index 34a6cae..9d692ec 100644 --- a/sources/queued/include/queued/QueuedDatabaseSchema.h +++ b/sources/queued/include/queued/QueuedDatabaseSchema.h @@ -88,8 +88,7 @@ const QueuedDBSchema DBSchema = { {{"_id", {"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}}, - {"key", - {"key", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String, true}}, + {"key", {"key", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}}, {"value", {"value", "TEXT", QVariant::String, true}}}}, {TASKS_TABLE, {{"_id", @@ -111,16 +110,14 @@ const QueuedDBSchema DBSchema = { {{"_id", {"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}}, - {"token", - {"token", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String, true}}, + {"token", {"token", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}}, {"validUntil", {"validUntil", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}}}}, {USERS_TABLE, {{"_id", {"_id", "INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}}, - {"name", - {"name", "TEXT NOT NULL UNIQUE DEFAULT '0'", QVariant::String, true}}, + {"name", {"name", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}}, {"password", {"password", "TEXT", QVariant::String, false}}, {"email", {"email", "TEXT", QVariant::String, false}}, {"lastLogin", {"lastLogin", "TEXT", QVariant::String, true}}, diff --git a/sources/queued/include/queued/QueuedDebug.h b/sources/queued/include/queued/QueuedDebug.h index ddbfc42..6ac75b7 100644 --- a/sources/queued/include/queued/QueuedDebug.h +++ b/sources/queued/include/queued/QueuedDebug.h @@ -27,6 +27,10 @@ #include +/** + * @brief daemon logging category + */ +Q_DECLARE_LOGGING_CATEGORY(LOG_APP) /** * @brief control application logging category */ @@ -63,7 +67,11 @@ const char LOG_FORMAT[] = "[%{time " "{if-warning}WW%{endif}%{if-critical}CC%{endif}%{if-" "fatal}FF%{endif}][%{category}][%{function}] " "%{message}"; - +/** + * @ingroup QueuedDebug + * @brief method to enable debug messages + */ +void enableDebug(); /** * @ingroup QueuedDebug * @brief additional method to get build details declared in version.h diff --git a/sources/queued/include/queued/QueuedEnums.h b/sources/queued/include/queued/QueuedEnums.h index c28895a..2cac124 100644 --- a/sources/queued/include/queued/QueuedEnums.h +++ b/sources/queued/include/queued/QueuedEnums.h @@ -31,30 +31,6 @@ */ namespace QueuedEnums { -/** - * @ingroup QueuedEnums - * @enum LimitType - * @brief available limit types - * @var LimitType::CPUThreads - * limit on CPU threads count - * @var LimitType::GPUThreads - * limit on GPU threads count - * @var LimitType::Memory - * limit on physical memory - * @var LimitType::GPUMemory - * limit on GPU memory - * @var LimitType::Storage - * limit on storage - */ -enum LimitType { - CPUThreads = 1 << 0, - GPUThreads = 1 << 1, - Memory = 1 << 2, - GPUMemory = 1 << 3, - Storage = 1 << 4 -}; -Q_DECLARE_FLAGS(LimitTypes, LimitType) -Q_DECLARE_OPERATORS_FOR_FLAGS(LimitTypes) /** * @ingroup QueuedEnums * @enum Permissions @@ -71,10 +47,9 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(LimitTypes) * access to reports */ enum class Permission { - SuperAdmin = 1 << 0, - Admin = 1 << 1, - JobOwner = 1 << 2, - User = 1 << 3, + SuperAdmin = 1 << 1, + Admin = 1 << 2, + JobOwner = 1 << 3, Web = 1 << 4, Reports = 1 << 5 }; @@ -92,9 +67,9 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Permissions) * process exit */ enum class ProcessState { - NotRunning = 1 << 0, - Running = 1 << 1, - Exited = 1 << 2 + NotRunning = 1 << 1, + Running = 1 << 2, + Exited = 1 << 3 }; }; diff --git a/sources/queued/include/queued/QueuedLimits.h b/sources/queued/include/queued/QueuedLimits.h index 68caacc..a3933f0 100644 --- a/sources/queued/include/queued/QueuedLimits.h +++ b/sources/queued/include/queued/QueuedLimits.h @@ -88,7 +88,7 @@ struct Limits { Limits(const QString &_stringLimits) { QStringList limits = _stringLimits.split(QChar('\x01')); - while (limits.count() < 4) + while (limits.count() < 5) limits.append(QString("0")); cpu = limits.at(0).toLongLong(); diff --git a/sources/queued/src/QueuedCore.cpp b/sources/queued/src/QueuedCore.cpp index 52e0894..12de68d 100644 --- a/sources/queued/src/QueuedCore.cpp +++ b/sources/queued/src/QueuedCore.cpp @@ -65,7 +65,12 @@ bool QueuedCore::addTask( qCDebug(LOG_LIB) << "Add task" << _command << "with arguments" << _arguments << "from user" << _userId; - long long userAuthId = m_users->user(_auth.user)->index(); + auto authUser = m_users->user(_auth.user); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _auth.user; + return false; + } + long long userAuthId = authUser->index(); long long actualUserId = (_userId == -1) ? userAuthId : _userId; // check permissions @@ -89,8 +94,13 @@ bool QueuedCore::addTask( // add to database auto ids = m_users->ids(_userId); + auto user = m_users->user(_userId); + if (!user) { + qCWarning(LOG_LIB) << "Could not find task user" << _userId; + return false; + } auto taskLimits = QueuedLimits::minimalLimits( - _limits, m_users->user(_userId)->limits(), + _limits, user->limits(), QueuedLimits::Limits( m_advancedSettings->get(QString("DefaultLimits")).toString())); QVariantHash properties = {{"user", _userId}, @@ -131,6 +141,13 @@ bool QueuedCore::addUser( return false; } + // check if already exists + auto user = m_users->user(_name); + if (user) { + qCWarning(LOG_LIB) << "User" << _name << "already exists"; + return false; + } + // add to dababase QVariantHash properties = {{"name", _name}, @@ -158,6 +175,7 @@ QueuedCore::authorization(const QString &_name, const QString &_password) QString token = m_users->authorize(_name, _password); QueuedUserManager::QueuedUserAuthorization auth; auth.user = _name; + auth.token = token; if (!token.isEmpty()) { QVariantHash payload = { @@ -225,7 +243,12 @@ bool QueuedCore::editTask( } // check permissions - long long userAuthId = m_users->user(_auth.user)->index(); + auto authUser = m_users->user(_auth.user); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _auth.user; + return false; + } + long long userAuthId = authUser->index(); bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin); bool isUser = m_users->authorize(_auth, QueuedEnums::Permission::JobOwner); if (userAuthId == task->user()) { @@ -290,8 +313,13 @@ bool QueuedCore::editUser( } // check permissions + auto authUser = m_users->user(_auth.user); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _auth.user; + return false; + } + long long userAuthId = authUser->index(); bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin); - long long userAuthId = m_users->user(_auth.user)->index(); if (userAuthId != _id) { if (!isAdmin) { qCInfo(LOG_LIB) << "User" << _auth.user @@ -339,8 +367,13 @@ bool QueuedCore::editUserPermission( } // check permissions + auto authUser = m_users->user(_auth.user); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _auth.user; + return false; + } + long long userAuthId = authUser->index(); bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin); - long long userAuthId = m_users->user(_auth.user)->index(); if (userAuthId != _id) { if (!isAdmin) { qCInfo(LOG_LIB) << "User" << _auth.user @@ -385,8 +418,13 @@ bool QueuedCore::startTask( qCDebug(LOG_LIB) << "Force start task with ID" << _id; // check permissions + auto authUser = m_users->user(_auth.user); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _auth.user; + return false; + } + long long userAuthId = authUser->index(); bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin); - long long userAuthId = m_users->user(_auth.user)->index(); if (userAuthId != _id) { if (!isAdmin) { qCInfo(LOG_LIB) << "User" << _auth.user @@ -417,7 +455,12 @@ bool QueuedCore::stopTask( } // check permissions - long long userAuthId = m_users->user(_auth.user)->index(); + auto authUser = m_users->user(_auth.user); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _auth.user; + return false; + } + long long userAuthId = authUser->index(); bool isAdmin = m_users->authorize(_auth, QueuedEnums::Permission::Admin); bool isUser = m_users->authorize(_auth, QueuedEnums::Permission::JobOwner); if (userAuthId == task->user()) { @@ -442,6 +485,28 @@ bool QueuedCore::stopTask( } +/** + * @fn task + */ +const QueuedProcess *QueuedCore::task(const long long _id) +{ + qCDebug(LOG_LIB) << "Get task by ID" << _id; + + return m_processes->process(_id); +} + + +/** + * @fn user + */ +const QueuedUser *QueuedCore::user(const long long _id) +{ + qCDebug(LOG_LIB) << "Get user by ID" << _id; + + return m_users->user(_id); +} + + /** * @fn deinit */ @@ -455,6 +520,8 @@ void QueuedCore::deinit() // dbus cleanup QDBusConnection::sessionBus().unregisterObject( QueuedConfig::DBUS_OBJECT_PATH); + QDBusConnection::sessionBus().unregisterObject( + QueuedConfig::DBUS_PROPERTY_PATH); QDBusConnection::sessionBus().unregisterService(QueuedConfig::DBUS_SERVICE); // delete objects now @@ -583,7 +650,7 @@ QVariantHash QueuedCore::dropAdminFields(const QString &_table, */ void QueuedCore::initDBus() { - QDBusConnection bus = QDBusConnection::sessionBus(); + QDBusConnection bus = QDBusConnection::systemBus(); if (!bus.registerService(QueuedConfig::DBUS_SERVICE)) { QString message = QString("Could not register service %1") @@ -600,6 +667,14 @@ void QueuedCore::initDBus() qCCritical(LOG_DBUS) << message; throw QueuedDBusException(message); } + if (!bus.registerObject(QueuedConfig::DBUS_PROPERTY_PATH, + new QueuedCorePropertiesInterface(this), + QDBusConnection::ExportAllContents)) { + QString message = QString("Could not register properties object %1") + .arg(bus.lastError().message()); + qCCritical(LOG_DBUS) << message; + throw QueuedDBusException(message); + } } @@ -677,7 +752,7 @@ void QueuedCore::initUsers() QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); auto dbTokens = m_database->get( QueuedDB::TOKENS_TABLE, - QString("WHERE datetime(validUntil) > datetime(%2)").arg(now)); + QString("WHERE datetime(validUntil) > datetime('%1')").arg(now)); m_users->loadTokens(dbTokens); auto dbUsers = m_database->get(QueuedDB::USERS_TABLE); m_users->loadUsers(dbUsers); diff --git a/sources/queued/src/QueuedCoreAdaptor.cpp b/sources/queued/src/QueuedCoreAdaptor.cpp index 27ef654..f3516d9 100644 --- a/sources/queued/src/QueuedCoreAdaptor.cpp +++ b/sources/queued/src/QueuedCoreAdaptor.cpp @@ -23,24 +23,35 @@ #include "queued/Queued.h" +#include +#include + /** - * @class QueuedCoreAdaptor + * @fn sendRequest */ -/** - * @fn QueuedCoreAdaptor - */ -QueuedCoreAdaptor::QueuedCoreAdaptor(QObject *parent) - : QObject(parent) +QVariantList QueuedCoreAdaptor::sendRequest(const QString &_service, + const QString &_path, + const QString &_interface, + const QString &_cmd, + const QVariantList &_args) { - qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; -} + qCDebug(LOG_DBUS) << "Send request to service" << _service << "by interface" + << _interface << "to" << _path << "command" << _cmd + << "with args" << _args; + QDBusConnection bus = QDBusConnection::systemBus(); + QDBusMessage request + = QDBusMessage::createMethodCall(_service, _path, _interface, _cmd); + if (!_args.isEmpty()) + request.setArguments(_args); -/** - * @fn ~QueuedCoreAdaptor - */ -QueuedCoreAdaptor::~QueuedCoreAdaptor() -{ - qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; + QDBusMessage response = bus.call(request, QDBus::BlockWithGui); + QVariantList arguments = response.arguments(); + + QString error = response.errorMessage(); + if (!error.isEmpty()) + qCWarning(LOG_DBUS) << "Error message" << error; + + return arguments; } diff --git a/sources/queued/src/QueuedCoreInterface.cpp b/sources/queued/src/QueuedCoreInterface.cpp index 12cbb56..80f629e 100644 --- a/sources/queued/src/QueuedCoreInterface.cpp +++ b/sources/queued/src/QueuedCoreInterface.cpp @@ -100,14 +100,54 @@ bool QueuedCoreInterface::TaskAdd( /** * @fn TaskEdit */ -bool QueuedCoreInterface::TaskEdit(const qlonglong id, const QDBusVariant &data, - const QString &whoAmI, const QString &token) +bool QueuedCoreInterface::TaskEdit( + const qlonglong id, const QString &command, const QStringList &arguments, + const QString &directory, const uint nice, const uint uid, const uint gid, + const uint state, const long long cpu, const long long gpu, + const QString &memory, const QString &gpumemory, const QString &storage, + const QString &whoAmI, const QString &token) { - qCDebug(LOG_DBUS) << "Edit task" << id << data.variant() << "auth by" - << whoAmI; + qCDebug(LOG_DBUS) << "Edit task" << id << command << arguments << directory + << nice << uid << gid << state << cpu << gpu << memory + << gpumemory << storage << "auth by" << whoAmI; - return m_core->editTask(id, data.variant().toHash(), - QueuedUserManager::auth(whoAmI, token)); + auto task = m_core->task(id); + if (!task) { + qCWarning(LOG_DBUS) << "Could not find task" << id; + return false; + } + + // build payload + QVariantHash data; + if (!command.isEmpty()) + data[QString("command")] = command; + if (!arguments.isEmpty()) + data[QString("arguments")] = arguments; + if (!directory.isEmpty()) + data[QString("directory")] = directory; + if (nice > 0) + data[QString("nice")] = nice; + if (uid > 0) + data[QString("uid")] = uid; + if (gid > 0) + data[QString("gid")] = gid; + if (state > 0) + data[QString("state")] = state; + // append limits now + auto limits = task->limits(); + if (cpu > -1) + limits.cpu = cpu; + if (gpu > -1) + limits.gpu = gpu; + if (memory > -1) + limits.memory = QueuedLimits::convertMemory(memory); + if (gpumemory > -1) + limits.gpumemory = QueuedLimits::convertMemory(gpumemory); + if (storage > -1) + limits.storage = QueuedLimits::convertMemory(storage); + data[QString("limits")] = limits.toString(); + + return m_core->editTask(id, data, QueuedUserManager::auth(whoAmI, token)); } @@ -161,14 +201,47 @@ bool QueuedCoreInterface::UserAdd(const QString &name, const QString &email, /** * @fn UserEdit */ -bool QueuedCoreInterface::UserEdit(const qlonglong id, const QDBusVariant &data, +bool QueuedCoreInterface::UserEdit(const qlonglong id, const QString &name, + const QString &password, + const QString &email, const long long cpu, + const long long gpu, const QString &memory, + const QString &gpumemory, + const QString &storage, const QString &whoAmI, const QString &token) { - qCDebug(LOG_DBUS) << "Edit user" << id << data.variant() << "auth by" - << whoAmI; + qCDebug(LOG_DBUS) << "Edit user" << id << name << email << cpu << gpu + << memory << gpumemory << storage << "auth by" << whoAmI; - return m_core->editUser(id, data.variant().toHash(), - QueuedUserManager::auth(whoAmI, token)); + // get user object first to match limits + auto user = m_core->user(id); + if (!user) { + qCWarning(LOG_DBUS) << "Could not find user" << id; + return false; + } + + // build payload + QVariantHash data; + if (!name.isEmpty()) + data[QString("name")] = name; + if (!password.isEmpty()) + data[QString("password")] = password; + if (!email.isEmpty()) + data[QString("email")] = email; + // append limits now + auto limits = user->limits(); + if (cpu > -1) + limits.cpu = cpu; + if (gpu > -1) + limits.gpu = gpu; + if (memory > -1) + limits.memory = QueuedLimits::convertMemory(memory); + if (gpumemory > -1) + limits.gpumemory = QueuedLimits::convertMemory(gpumemory); + if (storage > -1) + limits.storage = QueuedLimits::convertMemory(storage); + data[QString("limits")] = limits.toString(); + + return m_core->editUser(id, data, QueuedUserManager::auth(whoAmI, token)); } diff --git a/sources/queued/src/QueuedCorePropertiesInterface.cpp b/sources/queued/src/QueuedCorePropertiesInterface.cpp new file mode 100644 index 0000000..0e076b4 --- /dev/null +++ b/sources/queued/src/QueuedCorePropertiesInterface.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +/** + * @file QueuedCorePropertiesInterface.cpp + * Source code of queued library + * @author Evgeniy Alekseev + * @copyright GPLv3 + * @bug https://github.com/arcan1s/queued/issues + */ + + +#include "queued/Queued.h" + + +/** + * @class QueuedCorePropertiesInterface + */ +/** + * @fn QueuedCorePropertiesInterface + */ +QueuedCorePropertiesInterface::QueuedCorePropertiesInterface(QueuedCore *parent) + : QDBusAbstractAdaptor(parent) + , m_core(parent) +{ + qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__; +} + + +/** + * @fn ~QueuedCorePropertiesInterface + */ +QueuedCorePropertiesInterface::~QueuedCorePropertiesInterface() +{ + qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__; +} + + +/** + * @fn TaskProperty + */ +QDBusVariant +QueuedCorePropertiesInterface::TaskProperty(const long long id, + const QString &property) +{ + qCDebug(LOG_DBUS) << "Get property" << property << "from task" << id; + + auto task = m_core->task(id); + if (!task) { + qCWarning(LOG_DBUS) << "Could not find task" << id; + return QDBusVariant(); + } + + return QDBusVariant(task->property(property.toLocal8Bit().constData())); +} + + +/** + * @fn UserProperty + */ +QDBusVariant +QueuedCorePropertiesInterface::UserProperty(const long long id, + const QString &property) +{ + qCDebug(LOG_DBUS) << "Get property" << property << "from user" << id; + + auto user = m_core->user(id); + if (!user) { + qCWarning(LOG_DBUS) << "Could not find user" << id; + return QDBusVariant(); + } + + return QDBusVariant(user->property(property.toLocal8Bit().constData())); +} diff --git a/sources/queued/src/QueuedDatabase.cpp b/sources/queued/src/QueuedDatabase.cpp index edadade..c8c81e8 100644 --- a/sources/queued/src/QueuedDatabase.cpp +++ b/sources/queued/src/QueuedDatabase.cpp @@ -80,15 +80,17 @@ void QueuedDatabase::createAdministrator(const QString &_user, const QString &_password) { qCDebug(LOG_LIB) << "Check for user" << _user; - QString table("users"); - QSqlQuery query = m_database.exec( - QString("SELECT * FROM '%1' WHERE name='%2'").arg(table).arg(_user)); + QSqlQuery query + = m_database.exec(QString("SELECT * FROM '%1' WHERE name='%2'") + .arg(QueuedDB::USERS_TABLE) + .arg(_user)); QSqlError error = query.lastError(); if (error.isValid()) - qCWarning(LOG_LIB) << "Could not get record" << _user << "from" << table - << "message" << error.text(); - else if (query.size() > 0) + qCWarning(LOG_LIB) << "Could not get record" << _user << "from" + << QueuedDB::USERS_TABLE << "message" + << error.text(); + else if (query.next()) return; qCInfo(LOG_LIB) << "Create administrator user" << _user; @@ -97,7 +99,7 @@ void QueuedDatabase::createAdministrator(const QString &_user, {"password", _password}, {"permissions", static_cast(QueuedEnums::Permission::SuperAdmin)}}; - if (!add(table, payload)) + if (!add(QueuedDB::USERS_TABLE, payload)) qCCritical(LOG_LIB) << "Could not create administrator"; } @@ -113,7 +115,7 @@ QList QueuedDatabase::get(const QString &_table, QList output; QSqlQuery query - = m_database.exec(QString("SELECT * FROM '%1' ORDER BY _id DESC %1") + = m_database.exec(QString("SELECT * FROM '%1' %2 ORDER BY _id DESC") .arg(_table) .arg(_condition)); @@ -227,7 +229,7 @@ bool QueuedDatabase::modify(const QString &_table, const long long _id, auto payload = getQueryPayload(_table, _value); QStringList stringPayload; for (int i = 0; i < payload.first.count(); i++) - stringPayload.append(QString("%1='%2'") + stringPayload.append(QString("%1=%2") .arg(payload.first.at(i)) .arg(payload.second.at(i))); // build query @@ -274,7 +276,7 @@ void QueuedDatabase::removeTasks(const QDateTime &_endTime) qCDebug(LOG_LIB) << "Remove all tasks which are older than" << _endTime; QSqlQuery query = m_database.exec( - QString("DELETE FROM %1 WHERE datetime(endTime) < datetime(%2)") + QString("DELETE FROM %1 WHERE datetime(endTime) < datetime('%2')") .arg(QueuedDB::TASKS_TABLE) .arg(_endTime.toString(Qt::ISODate))); @@ -292,7 +294,7 @@ void QueuedDatabase::removeTokens() { QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); QSqlQuery query = m_database.exec( - QString("DELETE FROM %1 WHERE datetime(validUntil) > datetime(%2)") + QString("DELETE FROM %1 WHERE datetime(validUntil) > datetime('%2')") .arg(QueuedDB::TOKENS_TABLE) .arg(now)); @@ -312,7 +314,7 @@ void QueuedDatabase::removeUsers(const QDateTime &_lastLogin) << _lastLogin; QSqlQuery query = m_database.exec( - QString("DELETE FROM %1 WHERE datetime(lastLogin) < datetime(%2)") + QString("DELETE FROM %1 WHERE datetime(lastLogin) < datetime('%2')") .arg(QueuedDB::USERS_TABLE) .arg(_lastLogin.toString(Qt::ISODate))); diff --git a/sources/queued/src/QueuedDebug.cpp b/sources/queued/src/QueuedDebug.cpp index 7781184..48e8519 100644 --- a/sources/queued/src/QueuedDebug.cpp +++ b/sources/queued/src/QueuedDebug.cpp @@ -26,6 +26,7 @@ #include "version.h" +Q_LOGGING_CATEGORY(LOG_APP, "org.queued.application", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_CTL, "org.queued.control", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_DBUS, "org.queued.dbus", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_LIB, "org.queued.library", QtMsgType::QtWarningMsg) @@ -33,6 +34,15 @@ Q_LOGGING_CATEGORY(LOG_PL, "org.queued.plugin", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_SERV, "org.queued.server", QtMsgType::QtWarningMsg) +/** + * @fn enableDebug + */ +void QueuedDebug::enableDebug() +{ + QLoggingCategory::setFilterRules(QString("org.queued.*=true")); +} + + /** * @fn getBuildData */ diff --git a/sources/queued/src/QueuedTokenManager.cpp b/sources/queued/src/QueuedTokenManager.cpp index 05e85cd..8844918 100644 --- a/sources/queued/src/QueuedTokenManager.cpp +++ b/sources/queued/src/QueuedTokenManager.cpp @@ -73,11 +73,15 @@ void QueuedTokenManager::loadTokens(const QList &_values) token[QString("validUntil")].toString(), Qt::ISODate); QString tokenId = token[QString("token")].toString(); m_tokens[tokenId] = validUntil; - QTimer::singleShot( + // create timer + std::chrono::milliseconds duration( validUntil.toMSecsSinceEpoch() - - QDateTime::currentDateTimeUtc().toMSecsSinceEpoch(), - Qt::VeryCoarseTimer, - [this, tokenId]() { return expireToken(tokenId); }); + - QDateTime::currentDateTimeUtc().toMSecsSinceEpoch()); + QTimer timer; + timer.setSingleShot(true); + timer.setInterval(duration); + connect(&timer, &QTimer::timeout, + [this, tokenId]() { return expireToken(tokenId); }); } } diff --git a/sources/queued/src/QueuedUser.cpp b/sources/queued/src/QueuedUser.cpp index 7e8b3bb..38cb8fb 100644 --- a/sources/queued/src/QueuedUser.cpp +++ b/sources/queued/src/QueuedUser.cpp @@ -79,7 +79,8 @@ QueuedUser::addPermissions(const QueuedEnums::Permissions _permissions) QString QueuedUser::hashFromPassword(const QString &_password) { return QCryptographicHash::hash(_password.toUtf8(), - QCryptographicHash::Sha512); + QCryptographicHash::Sha512) + .toHex(); } @@ -122,9 +123,7 @@ QPair QueuedUser::ids() */ bool QueuedUser::isPasswordValid(const QString &_password) const { - return (m_definitions.password.toUtf8() - == QCryptographicHash::hash(_password.toUtf8(), - QCryptographicHash::Sha512)); + return (m_definitions.password.toUtf8() == hashFromPassword(_password)); }