KUserFeedback

main.cpp
1/*
2 SPDX-FileCopyrightText: 2017 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: MIT
5*/
6
7#include <kuserfeedback_version.h>
8
9#include <jobs/handshakejob.h>
10#include <jobs/productexportjob.h>
11#include <jobs/productimportjob.h>
12#include <jobs/securityscanjob.h>
13#include <rest/restapi.h>
14#include <rest/restclient.h>
15#include <rest/serverinfo.h>
16#include <core/product.h>
17
18#include <QCommandLineParser>
19#include <QCoreApplication>
20#include <QDir>
21#include <QNetworkReply>
22
23#include <iostream>
24
25using namespace KUserFeedback::Console;
26
27static int jobCount = 0;
28
29int main(int argc, char **argv)
30{
31 QCoreApplication app(argc, argv);
32 QCoreApplication::setApplicationName(QStringLiteral("userfeedbackctl"));
33 QCoreApplication::setOrganizationName(QStringLiteral("KDE"));
34 QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org"));
35 QCoreApplication::setApplicationVersion(QStringLiteral(KUSERFEEDBACK_VERSION_STRING));
36
37 QCommandLineParser parser;
38 parser.setApplicationDescription(QStringLiteral("UserFeedback management tool"));
39 parser.addHelpOption();
40 parser.addVersionOption();
41 QCommandLineOption serverOpt({ QStringLiteral("server"), QStringLiteral("s") }, QStringLiteral("Server Name"), QStringLiteral("name"));
42 parser.addOption(serverOpt);
43 QCommandLineOption outputOpt({ QStringLiteral("output"), QStringLiteral("o") }, QStringLiteral("Output path"), QStringLiteral("path"));
44 parser.addOption(outputOpt);
45 QCommandLineOption forceOpt({ QStringLiteral("force"), QStringLiteral("f") }, QStringLiteral("Force destructive operations"));
46 parser.addOption(forceOpt);
47 QCommandLineOption urlOpt({ QStringLiteral("url"), QStringLiteral("u") }, QStringLiteral("Server URL"), QStringLiteral("url"));
48 parser.addOption(urlOpt);
49 QCommandLineOption userOpt({ QStringLiteral("user") }, QStringLiteral("User name"), QStringLiteral("name"));
50 parser.addOption(userOpt);
51 QCommandLineOption passOpt({ QStringLiteral("password") }, QStringLiteral("Password"), QStringLiteral("pass"));
52 parser.addOption(passOpt);
53 parser.addPositionalArgument(QStringLiteral("command"), QStringLiteral("Command: add-server, delete-product, delete-server, export-all, export-product, import-product, list-products, list-servers, scan-server"));
54
55 parser.process(app);
56
57 if (parser.positionalArguments().isEmpty())
58 parser.showHelp(1);
59 const auto cmd = parser.positionalArguments().at(0);
60 if (cmd == QLatin1String("list-servers")) {
61 const auto servers = ServerInfo::allServerInfoNames();
62 for (const auto &n : servers)
63 std::cout << qPrintable(n) << std::endl;
64 return 0;
65 }
66 if (!parser.isSet(serverOpt))
67 parser.showHelp(1);
68
69 if (cmd == QLatin1String("add-server")) {
70 if (!parser.isSet(urlOpt))
71 parser.showHelp(1);
72 ServerInfo s;
73 s.setName(parser.value(serverOpt));
74 s.setUrl(QUrl::fromUserInput(parser.value(urlOpt)));
75 s.setUserName(parser.value(userOpt));
76 s.setPassword(parser.value(passOpt));
77 s.save();
78 return 0;
79 } else if (cmd == QLatin1String("delete-server")) {
80 ServerInfo::remove(parser.value(serverOpt));
81 return 0;
82 }
83
84 const auto server = ServerInfo::load(parser.value(serverOpt));
85 if (!server.isValid()) {
86 std::cerr << "Invalid server information." << std::endl;
87 return 1;
88 }
89
90 QFileInfo fi(parser.value(outputOpt));
91 if (parser.isSet(outputOpt) && (!fi.isDir() || !fi.isWritable())) {
92 std::cerr << "Output path does exist or is not accessible." << std::endl;
93 return 1;
94 }
95
96 RESTClient restClient;
97 QObject::connect(&restClient, &RESTClient::errorMessage, [](const auto &msg) {
98 std::cerr << qPrintable(msg) << std::endl;
100 });
101 restClient.setServerInfo(server);
102
103 if (cmd == QLatin1String("delete-product")) {
104 jobCount = parser.positionalArguments().size() - 1;
105 if (jobCount <= 0 || !parser.isSet(forceOpt))
106 parser.showHelp(1);
107 QObject::connect(&restClient, &RESTClient::clientConnected, [&parser, &restClient]() {
108 for (int i = 0; i < jobCount; ++i) {
109 Product p;
110 p.setName(parser.positionalArguments().at(i+1));
111 auto reply = RESTApi::deleteProduct(&restClient, p);
112 QObject::connect(reply, &QNetworkReply::finished, [reply]() {
113 if (reply->error() != QNetworkReply::NoError)
114 return;
115 --jobCount;
116 if (jobCount == 0)
117 qApp->quit();
118 });
119 }
120 });
121 } else if (cmd == QLatin1String("export-all")) {
122 if (parser.positionalArguments().size() != 1)
123 parser.showHelp(1);
124 QObject::connect(&restClient, &RESTClient::clientConnected, [&]() {
125 auto reply = RESTApi::listProducts(&restClient);
126 QObject::connect(reply, &QNetworkReply::finished, [reply, &parser, &outputOpt, &restClient]() {
127 if (reply->error() != QNetworkReply::NoError)
128 return;
129 const auto products = Product::fromJson(reply->readAll());
130 for (const auto &p : products) {
131 ++jobCount;
132 auto job = new ProductExportJob(p, parser.value(outputOpt), &restClient);
133 QObject::connect(job, &Job::destroyed, []() {
134 --jobCount;
135 if (jobCount == 0)
136 qApp->quit();
137 });
138 QObject::connect(job, &Job::error, [](const auto &msg) {
139 std::cerr << qPrintable(msg) << std::endl;
140 });
141 }
142 });
143 });
144 } else if (cmd == QLatin1String("export-product")) {
145 if (parser.positionalArguments().size() != 2)
146 parser.showHelp(1);
147 QObject::connect(&restClient, &RESTClient::clientConnected, [&parser, &outputOpt, &restClient]() {
148 auto job = new ProductExportJob(parser.positionalArguments().at(1), parser.value(outputOpt), &restClient);
149 QObject::connect(job, &Job::destroyed, qApp, &QCoreApplication::quit);
150 QObject::connect(job, &Job::error, [](const auto &msg) {
151 std::cerr << qPrintable(msg) << std::endl;
152 });
153 });
154 } else if (cmd == QLatin1String("import-product")) {
155 if (parser.positionalArguments().size() != 2)
156 parser.showHelp(1);
157 QObject::connect(&restClient, &RESTClient::clientConnected, [&parser, &restClient]() {
158 auto job = new ProductImportJob(parser.positionalArguments().at(1), &restClient);
159 QObject::connect(job, &Job::destroyed, qApp, &QCoreApplication::quit);
160 QObject::connect(job, &Job::error, [](const auto &msg) {
161 std::cerr << qPrintable(msg) << std::endl;
162 });
163 });
164 } else if (cmd == QLatin1String("list-products")) {
165 if (parser.positionalArguments().size() != 1)
166 parser.showHelp(1);
167 QObject::connect(&restClient, &RESTClient::clientConnected, [&restClient]() {
168 auto reply = RESTApi::listProducts(&restClient);
169 QObject::connect(reply, &QNetworkReply::finished, [reply]() {
170 if (reply->error() != QNetworkReply::NoError)
171 return;
172 const auto products = Product::fromJson(reply->readAll());
173 for (const auto &p : products)
174 std::cout << qPrintable(p.name()) << std::endl;
175 qApp->quit();
176 });
177 });
178 } else if (cmd == QLatin1String("scan-server")) {
179 QObject::connect(&restClient, &RESTClient::clientConnected, [&restClient]() {
180 auto job = new SecurityScanJob(&restClient);
181 QObject::connect(job, &Job::destroyed, qApp, &QCoreApplication::quit);
182 QObject::connect(job, &Job::error, [](const auto &msg) {
183 std::cerr << qPrintable(msg) << std::endl;
184 });
185 QObject::connect(job, &Job::info, [](const auto &msg) {
186 std::cout << qPrintable(msg) << std::endl;
187 });
188 });
189 } else {
190 parser.showHelp(1);
191 }
192
193 auto job = new HandshakeJob(&restClient);
194 QObject::connect(job, &Job::error, [](const QString &msg) {
195 std::cerr << qPrintable(msg) << std::endl;
197 });
198
199 return app.exec();
200}
QString name(StandardShortcut id)
QCommandLineOption addHelpOption()
bool addOption(const QCommandLineOption &option)
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
QCommandLineOption addVersionOption()
bool isSet(const QCommandLineOption &option) const const
QStringList positionalArguments() const const
void process(const QCoreApplication &app)
void setApplicationDescription(const QString &description)
void showHelp(int exitCode)
QString value(const QCommandLineOption &option) const const
void setApplicationName(const QString &application)
void setApplicationVersion(const QString &version)
void exit(int returnCode)
void setOrganizationDomain(const QString &orgDomain)
void setOrganizationName(const QString &orgName)
const_reference at(qsizetype i) const const
bool isEmpty() const const
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QTextStream & endl(QTextStream &stream)
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:56 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.