refactor: proxy commandline arguments
Add a 'proxy' to forward external API calls into the main application control flow. Right now it only supports forwarding commandline arguments, but this construct is already useful as a starting point for future D-Bus API support.master
parent
7274dc4f25
commit
ea19844300
|
@ -1,9 +1,9 @@
|
|||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
# SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
# SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
#
|
||||
|
||||
set(Test_DEP_LIBS Qt5::Core Qt5::Concurrent Qt5::Test keysmith_lib test_lib)
|
||||
set(Test_DEP_LIBS Qt5::Core Qt5::Gui Qt5::Concurrent Qt5::Test keysmith_lib test_lib)
|
||||
|
||||
set(app_test_SRCS
|
||||
commandline-account-job.cpp
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
*/
|
||||
#include "cli.h"
|
||||
#include "../logging_p.h"
|
||||
#include "../model/qr.h"
|
||||
#include "flows_p.h"
|
||||
#include "state_p.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <QCommandLineOption>
|
||||
|
@ -16,10 +18,7 @@ namespace app
|
|||
{
|
||||
void CommandLineOptions::addOptions(QCommandLineParser &parser)
|
||||
{
|
||||
parser.addPositionalArgument(
|
||||
QStringLiteral("<uri>"),
|
||||
i18nc("@info (<uri> placeholder)", "Optional account to add, formatted as otpauth:// URI (e.g. from a QR code)")
|
||||
);
|
||||
Proxy::addOptions(parser);
|
||||
}
|
||||
|
||||
CommandLineOptions::CommandLineOptions(QCommandLineParser &parser, bool parseOk, QObject *parent) :
|
||||
|
@ -107,4 +106,67 @@ namespace app
|
|||
qCDebug(logger) << "Failed to signal result of processing the URI passed on the commandline";
|
||||
}
|
||||
}
|
||||
|
||||
Proxy::Proxy(QGuiApplication *app, QObject *parent) :
|
||||
QObject(parent), m_keysmith(nullptr), m_app(app)
|
||||
{
|
||||
Q_ASSERT_X(m_app, Q_FUNC_INFO, "Should have a valid QGuiApplication instance");
|
||||
}
|
||||
|
||||
void Proxy::addOptions(QCommandLineParser &parser)
|
||||
{
|
||||
parser.addPositionalArgument(
|
||||
QStringLiteral("<uri>"),
|
||||
i18nc("@info (<uri> placeholder)", "Optional account to add, formatted as otpauth:// URI (e.g. from a QR code)")
|
||||
);
|
||||
}
|
||||
|
||||
bool Proxy::parseCommandLine(QCommandLineParser &parser, const QStringList &argv)
|
||||
{
|
||||
// options that will be handled via UI interaction
|
||||
app::Proxy::addOptions(parser);
|
||||
return parser.parse(argv);
|
||||
}
|
||||
|
||||
void Proxy::disable(void)
|
||||
{
|
||||
m_keysmith = nullptr;
|
||||
}
|
||||
|
||||
bool Proxy::enable(Keysmith *keysmith)
|
||||
{
|
||||
Q_ASSERT_X(keysmith, Q_FUNC_INFO, "should be given a valid Keysmith instance");
|
||||
if (m_keysmith) {
|
||||
qCDebug(logger)
|
||||
<< "Not (re)initialising proxy with new Keysmith instance:" << keysmith
|
||||
<< "Already initialised with:" << m_keysmith;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_keysmith = keysmith;
|
||||
QObject::connect(m_keysmith, &QObject::destroyed, this, &Proxy::disable);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Proxy::proxy(const QCommandLineParser &parser, bool parsedOk)
|
||||
{
|
||||
if (!parsedOk) {
|
||||
qCDebug(logger) << "Not proxying to Keysmith instance: invalid command line";
|
||||
return false;
|
||||
}
|
||||
if (!m_keysmith) {
|
||||
qCDebug(logger) << "Not proxying command line arguments: not initialised with a Keysmith instance";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto state = flowStateOf(m_keysmith);
|
||||
if (state->flowRunning()) {
|
||||
qCDebug(logger) << "Not proxying command line arguments: a 'competing' flow is already running";
|
||||
return false;
|
||||
}
|
||||
|
||||
(new InitialFlow(m_keysmith))->run(parser);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
* SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2020-2021 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
|
||||
*/
|
||||
#ifndef APP_COMMAND_LINE_H
|
||||
#define APP_COMMAND_LINE_H
|
||||
|
||||
#include "keysmith.h"
|
||||
#include "../model/input.h"
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QGuiApplication>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
namespace app
|
||||
{
|
||||
|
@ -56,6 +59,23 @@ namespace app
|
|||
const QString m_errorText;
|
||||
QCommandLineParser &m_parser;
|
||||
};
|
||||
|
||||
class Proxy: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static bool parseCommandLine(QCommandLineParser &parser, const QStringList &argv);
|
||||
static void addOptions(QCommandLineParser &parser);
|
||||
public:
|
||||
explicit Proxy(QGuiApplication *app, QObject *parent = nullptr);
|
||||
bool enable(Keysmith *keysmith);
|
||||
bool proxy(const QCommandLineParser &parser, bool parsedOk);
|
||||
private Q_SLOTS:
|
||||
void disable(void);
|
||||
private:
|
||||
Keysmith * m_keysmith;
|
||||
QGuiApplication *m_app;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
12
src/main.cpp
12
src/main.cpp
|
@ -46,14 +46,12 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
|||
QGuiApplication::setApplicationDisplayName(i18nc("@title", "Keysmith"));
|
||||
|
||||
QCommandLineParser cliParser;
|
||||
// options that will be handled via UI interaction
|
||||
app::CommandLineOptions::addOptions(cliParser);
|
||||
|
||||
// default/boilerplate options handled entirely via command line
|
||||
const auto helpOption = cliParser.addHelpOption();
|
||||
const auto versionOption = cliParser.addVersionOption();
|
||||
|
||||
bool parseOk = cliParser.parse(QCoreApplication::arguments());
|
||||
bool parseOk = app::Proxy::parseCommandLine(cliParser, QCoreApplication::arguments());
|
||||
|
||||
/*
|
||||
* First check for pure command line options and handle these.
|
||||
|
@ -71,6 +69,8 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
|||
return 0; // just to be explicit: showVersion() is documented to call exit()
|
||||
}
|
||||
|
||||
app::Proxy proxy(&app);
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
|
||||
|
||||
|
@ -90,11 +90,13 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
|||
qmlRegisterType<validators::IssuerValidator>("Keysmith.Validators", 1, 0, "AccountIssuerValidator");
|
||||
qmlRegisterType<validators::Base32Validator>("Keysmith.Validators", 1, 0, "Base32SecretValidator");
|
||||
qmlRegisterType<validators::UnsignedLongValidator>("Keysmith.Validators", 1, 0, "HOTPCounterValidator");
|
||||
qmlRegisterSingletonType<app::Keysmith>("Keysmith.Application", 1, 0, "Keysmith", [](QQmlEngine *qml, QJSEngine *js) -> QObject *
|
||||
qmlRegisterSingletonType<app::Keysmith>("Keysmith.Application", 1, 0, "Keysmith", [&proxy](QQmlEngine *qml, QJSEngine *js) -> QObject *
|
||||
{
|
||||
Q_UNUSED(js);
|
||||
|
||||
return new app::Keysmith(new app::Navigation(qml));
|
||||
auto app = new app::Keysmith(new app::Navigation(qml));
|
||||
proxy.enable(app);
|
||||
return app;
|
||||
});
|
||||
qmlRegisterSingletonType<app::CommandLineOptions>("Keysmith.Application", 1, 0, "CommandLine", [parseOk, &cliParser](QQmlEngine *qml, QJSEngine *js) -> QObject *
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue